Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .changeset/dark-mode-toggle-mobile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
"@stackwright/core": patch
---

fix(top-app-bar): always show color mode toggle on mobile

The `colorModeToggle` was previously hidden on narrow screens when nav
menu items were present. It is now always visible — rendering to the
left of the hamburger icon on mobile (`[🌙] [☰]`) and to the right of
nav links on desktop. Replaces one compound conditional with three
intent-revealing render sites.
5 changes: 5 additions & 0 deletions .changeset/fix-back-merge-loop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stackwright/cli": patch
---

Upgrade the back-merge rebase conflict handler from a one-shot block to a loop. Dev can accumulate multiple alpha-bump commits that all modified `.changeset/pre.json` — the previous one-shot `||{ }` only resolved the first conflict. The loop now runs until all pre.json conflicts are resolved or an unexpected conflict is encountered.
5 changes: 5 additions & 0 deletions .changeset/fix-back-merge-pre-json-conflict.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stackwright/cli": patch
---

Fix back-merge into dev failing with a modify/delete conflict on `.changeset/pre.json` during rebase. The release workflow deletes this file via `changeset pre exit`, but dev's alpha-bump commits still reference it. The rebase now explicitly resolves the conflict by accepting main's deletion and continuing.
5 changes: 5 additions & 0 deletions .changeset/fix-js-yaml-override-conflict.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@stackwright/cli": patch
---

Fix js-yaml version override conflict in pnpm overrides that caused `yaml.safeLoad is removed` errors when running `changeset pre exit` in CI. The global `js-yaml: >=4.1.1` override was stomping the scoped `read-yaml-file>js-yaml: ^3` override, forcing js-yaml v4 into read-yaml-file which doesn't support it.
30 changes: 30 additions & 0 deletions .changeset/pre.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{
"mode": "pre",
"tag": "alpha",
"initialVersions": {
"stackwright-docs": "0.1.6",
"@stackwright/build-scripts": "0.7.2",
"@stackwright/cli": "0.8.5",
"@stackwright/collections": "0.1.1",
"@stackwright/core": "0.8.4",
"@stackwright/e2e": "0.3.0",
"@stackwright/hooks-registry": "0.1.1",
"@stackwright/icons": "0.5.2",
"launch-stackwright": "0.2.5",
"@stackwright/maplibre": "2.0.4",
"@stackwright/mcp": "0.4.5",
"@stackwright/nextjs": "0.5.3",
"@stackwright/otters": "0.2.1",
"@stackwright/sbom-generator": "0.2.1",
"@stackwright/scaffold-core": "0.3.1",
"@stackwright/themes": "0.5.3",
"@stackwright/types": "1.5.0",
"@stackwright/ui-shadcn": "0.1.3"
},
"changesets": [
"dark-mode-toggle-mobile",
"fix-back-merge-loop",
"fix-back-merge-pre-json-conflict",
"fix-js-yaml-override-conflict"
]
}
51 changes: 49 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ Stackwright is a typed DSL that compiles YAML content files into production-read

Because the YAML schema defines a bounded set of expressible behaviors, every application built on Stackwright is **verifiably safe by construction**. You don't audit individual apps — you audit the platform. Then every app built on it inherits those guarantees.

AI coding tools amplify whatever architectural decisions are already in place — good ones and bad ones equally. They're reliable at fixing syntax errors and equally reliable at propagating bad structural choices across an entire codebase at scale. Without a constrained framework, the quality floor on AI-generated code is effectively set by the least-experienced person on the team, and that floor gets re-negotiated from scratch on every project. Stackwright embeds expert judgment into the schema itself. The quality floor is set once, at the framework level, and every project built on it inherits it.

## Why Stackwright?

- **Safe by construction**: The constrained YAML grammar can only express pre-approved behaviors. AI-generated content passes through Zod schema validation at build time and runtime — invalid states are rejected before they reach the browser
Expand All @@ -17,6 +19,9 @@ Because the YAML schema defines a bounded set of expressible behaviors, every ap
- **Own everything**: The output is a standard Next.js app in a git repo you control. Git is the CMS — version history, branching, PR review, and rollback come free
- **No lock-in**: Any React developer can open the project and extend it immediately. The escape hatch is a feature, not a compromise
- **Graduate naturally**: Begin with YAML-driven pages, add custom React components alongside them as you grow — no migration, no rewrite

## Quick Start

```bash
git clone https://github.com/Per-Aspera-LLC/stackwright.git
cd stackwright
Expand All @@ -27,6 +32,16 @@ pnpm dev:hellostackwright

> **Tip:** Stackwright uses Turborepo for incremental builds. Use `pnpm turbo:build` for faster builds with caching.

## Who Is This For?

**Teams building with AI agents**: You want AI-generated content to be reviewable, validated, and safe — not arbitrary code that could do anything. The MCP server gives agents a typed interface; Zod validation rejects anything that doesn't conform at build time. The worst an AI agent can produce is a build failure, not a security incident.

**Regulated-environment teams** (government, defense, healthcare, finance): You need auditability built in from the start, not layered on afterward. The Zod schemas define what is expressible — audit them once, and every application built on the platform inherits those guarantees. SBOMs are generated automatically on every build.

**Non-technical stakeholders**: You can contribute content, launch pages, and iterate on designs by describing what you want to an AI agent — no developer required for content changes, no CMS login, no deployment pipeline to understand.

**Engineering teams without a dedicated architect on every project**: Structural judgment is embedded in the schema. The framework rejects invalid states before they reach the browser. You don't need a senior architect reviewing every AI-generated output if the schema already encodes what valid output looks like.

## How It Works

Pages are YAML files in `pages/`. Each page is a directory containing `content.yml`:
Expand Down Expand Up @@ -286,6 +301,8 @@ import { SearchModal } from '@stackwright/core';

## Safe by Construction

> The schema is the security policy. Every application built on Stackwright inherits the same guarantees — you audit the schema once, not each app individually.

Stackwright's security model is called **Safe by Construction**.

The mechanism is **The Bounded Contract**: a strict Zod schema defines exactly what is expressible. Every generated application **inherits** those guarantees — we call this **Verified Inheritance**. The schema is the parent class; every app is a derived type with the same safety properties.
Expand Down Expand Up @@ -344,14 +361,44 @@ For `@stackwright-pro/openapi`:
| Malformed API data | Zod validates responses at runtime |
| Schema drift | Generated TypeScript types stay in sync with Zod schemas |

### SBOM Generation

Stackwright automatically generates a Software Bill of Materials (SBOM) during every build in three formats:

- **SPDX 2.3** — the NIST-recommended format for federal procurement
- **CycloneDX 1.5** — widely supported in enterprise toolchains
- **Stackwright Build Manifest** — a framework-level summary including schema versions, content type registry, and build metadata

Output goes to `.stackwright/sbom/`. CLI commands:

```bash
pnpm stackwright -- sbom generate # Regenerate SBOM
pnpm stackwright -- sbom validate # Validate SBOM schemas
pnpm stackwright -- sbom diff # Compare two builds
```

This supports CISA Secure by Design requirements and government/enterprise provenance tracking. Because the schema constrains what components can appear in a Stackwright application, the SBOM surface is well-bounded by construction.

### Regulated Environments

Because Stackwright constrains what is expressible at the schema level, a compliance reviewer can audit the Zod schemas once — not each application individually. Every app built on the platform is structurally identical in its safety properties. We call this **Verified Inheritance**: the schema is the parent type; every application is a derived type that inherits the same guarantees.

This is architecturally different from scanning code after the fact. Post-hoc scanning tells you what a specific build contained at a point in time. Stackwright's model is a structural guarantee: invalid states are rejected before they reach the runtime, on every build, for every application on the platform.

Practical implications for regulated environments:

- A compliance reviewer audits the Zod schemas once — not App A, App B, and App C separately
- New applications start compliant by construction, not by review
- SBOM generation (see [SBOM Generation](#sbom-generation) above) provides dependency provenance on every build without manual intervention

The constrained schema model is the core architectural decision — it wasn't added for compliance. Compliance is a consequence of a design that was always primarily about correctness.

### What This Doesn't Cover

Stackwright constrains the YAML layer and generated clients. Custom React components (written outside the YAML layer) are standard Next.js — they're your code, and security responsibility is yours. The framework makes it easy to stay inside the safe path; it doesn't prevent you from stepping outside it.

**Bottom line**: You audit the Zod schemas once. Every app built on the platform inherits those guarantees. This is "verifiable safe" — not "we scanned it and it looks okay."

> **Why this matters for government and enterprise**: You audit the schema once. Every application built on Stackwright inherits those guarantees. This isn't "we scanned it afterward" — it's mathematical proof that invalid inputs cannot reach the runtime.

### Plugin Security

For information about securing plugins and extensions, see [docs/PLUGIN_SECURITY.md](./docs/PLUGIN_SECURITY.md).
Expand Down
8 changes: 8 additions & 0 deletions examples/stackwright-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# stackwright-docs

## 0.1.7-alpha.0

### Patch Changes

- Updated dependencies [5279236]
- @stackwright/core@0.8.5-alpha.0
- @stackwright/nextjs@0.5.4-alpha.0

## 0.1.6

### Patch Changes
Expand Down
10 changes: 5 additions & 5 deletions examples/stackwright-docs/build-manifest.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"format": "stackwright-build-manifest",
"version": "1.0.0",
"generated": "2026-05-15T14:03:57.119Z",
"generated": "2026-05-18T16:22:20.092Z",
"project": {
"name": "stackwright-docs",
"version": "0.1.6-alpha.3",
"version": "0.1.6",
"root": "/home/charles/git/peraspera/stackwright/examples/stackwright-docs",
"isMonorepo": false
},
Expand Down Expand Up @@ -137,11 +137,11 @@
},
{
"name": "tailwind-merge",
"version": "3.5.0",
"version": "3.6.0",
"type": "direct",
"category": "external",
"purl": "pkg:npm/tailwind-merge@3.5.0",
"integrity": "039d2e92d475e4268b1babe22545c8cc507d46e9fc09aacaa75ee5925b885a10",
"purl": "pkg:npm/tailwind-merge@3.6.0",
"integrity": "084c7514e672a9283e7a4bf1c162bf248d481e0aac75ffe397d8763082a57852",
"depth": 0
}
],
Expand Down
14 changes: 7 additions & 7 deletions examples/stackwright-docs/cyclonedx.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"specVersion": "1.5",
"version": 1,
"metadata": {
"timestamp": "2026-05-15T14:03:57.118Z",
"timestamp": "2026-05-18T16:22:20.092Z",
"tools": [
{
"vendor": "Stackwright",
Expand All @@ -14,8 +14,8 @@
"component": {
"type": "application",
"name": "stackwright-docs",
"version": "0.1.6-alpha.3",
"purl": "pkg:npm/stackwright-docs@0.1.6-alpha.3"
"version": "0.1.6",
"purl": "pkg:npm/stackwright-docs@0.1.6"
}
},
"components": [
Expand Down Expand Up @@ -288,13 +288,13 @@
{
"type": "library",
"name": "tailwind-merge",
"version": "3.5.0",
"purl": "pkg:npm/tailwind-merge@3.5.0",
"version": "3.6.0",
"purl": "pkg:npm/tailwind-merge@3.6.0",
"scope": "required",
"hashes": [
{
"alg": "SHA-256",
"content": "039d2e92d475e4268b1babe22545c8cc507d46e9fc09aacaa75ee5925b885a10"
"content": "084c7514e672a9283e7a4bf1c162bf248d481e0aac75ffe397d8763082a57852"
}
],
"externalReferences": [
Expand All @@ -307,7 +307,7 @@
],
"dependencies": [
{
"ref": "pkg:npm/stackwright-docs@0.1.6-alpha.3",
"ref": "pkg:npm/stackwright-docs@0.1.6",
"dependsOn": [
"@radix-ui/react-accordion",
"@radix-ui/react-slot",
Expand Down
2 changes: 1 addition & 1 deletion examples/stackwright-docs/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "stackwright-docs",
"version": "0.1.6",
"version": "0.1.7-alpha.0",
"private": true,
"scripts": {
"prebuild": "stackwright-prebuild",
Expand Down
41 changes: 13 additions & 28 deletions examples/stackwright-docs/pages/acknowledgements/content.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
content:
meta:
title: "Acknowledgements | Stackwright"
description: "Thank you to the humans and AI agents who built Stackwright."
title: "Acknowledgements | StackWright"
description: "Thank you to the humans and AI agents who built StackWright."

content_items:
# ─────────────────────────────────────────────────────────
Expand All @@ -13,7 +13,7 @@ content:
text: "Acknowledgements 🙏"
textSize: h1
textBlocks:
- text: "Stackwright is built by humans, powered by AI, and shaped by open source."
- text: "StackWright is built by humans, powered by AI, and shaped by open source."
textSize: h3
- text: "This page thanks the contributors — silicon and carbon alike — who made it possible."
textSize: body1
Expand All @@ -28,15 +28,15 @@ content:
text: "Code Puppy 🐶"
textSize: h2
textBlocks:
- text: "The AI coding agent that built Stackwright. Every package, every component, every test — code-puppy wrote the code that writes your code."
- text: "The AI coding agent that built StackWright. Every package, every component, every test — code-puppy wrote the code that writes your code."
textSize: body1
background: background

- type: alert
label: code-puppy-origin
variant: note
title: "A Sassy Little Puppy"
body: "Code Puppy was created by Marcus Paffenberger in response to AI coding tools removing access to models and raising prices. It's privacy-first, sarcastic, and thoroughly unimpressed with enterprise software. It coded Stackwright out of spite for expensive IDEs."
body: "Code Puppy was created by Michael Pfaffenberger (https://github.com/mpfaffenberger) in response to AI coding tools removing access to models and raising prices. It's privacy-first, sarcastic, and thoroughly unimpressed with expensive IDEs."
background: surface

- type: feature_list
Expand Down Expand Up @@ -106,7 +106,7 @@ content:
code: |
# Try Code Puppy yourself
uvx code-puppy

# Or install permanently
pip install code-puppy

Expand All @@ -130,26 +130,11 @@ content:
href: "https://code-puppy.dev"
background: background

# ─────────────────────────────────────────────────────────
# CLAUDE SECTION
# ─────────────────────────────────────────────────────────
- type: text_block
label: claude-heading
heading:
text: "Claude (Anthropic) 🤖"
textSize: h2
textBlocks:
- text: "Code Puppy is powered by Claude. The reasoning, generation, and architectural decisions that make Stackwright work — all catalyzed by Anthropic's model."
textSize: body1
- text: "We chose Claude for its ability to understand complex codebases, maintain context across long conversations, and produce production-ready code — not rough drafts."
textSize: body1
background: background

- type: alert
label: anthropic-note
variant: info
title: "Privacy Matters"
body: "Both Stackwright and Code Puppy are committed to privacy. Your prompts are never logged, your code is never shared, and you can run everything locally if you prefer."
body: "Both StackWright and Code Puppy are committed to privacy. Your prompts are never logged, your code is never shared, and you can run everything locally if you prefer."
background: surface

# ─────────────────────────────────────────────────────────
Expand Down Expand Up @@ -184,7 +169,7 @@ content:
],
"tools": [
"list_files",
"read_file",
"read_file",
"create_file",
"agent_share_your_reasoning"
]
Expand All @@ -206,7 +191,7 @@ content:
text: "Open Source Dependencies"
textSize: h2
textBlocks:
- text: "Stackwright stands on the shoulders of giants:"
- text: "StackWright stands on the shoulders of giants:"
textSize: body1
background: background

Expand Down Expand Up @@ -269,7 +254,7 @@ content:
label: gratitude
variant: success
title: "Thank You"
body: "To every maintainer, contributor, and user of these projects — thank you for making the open source ecosystem what it is. Stackwright is just one small flower in a vast garden."
body: "To every maintainer, contributor, and user of these projects — thank you for making the open source ecosystem what it is. StackWright is just one small flower in a vast garden."
background: surface

# ─────────────────────────────────────────────────────────
Expand All @@ -281,9 +266,9 @@ content:
text: "Per Aspera Sapientia"
textSize: h2
textBlocks:
- text: "\"Through hardships to wisdom.\" — The motto of Per Aspera LLC."
- text: "\"Through hardships to wisdom.\" — The motto of Per Aspera Sapientia LLC."
textSize: body1
- text: "Stackwright was built because the founder got tired of enterprise software that was expensive, opaque, and disrespectful of users. We built something that respects your time, your privacy, and your intelligence."
- text: "StackWright encodes software architecture and security experiences earned the hard way into a framework."
textSize: body1
- text: "The AI coding tools existed. We just made them work together. The hard part wasn't the code — it was the vision of what could be."
textSize: body1
Expand All @@ -298,7 +283,7 @@ content:
text: "Thank you for reading"
textSize: h3
textBlocks:
- text: "Built with ❤️ by Per Aspera LLC. Powered by code-puppy. Made possible by open source."
- text: "Built with ❤️ by Per Aspera Sapientia LLC. Powered by code-puppy. Made possible by open source."
textSize: body1
buttons:
- text: "Back to Home"
Expand Down
Loading
Loading