Skip to content
duxt
v0.9.0 released

Versioned docs, from the repositories you already have

duxt is a Nuxt layer: extend it and your docs/ folder becomes a site, with theme, search, API reference and llms.txt included. Point it at other repositories, or at tags of the same one, and each becomes a version.

line of config
1
locales shipped
7
licensed, open source
MIT

Live demo

http://localhost/getting-started
Open

Setup

One line, and the folder is a site

duxt is a Nuxt layer, so extending it brings the theme, the pages, the components and the build steps at once, and leaves every one of them replaceable.

  • No generator and nothing to eject: your repository keeps its own files.
  • Override a component by putting your own at the same path.
  • Builds to a static site: deploy it anywhere Nuxt goes.
Installation
export default defineNuxtConfig({
  extends: ['@kirchdev/duxt']
})
export default defineAppConfig({
  duxt: {
    title: 'Acme',
    // The folder you already write in.
    sources: [{ path: 'docs' }]
  }
})

Sources

Several repositories, several versions, one list

A source is a repository and the releases, tags or branches to publish from it. duxt turns the list into one collection per version and repo, and into the URL prefixes that keep them apart. Decided at build time, so nothing is resolved while a reader waits.

  • Cloning, private-repo auth and caching are Content v3’s own, not a rebuild.
  • A single source needs no prefix at all: a segment with one value distinguishes nothing.
  • The switcher stays on the page you are reading, and says when it does not exist there.
URLs and versions
sources: [
  // The repository you are standing in.
  { path: 'docs' },

  // Another one: retain the newest patch in every minor line.
  {
    repo: 'acme/api',
    path: 'docs',
    releases: { select: 'minor' },
    refs: [{ branch: 'main', status: 'upcoming' }]
  }
]
# What the build publishes from the list beside this.

/guides/deploying          # this repository, no prefix
/api/guides/retries        # acme/api at the newest selected release
/api/main/guides/retries   # the branch, marked "upcoming"
/api/v1.4.0/guides/retries # another retained minor line

Generated reference

Reference from the artefacts you already ship

OpenAPI documents become operation and schema pages, Bruno collections become request pages and downloads, and tfplugindocs trees become provider-aware references. All remain ordinary Content collections for search, versions and machine readers.

  • OpenAPI supplies operations, schemas, examples and security models.
  • Bruno preserves request folders, docs and variables, and offers a redacted download.
  • tfplugindocs keeps provider categories and headings instead of flattening its Markdown tree.
How generated reference works
openapi: 3.1.0
info:
  title: Acme API
  version: 2.4.0
paths:
  /widgets:
    get:
      operationId: listWidgets
meta {
  name: List widgets
  type: http
  seq: 1
}

get {
  url: {{baseUrl}}/widgets
  body: none
  auth: inherit
}
---
page_title: acme_widget Resource
subcategory: Widgets
---

# acme_widget (Resource)

Creates and manages an Acme widget.

Try it

A client that sends the real request

Every operation page carries a client. Fill in the parameters, edit the body against its schema, send it from your own browser, and read the response beside the sample that would have produced it.

  • Seven samples out of the box, twelve shipped, or one of your own, rewritten as you type.
  • The body editor is CodeMirror, loaded on demand: a page without an endpoint downloads none of it.
  • Your token stays in your browser: there is no server in this to send it to.
How the client works

Send a request

Authentication

What you type here stays in this tab, is never stored, and is sent only to the server you chose.

The request is sent by your browser, straight to that server.

In your stack

The same request, in your own language

Not an example of a request like the one above, but that request. The server you picked, the token you typed and the body you edited, rewritten on every keystroke into whichever client you are going to paste it in.

  • One component, so the sample and the button can never disagree.
  • Add your own with `requestSamples`, or drop the ones your readers do not use.
Request samples

Request sample

curl '/demo/echo' \
  -H 'Content-Type: application/json' \
  -H 'Authorization: Bearer demo-token' \
  -d '{
  "reference": "HB-1042",
  "mode": "sea"
}'

Machine readers

Written for the model reading it too

The same content in the shapes a machine reads: an index at llms.txt, the default-version corpus at llms-full.txt, every page as Markdown, and an MCP route for listing versions and pages, searching and reading.

  • The text routes can be prerendered with the pages; MCP serves the same collections at runtime.
  • Every page has a "copy as Markdown", and a link that opens it in an assistant.
  • The MCP route serves the same collections the site queries: one source, two readers.
Machine readers
http://localhost/llms.txt
Open

Features