This is a CRA-style template you can use to create reactive[1] offline-first per-user-document-based apps. To achieve this, I've integrated:
useCollection
hook that exposes an RxDB collection and any number of reactive[2] queries (usage below):const [collection, [query-result1, query-result2, ...]] = useCollection(
collection-name,
[mongo-style-query1, mongo-style-query2, ...],
[index1, index2, ...]
)
Also out-of-the-box:
[1]: Reactive as in, updates to user documents in one browser will be immediately reflected in all other browsers where the same user is logged in, via Fauna's streaming
[2]: Reactive as in, changes to the state of the local RxDB database will be reflected in the hook variable and cause a rerender
(If you get an error about accessing uv_cwd
with the npm run
scripts below, please see this)
npx @jfrancos/crancos [your-project]
snowpack.config.mjs
:...
config.env = { MAGIC_PUBLISHABLE_KEY: 'pk_live_...' };`
...
.env
:MAGIC_SECRET=sk_live_...
FAUNA_SECRET=fn...
STRIPE_SECRET=sk_test_...
npm run provision-fauna
npm run provision-stripe
npm run dev
npm run ngrok
(auto-tunnel for your stripe endpoint)(continued after video)
Chrome on the left, Brave on the right:
Controller.jsx
with your own very special time-managmentment app, video game, or other user-document-based app.useCollection
usageimport { useCollection } from './lib/ReplicatedCollection';
const [collection, [query-result1, query-result2, ...]] = useCollection(
collection-name,
[mongo-style-query1, mongo-style-query2, ...],
[index1, index2, ...]
)
collection
is an RxDB Collection with which you can e.g. insert
and remove
documents.
query-results
are the results of mongo-style-queries that are kept up-to-date as the collection and its documents are updated.
collection-name
will become the name of the underlying RxDB/pouchdb collection. You can use multiple collections and have them replicated, if you give them different names.
mongo-style-queries
follow the structure defined here, i.e. these are objects with a mandatory selector
and optional limit
, skip
, sort
etc. See Controller.jsx
for a couple examples.
indices
: It's good to create an index for any data you're searching or sorting over. Data stored using useCollection
is schemaless from our point of view, with all data stored in the document's data
object, thus you should prefix indices accordingly e.g. "data.title"
. RxDB will not always complain when you search for something that doesn't have an index, so if you want to be sure, uncomment the following two lines in the _create
function of src/lib/Collection.jsx
and look for pouchdb:find query plan
in your browsers' js console:
// addPouchPlugin(pouchdbDebug);
// PouchDB.debug.enable('pouchdb:find');
The underlying RxDB collections have a schema, but from the useCollection
user's point of view, this setup is schemaless - just make sure all your data is stored inside the data
object e.g.:
collection.insert({
data: {
completed: false,
title: inputValue,
}
});
dev
and build
(npm run build
) modes.dev
mode. But with npm run build
, you can kill the server, and the page will still reload. To then update the site, you'll have to remove the cached site via Developer Tools -> Application -> Storage -> Clear site dataWhen the same user is logged into two different browsers and they both go offline, "conflicts" arise when the same document (e.g. a todo item) is updated in both browsers in different ways. When they reconnect, they'll both let the server (Fauna) know about these updates, and only one of these versions can "win". Should the final state of the document be determined by:
There's no automatic answer, but I think the latter is the better default, and that's how I've setup the replication logic.
In addition, deletion is a quality of a document (this is per RxDB's replication spec). Thus documents removed are never actually deleted from the server, they just get a deleted: true
property (this is necessary to properly sync deleted documents when offline devices come online).
To update your stripe plans, see add-stripe.mjs
There is still a lot to do here. Priorities at the moment:
Some other things I think about include:
Misc:
./src/index.css
has
div {
display: flex;
}
(a personal preference that should probably be extracted into a separate package)