Configuração
Cada chave sob duxt em app.config.ts — o que controla e quando é lida.
Tudo o que se segue vive sob duxt no teu app/app.config.ts. Como a
combinação funciona, e porque os arrays substituem em vez de acrescentar, está
em Configuração.
Site
| Chave | Por omissão | O que controla |
|---|---|---|
title | nenhum | O nome na barra de navegação e no título de SEO |
logo | nenhum | Um logótipo em vez do par de ícone e nome — ver abaixo |
version | nenhuma | O distintivo ao lado |
organization | nenhuma | Quem publica o site, para schema.org — ver abaixo |
locales | os sete | Que idiomas da camada este site serve |
breadcrumb | true | false retira o trilho por cima do título da página |
pageIcon | nenhum | Ícone para páginas sem um próprio — o da secção ganha |
packageManagers | pnpm, npm, yarn, bun | Que gestores um bloco de comando oferece, por essa ordem |
requestSamples | sete de doze | Que amostras de código o cliente de ensaio oferece — ver Amostras de pedido |
sampleLanguages | nenhuma | Gramáticas Shiki adicionais, para x-codeSamples numa linguagem que nenhuma amostra nomeia |
poweredBy | ligado | false retira a linha «Powered by duxt» do rodapé |
Comportamento
| Chave | Por omissão | Efeito |
|---|---|---|
copy.models | ChatGPT, Claude | Destinos pela ordem do menu; a lista substitui o padrão |
contributors.avatarUrl | template GitHub | {username} é substituído por contribuidor |
toc.depth | 3 | Título mais profundo no índice |
toc.scrollOffset | 96 | Linha de ativação sob o topo da janela |
search.fuzzy | 0.35, 3, 20 | Limiar Fuse, comprimento mínimo e limite |
search.recentPages | 5 | Páginas recentes; 0 oculta a lista |
openapi.exampleDepth | 6 | Profundidade máxima dos exemplos derivados |
openapi.schemaDepth | 8 | Profundidade máxima da árvore de schema |
shortcuts.singleCharacter | true | Teclas globais ?, [ e ]; ⌘/Ctrl+K permanece |
analytics.track | nenhum | Callback neutro quanto ao provider por interação |
export default defineAppConfig({
duxt: {
copy: {
models: [
{
label: 'O meu assistente',
icon: 'simple-icons:openai',
url: 'https://example.com/new?prompt='
}
]
},
contributors: {
avatarUrl: 'https://github.com/{username}.png?size=96'
},
toc: { depth: 4, scrollOffset: 112 },
search: {
fuzzy: { threshold: 0.3, minMatchCharLength: 3, limit: 15 },
recentPages: 8
},
openapi: { exampleDepth: 6, schemaDepth: 8 },
shortcuts: { singleCharacter: false }
}
})
As listas substituem os padrões. Uma lista copy.models vazia remove destinos
externos, não as ações de copiar e ver a fonte. search.recentPages: 0 não
guarda entradas novas. As opções fuzzy só afetam aproximações depois de uma
pesquisa Content vazia. Sem callback de analytics nada é enviado;
consentimento, provider e armazenamento pertencem ao site consumidor.
logo
| Campo | Tipo | Notas |
|---|---|---|
src | string | A marca. Sem valor fica o ícone genérico ao lado de title |
srcDark | string | Trocado por CSS sob a classe dark, não por script |
alt | texto | Recai em title |
Definir um é Dá identidade ao teu site.
organization
O nó Organization que os motores de busca e os resumos de IA leem para nomear
uma fonte. Ausente até o definires: o duxt renderiza a documentação de outros e
não adivinha de quem.
| Campo | Tipo | Notas |
|---|---|---|
name | texto | O nome de quem publica. Sem ele não se publica nada |
url | string | O site dessa entidade. Recorre a site.url |
logo | string | Absoluto, ou um caminho desde a raiz; quadrado e com 112px ou mais |
Anúncios
Um aviso para todo o site — uma versão, uma migração ou uma manutenção. Nada é renderizado nem ocupa espaço até escreveres uma entrada.
announcements: [
{
text: { 'en-GB': 'Version 2 is out.', 'pt-PT': 'A versão 2 foi lançada.' },
link: { label: 'Ler as notas', to: '/releases/v2' }
},
{
id: 'march-maintenance',
text: 'Manutenção agendada no domingo a partir das 09:00 UTC.',
placement: 'below-header',
startsAt: '2026-03-01T09:00:00Z',
endsAt: '2026-03-08T09:00:00Z'
}
],
announcementOptions: { maxVisible: 1 }
A lista é desenhada por ordem: uma versão e uma indisponibilidade são dois anúncios, e o fim de um não deve retirar o outro.
| Campo | Tipo | Notas |
|---|---|---|
text | texto | Literal, chave i18n ou registo por locale |
link | ligação | Uma ação; as restantes pertencem à página ligada |
placement | above-header, below-header ou above-content | Posição; above-header por omissão |
startsAt | string | Início; qualquer valor que Date analise |
endsAt | string | Fim |
id | string | Identidade de fecho; derivada do conteúdo e da ligação se faltar |
Onde são apresentados
| Posição | Local |
|---|---|
above-header | Largura total no topo, acima da navegação — o padrão |
below-header | Largura total sob a navegação e acima das barras laterais |
above-content | Na coluna do documento, com avisos de versão e tradução |
above-content pertence à coluna do documento, por isso aparece em páginas
de documentação e não numa landing page sem essa coluna.
announcementOptions.maxVisible limita quantos anúncios uma posição mostra
ao mesmo tempo. Um número limita cada posição, um objeto limita-as
separadamente ({ 'above-header': 1 }), e null, uma chave omitida ou a
ausência de maxVisible significa ilimitado. Fechar o aviso superior promove o
seguinte.
Quando são apresentados
startsAt e endsAt são lidos no browser contra o relógio do leitor. O
anúncio começa e termina sem deploy nem recarregar a página. A janela é
semiaberta: visível desde startsAt e até endsAt.
Escreve um offset quando o instante exato importa
(2026-03-01T09:00:00Z). Sem fuso horário usa-se a hora local do leitor. Uma
data inválida é tratada como ausente, para que um erro não esconda o aviso em
silêncio.
Fecho
Um anúncio fechado permanece fechado durante navegação, reloads e mudanças de idioma. É a sua identidade que fica guardada:
- com
id, exatamente essa string independente do locale; mudá-la volta a mostrar o anúncio a todos, - sem
id, um valor derivado de todas as variantes detextelink; mudar o texto cria um anúncio novo, reordenar as chaves de locale não.
Define id para corrigir o texto sem voltar a apresentá-lo. Os fechos vivem
apenas em localStorage; chaves de anúncios removidos são descartadas. Como o
relógio e os fechos pertencem ao browser, a faixa é desenhada depois da
hidratação.
A superfície do componente está em DuxtAnnouncements.
Navegação e ligações
Uma entrada de secção é uma ligação mais um campo próprio:
| Campo | Tipo | Notas |
|---|---|---|
pageIcon | string | Ícone para as páginas desta secção que não definam um. Prevalece sobre duxt.pageIcon; o frontmatter de uma página continua a ganhar |
Útil onde as páginas não podem levar ícone — o frontmatter de um ADR está fixo em
title, description, status e date, pelo que o registo de decisões seria
apresentado sem nenhum.
| Chave | Por omissão | O que controla |
|---|---|---|
navigation | uma entrada | Ligações da barra; uma entrada com children vira um menu |
sections | vazio | A segunda linha da barra — as partes de topo da documentação |
links | vazio | Ligações com ícone à direita da barra |
aside | só o título | title e links sob o índice |
footer | vazio | copyright e legal |
landing | uma ação | A página em / |
A maioria é entregue vazia, por duas razões diferentes. links, aside.links,
footer.legal, title, version e o texto da página inicial nomeiam um projeto
concreto — um repositório, uma comunidade, um aviso legal, um nome, uma versão
publicada, uma frase sobre o que faz — e pertencem a quem gere o site. sections nomeia as partes de
uma árvore de documentação, e a árvore é tua: quatro separadores a apontar
para nomes de pasta que a camada adivinhasse não levariam a lado nenhum.
Define-o quando a tua documentação tiver secções; até lá a linha não é
apresentada e a barra lateral mostra a árvore inteira, que é a forma certa para
documentação sem secções.
Uma linha por fonte. Uma entrada pertence à fonte sob cujo prefixo de URL
está, e a linha mostra as entradas da fonte em que o leitor se encontra — um
site com a documentação na raiz e outra coisa em /demo escreve assim uma só
lista sections, e cada área desenha a sua parte dela. Uma secção gerada por
baixo de uma área (/demo/openapi) pertence a essa área em vez de ser uma. Um site
com uma única fonte tem uma área, cada entrada está lá dentro, e a linha é
exactamente a lista tal como foi escrita.
A página inicial
A página em / desenha três faixas, e cada uma está ausente até a sua chave
estar definida.
| Chave | Por omissão | O que desenha |
|---|---|---|
badge | nenhum | A pastilha por cima do título — texto, ou um objeto de distintivo |
headline | nenhum | O h1; recai sobre title |
description | nenhuma | O parágrafo por baixo, e a meta description da página |
actions | uma, «Ler a documentação» | Os botões do bloco principal; uma ação sem to resolve para a primeira secção |
command | nenhum | Um comando de instalação copiável sob os botões |
preview | nenhum | Uma página deste site, incorporada numa janela de browser |
features | vazio | A grelha de cartões |
command é uma string simples, não texto: um comando de shell é igual em
todos os idiomas, e um traduzido por engano é um que não corre. A camada não
entrega nenhum — não sabe como se chama o teu projeto, pela mesma razão por que
links está vazio.
Não há chamada à ação final, deliberadamente. Os botões do bloco principal são a chamada; repeti-los sob uma grelha de cartões pede a um leitor acabado de chegar que decida duas vezes.
badge é entregue vazio pela mesma razão que links: uma pastilha por cima do
título diz algo sobre o estado de um projeto — «beta», «a v2 saiu» — e a camada
nada sabe sobre o estado do teu. Um texto é a forma curta; o objeto acrescenta
ícone, cor e destino.
Campo de badge | Tipo | Notas |
|---|---|---|
label | texto | Obrigatório. {version} é substituído pela version do site |
icon | string | Qualquer nome do Iconify |
variant | string | default, secondary, outline, success, destructive |
to | string | Faz de toda a pastilha uma ligação |
external | boolean | O separador novo |
badge: {
label: '{version} lançada',
icon: 'lucide:rocket',
variant: 'success',
to: 'https://github.com/acme/sdk/releases/latest',
external: true
}
preview é uma janela viva, não uma imagem. Incorpora uma página deste site
num enquadramento de browser que o leitor pode percorrer, navegar e cujo tema
pode mudar sem sair da página inicial. O enquadramento só é montado quando a
faixa entra no ecrã, e nunca durante a renderização no servidor — um iframe no
HTML inicial é um segundo carregamento completo a competir com o primeiro.
Campo de preview | Tipo | Notas |
|---|---|---|
to | string | A página a incorporar; por omissão, a primeira secção |
height | string | Qualquer comprimento CSS. Por omissão 32rem, 24rem sob sm |
src | string | Uma captura EM VEZ da página viva |
srcDark | string | Serve o modo escuro; sem ele, src serve ambos |
alt | texto | O texto alternativo da imagem e o nome acessível do enquadramento |
O enquadramento vivo carrega a aplicação uma segunda vez. Um site que prefira
não pagar isso define src e obtém a mesma janela à volta de uma imagem fixa.
Forma de uma ligação
| Campo | Tipo | Notas |
|---|---|---|
label | texto | Obrigatório |
to | string | Um caminho de documentação é localizado; um URL não |
icon | string | Qualquer nome do Iconify, p. ex. lucide:rocket |
description | texto | Mostrada num menu suspenso da barra |
external | boolean | O separador novo e a seta — nunca o roteamento |
children | DuxtLink[] | Transforma uma entrada da barra num menu suspenso |
variant | variante de botão | Só landing.actions |
Todos os campos marcados como texto aceitam um literal, uma chave i18n ou um registo por locale — ver Localização.
Fontes
| Chave | Lida em | O que controla |
|---|---|---|
sources | tempo de compilação | As fontes de documentação |
sourceOptions | tempo de compilação | Como essas fontes se tornam prefixos de URL |
versions | execução | Substitui as versões derivadas quando precisam de rótulos ou descrições |
Ambas as chaves de fonte têm uma página própria.
locales é a terceira chave de compilação: alterar qualquer uma das três exige
nova compilação.
O feed
/rss.xml está vazio até feed.path nomear uma secção:
feed: { path: '/changelog', title: 'o meu projeto — lançamentos' }
Desligado por omissão, de propósito. Um feed é uma lista de coisas que
aconteceram, e uma página de referência editada não é um acontecimento — um
site que publica cada edição como item ensina os seus leitores a cancelar a
subscrição. Os itens são ordenados pela date da própria página, recorrendo ao
último commit que lhe tocou, e só a versão predefinida de cada fonte contribui,
por isso um changelog versionado não repete cada entrada uma vez por versão.
A secção para a qual costuma apontar é um
histórico de versões, cujas páginas trazem cada uma a sua
date.
Gerado, não escrito
| Chave | Escrito por | Contém |
|---|---|---|
resolvedSources | a compilação | O manifesto: que coleção serve que prefixo |
layerVersion | a compilação | A versão do duxt, para o rodapé |
layerRepository | a compilação | O repositório do duxt, para o rodapé |
Definir qualquer um dos três à mão é sobrescrito na compilação seguinte.