Example: Notes API
A complete REST API built with Hono, using a Flect database for persistence and a Flect KV store for caching.
Source: examples/notes-api
Live demo: https://notes-yc8sx2.up.flect.run
What it demonstrates
Section titled “What it demonstrates”- Database CRUD with
@flect/sdk - KV cache-first pattern (list cached 60s, single item 120s)
- Cache invalidation on write
flect.tomlbinding configuration- Docker multi-stage build with tsup
1. Create resources
Section titled “1. Create resources”flect org create --name flect-examples && flect org use flect-examplesflect ws create --name default && flect ws use defaultflect proj create --name notes && flect proj use notesflect env create --name production && flect env use production2. Create database and KV store
Section titled “2. Create database and KV store”flect db create --name notes-dbflect kv create --name notes-cache3. Run migrations
Section titled “3. Run migrations”flect db migrate notes-db --dir migrationsThe migration creates the notes table:
-- migrations/0001_create_notes.sqlCREATE TABLE IF NOT EXISTS notes ( id TEXT PRIMARY KEY, title TEXT NOT NULL, body TEXT NOT NULL DEFAULT '', created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL);4. Create the app
Section titled “4. Create the app”flect app create --name notes5. Deploy
Section titled “5. Deploy”flect app deploy notes --image ghcr.io/dotlabshq/notes-api:0.1.4| Method | Path | Description |
|---|---|---|
GET |
/notes |
List all notes (cached) |
POST |
/notes |
Create a note |
GET |
/notes/:id |
Get a note (cached) |
PATCH |
/notes/:id |
Update a note |
DELETE |
/notes/:id |
Delete a note |
GET |
/healthz |
Health check |
Create a note
Section titled “Create a note”curl -X POST https://notes-yc8sx2.up.flect.run/notes \ -H 'Content-Type: application/json' \ -d '{"title": "My first note", "body": "Hello from Flect!"}'{ "note": { "id": "cdb564dc-7fe5-4e6b-b545-5fd534ed038f", "title": "My first note", "body": "Hello from Flect!", "created_at": 1782594882769, "updated_at": 1782594882769 }}List notes
Section titled “List notes”curl https://notes-yc8sx2.up.flect.run/notes{ "notes": [...], "source": "cache"}source is "db" on first load, "cache" on subsequent requests within 60 seconds.
Code walkthrough
Section titled “Code walkthrough”flect.toml
Section titled “flect.toml”name = "notes-api"port = 3000
[[databases]]binding = "DB"name = "notes-db"migrations_dir = "migrations"
[[kv]]binding = "CACHE"name = "notes-cache"src/index.ts
Section titled “src/index.ts”import { createEnv } from '@flect/sdk'
const env = createEnv()const db = env.db('DB') // connects via FLECT_TOKEN → flect-proxy → sqldconst cache = env.kv('CACHE') // connects via FLECT_TOKEN → flect-proxy → Valkey
// cache-first listapp.get('/notes', async (c) => { const cached = await cache.getJson<Note[]>('all') if (cached) return c.json({ notes: cached, source: 'cache' })
const notes = await db.query<Note>('SELECT * FROM notes ORDER BY created_at DESC') await cache.setJson('all', notes, { ttl: 60 }) return c.json({ notes, source: 'db' })})
// invalidate cache on writeapp.post('/notes', async (c) => { // ... insert into db await cache.del('all') return c.json({ note }, 201)})Dockerfile
Section titled “Dockerfile”FROM node:22-alpine AS builderWORKDIR /appRUN corepack enable && corepack prepare pnpm@latest --activate
COPY package.json pnpm-workspace.yaml pnpm-lock.yaml ./COPY examples/notes-api/package.json examples/notes-api/package.jsonCOPY projects/flect/packages/sdk/package.json projects/flect/packages/sdk/package.json
RUN pnpm install --frozen-lockfile
COPY projects/flect/packages/sdk/ projects/flect/packages/sdk/COPY examples/notes-api/ examples/notes-api/
RUN pnpm --filter @flect/sdk buildRUN pnpm --filter notes-api build
FROM node:22-alpineWORKDIR /appCOPY --from=builder /app/examples/notes-api/dist/index.cjs ./index.cjsENV NODE_ENV=productionEXPOSE 3000CMD ["node", "index.cjs"]Key points:
- Multi-stage build keeps the final image minimal
tsupwithformat: ['cjs']andnoExternal: [/.*/]bundles everything into a single file — nonode_modulesin the final image@flect/sdkis built first, then bundled into the app