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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .agents/skills/add-column-type/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ Registering the *type* is compiler-enforced. Registering its *metadata* is not,
- [ ] `migrateCellsTo` / `migrateCellsFrom` added if the stored bytes change
- [ ] New metadata keys added to `TYPE_SPECIFIC_COLUMN_KEYS` + `FOREIGN_METADATA_VERB`
- [ ] Unit tests for `coerce` / `isCompatibleWith` round-trips, verified to fail without the code
- [ ] Docs row added to `apps/docs/content/docs/en/tables/index.mdx`
- [ ] Docs row added to `apps/docs/content/docs/tables/index.mdx`

## Final Validation (Required)

Expand Down
2 changes: 1 addition & 1 deletion .agents/skills/add-integration/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ bun run deployment-config:check
bun run docs:check
```

This creates `apps/docs/content/docs/en/integrations/{service}.mdx` — one page per service carrying the block's Actions and, if it has one, its Triggers section. Never hand-edit generated pages; the only editable region is the `{/* MANUAL-CONTENT */}` block (see `scripts/README.md`).
This creates `apps/docs/content/docs/integrations/{service}.mdx` — one page per service carrying the block's Actions and, if it has one, its Triggers section. Never hand-edit generated pages; the only editable region is the `{/* MANUAL-CONTENT */}` block (see `scripts/README.md`).

The docs generator refreshes `packages/deployment-config/src/integrations.json`, and the deployment
config generator projects service-account provider IDs from that catalog plus the canonical OAuth
Expand Down
2 changes: 1 addition & 1 deletion .agents/skills/add-model/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ If the entry has `capabilities.thinking` or `capabilities.reasoningEffort`, it a

- **Anthropic-family (`anthropic`, `azure-anthropic`) thinking models MUST declare `capabilities.thinking.streamed`** (`'full' | 'summary' | 'none'`). Verify against Anthropic's current thinking-display and streaming docs: visible thinking returned by the API is summarized, including when Sim opts models whose default display is `omitted` into `display: 'summarized'` on agent-events runs, so current Claude thinking models use `'summary'`. Use `'full'` only if future official API docs explicitly guarantee raw thinking deltas. `bun run agent-stream-docs:check` (CI) fails if the field is missing.
- Other families usually omit the field and inherit the provider default in `getThinkingStreamVisibility` (Gemini/OpenAI → summaries; Bedrock/Meta → none; OpenAI-compatible vendors with documented reasoning fields → full deltas). Set it explicitly only when the model deviates from its family.
- After inserting the entry, run `bun run agent-stream-docs:generate` and commit the regenerated `apps/docs/content/docs/en/workflows/blocks/agent.mdx` — CI diffs it.
- After inserting the entry, run `bun run agent-stream-docs:generate` and commit the regenerated `apps/docs/content/docs/workflows/blocks/agent.mdx` — CI diffs it.
- Include the `streamed` value (with its source URL) in the verification report when set.

### Wrong family entirely?
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -630,7 +630,7 @@ jobs:
with:
filters: |
docs:
- 'apps/docs/content/docs/en/**'
- 'apps/docs/content/docs/**'
- 'apps/sim/scripts/process-docs.ts'
- 'apps/sim/lib/chunkers/**'

Expand Down
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ start-collector.sh

## Helm Chart Tests
helm/sim/test
i18n.cache

## Claude Code
.claude/launch.json
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type React from 'react'
import { highlight } from 'fumadocs-core/highlight'
import type { Root } from 'fumadocs-core/page-tree'
import { findNeighbour } from 'fumadocs-core/page-tree'
import type { ApiPageProps } from 'fumadocs-openapi/ui'
import { createAPIPage } from 'fumadocs-openapi/ui'
Expand All @@ -16,13 +15,11 @@ import { APIExampleSelector } from '@/components/ui/api-example-selector'
import { CodeBlock } from '@/components/ui/code-block'
import { Heading } from '@/components/ui/heading'
import { ResponseSection } from '@/components/ui/response-section'
import { i18n } from '@/lib/i18n'
import { getApiSpecContent, getAuthenticatedCodeSamples, openapi } from '@/lib/openapi'
import { simShikiOptions } from '@/lib/shiki-theme'
import { type PageData, source } from '@/lib/source'
import { DOCS_BASE_URL } from '@/lib/urls'

const SUPPORTED_LANGUAGES: Set<string> = new Set(i18n.languages)
const BASE_URL = DOCS_BASE_URL

/**
Expand All @@ -40,37 +37,6 @@ function isContentHeading(item: { url: string }): boolean {
return !ONWARD_NAV_SLUG.test(item.url)
}

const OG_LOCALE_MAP: Record<string, string> = {
en: 'en_US',
es: 'es_ES',
fr: 'fr_FR',
de: 'de_DE',
ja: 'ja_JP',
zh: 'zh_CN',
}

function resolveLangAndSlug(params: { slug?: string[]; lang: string }) {
const isValidLang = SUPPORTED_LANGUAGES.has(params.lang)
const lang = isValidLang ? params.lang : 'en'
const slug = isValidLang ? params.slug : [params.lang, ...(params.slug ?? [])]
return { lang, slug }
}

/**
* Strips a leading `/{lang}` path segment from a page URL. Unlike a naive
* `String.replace`, this only removes the locale when it is actually the
* first path segment — a plain substring replace would also match `/en`
* inside unrelated slugs (e.g. `/platform/enterprise`, `/integrations/enrich`,
* `/platform/self-hosting/environment-variables`), corrupting canonical and
* hreflang URLs for those pages.
*/
function stripLocalePrefix(url: string, lang: string): string {
const prefix = `/${lang}`
if (url === prefix) return ''
if (url.startsWith(`${prefix}/`)) return url.slice(prefix.length)
return url
}

/**
* Renders the API reference's request and response samples through the docs' own `CodeBlock`
* rather than fumadocs-openapi's built-in one, so those blocks get the emcn copy control
Expand Down Expand Up @@ -122,10 +88,9 @@ const APIPage = createAPIPage(openapi, {
},
})

export default async function Page(props: { params: Promise<{ slug?: string[]; lang: string }> }) {
const params = await props.params
const { lang, slug } = resolveLangAndSlug(params)
const page = source.getPage(slug, lang)
export default async function Page(props: { params: Promise<{ slug?: string[] }> }) {
const { slug } = await props.params
const page = source.getPage(slug)
if (!page) notFound()

const data = page.data as unknown as PageData & {
Expand All @@ -139,9 +104,7 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
const isAcademy = slug?.[0] === 'academy'
const isCli = slug?.[0] === 'cli'

const pageTreeRecord = source.pageTree as Record<string, Root>
const pageTree = pageTreeRecord[lang] ?? pageTreeRecord.en ?? Object.values(pageTreeRecord)[0]
const rawNeighbours = pageTree ? findNeighbour(pageTree, page.url) : null
const rawNeighbours = findNeighbour(source.pageTree, page.url)
// Academy, API Reference, and CLI are self-contained sections; keep prev/next
// inside the section instead of spilling into the main documentation tree.
// Match both the section's pages (`/<slug>/...`) and its index (`/<slug>`).
Expand Down Expand Up @@ -173,11 +136,6 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
let currentPath = ''

urlParts.forEach((part: string, index: number) => {
if (index === 0 && SUPPORTED_LANGUAGES.has(part)) {
currentPath = `/${part}`
return
}

currentPath += `/${part}`

const name = part
Expand Down Expand Up @@ -218,7 +176,6 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
title={data.title}
description={data.description || ''}
url={`${BASE_URL}${page.url}`}
lang={lang}
breadcrumb={breadcrumbs}
/>
<DocsPage
Expand Down Expand Up @@ -265,7 +222,6 @@ export default async function Page(props: { params: Promise<{ slug?: string[]; l
title={data.title}
description={data.description || ''}
url={`${BASE_URL}${page.url}`}
lang={lang}
breadcrumb={breadcrumbs}
/>
<DocsPage
Expand Down Expand Up @@ -336,12 +292,9 @@ export async function generateStaticParams() {
return source.generateParams()
}

export async function generateMetadata(props: {
params: Promise<{ slug?: string[]; lang: string }>
}) {
const params = await props.params
const { lang, slug } = resolveLangAndSlug(params)
const page = source.getPage(slug, lang)
export async function generateMetadata(props: { params: Promise<{ slug?: string[] }> }) {
const { slug } = await props.params
const page = source.getPage(slug)
if (!page) notFound()

const data = page.data as unknown as PageData
Expand Down Expand Up @@ -377,13 +330,7 @@ export async function generateMetadata(props: {
url: fullUrl,
siteName: 'Sim Documentation',
type: 'article',
locale: OG_LOCALE_MAP[lang] ?? 'en_US',
alternateLocale: i18n.languages.reduce<string[]>((locales, l) => {
if (l !== lang) {
locales.push(OG_LOCALE_MAP[l] ?? 'en_US')
}
return locales
}, []),
locale: 'en_US',
images: [
{
url: ogImageUrl,
Expand All @@ -406,15 +353,6 @@ export async function generateMetadata(props: {
canonical: fullUrl,
alternates: {
canonical: fullUrl,
languages: {
'x-default': `${BASE_URL}${stripLocalePrefix(page.url, lang)}`,
en: `${BASE_URL}${stripLocalePrefix(page.url, lang)}`,
es: `${BASE_URL}/es${stripLocalePrefix(page.url, lang)}`,
fr: `${BASE_URL}/fr${stripLocalePrefix(page.url, lang)}`,
de: `${BASE_URL}/de${stripLocalePrefix(page.url, lang)}`,
ja: `${BASE_URL}/ja${stripLocalePrefix(page.url, lang)}`,
zh: `${BASE_URL}/zh${stripLocalePrefix(page.url, lang)}`,
},
},
}
}
129 changes: 0 additions & 129 deletions apps/docs/app/[lang]/layout.tsx

This file was deleted.

15 changes: 7 additions & 8 deletions apps/docs/app/api/og/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const TITLE_FONT_SIZE = {
} as const
/** Average glyph width as a fraction of font size, for this weight/family — used to pack words into lines. */
const LATIN_CHAR_WIDTH_EM = 0.42
/** CJK glyphs (docs ships `ja`/`zh` locales) render near-square, roughly 2.4x a Latin glyph at this weight. */
/** CJK glyphs render near-square, roughly 2.4x a Latin glyph at this weight. */
const CJK_CHAR_WIDTH_EM = 1
const CJK_RANGE = /[\u3000-\u30ff\u3400-\u4dbf\u4e00-\u9fff\uf900-\ufaff\uff00-\uffef]/
const TITLE_BOX_WIDTH = 1020
Expand Down Expand Up @@ -58,7 +58,7 @@ function getTitleStyle(title: string): CSSProperties {
}
}

/** Sums per-character em-widths rather than counting characters, so wide CJK glyphs (docs ships `ja`/`zh`) don't under-wrap. */
/** Sums per-character em-widths rather than counting characters, so wide CJK glyphs don't under-wrap. */
function estimateWidthEm(text: string): number {
let width = 0
for (const char of text) {
Expand All @@ -69,11 +69,10 @@ function estimateWidthEm(text: string): number {

/**
* Splits a single word wider than `maxWidthEm` into character-level chunks
* that each fit. CJK titles (docs ships `ja`/`zh` locales) are often
* space-free, so a whole run can arrive as one "word" from `wrapTitleLines`'
* space-based split. Breaking mid-word is correct for CJK, where each glyph
* is independently readable; Latin words never reach this path since they
* stay under `maxWidthEm` in practice.
* that each fit. CJK titles are often space-free, so a whole run can arrive
* as one "word" from `wrapTitleLines`' space-based split. Breaking mid-word
* is correct for CJK, where each glyph is independently readable; Latin words
* never reach this path since they stay under `maxWidthEm` in practice.
*/
function splitOversizedWord(word: string, maxWidthEm: number): string[] {
const chunks: string[] = []
Expand Down Expand Up @@ -139,7 +138,7 @@ function wrapTitleLines(title: string, fontSize: number): string[] {
* last-shipped `soehne-kraftig.woff2` since Satori (`next/og`'s renderer)
* can't parse WOFF2 or variable fonts. Fetched over HTTP since the edge
* runtime has no filesystem access — served from `/static/fonts/` (not
* `/fonts/`) so it isn't intercepted by the site's i18n proxy (`proxy.ts`),
* `/fonts/`) so it isn't intercepted by the site's proxy (`proxy.ts`),
* whose matcher excludes `static` but not `fonts`.
*/
async function loadTitleFont(baseUrl: string): Promise<ArrayBuffer> {
Expand Down
Loading
Loading