From b86596b0427133d9485b199b9105de398c87d413 Mon Sep 17 00:00:00 2001
From: Nick Gomez <122398915+nick-inkeep@users.noreply.github.com>
Date: Wed, 1 Jul 2026 10:41:35 -0700
Subject: [PATCH] Extract OpenKnowledge marketing site into a private
ok-marketing app (#2334)
* docs(open-knowledge): add marketing-site-separation spec
PRD plus technical spec for extracting the marketing site into its own private, non-mirrored Next.js app (private/ok-marketing), leaving docs and the product routes public and preserving every current URL via Vercel Microfrontends.
Covers the vendored-core editor-preview mechanism (committed dist plus a CI drift-guard), the component untangle, the cutover and rollback plan, and the verification substrate. Includes the decision log, spec-local evidence, and two cold-reader audits.
Internal only; specs/ is not mirrored to the public repo.
* [US-002] scaffold private/ok-marketing Next.js app + workspace member
* [US-003] vendor core dist behind a shim with a rebuild-and-diff drift guard
Give the marketing app the live editor preview's core slice without
crossing the pnpm/Bun boundary at build time. Commit core's built barrel
(dist/index.mjs plus its hashed sibling chunk) under
private/ok-marketing/vendor/open-knowledge-core/ behind a thin shim
package.json that re-exports it and mirrors core's dependency block, and
consume it via a file: dep. This is the raw committed-dist path the
US-001 spike certified, not the ok-editor-preview wrapper fallback.
scripts/verify-core-dist.mjs rebuilds core with Bun and diffs its fresh
dist closure against the committed copy, failing with the regenerate
command on drift; --write (regen-core-dist) refreshes it. The closure is
resolved from index.mjs's own local imports, so a content-hash rename of
the shared chunk is caught rather than assumed away. The drift
classifier is unit tested.
Supporting wiring:
- .gitignore exempts the vendored dist from the dist/ build-output rule
- biome files.includes and tsconfig exclude vendor/ so the formatter and
typechecker skip the minified barrel and the tiptap-typed .d.ts
- carve private/ok-marketing/vendor out of the dep-drift and
workspace-membership trap scans, since the shim's mirrored dep block is
a vendored artifact, not a workspace member
Also reconcile the shared-dep drift the US-002 scaffold introduced but
did not check: align next to ^16.2.4 to match the rest of the monorepo,
and grandfather the remaining heterogeneous frontend devDeps alongside
copilot-app in the drift allowlist. Monorepo traps and lockfiles are
green.
* [US-004] untangle (home)-coupled components out of the docs app
Move footer, dot-texture, and marketing-button out of the docs app's
(home) route group into neutral src/components/ so the staying routes
(/continue, /d/[encoded]) no longer reach into (home). All eight
importers repointed to the @/components/* alias. No file outside (home)
imports from (home) anymore; docs build and typecheck stay green.
* [US-005] relocate marketing landing + shared chrome into ok-marketing
Copy the (home) landing closure out of the docs app into the private
marketing app with the directory structure preserved so @/ aliases resolve,
replacing the docs-coupled pieces:
- getGitHubStars: direct GitHub REST fetch in lib/github-stars.ts (no core
import), returning null on failure at the network trust boundary.
- hero: static, self-contained preview. The chat intro animation is kept
verbatim; the live TipTap editor pane is replaced by a step-driven static
document plus an inline activity chart. The live editor lands in US-006.
- provider: next-themes forced-light, dropping the fumadocs RootProvider.
- global.css: self-contained (no fumadocs imports), class-based dark
variant, fd-background and fd-muted-foreground registered as theme tokens.
- next.config: PostHog /ingest rewrites; instrumentation-client copied.
Duplicates the shared presentational set, replicates the root layout, fonts,
JsonLd and PostHog wiring, and copies the referenced public assets. New deps
are aligned to existing scanned versions to keep dependency drift minimal.
* [US-006] wire the live OK editor preview in ok-marketing via vendored core
Bring the ok-editor closure and the two ui components it needs into the
marketing app, and restore the live hero-preview so the hero mounts the real
TipTap editor instead of the static placeholder. The editor imports its four
client symbols (MarkdownManager, sharedExtensions, CodeBlockFidelity,
PREVIEW_THEME_TOKENS) from the vendored core shim.
Add the TipTap and CodeMirror runtime deps at the versions the docs app uses so
they dedupe to a single @tiptap instance shared with the shim. The vendored
shim exposes only four symbols, so the extension packages' command-type
augmentations are loaded via a devDependency-backed ambient declaration.
Client bundle carries the editor pipeline with zero node: builtins; core source
and exports are unchanged.
* [US-007] drop docs (home) root, migrate middleware to proxy
Docs no longer answers /; the marketing landing now lives in the private
marketing app. Remove the (home) route group and its orphaned exclusive
dependencies (the ok-editor live-preview closure, ok-icon, ui/sheet,
ui/tooltip) so the public docs no longer carries the editor-to-core
coupling that the separation moves to the private app.
Rename middleware.ts to proxy.ts (Next 16), keeping the www to apex 308
canonicalization and the /.well-known/* carve-out that serves AASA as a
direct 200 on both apex and www. Verified against next 16.2.3 that the
config export stays named config.
Simplify provider.tsx (drop the dead /-only light theme pin) and make the
sitemap docs-only (drop the root entry so the public standalone deploy
does not advertise a 404 root). Document the /docs default route in a
mirror-safe next.config.ts comment.
* [US-008] wire Vercel Microfrontends config (docs default, marketing child)
Compose openknowledge.ai from two Vercel projects via Vercel Microfrontends,
config only. The docs app stays the default (apex + every current path); the
marketing app is a child claiming only / plus its asset prefix.
- add @vercel/microfrontends to both apps; wrap both next.configs with
withMicrofrontends
- microfrontends.json in the docs (default) app: docs=default (no routing),
marketing=child routing / and /marketing-assets/:path*
- move marketing public/ assets under /marketing-assets so they route to the
marketing zone (the docs app still serves /images/* and /ok-logo.png, so a
shared root path would hijack docs assets on the apex)
- duplicate HSTS (includeSubDomains; preload) in the marketing next.config
- MICROFRONTENDS.md documents the topology, Fallback Environment=Production
intent, the app-name-must-match-Vercel-project check, and that the production
apex cutover is a separate human step (not executed here)
- contract test pins the marketing routing entry against the app's real package
name and public assets
The docs app builds green off-Vercel with the wrapper and config present, so the
public mirror's standalone docs build is unaffected.
* [US-009] point marketing subscribe form at the apex /api/subscribe cross-origin
Extract the newsletter network contract into lib/subscribe.ts: a single-source
subscribeSchema, an absolute apex SUBSCRIBE_ENDPOINT (derived from SITE_URL,
env-overridable for local dev), and subscribeToNewsletter(). The marketing zone
has no /api route, so the form must POST cross-origin to the product app's
endpoint (which already serves wildcard CORS + an OPTIONS preflight for exactly
this caller) rather than a relative path that would 404.
Pin the cross-app request contract in subscribe.test.ts: endpoint is absolute
apex + cross-origin, the POST sends a JSON { email } body that parses under a
mirror of the docs route schema, and a non-ok response maps to { ok: false }.
* [US-010] add ok-marketing CI validation gate + verify-core-dist wiring
Add .github/workflows/ok-marketing-validation.yml validating the private
marketing app on changes. A thin caller of the reusable _subtree-validation.yml
runs the standard build/lint/typecheck/test matrix (copilot-app precedent,
composite install, marketing-scoped paths). A bespoke verify-core-dist job the
reusable cannot express sets up Node plus Bun, installs the Open Knowledge
workspace, and runs the rebuild-and-diff drift guard so a stale vendored core
dist fails CI with the regenerate command.
The gate aggregator tolerates cancelled/skipped and keeps abandoned fail-closed
(passes check:gate-cancel-resilient). The drift guard fires on marketing paths
only, not core source: it rebuilds current core on every marketing PR so a
since-moved core surfaces the moment marketing is touched, without coupling
every core change to the marketing vendor. Registering it as a required check in
the branch-protection ruleset is a follow-up repo-admin step, noted in the
workflow header.
* [US-011] add pre-cutover URL/AASA/HSTS sweep + render smoke + cutover runbook
* fix(ci): harden ok-marketing drift-guard + prune dead editor deps
Phase 7 no-skimp fixes from the adversarial review gate.
verify-core-dist gate (ok-marketing-validation.yml):
- single-source the path scope via a paths job consumed by both the matrix
caller and the drift gate, so the two cannot silently diverge
- the drift gate now also fires on public/open-knowledge/packages/core
changes, so a core-source edit re-runs the rebuild-and-diff on the same PR
that drifts the vendored dist (genuinely fail-closed)
- the aggregate gate now includes detect-core-dist-changes in needs and fails
closed on its failure; a transient path-detect failure previously skipped
the guard while the required gate stayed green
marketing:
- delete the dead download-links.ts resolver fork; fold the two consumed
constants (DMG_ASSET_NAME, STABLE_DMG_URL) into site.ts
- add vendored-core-contract.test.ts: runs the real vendored .mjs against the
hand-authored .d.ts so a core signature change cannot leave the types stale
docs:
- remove 11 tiptap/codemirror deps + @floating-ui/dom, unused since the (home)
editor was removed; they were mirroring to the public repo and reintroducing
the editor-dep surface the separation exists to shed
* chore(mirror): exclude docs/microfrontends.json from the public mirror
docs/microfrontends.json names the private @inkeep/ok-marketing app and its routes. openknowledge.ai deploys from agents-private (confirmed: the open-knowledge-docs Vercel project Root Directory is public/open-knowledge/docs), so the public mirror is not a Vercel deploy source and the file is inert there. Excluding it keeps the OSS repo from disclosing an internal app name and route while the private composed deploy keeps the file unchanged. The withMicrofrontends wrapper and the @vercel/microfrontends dependency stay public (harmless and inert in the public standalone docs build).
* fix(boundaries): exclude vendored re-export shims from the private-package name map
The vendored core shim (private/ok-marketing/vendor/open-knowledge-core) re-uses the
public package name @inkeep/open-knowledge-core so the private marketing app can consume
it via a file: dependency. check:boundaries keyed its private-package map by name and
walked all of private/, so the shim registered that public name as private-only and both
scans (public source imports + public workspace: manifests) misresolved the OK app's
legitimate public-core references to the private shim. Skip vendor/ dirs the same way
node_modules is skipped: committed dependency output, not first-party private source.
* chore(docs): shed orphaned (home)-landing code after the marketing separation
US-007 dropped the docs (home) landing; these were its private supporting code,
now unused in docs (0 importers, verified by knip) and already relocated to
private/ok-marketing:
- use-is-in-view / use-prefers-reduced-motion scroll hooks (deleted)
- CodexBrandIcon / CodexBrandMonoIcon (plain CodexIcon stays; the now-unused useId
import drops with them)
- EXAMPLE_KB_SHARE_URL share-splash constant
Completes the separation's goal of shedding the landing footprint from the
public-mirrored docs app, the source-level analog of the dead editor-dep removal.
check:drift (knip) and docs typecheck are green.
* fix(ci): make vendored dist + mirror docs build survive the main merge
- verify-core-dist: regenerate the vendored core dist. The merge pulled main's
core changes, so the committed vendored index.mjs was stale vs a fresh build.
- mirror-runnability (required check): the materialized mirror docs build threw
MicrofrontendsError because withMicrofrontends() needs a microfrontends.json,
which the mirror-exclude removes. Guard the wrapper behind an existsSync check
so the public standalone docs build is a plain Next.js app, while agents-private
(which keeps the config) still gets Microfrontends. Confirmed locally via
check:ok-mirror-runnable (materialized export builds clean).
* fix(ok-marketing): address review findings (JSON-LD, subscribe timeout, DRY)
- layout.tsx: drop the copy-pasted alternateName 'OpenKnowledge Docs' from the
marketing WebSite JSON-LD (factually wrong for the apex; SITE_NAME already names it).
- subscribe.ts: add AbortSignal.timeout(10s) to the cross-origin subscribe POST so a
hung docs zone cannot lock the form's submit state forever.
- footer.tsx: import GITHUB_URL/DISCORD_URL/X_URL from site.ts instead of re-hardcoding
them (site.ts is the single source; the merge added those exports).
- url-continuity-sweep.mjs: add .catch() so a throw mid-sweep fails loud with a non-zero
exit instead of an unhandled rejection (pre-cutover safety gate).
- instrumentation-client.ts: document why the PostHog defaults date stays '2025-11-30'
(posthog-js is override-pinned to 1.316.1 here; docs is a separate Bun workspace).
* chore(ok-marketing): address review pending-recommendations
- lint-staged + check-pre-push SUBTREES: register private/ok-marketing so staged
files route to its Biome formatter and the scoped pre-push runs its checks
(every peer subtree already had both entries).
- site.ts: document the DMG_ASSET_NAME lockstep with the docs download-links.ts
canonical source (duplicated, not imported, across the workspace boundary).
- AGENTS.md + CI.md: enumerate the new private/ok-marketing subtree and its OK
Marketing Validation workflow (AGENTS.md kept under the 38,500-byte guard).
- site.test.ts + subscribe.test.ts: cover metaDescription's four branches, the
SUBSCRIBE_ENDPOINT env override, and the abort-signal on the fetch.
* fix(ok-marketing): restore the Brand link in the marketing footer
Visual QA against prod caught that the relocated footer dropped the /brand link:
prod shows Brand, Terms of Service, Privacy; the marketing footer had only Terms
and Privacy. Add it back with the same internal/external handling as the docs
footer. /brand is served by the docs zone and Vercel Microfrontends routes it
there, so it stays a same-tab in-product link.
* test(check-pre-push): pin ok-marketing in the SUBTREES expected set
Follow-on to registering private/ok-marketing in check-pre-push.mjs SUBTREES: the
'SUBTREES contains the expected set' guard hardcodes the full list to catch
accidental additions/removals, so it must list ok-marketing too. (The pre-push
guard correctly flagged the omission.)
---------
GitOrigin-RevId: b0f3669926d09339e1a09b7983e20cef8dac2ea3
---
bun.lock | 49 +-
docs/next.config.ts | 17 +-
docs/package.json | 13 +-
docs/src/app/(home)/brand/page.tsx | 6 +-
docs/src/app/(home)/feature-item.tsx | 25 -
docs/src/app/(home)/layout.tsx | 12 -
docs/src/app/(home)/page.tsx | 50 --
docs/src/app/(home)/section.tsx | 13 -
.../(home)/sections/agent-brain-graphic.tsx | 133 ----
.../app/(home)/sections/call-to-action.tsx | 126 ----
.../src/app/(home)/sections/collaboration.tsx | 241 ------
.../app/(home)/sections/eng-specs-graphic.tsx | 241 ------
docs/src/app/(home)/sections/hero-preview.tsx | 691 ------------------
docs/src/app/(home)/sections/hero.tsx | 136 ----
.../sections/knowledge-base-graphic.tsx | 248 -------
.../sections/made-for-agents-preview.tsx | 303 --------
.../app/(home)/sections/made-for-agents.tsx | 89 ---
.../(home)/sections/own-your-knowledge.tsx | 45 --
.../app/(home)/sections/put-it-to-work.tsx | 54 --
docs/src/app/(home)/sections/rich-editing.tsx | 625 ----------------
docs/src/app/(home)/site-nav.tsx | 299 --------
.../src/app/d/[encoded]/splash-share-view.tsx | 4 +-
docs/src/app/provider.tsx | 7 -
.../(home) => components}/dot-texture.tsx | 0
.../src/{app/(home) => components}/footer.tsx | 0
docs/src/components/icons/codex.tsx | 59 +-
docs/src/components/logo-context-menu.tsx | 70 --
.../marketing-button.tsx | 0
.../ok-editor/block-type-selector.tsx | 140 ----
docs/src/components/ok-editor/bubble-menu.tsx | 169 -----
docs/src/components/ok-editor/drag-handle.tsx | 99 ---
docs/src/components/ok-editor/mode-toggle.tsx | 54 --
docs/src/components/ok-editor/ok-editor.css | 538 --------------
docs/src/components/ok-editor/ok-editor.tsx | 175 -----
.../ok-editor/preview-code-block.tsx | 90 ---
docs/src/components/ok-editor/seed.ts | 64 --
.../components/ok-editor/slash-command.tsx | 134 ----
docs/src/components/ok-editor/slash-items.tsx | 136 ----
docs/src/components/ok-editor/slash-menu.tsx | 45 --
.../components/ok-editor/source-editor.tsx | 63 --
docs/src/components/ok-icon.tsx | 61 --
.../(home) => components}/section-heading.tsx | 0
docs/src/components/slide-page.tsx | 4 +-
docs/src/components/subscribe-form.tsx | 2 +-
docs/src/components/ui/context-menu.tsx | 104 ---
docs/src/components/ui/sheet.tsx | 134 ----
docs/src/components/ui/tooltip.tsx | 53 --
docs/src/lib/brand-assets.ts | 2 -
docs/src/lib/copy-svg.ts | 5 -
docs/src/lib/site.ts | 3 -
docs/src/lib/use-is-in-view.ts | 19 -
docs/src/lib/use-prefers-reduced-motion.ts | 15 -
.../src/{middleware.test.ts => proxy.test.ts} | 6 +-
docs/src/{middleware.ts => proxy.ts} | 2 +-
54 files changed, 63 insertions(+), 5610 deletions(-)
delete mode 100644 docs/src/app/(home)/feature-item.tsx
delete mode 100644 docs/src/app/(home)/layout.tsx
delete mode 100644 docs/src/app/(home)/page.tsx
delete mode 100644 docs/src/app/(home)/section.tsx
delete mode 100644 docs/src/app/(home)/sections/agent-brain-graphic.tsx
delete mode 100644 docs/src/app/(home)/sections/call-to-action.tsx
delete mode 100644 docs/src/app/(home)/sections/collaboration.tsx
delete mode 100644 docs/src/app/(home)/sections/eng-specs-graphic.tsx
delete mode 100644 docs/src/app/(home)/sections/hero-preview.tsx
delete mode 100644 docs/src/app/(home)/sections/hero.tsx
delete mode 100644 docs/src/app/(home)/sections/knowledge-base-graphic.tsx
delete mode 100644 docs/src/app/(home)/sections/made-for-agents-preview.tsx
delete mode 100644 docs/src/app/(home)/sections/made-for-agents.tsx
delete mode 100644 docs/src/app/(home)/sections/own-your-knowledge.tsx
delete mode 100644 docs/src/app/(home)/sections/put-it-to-work.tsx
delete mode 100644 docs/src/app/(home)/sections/rich-editing.tsx
delete mode 100644 docs/src/app/(home)/site-nav.tsx
rename docs/src/{app/(home) => components}/dot-texture.tsx (100%)
rename docs/src/{app/(home) => components}/footer.tsx (100%)
delete mode 100644 docs/src/components/logo-context-menu.tsx
rename docs/src/{app/(home) => components}/marketing-button.tsx (100%)
delete mode 100644 docs/src/components/ok-editor/block-type-selector.tsx
delete mode 100644 docs/src/components/ok-editor/bubble-menu.tsx
delete mode 100644 docs/src/components/ok-editor/drag-handle.tsx
delete mode 100644 docs/src/components/ok-editor/mode-toggle.tsx
delete mode 100644 docs/src/components/ok-editor/ok-editor.css
delete mode 100644 docs/src/components/ok-editor/ok-editor.tsx
delete mode 100644 docs/src/components/ok-editor/preview-code-block.tsx
delete mode 100644 docs/src/components/ok-editor/seed.ts
delete mode 100644 docs/src/components/ok-editor/slash-command.tsx
delete mode 100644 docs/src/components/ok-editor/slash-items.tsx
delete mode 100644 docs/src/components/ok-editor/slash-menu.tsx
delete mode 100644 docs/src/components/ok-editor/source-editor.tsx
delete mode 100644 docs/src/components/ok-icon.tsx
rename docs/src/{app/(home) => components}/section-heading.tsx (100%)
delete mode 100644 docs/src/components/ui/context-menu.tsx
delete mode 100644 docs/src/components/ui/sheet.tsx
delete mode 100644 docs/src/components/ui/tooltip.tsx
delete mode 100644 docs/src/lib/copy-svg.ts
delete mode 100644 docs/src/lib/use-is-in-view.ts
delete mode 100644 docs/src/lib/use-prefers-reduced-motion.ts
rename docs/src/{middleware.test.ts => proxy.test.ts} (94%)
rename docs/src/{middleware.ts => proxy.ts} (90%)
diff --git a/bun.lock b/bun.lock
index d7b4bfc89..b899f4e4f 100644
--- a/bun.lock
+++ b/bun.lock
@@ -21,23 +21,12 @@
"name": "@inkeep/open-knowledge-docs",
"version": "0.0.8",
"dependencies": {
- "@codemirror/commands": "^6.10.3",
- "@codemirror/lang-markdown": "^6.5.0",
- "@codemirror/language": "^6.12.3",
- "@codemirror/state": "^6.6.0",
- "@codemirror/view": "^6.41.0",
- "@floating-ui/dom": "^1.7.6",
"@hookform/resolvers": "^5.4.0",
"@inkeep/cxkit-react": "^0.5.117",
"@inkeep/open-knowledge-core": "workspace:*",
"@radix-ui/react-popover": "^1.1.17",
- "@tiptap/core": "^3.22.3",
- "@tiptap/extension-drag-handle": "3.22.3",
- "@tiptap/extensions": "^3.22.3",
- "@tiptap/pm": "^3.22.3",
- "@tiptap/react": "^3.22.3",
- "@tiptap/suggestion": "^3.22.3",
"@types/mdx": "^2.0.13",
+ "@vercel/microfrontends": "^2.3.6",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"fumadocs-core": "~16.1.0",
@@ -1138,7 +1127,7 @@
"@napi-rs/wasm-tools-win32-x64-msvc": ["@napi-rs/wasm-tools-win32-x64-msvc@1.0.1", "", { "os": "win32", "cpu": "x64" }, "sha512-rEAf05nol3e3eei2sRButmgXP+6ATgm0/38MKhz9Isne82T4rPIMYsCIFj0kOisaGeVwoi2fnm7O9oWp5YVnYQ=="],
- "@next/env": ["@next/env@16.2.3", "", {}, "sha512-ZWXyj4uNu4GCWQw9cjRxWlbD+33mcDszIo9iQxFnBX3Wmgq9ulaSJcl6VhuWx5pCWqqD+9W6Wfz7N0lM5lYPMA=="],
+ "@next/env": ["@next/env@16.0.10", "", {}, "sha512-8tuaQkyDVgeONQ1MeT9Mkk8pQmZapMKFh5B+OrFUlG3rVmYTXcXlBetBgTurKXGaIZvkoqRT9JL5K3phXcgang=="],
"@next/swc-darwin-arm64": ["@next/swc-darwin-arm64@16.2.3", "", { "os": "darwin", "cpu": "arm64" }, "sha512-u37KDKTKQ+OQLvY+z7SNXixwo4Q2/IAJFDzU1fYe66IbCE51aDSAzkNDkWmLN0yjTUh4BKBd+hb69jYn6qqqSg=="],
@@ -1902,6 +1891,8 @@
"@types/markdown-it": ["@types/markdown-it@14.1.2", "", { "dependencies": { "@types/linkify-it": "^5", "@types/mdurl": "^2" } }, "sha512-promo4eFwuiW+TfGxhi+0x3czqTYJkG8qB17ZUJiVF10Xm7NLVRSLUsfRTU/6h1e24VvRnXCx+hG7li58lkzog=="],
+ "@types/md5": ["@types/md5@2.3.6", "", {}, "sha512-WD69gNXtRBnpknfZcb4TRQ0XJQbUPZcai/Qdhmka3sxUR3Et8NrXoeAoknG/LghYHTf4ve795rInVYHBTQdNVA=="],
+
"@types/mdast": ["@types/mdast@4.0.4", "", { "dependencies": { "@types/unist": "*" } }, "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA=="],
"@types/mdurl": ["@types/mdurl@2.0.0", "", {}, "sha512-RGdgjQUZba5p6QEFAVx2OGb8rQDL/cPRG7GiedRzMcJ1tYnUANBncjbSB1NRGwbvjcPeikRABz2nshyPk1bhWg=="],
@@ -1968,6 +1959,8 @@
"@upsetjs/venn.js": ["@upsetjs/venn.js@2.0.0", "", { "optionalDependencies": { "d3-selection": "^3.0.0", "d3-transition": "^3.0.1" } }, "sha512-WbBhLrooyePuQ1VZxrJjtLvTc4NVfpOyKx0sKqioq9bX1C1m7Jgykkn8gLrtwumBioXIqam8DLxp88Adbue6Hw=="],
+ "@vercel/microfrontends": ["@vercel/microfrontends@2.3.6", "", { "dependencies": { "@next/env": "16.0.10", "@types/md5": "^2.3.5", "ajv": "^8.17.1", "commander": "^12.1.0", "cookie": "1.0.2", "fast-glob": "^3.3.2", "http-proxy": "^1.18.1", "jsonc-parser": "^3.3.1", "md5": "^2.3.0", "nanoid": "^3.3.9", "path-to-regexp": "6.3.0", "semver": "^7.7.2" }, "peerDependencies": { "@sveltejs/kit": ">=1", "@vercel/analytics": ">=1.5.0", "@vercel/speed-insights": ">=1.2.0", "next": ">=13", "react": ">=17.0.0", "react-dom": ">=17.0.0", "vite": ">=5" }, "optionalPeers": ["@sveltejs/kit", "@vercel/analytics", "@vercel/speed-insights", "next", "react", "react-dom", "vite"], "bin": { "microfrontends": "cli/index.cjs" } }, "sha512-iMgZp5wmNWMeFO8Sg4BlzshjsjbiXfnIOOGwcFWWb+90nrySy6YV0fgXxj2ZubDGFa6BwWD/Mh/fKKXr4I+iuQ=="],
+
"@vimeo/player": ["@vimeo/player@2.30.4", "", { "dependencies": { "native-promise-only": "0.8.1", "weakmap-polyfill": "2.0.4" } }, "sha512-M8m1UAhJSb+KCWuXDLWHViwj+3YY/0ogwFquRfMHs9e9LYjXT9iB7n+sOCKwUusbiXuU2HKmXx+FEGHtYZfUSg=="],
"@vitejs/plugin-react": ["@vitejs/plugin-react@6.0.1", "", { "dependencies": { "@rolldown/pluginutils": "1.0.0-rc.7" }, "peerDependencies": { "@rolldown/plugin-babel": "^0.1.7 || ^0.2.0", "babel-plugin-react-compiler": "^1.0.0", "vite": "^8.0.0" }, "optionalPeers": ["@rolldown/plugin-babel", "babel-plugin-react-compiler"] }, "sha512-l9X/E3cDb+xY3SWzlG1MOGt2usfEHGMNIaegaUGFsLkb3RCn/k8/TOXBcab+OndDI4TBtktT8/9BwwW8Vi9KUQ=="],
@@ -2212,6 +2205,8 @@
"chardet": ["chardet@2.1.1", "", {}, "sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ=="],
+ "charenc": ["charenc@0.0.2", "", {}, "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA=="],
+
"chevrotain": ["chevrotain@12.0.0", "", { "dependencies": { "@chevrotain/cst-dts-gen": "12.0.0", "@chevrotain/gast": "12.0.0", "@chevrotain/regexp-to-ast": "12.0.0", "@chevrotain/types": "12.0.0", "@chevrotain/utils": "12.0.0" } }, "sha512-csJvb+6kEiQaqo1woTdSAuOWdN0WTLIydkKrBnS+V5gZz0oqBrp4kQ35519QgK6TpBThiG3V1vNSHlIkv4AglQ=="],
"chevrotain-allstar": ["chevrotain-allstar@0.4.1", "", { "dependencies": { "lodash-es": "^4.17.21" }, "peerDependencies": { "chevrotain": "^12.0.0" } }, "sha512-PvVJm3oGqrveUVW2Vt/eZGeiAIsJszYweUcYwcskg9e+IubNYKKD+rHHem7A6XVO22eDAL+inxNIGAzZ/VIWlA=="],
@@ -2298,7 +2293,7 @@
"convert-source-map": ["convert-source-map@2.0.0", "", {}, "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="],
- "cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
+ "cookie": ["cookie@1.0.2", "", {}, "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA=="],
"cookie-signature": ["cookie-signature@1.2.2", "", {}, "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg=="],
@@ -2322,6 +2317,8 @@
"crossws": ["crossws@0.4.4", "", { "peerDependencies": { "srvx": ">=0.7.1" }, "optionalPeers": ["srvx"] }, "sha512-w6c4OdpRNnudVmcgr7brb/+/HmYjMQvYToO/oTrprTwxRUiom3LYWU1PMWuD006okbUWpII1Ea9/+kwpUfmyRg=="],
+ "crypt": ["crypt@0.0.2", "", {}, "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow=="],
+
"css-tree": ["css-tree@3.2.1", "", { "dependencies": { "mdn-data": "2.27.1", "source-map-js": "^1.2.1" } }, "sha512-X7sjQzceUhu1u7Y/ylrRZFU2FS6LRiFVp6rKLPg23y3x3c3DOKAwuXGDp+PAGjh6CSnCjYeAul8pcT8bAl+lSA=="],
"css.escape": ["css.escape@1.5.1", "", {}, "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="],
@@ -2704,6 +2701,8 @@
"float-tooltip": ["float-tooltip@1.7.5", "", { "dependencies": { "d3-selection": "2 - 3", "kapsule": "^1.16", "preact": "10" } }, "sha512-/kXzuDnnBqyyWyhDMH7+PfP8J/oXiAavGzcRxASOMRHFuReDtofizLLJsf7nnDLAfEaMW4pVWaXrAjtnglpEkg=="],
+ "follow-redirects": ["follow-redirects@1.16.0", "", { "peerDependencies": { "debug": "*" }, "optionalPeers": ["debug"] }, "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw=="],
+
"for-each": ["for-each@0.3.5", "", { "dependencies": { "is-callable": "^1.2.7" } }, "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg=="],
"force-graph": ["force-graph@1.51.2", "", { "dependencies": { "@tweenjs/tween.js": "18 - 25", "accessor-fn": "1", "bezier-js": "3 - 6", "canvas-color-tracker": "^1.3", "d3-array": "1 - 3", "d3-drag": "2 - 3", "d3-force-3d": "2 - 3", "d3-scale": "1 - 4", "d3-scale-chromatic": "1 - 3", "d3-selection": "2 - 3", "d3-zoom": "2 - 3", "float-tooltip": "^1.7", "index-array-by": "1", "kapsule": "^1.16", "lodash-es": "4" } }, "sha512-zZNdMqx8qIQGurgnbgYIUsdXxSfvhfRSIdncsKGv/twUOZpwCsk9hPHmdjdcme1+epATgb41G0rkIGHJ0Wydng=="],
@@ -2880,6 +2879,8 @@
"http-errors": ["http-errors@2.0.1", "", { "dependencies": { "depd": "~2.0.0", "inherits": "~2.0.4", "setprototypeof": "~1.2.0", "statuses": "~2.0.2", "toidentifier": "~1.0.1" } }, "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ=="],
+ "http-proxy": ["http-proxy@1.18.1", "", { "dependencies": { "eventemitter3": "^4.0.0", "follow-redirects": "^1.0.0", "requires-port": "^1.0.0" } }, "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ=="],
+
"http-proxy-agent": ["http-proxy-agent@7.0.2", "", { "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" } }, "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig=="],
"http2-wrapper": ["http2-wrapper@1.0.3", "", { "dependencies": { "quick-lru": "^5.1.1", "resolve-alpn": "^1.0.0" } }, "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg=="],
@@ -2948,6 +2949,8 @@
"is-boolean-object": ["is-boolean-object@1.2.2", "", { "dependencies": { "call-bound": "^1.0.3", "has-tostringtag": "^1.0.2" } }, "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A=="],
+ "is-buffer": ["is-buffer@1.1.6", "", {}, "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="],
+
"is-callable": ["is-callable@1.2.7", "", {}, "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA=="],
"is-core-module": ["is-core-module@2.16.1", "", { "dependencies": { "hasown": "^2.0.2" } }, "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w=="],
@@ -3190,6 +3193,8 @@
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
+ "md5": ["md5@2.3.0", "", { "dependencies": { "charenc": "0.0.2", "crypt": "0.0.2", "is-buffer": "~1.1.6" } }, "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g=="],
+
"mdast-util-find-and-replace": ["mdast-util-find-and-replace@3.0.2", "", { "dependencies": { "@types/mdast": "^4.0.0", "escape-string-regexp": "^5.0.0", "unist-util-is": "^6.0.0", "unist-util-visit-parents": "^6.0.0" } }, "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg=="],
"mdast-util-from-markdown": ["mdast-util-from-markdown@2.0.3", "", { "dependencies": { "@types/mdast": "^4.0.0", "@types/unist": "^3.0.0", "decode-named-character-reference": "^1.0.0", "devlop": "^1.0.0", "mdast-util-to-string": "^4.0.0", "micromark": "^4.0.0", "micromark-util-decode-numeric-character-reference": "^2.0.0", "micromark-util-decode-string": "^2.0.0", "micromark-util-normalize-identifier": "^2.0.0", "micromark-util-symbol": "^2.0.0", "micromark-util-types": "^2.0.0", "unist-util-stringify-position": "^4.0.0" } }, "sha512-W4mAWTvSlKvf8L6J+VN9yLSqQ9AOAAvHuoDAmPkz4dHf553m5gVj2ejadHJhoJmcmxEnOv6Pa8XJhpxE93kb8Q=="],
@@ -3532,7 +3537,7 @@
"path-scurry": ["path-scurry@1.11.1", "", { "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" } }, "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA=="],
- "path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
+ "path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
"path-type": ["path-type@4.0.0", "", {}, "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw=="],
@@ -3812,6 +3817,8 @@
"require-in-the-middle": ["require-in-the-middle@7.5.2", "", { "dependencies": { "debug": "^4.3.5", "module-details-from-path": "^1.0.3", "resolve": "^1.22.8" } }, "sha512-gAZ+kLqBdHarXB64XpAe2VCjB7rIRv+mU8tfRWziHRJ5umKsIHN2tLLv6EtMw7WCdP19S0ERVMldNvxYCHnhSQ=="],
+ "requires-port": ["requires-port@1.0.0", "", {}, "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ=="],
+
"resedit": ["resedit@1.7.2", "", { "dependencies": { "pe-library": "^0.4.1" } }, "sha512-vHjcY2MlAITJhC0eRD/Vv8Vlgmu9Sd3LX9zZvtGzU5ZImdTN3+d6e/4mnTyV8vEbyf1sgNIrWxhWlrys52OkEA=="],
"resend": ["resend@6.16.0", "", { "dependencies": { "postal-mime": "2.7.4", "standardwebhooks": "1.0.0" }, "peerDependencies": { "@react-email/render": "*" }, "optionalPeers": ["@react-email/render"] }, "sha512-SaKISwHtxvAxneF84Njgnzg+zdngUu1vOT/paRU1De9QF+zXQR3GnwJHSh+mpJPjUhsGD4WxYi5CfKkXMkDqwg=="],
@@ -4598,6 +4605,8 @@
"@types/yauzl/@types/node": ["@types/node@24.12.2", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g=="],
+ "@vercel/microfrontends/commander": ["commander@12.1.0", "", {}, "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA=="],
+
"ajv-keywords/ajv": ["ajv@6.14.0", "", { "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" } }, "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw=="],
"app-builder-lib/@electron/fuses": ["@electron/fuses@1.8.0", "", { "dependencies": { "chalk": "^4.1.1", "fs-extra": "^9.0.1", "minimist": "^1.2.5" }, "bin": { "electron-fuses": "dist/bin.js" } }, "sha512-zx0EIq78WlY/lBb1uXlziZmDZI4ubcCXIMJ4uGjXzZW0nS19TjSPeXPAjzzTmKQlJUZm0SbmZhPKP7tuQ1SsEw=="],
@@ -4678,6 +4687,8 @@
"estimo/nanoid": ["nanoid@5.1.5", "", { "bin": { "nanoid": "bin/nanoid.js" } }, "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw=="],
+ "express/cookie": ["cookie@0.7.2", "", {}, "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w=="],
+
"extract-zip/get-stream": ["get-stream@5.2.0", "", { "dependencies": { "pump": "^3.0.0" } }, "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA=="],
"filelist/minimatch": ["minimatch@5.1.9", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw=="],
@@ -4690,6 +4701,8 @@
"formdata-node/web-streams-polyfill": ["web-streams-polyfill@4.0.0-beta.3", "", {}, "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug=="],
+ "fumadocs-core/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
+
"fumadocs-mdx/esbuild": ["esbuild@0.27.7", "", { "optionalDependencies": { "@esbuild/aix-ppc64": "0.27.7", "@esbuild/android-arm": "0.27.7", "@esbuild/android-arm64": "0.27.7", "@esbuild/android-x64": "0.27.7", "@esbuild/darwin-arm64": "0.27.7", "@esbuild/darwin-x64": "0.27.7", "@esbuild/freebsd-arm64": "0.27.7", "@esbuild/freebsd-x64": "0.27.7", "@esbuild/linux-arm": "0.27.7", "@esbuild/linux-arm64": "0.27.7", "@esbuild/linux-ia32": "0.27.7", "@esbuild/linux-loong64": "0.27.7", "@esbuild/linux-mips64el": "0.27.7", "@esbuild/linux-ppc64": "0.27.7", "@esbuild/linux-riscv64": "0.27.7", "@esbuild/linux-s390x": "0.27.7", "@esbuild/linux-x64": "0.27.7", "@esbuild/netbsd-arm64": "0.27.7", "@esbuild/netbsd-x64": "0.27.7", "@esbuild/openbsd-arm64": "0.27.7", "@esbuild/openbsd-x64": "0.27.7", "@esbuild/openharmony-arm64": "0.27.7", "@esbuild/sunos-x64": "0.27.7", "@esbuild/win32-arm64": "0.27.7", "@esbuild/win32-ia32": "0.27.7", "@esbuild/win32-x64": "0.27.7" }, "bin": { "esbuild": "bin/esbuild" } }, "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w=="],
"fumadocs-mdx/lru-cache": ["lru-cache@11.3.3", "", {}, "sha512-JvNw9Y81y33E+BEYPr0U7omo+U9AySnsMsEiXgwT6yqd31VQWTLNQqmT4ou5eqPFUrTfIDFta2wKhB1hyohtAQ=="],
@@ -4716,6 +4729,8 @@
"hosted-git-info/lru-cache": ["lru-cache@6.0.0", "", { "dependencies": { "yallist": "^4.0.0" } }, "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA=="],
+ "http-proxy/eventemitter3": ["eventemitter3@4.0.7", "", {}, "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="],
+
"iconv-corefoundation/cli-truncate": ["cli-truncate@2.1.0", "", { "dependencies": { "slice-ansi": "^3.0.0", "string-width": "^4.2.0" } }, "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg=="],
"iconv-corefoundation/node-addon-api": ["node-addon-api@1.7.2", "", {}, "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg=="],
@@ -4752,7 +4767,7 @@
"msw/cookie": ["cookie@1.1.1", "", {}, "sha512-ei8Aos7ja0weRpFzJnEA9UHJ/7XQmqglbRwnf2ATjcB9Wq874VKH9kfjjirM6UhU2/E5fFYadylyhFldcqSidQ=="],
- "msw/path-to-regexp": ["path-to-regexp@6.3.0", "", {}, "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="],
+ "next/@next/env": ["@next/env@16.2.3", "", {}, "sha512-ZWXyj4uNu4GCWQw9cjRxWlbD+33mcDszIo9iQxFnBX3Wmgq9ulaSJcl6VhuWx5pCWqqD+9W6Wfz7N0lM5lYPMA=="],
"next/postcss": ["postcss@8.4.31", "", { "dependencies": { "nanoid": "^3.3.6", "picocolors": "^1.0.0", "source-map-js": "^1.0.2" } }, "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ=="],
@@ -4846,6 +4861,8 @@
"rolldown-plugin-dts/get-tsconfig": ["get-tsconfig@4.13.7", "", { "dependencies": { "resolve-pkg-maps": "^1.0.0" } }, "sha512-7tN6rFgBlMgpBML5j8typ92BKFi2sFQvIdpAqLA2beia5avZDrMs0FLZiM5etShWq5irVyGcGMEA1jcDaK7A/Q=="],
+ "router/path-to-regexp": ["path-to-regexp@8.4.2", "", {}, "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA=="],
+
"seek-bzip/commander": ["commander@6.2.1", "", {}, "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA=="],
"serialize-error/type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="],
diff --git a/docs/next.config.ts b/docs/next.config.ts
index 6ba8a0ac5..195cc665e 100644
--- a/docs/next.config.ts
+++ b/docs/next.config.ts
@@ -1,6 +1,13 @@
+import { existsSync } from 'node:fs';
+import { fileURLToPath } from 'node:url';
+import { withMicrofrontends } from '@vercel/microfrontends/next/config';
import { createMDX } from 'fumadocs-mdx/next';
import type { NextConfig } from 'next';
+// Routing home is `/docs` — this app serves no landing page at `/`. In the
+// production deployment the apex `/` is served by a separate app, so `/` never
+// reaches this project there; a standalone deployment should set its default
+// route to `/docs`.
const nextConfig: NextConfig = {
reactStrictMode: true,
reactCompiler: {
@@ -125,5 +132,13 @@ const nextConfig: NextConfig = {
};
const withMDX = createMDX();
+const baseConfig = withMDX(nextConfig);
-export default withMDX(nextConfig);
+// `withMicrofrontends` requires a microfrontends.json that declares this app. That
+// file names the private marketing app and is a Microfrontends deploy concern of
+// agents-private only, so it is excluded from the public mirror — the standalone
+// OSS docs build has none. Apply the wrapper only when the config is present,
+// leaving the mirror (and any standalone clone) a plain Next.js app.
+const microfrontendsConfig = fileURLToPath(new URL('./microfrontends.json', import.meta.url));
+
+export default existsSync(microfrontendsConfig) ? withMicrofrontends(baseConfig) : baseConfig;
diff --git a/docs/package.json b/docs/package.json
index 05a2f992e..94518aa0d 100644
--- a/docs/package.json
+++ b/docs/package.json
@@ -17,23 +17,12 @@
"postinstall": "fumadocs-mdx"
},
"dependencies": {
- "@codemirror/commands": "^6.10.3",
- "@codemirror/lang-markdown": "^6.5.0",
- "@codemirror/language": "^6.12.3",
- "@codemirror/state": "^6.6.0",
- "@codemirror/view": "^6.41.0",
- "@floating-ui/dom": "^1.7.6",
"@hookform/resolvers": "^5.4.0",
"@inkeep/cxkit-react": "^0.5.117",
"@inkeep/open-knowledge-core": "workspace:*",
"@radix-ui/react-popover": "^1.1.17",
- "@tiptap/core": "^3.22.3",
- "@tiptap/extension-drag-handle": "3.22.3",
- "@tiptap/extensions": "^3.22.3",
- "@tiptap/pm": "^3.22.3",
- "@tiptap/react": "^3.22.3",
- "@tiptap/suggestion": "^3.22.3",
"@types/mdx": "^2.0.13",
+ "@vercel/microfrontends": "^2.3.6",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"fumadocs-core": "~16.1.0",
diff --git a/docs/src/app/(home)/brand/page.tsx b/docs/src/app/(home)/brand/page.tsx
index 7bbd0e50f..13b70e914 100644
--- a/docs/src/app/(home)/brand/page.tsx
+++ b/docs/src/app/(home)/brand/page.tsx
@@ -1,9 +1,9 @@
import type { Metadata } from 'next';
+import { SiteFooter } from '@/components/footer';
+import { MarketingButton } from '@/components/marketing-button';
+import SectionHeading from '@/components/section-heading';
import { BRAND_ASSETS, BRAND_ROUTE, BRAND_ZIP } from '@/lib/brand-assets';
import { cn } from '@/lib/utils';
-import { SiteFooter } from '../footer';
-import { MarketingButton } from '../marketing-button';
-import SectionHeading from '../section-heading';
export const metadata: Metadata = {
title: 'Brand assets',
diff --git a/docs/src/app/(home)/feature-item.tsx b/docs/src/app/(home)/feature-item.tsx
deleted file mode 100644
index 738492bb7..000000000
--- a/docs/src/app/(home)/feature-item.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-import type { LucideIcon } from 'lucide-react';
-import { cn } from '@/lib/utils';
-
-interface FeatureItemProps {
- icon: LucideIcon;
- title: string;
- description: string;
- className?: string;
-}
-
-const FeatureItem = ({ icon: Icon, title, description, className }: FeatureItemProps) => {
- return (
-
- {/* Icon-based "agent" avatars use a white plate + thin colored ring so the
- brand mark stays legible. Text-initial "human" avatars (Alan) keep the
- solid-color treatment so the initial reads at high contrast. */}
-
-
- A
-
-
-
-
-
-
-
-
-
- );
-}
-
-function PresenceAvatar({
- tint,
- ringClass,
- children,
-}: {
- tint: EditorTint;
- ringClass: string;
- children: ReactNode;
-}) {
- return (
-
- {children}
-
- );
-}
-
-function Highlight({
- tint,
- name,
- icon: Icon,
- children,
-}: {
- tint: EditorTint;
- name: string;
- icon?: (props: SVGProps) => ReactNode;
- children: ReactNode;
-}) {
- return (
-
- {children}
- {/* Inline-block anchor at the trailing edge of the last line. Holds both
- the caret and the floating name badge so they stay glued together when
- the highlight wraps across lines (absolute positioning on the outer
- span otherwise stretches the caret across both line boxes and floats
- the badge over the first line). */}
-
-
-
- {Icon ? : null}
- {name}
-
-
-
- );
-}
-
-function CollaborationPreview() {
- return (
-
- {/* Document chrome — filename + presence */}
-
- roadmap.md
-
-
-
-
-
-
- {/* Document body */}
-
-
- Q3 Roadmap
-
-
-
- We’re bringing the whole team into{' '}
-
- one shared workspace
-
- , where people and agents edit the same files instead of losing context in a thread.
-
-
-
- This quarter
-
-
-
-
- Ship the{' '}
-
- collaborative editor
- {' '}
- for docs and spaces
-
-
-
-
- One click to share a doc, or a whole workspace
-
-
-
-
-
-
- Git-backed sync so history and ownership stay yours
-
-
-
-
- {/* Chat cell — one chat panel per agent, stacked and cross-faded. All
- share the single animation state; only the active agent's branding
- is visible, so switching agents just cross-fades the chat. */}
-
- {/* Badge sizes to content — the right edge is pinned by the parent's
- justify-between so the tool name's left edge is stable. */}
- {isPending ? (
-
-
- Calling
-
- ) : (
-
-
- Done
-
- )}
-
- {/* Line 2 — reserved at zero opacity during pending so the card doesn't jump */}
-
-
- {/* Icon-only on small screens; the full wordmark lockup on large. */}
-
-
-
-
- {animationDone ? : }
-
-
-
-
-
-
-
- {/* Fade beneath the header so document content scrolls in softly. */}
-
-
-
-
-
-
-
-
-
-
- {/* Word-count footer — pinned below the scrolling document body */}
-
- {/* Fade above the footer so document content dissolves into it. */}
-
-
- main
-
- {/* Invisible placeholder pins a min width; live stats overlay it. */}
-
-
- 76 words · 385 chars · ~97 tokens
-
-
-
-
- {AGENTS.map(({ id, label, Icon, brandColor }) => (
- // biome-ignore lint/a11y/useSemanticElements: chip is a button styled with icon+label; would force a visually-hidden input + label workaround for the same role.
-
- ))}
-
-
-
-
-
-
-
- {/* `flex-1 min-h-0` fills the card and hands a definite pixel height
- down the editor's `h-full` chain — more robust than a percentage
- chain (Safari in particular mishandles `height:100%` descendants of
- some sized boxes). Single-pane (
- {/* One shared preview: the editor + intro animation are a single
- instance, so switching agents only cross-fades the chat panel —
- the intro never replays and editor edits persist. */}
-
-
-
- );
-}
diff --git a/docs/src/app/(home)/sections/own-your-knowledge.tsx b/docs/src/app/(home)/sections/own-your-knowledge.tsx
deleted file mode 100644
index 0d75570bc..000000000
--- a/docs/src/app/(home)/sections/own-your-knowledge.tsx
+++ /dev/null
@@ -1,45 +0,0 @@
-import { GitFork, Laptop, Puzzle } from 'lucide-react';
-import FeatureItem from '../feature-item';
-import { Section } from '../section';
-import SectionHeading from '../section-heading';
-
-const features = [
- {
- icon: Laptop,
- title: 'Local-first',
- description: 'Runs on your machine; private by design.',
- },
- {
- icon: GitFork,
- title: 'Open source',
- description: 'Auditable, self-hostable, & community-built.',
- },
- {
- icon: Puzzle,
- title: 'Platform-agnostic',
- description: 'Use with any agent and any tool.',
- },
-];
-
-export function OwnYourKnowledge() {
- return (
-
-
- Own your knowledge.
-
-
- {features.map((feature) => (
-
- ))}
-
-
- );
-}
diff --git a/docs/src/app/(home)/sections/put-it-to-work.tsx b/docs/src/app/(home)/sections/put-it-to-work.tsx
deleted file mode 100644
index 8217c2a52..000000000
--- a/docs/src/app/(home)/sections/put-it-to-work.tsx
+++ /dev/null
@@ -1,54 +0,0 @@
-import type { ReactNode } from 'react';
-import { Section } from '../section';
-import SectionHeading from '../section-heading';
-import { AgentBrainGraphic } from './agent-brain-graphic';
-import { EngSpecsGraphic } from './eng-specs-graphic';
-import { KnowledgeBaseGraphic } from './knowledge-base-graphic';
-
-type UseCaseCard = {
- visual: ReactNode;
- title: string;
- description: string;
-};
-
-const cards: UseCaseCard[] = [
- {
- visual: ,
- title: 'Agent brain',
- description:
- 'A shared knowledge base your agents read from and write to — the persistent memory behind every session.',
- },
- {
- visual: ,
- title: 'Knowledge base',
- description:
- 'A living wiki for you and your team — skills, docs, notes in plain markdown, kept automatically in sync.',
- },
- {
- visual: ,
- title: 'Engineering specs',
- description:
- 'Specs, PRDs, and roadmaps living next to the code, edited by humans and coding agents in the same loop.',
- },
-];
-
-export function PutItToWork() {
- return (
-
- Put it to work.
-
- {cards.map((card) => (
-
-
- {card.visual}
-
-
-
{card.title}
-
{card.description}
-
-
- ))}
-
-
- );
-}
diff --git a/docs/src/app/(home)/sections/rich-editing.tsx b/docs/src/app/(home)/sections/rich-editing.tsx
deleted file mode 100644
index 3ecca360d..000000000
--- a/docs/src/app/(home)/sections/rich-editing.tsx
+++ /dev/null
@@ -1,625 +0,0 @@
-'use client';
-
-import {
- BookOpen,
- ChevronRight,
- Code2,
- Compass,
- Image as ImageIcon,
- Info,
- LayoutPanelTop,
- MessageSquareWarning,
- Network,
- PenLine,
- Play,
- Video as VideoIcon,
- Workflow,
-} from 'lucide-react';
-import NextImage from 'next/image';
-import { useEffect, useRef, useState } from 'react';
-import { useIsInView } from '@/lib/use-is-in-view';
-import { usePrefersReducedMotion } from '@/lib/use-prefers-reduced-motion';
-import { cn } from '@/lib/utils';
-import { Section } from '../section';
-import SectionHeading from '../section-heading';
-
-function MockupCard({ children, className }: { children: React.ReactNode; className?: string }) {
- return (
-
-
- );
-}
-
-export const PreviewCodeBlock = CodeBlockFidelity.extend({
- addNodeView() {
- return ReactNodeViewRenderer(PreviewCodeBlockView);
- },
-});
diff --git a/docs/src/components/ok-editor/seed.ts b/docs/src/components/ok-editor/seed.ts
deleted file mode 100644
index 8067d83b5..000000000
--- a/docs/src/components/ok-editor/seed.ts
+++ /dev/null
@@ -1,64 +0,0 @@
-const HERO_INTRO = `# Launch week recap
-
-v2.0 went public on June 3 — the end of a quiet QA window and the start of launch week.
-
-47 PRs merged across the cycle. Activity stayed close to zero through QA, then spiked on launch day as the announcement went live.`;
-
-const HERO_TASKS = [
- '- [ ] Shipped v2.0 to public on Jun 3',
- '- [ ] 1.4k new signups in the first 24 hours',
- '- [ ] Hit #1 on Product Hunt and front of Hacker News',
-];
-
-export const HERO_FRONTMATTER = {
- title: 'Launch week recap',
- tags: ['launch', 'retro', 'v2'],
-} as const;
-
-export const HERO_FRONTMATTER_YAML = [
- '---',
- `title: ${HERO_FRONTMATTER.title}`,
- 'tags:',
- ...HERO_FRONTMATTER.tags.map((t) => ` - ${t}`),
- '---',
-].join('\n');
-
-const HERO_CHART_HTML = `