Define a database collection and schema for SvelteKit from the command line

A new model in a SvelteKit app means a database table, a migration, a Zod schema and TypeScript types that agree with each other. vela generate resource creates all of them from one field list, without opening an admin UI.

3 min read databasepocketbasezodmigrationsgeneratorssveltekit

Adding a table to a SvelteKit app is usually a tour: create the collection in the database admin, write a migration so teammates get it too, write a Zod schema for validation, and generate or hand-write the TypeScript types. Four places that describe the same fields and slowly drift apart. vela generate resource treats the field list as the single source and produces the rest: a PocketBase collection, a versioned migration, a Zod schema, and synced types.

Prerequisites

A vela project with a backend. npx vela create my-app gives you one; npx vela bless adds the backend to an existing SvelteKit project (more on that here). The author:current_user field below needs authentication enabled.

Run the command

$ vela generate resource articles title:text! body:editor author:current_user
✔ Created collection articles
✔ Created migrations/1788445216_created_articles.js
✔ Created src/lib/schemas/article.ts
✔ Synced types

Three things happened:

  1. The articles collection now exists in your local PocketBase, with title required, body as rich text, and author as a relation to the users collection.
  2. A migration file was written to migrations/, so the same collection is created wherever the app is deployed or cloned.
  3. Types were synced: Models["articles"] and Schemas["articles"] from @velastack/pocketbase now describe the new collection.

What was generated

The one source file is the Zod schema. The satisfies on the last line is the part that matters: it ties the schema to the synced type, so if a field changes in the database and the schema does not, the type checker says so.

src/lib/schemas/article.ts
import { z } from "zod";
import type { Schemas } from "@velastack/pocketbase";

export const articleSchema = z.object({
  id: z.string().optional(),
  collectionId: z.string().optional(),
  title: z.string().nonempty(),
  body: z.string().optional(),
  author: z.string(),
}) satisfies Schemas["articles"];

author is a plain string in the schema because relations are stored as record ids. The current_user type also does two things outside this file: forms generated for the model skip the field and fill it from the session, and the collection’s access rules restrict rows to their owner.

Use it

The collection is reachable through the PocketBase client on locals. locals.pb is scoped to the signed-in user; locals.admin sees everything:

src/routes/(app)/articles/+page.server.ts
export const load = async ({ locals }) => {
  const articles = await locals.pb.collection("articles").getFullList();
  return { articles };
};

The records are typed as Models["articles"], so article.title autocompletes and article.tittle does not compile. To validate input before writing, use the schema exactly as the form generator does.

Tip
If you want the pages as well as the model, vela generate scaffold takes the same field list and adds list, create, view and edit routes on top.

Change the model later

The field list is not a one-shot. Once the collection exists, evolve it with a migration:

$ vela generate migration articles add published:bool

Evolving your schema with migrations covers add, remove, rename and references.

Going further

Related tutorials

The field syntax behind vela generate - types, modifiers, relations and nested models

Every vela generator reads the same one-line field syntax. This is the whole grammar with an example of what each piece generates, from name:text! to select(...), current_user and users/pets.

4 min read

CRUD with SvelteKit remote functions - a scaffold without form actions

The same list, create, view and edit pages as the classic scaffold, but the forms post to typed remote functions instead of form actions. vela generate scaffold --remote writes the routes, the .remote.ts handlers, the schema, the collection and the tests.

3 min read

SvelteKit CRUD in one command - list, create, view and edit pages with a database table

A full CRUD interface in SvelteKit is ten files, a data table, two forms and a collection. vela generate scaffold writes all of it from a field list, tested, so you can spend the afternoon on the parts that are specific to your app.

4 min read