Skip to content

Quick Start

Quick Start

In five minutes you will have a tiny but complete workspace: one collection, one app, and a built bundle. The same source builds locally and, when you host on Colony , in Workspace Studio.

src/
├── collections/
│   ├── +relationship.ts        # relationship registry (required)
│   └── tasks/
│       └── +model.ts           # the collection
└── apps/
    └── +tasks.svelte           # the app

1. Configure Vite and TypeScript

Start from a plain Vite project and add the Bolt plugin. The plugin owns the build.

// vite.config.ts
import { bolt } from '@norbital-ai/bolt/vite';
import { defineConfig } from 'vite';

export default defineConfig({ plugins: [bolt()] });
// tsconfig.json
{ "extends": "./.norbital/tsconfig.json" }

2. Define a collection

Create src/collections/tasks/+model.ts . The directory name tasks is the collection ID; the model declares fields and options, nothing else.

// src/collections/tasks/+model.ts
import { defineModel, enums, text } from '@norbital-ai/bolt/authoring';

export default defineModel(
  {
    title: text().notNull(),
    status: enums(['open', 'done']).notNull().default('open')
  },
  { description: 'Task', recordLabel: 'title' }
);

3. Add the relationship registry

Create src/collections/+relationship.ts . Every workspace needs exactly one of these; it is where all collection relationships are declared.

// src/collections/+relationship.ts
import type { Relationships } from './$types.js';

export default ((r) => ({
  tasks: {}
})) satisfies Relationships;

4. Add an app

Create src/apps/+tasks.svelte . Apps are plain Svelte components; the filename is the app ID. CollectionTable renders your collection with schema-derived forms and create/edit built in — and reads through live queries , so the table stays live as data changes.

<!-- src/apps/+tasks.svelte -->
<script lang="ts">
  import { CollectionTable } from '@norbital-ai/ui/collection-table';
  import { Stack } from '@norbital-ai/ui/layout';
  import { PageHeader } from '@norbital-ai/ui/page-header';
</script>

<svelte:head>
  <title>Tasks</title>
  <meta name="bolt:icon" content="lucide:list-todo" />
</svelte:head>

<Stack gap="lg">
  <PageHeader title="Tasks" description="Everything the team is working on." />
  <CollectionTable collection="tasks">
    {#snippet columns({ Column })}
      <Column name="title" />
      <Column name="status" />
    {/snippet}
  </CollectionTable>
</Stack>

5. Sync

bolt sync
  • bolt sync runs the filesystem compiler : it validates role files (a stray `+`-prefixed file with no role is an error), generates .norbital/tsconfig.json , registry modules, and local $types .
  • bolt sync also builds the client under .norbital/dist/ and emits the portable server artifact under .norbital/artifact/ .
Two different ‘sync’s
bolt sync is the filesystem compiler that validates and regenerates types on every save. The data sync engine is the runtime layer that keeps live queries current inside running apps. Same word, different jobs.

Next

You now have a buildable workspace. From here: