Build-Time Composition for Any Text File
current specification npm · @vkdatta/stitch build-time only any language static output host-native routing

Build one by one.
Stitch to bundle.

Stitch replaces <stitch> imports and $stitch-drop calls with real content at build time — in HTML, JavaScript, CSS, C, Python, or any text file. The browser receives ordinary, finished files with no component-loader JavaScript.

download 01 / Install

Install Stitch

npm i @vkdatta/stitch -g

Stitch is a build tool for your website — and for any project made of text files. Install it globally, then run it inside the project you build and deploy.

stitch build     # compose src/ into dist/
stitch dev       # build, serve, and rebuild on every change
stitch reverse   # rebuild src/ from a built dist/
stitch help

folder_open 02 / Structure

Keep your source organized

project/
├── src/
│   ├── index.html
│   ├── repo.html
│   ├── components/
│   │   ├── header.html
│   │   └── footer.html
│   ├── data/
│   │   └── version.txt
│   ├── style.css
│   └── script.js
└── package.json

Stitch reads src/ and writes the deployable site to dist/. Static assets are copied into dist/stitch_assets/. Every text file — HTML, JavaScript, CSS, plain text, source code in any language — is processed for Stitch directives; binary files are copied as they are.

extension 03 / Components

Consume a component

<stitch src="components/header.html"></stitch>

<main>
  <h1>Hello</h1>
</main>

<stitch src="components/footer.html"></stitch>

Paths are resolved relative to the file containing the tag. This lets nested files reference components relative to their own location. The referenced file may itself contain additional <stitch src> calls — composition is recursive.

Extension handling

When the referenced path has no extension, Stitch tries .html first, then a file with exactly that name (such as Makefile). A path with an extension is used as written — and it may be any text file, not only HTML. See Any Language.

<stitch src="/tags/opening"></stitch>
resolves as: src/tags/opening.html

<stitch src="data/version.txt"></stitch>
resolves as: src/data/version.txt

data_object 04 / Data

Reuse one component with different values

A reusable component declares placeholders:

<stitch reusable></stitch>

<article class="card">
  <span>{{icon}}</span>
  <h2>{{title}}</h2>
</article>

A caller supplies values through data-* attributes:

<stitch src="components/card.html"
     data-title="API"
     data-icon="bolt"></stitch>

Stitch produces:

<article class="card">
  <span>bolt</span>
  <h2>API</h2>
</article>

Substitution happens at build time. The same component can be consumed repeatedly with different values. Substitution may occur in text or attributes, in any file type, and values can be passed by id too: $stitch-drop('card', data-title="API"). The <stitch reusable> declaration itself never appears in generated output.

warning Interactive Warning

If a caller supplies data-* values but the target does not declare <stitch reusable>, Stitch pauses the build and asks whether the target should be marked reusable. The user may approve the conversion or abort.

build 05 / Build

Build your site

npx stitch build

The generated dist/ directory is the deployable output. Deploy dist/, not src/. Manual changes to generated files are not durable — always modify src/, then rebuild.

npx stitch build --src src --out dist     # explicit folders
npx stitch build --no-reverse              # clean production output (no markers, no manifest)
npx stitch build --asset-dir .             # non-HTML files at the output root
npx stitch dev                             # build + serve + rebuild on change

By default a build also records what stitch reverse needs and verifies it. Use --no-reverse for the files you actually ship.

Before → after

Source

<header>
  ...
</header>

<stitch src="components/footer.html"></stitch>

Generated output

<header>
  ...
</header>

<footer>
  ...
</footer>

The browser does not need to understand <stitch>. It receives finished HTML directly with no component-fetching requests and no runtime component parser.

bolt 06 / Dev Server

stitch dev — build, serve, rebuild

npx stitch dev
npx stitch dev --port 8080
npx stitch dev --src website --out public --port 4000 --host 0.0.0.0

Builds your project once, serves the output directory, watches src/ recursively, and rebuilds on every change. Pages that are open in the browser reload by themselves.

What it does

Errors do not stop the server

A build error — a duplicate id, a missing file, a cycle — is printed in the terminal and the server keeps serving the last good output. Fix the file and save; the next rebuild clears the error.

🔴 STITCH DEV BUILD ERROR
Duplicate stitch id found. Every <stitch id="..."> must be unique:

  id "version" is declared 2 times:
    - src/a/version.txt:1
    - src/b/version.txt:1
warning Development output is not production output

stitch dev builds with reverse markers and a manifest (see stitch reverse). Ship the output of stitch build --no-reverse.

terminal 07 / Any Language

Not just HTML — stitch any text file

Stitch directives are plain text, so they work in any text file: .js, .mjs, .css, .c, .h, .py, .txt, .json, .md, and files with no extension at all. Split a file into as many pieces as you like and drag them back together with a tag.

src/main.js

window.DELLUNA_SITE = {
    version:  "<stitch src='version.txt'></stitch>",
    registry: "<stitch src='registry.txt'></stitch>",
    base:     "<stitch src='base.txt'></stitch>"
};

plus version.txt, registry.txt and base.txt, each holding one value.

dist/stitch_assets/main.js

window.DELLUNA_SITE = {
    version:  "v0.0.111",
    registry: "https://cdn.jsdelivr.net/gh/vkdatta/delluna@v0.0.111/registry",
    base:     "https://cdn.jsdelivr.net/gh/vkdatta/delluna@v0.0.111"
};

The tag is replaced exactly where it stands — inside a string, a comment, or on a line of its own.

How it behaves in non-HTML files

Building a project that is not a website

By default non-HTML output goes under stitch_assets/. For a C, Python or any other project, emit it at the output root instead:

src/
├── main.c          ← <stitch src="body.c"></stitch>
├── body.c
└── config.h

npx stitch build --src src --out build --asset-dir .

build/
├── main.c          ← composed
└── config.h

body.c was consumed, so it is not emitted. Run your compiler on build/.

tag 08 / id & stitch-drop

Name a file once, drop it anywhere

Give any source file — reusable or not, HTML or not — an id at its head. Then drop it by that name from any other file, without caring where it lives.

src/version.txt

<stitch id="version"></stitch>
v0.0.111

src/main.js

window.DELLUNA_SITE = {
    version:  "$stitch-drop('version')",
    registry: "$stitch-drop('registry')",
    base:     "$stitch-drop('base')"
};

dist/stitch_assets/main.js

window.DELLUNA_SITE = {
    version:  "v0.0.111",
    registry: "https://cdn.jsdelivr.net/gh/vkdatta/delluna@v0.0.111/registry",
    base:     "https://cdn.jsdelivr.net/gh/vkdatta/delluna@v0.0.111"
};

registry.txt and base.txt are headed with <stitch id="registry"> and <stitch id="base"> the same way.

The two forms are equivalent

By pathBy id
<stitch src="version.txt"></stitch> $stitch-drop('version')
<stitch src="card.html" data-title="API"></stitch> $stitch-drop('card', data-title="API")

Pick by path when the file location is the point; pick by id when callers should survive a file being moved or renamed.

Rules

content_copy Ids must be unique

Every id must be unique across the entire source tree, HTML and text files together. A duplicate fails the build and lists every declaration with its file and line:

Duplicate stitch id found. Every <stitch id="..."> must be unique:

  id "version" is declared 2 times:
    - src/a/version.txt:1
    - src/b/version.txt:2

Dropping an id nobody declared is also a hard error, with a "did you mean" suggestion and the list of declared ids.

toggle_off 09 / off

off — leave a directive as plain text

Add off to a directive and Stitch ignores it completely: it is not resolved, not stitched, not stripped, and not rewritten — even if the file it names really exists.

<stitch src="location" off></stitch>
<stitch id="version" off></stitch>
$stitch-drop('version', off)

What happens to it

When to use it

gavel The one exception to the absolute rule

No <stitch> directive may remain in generated output — except a directive you explicitly marked off. In HTML, an off tag stays as an unknown element the browser ignores. To print a directive on an HTML page without any leftover, escape it as you always have: &lt;stitch ...&gt; and &#36;stitch-drop(...).

undo 10 / Reverse

stitch reverse — turn dist back into src

npx stitch build                    # src -> dist (+ dist/.stitch/manifest.json)
npx stitch reverse --src restored   # dist -> restored/   (byte-identical to src)
npx stitch reverse --check          # compare dist's source against ./src, write nothing

Every stitch build records how each output was produced, so the built output can be turned back into the exact source files. This works for HTML and for every other text file Stitch composed.

What a build records

Options

FlagMeaning
--out <dir>The built directory to read. Default dist.
--src <dir>Where to restore the source. Default src.
--checkCompare the restored source with --src; write nothing; exit 1 on any difference.
--overwriteAllow writing into a non-empty --src. Without it Stitch refuses.
--manifest <file>Manifest location, if it was kept outside dist/.
build --no-reverseProduce clean output: no markers, no manifest. Use it for production.

Guarantees

recycling 11 / Component Lifecycle

Only consumed components disappear

A file becomes a consumed component when another file references it through <stitch src="..."> or $stitch-drop('id'). Its contents are embedded into the consumer, so that source file is omitted from dist/. This holds for any text file: a version.txt dropped into main.js is not emitted on its own.

Unused HTML files and ordinary assets remain. CSS, JavaScript, images, fonts, manifests, JSON, PDFs, and other files are copied — non-HTML static source files go into dist/stitch_assets/.

lightbulb 12 / Why Stitch

Runtime imports are convenient. Build-time imports are faster.

target Core Intent

Stitch is a build-time composition processor. It allows a developer to split a large project — HTML first, but equally JavaScript, CSS, or source code in any language — into modular files, recursively compose those files during the build, and deploy ordinary static output.

The problem with runtime composition

A runtime component processor improves source modularity but shifts composition work onto every visitor:

What Stitch gives you

Build time may increase slightly because Stitch performs assembly before deployment. That cost happens once per build instead of being paid by every visitor.

merge Fundamental Pipeline
SOURCE → ZAP BUILD → DIST → STATIC HOST / CDN → BROWSER

There is no Stitch component loader running in the deployed website.

compare 13 / Comparison

How Stitch compares to other approaches

Rough conceptual ranges assuming the network response has already arrived. Network latency can dominate all of these numbers.

Method Assembly happens Initial network requests Time to usable page* Browser CPU HTML transfer size Best for
Stitch (build-time) Once during build 1 page + assets ~10–100 ms browser-side assembly Very low Higher Static sites / docs
Plain static HTML Developer manually 1 page + assets ~10–100 ms Very low Higher Small / simple sites
JS fetch components Every visitor Many / additional ~100–1000+ ms Medium–high Lower initial HTML Rarely ideal for static sites
JS <template> cloning Every visitor 1 HTML + JS ~20–300 ms Medium Lower HTML Large dynamic repeated UI
Web Components Every visitor HTML + JS ~30–500 ms Medium Lower HTML Reusable interactive UI
Server-side includes (SSI) Every request 1 page + assets ~5–100 ms server assembly Very low Normal Traditional server sites
SSR / server rendering Every request or cache miss 1 page + assets ~20–500+ ms server work Low Normal Dynamic / user-specific pages
Edge rendering At CDN edge / cache miss 1 page + assets ~10–200 ms Low Normal Personalized / global apps
Static site generator Once during build 1 page + assets ~10–100 ms Very low Higher Static sites / docs
Hybrid: static + JS enhancement Static at build, dynamic parts runtime 1 page + JS ~10–150 ms Low Balanced Modern content-heavy sites

* Time to usable page is a rough conceptual range assuming the network response has arrived.

account_tree 14 / Architecture

Current Architecture

Stitch is intentionally a build-time system. Its responsibility ends when the final deployable files have been generated.

src/
│
├── modular HTML files
├── text files in any language (JS, CSS, C, Python, TXT ...)
├── nested directories
├── reusable components, ids
├── routed pages
├── images / fonts / other binary assets
│
▼
ZAP BUILD
│
├── scan every text file for directives
├── validate routes and ids (ids must be unique)
├── build dependency graph (src= and $stitch-drop)
├── detect cycles
├── recursively compose HTML and text files
├── perform data-* substitution
├── strip Stitch directives (except those marked off)
├── emit public HTML pages
├── emit composed text files; consumed fragments are not emitted
├── centralize static assets  →  dist/stitch_assets/
├── rewrite local asset URLs
├── record markers + manifest for stitch reverse
└── generate host routing rules  →  dist/_redirects
│
▼
dist/
│
├── index.html
├── routed HTML files
├── stitch_assets/
├── .stitch/manifest.json  (unless --no-reverse)
├── _redirects  (when routes exist)
└── host configuration files at root
│
▼
STATIC HOST / CDN  →  REAL BROWSER NAVIGATION
info Important

Stitch does not replace browser navigation. Clicking a normal internal link performs normal navigation. The host serves the destination page. The browser loads and renders that page as an ordinary HTML document.

What Stitch does not need

code 15 / Tag Reference

Stitch Tag Reference

<stitch src> — File Composition

Instructs Stitch to resolve another local text file — HTML or any other language — and insert its processed contents at the exact position of the tag.

<stitch src="./header"></stitch>
<stitch src="./header.html" />
<stitch src="components/header"></stitch>
<stitch src="data/version.txt"></stitch>     (inside a .js, .css, .c, .py ... file)

<stitch id> — Name a File

Heads any source file with a unique name so other files can drop it without knowing its path. Removed from the output. See id & stitch-drop.

<stitch id="version"></stitch>

$stitch-drop — Include by id

Replaced by the contents of the file declared with that id. Accepts data-* values for reusable files.

$stitch-drop('version')
$stitch-drop("card", data-title="API")

off — Disable a Directive

Any directive carrying off is left in the output exactly as written. See off.

<stitch src="location" off></stitch>
$stitch-drop('version', off)

<stitch reusable> — Reusable Template Declaration

Marks a component as reusable with build-time {{slot}} substitution. The declaration never appears in generated HTML.

<stitch reusable></stitch>

<article>
  <h2>{{title}}</h2>
  <p>{{description}}</p>
</article>

<stitch route> — Public URL Declaration

Declares the public URL for a page. The route does not determine the source file's physical location — a file may exist anywhere inside src/.

<stitch route="/privacy"></stitch>

This declares the public URL https://example.com/privacy.

File name–based routing

Normal HTML files derive routes from their filenames without needing an explicit <stitch route>:

src/index.html       → /
src/terms.html       → /terms
src/docs/index.html  → /docs
gavel Absolute Rule

No <stitch ...> tag or $stitch-drop call may remain in generated output. All Stitch directives are processed and stripped before output — except those you explicitly marked off.

Quick command reference

# Install
npm i @vkdatta/stitch -g

# Embed a component (relative or absolute path)
<stitch src="relative or absolute path to file"></stitch>

# File name–based routing
<stitch route="allow"></stitch>

# Explicit route (e.g. inside legal.html)
<stitch route="others/legal"></stitch>

# Name a file, then drop it from anywhere
<stitch id="version"></stitch>
$stitch-drop('version')

# Leave a directive as plain text
<stitch src="location" off></stitch>

# Build, develop, reverse
npx stitch build
npx stitch dev
npx stitch reverse

route 16 / Path Resolution

Component Path Resolution

Stitch resolves component paths relative to the file containing the <stitch src> call, unless the path explicitly indicates the source root. This applies to every file type — a .js, .css or .c file resolves its includes the same way an HTML file does.

Style Example Resolution
Relative ./header Relative to the current HTML file.
Parent relative ../shared/header Relative to the parent directory of the current file.
Source-root tags/header Resolved from the source root. If nothing exists there, the file next to the one containing the tag is tried, so sibling files can simply be named.
Explicit source-root src/tags/header The src/ prefix is removed; resolution starts at the source root.
Leading slash shorthand /tags/header Source-root shorthand — resolved inside src/, not the OS filesystem root.

Extensions

WrittenStitch looks for
headerheader.html, then a file named exactly header
MakefileMakefile.html, then Makefile
version.txtexactly version.txt — any text extension works

A directive can point only at a text file. Pointing at an image or any other binary file is a hard error. $stitch-drop('id') needs no path at all: it finds the file by its id.

shield Path Traversal Protection

A resolved component path must remain inside the source directory. Any reference that escapes the source root is a hard build error.

repeat 17 / Reusable Components

Reusable Components & Data Substitution

Rules

edit_note Source Modification Exception

Source files are normally read-only from Stitch's perspective. The explicit user-approved reusable conversion (triggered by the interactive warning) is the only exception.

fork_right 18 / Routing

Static Host Routing

Routing is a deployment concern, not a browser-side Stitch runtime concern.

How explicit routes work

src/fx/fx_counter.html
  contains: <stitch route="/fx_counter"></stitch>

Stitch emits:
  dist/fx/fx_counter.html

And generates the host rule:
  /fx_counter  /fx/fx_counter.html  200

Result:
  example.com/fx_counter  →  host routing  →  dist/fx/fx_counter.html  →  browser
compare_arrows Route and Filesystem Are Separate

The route controls the public URL. The source file's relative location controls where the generated HTML is written inside dist/.

_redirects generation

When one or more explicit routes exist, Stitch generates dist/_redirects. Each route uses an HTTP 200 rewrite so the visible URL remains the route while the host serves the generated HTML file.

Route validation rules

link_off Warning — Reference Dropped

A routed HTML file cannot be consumed inline through <stitch src>. Stitch emits a warning, removes that reference from the caller, and continues building. The correct way to reach a routed page is ordinary navigation: <a href="/privacy">Privacy</a>.

storage 19 / Static Assets

Centralized Asset Output

Non-HTML static source files are copied into a single owned output directory:

src/style.css        →  dist/stitch_assets/style.css
src/script.js        →  dist/stitch_assets/script.js
src/images/logo.svg  →  dist/stitch_assets/images/logo.svg

Text files that use directives are written composed, at the same relative path. Text files consumed by another file are fragments and are not written at all. With --asset-dir . everything lands at the output root instead of stitch_assets/ (for non-web projects).

Asset URL rewriting

Because assets are centralized during the build, Stitch resolves each local asset reference and rewrites the generated URL to the final public asset path.

<link rel="stylesheet" href="../style.css">
  →  <link rel="stylesheet" href="/stitch_assets/style.css">

<img src="../../images/logo.svg">
  →  <img src="/stitch_assets/images/logo.svg">

URL suffix preservation

Query strings and fragments are preserved during rewriting: ../style.css?v=3 → /stitch_assets/style.css?v=3

External URLs not rewritten

URLs beginning with https://, http://, //, data:, javascript:, mailto:, tel:, or a bare #fragment are never modified.

Resource-bearing attributes rewritten

link[href]  script[src]  img[src]  source[src]  video[src]
video[poster]  audio[src]  iframe[src]  embed[src]  object[data]
track[src]  input[src]  srcset
settings wrangler.toml

wrangler.toml is deployment configuration, not a browser asset. It must not be copied into stitch_assets/ — it is preserved at the root of dist/.

output 20 / Output Rules

What Goes Into dist/

Full example

src/
├── index.html
├── style.css
├── script.js
├── wrangler.toml
├── tags/
│   ├── opening.html
│   └── closing.html
├── pages/
│   ├── privacy.html      ← <stitch route="/privacy">
│   └── support.html
└── fx/
    ├── fx_counter.html   ← <stitch route="/fx_counter">
    └── fx_clamp.html     ← <stitch route="/fx_clamp">

↓ npx stitch build ↓

dist/
├── index.html
├── _redirects
├── wrangler.toml
├── stitch_assets/
│   ├── style.css
│   └── script.js
├── pages/
│   ├── privacy.html
│   └── support.html
└── fx/
    ├── fx_counter.html
    └── fx_clamp.html

error 21 / Validation

Errors & Warnings

Situation Severity Behaviour
<stitch src> target does not exist Hard Error Stop the build; clearly show the caller and resolved missing path.
Target is a binary file Hard Error Stop — only text files can be stitched; binary files are rejected.
Duplicate <stitch id> Hard Error Stop and list every duplicated id with each file and line.
$stitch-drop of an undeclared id Hard Error Stop; show the caller, a "did you mean" hint and the declared ids.
Invalid id, more than one id per file, src combined with id, malformed $stitch-drop(...) Hard Error Stop and show the file and line.
Circular component dependency Hard Error Stop and show the complete dependency chain.
Path escapes source root Hard Error Stop with a path traversal error.
Duplicate explicit route Hard Error Stop and show both source files.
Route does not begin with / Hard Error Stop and show the invalid route and source file.
<stitch src> points to a routed HTML file Warning Warn, drop the inline reference, continue building.
route / loader in a non-HTML file Warning Warn, ignore the tag, continue building.
data-* supplied to non-reusable target Interactive Warning Offer reusable conversion or abort the build.

Cycle detection

a.html → b.html → c.html → a.html  ← HARD ERROR

Stitch stops and reports the full cycle. Recursive composition has a maximum supported nesting depth of 32. Exceeding the limit fails clearly rather than risking uncontrolled recursion.

inventory_2 22 / Package Structure

Recommended Package Shape

stitch/
├── package.json
├── bin/
│   └── stitch.js
└── lib/
     ├── index.js
     ├── directives.js
     ├── utils.js
     ├── graph.js
     ├── build.js
     ├── dev.js
     ├── manifest.js
     ├── patch.js
     └── reverse.js

Responsibilities

File Responsibility
directives.js Finds <stitch> tags and $stitch-drop calls in any text file, honours off, strips consumed directives.
utils.js Path resolution, text/binary detection, fragment handling, local asset URL rewriting, and shared helpers.
graph.js Text-file discovery, dependency graph construction, route and id validation (unique ids), reusable metadata, and cycle detection.
build.js Composition orchestration, public HTML emission, composed text files, asset copying, and route rule generation.
dev.js The stitch dev server: watch, rebuild, live reload.
manifest.js, patch.js, reverse.js Build markers, the reverse manifest, lossless patches, and stitch reverse.
index.js Package exports and public API.
bin/stitch.js CLI entry point for commands such as npx stitch build, stitch dev and stitch reverse.
info Build-time only

The manifest.js here is the build-time reverse manifest. The removed browser-side route / resource runtime (runtime.js) is still gone: nothing Stitch-specific ships to visitors.

timeline 23 / Workflow

Developer Workflow

1. Develop in src/

src/
├── modular HTML
├── nested components
├── reusable templates
├── routed pages
├── CSS / JavaScript / images
└── deployment configuration

2. Develop live, then build

npx stitch dev                      # serve + rebuild on every change
npx stitch build --no-reverse       # clean production output

3. Deploy dist/

npx wrangler pages deploy dist

Recover the source from a build

npx stitch reverse --src restored

4. Browser

https://example.com/
https://example.com/privacy
https://example.com/fx_counter

These are normal browser navigations to ordinary static HTML output.

flag Primary Objective

Developers receive modular source files. Visitors receive already-assembled HTML.

science 24 / Testing

Minimum Regression Tests

Any modification to the build system should test at least:

  1. simple component composition;
  2. nested component composition;
  3. deep recursive component composition;
  4. the same component consumed from multiple callers;
  5. the same reusable component consumed with different data values;
  6. relative component paths;
  7. source-root component paths;
  8. leading-slash source-root shorthand;
  9. missing component errors;
  10. circular component errors;
  11. path traversal protection;
  12. duplicate route errors;
  13. invalid route errors;
  14. attempted consumption of routed pages;
  15. asset copying into stitch_assets/;
  16. asset URL rewriting from deeply nested HTML files;
  17. query string and fragment preservation during asset rewriting;
  18. external URL preservation;
  19. wrangler.toml preservation outside stitch_assets/;
  20. _redirects generation when routes exist;
  21. no <stitch> directives remaining in emitted output;
  22. <stitch src> in non-HTML files (JS, CSS, C, Python, TXT), with fragments not emitted;
  23. <stitch id> with $stitch-drop, all quoting styles and data-* values;
  24. duplicate ids failing with every file and line listed;
  25. unknown ids, malformed drops and drop cycles;
  26. off leaving directives untouched even when the target exists;
  27. text and HTML files including each other without markers leaking;
  28. stitch reverse restoring every file byte-for-byte, including edits made to built files;
  29. --asset-dir . for non-web output.

block 25 / Hard Rules

What Stitch Never Does

block Absolute Prohibitions
  • leave any <stitch> directive or $stitch-drop call in generated output, unless it is marked off;
  • reintroduce a browser-side Stitch component loader;
  • reintroduce runtime route processing;
  • reintroduce a route manifest for browser navigation;
  • fetch component HTML in the deployed browser;
  • intercept ordinary navigation merely to implement Stitch routing;
  • replace the browser's document body as a routing mechanism;
  • hide routed page content while waiting for a removed runtime;
  • generate lazy / JIT route loading infrastructure;
  • move deployment configuration such as wrangler.toml into browser assets;
  • copy HTML components into stitch_assets/;
  • change external URLs during local asset rewriting;
  • allow component paths to escape the source root;
  • silently ignore circular dependencies;
  • silently resolve duplicate routes or duplicate ids;
  • remap physical output locations based solely on route values;
  • modify source files without explicit behaviour that authorizes it;
  • treat dist/ as a second hand-maintained source project;
  • add architecture unrelated to build-time composition without an explicit requirement.
diamond Final Design Principle

Stitch should remain small, deterministic, dependency-light, and focused.

MODULAR SOURCE
+
BUILD-TIME COMPOSITION
+
STATIC OUTPUT
+
HOST-NATIVE ROUTING
=
ZAP