Own a piece of the internet. 1,000,000 pixels. One URL. Forever.
pixelboard/
βββ backend/
β βββ server.js # Express + Socket.IO entry point
β βββ config/
β β βββ env.js # Environment config
β β βββ db.js # PostgreSQL pool
β βββ routes/
β β βββ blocks.js # Pixel block CRUD + collision detection
β β βββ payments.js # Stripe Checkout + webhook
β β βββ users.js # Auth + user profile
β β βββ admin.js # Admin panel API
β β βββ stats.js # Public stats endpoint
β βββ middleware/
β β βββ auth.js # JWT middleware
β β βββ errorHandler.js # Global error handler
β βββ services/
β βββ pricing.js # Dynamic + prime-zone pricing
β βββ realtime.js # Socket.IO setup
β βββ storage.js # S3/Cloudinary image upload
β
βββ frontend/
β βββ src/
β βββ components/
β β βββ PixelGrid.jsx # Canvas grid (zoom, pan, select)
β β βββ Sidebar.jsx # Buy / Explore / Leaderboard
β β βββ BuyModal.jsx # 3-step purchase flow
β β βββ BlockTooltip.jsx # Hover tooltip
β β βββ MiniMap.jsx # Overview minimap
β β βββ ActivityFeed.jsx # Real-time purchases
β β βββ ShareCard.jsx # Viral share card
β β βββ AdminPanel.jsx # Admin dashboard
β βββ store/
β β βββ gridStore.js # Zustand: blocks + occupancy
β β βββ pricingStore.js # Zustand: live pricing
β β βββ uiStore.js # Zustand: modals, tabs
β βββ hooks/
β β βββ useSocket.js # Socket.IO connection
β β βββ useOccupancy.js # Binary occupancy check
β βββ pages/
β βββ Home.jsx # Main billboard page
β βββ Success.jsx # Post-payment success
β βββ Profile.jsx # User's owned pixels
β
βββ database/
βββ schema.sql # Full PostgreSQL schema
- Node.js 20+
- PostgreSQL 15+
- Stripe account (for payments)
- Cloudinary or S3 (for image uploads)
git clone https://github.com/yourname/pixelboard
cd pixelboard
# Backend
cd backend && npm install
# Frontend
cd ../frontend && npm installbackend/.env
PORT=4000
FRONTEND_URL=http://localhost:5173
DATABASE_URL=postgresql://user:pass@localhost:5432/pixelboard
JWT_SECRET=your-super-secret-jwt-key
IP_SALT=random-salt-for-ip-hashing
# Stripe
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
# Storage (choose one)
CLOUDINARY_URL=cloudinary://api_key:api_secret@cloud_name
# or AWS:
AWS_ACCESS_KEY_ID=...
AWS_SECRET_ACCESS_KEY=...
AWS_S3_BUCKET=pixelboard-images
# Pricing
BASE_PRICE_PER_PIXEL=0.10
PRIME_MULTIPLIER=2.0
MODERATION_REQUIRED=falsefrontend/.env
VITE_API_URL=http://localhost:4000/api
VITE_WS_URL=http://localhost:4000
VITE_STRIPE_PUBLISHABLE_KEY=pk_test_...psql -U postgres -c "CREATE DATABASE pixelboard;"
psql -U postgres -d pixelboard -f database/schema.sql# Terminal 1 β Backend
cd backend && npm run dev
# Terminal 2 β Frontend
cd frontend && npm run devstripe listen --forward-to localhost:4000/api/payments/webhook| Method | Endpoint | Description |
|---|---|---|
| GET | /api/blocks |
All approved blocks |
| GET | /api/blocks/occupancy |
Binary occupancy bitmap |
| POST | /api/blocks/check |
Validate selection (no auth) |
| POST | /api/blocks |
Create block (post-payment) |
| POST | /api/blocks/:id/click |
Record click |
| GET | /api/blocks/search |
Search + filter blocks |
| GET | /api/stats |
Public statistics |
| POST | /api/payments/create-session |
Stripe Checkout session |
| POST | /api/payments/webhook |
Stripe webhook |
| GET | /api/admin/dashboard |
Admin summary |
| PATCH | /api/admin/blocks/:id/status |
Approve/reject |
- Database layer: PostgreSQL GiST spatial index +
BOXoverlap operator (&&) + trigger that raises exception on any overlap. Zero false approvals possible. - Frontend layer: Server-fetched binary occupancy bitmap (125KB for 1M pixels, decoded as
Uint8Array). Bit-level lookup = O(1) per pixel. Client checks before payment, server re-validates at write.
- Canvas 2D rendering (not DOM) for 1M-pixel grid β handles 10,000+ blocks smoothly
- Binary occupancy map transferred as
application/octet-streamβ 125KB vs ~MB for JSON - Socket.IO broadcasts real-time block additions β clients patch their local bitmap
- DB GiST index makes spatial queries sub-millisecond
Base price: $0.10/pixel
Prime zone (center 400Γ400): $0.20/pixel
Dynamic scarcity multipliers:
0β25% sold: 1.0Γ β $0.10/px
25β50% sold: 1.5Γ β $0.15/px
50β75% sold: 2.5Γ β $0.25/px
75β90% sold: 5.0Γ β $0.50/px
90β100% sold: 10Γ β $1.00/px
Revenue at full sell-out (with prime): ~$116,000
{
"express": "^4.18",
"pg": "^8.11",
"stripe": "^14",
"socket.io": "^4.6",
"jsonwebtoken": "^9",
"multer": "^1.4",
"helmet": "^7",
"express-rate-limit": "^7",
"cloudinary": "^1.41"
}{
"react": "^18",
"vite": "^5",
"zustand": "^4",
"socket.io-client": "^4",
"axios": "^1.6",
"@stripe/stripe-js": "^2",
"tailwindcss": "^3",
"framer-motion": "^11"
}| Layer | Service |
|---|---|
| Frontend | Vercel (auto-deploy from GitHub) |
| Backend | Railway or Render |
| Database | Supabase (managed Postgres) |
| Images | Cloudinary free tier β paid |
| CDN | Cloudflare (free) |
Supabase provides PostgreSQL + realtime + storage out of the box.
Replace pool with Supabase client and use their storage for images.
The schema.sql works directly on Supabase.
-- Add a demo admin user
INSERT INTO users (email, name, role) VALUES ('admin@pixelboard.io', 'Admin', 'admin');
-- Add example blocks
INSERT INTO pixel_blocks (x,y,width,height,tooltip_name,tooltip_desc,redirect_url,color,status,price_paid)
VALUES
(10, 10, 80, 60, 'TechCorp', 'Building the future', 'https://techcorp.io', '#534AB7', 'approved', 480),
(120,20, 50, 50, 'GreenAI', 'Sustainable tech', 'https://greenai.com', '#1D9E75', 'approved', 250),
(200,100,100, 80, 'Launchpad', 'Startup accelerator', 'https://launchpad.io', '#D85A30', 'approved', 800),
(400,400,120,100, 'MetaVerse', 'Digital worlds', 'https://metaverse.xyz', '#3266ad', 'featured',2400),
(600, 50, 60, 60, 'CryptoPay','Web3 payments', 'https://cryptopay.io', '#BA7517', 'approved', 360);