A Halloween-themed interactive gallery showcasing high-quality WebGL and CSS visual effects. Browse "Cursed Cards," experience live demos, and discover the code behind atmospheric micro-interactions.
Spooky Snippets Studio solves the problem of scattered, hard-to-replicate creative coding inspiration. It provides a performant playground where developers can view live Three.js/Pixi.js demos, understand the underlying tech stack, and access implementation logic—all wrapped in a delightfully spooky atmosphere.
- The Haunted Gallery — Responsive grid of interactive "Cursed Cards" with hover animations
- The Séance Room — Full-screen detail view with live WebGL demos and code explanations
- Tech Tags — Color-coded badges (Three.js, Pixi.js, CSS) for quick stack identification
- Curse Counter — Community "Like" system with real-time persistence
- Atmospheric Audio — Optional ambient sounds and UI effects (default: off)
- Snippet Export — One-click code copying for easy implementation
| Layer | Technology |
|---|---|
| Framework | Next.js 14+ (App Router) |
| Language | TypeScript |
| Styling | Tailwind CSS |
| Animation | Framer Motion |
| 3D/2D Graphics | Three.js (@react-three/fiber), Pixi.js |
| State | Zustand |
| Audio | Howler.js |
| Database | Upstash Redis |
| Hosting | Vercel |
┌─────────────────────────────────────────────────────────────┐
│ Vercel Edge Network │
├─────────────────────────────────────────────────────────────┤
│ Gallery (SSG) │ Detail View (CSR) │
│ - Video/Image previews │ - Dynamic WebGL loading │
│ - No WebGL contexts │ - Three.js / Pixi.js canvas │
├─────────────────────────────────────────────────────────────┤
│ Next.js API Routes │ Upstash Redis │
│ - Rate limiting │ - Curse counters │
│ - Input validation │ - Rate limit keys │
└─────────────────────────────────────────────────────────────┘
Key decisions:
- WebGL Isolation — Gallery uses video/image previews only; WebGL reserved for Detail View to prevent context exhaustion
- Static Content — Snippet metadata stored as JSON/MDX files; only curse counts are dynamic
- Serverless — API routes scale automatically with traffic
- Node.js 18.x+
- npm or yarn
- Upstash Redis account (for curse counter)
# Clone the repository
git clone https://github.com/your-org/spooky-snippets-studio.git
cd spooky-snippets-studio
# Install dependencies
npm install
# Set up environment variables
cp .env.example .env.localUPSTASH_REDIS_REST_URL=your_redis_url
UPSTASH_REDIS_REST_TOKEN=your_redis_token
NEXT_PUBLIC_GA_ID=your_ga_measurement_id # Optionalnpm run devOpen http://localhost:3000 to view the gallery.
# Type check and lint
npm run lint
npm run type-check
# Production build
npm run build
# Deploy (auto-deploys on push to main via Vercel)├── app/
│ ├── page.tsx # Gallery (Home)
│ ├── snippet/[id]/ # Detail View (Séance Room)
│ └── api/curses/ # Curse counter API
├── components/
│ ├── gallery/ # Grid and card components
│ ├── canvas/ # WebGL runners (Three.js/Pixi.js)
│ └── ui/ # Shared UI components
├── content/
│ └── snippets/ # JSON/MDX snippet definitions
├── lib/
│ ├── redis.ts # Upstash client
│ └── utils.ts # Helpers
├── public/
│ └── assets/ # GLB models, textures, videos
└── stores/
└── audio.ts # Zustand audio state
Snippets are defined in /content/snippets/*.json:
interface SpookySnippet {
id: string; // "ghostly-graveyard"
title: string; // "The Wandering Spirit"
description: string;
techStack: "Three.js" | "Pixi.js" | "CSS" | "Canvas";
difficulty: "Easy" | "Medium" | "Hard";
codeSnippet: string;
assets: {
thumbnail: string;
previewVideo?: string;
};
config: Record<string, any>;
}Returns curse counts for all snippets.
{ "ghostly-graveyard": 150, "glitch-text": 42 }Increments curse count. Rate limited: 5 requests/minute/IP.
// Request
{ "snippetId": "ghostly-graveyard" }
// Response
{ "snippetId": "ghostly-graveyard", "newCount": 151 }| Metric | Target |
|---|---|
| LCP (Gallery) | < 1.2s |
| TTI | < 1.5s |
| FID | < 100ms |
| Frame Rate (Detail) | 60fps |
| API Latency | < 50ms |
- Rate limiting on all write endpoints
- Zod schema validation for API inputs
- CSP headers restricting script sources
- Secrets stored in Vercel encrypted env vars
- No user authentication required (anonymous interactions)
- Fork the repository
- Create a feature branch (
git checkout -b feature/new-curse) - Commit changes (
git commit -m 'Add new curse effect') - Push to branch (
git push origin feature/new-curse) - Open a Pull Request
MIT
"The spirits are watching..." 👻