Architectural Rules Enforced by Instatic's Architecture Tests: The Complete Guide

Instatic enforces 18 categories of structural and design-time invariants through automated architecture tests located in src/__tests__/architecture/*.test.ts, which break the build immediately upon any violation.

Instatic, developed by CoreBunch, encodes its architectural decisions as executable tests that run on every bun test invocation. These tests act as guardrails for module boundaries, database portability, security boundaries, and UI consistency. The following sections detail every rule encoded in the test suite, referencing the actual test files and enforced constraints found in the source code.

Module Import and Public API Boundaries

Instatic strictly controls how modules expose and consume internal APIs to maintain stable public surfaces.

Barrel-Import Discipline

The test src/__tests__/architecture/no-core-barrel-deep-imports.test.ts enforces that external code imports public APIs exclusively through a module’s barrel (@core/page-tree) and never via concrete internal paths such as @core/page-tree/node.ts. This prevents accidental reliance on private implementation details that may change.

// ❌ Wrong – deep import of an internal file
import { PageNode } from '@core/page-tree/node';

// ✅ Correct – use the barrel export
import { PageNode } from '@core/page-tree';

Plugin Import Boundaries

Plugin bundles are prohibited from importing Node/Bun core modules or performing unauthorized I/O. The plugin-sandbox-invariants.test.ts and plugin-host-import-boundaries.test.ts tests ensure that all permissions are centrally declared and that plugin hosts do not import the API dispatch layer, preventing circular dependencies.

Database Dialect and Storage Conventions

Instatic maintains portability between PostgreSQL and SQLite through strict SQL and schema rules.

ANSI-SQL Compliance and JSON Handling

The db-postgres-isms.test.ts test bans PostgreSQL-specific syntax (now(), ::int, etc.), enforcing ANSI-SQL only. Additionally, db-json-column-naming.test.ts requires JSON columns to end with _json, mapping to jsonb in Postgres and text in SQLite. All persisted JSON must pass through TypeBox helpers rather than raw JSON.parse, as enforced by json-extract-egress.test.ts and boundary-validation.test.ts.

// ❌ Illegal usage in a repository
await db.query('SELECT * FROM posts WHERE created_at > now()');

// ✅ ANSI-SQL compliant
await db.query('SELECT * FROM posts WHERE created_at > CURRENT_TIMESTAMP');

Migration Parity and Content Storage

The migration-parity.test.ts test ensures that migrations for PostgreSQL and SQLite share identical IDs and order. Content-storage conventions are enforced by data-tables-system-flag.test.ts, no-legacy-content-domain.test.ts, and no-legacy-pages-table.test.ts, which mandate that system tables (posts, pages, components) are seeded with system: true, legacy tables are eradicated, and all content lives in data_* tables.

Validation and Type Safety Boundaries

Instatic uses TypeBox to maintain type safety at runtime boundaries.

TypeBox-Only Validation

The boundary-validation.test.ts test enforces five critical rules:

  1. HTTP responses must be validated with apiRequest or readEnvelope.
  2. No raw JSON.parse(... ) as casts at persistence boundaries.
  3. Admin code may only use fetch for a small allow-list (NDJSON streams, SVG bytes, FormData uploads).
  4. Server handlers must use readValidatedBody.
  5. After readEnvelope or parseJsonResponse, never cast fields; instead reference the proper TypeBox schema.
// ❌ Bad – raw cast
const data = JSON.parse(body) as MyType;

// ✅ Good – use TypeBox helper
import { safeParseJson } from '@core/utils/json';
const data = safeParseJson(body, MyTypeSchema);

Error Handling Consistency

The no-inline-error-ternary.test.ts test requires that every catch (err) in admin code extract the message using getErrorMessage(err, fallback), prohibiting manual ternary checks for error messages.

Authentication and Capability Gating

Security boundaries are enforced through mandatory capability checks.

Handler Protection

The cms-handlers-capability-gated.test.ts and capability-picker-coverage.test.ts tests ensure that every CMS handler calls a capability check (requireCapability, requireAuthenticatedUser, etc.) and that capability metadata and client-side lists remain synchronized.

// ❌ No capability guard
export async function deletePost(req: Request) {
  // …
}

// ✅ Proper guard
export async function deletePost(req: Request) {
  requireCapability(req, 'cms.content.delete');
  // …
}

UI Architecture and Design System

Instatic enforces a strict design system through CSS and component usage rules.

CSS Token Policies

The css-token-policy.test.ts, no-css-var-fallbacks.test.ts, and noTailwindUtilities.test.ts tests enforce that CSS Modules use only token variables (var(--token)) with no raw hex/rgb/hsl values, no fallback values in var(--x, fallback), and absolutely no Tailwind utility classes or dependencies.

// ❌ Prohibited
<div className="flex items-center gap-2">...</div>

// ✅ Preferred – CSS Module with token vars
import styles from './MyComponent.module.css';
<div className={styles.container}>...</div>

UI Primitive Requirements

The button-primitive-usage.test.ts, ui-primitives-location.test.ts, and related icon tests mandate that all interactive controls use primitives under src/ui/components/. Bare <button> elements require explicit allow-list justification. Native browser dialogs (alert, confirm, prompt) are banned in favor of built-in Dialog and Toast components. Icons must be deep-imported from the vendored pixel-art-icons package, never from other libraries.

Admin Routing and Navigation Discipline

Internal navigation consistency is enforced by admin-router-usage.test.ts, which requires all internal navigation in the admin UI to use the custom router (@admin/lib/routing). Direct <a href="/admin…"> links and react-router-dom usage are prohibited.

Editor and Canvas Integrity

The visual editing surface maintains strict structural invariants.

Canvas and Component Rules

Tests including canvasFastRefreshBoundaries.test.ts, no-circular-dependencies.test.ts, and component-system-placement.test.ts enforce that:

  • Component and non-component exports are never mixed in a .tsx file.
  • The codebase remains free of circular imports.
  • Canvas selectors subscribe to the correct slice of state.
  • Component insertion always flows through insertComponentRef, banning direct tree mutations.

Page-Tree Mutation Contracts

The no-vc-mode-branches-in-mutations.test.ts and visual-components-mutation-contract.test.ts tests ensure that store actions (insertNode, deleteNode) never branch on kind === 'visualComponent', and that Visual-Component tree mutations preserve slot-instance / slot-outlet invariants. All mutations funnel through a single entry point to maintain consistent undo/redo history, as verified by centralized-site-mutation-history.test.ts.

Spotlight and Keybindings

The spotlight-no-direct-store-mutation.test.ts and keybindings-registry-single-source.test.ts tests prohibit Spotlight providers from mutating the editor store directly and mandate that all shortcuts flow through a central registry.

AI Infrastructure and Security

AI capabilities are isolated and strictly controlled.

AI Driver Isolation

The ai-driver-isolation.test.ts test bans provider SDKs (@anthropic-ai/..., @openai/...) except within the MCP server. All AI-tool schemas are defined once with TypeBox and re-exported, enforced by ai-tools-typebox-only.test.ts and ai-tool-schema-ssot.test.ts.

Capability and Credential Protection

Every AI handler must check capabilities before performing work (ai-handlers-capability-gated.test.ts), and credentials must never leak in responses (ai-credentials-never-leak.test.ts).

Media and Publishing Pipelines

Content delivery pipelines maintain specific processing orders and isolation guarantees.

Media Serving Constraints

The media-migration-invariants.test.ts, media-presentation-pipeline.test.ts, and media-storage-no-bytes-in-sandbox.test.ts tests validate that media migrations preserve all variants, <picture> and srcset generation follows the pipeline, signed URLs are used for downloads, and sandboxed plugins cannot read raw media bytes.

Publisher Integrity

The dispatcher-html-pipeline.test.ts and publish-html-filter-context.test.ts tests enforce that the HTML pipeline runs in the correct order (sanitize → filters → injections) and that HTML filter plugins receive proper context. Additionally, static-artefact-served-before-render.test.ts and publish-bumps-cache-version.test.ts ensure static artefacts are served before full renders when possible and that every publish operation bumps the cache version. The hole-runtime-asset-route.test.ts verifies the hole runtime route is registered before public routes.

Site Import and Agent Contracts

Headless operations and AI agents follow strict interface contracts.

Site Import Isolation

The siteImport-headless.test.ts test ensures the headless site-import package has zero dependencies on admin UI, server code, or React, guaranteeing it runs in pure Node environments.

Agent Surface Contracts

The agent-no-raw-html-in-reply-rule.test.ts, agent-system-prompt-no-module-enumeration.test.ts, and agent-tool-surface.test.ts tests enforce that agent replies remain plain text (no raw HTML/CSS/JSON), system prompts do not enumerate internal modules, and the set of write-tools matches the documented surface exactly.

Summary

Instatic’s architecture tests form a comprehensive guardrail layer that preserves the codebase’s structural integrity:

  • Module boundaries are protected through barrel-import discipline and plugin sandboxing.
  • Database portability is enforced via ANSI-SQL compliance and JSON column conventions.
  • Type safety is maintained through mandatory TypeBox validation at all boundaries.
  • Security depends on capability-gated handlers and isolated AI/media pipelines.
  • UI consistency relies on token-based CSS and primitive component usage.
  • Editor integrity is preserved through strict canvas and mutation contracts.

Any deviation triggers a failing test during bun test, forcing immediate correction at the source.

Frequently Asked Questions

What happens when an architecture test fails in Instatic?

When an architecture test fails, the bun test command exits with a non-zero status, breaking the build pipeline. Developers must correct the violation—such as replacing a deep import with a barrel import or adding a missing capability check—before the code can be merged, ensuring architectural drift is caught at development time rather than in production.

Why does Instatic ban Tailwind CSS and enforce CSS Modules?

Instatic bans Tailwind utilities (noTailwindUtilities.test.ts) and enforces CSS Modules with design tokens (css-token-policy.test.ts) to maintain a strict, consistent visual design system that is resilient to refactoring. This prevents utility-class proliferation and ensures all styling values derive from a centralized token source, making theme changes and accessibility updates predictable across the entire application.

How do the database architecture tests ensure portability between PostgreSQL and SQLite?

The db-postgres-isms.test.ts test blocks PostgreSQL-specific syntax like now() or ::int, forcing ANSI-SQL standards, while migration-parity.test.ts ensures both dialects share identical migration IDs and ordering. Additionally, db-json-column-naming.test.ts standardizes JSON handling by requiring _json suffixes, automatically mapping to jsonb in PostgreSQL and text in SQLite, ensuring schema definitions remain portable across both engines.

What is the purpose of the barrel-import rule in Instatic's architecture?

The barrel-import rule, enforced by no-core-barrel-deep-imports.test.ts, prevents consumers from importing internal implementation files directly. By forcing all external access through public barrel exports (@core/page-tree), Instatic maintains a stable public API surface, allowing internal refactoring without breaking downstream consumers and preventing accidental coupling to private implementation details.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →