Nara is an architecture-aware TypeScript application kit built around composable, evolvable open code.
Build by feature, not by layer. Own the source. Compose explicitly. Understand architecture. Evolve without losing customization. Protect change.
Compose → Own → Understand → Evolve → Protect
Nara keeps each business capability together and makes public boundaries, statically provable public API consumers, and canonical application integrations machine-checkable. The underlying stack stays transparent: Hono handles HTTP, TypeScript defines the application, and Nara's CLI explains the repository without an LLM.
@nara-web/cli is not yet published to the npm registry. The registry command
below is the canonical user flow once the first publish is complete; until
then, work from a source checkout or the locally staged/packed package.
npx @nara-web/cli new my-app
cd my-app
npm install
npm run devThis is the canonical lifecycle: nara new creates a minimal runnable
application that carries its own pinned Nara tooling as a devDependency,
so architecture checks travel with the project. Its default Health Feature is
copied from the same official open-code source used by nara add, with
lineage already established before the generated project is visible:
npm run check # typechecks, tests, and nara doctor
npx nara doctor # validate architecture from the local install
npx nara context health --json
npx nara impact health --json
npx nara add audit # install an official open-code featureNara stays useful after creation: the same local CLI that scaffolds the
project keeps understanding (inspect, context, impact), including which
Features consume exact public or browser-safe symbols and whether each usage is
explicitly type-only or uses value-capable syntax. Nara does not resolve
declaration categories through the TypeScript type checker. It describes change
(diff --base main), and protects (doctor for current architecture,
guard --base origin/main for architecture change) its feature architecture in
month 12. No AI provider is required.
To work on Nara itself instead, clone the reference repository:
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 creates the
first administrator when one does not already exist. With no admin environment
overrides it prints the development bootstrap credential
admin@nara.local / admin12345; that credential is marked temporary and the
application requires a password change before any normal authenticated API or
workspace route can be used. Set NARA_ADMIN_NAME, NARA_ADMIN_EMAIL, and
NARA_ADMIN_PASSWORD before setup to provide your own initial credential.
The repository root is the development/reference application proving richer
Nara capabilities (auth, RBAC, users, assets, SQLite lifecycle). It is not
the starting point for new products — nara new is. Additional capabilities
reach generated projects as explicit open-code features via nara add, not
by cloning the reference app.
Packaging note: Nara's publishable npm package is named @nara-web/cli. It exposes the nara executable, so generated projects use commands such as nara doctor, nara diff, and nara guard. The package lives at packages/nara (bin points at the staged CLI and files ships only the staged dist/, official-features/ source, substrate/, LICENSE, and README.md). The source release is tagged v3.2.0, but the package has not yet been published to the npm registry; source/Git release status and npm distribution status are separate. The remaining registry step is a one-time npm run build && npm run stage:package && npm publish from packages/nara on a clean tree. Until then, staging plus npm pack from packages/nara produces the artifact intended for the registry.
Development uses one Vite HTTP server on PORT (default 5555). Vite serves the Vue app and HMR, while the Hono application is mounted into that same server for /api, /health, and /ready. There is no second development listener or proxy hop.
A feature owns a business capability, its public contract, runtime code, optional web code, and tests:
src/features/billing/
├── contract.ts # types and runtime-safe boundary data
├── index.ts # the only public import boundary
├── server/ # routes, services, repositories
├── web/ # optional client-side surface
└── tests/ # feature tests
Cross-feature code imports the target feature's public index.ts:
import { getUser } from '@/features/users';This is invalid:
import { findUserById } from '@/features/users/server/repository';The second import couples one feature to another feature's implementation. nara doctor detects this, along with malformed features, dependency cycles, and server-only code leaking into web/.
Inside a generated project the CLI is a pinned local devDependency — every command below runs from the project's own install, reproducibly:
npm run architecture:doctor # local nara doctor
npx nara make feature billing
npx nara doctorWhen working directly from a Nara checkout, use the equivalent command:
node build/src/cli/index.js make feature billing
node build/src/cli/index.js doctorAvailable commands:
nara new <name> Create a runnable v3 application
nara make feature <name> Create the canonical feature skeleton
nara add <feature> Install an official open-code feature
nara evolve <feature> Safely evolve an installed official Feature
nara doctor Validate architecture
nara inspect <feature> Show bounded feature facts
nara context <feature>|--file <path> Architecture Context Pack before editing a feature
nara impact <feature> Show feature-graph dependents
nara diff --base main Show how the architecture is changing
nara guard --base origin/main Fail when the change introduces new violations
Nara can describe not only what the architecture is, but how the architecture is changing. git diff explains text changes; nara diff explains deterministic Feature-architecture changes, including public/web consumer evidence, removed-public-symbol consumer impact, canonical application imports, Hono mounts, and Vue Router records, with affected output labeled structural dependency impact (never semantic behavior prediction) and no AI provider required. nara guard turns that intelligence into a regression ratchet: it fails only when the change introduces new doctor diagnostics compared with the Git baseline, so existing debt is tolerated while new debt cannot enter unnoticed. See docs/v3/cli.md.
Architecture facts are deterministic and available as JSON for scripts and agents:
npx nara inspect health --json
npx nara context health --json
npx nara impact health --json
npx nara diff --base main --json
npx nara guard --base origin/main --jsonNo AI provider is required for these commands. nara new pins the creating
CLI version exactly as @nara-web/cli in the generated project, so
architecture-rule changes arrive only through an explicit dependency update
(see ADR 0011).
Request
│
▼
Hono application (src/app/server.ts)
│
├── Feature routes
│ ├── auth
│ └── users
│
├── Health and readiness
└── Shared infrastructure
├── configuration
├── SQLite database
├── structured logging
└── error handling
The reference application (repository root) exposes:
| Surface | Purpose |
|---|---|
/health |
Liveness response |
/ready |
Database readiness response |
/api/auth |
Registration, login, sessions, and password changes |
/api/roles |
Role and permission administration |
/api/users |
Profile and user administration |
/api/assets |
Avatar upload and delivery |
Hono is the HTTP layer. Nara records static Feature composition from src/app/server.ts and Vue route composition from src/app/router.ts; it does not replace either with a custom runtime or a native HTTP dependency.
src/
├── app/ HTTP composition and error handling
├── cli/ TypeScript CLI and architecture engine
├── features/
│ ├── auth/ Sessions, passwords, roles, permissions
│ └── users/ Profiles, administration, and avatars
└── shared/ Configuration, database, errors, logging
official-features/
├── audit/ Installable audit feature
├── health/ Installable health feature
└── users/ Installable users assembly (requires a compatible provider)
resources/ Vue 3/Vite/TypeScript frontend shell
tests/
├── v3/ Runtime and CLI tests
└── fixtures/architecture Valid and invalid architecture projects
web/ is optional inside a feature. A backend-only feature is valid. The supported browser stack is Vue 3 + Vite + TypeScript; feature-specific Vue pages, components, and composables live in the owning Feature's web/, while application-wide composition lives under src/app/. The architecture CLI treats only the canonical server.ts and router.ts roots as application integration evidence.
Make a focused change, then run the checks that defend it:
npm run lint # TypeScript typecheck
npm run check:frontend # Vue-aware frontend typecheck
npm test # Vitest suite
npm run architecture:doctor # Human-readable architecture report
npm run check # All repository checks above
npm run build # Production client and server buildThe architecture tests include valid projects and intentionally invalid fixtures for:
- invalid feature shape
- cross-feature internal imports
- circular feature dependencies
- server/client leaks
Diagnostics report the problem, source file, relationship, reason, and recommended fix. Human output and --json output use the same analysis.
Development configuration starts from .env.example:
NODE_ENV=development
PORT=5555
DB_FILE=database/dev.sqlite3
PORT is the single development HTTP port. APP_URL defaults to http://localhost:${PORT} in development and can be overridden explicitly when needed. Production still requires an explicit public APP_URL.
Nara's database is a local SQLite file managed by better-sqlite3. Apply its Feature-owned migrations before using database-backed routes:
npm run setup # migrate + reference seeds + first-admin bootstrap
npm run migrate
npm run seed
npm run db:checkReference seeds contain structural data such as roles and permissions; they do
not recreate administrator accounts. npm run setup is idempotent for the
first-admin step and never resets an existing administrator password.
For the production Node process, copy .env.production.example to .env.production, set APP_URL to the public application origin, choose a production database path, and build:
cp .env.production.example .env.production
npm run build
npm startProduction serves the built Vue SPA, public files, and backend APIs from the same Node/Hono origin. npm start requires build/client/index.html; run npm run build first. The startup log identifies the browser/API URL from APP_URL.
Linux runtime: the Hono + @hono/node-server HTTP path uses no Ultimate/uWebSockets native HTTP runtime. (Other native dependencies such as better-sqlite3 or Sharp are legitimate and unrelated to this contract; the portable HTTP-stack audit in release validation guards against reintroducing the old runtime.) Canonical validation is one gate:
npm run validate:release # check, production serving + startup
# failures, HTTP-stack audit, fresh project, official feature
npm run perf:sanity # separate machine-sensitive sanity (catastrophic tripwires only)Production configuration fails during startup with the invalid field named in the error. SQLite files, WAL files, and backups must live on storage local to the application host; Nara's default SQLite architecture is not intended for multi-host shared network filesystems. Applications with high write concurrency or multi-host database requirements should use a client/server database architecture instead. Put TLS termination and public traffic handling in a reverse proxy such as nginx or Caddy.
Development HTML is served by Vite and is not covered by Hono security headers; production is authoritative for page headers.
Official features are composable open TypeScript source. Installation is
transactional and explicit: Feature-owned source lands in
src/features/<name>, application-owned bindings land in
src/app/bindings/ with composition calls in the canonical roots, npm
prerequisites compose into package.json for the application to install,
and lineage records the exact official source under .nara/lineage.
Existing source is never merged into or silently overwritten:
npx nara add health
npx nara add audit
npx nara add users # requires a compatible provider (e.g. Auth)The installation result is inspectable source, not a hidden runtime plugin. Run npx nara doctor after adding a feature.
The catalog is intentionally small (health, audit, users). Users is
the substantial proof of typed host requirements: it declares the account
surface it needs, and the application binding satisfies it with Auth or
another compatible provider — no DI container, no direct Users → Auth
implementation dependency. Auth itself stays a reference implementation in
this repository, not an installable package.
Official Features remain ordinary project source after nara new or
nara add, but they also carry a small local lineage record. The Health
Feature created by nara new starts from the same official open-code source
that later nara evolve health treats as INCOMING.
.nara/
└── lineage/
└── official-features/<feature>/
├── base/ # exact official source bytes
└── lineage.json # schema, source kind, SHA-256 base digest
The lineage directory is not an architecture manifest. Architecture facts
remain derived from src/ by the existing inspect, context, diff, snapshot,
and doctor primitives. .nara/lineage is only the deterministic historical
BASE used by nara evolve.
npx nara evolve audit --dry-run
npx nara evolve audit --dry-run --json
npx nara evolve auditEvolution compares three states:
| State | Meaning |
|---|---|
BASE |
exact official source recorded by the last add or successful evolve |
LOCAL |
the installed, possibly customized src/features/<feature> |
INCOMING |
the current official source bundled with the installed Nara CLI |
Unchanged files, upstream-only updates, local-only changes, additions, and
deletions are resolved deterministically. Text files use git merge-file;
binary files merge only when one side is unchanged or both sides reached the
same bytes. Conflicts are reported as a stable path list, never written as
conflict markers, and never partially applied.
Before a conflict-free apply, Nara materializes an isolated candidate
Feature, reruns the existing architecture snapshot and diff model, computes
structural downstream impact, and blocks only newly introduced architecture
diagnostics. Existing diagnostics are baseline debt and remain tolerated.
Successful application replaces the Feature and advances BASE to pure
INCOMING bytes while preserving local-only code. Application-owned
bindings, package.json composition, and the provider choice are never
modified by evolution. A missing lineage is
bootstrapped only when local source is byte-identical to the current official
source; divergent legacy source fails closed. Application-owned Features
without an official package are not evolved.
docs/v3/release-notes-3.2.0.md— v3.2 Composable & Evolvable Open Codedocs/v3/release-notes.md— v3 release notes and verificationdocs/v3/release-checklist.md— pre-RC gates and validation semanticsdocs/v3/feature-model.md— feature ownership and boundariesdocs/v3/cli.md— CLI command reference and JSON outputdocs/v3/feature-format.md— installable feature formatdocs/v3/v2-inventory.md— capability migration inventorydocs/v3/migration-v2-v3.md— v2 to v3 porting guidedocs/v3/architecture-philosophy.md— Compose, Understand, Protectdocs/v3/database-lifecycle.md— canonical SQLite migrations, seeds, backup, and integrity lifecycleSECURITY.md— security reporting