Deploying
Ship your docs to Vercel, Cloudflare Pages, Netlify, Docker, or any static host.
Deploying
tangly build produces a static site at dist/ that drops onto any CDN. The adapter is auto-detected from your project; override with --adapter.
Adapter auto-detection
| File present in project root | Adapter selected |
|---|---|
vercel.json | vercel |
wrangler.toml or wrangler.jsonc | cloudflare |
Dockerfile | node |
| (none) | static |
Vercel
The simplest path. Add vercel.json (even empty {} is fine — its presence is the auto-detect signal) and:
bun x tangly build
vercel deploy ./distFor a git-connected project, configure the build through vercel.json:
{
"buildCommand": "bun x tangly build",
"outputDirectory": "dist",
"framework": null
}Or set the same in the Vercel dashboard:
| Setting | Value |
|---|---|
| Framework Preset | Other |
| Build Command | bun x tangly build |
| Output Directory | dist |
| Install Command | bun install |
Cloudflare Pages
bun x tangly build
bunx wrangler pages deploy ./dist --project-name my-docsFor a git-connected project, in the Cloudflare dashboard:
| Setting | Value |
|---|---|
| Framework preset | None |
| Build command | bun x tangly build |
| Build output directory | dist |
| Root directory | / (or your subdir) |
A wrangler.toml at the project root triggers auto-detect:
name = "my-docs"
compatibility_date = "2026-04-29"
[site]
bucket = "./dist"
Netlify
No special adapter — Netlify serves any static directory. Add netlify.toml:
[build]
command = "bun x tangly build"
publish = "dist"
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
Or via the dashboard with the same build command and publish directory.
Plain static (S3, R2, GitHub Pages, nginx)
bun x tangly build
# Upload dist/ to your host.
# S3:
aws s3 sync dist/ s3://my-bucket --delete
# rsync to a VPS:
rsync -avz --delete dist/ user@host:/var/www/docs/
# GitHub Pages: commit dist/ to the gh-pages branch.For nginx, point the server root at dist/:
server {
listen 80;
server_name docs.example.com;
root /var/www/docs;
index index.html;
location / {
try_files $uri $uri/index.html =404;
}
}
Docker
Drop a Dockerfile to trigger the node adapter (still static today):
FROM oven/bun:1.2-alpine AS build
WORKDIR /app
COPY . .
RUN bun install --frozen-lockfile
RUN bun x tangly build
FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80
nginx.conf:
server {
listen 80;
root /usr/share/nginx/html;
location / {
try_files $uri $uri/index.html =404;
}
}
Build and run:
docker build -t my-docs .
docker run -p 8080:80 my-docsGitHub Pages
name: Deploy docs
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: oven-sh/setup-bun@v2
- run: bun install --frozen-lockfile
- run: bun x tangly build --base /REPO-NAME
- uses: actions/upload-pages-artifact@v3
with:
path: dist
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- id: deployment
uses: actions/deploy-pages@v4The --base flag is required when serving under https://USER.github.io/REPO/.
Subpath hosting
Deploy under /docs instead of the host root:
bun x tangly build --base /docsEvery internal link, asset URL, sitemap entry, llms.txt URL, and Pagefind result is prefixed with the base. See Hosting docs at a subpath for the five common strategies — building into a parent site’s public/, edge rewrites on Vercel/Netlify/Cloudflare, nginx reverse proxy, and GitHub Pages project repos.
What gets built
dist/
- index.html redirects to first nav page
- introduction/index.html
- introduction.md raw source for AI agents
guides/<slug>/index.htmlguides/<slug>.mdimages/ copied verbatim from project root
- …
logo/
- …
public/
- …
pagefind/ search index
- …
- sitemap.xml
- robots.txt
- llms.txt for AI crawlers
- llms-full.txt
Drafts (draft: true in frontmatter) are excluded. noindex: true pages are emitted but excluded from sitemap.xml, llms.txt, llms-full.txt, the per-page .md files, and the Pagefind index.
Markdown for agents
Tangly emits a raw-Markdown twin of every page (<slug>.md alongside <slug>/index.html) so coding assistants can fetch source instead of rendered HTML — ~10× token reduction. Works on any static host with no extra config: append .md to any URL and you get the source.
For same-URL content negotiation (Accept: text/markdown returns Markdown, browsers still get HTML), add a one-line CDN rewrite — see Markdown for agents for Vercel, Cloudflare, and Netlify recipes.
Pre-deploy checklist
bun x tangly check --strict # exit 0 means clean
bun x tangly build
bun x tangly preview # smoke test in browserCI: drop the same three commands into your pipeline. tangly check --strict --json plays well with annotation scripts.