A modern full-stack AI-enabled template using Next.js for frontend and Express.js for backend, with Telegram and OpenAI integrations! ✨
This template is specially crafted for the Cursor IDE, offering:
- 🤖 AI-assisted development with inline code explanations
- 🔍 Smart environment variable setup assistance
- 💡 Intelligent error resolution
- 📝 Context-aware code completion
- 🛠️ Built-in debugging helpers
Just highlight any error message, code snippet, or variable in Cursor and ask the AI for help!
Cmd/Ctrl + K
: Ask AI about highlighted codeCmd/Ctrl + L
: Get code explanationsCmd/Ctrl + I
: Generate code completions- Highlight any error message to get instant fixes
- Prerequisites:
node >= 22 🟢
pnpm >= 9.14.1 📦
- Install dependencies:
pnpm install
- Fire up the dev servers:
pnpm run dev
.
├── 📦 client/ # Next.js frontend
│ ├── 📱 app/ # Next.js app router (pages, layouts)
│ ├── 🧩 components/ # React components
│ │ └── HelloWorld.tsx # Example component with API integration
│ ├── 💅 styles/ # Global styles and Tailwind config
│ │ ├── globals.css # Global CSS and Tailwind imports
│ │ └── tailwind.config.ts # Tailwind configuration
│ ├── 🛠️ bin/ # Client scripts
│ │ └── validate-env # Environment variables validator
│ ├── next.config.js # Next.js configuration (API rewrites)
│ ├── .env.example # Example environment variables for client
│ └── tsconfig.json # TypeScript configuration
│
├── ⚙️ server/ # Express.js backend
│ ├── 📂 src/ # Server source code
│ │ ├── 🛣️ routes/ # API route handlers
│ │ │ └── hello.ts # Example route with middleware
│ │ └── index.ts # Server entry point (Express setup)
│ ├── 🛠️ bin/ # Server scripts
│ │ ├── validate-env # Environment validator
│ │ └── www-dev # Development server launcher
│ └── tsconfig.json # TypeScript configuration
│
├── 📦 scripts/ # Project scripts
│ └── dev # Concurrent dev servers launcher
│
├── 📝 .env.example # Root environment variables example for server
├── 🔧 package.json # Root package with workspace config
└── 📦 pnpm-workspace.yaml # PNPM workspace configuration
💡 Pro Tip: In Cursor IDE, highlight any environment variable name and ask the AI for setup instructions!
NEXT_PUBLIC_API_URL
: Backend API URL (default: http://localhost:3001) 🌐NEXT_PUBLIC_TELEGRAM_BOT_NAME
: Telegram bot name without the @ symbol, you can get it from BotFather after creating your bot (default: your_bot_username) 🤖
-
PORT
: Server port (default: 3001) 🚪 -
NODE_ENV
: Environment (development/production) 🌍 -
TELEGRAM_BOT_TOKEN
: 🤖- Open Telegram and search for @BotFather
- Start chat and send
/newbot
- Follow prompts to name your bot
- Copy the provided token
-
OPENAI_API_KEY
: 🧠- Visit https://platform.openai.com/api-keys
- Click "Create new secret key"
- Give it a name and copy the key immediately
- Set usage limits in API settings if needed
-
NGROK_AUTH_TOKEN
: 🔗- Create account at https://dashboard.ngrok.com/signup
- Go to https://dashboard.ngrok.com/get-started/your-authtoken
- Copy your authtoken
-
NGROK_DOMAIN
: 🔗- Go to https://dashboard.ngrok.com/domains
- Copy your domain (without https://)
-
COLLABLAND_API_KEY
: 🤝- Visit https://dev-portal-qa.collab.land/signin
- Click on "Get Started"
- Select Telegram login
- Login with Telegram
- Verify your e-mail with the OTP sent to your inbox
- Click on "Request API Access" on the top right corner, and set up the API key name
- Copy your API key
-
GAIANET_MODEL
: 🤖- Visit https://docs.gaianet.ai/user-guide/nodes
- Choose your model (default: llama)
- Copy the model name
-
GAIANET_SERVER_URL
: 🌐- Visit https://docs.gaianet.ai/user-guide/nodes
- Get server URL for your chosen model
- Default: https://llama8b.gaia.domains/v1
-
GAIANET_EMBEDDING_MODEL
: 🧬- Visit https://docs.gaianet.ai/user-guide/nodes
- Choose embedding model (default: nomic-embed)
- Copy the model name
-
USE_GAIANET_EMBEDDING
: ⚙️- Set to TRUE to enable Gaianet embeddings
- Set to FALSE to disable (default: TRUE)
-
JOKERACE_CONTRACT_ADDRESS
: 🎰- Go to https://www.jokerace.io/contest/new
- Create the contest
- Copy the contract address
-
ELIZA_CHARACTER_PATH
: 🤖- Default: "character.json"
- Points to a JSON file containing your AI agent's personality configuration
- Example paths:
- character.json (default Ace personality)
- vaitalik.json (Vitalik personality)
- custom/my-agent.json (your custom personality)
-
TOKEN_DETAILS_PATH
: Points to a JSON/JSONC file containing your token metadata for minting- Default: "token_metadata.example.jsonc"
- Steps:
- Copy the template:
cp token_metadata.example.jsonc token.jsonc
- Set this env var to point to your file
- Example:
token.jsonc
-
TWITTER_CLIENT_ID
&TWITTER_CLIENT_SECRET
: Authentication credentials for Twitter API integration- Go to Twitter Developer Portal
- Create a new project/app if you haven't already
- Navigate to "Keys and Tokens" section
- Under "OAuth 2.0 Client ID and Client Secret":
- Copy "Client ID" →
TWITTER_CLIENT_ID
- Generate "Client Secret" →
TWITTER_CLIENT_SECRET
- Copy "Client ID" →
- Configure OAuth settings:
- Add callback URL:
http://localhost:3001/auth/twitter/callback
(development) - Add your production callback URL if deploying
- Add callback URL:
- Format: Alphanumeric strings
- Example:
TWITTER_CLIENT_ID=Abc123XyzClientID TWITTER_CLIENT_SECRET=Xyz789AbcClientSecret
-
DISCORD_CLIENT_ID
&DISCORD_CLIENT_SECRET
: Authentication credentials for Discord API integration- Go to Discord Developer Portal
- Click "New Application" or select existing one
- Navigate to "OAuth2" section in left sidebar
- Under "Client Information":
- Copy "Client ID" →
DISCORD_CLIENT_ID
- Copy "Client Secret" →
DISCORD_CLIENT_SECRET
- Copy "Client ID" →
- Configure OAuth settings:
- Add redirect URL:
http://localhost:3001/auth/discord/callback
(development) - Add your production redirect URL if deploying
- Select required scopes (typically
identify
andemail
)
- Add redirect URL:
- Format: Alphanumeric strings
- Example:
DISCORD_CLIENT_ID=123456789012345678 DISCORD_CLIENT_SECRET=abcdef123456789xyz
-
GITHUB_CLIENT_ID
&GITHUB_CLIENT_SECRET
: Authentication credentials for GitHub OAuth integration- Go to GitHub Developer Settings
- Click "New OAuth App" or select existing one
- Under "OAuth Apps" settings:
- Application name: Your app name
- Homepage URL:
http://localhost:3001
(development) - Authorization callback URL:
http://localhost:3001/auth/github/callback
- After creating/selecting the app:
- Copy "Client ID" →
GITHUB_CLIENT_ID
- Generate new "Client Secret" →
GITHUB_CLIENT_SECRET
- Copy "Client ID" →
- Configure OAuth scopes:
- Recommended scopes:
read:user
,user:email
- Recommended scopes:
- Format: Alphanumeric strings
- Example:
GITHUB_CLIENT_ID=1234567890abcdef1234 GITHUB_CLIENT_SECRET=1234567890abcdef1234567890abcdef12345678
Note: For production, update the Homepage URL and callback URL to your production domain.
Security Notes:
- Never commit these values to version control
- Use different credentials for development and production
- Rotate secrets periodically
- Store production secrets in secure environment variables
🔒 Note: Keep these tokens secure! Never commit them to version control. The template's
.gitignore
has your back!
- Build both apps:
pnpm run build
- Launch production servers:
pnpm start
- For production deployment: 🌎
- Set
NODE_ENV=production
- Use proper SSL certificates 🔒
- Configure CORS settings in server/src/index.ts 🛡️
- Set up error handling and logging 📝
- Use process manager like PM2 ⚡
- Client:
const ENV_HINTS = {
NEXT_PUBLIC_API_URL: "Your API URL (usually http://localhost:3001)",
// Add more hints as needed! ✨
};
- Server:
const ENV_HINTS = {
PORT: "API port (usually 3001)",
NODE_ENV: "development or production",
TELEGRAM_BOT_TOKEN: "Get from @BotFather",
OPENAI_API_KEY: "Get from OpenAI dashboard",
NGROK_AUTH_TOKEN: "Get from ngrok dashboard",
// Add more hints as needed! ✨
};
- Add TypeScript types in respective env.d.ts files 📝
- Create new route file in server/src/routes/
- Import and use in server/src/index.ts
- Add corresponding client API call in client/components/
- Create component in client/components/
- Use Tailwind CSS for styling
- Follow existing patterns for API integration
- Create middleware in server/src/middleware/
- Apply globally or per-route basis
- Copy the token metadata template:
cp token_metadata.example.jsonc token.jsonc
- Edit
token.jsonc
with your token details:
{
"name": "YourToken", // Token name
"symbol": "TOKEN", // Token symbol (2-6 chars)
"description": "Your token description",
"websiteLink": "https://yoursite.com",
"twitter": "your_twitter_handle",
"discord": "https://discord.gg/your_server",
"telegram": "your_bot_telegram_username",
"nsfw": false,
"image": "ipfs://your_ipfs_hash", // Upload image to IPFS first
}
- Update
.env
to point to your token file:
TOKEN_DETAILS_PATH=token.jsonc
- Start your bot and use the
/mint
command in Telegram. The bot will:
- Read your token config
- Mint on Base Sepolia testnet
- Return contract details and token page URL
Note: Make sure you have set up your COLLABLAND_API_KEY and TELEGRAM_BOT_TOKEN in .env first.
- Next.js App Router: https://nextjs.org/docs/app 🎯
- Express.js: https://expressjs.com/ ⚡
- Tailwind CSS: https://tailwindcss.com/docs 💅
- TypeScript: https://www.typescriptlang.org/docs/ 📘
Follow these commit message guidelines to automate changelog generation:
feat: add new feature
- New features (generates under 🚀 Features)fix: resolve bug
- Bug fixes (generates under 🐛 Bug Fixes)docs: update readme
- Documentation changes (generates under 📝 Documentation)chore: update deps
- Maintenance (generates under 🧰 Maintenance)
Example:
git commit -m "feat: add OAuth support for Discord"
git commit -m "fix: resolve token validation issue"
- Navigate to lit-actions directory:
cd lit-actions
pnpm install
- Configure environment:
cp .env.example .env
Required variables:
PINATA_JWT
: Your Pinata JWT for IPFS uploadsPINATA_URL
: Pinata gateway URL
- Create new action in
src/actions/
:
/// <reference path="../global.d.ts" />
const go = async () => {
// Access Lit SDK APIs
const tokenId = await Lit.Actions.pubkeyToTokenId({ publicKey });
// Sign data
const signature = await Lit.Actions.signEcdsa({
publicKey,
toSign,
sigName,
});
// Return response
Lit.Actions.setResponse({
response: JSON.stringify({ result: "success" }),
});
};
go();
- Start development server:
pnpm run dev
This will:
- Build TypeScript → JavaScript
- Bundle with dependencies
- Inject SDK shims
- Upload to IPFS
- Watch for changes
- Create shim in
shims/
:
// shims/my-sdk.shim.js
import { MySDK } from "my-sdk";
globalThis.MySDK = MySDK;
- Update types in
src/global.d.ts
:
declare global {
const MySDK: typeof MySDK;
}
# Build only
pnpm run build
# Build & deploy to IPFS
pnpm run start
IPFS hashes are saved to actions/ipfs.json
:
{
"my-action.js": {
"IpfsHash": "Qm...",
"PinSize": 12345,
"Timestamp": "2025-01-03T..."
}
}
The Lit Actions runtime provides:
-
Lit.Actions
signEcdsa()
: Sign data with PKPpubkeyToTokenId()
: Convert public key to token IDgetPermittedAuthMethods()
: Get permitted auth methodscheckConditions()
: Check access control conditionssetResponse()
: Return data to client- Full API in
src/global.d.ts
-
Built-in SDKs
ethers
: Ethereum interactionsBuffer
: Buffer utilities
-
Type Safety
- Always reference
global.d.ts
- Define types for parameters
- Use TypeScript features
- Always reference
-
SDK Management
- Create minimal shims
- Document SDK versions
- Test SDK compatibility
-
Action Structure
- One action per file
- Clear async/await flow
- Proper error handling
-
Deployment
- Test locally first
- Verify IPFS uploads
- Keep actions small
pnpm run dev # Development mode
pnpm run build # Build actions
pnpm run start # Deploy to IPFS
pnpm run lint # Fix code style
pnpm run watch # Watch mode
lit-actions/
├── actions/ # Built JS + IPFS hashes
├── shims/ # SDK shims
├── src/
│ ├── actions/ # TypeScript sources
│ ├── global.d.ts # Type definitions
│ └── index.ts # IPFS deployment
├── esbuild.js # Build config
└── package.json
For more details, check the Lit Protocol docs.