Types catch wrong code. Nara catches wrong access.
Let AI write your features. Nara proves who can reach every route and hear every event, before it ships.
- Every route declares its access. The server refuses to start while an
/apiroute declares none, and the authorization matrix tests every route against anonymous callers, members, permission holders, and administrators. - Every live event declares its audience. The realtime matrix proves each topic reaches the people it names and nobody else.
- Every feature keeps to its boundary. Features meet only through their
public
index.ts;nara doctorrefuses anything else, and host contracts are verified by conformance suites.
TypeScript, Hono, Vue, and SQLite, without a custom runtime in between. Build by feature, own the source, and keep evolving official features in place.
The repository root is the canonical Nara application baseline. Start a new product from a source checkout/copy of this reference app, then remove its Git history if you want an independent repository. Nara intentionally does not generate a second, smaller starter shape.
npm run check
npm run nara -- doctor
npm run nara -- context auth --json
npm run nara -- inspect users --jsonnpm run nara -- runs the CLI from this checkout, and keeps working after you
rename the package in package.json. Do not use npx nara
before @nara-web/cli is published: it resolves an unrelated npm package.
Nara's architecture analysis is deterministic and does not require an AI
provider.
git clone https://github.com/MasRama/nara.git
cd nara
npm install
cp .env.example .env
npm run setup
npm run devnpm run setup applies pending migrations, reference seeds, and bootstraps the
first administrator if needed. Without admin environment overrides it creates
a temporary development credential:
admin@nara.local / admin12345
The application requires that temporary password to be changed before normal
authenticated use. Set NARA_ADMIN_NAME, NARA_ADMIN_EMAIL, and
NARA_ADMIN_PASSWORD before setup to provide your own initial credential.
The repository root proves Auth/RBAC (including per-device sessions and TOTP
two-factor sign-in at /security), Users, Activity, assets, storage, the
SQLite lifecycle, and live updates that sign a tab out, apply permission changes,
and refresh Activity, sessions, roles, and users without a reload, plus safe
concurrent editing: an open form shows who else is editing, takes other people's
saves into the fields you have not touched, and asks only about fields you both changed. Additional official capabilities are installed explicitly
with nara add.
Development uses one Vite HTTP server on PORT (default 5555). Vite serves
the Vue app and HMR while Hono handles /api, /health, and /ready on the
same origin.
A Feature owns one business capability:
src/features/billing/
├── contract.ts # shared boundary types and schemas
├── index.ts # public server/general boundary
├── server/ # runtime and persistence
├── web/ # optional browser surface
└── tests/ # feature tests
Cross-feature imports use the target Feature's public boundary:
import { getCurrentUser } from '@/features/auth';Deep cross-feature imports such as @/features/users/server/repository are
invalid and detected by nara doctor.
See ARCHITECTURE.md and
docs/feature-model.md for the full ownership and
composition rules.
Common commands:
nara make feature <name> Create the canonical Feature skeleton
nara add <feature> Install an official open-code Feature
nara evolve <feature> Evolve installed official source
nara doctor Validate current architecture
nara inspect <feature> Show bounded Feature facts
nara context <feature> Produce a focused architecture context pack
nara impact <feature> Show structural dependents
nara diff --base main Describe architecture change
nara guard --base origin/main Fail on newly introduced architecture debt
All architecture commands support deterministic JSON where documented.
Full command and output semantics live in docs/cli.md.
src/
├── app/ application composition
├── cli/ CLI and architecture engine
├── features/
│ ├── activity/ official (has .nara/)
│ ├── auth/ official (has .nara/)
│ ├── health/ official (has .nara/)
│ └── users/ official (has .nara/)
└── shared/ business-neutral infrastructure
resources/ Vue/Vite application shell
scripts/ setup, database, build, release helpers
tests/ cross-cutting and integration tests
web/ is optional inside a Feature. The supported browser stack is Vue 3 +
Vite + TypeScript; Hono is the HTTP layer; SQLite uses better-sqlite3 and raw
SQL.
Use the narrowest relevant test while iterating, then run the canonical gate before handoff:
npm run lint
npm run check:frontend
npm run test:fast
npm run test:integration
npm run test:heavy
npm run architecture:doctor
npm run check
npm run buildnpm run check is the canonical repository gate. Release/distribution work
uses:
npm run validate:release
npm run perf:sanity # separate machine-sensitive sanity checkSee CONTRIBUTING.md for contribution workflow and
validation expectations.
Development starts from .env.example. The main lifecycle commands are:
npm run setup
npm run migrate
npm run seed
npm run db:check
npm run db:backupProduction requires an explicit public APP_URL and a local SQLite path:
cp .env.production.example .env.production
npm run build
npm startProduction serves the built Vue SPA and Hono APIs from the same Node process. SQLite files, WAL files, and backups must live on storage local to the application host; the default architecture is not intended for shared multi-host network filesystems.
Live updates stream from GET /api/events in the same process. The response
sends X-Accel-Buffering: no for nginx; other reverse proxies must not buffer
text/event-stream responses, and their read timeout must exceed the 25-second
heartbeat.
Each Feature declares the upkeep of its own tables, and the runtime runs it
after migrations and then on each task's interval: Auth deletes expired
sessions hourly, Activity prunes events older than ACTIVITY_RETENTION_DAYS
(default 365) in bounded batches, Users removes the avatars of deleted
accounts, and the app optimizes SQLite planner statistics. Set the retention to 0 only when indefinite Activity retention
is intentional.
Database ownership, migrations, seeds, backup, and integrity behavior are
documented in docs/database-lifecycle.md.
Nara ships a provider-neutral AssetStorage capability as part of the
guaranteed substrate. The reference app binds Users to the local filesystem
adapter under storage/, so cloning the repository still works with no cloud
account or extra service.
Features store a logical storage_key in their own metadata and depend only on
the AssetStorage contract. The application binding chooses the provider. A
deployment can therefore replace the local adapter with S3/R2-compatible
storage without changing Users-owned upload, cleanup, or delivery workflows.
Browser Feature code may not import shared/storage; storage providers remain
server-only infrastructure.
The current installable catalog is intentionally small:
auth
health
users
activity
There is one copy of each: the Feature in src/features/<name>, marked
official by its .nara/ folder and shipped from there by
npm run stage:package. Tests that need this reference app rather than the
Feature alone live in its tests/app/ and are not shipped.
Activity records what other Features report. nara add activity mounts its
page, API, permission and retention; the application then creates a reporter
with createActivityRecorder(...) from src/app/bindings/activity.server.ts
and hands it to the Features it wants recorded, as the reference app does for
Auth and Users in src/app/server.ts. Each of those Features declares the
actions it reports, with the label the feed shows, and can report only those.
Installation copies visible source into the application and composes explicit application-owned bindings where needed. There is no runtime plugin registry or DI container. Users is the substantial assembly proof and can bind to the reference Auth capability or another compatible provider.
Package shape and prerequisites are documented in
docs/feature-format.md.
The npm package is @nara-web/cli and exposes the nara executable. The first
registry publication is still pending. The staged publishable package lives at
packages/nara; npm run stage:package and npm pack produce the artifact
used by release validation.
ARCHITECTURE.md— current architecture authoritydocs/feature-model.md— Feature ownership and boundariesdocs/feature-format.md— installable Feature formatdocs/auth.md— registration, roles, your own sign-in pages, limitsdocs/cli.md— CLI referencedocs/database-lifecycle.md— SQLite lifecycleSECURITY.md— security model and reportingCODE_OF_CONDUCT.md— community participation