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
2 changes: 2 additions & 0 deletions apps/docs/content/docs/api-reference/getting-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Sim Cloud uses `https://www.sim.ai`, with API paths under `/api/v2`. There is no

Download the [OpenAPI 3.1 specification](/openapi.json) for client generation, request validation, and API tooling.

Official SDKs wrap these calls: [TypeScript](/api-reference/typescript) (`bun add simstudio-ts-sdk`) and [Python](/api-reference/python) (`pip install simstudio-sdk`). The [CLI](/cli) (`bun add -g sim`) runs workflows and manages resources from a terminal.

## Run a deployed workflow [#quick-start]

<Steps>
Expand Down
4 changes: 4 additions & 0 deletions apps/docs/lib/redirects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ const PATH_REDIRECTS: DocsRedirect[] = [
permanent: true,
},
{ source: '/api-reference', destination: '/api-reference/getting-started', permanent: true },
// sdks/* folded into api-reference/
{ source: '/sdks', destination: '/api-reference/getting-started', permanent: true },
{ source: '/sdks/typescript', destination: '/api-reference/typescript', permanent: true },
{ source: '/sdks/python', destination: '/api-reference/python', permanent: true },
// building-agents/agents merged into the building-agents overview
{ source: '/building-agents/agents', destination: '/agents', permanent: true },
// form deployment removed
Expand Down
16 changes: 7 additions & 9 deletions apps/sim/app/(landing)/components/hero/hero.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { INTEGRATION_COUNT_LABEL } from '@sim/deployment-config/integration-claims'
import { cn } from '@sim/emcn'
import { HeroAnnouncementChip } from '@/app/(landing)/components/hero/components/hero-announcement-chip'
import { LandingHeroHeader } from '@/app/(landing)/components/hero/components/hero-header'
import { HeroPlatformStage } from '@/app/(landing)/components/hero/components/hero-platform-stage'
import {
HOME_HERO_HEADING,
HOME_HERO_SUMMARY,
} from '@/app/(landing)/components/home-structured-data'
import {
HOME_INSET,
LANDING_CONTENT_WIDTH,
Expand Down Expand Up @@ -30,12 +33,7 @@ export function Hero() {
LANDING_GUTTER
)}
>
<p className='sr-only'>
Sim is the open-source AI workspace where teams build, deploy, and manage AI agents for
their organization. Connect {INTEGRATION_COUNT_LABEL} integrations and every major LLM, then
govern access, spend, data, and deployment from one place. Build visually, conversationally,
or with code, and run Sim in your own cloud.
</p>
<p className='sr-only'>{HOME_HERO_SUMMARY}</p>

<div className={HOME_INSET}>
<LandingHeroHeader
Expand All @@ -44,9 +42,9 @@ export function Hero() {
eyebrow={<HeroAnnouncementChip />}
heading={
<>
Build and govern
{HOME_HERO_HEADING[0]}
<br />
every AI agent in one place
{HOME_HERO_HEADING[1]}
</>
}
description='Build, deploy, and manage AI agents with central control over access, spend, and data.'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,42 @@ export const HOME_PAGE_DESCRIPTION = `Sim is the open-source AI workspace where
*/
export const HOME_PAGE_TITLE = 'The AI Workspace | Build, Distribute & Govern AI Agents | Sim'

/** The hero's `<h1>`, one entry per rendered line. */
export const HOME_HERO_HEADING = ['Build and govern', 'every AI agent in one place'] as const

/**
* The hero's summary paragraph, shared with the homepage's Markdown representation (`/index.md`).
*/
export const HOME_HERO_SUMMARY = `Sim is the open-source AI workspace where teams build, deploy, and manage AI agents for their organization. Connect ${INTEGRATION_COUNT_LABEL} integrations and every major LLM, then govern access, spend, data, and deployment from one place. Build visually, conversationally, or with code, and run Sim in your own cloud.`

/**
* The product's feature claims, shared by the JSON-LD `featureList` below and the homepage's
* Markdown representation (`/index.md`).
*/
export const HOME_FEATURES = [
'AI workspace for teams',
'Chat: build and manage agents in natural language',
'Visual workflow builder',
'CLI access for coding agents and terminal workflows',
`${INTEGRATION_COUNT_LABEL} integrations`,
'LLM orchestration (OpenAI, Anthropic, Google, xAI, Mistral, Perplexity)',
'Knowledge base creation',
'Table creation',
'Document creation',
'API access',
'Custom functions',
'Scheduled workflows',
'Event triggers',
'Permission groups for model, integration, and tool access',
'Organization and per-member spend limits',
'Usage analytics by workspace and member',
'Agent deployment as chat, API, or MCP with SSO, email, or password access',
'Single sign-on with domain verification',
'Audit records and run tracing',
'Configurable data retention',
'Self-hosting with Docker or Kubernetes',
] as const

const HOME_JSON_LD = {
'@context': 'https://schema.org',
'@graph': [
Expand Down Expand Up @@ -68,29 +104,7 @@ const HOME_JSON_LD = {
browserRequirements: 'Requires a modern browser with JavaScript enabled',
installUrl: `${SITE_URL}/signup`,
publisher: { '@id': `${SITE_URL}#organization` },
featureList: [
'AI workspace for teams',
'Chat: build and manage agents in natural language',
'Visual workflow builder',
'CLI access for coding agents and terminal workflows',
`${INTEGRATION_COUNT_LABEL} integrations`,
'LLM orchestration (OpenAI, Anthropic, Google, xAI, Mistral, Perplexity)',
'Knowledge base creation',
'Table creation',
'Document creation',
'API access',
'Custom functions',
'Scheduled workflows',
'Event triggers',
'Permission groups for model, integration, and tool access',
'Organization and per-member spend limits',
'Usage analytics by workspace and member',
'Agent deployment as chat, API, or MCP with SSO, email, or password access',
'Single sign-on with domain verification',
'Audit records and run tracing',
'Configurable data retention',
'Self-hosting with Docker or Kubernetes',
],
featureList: HOME_FEATURES,
},
{
'@type': 'SoftwareSourceCode',
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1,8 @@
export { HOME_PAGE_DESCRIPTION, HOME_PAGE_TITLE, HomeStructuredData } from './home-structured-data'
export {
HOME_FEATURES,
HOME_HERO_HEADING,
HOME_HERO_SUMMARY,
HOME_PAGE_DESCRIPTION,
HOME_PAGE_TITLE,
HomeStructuredData,
} from './home-structured-data'
3 changes: 2 additions & 1 deletion apps/sim/app/(landing)/page.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { Metadata } from 'next'
import { SITE_URL } from '@/lib/core/utils/urls'
import { SITE_URL, toSiteUrl } from '@/lib/core/utils/urls'
import {
HOME_PAGE_DESCRIPTION,
HOME_PAGE_TITLE,
Expand Down Expand Up @@ -54,6 +54,7 @@ export const metadata: Metadata = {
},
alternates: {
canonical: SITE_URL,
types: { 'text/markdown': toSiteUrl('/index.md') },
languages: {
'en-US': SITE_URL,
'x-default': SITE_URL,
Expand Down
79 changes: 79 additions & 0 deletions apps/sim/app/index.md/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import { SITE_URL } from '@/lib/core/utils/urls'
import { DOCS_URL } from '@/lib/help-links'
import {
HOME_FEATURES,
HOME_HERO_HEADING,
HOME_HERO_SUMMARY,
HOME_PAGE_DESCRIPTION,
} from '@/app/(landing)/components/home-structured-data'
import { PLATFORM_MENU } from '@/app/(landing)/components/navbar/components/nav-menu-chip'
import {
DOCS_LINE,
GITHUB_LINE,
linkLine,
markdownResponse,
navMenuLines,
PRICING_LINE,
SITEMAP_LINE,
SOLUTION_LINES,
section,
} from '@/app/llms.txt/llms'

export const dynamic = 'force-static'
export const revalidate = 3600

/**
* The homepage as Markdown. `next.config.ts` rewrites `/` here when `Accept` asks for
* `text/markdown`, so this body is also served at `/`. It is `no-store` so a cache that ignores
* `Vary` can never hand it to a browser; at worst such a cache serves the HTML to a Markdown
* client.
*/
export async function GET() {
const response = markdownResponse(
[
`# Sim: ${HOME_HERO_HEADING.join(' ')}`,
`> ${HOME_PAGE_DESCRIPTION}`,
HOME_HERO_SUMMARY,
section('Get started', [
linkLine('Sign up', '/signup', 'Create a free account'),
PRICING_LINE,
DOCS_LINE,
GITHUB_LINE,
]),
section('Build with code', [
linkLine(
'API quickstart',
`${DOCS_URL}/api-reference/getting-started`,
'Create an API key and run a deployed workflow'
),
linkLine(
'TypeScript SDK',
`${DOCS_URL}/api-reference/typescript`,
'`bun add simstudio-ts-sdk`'
),
linkLine('Python SDK', `${DOCS_URL}/api-reference/python`, '`pip install simstudio-sdk`'),
linkLine('CLI', `${DOCS_URL}/cli`, '`bun add -g sim`'),
linkLine('MCP server', `${DOCS_URL}/mcp/overview`, 'Connect an AI app to Sim'),
]),
section(
'What teams do in Sim',
HOME_FEATURES.map((feature) => `- ${feature}`)
),
section('Platform', navMenuLines(PLATFORM_MENU)),
section('Solutions', SOLUTION_LINES),
section('More', [
linkLine('llms.txt', '/llms.txt', 'An index of every public page'),
linkLine(
'llms-full.txt',
'/llms-full.txt',
'Full text of the library, customer stories, and comparisons'
),
SITEMAP_LINE,
]),
],
revalidate
)
response.headers.set('Cache-Control', 'no-store')
response.headers.set('Link', `<${SITE_URL}>; rel="canonical"`)
return response
}
15 changes: 15 additions & 0 deletions apps/sim/app/llms.txt/llms.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { INTEGRATION_REACH } from '@sim/deployment-config/integration-claims'
import { SITE_URL, toSiteUrl } from '@/lib/core/utils/urls'
import { DOCS_URL } from '@/lib/help-links'
import type { NavMenu } from '@/app/(landing)/components/navbar/components/nav-menu-chip'
import { COMPLIANCE_PAGE_DESCRIPTION } from '@/app/(landing)/solutions/compliance/compliance'
import { ENGINEERING_PAGE_DESCRIPTION } from '@/app/(landing)/solutions/engineering/engineering'
Expand Down Expand Up @@ -36,6 +37,20 @@ const SOLUTIONS = [
{ title: 'AI agents for sales', path: '/solutions/sales', description: SALES_PAGE_DESCRIPTION },
] as const

/** Link lines both `/llms.txt` and the homepage's Markdown (`/index.md`) list. */
export const PRICING_LINE = linkLine('Pricing', '/pricing', 'Free, Pro, Max, and Enterprise plans')
export const DOCS_LINE = linkLine('Documentation', DOCS_URL, 'Guides, SDKs, and API reference')
export const GITHUB_LINE = linkLine(
'GitHub',
'https://github.com/simstudioai/sim',
'Open-source codebase'
)
export const SITEMAP_LINE = linkLine(
'Sitemap',
'/sitemap.xml',
'Every public URL, including each integration and model'
)

/** One llms.txt entry per `/solutions/*` page. */
export const SOLUTION_LINES = SOLUTIONS.map((s) => linkLine(s.title, s.path, s.description))

Expand Down
16 changes: 8 additions & 8 deletions apps/sim/app/llms.txt/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,14 @@ import { ALL_COMPETITORS } from '@/app/(landing)/comparisons/utils'
import { PLATFORM_MENU } from '@/app/(landing)/components/navbar/components/nav-menu-chip'
import { MODEL_PROVIDERS_WITH_CATALOGS } from '@/app/(landing)/models/utils'
import {
DOCS_LINE,
GITHUB_LINE,
LLMS_HEADER,
linkLine,
markdownResponse,
navMenuLines,
PRICING_LINE,
SITEMAP_LINE,
SOLUTION_LINES,
section,
} from '@/app/llms.txt/llms'
Expand Down Expand Up @@ -44,7 +48,7 @@ export async function GET() {
section('Platform', [
linkLine('Home', '/', 'Product overview and primary entry point'),
...navMenuLines(PLATFORM_MENU),
linkLine('Pricing', '/pricing', 'Free, Pro, Max, and Enterprise plans'),
PRICING_LINE,
]),
section('Solutions', SOLUTION_LINES),
section(
Expand Down Expand Up @@ -98,24 +102,20 @@ export async function GET() {
`${DOCS_URL}/llms-full.txt`,
'Full text of the Sim documentation'
),
linkLine('Documentation', DOCS_URL, 'Guides, SDKs, and API reference'),
DOCS_LINE,
]),
section('Blog', [
linkLine('Blog', '/blog', 'Announcements, engineering deep dives, and product context'),
...blogPosts.map((p) => linkLine(p.title, p.canonical, p.description)),
]),
section('Optional', [
linkLine('Changelog', '/changelog', 'Product updates and release notes'),
linkLine('GitHub', 'https://github.com/simstudioai/sim', 'Open-source codebase'),
GITHUB_LINE,
linkLine('Community Slack', SLACK_COMMUNITY_URL, 'Community workspace'),
linkLine('Terms of Service', '/terms'),
linkLine('Privacy Policy', '/privacy'),
linkLine('Cookie Policy', '/cookie-policy'),
linkLine(
'Sitemap',
'/sitemap.xml',
'Every public URL, including each integration and model'
),
SITEMAP_LINE,
]),
],
revalidate
Expand Down
33 changes: 21 additions & 12 deletions apps/sim/next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,19 @@ import {
import { LANDING_ROUTES } from './lib/landing/routes'
import { LIBRARY_MERGED_SLUGS, LIBRARY_MOVED_BLOG_SLUGS } from './lib/library/retired-slugs'

/**
* `Accept` header patterns for Markdown negotiation. `text/markdown` must be one of the listed
* media ranges, and `q=0` (RFC 9110 §12.4.2: not acceptable) keeps the HTML page. Next anchors
* both patterns to the whole header.
*/
const ACCEPTS_MARKDOWN = '(.*,)?\\s*text/markdown\\s*([;,].*)?'
const REFUSES_MARKDOWN =
'(.*,)?\\s*text/markdown(\\s*;[^,]*?)?\\s*;\\s*q\\s*=\\s*0(\\.0{0,3})?\\s*(,.*)?'
const MARKDOWN_REQUEST = {
has: [{ type: 'header' as const, key: 'accept', value: ACCEPTS_MARKDOWN }],
missing: [{ type: 'header' as const, key: 'accept', value: REFUSES_MARKDOWN }],
}

const nextConfig: NextConfig = {
devIndicators: false,
poweredByHeader: false,
Expand Down Expand Up @@ -264,6 +277,11 @@ const nextConfig: NextConfig = {
],
async headers() {
return [
{
/** `/` answers in HTML or Markdown by `Accept` (see the `beforeFiles` rewrite). */
source: '/',
headers: [{ key: 'Vary', value: 'Accept' }],
Comment thread
waleedlatif1 marked this conversation as resolved.
},
{
// `/public`-served assets keep their path across deploys (no content
// hash), so a shorter TTL + revalidation window bounds how long a
Expand Down Expand Up @@ -669,7 +687,8 @@ const nextConfig: NextConfig = {
},
async rewrites() {
return {
beforeFiles: [],
/** `beforeFiles` so a Markdown client's `/` reaches `/index.md` ahead of the HTML page. */
beforeFiles: [{ source: '/', ...MARKDOWN_REQUEST, destination: '/index.md' }],
afterFiles: [
{
source: '/favicon.ico',
Expand All @@ -683,21 +702,11 @@ const nextConfig: NextConfig = {
/**
* Fallback rewrites run only after every page and dynamic route has failed to match, so
* this answers a Markdown client's 404 in Markdown without shadowing any real route.
* `text/markdown` must be one of the listed media ranges, and `q=0` (RFC 9110 §12.4.2:
* not acceptable) keeps the HTML page. Next anchors both patterns to the whole header.
*/
fallback: [
{
source: '/:path*',
has: [{ type: 'header', key: 'accept', value: '(.*,)?\\s*text/markdown\\s*([;,].*)?' }],
missing: [
{
type: 'header',
key: 'accept',
value:
'(.*,)?\\s*text/markdown(\\s*;[^,]*?)?\\s*;\\s*q\\s*=\\s*0(\\.0{0,3})?\\s*(,.*)?',
},
],
...MARKDOWN_REQUEST,
destination: '/markdown-not-found',
},
],
Expand Down
Loading
Loading