This file provides guidance to Claude Code when working with this repository.
This is the official documentation repository for Coolify, an open-source self-hosting platform. The documentation is built with Fumadocs MDX, TanStack Start, React, Vite, and Bun, and is deployed at https://coolify.io/docs.
The Coolify application source can be found at https://github.com/coollabsio/coolify for reference and testing.
- main: Production branch, deployed to https://coolify.io/docs/ by
.github/workflows/production-build.yml - next: Development branch, deployed to https://next.coolify.io/docs/ by
.github/workflows/staging-build.yml - Pull requests must target
next, notmain.enforce-pr-standards.ymlretargets non-maintainer PRs tonextautomatically. - Weekly release cycle merges
nextintomain.
- Fumadocs MDX/UI/Core - Documentation content, layout, search, and MDX pipeline
- Fumadocs OpenAPI - API reference rendered from
config/openapi.json - TanStack Start / React 19 - Application runtime and prerendering
- Vite - Development server and production build
- Tailwind CSS 4 - Styling
- TypeScript - Type checking
- Bun - Package manager and script runner
- Plausible - Analytics
# Install dependencies
bun install
# Regenerate the service catalog (src/generated/services.json + content/docs/services/all.mdx)
bun run generate:services
# Regenerate the CLI command reference from github.com/coollabsio/coolify-cli
bun run generate:cli-reference
# Refresh config/openapi.json from the Coolify repository
bun run generate:openapi
# Run development server
bun run dev
# Build static production output
bun run build
# Type-check the Fumadocs source and app
bun run types:check
# Preview production build
bun run previewbun run dev and bun run build run generate:cli-reference, generate:openapi, and generate:services before starting Vite. bun run types:check runs generate:services, fumadocs-mdx, and tsc --noEmit.
generate:openapi rewrites config/openapi.json on every dev or build run. Only commit that file when you intend to update the API reference.
Do not run bun run generate:content. scripts/generate-fumadocs-content.mjs is the one-time migration script from the old VitePress docs/ folder, which no longer exists.
content/docs/ # Documentation source: MDX pages and meta.json sidebar files
content/docs/services/ # One-click service pages; all.mdx is generated
content/docs/cli/command-reference/commands/ # Generated CLI reference
public/ # Public assets served under the /docs base path
public/images/ # Documentation images, grouped by section
templates/ # Page templates (blank, guide, service, troubleshooting)
src/ # React/TanStack Start application
src/components/docs/ # MDX components (registered in mdx.tsx)
src/routes/ # App routes, including llms.txt, llms-full.txt and search
src/generated/services.json # Generated service directory data
config/site.shared.ts # Shared site metadata and docs base path
config/openapi.json # Coolify OpenAPI spec for the API reference
scripts/ # Generators, link checker, and postbuild script
nginx/ # Nginx config and redirects
atlas.json # Atlas devkit config (bun run dev:atlas)
content/docs/ is the source of truth for documentation. Edit MDX files there directly.
- Pages are
.mdxfiles incontent/docs/. Start new pages from the matching file intemplates/. - Sidebar order and section separators come from the
meta.jsonfile in each folder. Add new pages to the relevantmeta.json.
- Store images in
public/images/[section]/. - Reference them as
/docs/images/...in content. - Use the
ZoomImageMDX component for screenshots and logos.ZoomableImageis a legacy alias for the same component. - Keep meaningful alt text for screenshots and diagrams.
- Frontmatter should include
titleand usuallydescription. - Use the
<Callout type="...">component for callouts. Supported types areinfo,warning,error,success, andidea. VitePress:::containers are no longer supported. - Other available components include
Steps/Step,Tabs/Tab,ScreenshotTabs,Cards,Accordions, and theCool*components insrc/components/docs/. - Internal links should point to stable docs paths without the base path, for example
/applicationsor/services/postgresql. - Avoid raw HTML unless it is already supported by the MDX runtime.
Service pages live in content/docs/services/. scripts/generate-service-list.mjs reads their frontmatter into src/generated/services.json, and scripts/generate-services-page.mjs writes content/docs/services/all.mdx. Both files are generated: run bun run generate:services and commit the result instead of editing them by hand.
Service frontmatter:
---
title: "Buzz"
description: "Short description shown in the service catalog."
category: "Messaging"
icon: "/docs/images/services/buzz-logo.svg"
# disabled: true # hide from the catalog but keep the page
---When adding, renaming, or disabling services, update:
| File | Purpose |
|---|---|
content/docs/services/{slug}.mdx |
Service documentation |
public/images/services/ |
Service logo and screenshots |
nginx/redirects.conf |
Redirects for renamed or removed paths |
The current SEO and generated social-image pipeline reads title and description. Existing nested og metadata and frontmatter image fields do not override it.
Service filenames should use kebab-case lowercase and match the service slug. Use a category that already exists in all.mdx so the catalog doesn't get duplicate headings.
VITE_SITE_URL=https://coolify.io/docs/
VITE_ANALYTICS_DOMAIN=coolify.io/docs
VITE_PLAUSIBLE_SCRIPT_URL=https://analytics.coollabs.io/js/script.tagged-events.jsOptional: VITE_PLAUSIBLE_DOMAIN and VITE_PLAUSIBLE_API_HOST override the Plausible domain and API host, and COOLIFY_OPENAPI_URL changes the source of generate:openapi.
The Dockerfile builds the Fumadocs/TanStack app with Bun and copies .output/public into the Nginx image. Nginx serves the static site from /usr/share/nginx/html, preserving /docs/... URLs.
Build output includes:
.output/public/docs-manifest.json,sitemap.xml, androbots.txt(written byscripts/postbuild.ts).output/public/docs/llms.txtandllms-full.txt(prerendered fromsrc/routes/).output/public/docs/images/,docs/brand/, anddocs/site.webmanifest(copied byscripts/postbuild.ts)- Open Graph images for every page (rendered by
scripts/postbuild.ts)
Custom Nginx config lives in nginx/nginx.conf and redirect rules live in nginx/redirects.conf.
Production and next.coolify.io strip the /docs prefix before the request reaches Nginx, so write every redirect as location ~ ^(?:/docs)?/old/path/?$ { return 301 "/docs/new/path"; }. Run bun run check:redirects -- --base origin/next before opening a PR that renames or removes pages. It fails when a page that exists on next has no redirect, when a legacy URL in scripts/fixtures/legacy-urls.txt dead-ends, or when a rule loops or shadows a real page. The Check redirects workflow runs the same check on pull requests.
| Issue | Solution |
|---|---|
| Build fails in MDX | Open the content/docs/ file named in the error and check its frontmatter and component syntax |
| Service not listed | Check the page's frontmatter in content/docs/services/, then run bun run generate:services |
| Image missing | Check the asset in public/images/ and the /docs/images/... path in the page |
| Broken renamed page | Add a redirect in nginx/redirects.conf, update links in content/docs/, and run bun run check:redirects -- --base origin/next. Run node scripts/check-links.js <docs-url> against a running site to find broken links |
- The documentation can lag behind Coolify releases; check the Coolify source for behavior-sensitive claims.
src/generated/services.json,content/docs/services/all.mdx, and the CLI command reference are generated. Regenerate them rather than editing them by hand.- Keep redirects stable because existing docs URLs are indexed and linked externally.