Integración de dApps en Next.js
Una dApp de Solana en Next.js es un producto de tiempo de ejecución dividido: Server Components y Route Handlers en el lado de Node, Client Components vinculados a la billetera en el navegador, y @solana/kit 7.0.0 comunicándose con RPC (y a menudo WebSocket) en un clúster elegido.
Esta página es el paraguas de la sección. Mapea App Router + proveedores de Solana, firma del lado del cliente, rutas de API para transacciones, visualización de datos en cadena y almacenamiento en caché / tiempo real para que las guías hermanas se lean como niveles de zoom de una única pila.
Resumen
- Integrar Solana en el App Router de Next.js aislando las APIs de la billetera y del navegador detrás de un árbol de proveedores del cliente, construyendo y firmando transacciones de autoridad del usuario solo en el navegador, utilizando Route Handlers para secretos y patrocinio, e hidratando la UI desde RPC (con caché + suscripciones) bajo una política de compromiso explícita.
- Por Qué Importa: Mezclar SSR con
window, poner keypairs en el entornoNEXT_PUBLIC_, o tratar el éxito desendTransactioncomo liquidación produce compilaciones rotas, patrocinadores agotados y UX falsa. Un mapa compartido de responsabilidades del servidor frente al cliente previene esos modos de fallo. - Conceptos Clave: App Router, Server Component, Client Component, árbol de proveedores de Solana, adaptador de billetera / wallet-standard, RPC de @solana/kit, mensaje de transacción, vida útil del blockhash, firma del cliente, Route Handler, fee payer / patrocinio, commitment, SWR / React Query, accountSubscribe.
- Cuándo Usar: Para estructurar una dApp de Solana nueva en el App Router de Next.js 13+; para incorporar un equipo de React a las rutas de escritura de billeteras; para decidir qué se ejecuta en el servidor frente a la billetera; para planificar UIs de portafolio y saldos en vivo.
- Limitaciones / Compensaciones: Los proveedores del cliente y las modales de billetera no pueden renderizarse puramente en el servidor; las rutas patrocinadas necesitan autenticación, límites de tasa y límites de gasto; el sondeo agresivo agota el RPC; las WebSockets son vistas locales del nodo y aún requieren disciplina de compromiso.
- Temas Relacionados: Fundamentos de diseño de dApps, proveedores y App Router, firma del lado del cliente, rutas de API para transacciones, visualización de datos en cadena, almacenamiento en caché y tiempo real.
Fundamentos
Next.js App Router es primero Server Components: los archivos bajo app/ son del servidor por defecto, y "use client" marca las "islas" que se hidratan en el navegador.
Los SDK de billetera necesitan window, almacenamiento y gestos de usuario que no existen durante SSR. La regla es estructural: el contexto de la billetera, la UI de conexión y la firma viven en componentes del cliente; las carcasas de marketing y los manejadores que guardan secretos permanecen en el servidor.
Los proveedores de Solana se sientan en un único wrapper del cliente (por ejemplo, app/solana-provider.tsx) compuesto en el layout raíz. Ese árbol típicamente suministra:
- Configuración RPC / kit - URL HTTP del clúster (a menudo
NEXT_PUBLIC_RPC_URL). - Registro de billetera - adaptadores o descubrimiento de wallet-standard (Phantom, Solflare y otros).
- UI modal / de conexión - un único proveedor modal para que las rutas anidadas no monten diálogos duplicados.
El layout.tsx raíz puede permanecer como un Server Component que solo envuelve a los hijos con ese proveedor. Los layouts anidados no deben volver a declarar la misma pila de billetera.
@solana/kit 7.0.0 es el cliente recomendado para createSolanaRpc, createSolanaRpcSubscriptions, mensajes de transacción y ayudantes de confirmación. El legado web3.js v1 aparece solo en migraciones; el nuevo trabajo apunta a kit.
Clúster y entorno importan desde el primer día. NEXT_PUBLIC_* se envía al navegador (URL RPC, etiqueta de clúster, IDs de programa públicos). Los keypairs del patrocinador y los secretos de API privilegiados permanecen solo en el servidor (sin prefijo NEXT_PUBLIC_), idealmente en un gestor de secretos.
Commitment (processed, confirmed, finalized) coincide con el resto de este sitio: la UI optimista puede usar niveles más superficiales; los efectos fuera de cadena irreversibles esperan niveles más profundos.
Una forma mínima de la pila:
app/layout.tsx (Server Component)
|
+-- SolanaProvider ("use client")
| Conexión / config de kit
| WalletProvider + modal
|
+-- page.tsx (Server OK para lecturas públicas / SEO)
|
+-- islas del cliente (chips de saldo, botones de envío)
|
+-- app/api/**/route.ts (Route Handlers)
compilaciones del servidor / patrocinadores / Acciones JSON
Las páginas hermanas profundizan cada caja; esta página mantiene todo el diagrama a la vista.
Mecánicas e Interacciones
Proveedores y el límite del App Router
En la primera carga, los Server Components renderizan HTML sin estado de billetera. Después de la hidratación, los proveedores adjuntan la conexión y el contexto de la billetera. Hooks como useWallet o los ayudantes de wallet-standard se ejecutan solo bajo ese límite del cliente.
Reglas prácticas: importar CSS de billetera una vez; estabilizar adaptadores con useMemo; mantener un proveedor raíz (los duplicados montan diálogos dobles); dividir o importar dinámicamente con ssr: false si un widget aún extrae código solo del navegador a un grafo del servidor.
Firma del lado del cliente
El trabajo de autoridad del usuario (transferencias pagadas por el usuario, acuñaciones, aprobaciones DeFi) sigue un bucle fijo de Client Component:
- Asegurarse de que la billetera esté conectada y se conozca la pubkey del fee payer.
- Obtener un mensaje de transacción versionado y fresco (
getLatestBlockhash). - Construir un mensaje de transacción versionado con kit (fee payer, vida útil, instrucciones).
- Obtener firmas Ed25519 de la billetera (puente de firma de kit o rutas de adaptador).
- Enviar y esperar confirmación (
sendAndConfirmTransactionFactorycon HTTP + WSS, o equivalente).
Los secretos nunca salen de la billetera. La simulación antes de la modal reduce fallos evitables; la expiración del blockhash durante una aprobación lenta requiere reconstrucción y repetición de la solicitud.
Ver Firma del Lado del Cliente.
Rutas de API para transacciones
Los Route Handlers (app/api/.../route.ts) se ejecutan en el servidor cuando debe:
- Mantener un keypair de patrocinador / paymaster como fee payer para la incorporación sin gas.
- Aplicar reglas de negocio, listas blancas o inventario antes de ofrecer un mensaje a la billetera.
- Implementar Solana Actions (JSON de Acciones HTTPS para billeteras y Blinks).
- Ocultar claves API de terceros utilizadas al ensamblar instrucciones.
Un patrón común es la construcción parcial: el servidor construye (y puede firmar parcialmente como fee payer), devuelve bytes serializados y la billetera del usuario co-firma. La firma puramente del servidor es solo para cuentas que el servidor controla completamente.
Proteger endpoints: validar esquemas JSON, autenticar, limitar tasas, limitar patrocinios, nunca devolver material de clave.
Ver Rutas de API para Transacciones.
Visualización de datos en cadena
Renderizar el estado de la cadena es RPC de ruta de lectura más formato cuidadoso:
| Necesidad de UI | Fuente Típica |
|---|---|
| Saldo de SOL | getBalance |
| Saldos de tokens SPL | ATAs + decodificación de token / decimales de acuñación |
| NFTs / cNFTs | Proveedor DAS (getAsset, getAssetsByOwner) cuando esté disponible |
| Cuentas de programa personalizadas | Ayudantes de obtención de kit / Codama, derivación de PDA |
Mantenga los lamports y las unidades base de tokens como enteros / bigint hasta la cadena de visualización. Distinga cargando, vacío y error. Los Server Components pueden sembrar instantáneas públicas de SEO; los portafolios privados de la billetera permanecen del lado del cliente.
Ver Visualización de Datos en Cadena.
Almacenamiento en caché y tiempo real
Dos capas a menudo coexisten:
- Caché HTTP del cliente - SWR o React Query con claves que incluyen clúster + pubkey.
refreshIntervalopcional como respaldo aproximado. - Suscripciones WebSocket -
accountSubscribe(y suscripciones de firma) a través de kit; al notificar,mutatela caché.
RSC / caché de datos de Next no es la caché de la billetera del navegador. Después de su propia escritura confirmada, invalide las claves relacionadas. Aborte las suscripciones al desmontar. Retroceda en caso de 429.
Ver Almacenamiento en Caché y Tiempo Real.
Ruta de escritura de extremo a extremo (autocustodia)
El usuario hace clic en Enviar (Client Component)
|
v
kit: construir mensaje + blockhash reciente
|
v
Modal de billetera firma (Ed25519, secretos permanecen en la billetera)
|
v
sendTransaction vía RPC --> firma S
|
+-- WSS signatureSubscribe / confirm factory
|
v
commitment: processed -> confirmed -> finalized
|
v
invalide claves SWR; mostrar enlace al explorador
Los flujos patrocinados insertan un Route Handler entre el clic y la billetera: el servidor devuelve un mensaje parcial; el cliente aún recopila la firma del usuario cuando se requiere la autoridad del usuario.
Consideraciones Avanzadas y Aplicaciones
Mapa conceptual de la sección
| Preocupación | Página principal | Conclusión del desarrollador |
|---|---|---|
| Diseño de carpetas, entorno, división lectura/escritura | Fundamentos de Integración de dApps | Estructura antes que características |
| Árbol de proveedores del cliente, seguridad SSR | Proveedores y App Router | Un proveedor raíz; shell de layout del servidor |
| Construir, firmar, confirmar en el navegador | Firma del Lado del Cliente | Blockhash fresco; sin billetera del servidor |
| Saldos, tokens, estado del programa UI | Visualización de Datos en Cadena | bigint hasta el formato; estados explícitos |
| Transacciones construidas/patrocinadas por el servidor | Rutas de API para Transacciones | Secretos solo del servidor; límites y autenticación |
| SWR + suscripciones | Almacenamiento en Caché y Tiempo Real | Mutar después de confirmar; abortar al desmontar |
Las lecturas del lado del servidor, la UX de las transacciones y las mejores prácticas refinan el pulido; las filas anteriores son el núcleo de la integración.
Diseño de la división: servidor vs cliente
| Trabajo | Preferir cliente | Preferir servidor (Route Handler / RSC) |
|---|---|---|
| Conectar billetera, firmar como usuario | Sí | No |
| Configuración pública del programa para SEO | Semilla opcional | Sí |
| Keypair de patrocinador | Solo co-firmar | Sí para material de clave |
| Clave API de terceros privada | No | Sí (proxy) |
| Portafolio de billetera en vivo | Sí + WS | Solo instantánea pública inicial |
No "mueva la firma al servidor" para simplificar React; eso redefine la custodia.
Postura de producción
- Fijar clúster, IDs de programa y URLs RPC/WSS por entorno.
- Registrar IDs de correlación en rutas de API; mostrar errores de simulación decodificados, no trazas de pila.
- Preferir RPC de pago en mainnet; alinear la red de la billetera con el clúster RPC.
- Tratar las Acciones / Blinks como productos HTTPS de primera clase cuando exponga construcción desatendida.
Alineación de herramientas
Apuntar a @solana/kit 7.0.0 para RPC, mensajes y confirmación. Conectar los signers de wallet-adapter o wallet-ui a kit en lugar de pilas paralelas de web3.js v1. Las pruebas de integración pueden usar Surfpool o un validador local; las pruebas unitarias simulan RPC. Los programas co-desarrollados en este sitio asumen Anchor 0.32.1, Rust 1.91.1, Agave 4.1.1, y Solana CLI 3.0.10.
Conceptos Erróneos Comunes
- "Puedo llamar a useWallet desde cualquier Server Component si tengo cuidado." Los hooks de billetera requieren un límite de cliente y APIs del navegador; importarlos en un grafo del servidor falla la compilación o bloquea el SSR.
- "Poner el keypair del patrocinador en el entorno NEXT_PUBLIC_ está bien si el repositorio es privado." El entorno público se envía a cada navegador; trate las claves de patrocinador como secretos solo del servidor con rotación y límites de gasto.
- "sendTransaction devolviendo una firma significa que el usuario recibió los tokens." La firma es un identificador; la UX debe esperar el compromiso elegido y luego actualizar las lecturas cacheadas.
- "Las rutas de API reemplazan a la billetera para todas las transacciones." Las rutas pueden patrocinar tarifas y codificar políticas; la autoridad del usuario para cuentas propiedad del usuario aún necesita una firma de billetera a menos que el servidor sea el verdadero propietario.
- "El sondeo de SWR cada segundo es lo mismo que el tiempo real." El sondeo ajustado alcanza los límites de tasa y aún se retrasa; combine una caché HTTP modesta con la invalidación de WebSocket para cuentas activas.
- "Un contexto global de React para saldos en todos los usuarios es eficiente." Las claves de caché deben incluir identidad (y clúster); las claves compartidas filtran o mezclan datos de portafolio en sesiones de múltiples usuarios.
Preguntas Frecuentes
¿Cuál es el modelo en una frase para una dApp de Solana en Next.js?
Los Server Components y Route Handlers manejan SEO, secretos y políticas; un único árbol de proveedores del cliente posee el estado de la UI de la billetera y RPC; kit construye mensajes que la billetera firma; la caché y las suscripciones mantienen las cuentas mostradas honestas bajo un compromiso elegido.
¿Por qué App Router en lugar de Pages Router para nuevas dApps?
El trabajo nuevo debe usar App Router: Server Components, layouts anidados y Route Handlers se mapean limpiamente a la división servidor/cliente que Solana requiere. Pages Router sigue siendo solo una ruta de migración heredada.
¿Dónde pertenecen los proveedores de billetera en el árbol de archivos?
En un único módulo del cliente (por ejemplo, solana-provider.tsx) importado desde el layout raíz, no re-montado en cada layout o página anidada.
¿Pueden los Server Components leer la cadena?
Sí, para datos públicos a través de llamadas RPC/kit del lado del servidor. No pueden acceder a la billetera del usuario ni a claves privadas; pase props serializables simples a las "islas" del cliente para UI interactiva.
¿Cuándo debe la firma permanecer completamente del lado del cliente?
Siempre que el fee payer o la autoridad sea el usuario final y usted no esté patrocinando tarifas ni inyectando políticas solo del servidor. Esa es la configuración predeterminada para DeFi, transferencias y acuñaciones de autocustodia.
¿Cuándo necesito rutas de API para transacciones?
Cuando necesite un fee payer del servidor, comprobaciones de inventario o listas blancas, endpoints de Acciones/Blinks, o claves de terceros privadas durante la construcción del mensaje.
¿Cómo evito "window is not defined"?
Nunca importe los puntos de entrada del adaptador de billetera en Server Components. Manténgalos bajo módulos "use client" que solo se cargan en el grafo del navegador.
¿Qué biblioteca debe usar el código nuevo: kit o web3.js v1?
@solana/kit 7.0.0 es la base en este sitio. Use web3.js v1 solo mientras migra módulos heredados.
¿Cómo se deben formatear los saldos?
Mantenga los lamports y las unidades base de tokens como enteros/bigint a través de la lógica de negocio; divida por 10**decimals solo al producir una cadena de visualización.
¿Cómo mantengo la UI actualizada después de un envío exitoso?
Confirme a su compromiso objetivo, luego mutate las claves de SWR/React Query (o confíe en los manejadores de accountSubscribe) para que los saldos cacheados y los datos de la cuenta se recarguen.
¿Es NEXT_PUBLIC_RPC_URL un secreto?
No. Es una dirección de endpoint pública. Proxy los encabezados del proveedor privilegiado en el servidor si es necesario, y aún así limite la tasa del tráfico del cliente.
¿Qué compromiso debe esperar la dApp?
Muchas acciones del producto usan confirmed. Use finalized antes de efectos externos irreversibles. Trate processed como solo optimista.
¿A dónde debo ir ahora en esta sección?
Comience con Fundamentos de Integración de dApps, luego Proveedores y App Router, Firma del Lado del Cliente, Visualización de Datos en Cadena, Rutas de API para Transacciones, y Almacenamiento en Caché y Tiempo Real.
Relacionado
- Fundamentos de Integración de dApps - diseño de carpetas, entorno y ejemplos de división servidor/cliente
- Proveedores y App Router - árbol de proveedores de billetera y RPC sin fallos de SSR
- Firma del Lado del Cliente - construir, firmar y confirmar en el navegador con kit
- Visualización de Datos en Cadena - saldos, tokens, NFTs y estado del programa en React
- Rutas de API para Transacciones - mensajes construidos por el servidor, patrocinio y backends de Acciones
- Almacenamiento en Caché y Tiempo Real - patrones de invalidación de SWR/React Query más WebSocket
Versiones de la pila: Esta página fue escrita para Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, Rust 1.91.1, y @solana/kit 7.0.0.