Um dApp Solana em Next.js é um produto de runtime dividido: Server Components e Route Handlers no lado Node, Client Components vinculados à carteira no navegador, e @solana/kit 7.0.0 comunicando-se com RPC (e frequentemente WebSocket) em um cluster escolhido.
Esta página é o guarda-chuva da seção. Ela mapeia App Router + provedores Solana, assinatura no lado do cliente, rotas de API para transações, exibição de dados on-chain e cache / tempo real para que os tutoriais irmãos sejam lidos como níveis de zoom de uma única stack.
Integre Solana no Next.js App Router isolando APIs de carteira e navegador atrás de uma árvore de provedor cliente, montando e assinando transações de autoridade do usuário apenas no navegador, usando Route Handlers para segredos e patrocínio, e hidratando a UI a partir de RPC (com cache + assinaturas) sob uma política de commitment explícita.
Insight: Misturar SSR com window, colocar keypairs em variáveis de ambiente NEXT_PUBLIC_ ou tratar o sucesso de sendTransaction como liquidação produz builds quebrados, patrocinadores esgotados e UX enganosa. Um mapa compartilhado de responsabilidades do servidor versus cliente previne esses modos de falha.
Conceitos-Chave:App Router, Server Component, Client Component, árvore de provedores Solana, wallet adapter / wallet-standard, RPC @solana/kit, mensagem de transação, tempo de vida do blockhash, assinatura no cliente, Route Handler, fee payer / patrocínio, commitment, SWR / React Query, accountSubscribe.
Quando Usar: Para estruturar um dApp Solana novo no App Router do Next.js 13+; para integrar uma equipe React em fluxos de escrita com carteira; para decidir o que roda no servidor versus na carteira; para planejar UIs de portfólio e saldos em tempo real.
Limitações/Trade-offs: Provedores cliente e modais de carteira não podem ser renderizados puramente no servidor; rotas patrocinadas precisam de autenticação, limites de taxa e limites de gastos; polling agressivo consome cotas RPC; WebSockets são visualizações locais do nó e ainda exigem disciplina de commitment.
Tópicos Relacionados: Noções básicas de layout de dApp, provedores e App Router, assinatura no lado do cliente, rotas de API para transações, exibição de dados on-chain, cache e tempo real.
Next.js App Router é primariamente Server Components: arquivos em app/ são do lado do servidor por padrão, e "use client" marca "ilhas" que hidratam no navegador.
SDKs de carteira precisam de window, armazenamento e gestos do usuário que não existem durante o SSR. A regra é estrutural: o contexto da carteira, a UI de conexão e a assinatura residem em componentes cliente; os invólucros de marketing e os manipuladores que detêm segredos permanecem no servidor.
Provedores Solana ficam em um único wrapper cliente (por exemplo, app/solana-provider.tsx) composto no layout raiz. Essa árvore tipicamente fornece:
Registro de carteiras - adaptadores ou descoberta via wallet-standard (Phantom, Solflare e outros).
Modal / UI de conexão - um provedor modal para que rotas aninhadas não montem diálogos duplicados.
O layout.tsx raiz pode permanecer um Server Component que apenas envolve os filhos com esse provedor. Layouts aninhados não devem redeclarar a mesma stack de carteira.
@solana/kit 7.0.0 é o cliente recomendado para createSolanaRpc, createSolanaRpcSubscriptions, mensagens de transação e utilitários de confirmação. O legado web3.js v1 aparece apenas em migrações; novos trabalhos visam o kit.
Cluster e ambiente importam desde o primeiro dia. NEXT_PUBLIC_* é enviado ao navegador (URL RPC, rótulo do cluster, IDs de programa públicos). Keypairs de patrocinador e segredos de API privilegiados permanecem server-only (sem prefixo NEXT_PUBLIC_), idealmente em um gerenciador de segredos.
Commitment (processed, confirmed, finalized) alinha-se com o restante deste site: a UI otimista pode usar níveis mais rasos; efeitos off-chain irreversíveis esperam níveis mais profundos.
Uma forma mínima da stack:
app/layout.tsx (Server Component) | +-- SolanaProvider ("use client") | Configuração de Connection / kit | WalletProvider + modal | +-- page.tsx (Server OK para leituras públicas / SEO) | +-- ilhas cliente (chips de saldo, botões de envio) | +-- app/api/**/route.ts (Route Handlers) construções do servidor / patrocinadores / JSON de Actions
Páginas irmãs aprofundam cada caixa; esta página mantém o diagrama inteiro em vista.
Na primeira carga, Server Components renderizam HTML sem estado da carteira. Após a hidratação, os provedores anexam o contexto de conexão e da carteira. Hooks como useWallet ou utilitários do wallet-standard só rodam sob essa fronteira cliente.
Regras práticas: importe o CSS da carteira uma vez; estabilize os adaptadores com useMemo; mantenha um provedor raiz (duplicatas dobram modais); divida ou importe dinamicamente com ssr: false se um widget ainda puxar código exclusivo do navegador para o grafo do servidor.
O trabalho de autoridade do usuário (transferências pagas pelo usuário, mints, aprovações DeFi) segue um loop fixo de Client Component:
Garanta que a carteira está conectada e que a chave pública do fee payer é conhecida.
Busque um blockhash fresco (getLatestBlockhash).
Construa uma mensagem de transação versionada com o kit (fee payer, tempo de vida, instruções).
Obtenha assinaturas Ed25519 da carteira (ponte do signer do kit ou caminhos do adaptador).
Envie e aguarde o commitment (sendAndConfirmTransactionFactory com HTTP + WSS, ou equivalente).
Segredos nunca saem da carteira. A simulação antes do modal reduz falhas evitáveis; a expiração do blockhash durante aprovações lentas exige reconstrução e novo prompt.
Route Handlers (app/api/.../route.ts) rodam no servidor quando você precisa:
Manter um keypair de patrocinador / paymaster como fee payer para onboarding sem gas.
Aplicar regras de negócio, listas de permissão (allowlists) ou inventário antes de oferecer uma mensagem à carteira.
Implementar Solana Actions (JSON de Actions HTTPS para carteiras e Blinks).
Ocultar chaves de API de terceiros usadas ao montar instruções.
Um padrão comum é a construção parcial: o servidor monta (e pode assinar parcialmente como fee payer), retorna bytes serializados, e a carteira do usuário co-assina. A assinatura puramente do servidor é apenas para contas que o servidor controla totalmente.
Proteja os endpoints: valide o JSON com schema, autentique, limite a taxa de requisições, limite o patrocínio, nunca retorne material de chave.
Renderizar o estado da chain é RPC de caminho de leitura mais formatação cuidadosa:
Necessidade da UI
Fonte Típica
Saldo SOL
getBalance
Saldos de tokens SPL
ATAs + decodificação de token / decimais do mint
NFTs / cNFTs
Provedor DAS (getAsset, getAssetsByOwner) quando disponível
Contas de programa personalizadas
Utilitários de fetch do kit / Codama, derivação de PDA
Mantenha lamports e unidades base de token como inteiros / bigint até a string de exibição. Distinga carregando, vazio e erro. Server Components podem semear snapshots públicos para SEO; portfólios privados da carteira permanecem no lado do cliente.
Cache HTTP do cliente - SWR ou React Query com chaves que incluem cluster + pubkey. refreshInterval opcional como um fallback grosseiro.
Assinaturas WebSocket - accountSubscribe (e assinaturas de assinatura) via kit; ao notificar, mutate o cache.
O cache de dados do RSC / Next não é o cache da carteira do navegador. Após sua própria escrita confirmada, invalide chaves relacionadas. Aborte assinaturas ao desmontar. Recue em caso de 429.
Usuário clica em Enviar (Client Component) | v kit: monta mensagem + blockhash recente | v Modal da carteira assina (Ed25519, segredos permanecem na carteira) | v sendTransaction via RPC --> assinatura S | +-- WSS signatureSubscribe / confirm factory | v commitment: processed -> confirmed -> finalized | v invalida chaves SWR; mostra link do explorador
Fluxos patrocinados inserem um Route Handler entre o clique e a carteira: o servidor retorna uma mensagem parcial; o cliente ainda coleta a assinatura do usuário quando a autoridade do usuário é necessária.
Mire @solana/kit 7.0.0 para RPC, mensagens e confirmação. Faça a ponte de signers do wallet-adapter ou wallet-ui para o kit em vez de stacks paralelas do web3.js v1. Testes de integração podem usar Surfpool ou um validador local; testes unitários mockam RPC. Programas co-desenvolvidos neste site assumem Anchor 0.32.1, Rust 1.91.1, Agave 4.1.1 e Solana CLI 3.0.10.
"Posso chamar useWallet de qualquer Server Component se for cuidadoso." Hooks de carteira exigem uma fronteira cliente e APIs do navegador; importá-los em um grafo do servidor falha a build ou causa crash no SSR.
"Colocar o keypair do patrocinador em NEXT_PUBLIC_ env é aceitável se o repositório for privado." O env público é enviado a todos os navegadores; trate as chaves do patrocinador como segredos server-only com rotação e limites de gastos.
"O retorno de sendTransaction com uma assinatura significa que o usuário recebeu os tokens." A assinatura é um identificador; a UX deve esperar o commitment escolhido e então atualizar as leituras em cache.
"Rotas de API substituem a carteira para todas as transações." As rotas podem patrocinar taxas e codificar políticas; a autoridade do usuário para contas de propriedade do usuário ainda requer uma assinatura da carteira, a menos que o servidor seja o verdadeiro proprietário.
"Polling do SWR a cada segundo é o mesmo que tempo real." O polling apertado atinge limites de taxa e ainda assim atrasa; combine um cache HTTP modesto com invalidação via WebSocket para contas ativas.
"Um contexto React global para saldos de todos os usuários é eficiente." As chaves de cache devem incluir identidade (e cluster); chaves compartilhadas vazam ou embaralham dados de portfólio em sessões multiusuário.
Qual é o modelo de uma frase para um dApp Solana Next.js?
Server Components e Route Handlers lidam com SEO, segredos e política; uma única árvore de provedor cliente possui o estado da carteira e da UI RPC; o kit monta mensagens que a carteira assina; cache e assinaturas mantêm as contas exibidas corretas sob um commitment escolhido.
Por que App Router em vez de Pages Router para novos dApps?
Trabalhos novos devem usar App Router: Server Components, layouts aninhados e Route Handlers mapeiam de forma limpa para a divisão servidor/cliente que Solana exige. Pages Router permanece apenas como um caminho de migração legado.
Onde os provedores de carteira pertencem na árvore de arquivos?
Em um único módulo cliente (por exemplo, solana-provider.tsx) importado do layout raiz, não remontado em cada layout ou página aninhada.
Server Components podem ler a chain?
Sim, para dados públicos via chamadas de kit/RPC do lado do servidor. Eles não podem acessar a carteira do usuário ou chaves privadas; passe props serializáveis simples para ilhas cliente para UI interativa.
Quando a assinatura deve permanecer inteiramente no lado do cliente?
Sempre que o fee payer ou a autoridade for o usuário final e você não estiver patrocinando taxas ou injetando política server-only. Esse é o padrão para DeFi, transferências e mints de auto-custódia.
Quando preciso de rotas de API para transações?
Quando você precisa de um fee payer no servidor, verificações de inventário ou allowlist, endpoints Actions/Blinks, ou chaves privadas de terceiros durante a construção da mensagem.
Como evito "window is not defined"?
Nunca importe os pontos de entrada do adaptador de carteira em Server Components. Mantenha-os sob módulos "use client" que só carregam no grafo do navegador.
Qual biblioteca o novo código deve usar: kit ou web3.js v1?
@solana/kit 7.0.0 é a linha de base neste site. Use web3.js v1 apenas ao migrar módulos legados.
Como os saldos devem ser formatados?
Mantenha lamports e unidades base de token como inteiros/bigint através da lógica de negócio; divida por 10**decimals apenas ao produzir uma string de exibição.
Como mantenho a UI atualizada após um envio bem-sucedido?
Confirme até o seu commitment alvo, então mutate as chaves SWR/React Query (ou confie nos manipuladores accountSubscribe) para que os saldos em cache e os dados da conta sejam recarregados.
NEXT_PUBLIC_RPC_URL é um segredo?
Não. É um endereço de endpoint público. Faça proxy de cabeçalhos privilegiados do provedor no servidor, se necessário, e ainda assim limite a taxa do tráfego do cliente.
Para qual commitment o dApp deve esperar?
Muitas ações de produto usam confirmed. Use finalized antes de efeitos externos irreversíveis. Trate processed como otimista apenas.