A multilingual API documentation portal built with VitePress, Vue 3 and Scalar. Guides and an interactive API reference in English, Portuguese, Spanish and French, with the reference switching to the spec for the page's language.
Live demo: https://api-docs-starter.rafactx.workers.dev
Também disponível em português: README.pt-br.md
I built this while I was a Support Engineer at Involves, where I documented a real SaaS API for customers in several countries. The stock tools gave us either nice guides or a nice API reference, never both in one place, and none of them handled one translated spec per language. This repository is that portal, rebuilt as a reusable starter.
The company's API is not included. The demo documents Shelfline Field API, a fictional retail field-execution API (stores, products, field reps, visits, surveys). Its four localized specs are generated by openapi-fixer, the companion pipeline that turns a raw generated spec into a valid, translated one.
Requires Node.js 22+ and pnpm 10 (corepack enable picks up the version pinned in package.json).
git clone https://github.com/rafactx/api-docs-starter.git
cd api-docs-starter
pnpm install
pnpm dev # http://localhost:5173
pnpm typecheck # vue-tsc
pnpm build # static site in docs/.vitepress/dist
pnpm preview # serve the build locallyCI runs pnpm typecheck and pnpm build on every pull request; the build also fails on dead links. There is no automated test suite, so UI changes are checked by hand (see CONTRIBUTING.md).
openapi-fixer (separate repo) this repo
raw spec ──► hydrate ► fix ► validate ──► docs/public/openapi.<locale>.json ──► ScalarApi.vue ──► /<lang>/api-reference
docs/<lang>/*.md ─────────────────► VitePress guides
- Guides are Markdown in
docs/{en,pt,es,fr}/. Each locale has its own nav and sidebar indocs/.vitepress/config.ts. - API reference:
docs/.vitepress/components/ScalarApi.vueembeds Scalar and picks the spec from the page language (en→openapi.en.json,pt→openapi.pt-BR.json, ...). Passspec-urlto override. - Theme: Scalar runs with
theme: 'none'and its CSS variables are mapped onto VitePress's, so the reference follows the site's colors, fonts and dark mode. The palette lives indocs/.vitepress/theme/theme.css. - Components:
ApiCard(key/description tables used in the guides),HeroSection+SpotlightBackground(landing page). - Language routing:
/(docs/index.md) sends the browser to/pt/,/es/or/fr/based on its language, and to/en/otherwise. Without JavaScript it shows a list of the four languages.
docs/
├── .vitepress/
│ ├── components/ ApiCard, HeroSection, ScalarApi, SpotlightBackground
│ ├── theme/ theme.css (palette), style.css, api-docs-responsive.css, sidebar.css, fonts.css
│ └── config.ts locales, nav, sidebars
├── public/
│ ├── openapi.{en,pt-BR,es,fr}.json one spec per language
│ ├── preview.png hero image (also used above)
│ └── favicon.svg, logo-{light,dark}.svg
├── en/ pt/ es/ fr/ intro, authentication, rate-limits, examples, pagination, errors, api-reference
└── index.md language redirect
- Replace
docs/public/openapi.*.jsonwith your specs (one per language, or point every locale at the same file inSPEC_BY_LANGinsideScalarApi.vue). - Rewrite the guide pages in
docs/<lang>/and adjust the sidebars indocs/.vitepress/config.ts. - Change the brand block in
docs/.vitepress/theme/theme.cssand the logos indocs/public/. - Take a new
docs/public/preview.png(the hero shows it inside a MacBook frame: screenshot at 1440×932 and composite it into the screen area). - Deploy: any static host works. The live demo runs on Cloudflare Workers Static Assets:
pnpm run deploybuilds the site and runswrangler deploy(config inwrangler.jsonc).
Issues and pull requests are welcome. See CONTRIBUTING.md for setup, the checks CI runs and the PR flow. Report security issues privately as described in SECURITY.md.
MIT © 2025 Rafael Teixeira
