Start developing with Bijection
Before you begin: You'll need the Bijection CLI and Node.js
Before you begin: You'll need the Bijection CLI and Node.js
Install the Bijection command line on macOS or Linux:See Install Bijection for PATH setup. The backend
needs nothing else, but the chat app’s web frontend is a React app built with
Vite, so you also need Node.js with a package
manager: pnpm, bun, yarn or npm.
react-vite template:
bijection init writes a React app and a folder called bijection/, where
you’ll write your backend code, and installs the app’s dependencies with your
package manager.
Log this machine in to Bijection (once per machine), then start the backend:
Bijection’s hosted service is not yet open for public sign-up, and the CLI
has no default management service. Before running
bijection login, set
BIJECTION_MANAGEMENT_URL to the management service URL you were given, in
your shell’s startup file so that every later bijection command sees it too:bijection dev creates your backend, a dev deployment, and
writes its URL to .env.local, where the app finds it.
Make sure you keep bijection dev running in the background throughout this
tutorial. It keeps your backend in sync with your local codebase, pushing the
bijection/ folder on every change.
In another terminal, start the web app with the command bijection init
printed for your package manager, for example:
bijection/messages.ts and
bijection/schema.ts. In this tutorial you write the chat backend yourself, so
delete them:
How Bijection works
Database. The Bijection database is a document-relational database, which means you have tables with JSON like documents in them. All documents have an auto-generated_id that can be used to create relations between documents. You
interact with the database through mutation and query functions that are written
entirely in TypeScript.
Mutation functions. Mutations are TypeScript functions that update the
database. All mutation functions in Bijection run as a database transaction. So
either all the changes are committed, or none are.
Query functions. Queries are TypeScript functions that can only read from
the database. As we’ll see in a bit, you subscribe to them from your frontend to
keep your app automatically up to date.
Your frontend registers to listen to query updates through the client
library. The client libraries talk to Bijection via WebSockets for fast realtime
updates.
The sync engine reruns query functions when any input to the function
changes, including any changes to the documents in the database that the query
reads. It then updates every app listening to the query. The sync engine is the
combination of queries, mutations and the database.
Now, let’s dive into the code!
Your first mutation
Create a new file in your bijection/ folder called chat.ts. This is where
you’ll write your Bijection backend functions for this application.
Add the following to your bijection/chat.ts file.
- You’ve added a new backend
mutationfunction calledsendMessageand exposed it as a public api. - The whole function automatically runs as a transaction that will roll back if an exception is thrown.
- Since this is just a TypeScript function you can drop
console.loglines to do simple debugging on the server. args:ensures the function arguments are two strings nameduserandbody, both as types and runtime values.ctx.db.inserttells Bijection to insert a new message document into the table.
src/App.tsx file with this chat UI:
const sendMessage = useMutation(api.chat.sendMessage);gives your frontend app a handle to the mutation functionawait sendMessage({ user: NAME, body: newMessageText });calls the mutation with the proper parameters.
messages table.
Bijection automatically created a messages table when you sent the first message.
In Bijection, schemas are optional. Eventually, you’ll
want to enforce the structure of your tables, but for the purposes of the
tutorial we’ll skip this.
In the console you can also go to the
logs screen and see every call
to the mutation as you ran with the log line we added earlier. The logs screen
is a critical part of debugging your backend in development.
You’ve successfully created a mutation function, which is also a database
transaction, and connected it to your UI.
Now, let’s make sure your app can update live the same way the console is
updating live.
Your first query
Update your bijection/chat.ts file like this:
- You’ve added a new backend
queryfunction calledgetMessagesand exposed it as a public api. - Since this is a query function, the
ctx.dbin this function only lets you read data. - In the first line of the
handleryou are querying the most recent 50 messages from newest to oldest. - In the second line you’re reversing the list using plain old TypeScript.
src/App.tsx to read from your query:
useQuery line is doing a lot of work automatically for you. It’s
telling the Bijection client library to subscribe to your getMessages function.
Anytime there are new messages to show the query function is automatically
rerun. The result is put in const messages variable and React rerenders your
UI component to show the latest messages.
That’s it. Now go back to your app and try sending messages.
Your app should be showing live updates as new messages arrive:
Don’t believe it? Try opening two chat windows side by side and send some messages:
What you built
With just a few lines of code you’ve built a live updating chat app.- You created a
mutationTypeScript function that, in a transaction, adds new chat messages to your database. - You created a
queryTypeScript function updates your app with the latest data. - You used the client library that keeps your frontend in live sync with the backend.
Next up
In this tutorial we just touched on the very basics. It’s ok to just stop here and go explore the rest of the docs, including efficient queries via indexes and traversing relationships through joins. If you’re deeply curious about how Bijection works, you can read this excellent deep dive. But if you want to see how to call external services and build sophisticated backend workflows, jump into the next section →.Calling external services
Extend your chat app by calling external APIs using Bijection actions and the scheduler to integrate Wikipedia summaries into your application.