Quickstart
Five minutes from nothing to a deployed app. You need Node.js 22.12 or newer and nothing else.
#1. Create an app
npx @impetik/xeer new my-app
cd my-app
npm installNothing to install first. npm install then puts Xeer in the project, so from here on npx xeer <command>
resolves the local copy — and npm run dev, npm run check, npm run build, and npm test work too,
for you and for anyone who clones the repository.
Keep the scope. A bare
npx xeerlooks for a package literally namedxeer, which is not this one, andnpx xis an unrelated package entirely. The package is@impetik/xeer; the command it provides isxeer.
Running it often enough to want it on your PATH? npm install --global @impetik/xeer, and then drop the
npx from every command below.
xeer new writes a complete, working notes app: a manifest, a typed server, a client, styles,
and a passing test suite — plus an agent skill and an MCP config, so an AI assistant in the project
already knows the framework. All of it is yours to edit. The client is Preact unless you pass
--ui react; the source is the same either way.
Open xeer.app.json in an editor with JSON Schema support and it completes valid fields and values,
and marks structural mistakes inline. The scaffold's $schema URL is a live contract served with these
docs; xeer check remains the authoritative validator and works offline.
Start from something else with --template:
npx @impetik/xeer new my-blog --template blog--template | |
|---|---|
notes (default) | Per-user notes: one table, create and delete, ownership proven in tests. |
todo | A per-user task list: add, tick off, delete, and an open count read through an index. |
blog | Posts anyone can read and only their author can delete, with a list and a read view. |
personal-site | A few static pages from one shared content module, and no database at all. |
Every template checks, tests, and builds clean, and none of them scaffolds sign-in UI — see
step 2. The rest of this page follows notes.
Those four names are bundled and work offline. Any other exact --template value is resolved through
the public template catalog. Xeer downloads the catalog and archive only after confirming the target
is empty, verifies the archive checksum, and installs it without partial project files. Catalog
templates own their renderer, so do not pass --ui with one.
#Live catalog: atelier, orario, piazza, tavola, lumen-studio, northstar-saas
The live catalog has six templates. Four are Xeer applications and two are SvelteKit landing pages:
| Catalog id | Project | What it contains | Required secrets |
|---|---|---|---|
atelier | Xeer application | Creative portfolio, project galleries, services, and an enquiry inbox. | ADMIN_INVITE_CODE |
orario | Xeer application | Appointment booking, recurring opening hours, and a staff schedule board. | ADMIN_INVITE_CODE |
piazza | Xeer application | Local directory, public submissions, photographs, and a moderation queue. | MODERATOR_INVITE_CODE |
tavola | Xeer application | Table ordering, a live kitchen board, and menu management. | KITCHEN_INVITE_CODE, ADMIN_INVITE_CODE |
lumen-studio | SvelteKit | One-page creative studio site. | none |
northstar-saas | SvelteKit | SaaS landing page with routed feature pages. | none |
Install one by its exact id:
npx @impetik/xeer new my-studio --template lumen-studioThe catalog entry decides whether the result is a Xeer application or a framework project. It also
decides the renderer. The JSON result reports projectKind, optional framework, platformVersion,
and artifactVersion; it does not report ui for catalog installs.
#A SvelteKit app instead
--framework sveltekit writes the other kind of project Xeer runs: SvelteKit owns the routes, the
renderer, and the build; Xeer owns the configuration, the deployment, and the shared preview tunnel.
It is a separate axis from --template, not one of its values, and xeer init adopts a SvelteKit
project you already have.
npx @impetik/xeer new my-kit-app --framework sveltekit
cd my-kit-app
npm install
npx xeer devIt declares xeer.config.json rather than xeer.app.json, so xeer check, dev, test, and
build run the project's own package.json scripts — the install has to come first, and Xeer reads
the lockfile it writes, so pnpm, yarn, and bun work the same way. --ui does not apply and is
refused with XE3004; Svelte is the renderer. There is no declared database and no ctx.auth in a
+page.server.ts; see the CLI reference for the full boundary. The rest
of this page is about Xeer applications.
#2. Run it
npx xeer devThat starts a local server with your client and server running together. Client edits hot-reload;
server edits recompile and restart behind a health check. The URL is printed on startup — Xeer picks a
free port unless you pass --port.
Open it and add a note. It is already stored in a real database, and it is already scoped to you — the server filters by the caller's identity, and the database enforces it.
Notice what you did not have to do: there is no sign-in screen, and there was nothing to configure. Every caller of a Xeer app has a verified identity from their first request, so an app can own data per user without shipping any auth UI at all. Add sign-in later, when you want a named account. See Auth.
Want a write in one window to appear in another? Add one line to xeer.app.json:
"budgets": { "liveConnections": 100 }Then try two browser windows side by side. Add a note in one and it appears in the other immediately: every query records which tables it read, so a write to one of them refetches exactly the queries that care. It is opt-in because a held-open stream keeps your app resident for as long as a tab is open. See Live updates.
To see per-user isolation for yourself, open a private window and visit the local sign-in route to become
a different user — at whatever port xeer dev printed, or pass --port 5173 to make this exact:
http://127.0.0.1:5173/_xeer/auth/sign-in?persona=bob&returnTo=/Bob's list is empty, because these are two different application users. That is a local persona — the mechanism that makes authorization exercisable before you deploy anything.
#3. Change something
Open src/server.ts. Add a field to a note by declaring it in the manifest first — the manifest is
the source of truth, and the types follow from it.
In xeer.app.json, add pinned to the notes table:
{
"database": {
"tables": {
"notes": {
"fields": {
"text": { "type": "string", "maxLength": 500 },
"ownerId": { "type": "string", "maxLength": 128 },
"pinned": { "type": "boolean", "optional": true }
},
"indexes": { "by_owner": ["ownerId"] }
}
}
}
}Now ctx.db.table('notes') accepts and returns pinned in your editor, and a mutation that sets it
type-checks:
'notes.pin': mutation({
input: { id: 'string', pinned: 'boolean' },
handler: async (ctx, input) => {
const note = await ctx.db.table('notes').get(input.id);
if (!note || note.ownerId !== ctx.auth.appUserId) throw new Error('Note not found.');
return ctx.db.table('notes').update(input.id, { pinned: input.pinned });
},
}),xeer dev picks the change up as you save. If you get something wrong, the error names the file, the
line, and a suggested repair — see the diagnostics reference.
Run npx xeer check at any time for the same validation without a running server.
#4. Test it
npx xeer testxeer test builds your app, boots it with fresh isolated state that never touches your dev data, and
type-checks every tests/**/*.ts module before running the registered tests. Every call is made as a named persona, so ownership is asserted rather than
assumed:
import { as, expect, expectFailure, test } from '@impetik/xeer/test';
test('bob cannot remove a note owned by alice', async () => {
const note = await as('alice').mutation('notes.create', { text: 'Only for alice' });
const refused = await expectFailure(as('bob').mutation('notes.remove', { id: note.id }));
expect(refused.code).toBe('operation_failed');
expect((await as('alice').query('notes.list', {})).map((row) => row.id)).toContain(note.id);
});The scaffolded suite already contains five tests like this and they pass on a fresh project. See Testing.
#5. Deploy it
npx xeer auth login # opens a browser, prints a confirmation code
npx xeer deployxeer auth login signs you in — the person deploying. It has nothing to do with your app's own users,
who need no Xeer account at all; see Auth.
xeer deploy builds a content-addressed artifact, verifies it, and ships it. When it finishes it
prints your application's URL. That URL is live on a global edge network, serving your client and your
server, with its own database and real identity for every visitor.
Deploying needs a Xeer account, and accounts are currently by invitation. Everything in steps 1 through 4 works with no account and no network. The framework, the compiler, the dev server, and the test runner are open source and run entirely on your machine. If you would like an invitation, see the FAQ.
Prefer to look before you leap:
npx xeer deploy --environment preview # a side-by-side URL; production keeps serving
npx xeer promote --receipt review_… # deploy prints the complete reviewed receipt idThat is the whole shipping story, plus xeer rollback when you need yesterday's version back. See
Deploy, preview, promote, roll back.
#Where to go next
| If you want to… | Read |
|---|---|
| Understand every generated file | Project structure |
| Write queries, mutations, and endpoints | Server functions and the database |
| Read data and re-render | The client |
| Enforce who can see what | Auth |
| Switch users locally, and manage local data | Local development |
| Add a database table or a file store | Capabilities |
| Store an API key | Environment variables and secrets |
| Drive Xeer from an AI agent | Building with AI agents |
| Look up a command or an error code | CLI · Diagnostics |