npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@yagofontanez/create-seo-site

v0.6.0

Published

CLI para gerar projetos Next.js focados em SEO/GEO local a partir de um strategy.json

Downloads

504

Readme

@yagofontanez/create-seo-site

CLI para gerar rapidamente projetos web (Next.js) para clientes de agência, focados em SEO/GEO local, a partir de um strategy.json preenchido nos planejamentos de SEO feitos com o cliente.

O fluxo é:

mkdir cliente-x && cd cliente-x
npx @yagofontanez/create-seo-site init            # modo interativo
# preenche o strategy.json com o planejamento
npx @yagofontanez/create-seo-site generate --strategy ./strategy.json --out ./site
cd site && claude                              # Claude Code lê o PROMPT.md e completa o site
  1. Scaffold determinístico (init) — pergunta nome, tipo de site, paleta e estilo, copia um template Next.js pronto (design system, componentes de SEO, infra técnica) e aplica a combinação escolhida.
  2. Prompt final (generate) — valida o strategy.json e escreve um PROMPT.md dentro do projeto, juntando o prompt mestre + a estratégia.
  3. Execução — você abre o Claude Code na pasta do projeto e manda ele executar o PROMPT.md. O CLI não chama nenhuma API e não precisa de API key.

Instalação

npm install -g @yagofontanez/create-seo-site
# ou, sem instalar:
npx @yagofontanez/create-seo-site init cliente-x
# ou, em desenvolvimento local:
npm install && npm run build && npm link

O pacote instala dois comandos equivalentes: create-seo-site e o atalho seo-site. Os exemplos abaixo usam o atalho.

Comandos

init [nome-do-projeto]

Copia o template do tipo escolhido para ./<nome-do-projeto>, renomeia os dotfiles (gitignore → .gitignore, env.example → .env.example) e ajusta o name do package.json para o nome da pasta.

Rodado em um terminal, o init é interativo: pergunta o nome do projeto (texto livre), o tipo de site, a paleta (lista navegável, com as cores reais desenhadas ao lado de cada opção), o design system e se o projeto já sai dockerizado. As flags pré-selecionam a resposta — Enter aceita.

seo-site init                                     # pergunta os cinco
seo-site init cliente-exemplo                     # nome já preenchido
seo-site init cliente-exemplo -c yellow -s modern # tudo pré-selecionado
seo-site init cliente-exemplo -c yellow -s modern -y   # sem perguntar nada
seo-site init lp-campanha --type landing -y            # landing page única
seo-site init cliente-exemplo --docker -y              # já com Dockerfile + compose
? Paleta de cores do site  ↑↓ navega · Enter escolhe

 ❯ ██████ gold    editorial, premium · advocacia, contabilidade, imobiliária
   ██████ blue    confiança institucional · clínicas, TI, engenharia, financeiro
   ██████ teal    clínico limpo · odonto, estética, spa, laboratório
   ...

Fora de um TTY (CI, pipe, npx ... | tee) nada é perguntado: valem as flags e os padrões, e o nome do projeto passa a ser obrigatório.

| Opção | Padrão | Descrição | |---|---|---| | -T, --type <tipo> | completo | Tipo de site (ver tabela abaixo) | | -t, --template <nome> | do tipo | Template a ser copiado de templates/ — sobrepõe o do tipo | | -c, --color <paleta> | gold | Paleta de cores (ver tabela abaixo) | | -s, --style <estilo> | editorial | Estilo visual (ver tabela abaixo) | | -d, --docker / --no-docker | --no-docker | Gera (ou não) Dockerfile, docker-compose.yml, .dockerignore e os scripts docker:* | | -y, --yes | false | Aceita os padrões sem abrir o modo interativo | | -l, --list-designs | — | Lista tipos, paletas e estilos e sai | | -f, --force | false | Sobrescreve a pasta destino sem perguntar |

Se a pasta destino já existir e não estiver vazia, o CLI pede confirmação antes de sobrescrever (em ambiente não interativo, cancela — use --force).

Tipo, paleta ou estilo inválido aborta antes de criar qualquer arquivo.

--type — tipo de site

É a primeira escolha depois do nome, porque decide o template — e, por tabela, qual prompt mestre o generate vai usar.

| Tipo | Template | O que gera | |---|---|---| | completo | base-nextjs | Site institucional: páginas de conversão, blog com Supabase, /admin, formulário de lead, Search Console | | landing | landing-nextjs | Uma landing page só: / + política de privacidade. Sem banco, sem blog, sem painel e sem formulário — o contato sai por WhatsApp e telefone |

Os dois compartilham o mesmo design system (as 36 combinações valem para os dois), o mesmo src/lib/site.ts como fonte única de NAP e a mesma disciplina de JSON-LD, metadata, sitemap.xml, robots.txt, llms.txt e ai.txt.

Quando usar landing: campanha de tráfego pago, lançamento, um serviço único, cliente que não vai manter blog. A página inteira vive em src/app/page.tsx e o conteúdo em src/content/landing.ts; as seções viram âncoras (#servicos, #como-funciona, #faq, #onde-estamos) em vez de rotas. Continua com Pixel da Meta + CAPI e GA4, medindo o clique em WhatsApp, telefone e e-mail com deduplicação por eventID.

Quando usar completo: o cliente precisa de autoridade tópica, blog, múltiplas páginas de serviço ou captação de lead com histórico.

Trocar de tipo depois exige recriar a pasta — não é uma flag que se inverte num projeto já gerado.

--docker — projeto dockerizado

Última pergunta do modo interativo, e a única que não muda uma linha do site: decide só como ele roda. Com --docker o projeto gerado ganha

| Arquivo | Para que serve | |---|---| | Dockerfile | Multi-stage com três alvos: dev (next dev com hot reload), builder (next build) e runner (produção, servindo o output standalone) | | docker-compose.yml | Dois perfis: dev (bind mount do código, porta 3000) e prod (build da imagem + node server.js, restart: unless-stopped) | | .dockerignore | Mantém node_modules, .next, .git e .env* fora da imagem | | .env | Criado a partir do .env.example — é o arquivo que o compose lê, tanto no runtime quanto para os build args | | scripts docker:* | docker:dev, docker:build, docker:up, docker:logs, docker:down |

e o next.config.ts recebe output: "standalone" — sem isso o alvo runner não tem o que copiar.

seo-site init cliente-exemplo --docker -y
cd cliente-exemplo

npm run docker:dev    # http://localhost:3000 com hot reload
npm run docker:up     # produção em background (build + next start)
npm run docker:logs
npm run docker:down

As NEXT_PUBLIC_* são embutidas no JS durante o next build, então o compose as passa como build args (lidos do .env); mudar uma delas exige rebuild — o que o docker:up já faz. Uma seção ## Docker com esses detalhes é anexada ao README.md e ao CLAUDE.md do projeto gerado — o segundo para o Claude Code não tentar rodar o site fora do container nem remover o standalone.

Aplicar o Docker é idempotente: rodar o init --docker de novo sobre a mesma pasta não duplica a linha do next.config.ts nem a seção do README. Para dockerizar um projeto que nasceu sem Docker, o caminho é gerar um projeto novo com a flag e copiar os quatro arquivos.

Design system

O design é composto de dois eixos independentes. Qualquer paleta combina com qualquer estilo — são 9 × 4 = 36 combinações.

--color — paleta

Cada paleta define os mesmos 9 tokens de papel (ink, ink-soft, canvas, surface, accent, accent-ink, accent-lit, muted, line), então trocar de paleta não toca em nenhum componente.

| Paleta | Vibe | Segmentos típicos | |---|---|---| | gold (padrão) | editorial, premium | advocacia, contabilidade, imobiliária | | blue | confiança institucional | clínicas, TI, engenharia, financeiro | | teal | clínico limpo | odonto, estética, spa, laboratório | | green | natural, sustentável | ambiental, agro, solar, nutrição | | yellow | energia, alta visibilidade | construção, mecânica, solar, delivery | | orange | acolhedor, próximo | pet, infantil, marketing, e-commerce | | red | urgência, apetite | food, academia, automotivo, chaveiro | | purple | criativo, beleza | estética, moda, design, eventos | | slate | neutro, sóbrio | arquitetura, design, B2B premium |

As 9 paletas passam em 13 checagens de contraste WCAG cada (node scripts/check-contrast.mjs), incluindo AAA para texto de corpo.

--style — estilo visual

O estilo controla raio, sombra, par tipográfico, escala de texto e o tratamento de .eyebrow, .reticle e .prose-site.

| Estilo | Vibe | O que muda | |---|---|---| | editorial (padrão) | sério, documental | raio 2–6px, hairline entre seções, eyebrow mono com ticks de canto. Archivo + IBM Plex | | modern | SaaS, produto | raio 8–20px, sombra difusa, eyebrow em badge arredondado. Sora + Inter + JetBrains Mono | | bold | pesado, contrastado | raio 0, sombra dura offset, eyebrow em etiqueta chapada, títulos em caixa alta. Archivo Black + Inter | | soft | orgânico, acolhedor | raio 10–28px, sem bordas, display serifado, blockquote com fundo tingido. Fraunces + Nunito Sans |

Galeria de designs

Quem escolhe no escuro? O terminal mostra um quadradinho de cor e a palavra "editorial". Para ver as 36 combinações de verdade, abra a galeria de designs — as combinações renderizadas com o CSS exato que o projeto recebe (hero, cards, CTA e formulário), com filtro por paleta e estilo:

  • Arquivo gerado: docs/gallery.html
  • Regenerar: npm run build:gallery (lê design/, nunca desatualiza)

Trocar o design depois do init

O globals.css e o fonts.ts gerados são arquivos comuns do projeto — edite à vontade, nada os regenera. Para trocar de combinação, rode o init de novo em uma pasta limpa, ou copie os pedaços de design/ na mão.

generate --strategy <path>

Valida o strategy.json, monta o prompt final (prompt mestre + estratégia serializada) e grava em <out>/PROMPT.md.

seo-site generate --strategy ./strategy.json --out ./cliente-exemplo

| Opção | Padrão | Descrição | |---|---|---| | -s, --strategy <path> | — (obrigatório) | Caminho do strategy.json | | -o, --out <path> | . | Pasta do projeto já scaffoldado pelo init | | -f, --file <nome> | PROMPT.md | Nome do arquivo de prompt gerado | | -T, --type <tipo> | detectado | Força o prompt mestre de um tipo específico | | -p, --print | false | Imprime o prompt no stdout em vez de gravar o arquivo |

Com --print dá para mandar direto para outro lugar:

seo-site generate -s ./strategy.json --print | xclip -selection clipboard

Depois é só abrir o Claude Code no projeto:

cd cliente-exemplo && claude
> Leia PROMPT.md e execute o que está descrito lá.

Há um prompt mestre por tipo de site, e o generate escolhe sozinho olhando o projeto em --out (só a landing tem src/content/landing.ts). Use --type para forçar.

| Tipo | Prompt mestre | |---|---| | completo | src/prompts/generate-content.md | | landing | src/prompts/generate-landing.md |

É o prompt mestre que define o que o Claude Code faz com a estratégia: ordem de execução, mapeamento campo a campo do strategy.json, estrutura das páginas, regras de on-page, SEO local, busca generativa e conformidade, mais o checklist de verificação. O de landing acrescenta a premissa da página única — e manda avisar no relatório final quando a estratégia pede algo que só o modo completo comporta (blog, área logada, captação com banco), em vez de improvisar.

Edite esses arquivos para ajustar o padrão da agência; a mudança vale para todos os projetos seguintes.

studio

Sobe um app em http://localhost:4173 que junta a galeria de designs com o formulário do strategy.json — escolha o tipo de site e a combinação de design, preencha o planejamento e clique em Gerar site: o studio roda o init + generate por você, na pasta atual, com o prompt mestre do tipo escolhido.

seo-site studio                     # abre o navegador automaticamente
seo-site studio --port 5000         # porta diferente
seo-site studio --no-open           # sem abrir o navegador

O servidor escuta só em 127.0.0.1. O que ele gera é exatamente o que o init e o generate fazem na mão: o projeto pronto com strategy.json e PROMPT.md dentro. Se a pasta destino já existir e não estiver vazia, ele recusa (marque "Sobrescrever pasta" para forçar).

O formulário tem campo de verdade para cada item do strategy.json — nada de colar termo | intenção | volume numa textarea:

| Recurso | O que faz | |---|---| | Seletor de design | 9 swatches de paleta + 4 chips de estilo; escolher filtra a galeria naquela paleta e marca a combinação como escolhido. Clicar num card da galeria faz o caminho inverso | | Listas editáveis | Palavras-chave, páginas e FAQs em linhas com adicionar/remover, select de intenção e de tipo de página | | Rascunho automático | Tudo fica no localStorage do navegador; fechar e reabrir não perde nada. Limpar zera | | Importar / Exportar | Carrega um strategy.json existente para editar, ou baixa o que está no formulário | | Exemplo | Preenche com uma clínica fictícia completa, para ver o formato de cada campo | | Validação | O botão só libera com pasta, nome do cliente e domínio; o rodapé mostra o que falta | | Já vem dockerizado | Checkbox na seção do tipo de site — mesmo efeito do init --docker | | Ctrl/⌘ + Enter | Gera sem tirar a mão do teclado |

A interface acompanha o tema do sistema (claro/escuro) e o accent do studio muda junto com a paleta escolhida.

Registro de scaffolds (opt-in)

Cada init (no terminal ou no studio) pode avisar um servidor da agência sobre o scaffold gerado — nome da pasta, paleta, estilo, versão do CLI e plataforma. Nada é enviado por padrão: sem o token no ambiente, o CLI não abre nenhuma conexão.

export SEO_SITE_TOKEN=segredo-da-agencia        # liga o registro
export SEO_SITE_API_URL="https://.../scaffolds" # opcional; sobrescreve o padrão

O POST é fire-and-forget: tem timeout, erros são silenciosos — o comando termina na hora, mesmo sem internet.

  • Cabeçalho de autenticação: x-seo-site-token: <token>
  • Corpo: { projeto, paleta, estilo, template, cliVersion, node, platform, ts }

O pacote já aponta por padrão para a Edge Function register-scaffold do Supabase da agência (sobrescreva com SEO_SITE_API_URL se quiser outro lugar). A referência da API fica em supabase/:

supabase db push                                   # cria a tabela scaffolds
supabase functions deploy register-scaffold        # respeita verify_jwt=false do config.toml
supabase secrets set SEO_SITE_TOKEN=segredo-da-agencia

O SEO_SITE_TOKEN precisa ser o mesmo valor no CLI e no secret da função. Como o registro só sai com o token, quem instala o pacote do npm público nunca dispara nada sem querer — você recebe registros atribuídos, não telemetria anônima.

registrar [pasta]

Registra o site no painel da agência depois que o Supabase do cliente estiver configurado. Lê do projeto:

  • .env.local / .env → SUPABASE_URL + SUPABASE_SECRET_KEY (é daí que o painel lê os leads)
  • strategy.json → nome e domínio do cliente
export SEO_SITE_TOKEN=segredo-da-agencia   # mesmo token do registro de scaffolds
seo-site registrar ./cliente-x

Re-registrar um projeto já registrado atualiza as credenciais em vez de duplicar. Depois de registrar, o site aparece com os leads no painel da agência (projeto painel-agencia/).

strategy.json

Validado com zod. Nesta etapa exigimos apenas as chaves de alto nível — os campos internos ficam livres:

| Campo | Tipo | |---|---| | client | objeto | | keywords | array ou objeto | | pages | array ou objeto | | faqs | array ou objeto | | topicalAuthority | array ou objeto | | schema | array ou objeto | | gmb | objeto |

Veja strategy.example.json para um exemplo completo (ele também é copiado para dentro de todo projeto criado pelo init).

Estrutura do pacote

├── bin/                       # entrypoint compilado (tsup → bin/cli.js)
├── src/
│   ├── cli.ts                 # definição dos comandos (commander)
│   ├── commands/
│   │   ├── init.ts            # copia o template do tipo escolhido para o destino
│   │   ├── generate.ts        # lê strategy.json, monta e grava o PROMPT.md
│   │   ├── studio.ts          # servidor local: galeria + formulário do strategy.json
│   │   └── registrar.ts       # registra o site no painel da agência
│   ├── lib/
│   │   ├── strategySchema.ts  # validação do strategy.json (zod)
│   │   ├── design.ts          # catálogo de paletas/estilos e composição do CSS
│   │   ├── tipos.ts           # catálogo de tipos de site (template + prompt de cada um)
│   │   ├── docker.ts          # aplica o Docker no projeto gerado (--docker)
│   │   ├── registry.ts        # registro opt-in dos scaffolds (fire-and-forget)
│   │   ├── prompt.ts          # prompts do modo interativo (sem dependências)
│   │   └── paths.ts           # resolução de caminhos do pacote
│   └── prompts/
│       ├── generate-content.md  # prompt mestre do tipo completo
│       └── generate-landing.md  # prompt mestre do tipo landing
├── design/
│   ├── palettes/<cor>.css     # 9 tokens de cor por paleta
│   └── styles/<estilo>/
│       ├── theme.css          # fontes, escala tipográfica, raio (entra no @theme)
│       ├── style.css          # base + components + prose
│       └── fonts.ts           # next/font do estilo
├── scripts/
│   ├── design-tokens.mjs      # leitura e validação dos tokens (fonte única)
│   ├── check-contrast.mjs     # valida WCAG de todas as paletas
│   ├── check-combos.mjs       # gera as 36 combinações + os templates e valida o contrato
│   ├── build-gallery.mjs      # gera docs/gallery.html com as 36 combinações
│   ├── gallery-content.mjs    # negócios de exemplo do preview da galeria
│   └── sync-template-design.mjs  # regenera o CSS commitado dos templates
├── templates/
│   ├── base-nextjs/           # tipo completo: site institucional (ver abaixo)
│   └── landing-nextjs/        # tipo landing: uma página só (ver abaixo)
├── docker/                    # arquivos copiados pelo --docker (comuns aos dois tipos)
│   ├── Dockerfile             # alvos dev, builder e runner
│   ├── docker-compose.yml     # perfis dev e prod
│   ├── dockerignore           # vira .dockerignore no projeto
│   ├── README-section.md      # seção anexada ao README do projeto
│   └── CLAUDE-section.md      # seção anexada ao CLAUDE.md do projeto
├── docs/
│   └── gallery.html           # galeria das 36 combinações (npm run build:gallery)
├── supabase/                  # referência da API de registro (fora do pacote npm)
│   ├── functions/register-scaffold/  # Edge Function do registro opt-in
│   └── migrations/0001_scaffolds.sql # tabela scaffolds
└── package.json

O que os templates entregam

Os dois rodam Next.js 16 (App Router) + Tailwind 4, compartilham o design system e a mesma disciplina de SEO. O que muda é o tamanho da superfície.

base-nextjs — tipo completo

Site institucional com Supabase, na mesma arquitetura de um projeto de SEO já validado em produção:

| Área | Onde | |---|---| | Dados do negócio (NAP, unidades, horários, tópicos) | src/lib/site.ts | | Metadata + Open Graph padronizados | src/lib/seo.ts | | JSON-LD (grafo do site, FAQ, breadcrumb, serviço, blog, artigo) | src/lib/schema.ts | | sitemap.xml, robots.txt, llms.txt, ai.txt | src/app/ | | Blog com Supabase, markdown e índice automático | src/lib/blog.ts | | Formulário de contato com anti-spam, UTM e consentimento LGPD | src/app/actions/lead.ts | | Aviso de lead novo por e-mail (Resend) | src/lib/notificar.ts | | GA4 com rastreio automático de WhatsApp/telefone/e-mail | src/lib/analytics.ts | | Meta Pixel + Conversions API e GA4 server-side, deduplicados | src/lib/conversions/ | | Painel /admin: login, contatos, editor do blog | src/app/admin/ | | Analisador do Search Console (cliques, impressões, CTR, termos, por página) | src/lib/search-console.ts | | Design system (cores, tipografia, prose) | src/app/globals.css | | Fontes do estilo escolhido | src/app/fonts.ts | | Esquema do banco com RLS | supabase/migrations/ |

Rotas já criadas:

/                          home
/blog  /blog/[categoria]  /blog/[categoria]/[slug]
/sobre  /contato  /politica-de-privacidade  /termos-de-uso
/sitemap.xml  /robots.txt  /llms.txt  /ai.txt
/admin  /admin/leads  /admin/posts  /admin/posts/[id]  /admin/busca

As páginas de conversão (/<slug-do-servico>) e o conteúdo do blog são o que o Claude Code gera a partir do strategy.json.

O projeto sobe sem nenhuma variável de ambiente: o blog fica vazio, o formulário avisa que está indisponível e /admin mostra o que falta configurar.

landing-nextjs — tipo landing

Uma landing page só. Sem banco de dados, sem blog, sem painel e sem formulário: o contato sai por WhatsApp e telefone, e o clique é medido como conversão.

| Área | Onde | |---|---| | Dados do negócio (NAP, unidades, horários, tópicos) | src/lib/site.ts | | Conteúdo da landing, seção por seção | src/content/landing.ts | | A página inteira | src/app/page.tsx | | Metadata + Open Graph padronizados | src/lib/seo.ts | | JSON-LD (grafo do negócio, FAQPage, avaliações) | src/lib/schema.ts | | sitemap.xml, robots.txt, llms.txt, ai.txt | src/app/ | | GA4 com rastreio automático de WhatsApp/telefone/e-mail | src/lib/analytics.ts | | Meta Pixel + Conversions API, deduplicados por eventID | src/lib/conversions/ | | Design system (cores, tipografia, prose) | src/app/globals.css | | Fontes do estilo escolhido | src/app/fonts.ts |

Rotas já criadas:

/                          a landing
/politica-de-privacidade   LGPD
/sitemap.xml  /robots.txt  /llms.txt  /ai.txt
/api/eventos               espelha cliques na CAPI da Meta (única rota de servidor)

As seções da página são âncoras, não rotas — #servicos, #como-funciona, #diferenciais, #sobre, #faq, #onde-estamos — e cada uma some sozinha se o conteúdo correspondente estiver vazio. O llms.txt publica o conteúdo em texto puro, já que não há páginas para indexar.

Nenhuma variável de ambiente é obrigatória: sem .env.local a landing sobe inteira e só a medição fica desligada. Sem META_CAPI_TOKEN, o clique é medido só pelo navegador.

Desenvolvimento

npm run build      # compila src/ → bin/cli.js
npm run dev        # build em watch mode
npm run typecheck  # tsc --noEmit

Publicação

O publish é automático, disparado por tag. O push comum no main só roda os checks.

npm version minor        # sobe a versão, cria o commit e a tag
git push --follow-tags   # dispara o workflow Release

A Action valida que a tag bate com a versão do package.json, que essa versão ainda não está no registry, roda o CI inteiro e só então publica. A autenticação usa Trusted Publishing (OIDC) — não existe NPM_TOKEN nos secrets, o npm confia no repositório e no nome do workflow.

Configuração única, em npmjs.com → o pacote → Settings → Trusted Publisher: repositório yagofontanez/create-seo-site, workflow release.yml.

O que o CI verifica

| Check | O que pega | |---|---| | npm run typecheck | erro de tipo no CLI | | npm run check:contrast | paleta que reprova em WCAG | | galeria de designs | docs/gallery.html divergindo do que build:gallery geraria | | smoke test do studio | o servidor do studio não subir ou não servir / e /galeria | | npm run check:combos | paleta ou estilo incompleto, nas 36 combinações + uma passada por template extra | | guarda do tarball | design/, os templates ou os prompts ficando de fora do pacote — o erro que quebraria o init em produção | | matriz scaffold | init + generate + next build real do projeto gerado, em 6 combinações de tipo e design | | matriz docker | init --docker nos dois tipos: compose válido, output: "standalone" no next.config.ts e a imagem de produção respondendo 200 |