Conversation
Foundation for the docs overhaul tracked in CIP-3307: - IA.md: living migration checklist at the repo root (one checkbox per planned page; sections tick off as they land on this branch) - New `v2docs` collection (content/docs) served from the site root via a required catch-all route, alongside the legacy tree (content/stack) at /stack until every section migrates - Frontmatter facet model: Diátaxis `type`, `components`, `audience`, `integration` (category / setup / pairsWith), and review-tracking fields (`verifiedAgainst`, `reviewBy`) - Section scaffold: get-started, integrations (incl. the /integrations/supabase stub the Supabase listing links to), concepts, compare, guides, security, solutions, reference — meta.json + stubs - v2-redirects.mjs: full legacy→v2 map (85/85 pages covered), gated behind ENABLE_V2_REDIRECTS=1 so the preview serves both trees during migration; /quickstart vanity redirect ships ungated - scripts/validate-v2-redirects.ts wired into prebuild: CI fails if a legacy page has no v2 mapping - llms.txt, llms-full.txt, sitemap, and the .mdx raw-markdown mirror now cover both trees Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
…rence/eql Two issues caught by smoke-testing the scaffold: - Stub descriptions containing ":" broke YAML frontmatter parsing (500s across the v2 tree) — descriptions are now quoted. - The AI-citation redirect "/reference/eql" → "/stack/reference/eql" shadowed the v2 /reference/eql page (redirects run before the filesystem); removed since the v2 page now serves that path. Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…t bare root Two fixes from preview review: - The bare domain root (Vercel preview URLs) 404'd because the app lives under the /docs basePath — added a basePath:false redirect / → /docs. In production only /docs/* reaches this app, so previews-only. - The /docs landing was a standalone (home) page disconnected from the v2 nav, with every link pointing at legacy /stack URLs. It's now content/docs/index.mdx rendered inside DocsLayout (sidebar + search), linking the v2 sections. The catch-all became optional ([[...slug]]) and the (home) route group is deleted (recoverable from history; CIP-3327 refines the landing content). - The landing's raw-markdown mirror serves at /docs/index.mdx (its URL is "/", which can't carry the .mdx suffix). Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
Listing "index" explicitly in meta.json pages forced each section's index out as a separate child item with the same title as its folder (clicking "Get started" opened a sub-nav containing another "Get started"). With index unlisted, Fumadocs merges it into the folder row: the folder itself links to the page, and children are only real sub-pages (Integrations → Supabase, not Integrations → Integrations). The root meta.json keeps "index" — at tree root there is no folder row to merge into, so the landing needs its own sidebar item. Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
Folders whose only page is their index still rendered as collapsible sidebar folders with a chevron pointing at nothing. getV2PageTree() now collapses such folders into plain page items (recursively, so guides/* and reference/* leaves flatten too); a section becomes a folder again automatically when its first real sub-page lands. Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
MDX links (markdown and Card hrefs) render through the Link component, which prefixes the /docs basePath — hardcoded /docs/... links rendered as /docs/docs/... and 404'd. Convention (enforce via CIP-3349 lint): internal links in content are always basePath-relative. Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
There was a problem hiding this comment.
Pull request overview
This PR scaffolds the “Docs V2” information architecture by introducing a new content/docs tree served from the site root (under the existing /docs basePath), while keeping the legacy content/stack tree available at /docs/stack during migration. It also adds a gated legacy→v2 redirect map plus CI validation to ensure legacy pages won’t become orphaned when redirects are enabled.
Changes:
- Add a new
v2docscollection +v2sourceloader, plus root catch-all routes/layout for the v2 docs tree. - Introduce a full legacy→v2 redirect map (
v2-redirects.mjs) gated byENABLE_V2_REDIRECTS=1, with a prebuild validation script to enforce coverage. - Scaffold v2 section stubs/meta and update sitemap + LLM surfaces (
llms.txt,llms-full.txt,.mdxraw mirror) to include the v2 tree first.
Reviewed changes
Copilot reviewed 65 out of 65 changed files in this pull request and generated 25 comments.
Show a summary per file
| File | Description |
|---|---|
| v2-redirects.mjs | Adds the full legacy /stack/* → v2 redirect mapping list (flag-gated in Next config). |
| next.config.mjs | Wires in gated v2 redirects, adds preview root redirect, and adds .mdx rewrite for v2 raw mirror; removes old /reference/eql redirect collision. |
| scripts/validate-v2-redirects.ts | Adds CI/prebuild gate to ensure every legacy content/stack page is covered by v2 redirects. |
| package.json | Adds validate-redirects script and runs it during prebuild. |
| source.config.ts | Defines the new v2docs collection and its frontmatter facet schema. |
| src/lib/source.ts | Adds v2source, v2 page tree shaping (flattenEmptyFolders), and broadens getLLMText typing for both trees. |
| src/app/[[...slug]]/layout.tsx | Adds the v2 docs layout (DocsLayout + v2 tree) at the root catch-all segment. |
| src/app/[[...slug]]/page.tsx | Adds the v2 docs page renderer, metadata generation, and markdown mirror URL generation. |
| src/app/llms.mdx/v2/[[...slug]]/route.ts | Adds the v2 raw-markdown mirror route for agent/LLM consumption. |
| src/app/llms.txt/route.ts | Lists v2 pages first, then legacy pages, in llms.txt. |
| src/app/llms-full.txt/route.ts | Emits the concatenated markdown for v2 pages first, then legacy pages. |
| src/app/sitemap.ts | Includes both v2 and legacy pages in sitemap (v2 first). |
| src/app/og/docs/[...slug]/route.tsx | Import ordering tweak only. |
| src/app/api/search/route.ts | Import ordering tweak only. |
| src/app/layout.tsx | Import ordering tweak only. |
| src/app/stack/layout.tsx | Import ordering tweak only. |
| src/app/stack/[[...slug]]/page.tsx | Import ordering tweak only. |
| src/proxy.ts | Import ordering tweak only. |
| src/lib/posthog/provider.tsx | Import ordering tweak only. |
| src/components/icons/supabase.tsx | Fixes missing semicolon in return statement. |
| src/app/(home)/page.tsx | Removes the standalone legacy docs landing page implementation. |
| src/app/(home)/layout.tsx | Removes the legacy home layout wrapper. |
| IA.md | Adds the migration checklist + branch workflow rules for the v2 overhaul. |
| content/docs/meta.json | Adds v2 root meta defining top-level section ordering. |
| content/docs/index.mdx | Adds the v2 docs landing page content (Cards + LLM surface links). |
| content/docs/get-started/meta.json | Adds v2 “Get started” section meta. |
| content/docs/get-started/index.mdx | Adds v2 “Get started” stub page. |
| content/docs/integrations/meta.json | Adds v2 “Integrations” section meta. |
| content/docs/integrations/index.mdx | Adds v2 “Integrations” stub page. |
| content/docs/integrations/supabase/meta.json | Adds v2 Supabase integration meta (custom icon). |
| content/docs/integrations/supabase/index.mdx | Adds v2 Supabase stub page with facet example. |
| content/docs/concepts/meta.json | Adds v2 “Concepts” section meta. |
| content/docs/concepts/index.mdx | Adds v2 “Concepts” stub page. |
| content/docs/compare/meta.json | Adds v2 “Comparisons” section meta. |
| content/docs/compare/index.mdx | Adds v2 “Comparisons” stub page. |
| content/docs/guides/meta.json | Adds v2 “Guides” section meta. |
| content/docs/guides/index.mdx | Adds v2 “Guides” stub page. |
| content/docs/guides/development/meta.json | Adds v2 “Development” guides meta. |
| content/docs/guides/development/index.mdx | Adds v2 “Development” stub page. |
| content/docs/guides/migration/meta.json | Adds v2 “Data migration” guides meta. |
| content/docs/guides/migration/index.mdx | Adds v2 “Data migration” stub page. |
| content/docs/guides/deployment/meta.json | Adds v2 “Deployment” guides meta. |
| content/docs/guides/deployment/index.mdx | Adds v2 “Deployment” stub page. |
| content/docs/guides/troubleshooting/meta.json | Adds v2 “Troubleshooting” guides meta. |
| content/docs/guides/troubleshooting/index.mdx | Adds v2 “Troubleshooting” stub page. |
| content/docs/security/meta.json | Adds v2 “Architecture & security” section meta. |
| content/docs/security/index.mdx | Adds v2 “Architecture & security” stub page. |
| content/docs/security/compliance/meta.json | Adds v2 “Compliance” meta under security. |
| content/docs/security/compliance/index.mdx | Adds v2 “Compliance” stub page. |
| content/docs/solutions/meta.json | Adds v2 “Solutions” section meta. |
| content/docs/solutions/index.mdx | Adds v2 “Solutions” stub page. |
| content/docs/reference/meta.json | Adds v2 “Reference” section meta. |
| content/docs/reference/index.mdx | Adds v2 “Reference” stub page. |
| content/docs/reference/eql/meta.json | Adds v2 “EQL” reference meta. |
| content/docs/reference/eql/index.mdx | Adds v2 “EQL” stub page. |
| content/docs/reference/stack/meta.json | Adds v2 “Stack SDK” reference meta. |
| content/docs/reference/stack/index.mdx | Adds v2 “Stack SDK” stub page. |
| content/docs/reference/proxy/meta.json | Adds v2 “Proxy” reference meta. |
| content/docs/reference/proxy/index.mdx | Adds v2 “Proxy” stub page. |
| content/docs/reference/cli/meta.json | Adds v2 “CLI” reference meta. |
| content/docs/reference/cli/index.mdx | Adds v2 “CLI” stub page. |
| content/docs/reference/auth/meta.json | Adds v2 “Auth” reference meta. |
| content/docs/reference/auth/index.mdx | Adds v2 “Auth” stub page. |
| content/docs/reference/workspace/meta.json | Adds v2 “Workspace & account” reference meta. |
| content/docs/reference/workspace/index.mdx | Adds v2 “Workspace & account” stub page. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <Card title="Integrations" href="/docs/integrations" description="Platforms, ORMs, frameworks, auth providers, and runtimes." /> | ||
| <Card title="Concepts" href="/docs/concepts" description="How searchable encryption, key management, and identity-aware encryption work." /> | ||
| <Card title="Guides" href="/docs/guides" description="Development workflow, data migration, deployment, and troubleshooting." /> | ||
| <Card title="Architecture & security" href="/docs/security" description="Trust model, components, availability, audit, and compliance — for security review." /> | ||
| <Card title="Solutions" href="/docs/solutions" description="PII protection, HIPAA, AI/RAG, data residency, and provable access." /> |
| <Card title="Guides" href="/docs/guides" description="Development workflow, data migration, deployment, and troubleshooting." /> | ||
| <Card title="Architecture & security" href="/docs/security" description="Trust model, components, availability, audit, and compliance — for security review." /> | ||
| <Card title="Solutions" href="/docs/solutions" description="PII protection, HIPAA, AI/RAG, data residency, and provable access." /> | ||
| <Card title="Reference" href="/docs/reference" description="EQL, the Stack SDK, Auth, the CLI, and Proxy — precise API documentation." /> |
| - **Moving a page = ** move the file into `content/docs`, update its facets, | ||
| fix inbound links, confirm its `v2-redirects.mjs` entry, tick it here. |
Seven pages replacing the v2-era EQL reference, written against the eql_v3 branch of cipherstash/encrypt-query-language (3.0.0): - index: what EQL is, the v3 domain-variant model, install (single SQL script, idempotent), dbdev, Docker, migration/runtime permission split, managed-Postgres rationale - types: 10 scalar families × variants matrix; bool storage-only; _ord/_ord_ore twins; index terms per variant - operators: per-variant support matrix, typed-operand rule, no-LIKE, fail-loud blockers, query shapes, function-form equivalents - indexes: functional indexes on term extractors, engagement requirements, sort-key form for index-streamed ORDER BY, EXPLAIN checklist, large-table build guidance - json: ste_vec model, per-node-type terms (hm XOR oc), containment + GIN, field access, path queries, blocked native jsonb operators - functions: comparisons, extractors, min/max only (no SUM/AVG), version() - payload-format: v/i/c envelope (wire version still v:2), hm/ob/bf term keys, sv document shape, annotated examples (absorbs the legacy CipherCell page) Cross-page consistency verified against the shipped SQL: equality on _ord variants compares ORE terms (no hm in _ord payloads), and bare ORDER BY is correct but extractor-form sort keys stream from the index. Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
| { | ||
| source: "/stack/quickstart", | ||
| destination: "/get-started/quickstart", | ||
| permanent: true, |
There was a problem hiding this comment.
We shouldn't make these permanent for now.
There was a problem hiding this comment.
Done in d0ccd7e — all 71 entries flipped to permanent: false, with a header note to revisit as part of CIP-3335 once the map has soaked post-merge.
EQL is an abstraction over SQL the way Tailwind is over CSS — the docs now follow the same shape: Install → Core concepts → type categories → Indexes → query patterns, increasing in complexity. Each type-category page is the complete reference for its types (variants, payload shape, operators/functions, example queries on one page). - index: trimmed to the Install page - core-concepts (new): the canonical home for shared mechanics — variant model, payload anatomy (v/i/c envelope + hm/ob/bf terms, absorbs payload-format/CipherCell), typed-operand rule, fail-loud blockers, ORE-equality on _ord, term-leakage pointer - numbers-and-dates, text, booleans (new) + json (reworked): category pages; text owns the no-LIKE treatment; json absorbs the sv payload shape; booleans framed as "every type has a storage-only variant — for bool it's the only one" - filtering, sorting, grouping-and-aggregates, joins (new): cross-type query patterns; joins headlines the same-keyset constraint - deleted: types.mdx, operators.mdx, functions.mdx, payload-format.mdx (content redistributed; URLs never shipped publicly, no redirect debt) - Anti-drift rule recorded in IA.md: mechanics live ONLY in core-concepts; category/query pages link, never restate - meta.json: flat URLs with ---Types---/---Indexes---/---Queries--- sidebar separators; legacy redirect map retargeted (queries → filtering, cipher-cell → core-concepts) Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
…load v:3 Review feedback on the EQL section: - Variant tables: generic form first, then full enumeration of every concrete domain name (Tailwind-style); capability column made concise; "index term carried" column dropped — term internals live in core-concepts' payload anatomy - SEM specifiers documented as a concept in core-concepts: a trailing mechanism suffix (_ord_ore) pins WHICH searchable-encryption mechanism implements a capability; _ord tracks the default (currently ORE). Replaces the "twins" framing. Each orderable type page lists its specifiers under an "SEM specifiers" heading, noting the OPE specifier arriving for all orderable types (incl. text) in the v3 release - Payload `v` field documented as the EQL version (3) per team decision 2026-07-02; all payload examples updated from v:2 Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
…perators and Functions Review feedback: - Dates & times split out of Numbers — same traits, distinct semantics; each page's examples now match its domain (payroll vs audit-event time windows / retention cutoffs / newest-first) - CREATE TABLE examples get an explicit "Example" sub-heading + lead-in - Operators and Functions are separate sections on every type page — operators as the per-variant support matrix, functions as the form-equivalents table (+ MIN/MAX, which only exist as functions) - IA.md: split reflected; query-performance follow-up added (CIP-3351 — the v3 branch already folded the v2 perf guide into database-indexes.md, which our indexes page absorbed) Claude-Session: https://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P
- indexes.mdx: cast query-shape example params to their EQL domain types, consistent with the typed-operand rule - numbers/dates-and-times/text: the fail-loud note now scopes to operators — ORDER BY on a variant without an ordering term doesn't raise, it silently returns a meaningless order (links Sorting)
- v2-redirects.mjs: all entries permanent: false while the IA settles (per review); flip to permanent post-merge soak (CIP-3335) - IA.md: fix unmatched bold around 'Moving a page' - add placeholder pages for /concepts/searchable-encryption (CIP-3333) and /guides/troubleshooting/query-performance (CIP-3351) so the EQL reference's forward links resolve instead of 404ing
# Conflicts: # v2-redirects.mjs
|
Review comments addressed in d0ccd7e:
|
Docs V2: EQL v3 reference section, Tailwind-shaped (CIP-3326)
Per review: the 100x AWS KMS figure describes unreleased work, so the page uses 14x, which the benches repo supports and which proxy/index.mdx already states. The FHE and sub-millisecond claims are defensible and come back. Each number now names its source rather than floating free: - Sub-millisecond query overhead, explained (operators inline into functional indexes, so Postgres does a normal index scan). - 410,000x vs FHE, linked to the open tfhe-ore-bench harness. The old page said 100,000x; fhe.mdx and searchable-encryption.mdx both say 410,000x, so the outlier was the page being ported. - Up to 14x the throughput of AWS KMS, with the reason (bulk key derivation). Also frames the trade rather than leading with speed: encryption in use is slow if you do it with FHE, and searchable encryption buys its speed with bounded, published leakage.
"The trade" read as an apology. Each scheme's leakage is bounded and published, which makes it something you choose per column rather than something that happens to you. Renamed to "Choosing what each column reveals", with a table mapping declared capability to what an observer could infer, from "nothing" upward. The point is now that the goal is not to eliminate leakage but to pick capabilities whose leakage your threat model already tolerates, and to know exactly what you picked. A column whose frequency distribution is itself the secret gets encrypted without that capability and filtered after decryption. Same reframing on the quickstart's closing bullet, which had the same tone.
- Platform table, Neon/RDS/Aurora/Cloud SQL row: drop "Nothing special." - Section 4: "Identity binding, if you need it" -> "Identity binding". Removing "if you need it" changes the framing from optional to standard, so "Most teams start without this" went with it. Replaced by the reason it matters: identity binding is what shrinks the blast radius of a compromised application process, which is the point raised on the threat-model review.
docs(get-started): build the Get started section
Rewrites the EQL reference against the type and term shapes landing in EQL 3.0.0 (encrypt-query-language #391 and #389), verified against the generated schema and the domain SQL rather than against the PR bodies. Public domain types are now version-prefixed: `public.text_ord` becomes `public.eql_v3_text_ord`. 174 names across 15 pages. Ordering now defaults to CLLW OPE: - `_ord` carries `op` and extracts with `eql_v3.ord_term` - `_ord_ope` is its byte-identical, explicitly pinned twin - `_ord_ore` carries `ob` and extracts with `eql_v3.ord_term_ore` - `text_search` is `[hm, op, bf]`; the new `text_search_ore` is `[hm, ob, bf]` - `eql_v3.ord_ope_term` is gone; `eql_v3.ord_term` took its name OPE terms sort under `bytea_ops`, so ordering no longer needs a custom operator class. Where the installer runs as a non-superuser it cannot create one, and it disables the ORE-backed domains rather than let them install half-working. Documented on every page that offers the choice. Also corrects an equality claim the old pages had wrong in both directions. Equality on the non-text `_ord` variants compares the ordering term (those payloads carry no `hm`), but every text variant carries `hm` and compares that, because ordering over text is not equality-lossless. Confirmed in the domain SQL: `eq(bigint_ord)` calls `ord_term`, `eq(text_ord)` calls `eq_term`. The drift check stays red until EQL 3.0.0 publishes, because the pinned manifest is alpha.4, which predates both PRs. Every symbol this commit introduces was cross-checked against the SQL on the release branch.
Bumps EQL_RELEASE_TAG from eql-3.0.0-alpha.4. The drift check now passes against the real manifest, which confirms every domain and function this branch renamed. Two follow-ons the bump exposed: - The 40 scalar query-operand domains (`eql_v3.query_text_eq` and its siblings) are created inside a `DO ... EXECUTE` block, which the manifest's catalog generator does not walk, so the drift check rejected a correct reference. `eql_v3.query_jsonb`, created at the top level, is present. Added a narrow, documented allowlist rather than weakening the check; verified against the release SQL. - core-concepts named `public.text` / `public.json` / `public.integer` as the Postgres built-ins the `eql_v3_` prefix avoids shadowing. The drift check reads any `public.<name>` as an EQL domain reference. Say the same thing without schema-qualifying the built-ins.
docs(eql): update the reference to the EQL 3.0.0 shapes
* docs(reference): add the benchmarks page Publishes the EQL v3 query-performance numbers from cipherstash/benches at /reference/benchmarks, so the performance claims have a docs page to land on: - encrypted-vs-plaintext query latency (exact match and OPE range within ~1.2-1.4x of plaintext, flat from 10k to 10M rows) - the OPE-vs-ORE range/order tradeoff, free-text bloom match, JSON, GROUP BY - ingest throughput, methodology, caveats, and repro steps Every figure is sourced from the public benches report and cross-checked against the plaintext baseline. Ticks the IA checklist item. * docs(benchmarks): fix the inverted OPE/ORE variant labels The page had the ordering variants backwards relative to shipped EQL 3.0.0. It attributed OPE (fast, ~1s index build) to `_ord_ope` only and called `_ord` the ORE variant. Shipped, `_ord` IS the OPE default (op term, `eql_v3.ord_term`, indexes under the built-in btree opclass), and `_ord_ore` is the ORE-pinned variant (ob term, `eql_v3.ord_term_ore`, needs a superuser opclass). Verified against the 3.0.0 install SQL. Only the variant labels were wrong; every latency and build-time figure was already correct and is unchanged.
The Vercel build failed in `generate-docs`. Three causes, all from the Stack 1.0 monorepo restructure: 1. Stale entry points. `secrets/`, `drizzle/`, and `supabase/` no longer exist under `packages/stack/src` (secrets removed; the two adapters moved to their own packages), so TypeDoc had nothing to read. Dropped them; kept the seven modules `@cipherstash/stack` still ships. 2. Type errors from cross-package resolution. The stack monorepo is a pnpm workspace, but the generator installs it with `bun`, which leaves references like `@cipherstash/protect-ffi`'s `ProtectError` unresolved for the isolated typecheck even though 0.29.0 exports it. Set TypeDoc's `skipErrorChecking: true` — it emits accurate signatures from the source AST regardless, which is the right posture for documenting external source we don't control. 3. Multi-version generation broke on the layout change. The module layout diverged across majors (0.18 still has the adapters/secrets; 1.0 does not), and one shared `entryPoints` config can't document both. Generate only the latest major. Also reset the working tree before each checkout, since a prior tag's `bun install` rewrites the tracked package.json and would block switching tags. Also strips the now-dead TypeDoc deep-links from the legacy Drizzle reference page (the adapter's API pages are no longer generated here) and points it at /integrations/drizzle. Verified: `generate-docs`, `validate-links`, and a full `bun run build` all pass.
The "Functions available on this type" tables on the numbers, text, and dates-and-times reference pages were hand-maintained and had silently drifted from the EQL surface before. Generate them from the EQL manifest instead and embed them via Fumadocs' `<include>` directive, so the per-type operator-function matrix can't drift from the catalog it documents. - generate-eql-api-docs.ts emits content/partials/eql/functions-<page>.mdx from domains[].capabilities + variant, collapsing variants per capability (e.g. all `_ord` variants) and naming them concretely for single-type pages (text_eq) vs generically for type families (_eq). - Partials live outside the content collections so Fumadocs never routes them; they're included cwd-relative and committed so dev/types:check (which skip prebuild) resolve them. - Verified: output is byte-identical to the prior hand tables against the real EQL 3.0.0 manifest; full build produces no stray routes and inlines the tables into HTML, copy-markdown, and llms output. json (bespoke containment/path functions) and booleans (storage-only) are left as hand-written prose, not part of the per-type matrix.
Replace the generated function table with a per-function layout: one card per function (lt/lte/gt/gte grouped into one), showing its operator equivalents, the domains it applies to, and a worked example. - New <EqlFn> client component renders the card, operator badges, and the applies-to domain list. The domain list shows the first two variants with a "Show all N variants" toggle, so the 24-domain numbers cases don't flood the page. Styled with Fumadocs fd-* tokens so it tracks the theme. - generate-eql-api-docs.ts emits <EqlFn> blocks into the partials, with the domain list pulled from the manifest (drift-proof). The example is passed as the code-fence child so it keeps the site's highlighting and copy button; examples are templated by capability — the one authored part. - Text ordering functions demonstrate ORDER BY (sorting is the point on text); numbers/dates keep the range form. contains/contained_by only render where a match-capable domain exists, so they're absent on numbers and dates. Verified: full build renders every card, operators, pills, and highlighted examples with no stray tags; types:check and lint pass.
- Remove the worked example from each function card; each page's own "Example queries" section already covers examples, so the per-card ones only duplicated them. <EqlFn> no longer takes children. - Add a stable anchor id per function (fn-eq, fn-comparison, …) with a hover link affordance, so individual functions are deep-linkable. - Drop the accent border/tint on the grouped comparison card; every card now uses the same neutral card styling.
…s section Correcting the previous commit, which removed the examples from the wrong place. The per-function example belongs in each card; it's the page-level "## Example queries" section that was redundant with them. - Restore the worked example inside <EqlFn> (passed as children, so it keeps the site's highlighting and copy button); the generator templates it by capability again. - Remove the "## Example queries" section from the text, numbers, and dates-and-times pages — the per-function cards now carry the examples.
Each function's name is now a real `###` heading (with an explicit `[#fn-*]` id) instead of text inside the card. The table of contents only sees Markdown headings, so this lists every function as a sub-item under "Functions" in the right-hand nav, and keeps the stable deep-link anchor. The <EqlFn> card renders everything below the heading — operator equivalents (now under an "Operators"/"Aggregate" label), the applies-to domains, and the example. It no longer takes name/id props or renders its own anchor, since the heading owns both.
The JSON page's query surface (containment, field access, leaf comparisons, path queries, array helpers) was prose spread across three sections. Restructure it into a "## Functions" section of <EqlFn> cards under `###` headings, matching the scalar type pages: each function is now a TOC sub-item under Functions and a deep-link anchor. Unlike the scalar pages, JSON's functions aren't derivable from domain capabilities (the jsonb domains are storage-only), so these cards are authored directly in json.mdx rather than generated. json.mdx is scanned by the drift guard, so every eql_v3.* symbol referenced is still validated against the manifest. - Make <EqlFn>'s `ops` optional so pure functions (jsonb_path_query, the array helpers) render without an operator row. - Preserve the GIN containment index recipe and the selector-hash / typed-operand notes as prose within the new section.
Show the plaintext JSON the function examples query against, right under the Functions heading, and map the `*_selector` placeholders to their paths. Readers can see what each function operates on instead of inferring it from the selector names.
docs(eql): generate per-type function tables as included partials
Replace Shiki's default GitHub themes with two custom themes (light + dark) built from the site palette: the lime-green brand accent for keywords, warm neutrals for text and comments, and teal / gold / amber supporting hues tuned to the near-black and off-white grounds the docs already use. Shiki already runs in dual-theme mode, so this is purely a themes swap in rehypeCodeOptions — the copy button, line highlighting, diff/focus transformers, and Fira Code font are unchanged, and every code block picks it up.
Match the marketing site: H2 and below now render in Geist Sans (loaded via next/font/google), while H1 keeps its Fira Code monospace treatment. Body text and code are unchanged.
-0.02em reads too tight on the smaller Geist Sans headings; H2-H3 keep it.
docs: brand styling — CipherStash code theme + Geist Sans headings
Backport the code syntax palette settled on the marketing site (js-suite #572): rose keywords, purple functions, aqua types, lime strings, a lighter yellow for numbers, and a neutral grey for comments. The dark theme takes those exact values; the light theme uses darkened, readable variants of the same hues so both modes share one hue assignment.
docs: retune the code theme to match the marketing site
Long-lived integration branch for the docs V2 overhaul, tracked in CIP-3307. Opened as a draft — it merges only when the migration completes (CIP-3335); section work stacks as PRs targeting this branch, and this PR's Vercel preview is the staging site for the whole overhaul.
What's in the scaffold (CIP-3325)
IA.md— living migration checklist at the repo root: one checkbox per planned page, ticked as sections land, with the branch's working rules (how to move a page, redirect flag, URL conventions)v2docscollection (content/docs) served from the site root (/docs/get-started/…,/docs/integrations/supabase, …) via a required catch-all route. The legacy tree still serves at/docs/stack/*— both trees coexist until every section migrates, then the legacy tree is deletedtype,components,audience,integration(category / setup / pairsWith), and review-tracking fields (verifiedAgainst,reviewBy)/docs/integrations/supabase(the Supabase listing's link target)v2-redirects.mjs— full legacy→v2 map (85/85 pages covered), gated behindENABLE_V2_REDIRECTS=1so previews serve both trees during migration; the flag flips on at merge.bun run validate-redirectsis wired into prebuild: a legacy page without a mapping fails CI/docs/quickstartvanity redirect (ungated — no legacy traffic on that path).mdxraw-markdown mirror all cover the v2 tree (listed first)/reference/eql → /stack/reference/eql— its source collided with (and shadowed) the v2 page at that pathHow to review the preview
/docs/get-started,/docs/integrations/supabase,/docs/security/compliance,/docs/reference/eql(stubs for now)/docs/stack/quickstartetc..mdxto any v2 page URL;/docs/llms.txtMerge checklist (CIP-3335, end of migration)
ENABLE_V2_REDIRECTS=1set for productioncontent/stack,/stackroutes, and the legacy loader deletedhttps://claude.ai/code/session_01ACPpFPHvKtrV48nbEYuv7P