Frontend Release Management
The Solana dApp is half the product: Next.js releases carry RPC URLs, program IDs, feature flags, and wallet adapter versions. Mismatched frontend deploys cause more user pain than many on-chain bugs.
Recipe
Quick-reference recipe card - copy-paste ready.
# .env.production
NEXT_PUBLIC_CLUSTER=mainnet-beta
NEXT_PUBLIC_RPC_URL=https://your-mainnet-rpc.example
NEXT_PUBLIC_PROGRAM_ID=Hx7k...
NEXT_PUBLIC_IDL_VERSION=2.4.0import { createSolanaRpc } from "@solana/kit";
const rpc = createSolanaRpc(process.env.NEXT_PUBLIC_RPC_URL!);When to reach for this:
- Shipping UI changes independent of program upgrade
- Rotating RPC provider without program deploy
- Launch week CDN and cache strategy
- Incident rollback of client-only bug
- A/B testing transaction UX patterns
Working Example
// lib/solana-config.ts - validate at module load
const cluster = process.env.NEXT_PUBLIC_CLUSTER;
const programId = process.env.NEXT_PUBLIC_PROGRAM_ID;
const rpcUrl = process.env.NEXT_PUBLIC_RPC_URL;
if (!cluster || !programId || !rpcUrl) {
throw new Error("Missing Solana env vars");
}
if (process.env.VERCEL_ENV === "preview" && cluster === "mainnet-beta") {
throw new Error("Preview builds cannot target mainnet");
}
export const solanaConfig = { cluster, programId, rpcUrl };What this demonstrates:
- Fail-fast env validation in
@solana/kit7.0.0 client - Blocking preview deploys from mainnet cluster
- Single config module imported by app and API routes
Deep Dive
Release Train
- Merge to
main-> staging deploy (devnet RPC) - Smoke: wallet connect, simulate top flows
- Promote to production with production env group
- Tag
dapp-v1.2.3linked toIDL_VERSION
RPC in Frontend
| Path | RPC tier | Notes |
|---|---|---|
| Browser reads | Public or dedicated read | Cache short TTL |
| API route sends | Premium write + SWQoS | Keys server-side only |
| SSR balance | Server read RPC | Watch rate limits |
Gotchas
- NEXT_PUBLIC_ exposes secrets - Never put API keys in public env. Fix: Server-only env for send path.
- Stale ISR cache - Old program ID served. Fix: Revalidate on deploy webhook.
- Wallet adapter drift - Breaking wallet connect after dep bump. Fix: Pin adapter versions in lockfile.
- Program upgrade without client - Users hit wrong ix layout. Fix: IDL version gate in UI.
- A/B without cohort stickiness - Inconsistent tx path. Fix: Wallet-hash cohort (see feature flags page).
Alternatives
| Alternative | Use When | Don't Use When |
|---|---|---|
| Mobile app release | Solana Mobile MWA | Web-only product |
| Edge middleware routing | Multi-region RPC | Simple single RPC |
| Blue/green Vercel | Zero-downtime cutover | Tiny team overhead |
FAQs
How often ship frontend?
Independent of program; many teams ship daily with flags.
Preview URL safety?
Hard-block mainnet env on preview; use devnet program IDs only.
Where store RPC URL?
Env per environment; rotate via hosting provider secrets without rebuild if using runtime config.
Coordinate with program deploy?
Same change window for IDL-breaking releases; frontend can lead with flags.
Rollback speed?
Revert deploy in hosting UI; purge CDN cache; announce if user-facing.
Version display in UI?
Show IDL_VERSION in footer for support correlation.
SSR and wallet?
SSR for reads only; signing stays client-side.
Testing before prod?
Playwright against staging with devnet wallet fixture.
Multiple program IDs?
Config map per program; validate all at build.
Incident comms?
Status page links to deployed version and known-good prior version.
Related
- Feature Flags & Progressive Rollout - gradual enablement
- Devnet to Mainnet Promotion - env promotion
- Providers & App Router - Next.js integration
Stack versions: This page was written for Agave 4.1.1, Solana CLI 3.0.10, Anchor 0.32.1, anchor-lang 0.32.1, Rust 1.91.1, @solana/kit 7.0.0, Surfpool 0.12.0, and LiteSVM 0.6.x.