Communitygithub.com

Nuvraxis/nuvraxis-plugins

Regras de produção para aplicações Next.js 16 App Router na Nuvraxis — limites entre Componentes Servidor/Cliente, Cache Components ("use cache", cacheLife, cacheTag, updateTag), Server Actions, route handlers, tratamento de env, instrumentation, output standalone e a rota /api/health. Use quando o projeto tem "next" no package.json, um diretório app/ ou src/app/, next.config.ts, proxy.ts, instrumentation.ts ou arquivos nomeados page.tsx, layout.tsx, route.ts, loading.tsx, error.tsx.

O que é nuvraxis-plugins?

Esta skill fornece as regras de produção para aplicações Next.js 16 App Router na Nuvraxis. Ela define diretrizes sobre componentes servidor vs. cliente, uso do sistema de Cache Components ("use cache", cacheLife, cacheTag, updateTag), validação e autorização em Server Actions, tratamento de variáveis de ambiente, configuração de saída standalone, rota de health check /api/health e muito mais. É útil para desenvolvedores que trabalham com Next.js 16 em um ambiente de produção na Nuvraxis, garantindo consistência, segurança e boas práticas. A skill suporta Claude Code e Cursor, e é ativada automaticamente quando o projeto possui arquivos como next.config.ts, instrumentation.ts, ou diretórios app/ ou src/app/.

Funciona com✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/Nuvraxis/nuvraxis-plugins/tree/HEAD/plugins/nuvraxis-frontend/skills/nextjs-production

Perguntar na sua IA favorita

Abre um novo chat com esta habilidade de agente já pré-carregada.

Documentação

Next.js em produção

Use para qualquer código em um app Next.js 16 App Router. Regras específicas de segurança (auth em actions, CSP, headers, taint) estão em nextjs-security; regras de container em docker-nextjs. A skill integrada next-best-practices do Claude Code cobre convenções gerais de arquivos, metadados, otimização de imagens e fontes em profundidade; esta skill adiciona apenas o que é específico para como construímos e entregamos.

Linha de base: Next 16.4, React 19.3, Turbopack (padrão para dev e build), cacheComponents: true com partialPrefetching: true, output: "standalone", typedRoutes: true. O next.config.ts do template é a fonte da verdade.

Regras

  1. Componentes Servidor por padrão; "use client" apenas para estado, efeitos, APIs de navegador ou manipuladores de eventos. Coloque a diretiva na menor folha que precisar dela. Não a adicione porque um arquivo importa nuvui: as partes stateful do nuvui carregam sua própria diretiva (veja a skill nuvui, rules/server-components.md).

    // Errado: página inteira é cliente por causa de um manipulador
    "use client";
    export default function Page() { … <Select onValueChange={…} /> … }
    
    // Certo: a página permanece no servidor, o manipulador vive em uma folha
    export default async function Page() {
      const people = await getPeople();
      return <PeopleFilter people={people} />; // people-filter.tsx tem "use client"
    }
    

    Props que cruzam para um componente cliente devem ser serializáveis: sem funções (exceto Server Actions), sem instâncias de classe.

  2. Faça fetch no servidor, no componente que precisa dos dados. Sem fetch com useEffect, sem route handler apenas para alimentar sua própria página. Desduplique por requisição com cache() do React; armazene em cache entre requisições com a regra 3.

  3. Cache com "use cache" + cacheLife + cacheTag; todo o resto é dinâmico. Com Cache Components, nada é armazenado em cache a menos que você diga, e fetch não tem cache implícito.

    import { cacheLife, cacheTag } from "next/cache";
    
    export async function getInvoice(id: InvoiceId) {
      "use cache";
      cacheLife("minutes");
      cacheTag(`invoice:${id}`);
      return db.invoice.findUnique({ where: { id } });
    }
    

    Não use a configuração antiga de segmento (export const dynamic, revalidate, fetchCache): ela gera erro sob Cache Components. Argumentos e valores fechados se tornam parte da chave de cache, então passe ids, não objetos de requisição inteiros. Detalhes, os perfis e "use cache: private": references/caching.md.

  4. Invalide com updateTag em Server Actions, revalidateTag(tag, "max") em outros lugares. updateTag(tag) proporciona consistência de leitura-após-escrita e funciona apenas dentro de uma Server Action. De um webhook ou route handler use revalidateTag(tag, "max") (stale-while-revalidate) ou revalidateTag(tag, { expire: 0 }). A versão com um argumento revalidateTag(tag) está obsoleta.

  5. Empacote dados em tempo de requisição dentro de <Suspense>, ou a build falha. cookies(), headers(), searchParams, connection() e I/O não armazenado em cache fora de um limite Suspense interrompem o pré-renderização com "dados não armazenados em cache ou em tempo de execução durante pré-renderização". Dê a ele um limite com um fallback skeleton, armazene em cache, ou (apenas layout raiz, veja regra 14) marque a rota como bloqueante com export const instant = false. Todos params, searchParams, cookies(), headers() são assíncronos: use await neles.

  6. Toda Server Action valida sua entrada e verifica autorização por conta própria. Uma Server Action é um endpoint POST público independentemente da página em que está escrita. Analise FormData com o schema de typescript-production (valibot), depois autorize, depois mutação, depois updateTag. Retorne um resultado tipado para falhas esperadas; lance apenas para bugs. O conjunto completo de regras está em nextjs-security.

    "use server";
    export async function renameProject(_: State, form: FormData): Promise<State> {
      const session = await requireSession();                  // 401 se ausente
      const input = v.safeParse(RenameProject, Object.fromEntries(form));
      if (!input.success) return { ok: false, errors: flatten(input.issues) };
      await assertCanEdit(session, input.output.projectId);    // 403 se não autorizado
      await db.project.update(…);
      updateTag(`project:${input.output.projectId}`);
      return { ok: true };
    }
    
  7. Route handlers são para outros clientes (webhooks, mobile, health), não para suas próprias páginas. Coloque-os em app/api/. Valide o corpo como uma ação, retorne Response.json(...) e defina códigos de status intencionalmente.

  8. Todo app tem GET /api/health, dinâmico e sem dependências. O HEALTHCHECK do Docker e as probes do Kubernetes o acessam. Deve responder sem tocar no banco de dados, para que uma dependência lenta não reinicie todos os pods. await connection() impede que seja pré-renderizado em um arquivo estático. Está no template em src/app/api/health/route.ts; proxy.ts exclui /api/health do seu matcher.

  9. error.tsx, loading.tsx e not-found.tsx na raiz, e por segmento onde a UX difere. error.tsx é um componente cliente; registre através de onRequestError em instrumentation.ts, mostre uma tentativa com reset, nunca a mensagem de erro. Chame notFound() para registros ausentes em vez de renderizar um estado vazio.

  10. NEXT_PUBLIC_* é incorporado na build; todo o resto é lido em tempo de execução no servidor. Uma imagem é promovida de main para produção inalterada, então um valor NEXT_PUBLIC_ é o mesmo em todos os ambientes. Coloque apenas constantes de build lá (nome do app, um Sentry DSN público que é o mesmo em todos os lugares). Configuração por ambiente (URLs de API, feature flags, segredos) é um process.env.X no lado do servidor, lido em um Componente Servidor ou ação, e passado para o cliente como props se necessário. Valide env uma vez em src/env.ts (valibot) e importe de lá. Nunca use a chave env em next.config.ts: ela é inlinada em bundles do cliente.

  11. Marque módulos apenas do servidor com import "server-only". Qualquer coisa que leia segredos, converse com o BD ou importe um SDK com credenciais. Uma importação cliente disso falha na build em vez de vazar.

  12. after() para trabalho que não deve atrasar a resposta (logs de auditoria, análises, aquecimento de cache). Leia cookies()/headers() antes de chamar after, não dentro dele. Ele executa no mesmo processo, então o pod precisa de seu período de graça SIGTERM (o chart define terminationGracePeriodSeconds).

  13. Instrumente com src/instrumentation.ts: registerOTel + onRequestError. OpenTelemetry via @vercel/otel, exportador configurado pelas variáveis de ambiente padrão OTEL_EXPORTER_OTLP_* em tempo de execução. Veja references/observability.md.

  14. Mantenha output: "standalone" e nunca importe de fora do workspace. O runner Docker copia apenas .next/standalone, .next/static e public. No monorepo, server.js está em .next/standalone/apps/<app>/server.js; a raiz do workspace é encontrada a partir de pnpm-lock.yaml, então não defina outputFileTracingRoot ou turbopack.root a menos que a build avise. Detalhes de self-hosting (multi-replica, chaves Server Action, deploymentId): references/self-hosting.md.

  15. O layout raiz lê o nonce CSP, então o app renderiza por requisição. O proxy.ts do template define um CSP baseado em nonce e src/app/layout.tsx tem export const instant = false. Isso é uma troca deliberada: nonces e shells estáticos pré-renderizados não podem coexistir, e para apps de negócios logados um CSP estrito vence. O cache de dados com "use cache" ainda funciona. Não remova nenhuma das partes sem ler a regra 4 de nextjs-security.

  16. Estilos: SCSS BEM global, importado pelo componente. Turbopack compila Sass com o pacote sass; sassOptions.loadPaths: ["src/styles"] faz @use "abstracts" funcionar de qualquer profundidade. Sem imports ~, sem sassOptions.functions. Regras em scss-bem.

  17. Imagens através de next/image, fontes através de next/font. sharp vem com Next para o otimizador; a imagem do runner não precisa de pacote extra. Imagens remotas precisam de images.remotePatterns com um hostname exato.

  18. Verifique o tamanho do bundle com pnpm next analyze (analisador do Turbopack; @next/bundle-analyzer é apenas webpack). Carregue componentes cliente pesados (editor nuvui, mapas, gráficos abaixo da dobra) com next/dynamic.

  19. Use rotas tipadas e tipos gerados. typedRoutes: true verifica <Link href>; PageProps<"/invoices/[id]"> e LayoutProps são globais após next typegen (executado automaticamente por next dev/next build). Não escreva tipos params manualmente.

  20. Sem next lint. Foi removido na versão 16. Biome faz lint (veja biome); TypeScript verifica com tsc --noEmit por pacote.

Verificar

pnpm typecheck
pnpm lint
pnpm build                      # turbo run build: falha em erros de pré-renderização, erros de tipo, erros Sass
pnpm --filter <app> start &     # então:
curl -fsS localhost:3000/api/health

Fontes

Individual skills in this repo

This repo contains 4 individual skills — each has its own dedicated page.

Nuvraxis/nuvraxis-plugins

>- Biome 2.5 setup and rules for Nuvraxis monorepos — root biome.json with pinned $schema, VCS ignore, formatter settings, the recommended preset with a11y and the react/next domains, nursery policy, organize imports, overrides, nested per-package configs ("extends": "//"), biome check --write locally, biome ci in CI, VS Code settings, and migrating from ESLint/Prettier. Use when the repo has biome.json or biome.jsonc, @biomejs/biome in package.json, .eslintrc*/eslint.config.*/.prettierrc* to migrate, or when fixing lint and formatting errors.

Nuvraxis/nuvraxis-plugins

>- Dockerfile rules for Next.js standalone apps in a pnpm + Turborepo monorepo — multi-stage build (turbo prune → pnpm fetch/offline install → turbo build → minimal runner), pinned Node 26 Alpine by digest, checksum-verified pnpm binary, non-root uid 1001, read-only root filesystem with a writable .next/cache, HEALTHCHECK on /api/health, build args only for NEXT_PUBLIC_* values, BuildKit secrets and cache mounts, multi-arch, OCI labels and .dockerignore. Use when the repo has a Dockerfile, .dockerignore, compose file, or next.config with output "standalone", or when asked to containerise, shrink, harden or debug an image.

Nuvraxis/nuvraxis-plugins

>- GitHub Actions conventions for Nuvraxis Next.js apps — exactly three workflows: pr.yaml (every PR to any branch: Biome, stylelint, typecheck/test/build with turbo --affected, Docker build + health check, helm lint + kubeconform; publishes nothing), main.yaml (push to main: one multi-arch image to GHCR tagged sha-SHORTSHA and main, provenance + SBOM, gha cache), release.yaml (tag vX.Y.Z: verify on main, retag the existing image without rebuilding, package and push the Helm chart to OCI, GitHub Release with chart, digest and SBOM). Minimal permissions per job, GITHUB_TOKEN only, pinned action majors. Use when editing .github/workflows/*, adding a CI step, or debugging a failed run or release.

Nuvraxis/nuvraxis-plugins

>- Helm chart rules for Nuvraxis Next.js apps — one chart per app in charts/ (named after the app), published to oci://ghcr.io/nuvraxis/charts and synced by Argo CD; Chart.yaml version/appVersion set only by release.yaml; Deployment with startup/liveness/readiness probes on /api/health, non-root read-only security context, emptyDir for .next/cache, ConfigMap + existing Secret via envFrom, Service, Ingress with cert-manager, HPA, PDB, ServiceAccount, topology spread; no Helm hooks; helm lint --strict + kubeconform. Use when the repo has charts/, Chart.yaml, values*.yaml, templates/*.yaml with Helm syntax, or an Argo CD Application, or when asked to deploy, scale, expose or configure the app on Kubernetes.

Habilidades Relacionadas