Skip to main content

ENS Offchain Subnames + Privy Starter Kit

A Next.js starter integrating the Offchain Manager SDK with Privy for creating and managing offchain ENS subnames.

Features

  • Privy auth with embedded wallets and Wagmi
  • Offchain subname creation via secure API routes
  • Reverse resolution for addresses, e.g., 0x23... β†’ happy.offchainsub.eth
  • Preferred identity resolution (subname β†’ ENS β†’ truncated address)
  • Account modal with username creation and avatar upload
Repository: thenamespace/ens-subnames-privy-template

Prerequisites

  • Node.js (v18 or later)
  • An ENS name (e.g., namespace.eth)
  • Namespace API key from the Dev Portal
  • Privy App ID and Client ID (create via Privy Dashboard: dashboard.privy.io/account)

Setup

1

Use as a template or clone

Use GitHub’s template feature:
  1. Open: thenamespace/ens-subnames-privy-template
  2. Click β€œUse this template” β†’ β€œCreate a new repository”
  3. Clone your new repository locally
Or clone directly:
git clone https://github.com/thenamespace/ens-subnames-privy-template.git
cd ens-subnames-privy-template
pnpm install
2

Environment variables

Copy .env.example to .env.local in the project root and fill in values:
# Privy (public; required)
NEXT_PUBLIC_PRIVY_APP_ID=your_privy_app_id
NEXT_PUBLIC_PRIVY_CLIENT_ID=your_privy_client_id

# ENS name (public; required)
NEXT_PUBLIC_ENS_NAME=namespace.eth

# Namespace API key (server; required)
NAMESPACE_API_KEY=your_namespace_api_key

# Network/env (public; optional if not testnet)
NEXT_PUBLIC_NETWORK=mainnet

# Avatar service + SIWE
NEXT_PUBLIC_SIWE_DOMAIN=localhost:3000 # Change to your app domain
NEXT_PUBLIC_SIWE_URI=http://localhost:3000 # Change to your app uri
NEXT_PUBLIC_AVATAR_SERVICE_URL=https://metadata.namespace.ninja
NEXT_PUBLIC_SIWE_CHAIN_ID=1
Notes:
  • Do not expose server-only secrets in client code. The API key is used only server-side.
  • If you change domains or networks, update the SIWE values accordingly.
3

Configure Privy

  1. Sign up/sign in to the Privy Dashboard: dashboard.privy.io/account
  2. Create a new app (Web)
  3. In App settings β†’ Client tab, copy your App ID and Client ID
  4. Add both to .env.local as NEXT_PUBLIC_PRIVY_APP_ID and NEXT_PUBLIC_PRIVY_CLIENT_ID
4

Configure your ENS name

  1. Visit the Namespace Dev Portal
  2. Change the resolver for your ENS name to Namespace’s resolver
  3. Generate and copy your Namespace API key
  4. Add it to your .env.local as NAMESPACE_API_KEY
5

Run the development server

pnpm dev
Open http://localhost:3000 to see the application.
6

It's ready!

Create subname interface with form to create a new offchain subname

What’s included

πŸ” Privy Integration

  • Privy authentication with embedded wallets
  • Wagmi setup for EVM interactions
  • Account modal with subname creation and avatar upload
  • Automatic primary name resolution

File Structure

src/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ api/subname/create/route.ts     # Server-side subname creation
β”‚   β”œβ”€β”€ api/subname/avatar/route.ts     # Update avatar text record
β”‚   β”œβ”€β”€ page.tsx                        # Main demo page
β”‚   └── providers.tsx                   # Privy, Wagmi & React Query setup
β”œβ”€β”€ components/
β”‚   └── ui/
β”‚       β”œβ”€β”€ account-modal.tsx           # Account management modal
β”‚       └── profile-button.tsx          # Connect + open account modal
β”œβ”€β”€ hooks/
β”‚   β”œβ”€β”€ use-subnames.ts                 # Fetch subnames + preferred identity
β”‚   β”œβ”€β”€ use-identity.ts                 # Combine ENS + preferred identity
β”‚   β”œβ”€β”€ use-upload-avatar.ts            # SIWE + upload avatar + update text record
β”‚   └── use-update-ens-avatar.ts        # Helper to update avatar via server API
└── lib/
    β”œβ”€β”€ namespace.ts                    # Server-side client (with API key)
    └── namespace-client.ts             # Client-side client (read-only)

πŸ—οΈ Architecture

  • Server-side Namespace client (/src/lib/namespace.ts) - Uses API key securely for write operations
  • Client-side Namespace client (/src/lib/namespace-client.ts) - For read-only operations without API key exposure
  • API routes (/src/app/api/subname/*/route.ts) - Server-side write operations (create subname, update avatar)
  • Providers (/src/app/providers.tsx) - Privy + Wagmi + React Query providers

πŸͺ Custom Hooks

  • useSubnames - Fetch subnames for an address and build preferred identity
  • useIdentity - Combine ENS with preferred identity
  • useUploadAvatar - SIWE + upload avatar + update text record
  • useUpdateEnsAvatar - Helper to update avatar via server API

πŸ“‘ API Endpoints

  • POST /api/subname/create - Create subnames with custom address and text records
  • POST /api/subname/avatar - Update an ENS avatar text record for a subname

Security & Limitations

⚠️ Important Security Notes

  • Never expose your NAMESPACE_API_KEY to the client side
  • API key is only used in server-side code (/src/lib/namespace.ts and API routes)
  • Client-side operations use the public client without API key
  • All write operations happen in API routes or server-side code only
  • Validate and sanitize inputs in API routes

πŸ“Š Rate Limits

  • Up to 2,000 subnames can be created per API key to prevent abuse
  • Need more? Contact us on the Builders Group

References

⌘I