What gets built

The stack, the shape of the repository, and the parts the platform provides rather than the application.

Every application built here is the same shape. That is the constraint the platform is built on, and it is what makes one of these reviewable in an hour.

The stack#

FrameworkNuxt 4 — Vue 3, server routes on Nitro
StylingTailwind CSS v4, with the design system's tokens rendered into the stylesheet
DatabaseMongoDB or PostgreSQL, chosen at creation
Cache and sessionsRedis
File storageS3-compatible object storage, one bucket per environment
Package managerpnpm
RuntimeNode 24

No choices beyond the database. Not React, not a different CSS framework, not a different server.

The shape of the repository#

Ordinary Nuxt, with a few directories that are the platform's:

app/
  components/ui/    the shared design-system components
  pages/            the screens
  assets/css/       the design system's tokens, rendered
server/
  api/              server routes
  utils/
    platform.ts     email, SMS, Google — through the platform
    auth.ts         sign-in for the application's own users
    storage.ts      the application's own object storage
STACK.md            the rules the builder follows
.platform/          uploads and the design-system reference kit

What the application does not contain#

Deliberately absent, and this is the interesting part of the design:

  • No third-party credentials. Email, SMS and Google go through server/utils/platform.ts, which calls the platform with a capability token. The provider's key never reaches the container.
  • No password hashing and no session logic. server/utils/auth.ts asks the platform. requireUser(event) at the top of a protected route is the whole pattern.
  • No page-title or meta management for the values set in Appearance. A scaffolded Nitro plugin applies those from the environment, so a build cannot undo them.
  • No analytics code. A scaffolded middleware reports page views; the builder is told the file is not its to touch.

Where things run#

Each application has its own container, its own database container, its own Redis and its own storage bucket — per environment, not per application. Its container has no access to the host's container runtime and no platform credentials in it.

The storage credential it is given is scoped to one bucket by policy, so although one object store serves every application, none can read another's files.

Environment variables#

The platform sets the database address, the storage credentials and the capability token. Those names are reserved and cannot be overridden.

Everything else comes from Configuration and is read with useRuntimeConfig().

Files#

Three kinds, kept apart because they have different lifetimes:

  • Conversation attachments — under .platform/uploads/, for the builder.
  • Published files — served by the platform at /_files/<slug>, not in the repository and not part of a version.
  • What the application's users upload — the application's own bucket, through server/utils/storage.ts. Never in public/, never in the database as base64, never on the container filesystem — the first two end up in the build and the third is replaced on every deployment.