Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions .gitattributes
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,3 @@ Dockerfile* text eol=lf
*.ttf binary
*.eot binary
*.pdf binary

apps/docs/migration/report.json linguist-generated=true
apps/docs/migration/verification/** linguist-generated=true
4 changes: 2 additions & 2 deletions .github/workflows/docs-negotiation.yml
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ jobs:
DOCS_HEADER_REPORT_PATH: ${{ github.workspace }}/apps/docs/test-results/docs-headers.json
DOCS_NAVIGATION_REPORT_PATH: ${{ github.workspace }}/apps/docs/test-results/navigation/docs.json
DOCS_GENERATORS_REPORT_PATH: ${{ github.workspace }}/apps/docs/test-results/generators/report.json
DOCS_MIGRATION_REPORT_PATH: ${{ github.workspace }}/apps/docs/test-results/migration.json
DOCS_COMPATIBILITY_REPORT_PATH: ${{ github.workspace }}/apps/docs/test-results/compatibility.json
DOCS_SAMPLES_REPORT_PATH: ${{ github.workspace }}/apps/docs/test-results/samples/report.json
DOCS_SAMPLES_SYNTAX_LANGUAGES: javascript,python,bash,go,java,csharp
DOCS_SAMPLES_HTTP_BASE_URL: http://127.0.0.1:3001
Expand All @@ -195,7 +195,7 @@ jobs:
run: bun run --cwd apps/docs scripts/test-generators-e2e.ts
- name: Verify preserved routes, anchors and examples
if: always() && steps.build.outcome == 'success'
run: bun run --cwd apps/docs content:verify-migration
run: bun run --cwd apps/docs content:verify-compatibility
- name: Verify native header edge cases
if: always() && steps.build.outcome == 'success'
run: bun run --cwd apps/docs test:headers:e2e
Expand Down
18 changes: 10 additions & 8 deletions apps/docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Sim owns the content catalog, page rendering, navigation, search, and machine in
| Location | Responsibility |
| --- | --- |
| `content/docs/` | Authored MDX, navigation metadata, and generated content regions |
| `scripts/compile-content.ts` | Build orchestration, validation, cache, and migration report |
| `scripts/compile-content.ts` | Build orchestration, validation, cache, and compatibility verification |
| `lib/content/` | Typed catalog, MDX compilation, Markdown serialization, navigation, and OpenAPI projection |
| `.content/` | Ignored generated catalog and individually loadable compiled page modules |
| `components/docs/` | Shared design tokens, shell, navigation, page framing, search, and API reference |
Expand All @@ -17,7 +17,7 @@ Sim owns the content catalog, page rendering, navigation, search, and machine in
| `lib/http/`, `app/api/` | Bounded public discovery, page retrieval, and MCP adapters |
| `app/[[...slug]]/page.tsx` | Thin catalog-backed page, metadata, and static-parameter adapter |
| `app/design-system/` | Local component gallery, excluded from indexing |
| `migration/` | Baseline inventory, design-system specification, parity matrix, and migration results |
| `scripts/fixtures/content-baseline.json` | Frozen compatibility inventory for public routes, anchors, examples, and assets |

`app/` follows the App Router's file conventions. The root layout owns the persistent shell: navbar, sidebar, footer, search, and mobile navigation. Client navigation reads the current pathname without remounting the sidebar's scroll container. Only navigation metadata is shared with the client; document bodies and the complete catalog stay on the server. The single catch-all route loads that page's server-compiled MDX or specification reference into the shared article and page frame, which owns its responsive outline. Ordinary content does not create a React route or duplicate a layout. Promised route parameters and the Metadata API follow the installed Next.js 16 documentation.

Expand All @@ -29,11 +29,11 @@ Sim owns the content catalog, page rendering, navigation, search, and machine in
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.
5. Run `bun run --cwd apps/docs content:generate`, inspect the affected page and Markdown, and run the applicable repository gates.

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 and regenerate `migration/report.json`. Ordinary builds validate current content without loading the historical inventory or rewriting the migration report, allowing intentional prose and code updates. The compiler 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.
The compiler records source hashes, heading IDs, code-fence hashes and media references. Run `content:verify-compatibility` to enforce preservation against `scripts/fixtures/content-baseline.json` and write `test-results/compatibility.json` (or `DOCS_COMPATIBILITY_REPORT_PATH`). The frozen fixture retains its original source provenance and must not be regenerated from the implementation under test to silence a failure. Review intentional public-contract changes explicitly. Ordinary builds validate current content without loading this inventory or writing a compatibility report. The compiler 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.

## Extend the component library

Shared dimensions, tokens, component ownership, and intentional differences from platform components are documented in `migration/design-system.md`.
Shared dimensions, tokens, component ownership, and intentional differences from platform components are documented in `DESIGN_SYSTEM.md`.

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.

Expand All @@ -47,7 +47,9 @@ Keep platform screenshots and original integration logos in `public/static/` wit

The compiler converts local screenshot sources into Next.js static image imports after extracting their original Markdown URLs. Static imports give changed assets new content-addressed URLs. The shared image component supplies responsive sizes for each frame variant; Next serves a small set of WebP widths at quality 90 for interface text and 75 for scenery. The original loads when the media viewer opens. Backgrounds use the same hashed assets in both views. Legacy public asset URLs remain available; mutable filenames do not receive immutable caching.

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.
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. Specifications own authentication alternatives, media types, named examples, response headers, callbacks, defaults, and deprecation. Schema-derived samples are labeled as examples. Multipart examples must let the client set the boundary.

Keep existing API heading aliases (`authorization`, `parameters-path`, `parameters-query`, `parameters-header`, `parameters-cookie`, `request-body`, `response-body`, and `callbacks`) when changing the reference layout. Local JSON pointers preserve sibling properties, and recursive references remain explicit in both HTML and Markdown.

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.

Expand All @@ -65,8 +67,8 @@ The implementation was checked against the installed Next.js 16.4.1 docs and cur

## Review and rollback

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.
Review the compatibility report, library gallery, representative pages, and 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.

This change preserves the docs workspace, origin, deployment identity, product generators, and content paths. Restoring the previous docs deployment requires no schema migration or product-data rollback. Search publication changes `docs_embeddings` separately: before publishing, back up that table and record its paired docs deployment and source revision. Rollback must hold queued publishers, restore the paired deployment and index, and check freshness and citations from the restored source. The workflow does not create this backup automatically and checks out current `main`; ordinary dispatch cannot select an older publisher. Keep the PR in draft until the visual and behavior evidence has been reviewed.
Search publication changes `docs_embeddings` separately: before publishing, back up that table and record its paired docs deployment and source revision. Rollback must hold queued publishers, restore the paired deployment and index, and check freshness and citations from the restored source. The workflow does not create this backup automatically and checks out current `main`; ordinary dispatch cannot select an older publisher.

The requested move to `https://sim.ai/docs` requires a coordinated path-aware build and infrastructure cutover. See [the domain migration plan](migration/domain-move.md); the current build remains on `docs.sim.ai` until that work is verified.
The requested move to `https://sim.ai/docs` requires a coordinated path-aware build and infrastructure cutover. See [the domain migration plan](DOMAIN_MOVE.md); the current build remains on `docs.sim.ai` until that work is verified.
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ Disclosures use a 16px chevron, 8px label gap, a 38px desktop summary (44px touc
| Open navigation rows | `components/ui/cards.tsx` |
| CLI command grids | `components/ui/command-table.tsx` |
| Canonical provider marks | `components/ui/integration-icon.tsx` |
| Original workflow graph/configuration | `components/workflow-preview/workflow-preview.tsx`, `block-inspector.tsx` |
| Original workflow graph | `components/workflow-preview/workflow-preview.tsx` |
| Complete nested workflow results, copy, download | `components/workflow-preview/output-bundle.tsx` |
| Real component/state gallery | `components/docs/gallery.tsx` |

Expand Down
26 changes: 26 additions & 0 deletions apps/docs/DOMAIN_MOVE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# Moving docs to a path prefix

The site currently targets `docs.sim.ai`. A move to `sim.ai/docs` is separate infrastructure work, not completed by the docs redesign. Changing `NEXT_PUBLIC_DOCS_URL` alone is insufficient.

## Required changes

- Build Next.js with `basePath: '/docs'`; an asset prefix alone does not mount the app. Keep canonical catalog IDs such as `/introduction` independent of the public prefix.
- Centralize public URLs for native links, images, client fetches, fonts, canonicals, metadata, sitemap, Markdown, discovery, and MCP. Next links receive the configured base path; root-relative `new URL` inputs discard it.
- Route `/docs` and `/docs/*` before platform redirects and authentication. Preserve method, body, query, RSC parameters, content negotiation, and response headers. Use a stable upstream alias distinct from the redirected old hostname to avoid loops.
- Strip platform cookies and authorization before forwarding to public docs; do not relay upstream `Set-Cookie` headers.
- Update platform/landing consumers and search citations together. Retain agent VFS identities and `.mdx` compatibility; reuse vectors when only citation URLs change.
- Advertise the prefixed sitemap in the destination origin's root `robots.txt`; a nested robots file does not govern the origin.

## Verify before cutover

Run corpus, assets, navigation, content negotiation, search, and official MCP-client suites through the actual prefixed routing layer. The existing harnesses use root-relative paths and do not by themselves prove prefix support.

Verify HTML, Markdown, JSON, discovery, static assets, optimizer images, fonts, RSC navigation, direct fragments, unknown-page 404s, and MCP POST requests. Exercise mixed Accept values and both request orders to rule out representation-cache contamination. Every public URL must contain exactly one prefix.

Only then redirect the old hostname with a path/query-preserving 308 and verify existing client methods, bodies, and browser fragment inheritance. Do not redirect the upstream alias. No routing cutover or rollback rehearsal is implied by repository CI.

## Rollback

Record the source revision, docs deployment, routing revision, upstream alias, and a restorable search-index backup before cutover. Hold publishers while restoring paired routing, deployment, and index state; repeat citation and credential-isolation checks.

A 308 may be cached. Keep a known-good build available at the new destination for clients retaining the redirect; redirecting the new destination back can create a loop. Rehearse rollback in isolation before changing production routing. See [search publication operations](MACHINE_ACCESS.md#search-index-operations).
8 changes: 8 additions & 0 deletions apps/docs/MACHINE_ACCESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,11 @@ bun run test:search:postgres:e2e
```

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.

## Release verification and rollback

Repository CI proves the exercised HTTP, browser, generator, database, and deterministic provider contracts. It does not establish real-provider relevance, production CDN cache separation, field performance, native Safari behavior, or screen-reader usability. Verify those boundaries against the intended release; historical redesign measurements are retained in Git rather than treated as current readiness evidence.

Before publishing, independently verify that the serving docs deployment matches the publisher source and record a restorable index backup. The manual workflow records that attestation but does not make the backup. On rollback, hold queued publishers, restore the paired docs deployment and index, then check Markdown, search reads, and citations with the matching source. A legacy deployment cannot be certified by a freshness checker it did not ship. Historical rollback requires a separately reviewed procedure because ordinary publication dispatch targets current `main`.

The planned path-prefix move has its own [cutover and rollback requirements](DOMAIN_MOVE.md). Do not infer that it is complete from the redesign's successful CI.
2 changes: 1 addition & 1 deletion apps/docs/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Sim documentation

The documentation site uses Next.js, a build-time MDX content catalog, and the shared Sim docs component library. Read the [editorial guide](EDITORIAL_GUIDE.md) before changing copy or page organization. The [architecture and authoring guide](migration/content.md) explains content ownership, reusable components, assets, and generated references. The [copy audit](COPY_AUDIT.md) records the complete page inventory, accuracy corrections, and validation.
The documentation site uses Next.js, a build-time MDX content catalog, and the shared Sim docs component library. Read the [editorial guide](EDITORIAL_GUIDE.md) before changing copy or page organization. The [architecture and authoring guide](ARCHITECTURE.md) explains content ownership, reusable components, assets, and generated references. The [copy audit](COPY_AUDIT.md) records the complete page inventory, accuracy corrections, and validation.

## Develop

Expand Down
50 changes: 50 additions & 0 deletions apps/docs/components/ui/lightbox.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
'use client'

import type { ReactNode } from 'react'
import * as Dialog from '@radix-ui/react-dialog'
import { X } from '@sim/emcn/icons'
import { cn } from '@/components/docs/classnames'
import { docsControlClass, docsDialogClass } from '@/components/docs/primitives'

interface LightboxProps {
trigger: ReactNode
title: string
description: string
children: ReactNode
open?: boolean
onOpenChange?: (open: boolean) => void
}

/** Shared modal geometry and keyboard behavior for documentation media. */
export function Lightbox({
trigger,
title,
description,
children,
open,
onOpenChange,
}: LightboxProps) {
return (
<Dialog.Root open={open} onOpenChange={onOpenChange}>
<Dialog.Trigger asChild>{trigger}</Dialog.Trigger>
<Dialog.Portal>
<Dialog.Overlay className='docs-portal fixed inset-0 z-50 bg-[var(--docs-media-scrim)] backdrop-blur-[var(--docs-backdrop-blur)]' />
<Dialog.Content
className={cn(
docsDialogClass,
'fixed inset-3 z-50 flex flex-col overflow-hidden p-4 sm:inset-8'
)}
>
<div className='flex shrink-0 items-center justify-between gap-4 pb-3'>
<Dialog.Title className='text-docs-table'>{title}</Dialog.Title>
<Dialog.Close className={docsControlClass} aria-label='Close media viewer'>
<X className='size-4' />
</Dialog.Close>
</div>
<Dialog.Description className='sr-only'>{description}</Dialog.Description>
{children}
</Dialog.Content>
</Dialog.Portal>
</Dialog.Root>
)
}
Loading
Loading