Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.cubby.pro/llms.txt

Use this file to discover all available pages before exploring further.

Building Database Apps

Cubby is database-ready out of the box. The default cubby init template is SQLite on every plan — choose the Neon Postgres template (Builder/Pro) only when you need Postgres features. The default is SQLite, not Postgres.
Most first cubbies should start with SQLite. It is simple, fast, and already wired into the default cubby init template.

Choose a database path

PathBest forAvailability
SQLitepersonal tools, friend-group apps, prototypes, small dashboards, first cubbiesevery plan
Neon Postgresheavier relational apps, concurrent writes, Postgres-specific features, branching/snapshotsBuilder and Pro
Both paths use the same core rule: read DATABASE_URL from the runtime environment. Cubby injects it for you.

SQLite: the default path

Run cubby init and choose the default Next.js + SQLite template:
cubby init my-app
cd my-app
npm install
The template includes Prisma, a SQLite-ready schema, a database client, and Cubby instructions for AI tools:
my-app/
├── prisma/
│   └── schema.prisma     # SQLite datasource + your models
├── lib/
│   └── db.ts             # Prisma client singleton
├── cubby.yaml
├── CUBBY.md
└── package.json
Your Prisma datasource should read the database URL at runtime:
datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}
On Cubby, SQLite data is stored on persistent app storage. Locally, the template uses a local SQLite file so you can build quickly without running a database server.

Define your models

Edit prisma/schema.prisma:
model Todo {
  id        String   @id @default(cuid())
  title     String
  completed Boolean  @default(false)
  userId    String
  createdAt DateTime @default(now())
}

Decide data scoping before you write a schema — default to shared

Cubby’s gateway already controls who can open the app (the owner + explicitly-shared users). The x-cubby-user-id header answers “is this person allowed in?” — it is an access gate, not a partition key. So default to a shared dataset: one deployment = one shared dataset. For a separate group, deploy a separate copy.
import { prisma } from '@/lib/db'

// Shared (default): every authorized user sees the same data.
export async function GET() {
  const todos = await prisma.todo.findMany({
    orderBy: { createdAt: 'desc' },
  })
  return Response.json(todos)
}
Only key rows by the viewer when the app is explicitly per-user (e.g. a private journal where each person has their own isolated data). A family / team / household seed is a tell that the data is shared — do not key it per viewer:
import { headers } from 'next/headers'
import { prisma } from '@/lib/db'

// Per-user (opt in only when each viewer truly owns isolated data):
export async function GET() {
  const h = await headers()
  const userId = h.get('x-cubby-user-id')!
  const todos = await prisma.todo.findMany({
    where: { userId },
    orderBy: { createdAt: 'desc' },
  })
  return Response.json(todos)
}
Cubby auth runs before your app receives the request, so your app can trust the Cubby-injected identity headers (x-cubby-user-id, x-cubby-username).

Local development

SQLite (the default template): no Docker, and no local DB is needed for frontend work — Cubby runs prisma db push for you on deploy. Just run:
npm run dev
If you want a live local SQLite database to click through, the data/ directory must exist first, or prisma db push fails with P1003 Database does not exist:
mkdir -p data              # create the data/ dir (prisma db push then creates the .db file)
npx prisma db push         # now the schema applies and the SQLite file is created
npm run dev
Keep DATABASE_URL as file:./data/app.db — never a ../ path (it escapes the project and breaks the sandbox). Neon (the nextjs-neon template): use cubby dev, which requires Docker (it runs a local postgres:17-alpine):
cubby dev      # Docker required — local Postgres
cubby check
No Docker? Point DATABASE_URL at a real Neon branch in .env.local and run npm run dev. See cubby dev for details. Before deploying, make sure the schema is in source control and the app reads DATABASE_URL from the environment instead of hardcoding a file path.

Deploy

cubby deploy
During deploy, Cubby injects the production DATABASE_URL, applies platform checks, builds the app, and runs it with persistent storage.

Neon Postgres: Builder and Pro

Choose Neon Postgres when you need Postgres behavior rather than just persistence:
  • concurrent writes beyond SQLite’s sweet spot
  • Postgres extensions or SQL features
  • database branching and snapshots
  • a workflow that already expects Postgres
Start with the Neon template:
cubby init my-neon-app
# choose: Next.js + Neon Postgres
The template configures cubby.yaml for Neon:
name: my-neon-app
database:
  provider: neon
Cubby manages the Neon project/database and injects DATABASE_URL and DIRECT_URL at runtime. See Building with Neon Postgres for the full walkthrough.

Secrets are not database config

Do not commit .env files or database URLs. For third-party keys, use Cubby secrets:
cubby secrets set OPENAI_API_KEY --env prod   # NAME only — prompts for the value
cubby deploy
The default env is local, so pass --env prod for production secrets. Set them only after your first deploy, then redeploy (or run cubby secrets apply --env prod). Database URLs are platform-managed. App secrets are yours to set.

Troubleshooting

Make sure your schema uses url = env("DATABASE_URL"). Locally, create the expected local env file or run through cubby dev; on Cubby, the value is injected at runtime.
Use the Neon Postgres template and a Builder or Pro plan. SQLite is the default path, not the only path.
Check whether you changed or deleted your local SQLite file. Local data is separate from Cubby runtime data.
Point it at CUBBY.md. Cubby already provides auth headers and database injection; the app should use those platform primitives.

Next steps

Build your first app

A complete SQLite-first todo app walkthrough.

Use Neon Postgres

The Builder/Pro Postgres path.