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
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,16 @@ Three core modules form the **ingest → drive → emit** spine: `source` brings
events in, `state` decides what happens, and `sink` fans the resulting effects
out. Each is a thin seam you can adopt on its own, and none imports another.

<!--
The docs site renders these diagrams via docs/src/mermaid-theme.mjs on its own
dark background, so it can use the full dark brand palette. For the README on GitHub,
viewers may be in light or dark mode, so the diagrams here use a dual-context variant:
neutral steel fills (#8a929c) keep nodes legible on either background, while the same
ember/copper accents (#d9620a, #c47a3d) preserve brand identity. The canonical brand
hexes and the docs-site palette live in crucible.css and mermaid-theme.mjs.
-->
```mermaid
%%{init: {'theme':'base','themeVariables':{'background':'transparent','primaryColor':'#8a929c','primaryBorderColor':'#d9620a','primaryTextColor':'#16191d','lineColor':'#b06a28','defaultLinkColor':'#b06a28','titleColor':'#b5500c','mainBkg':'#8a929c','nodeBorder':'#d9620a','nodeTextColor':'#16191d','labelColor':'#16191d','edgeLabelBackground':'#c0c7cf','altBackground':'#aab1ba','clusterBkg':'#aab1ba','clusterBorder':'#d9620a'}}}%%
flowchart LR
streams[(external streams)] -->|source| engine[state engine]
engine -->|sink| destinations[(destinations)]
Expand All @@ -59,6 +68,7 @@ folds an event into a new instance and emits effects as plain data, leaving
persistence and dispatch to the host.

```mermaid
%%{init: {'theme':'base','themeVariables':{'background':'transparent','primaryColor':'#8a929c','primaryBorderColor':'#d9620a','primaryTextColor':'#16191d','lineColor':'#b06a28','defaultLinkColor':'#b06a28','titleColor':'#b5500c','mainBkg':'#8a929c','nodeBorder':'#d9620a','nodeTextColor':'#16191d','labelColor':'#16191d','edgeLabelBackground':'#c0c7cf','altBackground':'#aab1ba','clusterBkg':'#aab1ba','clusterBorder':'#d9620a'}}}%%
stateDiagram-v2
[*] --> Idle
Idle --> Working: Start [guard]
Expand All @@ -74,6 +84,7 @@ Consumes external streams (Kafka, JetStream, Redis, CDC, and more) and drives a
machine, with the ack tied to a durable transition so redelivery is safe.

```mermaid
%%{init: {'theme':'base','themeVariables':{'background':'transparent','primaryColor':'#8a929c','primaryBorderColor':'#d9620a','primaryTextColor':'#16191d','lineColor':'#b06a28','defaultLinkColor':'#b06a28','titleColor':'#b5500c','mainBkg':'#8a929c','nodeBorder':'#d9620a','nodeTextColor':'#16191d','labelColor':'#16191d','edgeLabelBackground':'#c0c7cf','altBackground':'#aab1ba','clusterBkg':'#aab1ba','clusterBorder':'#d9620a'}}}%%
flowchart LR
stream[(stream)] --> decode[decode / codec] --> route["route to (key, event)"] --> fire["Fire on instance"] --> commit[durable commit] --> ack[ack]
```
Expand All @@ -84,6 +95,7 @@ Fans emitted effects out to many destinations through a `Manifold`,
fire-and-forget; one outlet's failure never stops the rest.

```mermaid
%%{init: {'theme':'base','themeVariables':{'background':'transparent','primaryColor':'#8a929c','primaryBorderColor':'#d9620a','primaryTextColor':'#16191d','lineColor':'#b06a28','defaultLinkColor':'#b06a28','titleColor':'#b5500c','mainBkg':'#8a929c','nodeBorder':'#d9620a','nodeTextColor':'#16191d','labelColor':'#16191d','edgeLabelBackground':'#c0c7cf','altBackground':'#aab1ba','clusterBkg':'#aab1ba','clusterBorder':'#d9620a'}}}%%
flowchart LR
effect[emitted effect] --> manifold[Manifold]
manifold --> a[destination A]
Expand Down
25 changes: 21 additions & 4 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import { defineConfig } from 'astro/config';
import starlight from '@astrojs/starlight';
import mermaid from 'astro-mermaid';
import { crucibleMermaidThemeVariables } from './src/mermaid-theme.mjs';

// GitHub project page: https://stablekernel.github.io/crucible
// `site` + `base` must match the Pages URL so generated links and assets resolve.
Expand All @@ -13,11 +14,27 @@ export default defineConfig({
// Chosen over rehype-mermaid because it needs no headless browser (Playwright)
// at build time, keeping the CI `npm run build` step fast and dependency-light.
// It registers a remark plugin that transforms mermaid code blocks into a
// hydrated <pre class="mermaid"> element. `theme: 'dark'` matches the
// dark-default Crucible brand; mermaid auto-syncs when the user toggles theme.
// hydrated <pre class="mermaid"> element.
//
// Theming is centralized in ./src/mermaid-theme.mjs and applied to every
// diagram on the site (all stateDiagram-v2 + flowchart blocks, and the
// diagrams generated by tools/docsgen). We build on mermaid's `base` theme
// because it is the only theme that honors `themeVariables`, and pass the
// crucible brand palette through `mermaidConfig` (astro-mermaid forwards it
// verbatim to mermaid.initialize()).
//
// autoTheme is OFF deliberately. When on, the integration swaps in stock
// 'dark'/'default' mermaid themes per page mode, which discards most of our
// base themeVariables on toggle. astro-mermaid exposes a single mermaidConfig
// (no per-mode themeVariables), so to keep one source of truth we render the
// dark brand palette in both page modes. Dark charcoal nodes with white text
// stay legible on a light page the same way a fenced code block does.
mermaid({
theme: 'dark',
autoTheme: true,
theme: 'base',
autoTheme: false,
mermaidConfig: {
themeVariables: crucibleMermaidThemeVariables,
},
}),
starlight({
title: 'Crucible',
Expand Down
65 changes: 65 additions & 0 deletions docs/src/mermaid-theme.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// Crucible "foundry" mermaid theme — the single source of truth for diagram
// colors across the docs site (every stateDiagram-v2 + flowchart, plus the
// diagrams generated by tools/docsgen → ToMermaid).
//
// These hexes mirror the brand tokens in src/styles/crucible.css and the
// %%{init}%% directives in the repo-root README.md. Keep all three in sync.
//
// Identity: molten ember/copper accents over a deep steel/charcoal base.
// The brand is dark-default, so we build on mermaid's `base` theme — the only
// theme that honors `themeVariables` (see https://mermaid.js.org/config/theming.html)
// — with `darkMode: true` so derived shades resolve for a dark canvas. Every
// variable name below is a documented mermaid theme variable; nothing invented.
export const crucibleMermaidThemeVariables = {
darkMode: true,
background: '#16191d', // deep steel base canvas

// Primary nodes: charcoal surface, molten-ember border, white label.
primaryColor: '#23272c',
primaryBorderColor: '#d9620a', // ember-orange
primaryTextColor: '#f4f6f8',

// Edges / links: copper, with ember-glow reserved for emphasis (titles).
lineColor: '#c47a3d', // copper
defaultLinkColor: '#c47a3d',

// Secondary nodes: lighter charcoal panel, copper border.
secondaryColor: '#353b42',
secondaryBorderColor: '#c47a3d',
secondaryTextColor: '#f4f6f8',

// Tertiary / deep-composite + subgraph fills: nav-dark with a steel hairline.
tertiaryColor: '#1b1f24',
tertiaryBorderColor: '#2b3036',
tertiaryTextColor: '#e3e7ec',

// Flowchart specifics.
mainBkg: '#23272c',
nodeBorder: '#d9620a',
nodeTextColor: '#f4f6f8',
clusterBkg: '#1b1f24', // subgraph background
clusterBorder: '#c47a3d',
titleColor: '#f6a85b', // ember-glow emphasis on subgraph/diagram titles
edgeLabelBackground: '#23272c',

// stateDiagram-v2 specifics.
labelColor: '#f4f6f8',
altBackground: '#353b42', // deep composite-state background

// General text + notes.
textColor: '#f4f6f8',
noteBkgColor: '#353b42',
noteTextColor: '#f4f6f8',
};

// astro-mermaid passes `mermaidConfig` straight through to mermaid.initialize().
// We pin `theme: 'base'` here too because base is the only themeVariables-aware
// theme; the integration spreads this config and (when autoTheme is on) would
// otherwise swap in stock 'dark'/'default'. We keep autoTheme OFF in the astro
// config so the dark brand palette renders consistently in both page modes —
// dark charcoal nodes with white text stay legible on a light page background,
// the same way a fenced code block does.
export const crucibleMermaidConfig = {
theme: 'base',
themeVariables: crucibleMermaidThemeVariables,
};