Browse pages
Technology Stacks
A stack binds the specification to one technology: a backend stack lives under backend/, a frontend stack under frontend/. Selecting one applies exactly the provisions, version pins, and checks that technology needs. This page states what selecting a stack applies, where its versions come from, and how a replacement names every baseline provision it replaces.
Stack: any
Layer: workspace
Concepts#
What a Stack Folder Holds#
Each stack lives in one folder with a stack.md page: docs/backend/dotnet/, docs/frontend/web/react/, docs/frontend/web/svelte/, docs/frontend/blazor/, and docs/frontend/mobile/android/ are the current stacks. The stack.md states what the stack adds: its provisions, its version pins, and its checks.
Selecting a stack applies its folder and every folder above it, so a stack never restates an inherited principle. A stack folder is one with a stack.md page: frontend/patterns/ has none, so it applies with frontend/, while frontend/web/ applies only through its stacks. Supported scope states how size, shape, and stacks combine into one selection.
Versions and Replacements#
Every SDK, framework, and package version resolves from litespec.manifest.json, which owns the pins. A version copied from prose, an example, a package search, or agent memory drifts from that pin.
When an extension or a departure replaces baseline behavior, it names every baseline provision ID it replaces. The departure is recorded as an exception whose covers names the provision it replaces; there is no separate type or folder. rules <path> shows the departure in place of the provision. Unrelated stack provisions stay active, so a replacement stays inside the boundary it named. Each extension states how it composes with the Behavior fields its boundary touches, such as the audit field, the tenant scope, or the job record.
Selection Diagnostics#
These checks report a manifest selection no page can apply, so they are listed here instead of beside a provision.
| Family | Meaning | Codes |
|---|---|---|
STACK_* | A stack folder is outside the backend or frontend docs, is missing, holds no stack.md, or requires or pairs with a stack the manifest does not ship. | STACK_FOLDER, STACK_REFERENCE |
SHAPE_PAGE | A shape backend page is not a page directly in docs/backend/. | SHAPE_PAGE |
LAYER_* | A page sits in no known docs area, or no stack selection applies it. | LAYER_UNLISTED, LAYER_UNREACHABLE |
EXTENSION_* | An extension sits outside its declared path, is missing from the manifest, or lacks its activation scope, kinds, criterion, baseline, or dependencies, or it replaces an unknown provision or restates one it replaces. | EXTENSION_LOCATION, EXTENSION_UNLISTED, EXTENSION_SCOPE, EXTENSION_KIND, EXTENSION_ACTIVATION, EXTENSION_BASELINE, EXTENSION_DEPENDENCIES, EXTENSION_REPLACES_UNKNOWN, EXTENSION_REPLACES_ENFORCED |
Standards#
Apply the Complete Stack#
ruleruleguidancelitespec/core/stacks#apply-the-complete-stackA consumer selecting a stack MUST apply the pages in its folder, every folder above it, and their subfolders that hold no stack.
Why
The stack is the unit of conformance: a consumer cannot claim a stack while silently omitting an applicable page. Applying the folder, every folder above it, and their stackless subfolders keeps inherited principles in force without restating them. A deeper page replaces only the provisions it names, so everything it leaves unnamed keeps applying.
Checka reviewer answers
Reviewed forThe consumer file set covers every page in its stack folders, the folders above them, and their stackless subfolders.
Marked guidance: a reviewer answers this question.
Use Manifest Version Pins#
ruleruleguidancelitespec/core/stacks#use-manifest-version-pinsA consumer MUST resolve every SDK, framework, and package version from litespec.manifest.json.
Why
The manifest owns every pin, so resolving versions anywhere else produces builds the standard never described. A version copied from prose, an example, a package search, or agent memory drifts from the pin with the next edit. One resolution source keeps every consumer on the same tested combination.
Checka reviewer answers
Reviewed forEach resolved SDK, framework, and package version matches its pin in litespec.manifest.json.
Marked guidance: a reviewer answers this question.
Declare Replacements#
ruleruleguidancelitespec/core/stacks#declare-replacementsAn extension or a departure MUST name every baseline provision ID it replaces.
Why
Naming every replaced provision ID draws the exact boundary of the change: everything unnamed stays active. A departure is recorded as an exception whose covers names the provision, and rules <path> shows the departure in place of the provision. Without the list, a replacement silently widens its scope with each reading, and reviewers cannot tell which baseline provisions still bind the project.
Checka reviewer answers
Reviewed forEach extension or departure names every baseline provision ID it replaces, with the rest staying active.
Marked guidance: a reviewer answers this question.
Conventions#
Keep the Stack Visible#
conventiondefaultguidancelitespec/core/stacks#keep-the-stack-visibleName each selected stack in .litespec/project.json and the solution, applications, and commands in the root AGENTS.md.
ReplacementA consumer can replace this default with an explicit local convention.
Why
Naming each selected stack in .litespec/project.json with the solution, applications, and commands in the root AGENTS.md lets an agent resolve the project placeholders directly. Inferring the selection from the directory tree fails whenever folders outnumber stacks or names overlap. Visible selection also tells a human reader what the project runs before opening any code.
Checka reviewer answers
Reviewed for.litespec/project.json names each selected stack, and the root AGENTS.md names the solution, applications, and commands.
Marked guidance: a reviewer answers this question.