{"id":50652689,"url":"https://github.com/async-framework/async-db","last_synced_at":"2026-06-10T07:01:01.084Z","repository":{"id":356270513,"uuid":"1231706222","full_name":"async-framework/async-db","owner":"async-framework","description":"Gradual data workflow from JSON fixtures to generated types, local APIs, writable stores, and real persistence.","archived":false,"fork":false,"pushed_at":"2026-06-07T21:35:26.000Z","size":1801,"stargazers_count":4,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-07T22:26:26.624Z","etag":null,"topics":["async","async-db","database","falcorjs","graphql","json","jsondb"],"latest_commit_sha":null,"homepage":"https://async-framework.github.io/async-db/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/async-framework.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-05-07T07:56:34.000Z","updated_at":"2026-06-07T20:53:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/async-framework/async-db","commit_stats":null,"previous_names":["patrickjs/jsondb","async-framework/async-db"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/async-framework/async-db","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/async-framework%2Fasync-db","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/async-framework%2Fasync-db/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/async-framework%2Fasync-db/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/async-framework%2Fasync-db/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/async-framework","download_url":"https://codeload.github.com/async-framework/async-db/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/async-framework%2Fasync-db/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34140775,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-10T02:00:07.152Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["async","async-db","database","falcorjs","graphql","json","jsondb"],"created_at":"2026-06-07T22:00:16.623Z","updated_at":"2026-06-10T07:01:01.038Z","avatar_url":"https://github.com/async-framework.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @async/db\n\n`@async/db` gives frontend teams a gradual path from mock JSON to production data contracts. You can keep easy fixture files where they work, use the first-party JSON file database for small low-write resources, and move other resources to SQLite, Postgres, or custom stores as they get serious. The app keeps talking to one data layer while persistence changes behind each resource.\n\nUse it to:\n\n- Start from editable JSON, JSONC, or CSV fixtures in `db/`.\n- Infer schema contracts and generate TypeScript types from fixtures and schemas.\n- Serve local REST routes and a lightweight viewer while the backend contract is still forming.\n- Upgrade persistence per resource without rewriting frontend data access.\n- Keep static fixtures, the first-party JSON file database, SQLite, Postgres, KV/Redis-like stores, and custom stores behind the same app-facing resource model.\n- Emit schema metadata for admin, CMS, or form-building screens.\n\n`@async/db` is not a universal key/value driver layer; storage is one boundary inside the fixture-to-contract workflow.\n\n## File Map\n\n| Files | Purpose |\n| --- | --- |\n| `db/*.json`, `db/*.jsonc`, `db/*.csv` | Fixture data |\n| `db/*.schema.json`, `db/*.schema.jsonc`, `db/*.schema.js` | Optional stricter schema contracts |\n| `db.schema.js` | Optional root schema registry for all resources |\n| `db/\u003cresource\u003e/index.schema.js` | Folder-backed content collection marker |\n| `.db/state/*` | Generated writable JSON store state |\n| `.db/schema.generated.json`, `.db/types/index.d.ts` | Generated metadata and types |\n\n## Quick Summary\n\nMost projects can start with the defaults:\n\n1. Put fixtures in `db/`.\n2. Run `async-db sync` to generate schema metadata, TypeScript types, and runtime state.\n3. Run `async-db serve` to start the local API and viewer.\n4. Open `http://127.0.0.1:7331/__db`.\n5. Call REST routes like `GET /db/users.json` and `POST /db/users`.\n6. Add per-resource schemas or `db.schema.js` only when the fixture shape needs a clearer contract.\n\nThe default server is REST-first. GraphQL is available at `/graphql`, but you do not need it for the core workflow.\n\n## Examples\n\nStart with [`examples/basic`](./examples/basic) for the shortest schema-backed workflow.\n\nOther useful paths:\n\n- [`examples/data-first`](./examples/data-first): plain fixtures before schemas exist.\n- [`examples/content-collections`](./examples/content-collections): docs and blog folders as static content collections.\n- [`examples/computed-fields`](./examples/computed-fields): computed field patterns across several schema-backed models.\n- [`examples/production-json`](./examples/production-json): feature flags and settings in the JSON store behind registered operations.\n- [`examples/rest-client`](./examples/rest-client): calling @async/db from app or test code.\n- [`examples/local-web-app`](./examples/local-web-app): loopback app state saved directly to `db/*.json`.\n- [`examples/schema-manifest`](./examples/schema-manifest): schema metadata for admin/CMS UI.\n- [`examples/standard-schema`](./examples/standard-schema): Standard Schema validators with Async DB metadata overlays.\n- [`examples/hono-auth`](./examples/hono-auth): optional Hono auth and write hooks.\n\nSee [Which Example Should I Start With?](#which-example-should-i-start-with) for the full examples map.\n\n## Install\n\nInstall the published package in the app or package that will use it:\n\n```bash\nnpm install @async/db\n```\n\nAdd package scripts for the CLI commands you want to run often:\n\n```json\n{\n  \"scripts\": {\n    \"db\": \"async-db\",\n    \"db:sync\": \"async-db sync\",\n    \"db:serve\": \"async-db serve\",\n    \"db:types\": \"async-db types\"\n  }\n}\n```\n\nIf you need an unreleased fix, pin a reviewed GitHub commit or release tag instead of the moving default branch:\n\n```json\n{\n  \"devDependencies\": {\n    \"@async/db\": \"github:async-framework/async-db#\u003creviewed-commit-sha-or-tag\u003e\"\n  }\n}\n```\n\nThe package import name is `@async/db`; helpers are available from `@async/db/config`, `@async/db/schema`, `@async/db/client`, and `@async/db/json`. The root package exports runtime helpers such as `openDb()` and schema contract helpers such as `loadDbSchema()`.\n\n## Five-Minute Start\n\nCreate a fixture:\n\n```bash\nmkdir -p db\ncat \u003e db/users.json \u003c\u003c'JSON'\n[\n  {\n    \"id\": \"u_1\",\n    \"name\": \"Ada Lovelace\",\n    \"email\": \"ada@example.com\"\n  }\n]\nJSON\n```\n\nSync generated metadata, types, and runtime state:\n\n```bash\nnpm run db:sync\n```\n\nStart the local API and viewer in terminal 1:\n\n```bash\nnpm run db:serve\n```\n\nOpen the viewer:\n\n```txt\nhttp://127.0.0.1:7331/__db\n```\n\nCall the REST API from terminal 2:\n\n```bash\ncurl http://127.0.0.1:7331/db/users.json\n```\n\nCreate a local record:\n\n```bash\ncurl -X POST http://127.0.0.1:7331/db/users \\\n  -H 'content-type: application/json' \\\n  -d '{\"id\":\"u_2\",\"name\":\"Grace Hopper\",\"email\":\"grace@example.com\"}'\n```\n\nThe default sync output is generated:\n\n```txt\n.db/schema.generated.json\n.db/types/index.d.ts\n.db/state/users.json\n```\n\n`serve` syncs on startup, watches the fixture folder, refreshes valid resources when files change, and surfaces file-specific diagnostics in the viewer without breaking unrelated resources.\n\nSee [docs/getting-started.md](./docs/getting-started.md) for the expanded walkthrough.\n\n## Operational Contract\n\n| Behavior | Default |\n| --- | --- |\n| Source fixtures | Read from `./db` recursively. |\n| App data routes | Exposed under `/db` by default, such as `GET /db/users.json`. |\n| Runtime writes | Go to the default JSON store under `.db/state`. |\n| Source writes | Only happen for resources bound to the `sourceFile` store, and only for supported writebacks such as generated ids in plain `.json` collections. |\n| Optional stores | SQLite, Postgres, generic KV, and Redis-like stores plug into the same runtime store boundary without adding mandatory database client dependencies. |\n| Generated output | `.db/` is runtime output and normally stays uncommitted. |\n| Schema contract API | `loadDbSchema({ from })` loads metadata only by default; `openDb({ schema })` opens the runtime database from the same schema locator. |\n| Local server | Binds to `127.0.0.1:7331` by default and exposes writable local development endpoints. |\n| Trusted code | `.schema.js`, `db.config.mjs`, source readers, and manifest hooks execute as local project code. |\n| Mock latency | Responses include a small `30-100ms` delay by default so loading states are visible. |\n\nThe built-in JSON store is production-appropriate only for file-suitable resources: app settings, feature flags, content, templates, plan definitions, policy rules, seed data, and other small low-write data that can safely live with a single writer. Keep high-write user data, chat/messages, analytics/events, ledgers, inventory counters, multi-writer data, and compliance-heavy transactional records in SQLite, Postgres, or another app-owned store.\n\n@async/db is not an auth layer, an ORM, a hosted database service, or a broad JSON Schema compatibility project. For production-facing APIs, put app traffic behind registered operations, app-owned auth/authorization, rate limits, and observability. See [Production JSON Database](./docs/json-production.md), [Resource Graduation And Mixed Stores](./docs/store-graduation.md), and [Prototype To Production REST Guide](./docs/prototype-to-production.md).\n\nWhen another app consumes your data, define a `contracts` boundary in\n`db.config.mjs`. Contracts list the resources, fields, operations, and writes a\nconsumer is allowed to use. Generate starting points with\n`async-db contracts infer --from-tags`, scan callers with\n`async-db contracts infer --from-usage`, validate with\n`async-db contracts check`, and emit contract-scoped refs with\n`async-db contracts refs`.\n\n## Save Directly To `db/*.json`\n\nThe default `json` store keeps source fixtures unchanged and writes app edits to\nthe generated mirror under `.db/state`. For small local apps where saved state\nshould live in the project folder, use the `sourceFile` store:\n\n```js\nimport { defineConfig } from '@async/db/config';\n\nexport default defineConfig({\n  stores: {\n    default: 'sourceFile',\n  },\n});\n```\n\nNow writes to plain JSON resources update `db/\u003cresource\u003e.json` directly.\nOverride individual resources when some data should still use the mirror:\n\n```js\nexport default defineConfig({\n  stores: {\n    default: 'sourceFile',\n  },\n  resources: {\n    importedRows: { store: 'json' },\n  },\n});\n```\n\nSee [`examples/local-web-app`](./examples/local-web-app) for a loopback app that\nsaves on blur/change, keeps server state canonical, and uses browser storage\nonly for transient reload recovery.\n\nFor simple local websites, keep the shape boring:\n\n```txt\ndb/          saved JSON documents and seed data\nsrc/         browser HTML, CSS, and app code\nserver/      loopback request handlers and @async/db mounting\nframework/   small reload, draft, and DOM helpers\n```\n\nRun `async-db sync` in that loop even when every resource uses `sourceFile`.\nSync still validates the fixture folder, infers the schema, and writes generated\nmetadata/types for tools. The difference is that app writes go back to plain\n`db/*.json` instead of the `.db/state` mirror, so the project folder contains\nthe state you want to save, copy, or commit.\n\n## Open With An In-Memory Filesystem\n\n`openDb()` can take a filesystem adapter when a tool, test, or embedded runtime\nneeds to boot from virtual files and keep generated output out of the real\nproject folder:\n\n```js\nimport { createMemoryFs, openDb } from '@async/db';\n\nconst fs = createMemoryFs({\n  cwd: '/virtual-app',\n  files: {\n    'db/users.json': JSON.stringify([\n      { id: 'u_1', name: 'Ada Lovelace' },\n    ]),\n  },\n});\n\nconst db = await openDb({\n  cwd: '/virtual-app',\n  fs,\n  stores: {\n    default: 'json',\n  },\n});\n\nawait db.collection('users').create({\n  id: 'u_2',\n  name: 'Grace Hopper',\n});\n\nconst state = await fs.readFile('/virtual-app/.db/state/users.json', 'utf8');\n```\n\nThe adapter is used for fixture reads, generated outputs, JSON runtime state,\n`sourceFile` writebacks, operations manifests, forks, branches, and snapshots.\nExecutable local code such as `db.config.mjs` and `.schema.js` still runs\nthrough Node's module loader, so virtual projects should use inline options or\nJSON/JSONC/CSV schema sources.\n\n## Add Schema When It Pays For It\n\nData-first fixtures are enough until the shape matters. Inspect what @async/db infers:\n\n```bash\nnpm run db -- schema infer\nnpm run db -- schema infer users\nnpm run db -- schema infer users --out db/users.schema.jsonc\n```\n\nAdd `db/users.schema.json`, `db/users.schema.jsonc`, or `db/users.schema.js` when you need stricter behavior:\n\n```json\n{\n  \"kind\": \"collection\",\n  \"idField\": \"id\",\n  \"fields\": {\n    \"id\": { \"type\": \"string\", \"required\": true },\n    \"name\": { \"type\": \"string\", \"required\": true },\n    \"email\": {\n      \"type\": \"string\",\n      \"required\": true,\n      \"unique\": true,\n      \"description\": \"Email address used for local sign-in.\"\n    },\n    \"role\": {\n      \"type\": \"enum\",\n      \"values\": [\"admin\", \"user\"],\n      \"default\": \"user\"\n    }\n  }\n}\n```\n\nThen validate:\n\n```bash\nnpm run db -- schema validate\n```\n\nIn mixed mode, schema files define the contract and data files provide seed records. Unknown fields warn by default; configure `schema.unknownFields: 'error'` when drift should fail.\n\nSchema defaults fill omitted fields on create and safe additive runtime hydration. Updates, patches, and document puts preserve omitted fields; include a field in the write body when you want to change it.\n\nExecutable `.schema.js` files can also accept Standard Schema-compatible validators:\n\n```js\nimport { collection, field } from '@async/db/schema';\n\nexport default collection({\n  validator: UserSchema,\n  fields: {\n    email: field.string({ required: true, unique: true }),\n    displayName: field.computed(field.string(), ({ record }) =\u003e record.email),\n  },\n});\n```\n\nThe validator owns runtime parsing through `~standard.validate`; Async DB overlays keep generated metadata, relations, defaults, and computed resolvers. Async validators run in package, REST, and GraphQL writes. Sync schema helpers throw `DB_SCHEMA_ASYNC_VALIDATOR_REQUIRED` when the validator returns a Promise; use `validateAsync()` or `assertAsync()` for that path.\n\nSee [docs/concepts.md](./docs/concepts.md) and [docs/fixtures-and-schemas.md](./docs/fixtures-and-schemas.md).\n\n## Validate Or Resolve From Schema\n\nUse `loadDbSchema({ from })` when server code wants schema validation or field\nresolver access without opening stores:\n\n```ts\nimport { loadDbSchema, openDb } from '@async/db';\n\nconst schema = await loadDbSchema({ from: './db.schema.js' });\nconst input = schema.validator('users', { unknownFields: 'strip' }).assert(await request.json());\n\nconst userResolvers = schema.resolver('users', {\n  value: input,\n  context: { locale: 'en-US', nameFormatter },\n});\n\nconst fullName = await userResolvers.fullName();\nconst db = await openDb({ schema });\n```\n\nValidators reject computed and read-only fields. Resolver functions receive a\ndelegated `this` context with `this.get(name)`, so app-provided context can\noverride internal values while `this._internal` still exposes the original\nruntime view.\n\n## Admin/CMS Schema Metadata\n\nSchemas can also drive local admin, CMS, custom data viewers, and form-building screens. Use `GET /__db/manifest.json` at runtime when a UI runs beside `async-db serve`, or configure `outputs.viewerManifest` when app code needs a committed JSON artifact with the same viewer metadata. Browser requests can open `GET /__db/manifest.html`; AI clients can use `GET /__db/manifest.md`; `GET /__db/manifest` lets the `Accept` header choose among registered response formats.\n\nUse `outputs.schemaManifest` when an app only needs the smaller model metadata file without server route links, diagnostics, or viewer capabilities.\n\n```js\nimport { defineConfig, mergeManifest } from '@async/db/config';\n\nexport default defineConfig({\n  outputs: {\n    schemaManifest: './src/generated/db.schema.json',\n    viewerManifest: './src/generated/db.viewer.json',\n  },\n\n  server: {\n    viewerLinks: [\n      { label: 'App Data Viewer', href: 'http://127.0.0.1:5173/db' },\n    ],\n  },\n\n  schemaManifest: {\n    customizeResource({ file, defaultManifest }) {\n      // Group fields by source folder so an admin shell can show CMS records\n      // separately from operational data without hard-coding that in the UI.\n      return mergeManifest(defaultManifest, {\n        editor: {\n          group: file?.startsWith('db/cms/') ? 'CMS' : 'Data',\n        },\n      });\n    },\n\n    customizeField({ fieldName, path, defaultManifest }) {\n      if (fieldName.endsWith('Markdown')) {\n        // Markdown body fields need a richer editor than a plain text input,\n        // but the fixture record should still stay normal JSON data.\n        return mergeManifest(defaultManifest, {\n          ui: { component: 'markdown' },\n        });\n      }\n\n      if (path === 'blocks.chartId') {\n        // Relation ids stay as strings in fixtures, while the generated\n        // manifest tells the admin UI to render a picker backed by charts.\n        return mergeManifest(defaultManifest, {\n          ui: {\n            component: 'relation-select',\n            relationTo: 'charts',\n          },\n        });\n      }\n\n      return defaultManifest;\n    },\n  },\n});\n```\n\nThe generated manifest is metadata output; schema defaults and validation still come from the schema contract. Actual records stay on REST or GraphQL routes, so a custom viewer fetches `manifest.json` for fields and route links, then calls the listed resource routes for rows. `server.viewerLinks` exposes custom viewer URLs in root discovery and the shared manifest.\n\nSee [docs/generated-files.md](./docs/generated-files.md) and [examples/schema-manifest](./examples/schema-manifest).\n\n## Common Commands\n\nWith the `db` script from the install snippet:\n\n```bash\nnpm run db -- sync\nnpm run db -- types\nnpm run db -- types --watch\nnpm run db -- types --out ./src/generated/db.types.d.ts\nnpm run db -- schema\nnpm run db -- schema users\nnpm run db -- schema infer users\nnpm run db -- schema validate\nnpm run db -- integrate inspect ./src --sqlite ./data/app.sqlite\nnpm run db -- doctor\nnpm run db -- check --strict\nnpm run db -- create users '{\"id\":\"u_2\",\"name\":\"Grace Hopper\",\"email\":\"grace@example.com\"}'\nnpm run db -- serve\nnpm run db -- generate hono\n```\n\nWith pnpm and the same `\"db\": \"async-db\"` script:\n\n```bash\npnpm db sync\npnpm db schema validate\npnpm db serve\n```\n\nSee [docs/package-api.md](./docs/package-api.md) for CLI and package export details.\n\n## REST, GraphQL, Falcor, And Viewer\n\nThe local server exposes REST routes for collections and singleton documents, plus focused GraphQL and Falcor endpoints at `/graphql` and `/model.json`. REST remains the default path because it pairs directly with the viewer and local fixture workflow.\nSet `rest.enabled: false` when an app wants schema, manifest, viewer, import, events, GraphQL, and Falcor routes without generated REST resource routes or REST batching.\nSet `graphql.enabled: false` when an app wants REST and dev-tool routes without a GraphQL endpoint.\nSet `falcor.enabled: false` when an app wants REST, GraphQL, and dev-tool routes without a Falcor JSONGraph endpoint.\nRun `async-db usage scan --production` to produce a source-scan usage manifest with endpoint exposure recommendations.\n\n```txt\nGET     /db/users.json\nGET     /db/users/:id.json\nPOST    /db/users\nPATCH   /db/users/:id\nDELETE  /db/users/:id\n\nGET     /db/settings.json\nPUT     /db/settings\nPATCH   /db/settings\n```\n\nStandalone dev also exposes canonical REST aliases and a meta batch endpoint:\n\n```txt\nGET     /resources/users\nGET     /resources/users/:id\nPOST    /resources/users\nPATCH   /resources/users/:id\nDELETE  /resources/users/:id\nPOST    /batch\n```\n\nBulk resource requests use the collection route: `POST /resources/users` accepts an array of records, `PATCH /resources/users` accepts `{ \"ids\": [...], \"patch\": {...} }` or per-record patch items, `PUT /resources/users` replaces listed records, and `DELETE /resources/users?id=u_1\u0026id=u_2` deletes multiple records.\n\nUse `select`, `offset`, and `limit` when a prototype only needs part of a collection:\n\n```bash\ncurl 'http://127.0.0.1:7331/db/users.json?select=id,name\u0026offset=0\u0026limit=20'\ncurl 'http://127.0.0.1:7331/db/users.json?id=u_1\u0026select=id,name'\n```\n\nThe `?id=` shortcut is only for explicit JSON routes. Extensionless REST routes\nuse normal record URLs such as `/db/users/u_1`.\n\nThe `.json` route is a fixture-like URL for the synced runtime resource:\n`db/users.json` maps to `GET /db/users.json`, while local writes still go to\nthe selected runtime store. See [Fixture-Like `.json` Routes](./docs/server-and-viewer.md#fixture-like-json-routes).\n\nGraphQL remains available at `/graphql`, and Falcor browser clients can point `falcor.HttpDataSource` at `/model.json`. Scoped aliases also exist under the tool base as `/__db/graphql`, `/__db/model.json`, and `/__db/batch` for embedded dev servers.\n\nThe viewer at `/__db` lets you inspect resources, import CSV files into the configured fixture folder, view generated schema metadata, read GraphQL SDL/operation references, and try REST requests without writing client code first.\n\nThe built-in viewer and custom viewer UIs use the same JSON manifest at `/__db/manifest.json`. `/__db/manifest.html` opens a formatted JSON viewer, `/__db/manifest.md` returns an AI-friendly Markdown wrapper, and `/__db/manifest` chooses from registered media types in `Accept`. Apps can use `api.formats` from the manifest to discover supported extensions and build their own viewer UI against REST, GraphQL, or Falcor records.\n\nSee [docs/server-and-viewer.md](./docs/server-and-viewer.md). When local\n`/db/*` routes are ready to become `/api/db/*` or `/api/*` production API\nroutes, see the\n[Prototype To Production REST Guide](./docs/prototype-to-production.md).\n\n## Which Example Should I Start With?\n\nThe examples are a learning path. Run most examples with `npm run db -- sync --cwd ./examples/\u003cname\u003e` and `npm run db -- serve --cwd ./examples/\u003cname\u003e`, or run `npm run examples` to open one lazy examples index. Use `npm run examples` for examples with custom app routes such as `local-web-app` and `schema-ui`. The examples index binds to `127.0.0.1` by default; use `npm run examples -- --tailscale-serve` when you want Tailscale Serve to proxy that local port over HTTPS for devices in your tailnet.\n\n| If you want to learn... | Start with | What it shows |\n| --- | --- | --- |\n| The shortest schema-backed workflow | [`examples/basic`](./examples/basic) | Sync, viewer, REST create, committed generated types |\n| Plain data before schemas exist | [`examples/data-first`](./examples/data-first) | Inferred collections, documents, routes, and types |\n| Docs and blog folders as content collections | [`examples/content-collections`](./examples/content-collections) | `index.schema.mjs`, `files(..., { read })`, raw MDX bodies, config-owned static stores, computed fields |\n| Different computed field patterns | [`examples/computed-fields`](./examples/computed-fields) | Shorthand resolvers, `resolveMany`, formatting, and runtime-context lookups |\n| Contract-first resources | [`examples/schema-first`](./examples/schema-first) | Schema-only resources, empty seed records, committed types |\n| Calling @async/db from app or test code | [`examples/rest-client`](./examples/rest-client) | `createDbClient`, direct REST calls, REST batching |\n| Local app state saved in the project | [`examples/local-web-app`](./examples/local-web-app) | `stores.default: 'sourceFile'`, blur/change saves, transient reload state, custom example runtime |\n| Related local records | [`examples/relations`](./examples/relations) | Relation metadata, `expand`, and nested `select` |\n| CSV as the source of truth | [`examples/csv`](./examples/csv) | CSV inference, source hashes, mirror refreshes |\n| Admin/CMS-style field metadata | [`examples/schema-manifest`](./examples/schema-manifest) | `outputs.schemaManifest` and manifest customization |\n| Schema JSON to simple CMS UI templates | [`examples/schema-ui`](./examples/schema-ui) | `serve.mjs` SSR view/editor HTML from manifest + mirror (`node ./examples/schema-ui/serve.mjs`); `/templates` route keeps static placeholders |\n| Standard Schema validators | [`examples/standard-schema`](./examples/standard-schema) | Dependency-free Standard Schema validation, `field.meta(...)` overlays, async write validation, computed fields, and conservative type fallback |\n| Diagnostics for schema/data drift | [`examples/diagnostics`](./examples/diagnostics) | Warnings surfaced without breaking unrelated resources |\n| Production-suitable JSON control data | [`examples/production-json`](./examples/production-json) | Feature flags, app settings, explicit schemas, and registered operation refs |\n| Several advanced features together | [`examples/advanced`](./examples/advanced) | `.schema.mjs`, mixed mode, defaults, nested objects |\n| Hono auth and write hooks | [`examples/hono-auth`](./examples/hono-auth) | Optional Hono integration with auth lifecycle hooks |\n\nEach example README is the runnable authority for that example.\n\n## Docs Map\n\n| Task | Read |\n| --- | --- |\n| Start a project | [docs/getting-started.md](./docs/getting-started.md) |\n| Understand the model | [docs/concepts.md](./docs/concepts.md) |\n| Author fixtures and schemas | [docs/fixtures-and-schemas.md](./docs/fixtures-and-schemas.md) |\n| Manage generated output | [docs/generated-files.md](./docs/generated-files.md) |\n| Configure @async/db | [docs/configuration.md](./docs/configuration.md) |\n| Use JSON in production safely | [docs/json-production.md](./docs/json-production.md) |\n| Serve local data and use REST/GraphQL/viewer | [docs/server-and-viewer.md](./docs/server-and-viewer.md) |\n| Graduate REST prototypes to production API routes | [docs/prototype-to-production.md](./docs/prototype-to-production.md) |\n| Use the package API, CLI, or exports | [docs/package-api.md](./docs/package-api.md) |\n| Review public API surface changes | [API_SURFACE.md](./API_SURFACE.md) |\n| Integrate with Vite, Hono, or SQLite | [docs/integrations.md](./docs/integrations.md) |\n| Understand implementation boundaries | [docs/architecture.md](./docs/architecture.md) |\n| Work on the repo or publish releases | [CONTRIBUTING.md](./CONTRIBUTING.md) |\n\nFor the full product behavior and acceptance model, see [SPEC.md](./SPEC.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasync-framework%2Fasync-db","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasync-framework%2Fasync-db","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasync-framework%2Fasync-db/lists"}