Skip to content
contractajsPublic

About

Contract-driven, renderer-agnostic web composition with scoped resolution and deterministic manifests.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

56 Commits

Folders and files

Repository files navigation

Contracta

Contracta is a contract-driven web composition framework. A theme declares contracts and the modules that fill them; Contracta resolves those modules into trees, compiles the theme into a deterministic manifest, and gives hosts shared semantics for routes, navigation, and transitions, without depending on any host itself.

Core owns semantics. Adapters own environment integration. Themes own domain contracts. Sites own customization.

Status: 0.2.0 is the current release. Transition planning ships as experimental; see the release condition.

How the pieces fit

flowchart LR
  subgraph authored["Authored by a theme and a site"]
    theme["Theme<br/>contracts, modules, renderers"]
    components["Site's own<br/>Svelte components"]
  end
  subgraph here["This repository"]
    compiler["@contracta/compiler<br/>validate + compileTheme"]
    manifest[("Manifest<br/>deterministic JSON")]
    build["@contracta/svelte-build<br/>buildTheme"]
    core["@contracta/core<br/>resolution, routes,<br/>navigation, transitions"]
  end
  subgraph site["In the browser"]
    built["Built theme<br/>one Svelte component"]
    mounts["Mount points<br/>on the page"]
    runtime["@contracta/svelte<br/>runtime adapter"]
  end
  theme --> compiler --> manifest --> build
  components -- "bound by<br/>specifier" --> build
  build --> built --> mounts
  core -.-> compiler
  core -.-> build
  core -.-> runtime
  runtime -- "URL picks each<br/>mount point's module" --> mounts
Loading

A theme is authored with the Compiler's helpers and compiled into a manifest. The Svelte build resolves every module of the manifest with Core and generates one Svelte component, the built theme, which imports the site's own components through bindings from renderer identities to module specifiers. A site mounts the built theme at each mount point it lays out, and the runtime adapter, in its own repository, keeps each mount point's module in step with the URL.

Packages

Package Role Documentation
@contracta/core Contracts, modules, scopes, and resolution; route state, navigation intent, module identity, and transition planning (experimental) Core model, resolution, route state, navigation intent, transition plan
@contracta/compiler Typed definition helpers, theme validation with structured diagnostics, and deterministic manifests Compiler API, manifest format
@contracta/svelte-build A build tool, not a runtime library: turns a manifest, and bindings to a site's own Svelte components, into one mountable Svelte component, the built theme Svelte build

Core and the Compiler depend on no host: no Hugo, Svelte, DOM, filesystem renderer, or domain vocabulary. The Svelte build depends on Core, the Compiler, and the Svelte compiler only.

Installing

The packages are ES modules and run on Node.js 22 or later. The Compiler and the Svelte build name the Contracta packages they work with as peer dependencies, so a project installs them side by side and every package shares one copy of each:

npm install @contracta/core                          # resolution, routes, plans
npm install @contracta/compiler @contracta/core      # themes and manifests
npm install --save-dev @contracta/svelte-build @contracta/compiler @contracta/core svelte

Upgrade them together. The three are released at the same version, and before 1.0 each accepts only its own minor line of the others (^0.2.0). npm refuses a mixed set with ERESOLVE whenever the package being installed needs a newer sibling than the project has, as when the Compiler or the Svelte build is upgraded alone. Upgrading Core alone only warns, and leaves a set the packages do not support.

pnpm 12 installs a version published less than a day ago anyway, and records it under minimumReleaseAgeExclude in pnpm-workspace.yaml; commit that entry. A project that sets minimumReleaseAge itself is refused with ERR_PNPM_NO_MATURE_MATCHING_VERSION until the version is listed there or a day has passed.

Ecosystem packages

Host adapters, themes, and site integrations live in their own repositories and publish under the same @contracta scope:

Package Repository Role
@contracta/svelte contractajs/contracta-svelte Svelte runtime adapter: drives a site's mount points from its URL with Core's routes and navigation. Not yet published.

Quick start

Author a theme, compile it, and resolve a module:

import {
  compileTheme,
  defineContract,
  defineModule,
  defineTheme,
} from '@contracta/compiler'
import { resolveModule, single } from '@contracta/core'

const panel = defineContract({ id: 'panel', renderer: { id: 'panel' } })
const page = defineContract({
  id: 'page',
  renderer: { id: 'page' },
  children: { main: single('panel') },
})
const home = defineModule({
  id: 'home',
  contract: 'page',
  children: { main: { contract: 'panel', props: { heading: 'Welcome' } } },
})

const theme = defineTheme({
  id: 'minimal',
  contracts: { page, panel },
  modules: { home },
  renderers: [{ id: 'page' }, { id: 'panel' }],
})

// Deterministic JSON text; an invalid theme throws CompilationError.
const manifest = compileTheme(theme)

// The tree a host renders: each node with its contract, renderer, props,
// merged scope, and children.
const tree = resolveModule(home, { contracts: theme.contracts })

For the whole chain, from a theme to a page that mounts it, run the site example. The minimal example adds routes, navigation, and transition plans.

Documentation

The living specification is in openspec/specs/.

Development

Requirements: Node.js 24 and Corepack. The exact pnpm version is pinned in package.json.

corepack enable
pnpm install
pnpm run build
pnpm test
pnpm run typecheck
pnpm run lint
pnpm run format:check
pnpm run changelog:check

After building, run the examples:

pnpm run example:minimal
pnpm run example:site

Changes follow OpenSpec and land through squash-merged pull requests; see development flow and AGENTS.md.

License

Licensed under either Apache-2.0 or MIT, at your option.

About

Contract-driven, renderer-agnostic web composition with scoped resolution and deterministic manifests.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages