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: 1 addition & 1 deletion .github/workflows/generate-toolkit-docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ jobs:
OPENAI_MODEL: ${{ secrets.OPENAI_MODEL || 'gpt-4o-mini' }}

- name: Sync toolkit sidebar navigation
run: pnpm dlx tsx toolkit-docs-generator/scripts/sync-toolkit-sidebar.ts
run: pnpm dlx tsx toolkit-docs-generator/scripts/sync-toolkit-sidebar.ts --prune --verbose

- name: Check for changes
id: check-changes
Expand Down
59 changes: 59 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
# Arcade Docs

Arcade documentation site built with Next.js + Nextra (App Router), using pnpm as the package manager. Content is authored in MDX with custom React components. Check `package.json` for current framework versions.

## Commands

```bash
pnpm dev # Local dev server (port 3000)
pnpm build # Full production build (toolkit-markdown → next build → pagefind)
pnpm lint # Lint with Ultracite (Biome-based)
pnpm format # Auto-format with Ultracite
pnpm test # Run all Vitest tests
pnpm test:watch # Watch mode
pnpm vale:check # Check docs against style rules
```

Run a single test:
```bash
pnpm vitest run tests/broken-link-check.test.ts
```

## Architecture

- **`app/en/`** — English docs content (MDX pages). Nextra file-based routing with `_meta.tsx` for navigation order. i18n handled via `middleware.ts`.
- **`app/_components/`** — Shared React components (tabbed code blocks, toolkit docs, callouts, etc.).
- **`app/_lib/`** — Data-fetching utilities (toolkit catalog, slug generation, static params).
- **`app/api/`** — API routes (markdown export, toolkit-data, glossary).
- **`toolkit-docs-generator/`** — Generates MCP toolkit documentation from server metadata JSON files in `toolkit-docs-generator/data/toolkits/`.
- **`scripts/`** — Build/CI scripts (clean markdown export, Vale style fixes, redirect checking, pagefind indexing, i18n sync).
- **`tests/`** — Vitest tests (broken links, internal link validation, sitemap, smoke tests).
- **`lib/`** — Next.js utilities (glossary remark plugin, llmstxt plugin).
- **`next.config.ts`** — Contains ~138 redirect rules.

## Content Authoring

Follow **STYLEGUIDE.md** for writing standards and **AUTHORING.md** for formatting conventions. Key points:

- Sentence case for headings. Active voice. Direct tone.
- Product is always "Arcade" (never abbreviated, never "Arcade AI").
- Use "Arcade Engine" (capitalized), "MCP server" (lowercase server), "tool" (lowercase), "auth provider".
- Code snippets: 4 spaces for Python, 2 spaces for other languages.
- Run `pnpm vale:check` before submitting docs changes.

## Pre-commit Hooks

Husky runs on commit: Vale style checks on `.md/.mdx`, `_meta.tsx` key validation, redirect checking for deleted/renamed pages, internal link updates, and Ultracite formatting. You MUST fix any issues surfaced by the pre-commit hooks. NEVER bypass hooks with `--no-verify` or similar flags.

## Key Config Files

- `biome.jsonc` — Linter/formatter rules (Biome via Ultracite)
- `.vale.ini` — Vale style checker config (Google style base + Arcade vocabulary)
- `.nvmrc` — Required Node version
- `tsconfig.json` — TypeScript compiler configuration
- `components.json` — shadcn/ui component config
- `postcss.config.mjs` — PostCSS/Tailwind config

## Code Quality

NEVER add suppression comments (`// @ts-ignore`, `// @ts-expect-error`, `// biome-ignore`, `eslint-disable`, `{/* prettier-ignore */}`, etc.) to bypass TypeScript or linter errors. Fix the underlying issue instead.
40 changes: 20 additions & 20 deletions app/_components/agent-framework-tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,35 +7,35 @@ export function AgentFrameworkTabs() {
<Tabs.Tab>
<div className="mt-6 grid gap-3 sm:grid-cols-2 sm:gap-4 md:gap-5 lg:grid-cols-3">
<PlatformCard
icon="/images/icons/python.svg"
link="/get-started/agent-frameworks/setup-arcade-with-your-llm-python"
name="Vanilla Python"
type="MCP Client"
icon="https://avatars.githubusercontent.com/u/170677839?s=200&v=4"
link="/en/get-started/agent-frameworks/crewai/use-arcade-tools"
name="CrewAI"
type="Agent Framework"
/>
<PlatformCard
icon="/images/icons/langchain.svg"
invertInDark
link="/guides/agent-frameworks/langchain/use-arcade-tools"
name="LangChain"
icon="https://avatars.githubusercontent.com/u/1342004?s=200&v=4"
link="/en/get-started/agent-frameworks/google-adk/setup-python"
name="Google ADK"
type="Agent Framework"
/>
<PlatformCard
icon="https://avatars.githubusercontent.com/u/170677839?s=200&v=4"
link="/guides/agent-frameworks/crewai/use-arcade-tools"
name="CrewAI"
icon="/images/icons/langchain.svg"
invertInDark
link="/en/get-started/agent-frameworks/langchain/use-arcade-with-langchain-py"
name="LangChain"
type="Agent Framework"
/>
<PlatformCard
icon="https://avatars.githubusercontent.com/u/14957082?s=200&v=4"
link="/guides/agent-frameworks/openai-agents/overview"
link="/en/get-started/agent-frameworks/openai-agents/setup-python"
name="OpenAI Agents"
type="Agent Framework"
/>
<PlatformCard
icon="https://avatars.githubusercontent.com/u/1342004?s=200&v=4"
link="/guides/agent-frameworks/google-adk/overview"
name="Google ADK"
type="Agent Framework"
icon="/images/icons/python.svg"
link="/en/get-started/agent-frameworks/setup-arcade-with-your-llm-python"
name="Vanilla Python"
type="MCP Client"
/>
</div>
</Tabs.Tab>
Expand All @@ -44,27 +44,27 @@ export function AgentFrameworkTabs() {
<PlatformCard
icon="/images/icons/langchain.svg"
invertInDark
link="/guides/agent-frameworks/langchain/use-arcade-tools"
link="/en/get-started/agent-frameworks/langchain/use-arcade-with-langchain-ts"
name="LangChain"
type="Agent Framework"
/>
<PlatformCard
icon="https://avatars.githubusercontent.com/u/1342004?s=200&v=4"
link="/guides/agent-frameworks/google-adk/overview"
link="/en/get-started/agent-frameworks/google-adk/setup-typescript"
name="Google ADK"
type="Agent Framework"
/>
<PlatformCard
icon="/images/icons/mastra.svg"
invertInDark
link="/guides/agent-frameworks/mastra/overview"
link="/en/get-started/agent-frameworks/mastra"
name="Mastra"
type="Agent Framework"
/>
<PlatformCard
icon="/images/icons/vercel.svg"
invertInDark
link="/guides/agent-frameworks/vercelai"
link="/en/get-started/agent-frameworks/vercelai"
name="Vercel AI"
type="Agent Framework"
/>
Expand Down
8 changes: 4 additions & 4 deletions app/en/references/auth-providers/figma/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ The Figma auth provider enables tools and agents to call [Figma APIs](https://de

<Callout>
Want to quickly get started with Figma in your agent or AI app? The pre-built
[Arcade Figma MCP Server](/resources/integrations/others/figma) is what you
[Arcade Figma MCP Server](/resources/integrations/development/figma) is what you
want!
</Callout>

Expand All @@ -16,13 +16,13 @@ This page describes how to use and configure Figma auth with Arcade.

This auth provider is used by:

- The [Arcade Figma MCP Server](/resources/integrations/others/figma), which provides pre-built tools for interacting with Figma
- The [Arcade Figma MCP Server](/resources/integrations/development/figma), which provides pre-built tools for interacting with Figma
- Your [app code](#using-figma-auth-in-app-code) that needs to call the Figma API
- Or, your [custom tools](#using-figma-auth-in-custom-tools) that need to call the Figma API

### Required scopes for the Figma MCP Server

If you're using the [Arcade Figma MCP Server](/resources/integrations/others/figma), you'll need to configure these scopes based on which tools you plan to use:
If you're using the [Arcade Figma MCP Server](/resources/integrations/development/figma), you'll need to configure these scopes based on which tools you plan to use:

- `file_content:read` - File structure, pages, nodes, and image exports
- `library_content:read` - Published components, styles, and component sets from files
Expand Down Expand Up @@ -288,7 +288,7 @@ const token = authResponse.context.token;

## Using Figma auth in custom tools

You can use the pre-built [Arcade Figma MCP Server](/resources/integrations/others/figma) to quickly build agents and AI apps that interact with Figma.
You can use the pre-built [Arcade Figma MCP Server](/resources/integrations/development/figma) to quickly build agents and AI apps that interact with Figma.

If the pre-built tools in the Figma MCP Server don't meet your needs, you can author your own [custom tools](/guides/create-tools/tool-basics/build-mcp-server) that interact with the Figma API.

Expand Down
3 changes: 0 additions & 3 deletions app/en/resources/integrations/_meta.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,6 @@ const meta: MetaRecord = {
"customer-support": {
title: "Customer Support",
},
others: {
title: "Others",
},
"-- Submit your Server": {
type: "separator",
title: "Submit your server",
Expand Down
13 changes: 0 additions & 13 deletions app/en/resources/integrations/others/[toolkitId]/_meta.tsx

This file was deleted.

10 changes: 0 additions & 10 deletions app/en/resources/integrations/others/[toolkitId]/page-impl.tsx

This file was deleted.

14 changes: 0 additions & 14 deletions app/en/resources/integrations/others/[toolkitId]/page.mdx

This file was deleted.

78 changes: 0 additions & 78 deletions app/en/resources/integrations/others/_meta.tsx

This file was deleted.

48 changes: 21 additions & 27 deletions middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,40 +58,27 @@ function isAIAgent(request: NextRequest): boolean {
return AI_AGENT_PATTERNS.some((pattern) => pattern.test(userAgent));
}

function parseAcceptLanguageHeader(acceptLanguage: string): string[] {
return acceptLanguage
.split(",")
.map((lang) => lang.split(";")[0].trim())
.map((lang) => {
if (lang.startsWith("es")) {
return "es";
}
if (lang.startsWith("pt")) {
return "pt-BR";
}
return lang;
});
function getPreferredLocale(_request: NextRequest): string {
// We don't currently support other translations, so always use English.
return "en";
}

function getPreferredLocale(request: NextRequest): string {
const cookieLocale = request.cookies.get("NEXT_LOCALE")?.value;
function getEnglishLocaleRedirectPath(pathname: string): string | null {
for (const locale of SUPPORTED_LOCALES) {
if (locale === "en") {
continue;
}

if (cookieLocale && SUPPORTED_LOCALES.includes(cookieLocale)) {
return cookieLocale;
}
if (pathname === `/${locale}` || pathname === `/${locale}/`) {
return "/en/home";
}

const acceptLanguage = request.headers.get("accept-language");
if (acceptLanguage) {
const languages = parseAcceptLanguageHeader(acceptLanguage);
const preferredLocale = languages.find((lang) =>
SUPPORTED_LOCALES.includes(lang)
);
if (preferredLocale) {
return preferredLocale;
if (pathname.startsWith(`/${locale}/`)) {
return `/en${pathname.slice(locale.length + 1)}`;
}
}

return "en";
return null;
}

function pathnameIsMissingLocale(pathname: string): boolean {
Expand Down Expand Up @@ -181,6 +168,13 @@ function handleContentNegotiation(
export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;

const englishLocaleRedirectPath = getEnglishLocaleRedirectPath(pathname);
if (englishLocaleRedirectPath) {
const url = request.nextUrl.clone();
url.pathname = englishLocaleRedirectPath;
return NextResponse.redirect(url);
}

const contentNegotiationResponse = handleContentNegotiation(
request,
pathname
Expand Down
6 changes: 6 additions & 0 deletions next.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,12 @@ const nextConfig: NextConfig = withLlmsTxt({
withNextra({
async redirects() {
return [
// "others" category removed — toolkits moved to proper categories
{
source: "/:locale/resources/integrations/others/:path*",
destination: "/:locale/resources/integrations",
permanent: false,
},
// Google ADK tutorial consolidation - redirect old URL to new
{
source:
Expand Down
Loading