For AI Agents: This file is optimized for Claude and other AI coding assistants. Start with the Quick Reference section for common tasks, then consult detailed sections as needed.
# Development
npm run dev # Start dev server (port 3000)
npm run build # Build for production
npm run start # Start production server
# Validation (RUN BEFORE COMMITTING)
npm run type-check # TypeScript validation
npm run lint # ESLint checks
# Database
npm run db:init # Initialize SQLite database
npm run db:fetch-metadata # Fetch NFT metadata to DB
# Contracts
npm run compile # Compile Solidity contracts
# Testing
npm run test:network # Test Monad RPC connection| Purpose | File(s) |
|---|---|
| Environment config | lib/config.ts |
| Database operations | lib/db.ts |
| Star Skrumpey logic | lib/starSkrumpey.ts |
| RPC client with fallback | lib/rpcClient.ts |
| Wagmi/chain config | lib/wagmi.ts |
| API routes | app/api/*/route.ts |
| React components | components/*.tsx |
| Page components | app/*/page.tsx |
| Environment variables | .env.example (template) |
dev branch, NOT main.
git checkout dev
git checkout -b feature/your-feature
# Make changes
npm run type-check && npm run lint && npm run build
# Commit and push your feature branch- Always run validation:
npm run type-check && npm run lint - Test build:
npm run build - Use existing patterns: Check similar files for conventions
- Preserve existing tests: Don't remove working test infrastructure
Create file at app/api/{endpoint}/route.ts:
import { NextRequest, NextResponse } from 'next/server';
export async function GET(request: NextRequest) {
try {
const { searchParams } = new URL(request.url);
const param = searchParams.get('param');
if (!param) {
return NextResponse.json({ error: 'Missing param' }, { status: 400 });
}
return NextResponse.json({ success: true, data: param });
} catch (error) {
console.error('API Error:', error);
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
}
}
export async function POST(request: NextRequest) {
try {
const body = await request.json();
return NextResponse.json({ success: true });
} catch (error) {
console.error('API Error:', error);
return NextResponse.json({ error: 'Internal server error' }, { status: 500 });
}
}Add schema in lib/db.ts initDatabase() function:
db.exec(`
CREATE TABLE IF NOT EXISTS user_activity (
id INTEGER PRIMARY KEY AUTOINCREMENT,
wallet_address TEXT NOT NULL,
activity_type TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_user_activity_wallet ON user_activity(wallet_address);
`);// components/NewComponent.tsx
'use client';
interface NewComponentProps {
title: string;
onAction?: () => void;
}
export default function NewComponent({ title, onAction }: NewComponentProps) {
return (
<div className="bg-black/80 border border-[#00f7ff]/30 rounded-lg p-4">
<h2 className="text-[#00f7ff] font-['Press_Start_2P'] text-sm">{title}</h2>
{onAction && (
<button
onClick={onAction}
className="mt-2 px-4 py-2 bg-[#00f7ff]/20 hover:bg-[#00f7ff]/30
border border-[#00f7ff] text-[#00f7ff] rounded"
>
Action
</button>
)}
</div>
);
}import { useAccount, useReadContract, useWriteContract } from 'wagmi';
// Read from contract
const { data, isLoading } = useReadContract({
address: CONTRACT_ADDRESS,
abi: CONTRACT_ABI,
functionName: 'balanceOf',
args: [userAddress],
});
// Write to contract
const { writeContract } = useWriteContract();
writeContract({
address: CONTRACT_ADDRESS,
abi: CONTRACT_ABI,
functionName: 'transfer',
args: [recipient, amount],
});| ❌ DON'T | ✅ DO INSTEAD |
|---|---|
| Fetch NFT metadata from IPFS directly | Use getStarSkrumpeyMetadataBatch() from lib/db |
| Make sequential RPC calls in loops | Use checkStarOwnershipBatched() from lib/starSkrumpey |
| Hardcode RPC endpoints | Use getResilientClient() from lib/rpcClient |
Create PRs targeting main |
Target dev branch |
| Commit without running validation | Run npm run type-check && npm run lint && npm run build |
Use any type in TypeScript |
Define proper interfaces |
--neon-cyan: #00f7ff /* text-[#00f7ff], border-[#00f7ff] */
--neon-magenta: #ff00ff /* text-[#ff00ff] */
--neon-gold: #ffd700 /* text-[#ffd700] */
--deep-purple: #1a0033 /* bg-[#1a0033] */
--dark-navy: #0a0015 /* bg-[#0a0015] */- Headings:
font-['Press_Start_2P'](retro pixel font) - Body text: Default system font stack
// Standard card/panel
<div className="bg-black/80 backdrop-blur-md border border-[#00f7ff]/30 rounded-lg p-4 shadow-[0_0_15px_rgba(0,247,255,0.3)]">
// Neon glow button
<button className="px-4 py-2 bg-[#00f7ff]/20 hover:bg-[#00f7ff]/30 border border-[#00f7ff] text-[#00f7ff] rounded transition-all hover:shadow-[0_0_10px_#00f7ff]">Star World Order (SWO) is a Sub-DAO for Star Skrumpey holders on Monad blockchain.
| Property | Value |
|---|---|
| Website | https://starworldorder.com |
| https://x.com/StrWorldOrder | |
| Parent Project | https://x.com/skrumpeys |
| Repository | https://github.com/InverseAltruism/Star-World-Order |
Features: Retro N64-inspired UI with synthwave aesthetics, DAO governance, OTC marketplace, NFT staking, and community hangout hub.
| Layer | Technology | Version |
|---|---|---|
| Frontend | Next.js | 16 |
| UI Framework | React | 19 |
| Language | TypeScript | 5.9+ |
| Styling | Tailwind CSS | 4 |
| Web3 Library | Wagmi | 3 |
| Ethereum Client | Viem | 2 |
| Smart Contracts | Solidity | 0.8.20 |
| Contract Library | OpenZeppelin | 5.x |
| Database | SQLite | better-sqlite3 |
| Blockchain | Monad | Chain ID: 143 |
| Discord Bot | discord.js | TypeScript + Viem |
NEXT_PUBLIC_ENV_MODE=dev # All features unlocked
NEXT_PUBLIC_ENV_MODE=prod # DAO, Exchange hidden from navigationAuto-detection (if not set): localhost/192.168.x.x → dev, starworldorder.com → prod, unknown → prod
| Branch | Purpose | Port | Deployment |
|---|---|---|---|
main |
Production | 3080 | https://starworldorder.com |
dev |
Development/Testing | 3081 | Internal testing |
Workflow: Create PR → dev → Test → Merge dev → main → Deploy
/opt/star_world_order/
├── DEV/ # dev branch (port 3081)
├── PROD/ # main branch (port 3080)
├── SWO_bot/ # Discord bot
├── deploy-dev.sh, deploy-prod.sh, health-check.sh
└── logs/
/opt/swo/
├── data/swo.db # PROD database
├── data/swo-test.db # Test database
├── backups/ # Daily backups
└── scripts/, logs/
# Service management
sudo systemctl status star-world
sudo systemctl restart star-world
sudo journalctl -u star-world -f
# Aliases
swo-health, swo-deploy-dev, swo-deploy-prod, swo-logs, swo-status, swo-restart| Property | Value |
|---|---|
| Location | /opt/star_world_order/SWO_bot/ |
| Process Manager | pm2 (swo-bot) |
| Sync Interval | Every 5 minutes |
| Role | Requirement | Env Var |
|---|---|---|
| 👑 COSMIC EMPEROR | 10+ Stars | COSMIC_EMPEROR_ROLE_ID |
| ⚔️ STAR LORD | 5-9 Stars | STAR_LORD_ROLE_ID |
| 🛡️ COSMIC WARDEN | 2-4 Stars | COSMIC_WARDEN_ROLE_ID |
| ⭐ STAR FORGED | 1 Star | STAR_FORGED_ROLE_ID |
| Command | Description |
|---|---|
/verify |
Force verification check |
/status |
View verification status |
/tiers |
Display tier requirements |
/link <wallet> |
Link wallet via MON transfer |
/unlink |
Disconnect wallet |
- User runs
/link 0xTheirWallet - Bot shows verification address and amount (1 MON)
- User sends MON from their wallet
- User clicks "Verify Transaction"
- Bot verifies and links wallet + assigns roles
DISCORD_BOT_TOKEN=...
DISCORD_GUILD_ID=...
DISCORD_CLIENT_ID=...
COSMIC_EMPEROR_ROLE_ID=...
STAR_LORD_ROLE_ID=...
COSMIC_WARDEN_ROLE_ID=...
STAR_FORGED_ROLE_ID=...
DB_PATH=/opt/swo/data/swo.db
MONAD_RPC=https://rpc.monad.xyz
VERIFICATION_ADDRESS=0x...
VERIFICATION_AMOUNT=1pm2 status # Check status
pm2 logs swo-bot # View logs
pm2 restart swo-bot # Restart| Property | Value |
|---|---|
| Chain ID | 143 (0x8f) |
| Currency | MON |
| RPC (Primary) | https://rpc.monad.xyz |
| Explorer | https://monadscan.com |
RPC Fallbacks: rpc1-4.monad.xyz, rpc-mainnet.monadinfra.com, monad-mainnet.drpc.org
RPC: https://testnet-rpc.monad.xyz | Explorer: https://testnet.monadscan.com
| Contract | Address | Status |
|---|---|---|
| Skrumpeys NFT | 0xb0dad798c80e40dd6b8e8545074c6a5b7b97d2c0 |
✅ Live |
| Multicall3 | 0xcA11bde05977b3631167028862bE2a173976CA11 |
✅ Live |
| StarSkrumpeyMarketplace | TBD | Pending |
| StarSkrumpeyStaking | TBD | Pending |
| StarWorldOrderGovernor | TBD | Pending |
OTC peer-to-peer NFT marketplace for Star Skrumpey trading.
Features: Fixed-price listings, trustless atomic swaps, DAO fee (2.5%), pausable, reentrancy protected
function createListing(uint256 tokenId, uint256 price) external returns (uint256 listingId);
function buyListing(uint256 listingId) external payable;
function cancelListing(uint256 listingId) external;
function getListing(uint256 listingId) external view returns (Listing memory);
function calculateFees(uint256 price) external view returns (uint256 daoFee, uint256 sellerProceeds);NFT staking system with time-based multipliers.
| Lock Duration | Multiplier |
|---|---|
| 1 week | 110% |
| 1 month | 130% |
| 3 months | 150% |
| 6 months | 175% |
| 1 year | 200% |
function stake(uint256 tokenId, uint256 lockDuration) external;
function stakeMultiple(uint256[] calldata tokenIds, uint256 lockDuration) external;
function unstake(uint256 tokenId) external;
function emergencyUnstake(uint256 tokenId) external; // 10% penalty
function claimRewards() external;
function getPendingRewards(address user) external view returns (uint256);DAO governance: 1 Star Skrumpey = 1 Vote, three-way voting (Yes/No/Abstain)
Proposal States: Pending → Active → Defeated/Succeeded → Executed/Cancelled
function propose(address[] memory targets, uint256[] memory values, bytes[] memory calldatas, string memory description) external returns (uint256);
function castVote(uint256 proposalId, uint8 support) external returns (uint256);
function castVoteWithReason(uint256 proposalId, uint8 support, string calldata reason) external returns (uint256);
function execute(...) external payable returns (uint256);
function cancel(...) external returns (uint256);- Total: 333 NFTs with Star constellation trait
- Source:
lib/starSkrumpey.ts-STAR_SKRUMPEY_IDSarray - Lookup: O(1) using Set data structure
- Variants: aether, spectra, solveil, nebulu, chroma, rose, monflare, auracore, parallel, prime
Location: /opt/swo/data/swo.db (PROD) | /opt/swo/data/swo-test.db (DEV)
| Table | Purpose |
|---|---|
chat_messages |
Hangout Hub chat history |
online_presence |
Online users and status |
voice_sessions |
Voice chat sessions |
voice_participants |
Users in voice sessions |
social_connections |
Discord/X OAuth links |
user_profiles |
Display names, bios, avatars |
star_skrumpey_metadata |
Primary NFT metadata source |
user_xp |
Experience points and levels |
quests |
Quest definitions |
user_quests |
User quest progress |
notifications |
User notifications (wallet_address='global' for all) |
notification_settings |
User notification preferences |
friends |
Friend relationships |
direct_messages |
Private messages |
raffles |
Raffle definitions |
raffle_entries |
Raffle participation |
CREATE TABLE star_skrumpey_metadata (
id INTEGER PRIMARY KEY AUTOINCREMENT,
token_id INTEGER NOT NULL UNIQUE,
name TEXT NOT NULL,
description TEXT,
image_url TEXT NOT NULL,
constellation TEXT, -- The CORRECT constellation type
aura TEXT, background TEXT, eyes TEXT, form TEXT, mood TEXT,
attributes_json TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);Usage:
import { getStarSkrumpeyMetadataBatch } from '@/lib/db';
const metadataMap = getStarSkrumpeyMetadataBatch(tokenIds);CREATE TABLE user_xp (
id INTEGER PRIMARY KEY AUTOINCREMENT,
wallet_address TEXT NOT NULL UNIQUE,
total_xp INTEGER NOT NULL DEFAULT 0,
level INTEGER NOT NULL DEFAULT 1,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);Level Formula: Level = floor(sqrt(XP / 100)) + 1
CREATE TABLE notifications (
id INTEGER PRIMARY KEY AUTOINCREMENT,
wallet_address TEXT NOT NULL, -- 'global' for all users
type TEXT NOT NULL CHECK (type IN ('quest', 'achievement', 'system', 'social', 'governance')),
title TEXT NOT NULL,
message TEXT NOT NULL,
link TEXT,
icon TEXT DEFAULT '🔔',
is_read INTEGER NOT NULL DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);CREATE TABLE quests (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT NOT NULL,
xp_reward INTEGER NOT NULL DEFAULT 100,
quest_type TEXT NOT NULL CHECK (quest_type IN ('daily', 'weekly', 'one_time', 'urgent')),
category TEXT NOT NULL DEFAULT 'general',
requirements_json TEXT,
is_active INTEGER NOT NULL DEFAULT 1,
priority INTEGER NOT NULL DEFAULT 0,
icon TEXT DEFAULT '⭐',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
expires_at DATETIME
);
CREATE TABLE user_quests (
id INTEGER PRIMARY KEY AUTOINCREMENT,
wallet_address TEXT NOT NULL,
quest_id TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'available' CHECK (status IN ('available', 'in_progress', 'completed', 'claimed')),
progress INTEGER NOT NULL DEFAULT 0,
started_at DATETIME,
completed_at DATETIME,
claimed_at DATETIME,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE(wallet_address, quest_id)
);CREATE TABLE raffles (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
description TEXT,
prize_description TEXT NOT NULL,
prize_image_url TEXT,
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active', 'ended', 'drawn', 'cancelled')),
created_by TEXT NOT NULL,
start_time DATETIME NOT NULL,
end_time DATETIME NOT NULL,
winner_address TEXT,
winner_drawn_at DATETIME,
winner_draw_seed TEXT,
discord_bonus_enabled INTEGER NOT NULL DEFAULT 0,
require_x INTEGER NOT NULL DEFAULT 0,
require_discord INTEGER NOT NULL DEFAULT 0,
tweet_url TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE raffle_entries (
id INTEGER PRIMARY KEY AUTOINCREMENT,
raffle_id TEXT NOT NULL,
wallet_address TEXT NOT NULL,
tier TEXT NOT NULL,
entries_count INTEGER NOT NULL,
discord_bonus INTEGER NOT NULL DEFAULT 0,
engagement_bonus INTEGER NOT NULL DEFAULT 0,
star_count INTEGER NOT NULL,
entered_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE(raffle_id, wallet_address)
);Holder Tiers (Star-only raffles):
| Tier | Stars | Entries |
|---|---|---|
| Cosmic Emperor | 10+ | 4 |
| Star Lord | 5-9 | 3 |
| Cosmic Warden | 2-4 | 2 |
| Star Forged | 1 | 1 |
Public Raffle Entry Formula:
entries = regular_skrumpeys + (is_star_holder ? 5 + tier_bonus : 0)
- Each regular Skrumpey = 1 entry
- Star holders get flat 5 bonus + tier bonus (1-4)
- Example: 4 regular + 1 Star (Star Forged) = 4 + (5+1) = 10 entries
Verifiable Randomness: SHA-256 of ${blockHash}-${raffleId}-${timestamp}-${entryCount}
CREATE TABLE social_connections (
id INTEGER PRIMARY KEY AUTOINCREMENT,
wallet_address TEXT NOT NULL,
platform TEXT NOT NULL CHECK (platform IN ('discord', 'x')),
platform_user_id TEXT NOT NULL,
platform_username TEXT,
access_token TEXT,
refresh_token TEXT,
token_expires_at DATETIME,
connected_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE(wallet_address, platform)
);CREATE TABLE friends (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_address TEXT NOT NULL,
friend_address TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending' CHECK (status IN ('pending', 'accepted', 'blocked')),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
UNIQUE(user_address, friend_address)
);
CREATE TABLE direct_messages (
id INTEGER PRIMARY KEY AUTOINCREMENT,
sender_address TEXT NOT NULL,
recipient_address TEXT NOT NULL,
message TEXT NOT NULL,
is_read INTEGER NOT NULL DEFAULT 0,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);Metadata: getStarSkrumpeyMetadata(), getStarSkrumpeyMetadataBatch(), getAllStarSkrumpeyMetadata(), getConstellationDistribution()
XP: getUserXP(), addUserXP(), getXPProgress(), getXPLeaderboard()
Quests: getActiveQuests(), getQuestsByType(), getUrgentQuests(), startQuest(), completeQuest(), claimQuestReward(), getQuestsWithProgress()
Notifications: createNotification(), getNotifications(), markNotificationRead(), markAllNotificationsRead(), getUnreadNotificationCount(), getNotificationSettings(), updateNotificationSettings()
Friends: sendFriendRequest(), acceptFriendRequest(), declineFriendRequest(), getFriends(), getPendingFriendRequests(), areFriends(), blockUser(), removeFriend()
Messages: sendDirectMessage(), getConversation(), getConversations(), markMessagesAsRead(), getUnreadMessageCount(), deleteMessage()
Raffles: createRaffle(), enterRaffle(), drawRaffleWinner(), getRaffleEntries(), getRaffleTotalEntries(), getUserRaffleEntries(), hasViewedRaffleResult(), markRaffleResultViewed()
Admin: getAllUsersWithSocialConnections(), getUserCount(), getDatabaseStats(), getAllNotifications(), cleanupChatMessages(), cleanupOnlinePresence(), cleanupDirectMessages()
Backup: createDatabaseBackup(), listDatabaseBackups(), cleanupOldBackups()
| Endpoint | Methods | Description |
|---|---|---|
/api/metadata |
GET | NFT metadata (DB first, IPFS fallback) |
/api/treasury |
GET | Treasury data (Magic Eden + cache) |
/api/chat |
GET, POST | Chat messages |
/api/presence |
GET, POST, DELETE | Online presence |
/api/voice |
GET, POST, PATCH, DELETE | Voice sessions |
/api/profile |
GET, POST | User profiles |
/api/social-connections |
GET | Social connections |
/api/members |
GET | Star holders with profiles (5-min cache) |
/api/holder-stats |
GET | Holder count history |
| Endpoint | Methods | Description |
|---|---|---|
/api/quests |
GET, POST | Quest system |
/api/user-xp |
GET, POST | XP and levels |
/api/notifications |
GET, POST, PATCH, DELETE | Notifications |
/api/friends |
GET, POST | Friend system |
/api/messages |
GET, POST, PATCH, DELETE | Direct messages |
/api/raffle |
GET, POST | Raffle system |
/api/governance |
GET, POST | DAO voting |
/api/floor-prices |
GET | Public NFT floor prices |
/api/admin |
GET, POST | Admin functions |
| Endpoint | Description |
|---|---|
/api/auth/x |
X OAuth initiation |
/api/auth/callback/x |
X OAuth callback |
/api/cron/refresh-holders |
Refresh holder data (requires CRON_SECRET) |
/api/cron/refresh-floor-prices |
Refresh floor prices |
GET params: action = proposals|proposal|votes|hasVoted|userVote|canChangeVote|canCancel|snapshotStatus|verifySnapshot
POST actions: createProposal, vote, changeVote, cancelProposal, updateState
Voting values: 0 = No, 1 = Yes, 2 = Abstain
GET params: type = active|upcoming|past|all|history, id, address, export=csv
POST actions: enter, create, draw, end, cancel, markViewed
GET actions: health, notifications, allNotifications, users, dbStats, drawnRaffles
POST actions: clearCache, createNotification, deleteNotification, updateNotification, broadcastNotification, cleanup functions
Auth: Requires x-admin-auth header with format address:timestamp:signature
Uses Magic Eden's public Monad API (no API key required, 180 QPM limit).
Endpoint: POST https://api-mainnet.magiceden.dev/v4/evm-public/collections/user-collections
{ "chain": "monad", "walletAddresses": ["0x..."] }Caching: In-memory 1hr/address, SQLite 24hr for treasury, exponential backoff on 429s
Primary source for NFT floor prices. Runs on our infrastructure, scraping Magic Eden every 30 minutes.
| Property | Value |
|---|---|
| API Base | https://starworldorder.com/nft/api |
| Scheduler | Every 30 minutes via systemd |
| Database | ~/.me_scraper/floor_prices.db |
| Collections Tracked | 32+ |
Endpoints:
| Endpoint | Description |
|---|---|
/api/health |
Health check |
/api/collections |
All collection floor prices |
/api/collections/{name} |
Single collection with 24h history |
/api/stats |
Scraper statistics |
Usage in Treasury:
import { getLocalApiFloorPrices } from '@/lib/floorPriceApi';
const prices = await getLocalApiFloorPrices(); // Map<collectionName, floorPrice>Floor Price Priority:
- Local API (by collection name) - fastest, our own data
- BlockVision (by contract address) - external API fallback
- Database (by contract address) - manual entries fallback
Used for floor prices as fallback when local API doesn't have the collection.
BLOCKVISION_API=your-api-key-here- Batched Multicall: Check all 333 Star IDs in one call
- Star Ownership Cache: 30-second in-memory cache to prevent duplicate RPC calls
- Fallback Endpoints: Rotate through multiple RPCs
- Exponential Backoff: Retry with 1s, 2s, 4s delays
- Graceful Degradation: Return empty array on total failure
const ownershipChecks = await client.multicall({
contracts: STAR_SKRUMPEY_IDS.map(tokenId => ({
address: SKRUMPEY_CONTRACT_ADDRESS,
abi: ERC721_ABI,
functionName: 'ownerOf',
args: [BigInt(tokenId)],
})),
allowFailure: true,
});| File | Purpose |
|---|---|
lib/config.ts |
Environment mode detection |
lib/starSkrumpey.ts |
Star verification, token IDs, ownership |
lib/wagmi.ts |
Chain configuration |
lib/rpcClient.ts |
RPC fallback and retry |
lib/magiceden.ts |
Magic Eden API |
lib/floorPriceApi.ts |
Local floor price API integration |
lib/blockvision.ts |
BlockVision API (fallback floor prices) |
lib/floorPrices.ts |
Database floor prices (manual entries) |
lib/db.ts |
Database operations (3500+ lines) |
components/Header.tsx |
Navigation |
components/AccessGate.tsx |
NFT gating |
components/ProfileCard.tsx |
Profile UI |
app/page.tsx |
Home (N64 boot) |
app/dao/page.tsx |
DAO governance |
app/hangout/page.tsx |
Hangout Hub |
app/treasury/page.tsx |
Treasury |
app/raffle/page.tsx |
Cosmic Raffle |
app/admin_xyz/AdminContent.tsx |
Admin Dashboard |
# Environment Mode
NEXT_PUBLIC_ENV_MODE=dev|prod
# Monad Configuration
NEXT_PUBLIC_MONAD_CHAIN_ID=143
NEXT_PUBLIC_MONAD_RPC_URL=https://rpc.monad.xyz
# Contract Addresses
NEXT_PUBLIC_SKRUMPEY_CONTRACT=0xb0dad798c80e40dd6b8e8545074c6a5b7b97d2c0
NEXT_PUBLIC_MARKETPLACE_CONTRACT=
NEXT_PUBLIC_STAKING_CONTRACT=
NEXT_PUBLIC_GOVERNOR_CONTRACT=
# DAO Configuration
NEXT_PUBLIC_DAO_TREASURY_ADDRESS=
NEXT_PUBLIC_DAO_FEE_BPS=250
# Snapshot.org (optional)
NEXT_PUBLIC_SNAPSHOT_SPACE=
NEXT_PUBLIC_SNAPSHOT_HUB=https://hub.snapshot.org
# WalletConnect (optional)
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=
# OAuth (optional)
NEXT_PUBLIC_X_CLIENT_ID=
X_CLIENT_SECRET=
NEXT_PUBLIC_DISCORD_CLIENT_ID=
DISCORD_CLIENT_SECRET=
# Development
NEXT_PUBLIC_DEV_ACCESS_ENABLED=true|false
# Database
DATABASE_URL=file:./data/swo.db
# BlockVision (optional - fallback for floor prices)
BLOCKVISION_API=
# Floor Price API (optional - defaults to https://starworldorder.com/nft/api)
# FLOOR_PRICE_API_URL=https://starworldorder.com/nft/api
# Cron
CRON_SECRET=Hybrid model: SQLite for fast/free voting, Snapshot for decentralized verification (optional)
NEXT_PUBLIC_SNAPSHOT_SPACE=starworldorder.eth
NEXT_PUBLIC_SNAPSHOT_HUB=https://hub.snapshot.orgSee docs/SNAPSHOT_SETUP.md for full setup.
cd /opt/star_world_order/DEV/Star-World-Order
git pull origin dev && npm install
NEXT_PUBLIC_ENV_MODE=dev npm run build
npm start -- -p 3081
# Or: ./deploy-dev.shcd /opt/star_world_order/PROD/Star-World-Order
git pull origin main && npm install
NEXT_PUBLIC_ENV_MODE=prod npm run build
sudo systemctl restart star-world
# Or: ./deploy-prod.sh- User connects wallet
checkStarOwnershipBatched(address)checks all 333 Star token IDs- If owns ≥1 Star → grant access
- If not → show access denied + marketplace link
Dev Override: Set NEXT_PUBLIC_DEV_ACCESS_ENABLED=true in .env.local
| Schedule | Command | Description |
|---|---|---|
*/30 * * * * |
health-check.sh |
Health check |
0 3 * * * |
backup-db.sh |
Daily backup |
0 3 * * 0 |
sync-prod-to-test.sh |
Weekly sync |
| Issue | Solution |
|---|---|
| RPC rate limiting | Batched multicall should prevent; check endpoint health, try fallback |
| Database locked | One process at a time; check zombies; restart service |
| Build failures | Clear .next and node_modules; check Node.js 20+ |
| Contract not found | Verify env vars; check explorer; confirm network |
| Bot roles not updating | Check bot permissions; verify role hierarchy; check role IDs |
| Bot transaction not found | Wait for confirmation; check wallet direction; must occur after /link |
- Read relevant CLAUDE.md sections
- Check existing patterns in similar files
- Review
.env.example
- Use TypeScript with proper types
- Follow synthwave theme
- Use existing utilities from
lib/ - Add error handling
- Use Wagmi hooks for blockchain
-
npm run type-checkpasses -
npm run lintpasses -
npm run buildsucceeds - PR targets
devbranch
Star-World-Order/
├── app/ # Next.js App Router
│ ├── api/ # API routes
│ │ ├── admin/, chat/, friends/, messages/
│ │ ├── notifications/, profile/, quests/
│ │ ├── raffle/, treasury/, user-xp/, governance/
│ ├── admin_xyz/, dao/, gallery/, hangout/
│ ├── marketplace/, members/, profile/, raffle/, treasury/
│ ├── globals.css, layout.tsx, page.tsx, providers.tsx
├── components/ # React components
├── lib/ # Utilities
│ ├── config.ts, db.ts, starSkrumpey.ts
│ ├── rpcClient.ts, wagmi.ts, magiceden.ts
│ ├── blockvision.ts, contexts/, hooks/
├── contracts/ # Solidity contracts
├── scripts/, docs/, public/, data/
- Always use
devbranch for PRs - Use database for NFT metadata instead of IPFS
- Use multicall for RPC to avoid rate limiting
- Use resilient RPC client from
lib/rpcClient.ts - Follow synthwave theme for UI components
- Check similar existing files for patterns
- Review anti-patterns section
- Look at
lib/db.tsfor database operations - Check
lib/starSkrumpey.tsfor NFT operations - Review API routes in
app/api/for endpoint patterns
Last Updated: January 20, 2026
Repository: https://github.com/InverseAltruism/Star-World-Order