Technical Architecture

Stacks has two architectural views:

  1. the draft protocol’s portable roles and lifecycle;
  2. the Stacks.js packages and runtime mechanisms that implement them.

The distinction matters. @stacksjs/router is an implementation detail; “route matching occurs before validation and Action execution” is a protocol guarantee.

Protocol view

Transport


Request context → middleware → route → validation → authorization


                                                Action

                                     ┌─────────────┴─────────────┐
                                     ▼                           ▼
                                   Model                       Service
                                     │                           │
                                     └─────────────┬─────────────┘

                                              result / error

                                      serializer or rendered View


                                                Response

Protocol conformance concerns observable behavior: ordering, short-circuiting, stable errors, transactions, driver failure, and type/schema evidence.

Stacks.js repository view

At source revision bf1245e3:

stacks/
├── app/                                  # user-owned overrides and additions
├── routes/                               # route definitions
├── config/                               # typed capability settings
├── database/                             # migrations and local databases
├── resources/                            # STX views/components/functions
├── tests/                                # application tests
└── storage/framework/
    ├── core/                             # first-party framework packages
    │   ├── actions/
    │   ├── api/
    │   ├── auth/
    │   ├── database/
    │   ├── orm/
    │   ├── queue/
    │   ├── realtime/
    │   ├── router/
    │   ├── security/
    │   ├── validation/
    │   └── ...
    ├── defaults/app/                    # framework fallback application
    ├── types/                           # generated and ambient declarations
    ├── api/                             # API server/generated API artifacts
    ├── server/                          # server package
    └── cloud/                           # cloud integration

Resolution and overrides

Stacks.js resolves application code before bundled defaults:

app/Actions/Cms/PostIndexAction.ts
        │ exists? yes ──► use it
        │ no

storage/framework/defaults/app/Actions/Cms/PostIndexAction.ts

This pattern applies to logical paths supported by the relevant resolver. It permits local customization without forking framework storage.

Route files are different: routes/*.ts files are registered through app/Routes.ts. Creating a route file without registering it is not sufficient.

Request path

The router builds on Bun HTTP primitives and the underlying Bun router package. Stacks-specific layers add:

  • route-file loading and prefixes;
  • Action/controller resolution;
  • request augmentation and AsyncLocalStorage context;
  • middleware aliases and parameters;
  • CSRF handling;
  • request IDs and Server-Timing data;
  • response helpers;
  • development/production error behavior;
  • named URL generation.

The lifecycle can terminate before the Action when middleware, validation, authorization, or CSRF checks return an error response.

Action path

An Action declares metadata and handle(), and may declare:

  • validations;
  • authorize;
  • before and after hooks;
  • HTTP method/path metadata;
  • rate/retry/backoff metadata for relevant execution paths;
  • a Model association for request inference.

String-based route handlers are resolved lazily. This improves override flexibility but means some import errors surface only when a route is exercised. Route smoke tests are therefore important.

Model and migration path

defineModel() combines a literal definition with the query-builder runtime. A Model can declare:

  • attributes and validation rules;
  • relationships;
  • indexes;
  • factories;
  • timestamps, UUIDs, API generation, search, events, and domain traits;
  • accessors, mutators, and hooks.

Migration generation compares Model state with a dialect-specific snapshot and writes migration artifacts under database/migrations/. A safe workflow is:

edit Model → generate migrations → inspect diff/SQL → apply → run tests

Model-driven generation reduces duplicated schema declarations but does not eliminate migration review.

Type and schema path

Stacks.js uses multiple mechanisms:

BoundaryPrimary evidence
Model literal → runtime Modelgeneric/literal inference in defineModel()
Action validation → request bodyInferValidations plus runtime validation
Model/config/component inventoriesgenerated declarations and manifests
Routes → API descriptionexplicit OpenAPI generation
External inputruntime schema and parser checks
Database implementation edgestyped query builder plus selected dynamic casts

Generated declarations and OpenAPI output can become stale, so CI should regenerate or verify them.

Service packages

Selected capability boundaries:

CapabilityMain packagesSnapshot boundary
Routing/APIrouter, api, server, actionsImplemented; OpenAPI generation is explicit.
Datadatabase, orm, query-builderImplemented; test each selected dialect.
Authauth, securityBroad surface; shared-store assumptions matter.
Queuequeue, scheduler, cronSync/database/Redis execute; other configured names may not.
Real-timerealtimeServer must be initialized; scale-out is configuration-dependent.
Notificationsnotifications, email, sms, push, chatDatabase is concrete; provider delivery requires provider setup.
AIaiProvider-dependent; the built-in vector index is in-memory.
Observabilitylogging, healthRequest/trace IDs and health surfaces exist.
Cloudcloud, deploy, dnsAWS-oriented integration plus ts-cloud dependency.
DesktopdesktopCraft launch/build integration is experimental.

Runtime and process boundaries

The full framework targets Bun. Process-local mechanisms—including in-memory sessions, callbacks, registries, or caches—do not automatically coordinate across workers or hosts. When scaling horizontally, select shared stores and verify:

  • session and token behavior;
  • queue locks and retries;
  • real-time fan-out;
  • rate-limit state;
  • idempotency;
  • scheduler overlap prevention;
  • trace propagation.

Architecture guarantees versus aspirations

The source demonstrates broad capability coverage. It does not yet provide a language-neutral conformance suite, provider matrix, or certification report. Treat the repository as the reference design and the white paper requirements as the proposed path from design to verifiable protocol.

Continue