Skip to content

Commit 3bd9976

Browse files
committed
feat(docs): rebuild documentation with the Paper design system
1 parent a0f47b1 commit 3bd9976

267 files changed

Lines changed: 306317 additions & 6161 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/docs-negotiation.yml‎

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,29 @@ jobs:
2929
http:
3030
name: docs HTTP
3131
runs-on: ${{ (vars.CI_PROVIDER == '' || vars.CI_PROVIDER == 'blacksmith') && 'blacksmith-8vcpu-ubuntu-2404' || 'linux-x64-8-core' }}
32-
timeout-minutes: 15
32+
timeout-minutes: 20
33+
services:
34+
search-postgres:
35+
image: pgvector/pgvector:pg17
36+
env:
37+
POSTGRES_USER: docs_test
38+
POSTGRES_PASSWORD: docs_test
39+
POSTGRES_DB: docs_search_test
40+
ports:
41+
- 5432:5432
42+
options: >-
43+
--health-cmd "pg_isready -U docs_test -d docs_search_test"
44+
--health-interval 5s
45+
--health-timeout 5s
46+
--health-retries 10
3347
env:
3448
DATABASE_URL: postgresql://docs_test:docs_test@127.0.0.1:1/docs_test
3549
DOCS_E2E_BASE_URL: http://127.0.0.1:3001
3650
DOCS_NEGOTIATION_REPORT_PATH: ${{ github.workspace }}/test-results/docs-negotiation.json
51+
DOCS_SEARCH_E2E_DATABASE_URL: postgresql://docs_test:docs_test@127.0.0.1:5432/docs_search_test
52+
DOCS_SEARCH_E2E_REPORT_PATH: ${{ github.workspace }}/test-results/search-postgres/report.json
53+
DOCS_INTERFACES_REPORT_PATH: ${{ github.workspace }}/test-results/docs-interfaces.json
54+
DOCS_CORPUS_REPORT_PATH: ${{ github.workspace }}/test-results/docs-corpus.json
3755
DOCS_HEADER_REPORT_PATH: ${{ github.workspace }}/test-results/docs-headers.json
3856
DOCS_NAVIGATION_REPORT_PATH: ${{ github.workspace }}/test-results/navigation/docs.json
3957
steps:
@@ -47,6 +65,8 @@ jobs:
4765
run: bun run --cwd apps/docs build
4866
- name: Verify native header edge cases
4967
run: bun run --cwd apps/docs test:headers:e2e
68+
- name: Verify isolated PostgreSQL search and index lifecycle
69+
run: bun run --cwd apps/docs test:search:postgres:e2e
5070
- name: Install browser for navigation checks
5171
run: bunx --no-install playwright install --with-deps chromium
5272
- name: Verify HTTP content negotiation
@@ -56,6 +76,8 @@ jobs:
5676
DOCS_SERVER_PID=$!
5777
trap 'kill "$DOCS_SERVER_PID" 2>/dev/null || true' EXIT
5878
bun run --cwd apps/docs test:negotiation:e2e
79+
bun run --cwd apps/docs scripts/test-docs-interfaces-e2e.ts
80+
bun run --cwd apps/docs test:corpus:e2e
5981
bun run --cwd apps/docs test:navigation:e2e
6082
- name: Upload HTTP regression report
6183
if: always()

‎.github/workflows/docs.yml‎

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,21 @@ jobs:
3030
uses: ./.github/actions/setup
3131
with:
3232
provider: ${{ vars.CI_PROVIDER }}
33-
node-version: '22'
33+
node-version: '24'
3434

3535
- name: Process docs embeddings
36-
working-directory: ./apps/sim
36+
working-directory: ./apps/docs
3737
env:
3838
DATABASE_URL: ${{ secrets.DATABASE_URL }}
3939
OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
40-
run: bun run scripts/process-docs.ts --clear
40+
run: |
41+
bun run content:generate
42+
bun run scripts/index-search.ts
43+
bun run scripts/index-search.ts --check
44+
45+
- name: Upload search index report
46+
if: always()
47+
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
48+
with:
49+
name: docs-search-index
50+
path: apps/docs/test-results/docs-search-index.json

‎apps/docs/.gitignore‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,10 @@ bun-debug.log*
3535
*.tsbuildinfo
3636
next-env.d.ts
3737

38-
# Fumadocs
39-
/.source/
38+
# Build-generated content
39+
/.content/
4040
.plans/
4141

42-
# fumadocs generates .source dirs anywhere a source.config sits
43-
**/.source/
44-
4542
# Build-generated documentation asset
4643
/public/llms-full.txt
4744
/public/.llms-full-*/

‎apps/docs/ARCHITECTURE.md‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# Sim docs architecture and authoring
2+
3+
Sim owns the content catalog, page rendering, navigation, search, and machine interfaces. Next.js prerenders public pages from that catalog. MDX, Shiki, Radix primitives, and the official MCP SDK provide focused parsing, highlighting, accessibility, and protocol implementations. No Fumadocs runtime or build dependency remains.
4+
5+
## Directory ownership
6+
7+
| Location | Responsibility |
8+
| --- | --- |
9+
| `content/docs/` | Authored MDX, navigation metadata, and generated content regions |
10+
| `scripts/compile-content.ts` | Build orchestration, validation, cache, and migration report |
11+
| `lib/content/` | Typed catalog, MDX compilation, Markdown serialization, navigation, and OpenAPI projection |
12+
| `.content/` | Ignored generated catalog and individually loadable compiled page modules |
13+
| `components/docs/` | Shared design tokens, shell, navigation, page framing, search, and API reference |
14+
| `components/ui/` | Shared reading components used by MDX and generated references |
15+
| `components/workflow-preview/` | Interactive examples and their existing graph/configuration/output data |
16+
| `lib/search/` | Common search implementation for the UI, HTTP API, and MCP |
17+
| `lib/http/`, `app/api/` | Bounded public discovery, page retrieval, and MCP adapters |
18+
| `app/[[...slug]]/page.tsx` | Thin catalog-backed page, metadata, and static-parameter adapter |
19+
| `app/design-system/` | Local component gallery, excluded from indexing |
20+
| `migration/` | Baseline inventory, Paper measurements, parity matrix, and migration results |
21+
22+
`app/` follows the App Router's file conventions. Ordinary content does not create a React route or duplicate a layout. The single catch-all route imports a shared article and shell, then loads that page's server-compiled MDX or specification reference. Promised route parameters and the Metadata API follow the installed Next.js 16 documentation.
23+
24+
## Add or change a page
25+
26+
1. Read `EDITORIAL_GUIDE.md` and the complete existing page before editing.
27+
2. Add `content/docs/<section>/<page>.mdx` with a nonempty `title` and a useful `description`. Folder `index.mdx` files fold to the folder URL. Keep existing paths and explicit `[#anchor]` aliases stable.
28+
3. Place the page in the appropriate `meta.json` order. Its optional `labels` map overrides a navigation entry's label without changing the article title. The catalog derives navigation, section-local previous/next links, discovery, and the sitemap. Do not add another page list in a consumer.
29+
4. Use ordinary Markdown and shared components. MDX imports must be named imports registered in `lib/content/compile.ts`. Unknown modules, components, metadata, duplicate routes/anchors, broken internal links, or missing local media fail compilation with source context.
30+
5. Run `bun run --cwd apps/docs content:generate`, inspect the affected page and Markdown, and run the applicable repository gates.
31+
32+
The compiler records source hashes, heading IDs, code-fence hashes and media references. Run `content:verify-migration` to enforce preservation against the frozen replacement baseline; ordinary authoring permits intentional prose and code updates. It serializes every tab and disclosure into meaningful Markdown, including workflow configuration and outputs. The introductory paragraph is hidden in HTML only when it exactly repeats the page description; machine-readable prose remains intact.
33+
34+
## Extend the component library
35+
36+
Paper is the visual source of truth. Exact board references, dimensions, tokens and intentional differences from platform components are in `migration/paper-design.md`.
37+
38+
Keep reusable chrome in `components/docs/` and reusable reading components in `components/ui/`. Export Markdown element mappings from `getMDXComponents()` rather than styling each page. A new MDX component also needs an explicit compiler allowlist entry and a meaningful serializer in `lib/content/markdown.ts`. Add its states to `/design-system` and inspect its keyboard, touch, light and dark behavior.
39+
40+
Use canonical `@sim/emcn/icons` glyphs. Docs tokens are scoped under `.docs-root`/`.docs-portal`; platform and landing styles are unchanged. The docs `cn` wrapper extends class merging for the Paper text-size tokens, so a color utility cannot erase a typography utility. Shared controls own hover, focus, pressed, disabled, loading, success, and error states.
41+
42+
Default components to server rendering. Client islands are reserved for navigation, search, tabs, disclosure reveal, clipboard, media viewing, theme choice, and interactive workflow examples. Pass rendered server content into those islands. Never import the catalog, compiler, specifications, embedding credentials, or syntax highlighter into a client component.
43+
44+
## Assets and generated references
45+
46+
Keep platform screenshots and original integration logos in `public/static/` with meaningful alternative text. Use the shared `Image` component for sizing, captions and expansion. Preserve workflow fixtures as data; the shared preview renders the actual graph, inspector, and outputs.
47+
48+
Product contracts remain authoritative for OpenAPI. Run `bun run generate:openapi` after changing their owners; the docs compiler projects operations from all registered specifications. CLI, MCP operations, integration content, and marked Agent streaming regions retain their existing generators listed in `EDITORIAL_GUIDE.md`. Do not hand-edit generated regions. Request examples are inert and never execute an API call or accept credentials.
49+
50+
The agent docs manifest continues to publish existing `.mdx` paths and its deliberate corpus exclusions. Run `bun run check:docs-manifest`, `bun run check:agent-stream-docs`, `bun run check:cli-docs`, `bun run check:openapi`, and `bun run check:docs` after relevant changes.
51+
52+
## Delivery, discovery, and performance
53+
54+
One catalog owns HTML, canonical metadata, heading citations, per-page Markdown, JSON, MCP, and sitemap identity. The aggregate `llms-full.txt` deliberately excludes generated operation bodies; individual operation Markdown is complete. See `MACHINE_ACCESS.md` for public contracts, search freshness and real-client verification.
55+
56+
Reading routes use `generateStaticParams` and reject unknown slugs. Compilation and highlighting happen before or during the production build, not in the browser. The compiler caches unchanged MDX and emits separate modules per page; it bounds aggregate catalog size. The shell receives only navigation and headings, while article content remains server rendered. Fonts are local Geist/Geist Mono assets; only the reading font is preloaded. Code and tables scroll within their own surfaces. Reduced-motion preferences suppress decorative transitions.
57+
58+
Metadata uses canonical URLs, descriptive titles, Open Graph/Twitter images, real Git modification dates when available, `TechArticle`/`BreadcrumbList` structured data, and a generated sitemap. JSON-LD is safely serialized. Robots permit public docs and machine-readable discovery. There is no special AI-ranking markup or indexing guarantee: clear HTML, preserved citations, useful text, crawlable links, and consistent public representations are the supported foundations.
59+
60+
The implementation was checked against the installed Next.js 16.4.1 docs and current official [project structure](https://nextjs.org/docs/app/getting-started/project-structure), [server/client boundaries](https://nextjs.org/docs/app/getting-started/server-and-client-components), [MDX](https://nextjs.org/docs/app/guides/mdx), and [metadata](https://nextjs.org/docs/app/getting-started/metadata-and-og-images) guidance. The monorepo's patched Next version is retained. Google's [AI search guidance](https://developers.google.com/search/docs/appearance/ai-features) remains the basis for crawlability; no separate AI-specific schema is required.
61+
62+
## Review and rollback
63+
64+
Review the migration report first, then the library gallery and representative pages, then the HTTP/browser reports. Run a production build without embedding credentials to verify the local fallback. Production search index publication remains a separate deployment step and must pass its freshness check.
65+
66+
This change preserves the docs workspace, origin, deployment identity, product generators, and content paths. Reverting the docs replacement commit and its lockfile/workflow changes restores the prior implementation; it requires no database migration or product-data rollback. Keep the PR in draft until the visual and behavior evidence has been reviewed.

‎apps/docs/MACHINE_ACCESS.md‎

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Reading Sim documentation from tools
2+
3+
Every interface uses the same compiled catalog as the rendered pages. Documentation access is public and read-only. It does not authorize access to Sim workspaces or execute product API requests.
4+
5+
## Markdown and discovery
6+
7+
Append `.md` or `.mdx` to a canonical page URL, or request that URL with `Accept: text/markdown`:
8+
9+
```sh
10+
curl https://docs.sim.ai/integrations/slack.md
11+
curl -H 'Accept: text/markdown' https://docs.sim.ai/integrations/slack
12+
```
13+
14+
The compatibility path `/llms.mdx/integrations/slack` returns the same complete Markdown. HTTP negotiation respects quality values, defaults to HTML when representations have equal quality, and preserves `Vary: Accept`. Asset and API routes do not negotiate document Markdown.
15+
16+
`/llms.txt` lists canonical pages, including API operations. `/llms-full.txt` contains authored guides and integration references; it deliberately excludes generated API operation bodies. Each API operation has its own complete Markdown representation. `/openapi.json` downloads the combined canonical OpenAPI document.
17+
18+
## JSON API
19+
20+
`GET /api/docs/pages` returns `{ pages, nextCursor, total }`. Each metadata record includes `id`, `path`, canonical `url`, title, description, section, content hash and last-modified time when available.
21+
22+
- `section`: optional `docs`, `api`, `cli`, or `mcp`.
23+
- `limit`: 1–100, default 25.
24+
- `cursor`: the previous response's `nextCursor`. Omit it for the first page.
25+
26+
Continue until `nextCursor` is `null`. Unknown cursors and invalid parameters return 400.
27+
28+
`GET /api/docs/page?path=/introduction` returns `{ page }`, containing the same metadata, headings and complete processed `markdown`. Use a canonical site-relative path. Remote URLs, traversal paths and malformed paths return 400; an unknown canonical page returns 404. Content is never silently truncated.
29+
30+
`GET /api/search?query=slack&limit=10` returns the established array of `{ id, type: "page", url, content, breadcrumbs }`. `q` is a supported alias for `query`. Queries are bounded to 256 code points; the result limit defaults to 10 and is capped at 20. Heading citations preserve explicit document anchors. An empty query returns `[]`; an actual service failure returns 503.
31+
32+
## Documentation MCP
33+
34+
Configure a remote Streamable HTTP server at `https://docs.sim.ai/api/mcp`. This endpoint is separate from Sim's workspace MCP server and `/mcp/...` documentation pages. It requires no API key.
35+
36+
The official stable MCP TypeScript SDK 2.3.1 serves the 2026-07-28 protocol and stateless compatibility for 2025-era clients. Tools:
37+
38+
| Tool | Input | Result |
39+
| --- | --- | --- |
40+
| `list_pages` | Optional `section`, `cursor`, `limit` as above | Paginated metadata and next cursor |
41+
| `get_page` | `path` | Complete Markdown and canonical metadata |
42+
| `search` | `query`, optional `limit` 1–20 | The same search results as the docs UI |
43+
44+
All three tools advertise read-only behavior. Unknown pages produce tool errors; invalid inputs produce protocol/tool validation errors. The transport rejects unapproved browser origins, unrecognized hosts and request bodies over 16 KiB. Non-browser MCP clients normally omit `Origin`. No caller-supplied URL is fetched.
45+
46+
## Search index operations
47+
48+
Basic search uses a server-only index generated atomically with the local compiled catalog and needs no database or embedding credentials. Markdown parsing and text normalization happen during content compilation; requests read precomputed chunks. The generated index is capped at 64 MiB and its catalog fingerprint is validated before serving results. When `DATABASE_URL` is present, bounded PostgreSQL keyword search can supplement it; `OPENAI_API_KEY` additionally enables vector search using the existing 1536-dimensional `text-embedding-3-small` table contract. Unavailable providers fall back to lexical results. Results with old content hashes or nonexistent heading targets are excluded.
49+
50+
From `apps/docs`:
51+
52+
```sh
53+
bun run content:generate
54+
bun scripts/index-search.ts --plan
55+
bun scripts/index-search.ts --check
56+
bun scripts/index-search.ts
57+
```
58+
59+
`--plan` is local and read-only. `--check` requires the search database and reports missing, stale or retired documents without writes. The final command publishes changed pages with database and embedding credentials: it prepares bounded embedding batches, atomically replaces one document at a time, and removes retired documents only after all page updates succeed. A failed page leaves its previous index intact. The canonical index includes authored content and generated API operations; the agent VFS retains its deliberate `academy` and `api-reference` exclusions.
60+
61+
Set `DOCS_SEARCH_REPORT_PATH` to choose the JSON report destination. The default is `test-results/docs-search-index.json`. The main-branch docs workflow runs publication and freshness checks; no production indexing is part of the docs build.
62+
63+
## Repeatable verification
64+
65+
Start a local production server, then run the existing negotiation and navigation suites and the official-client interface suite:
66+
67+
```sh
68+
DOCS_E2E_BASE_URL=http://127.0.0.1:3001 \
69+
DOCS_INTERFACES_REPORT_PATH=test-results/interfaces.json \
70+
bun scripts/test-docs-interfaces-e2e.ts
71+
```
72+
73+
The suite exercises real HTTP and the official MCP client, including discovery pagination, complete page retrieval, search consistency, invalid inputs, denied origins and byte limits. `DOCS_NEGOTIATION_REPORT_PATH` and `DOCS_NAVIGATION_REPORT_PATH` configure the companion reports. CI uploads the reports and browser screenshots on success or failure.
74+
75+
76+
The PostgreSQL suite uses a new, empty, loopback database and no embedding key. It verifies real keyword search, citation freshness, graceful database failure, repeated index publication, retirement and failed-publication preservation. It refuses databases containing existing tables. CI provisions its own `pgvector/pgvector:pg17` service and uploads the report with the other docs checks.
77+
78+
To repeat locally, create a disposable container (the command returns its ID):
79+
80+
```sh
81+
docker run --rm -d --name sim-docs-search-e2e \
82+
-e POSTGRES_USER=docs_test -e POSTGRES_PASSWORD=docs_test \
83+
-e POSTGRES_DB=docs_search_test -p 127.0.0.1:15432:5432 \
84+
pgvector/pgvector:pg17
85+
docker exec sim-docs-search-e2e pg_isready -U docs_test -d docs_search_test
86+
```
87+
88+
After PostgreSQL reports ready, run from `apps/docs`:
89+
90+
```sh
91+
DOCS_SEARCH_E2E_DATABASE_URL=postgresql://docs_test:docs_test@127.0.0.1:15432/docs_search_test \
92+
DOCS_SEARCH_E2E_REPORT_PATH=test-results/search-postgres/report.json \
93+
bun --no-env-file --conditions=react-server scripts/test-search-postgres-e2e.ts
94+
```
95+
96+
Then stop the container using the ID returned by `docker run`; `--rm` removes its temporary data. Successful vector generation and provider ranking still require separate verification with an embedding provider. The local suite makes no paid provider calls.

0 commit comments

Comments
 (0)