Back to Home

$ examples

// Real-world use cases and integration guides

EXAMPLE 1

TypeScript Full-Stack

Build an NFT-gated API with Express backend and React frontend. Users authenticate with their Solana wallet to access protected content.

$ what-you-will-build

NFT-Gated API

Protect API endpoints that only NFT holders can access

React Dashboard

Frontend with wallet connection and protected content display

Production Ready

Complete with error handling, TypeScript, and best practices

$ prerequisites

  • [✓] Node.js 18+ installed
  • [✓] Basic TypeScript knowledge
  • [✓] Solana wallet (Phantom, Backpack, or Solflare)
  • [✓] Text editor (VS Code recommended)

$ step-by-step-guide

1

Project Setup

# Create project directory
mkdir nft-gated-api
cd nft-gated-api

# Initialize projects
mkdir server client
cd server && npm init -y
cd ../client && npm create vite@latest . -- --template react-ts

This creates a monorepo structure with separate server and client directories.

2

Install Dependencies

# Server dependencies
cd server
npm install @openkitx403/server express cors dotenv
npm install -D @types/express @types/cors tsx typescript

# Client dependencies
cd ../client
npm install @openkitx403/client @solana/web3.js
3

Write the Code

import express from 'express';
import cors from 'cors';
import { createOpenKit403, inMemoryLRU } from '@openkitx403/server';
import { Connection, PublicKey } from '@solana/web3.js';

const app = express();
app.use(cors());

// Initialize OpenKit403
const openkit = createOpenKit403({
  issuer: 'nft-gated-api',
  audience: 'http://localhost:3000',
  ttlSeconds: 60,
  replayStore: inMemoryLRU(),
  
  // Token gate: require specific NFT
  tokenGate: async (address: string) => {
    const connection = new Connection('https://api.mainnet-beta.solana.com');
    const pubkey = new PublicKey(address);
    
    // Check if wallet owns NFT from specific collection
    const NFT_COLLECTION = new PublicKey('YOUR_NFT_MINT_ADDRESS');
    
    const tokenAccounts = await connection.getParsedTokenAccountsByOwner(
      pubkey,
      { mint: NFT_COLLECTION }
    );
    
    return tokenAccounts.value.length > 0;
  }
});

// Public route
app.get('/api/public', (req, res) => {
  res.json({ message: 'This is public data' });
});

// Protected routes
const protectedRouter = express.Router();
protectedRouter.use(openkit.middleware());

protectedRouter.get('/profile', (req, res) => {
  const user = (req as any).openkitx403User;
  res.json({
    address: user.address,
    username: `NFT Holder ${user.address.slice(0, 6)}`,
    tier: 'Premium',
    joinedAt: new Date().toISOString()
  });
});

protectedRouter.get('/exclusive-content', (req, res) => {
  res.json({
    content: 'This is exclusive content only for NFT holders!',
    secretCode: 'HOLDER-' + Math.random().toString(36).substr(2, 9)
  });
});

app.use('/api/protected', protectedRouter);

const PORT = 3000;
app.listen(PORT, () => {
  console.log(`✅ Server running on http://localhost:${PORT}`);
});
4

Run the Application

# Terminal 1 - Start server
cd server
npx tsx server.ts

# Terminal 2 - Start client
cd client
npm run dev

• Server runs on http://localhost:3000

• Client runs on http://localhost:5173

• Open client in browser and connect your wallet

$ expected-output

[SUCCESS]

✅ Wallet connected: 5Gv8q5t...

✅ Authentication successful

✅ Profile loaded

✅ Exclusive content displayed

$ next-steps

Deploy to Production

Deploy server to Railway/Render and client to Vercel

Add Features

Implement token-gating, role-based access, webhooks

Download Complete Code

Get the complete working example with additional features, tests, and documentation.