# YEG SpookyBooth 🎃 > **Edmonton Halloween Magic Photo Experience** > An interactive, responsive, and kiosk-ready photo experience celebrating Canadian autumn folklore and Edmonton's river valley magic. Built with **Next.js**, **React**, **TypeScript**, and **Tailwind CSS**. Users step into the enchanted portal, capture a photo, pick an iconic Canadian/Edmonton Halloween disguise, and receive a transformed 3D cartoon character portrait. --- ## 🌟 Key Features - 🍁 **Edmonton & Canadian Halloween Atmosphere**: - Eerie shimmering **Northern Lights (Aurora Borealis)**. - Silhouettes of the iconic **High Level Bridge**, **Walterdale Arch**, glowing **Muttart Conservatory Pyramids**, and river valley spruce trees. - Radiant harvest moon, drifting autumn maple leaves, friendly bats, and a cute hovering ghost. - 🎨 **Stylized 3D Cartoon Character Disguises**: - 🌟 **Vibe Matcher**: Keep your exact face, outfit, hair & makeup completely unchanged, but replace the background with a funny, exaggerated scene that matches your vibe! - 🎸 **Classic Mullet**: Keep your photo portrait intact while rocking an iconic 80s mullet hairstyle. - đŸ›ī¸ **Muttart Pyramid Witch**: Whimsical young witch brewing emerald potions inside the glass conservatory pyramid. - đŸĻ‡ **High Level Vampire**: Chibi vampire in a winter velvet coat hovering above the foggy bridge. - đŸ§™â€â™‚ī¸ **100% Magical Lore**: Zero robotic AI technical jargon. The entire user experience is written as enchanting spooky spellcraft. - đŸ•šī¸ **Tactile Cartoon Arcade UI**: - Chunky 3D buttons (`.btn-cartoon-orange`, `.btn-cartoon-purple`, `.btn-cartoon-dark`) with satisfying downward click physics. - Bold comic-book outlines and playful cartoon wobbles. - 🧭 **Complete Navigation**: - **`← Back`** buttons across all intermediate screens (Camera, Confirm, Style Selection, and Loading). - Dedicated **`Finish 🏁`** button on the final result screen to reset the booth. - Top navigation bars use a strictly non-overlapping 3-column layout that never covers or blocks buttons. - 📲 **QR Code & Print Ready**: - On-screen QR code allows visitors to scan and instantly save their portrait to their smartphone. - Integrated 1-click photo printing formatted for 4x6 print media via `@media print`. - đŸ›Ąī¸ **Intelligent Content Safety & Zero-Lockout Uptime**: - Automatically identifies and handles image safety filter rejections (e.g. `PROHIBITED_CONTENT`, Safe-for-Work checks). - Safety rejections immediately return the user to the camera/photo capture screen with an interactive Spooky Safety Warning modal to snap or choose another photo. - No API cooldown lockouts: input rejections never penalize or disable the booth for subsequent guests. - âąī¸ **Kiosk Inactivity Auto-Reset**: Automatically resets to the standby welcome screen after $N$ seconds of inactivity. - đŸˇī¸ **Sokaris Studio Attribution**: Built-in footer attribution and copyright link to [sokaris.com](https://sokaris.com). --- ## đŸ–Ĩī¸ Display Modes ### 1. Standard Mode (Default) By default, the booth renders in a centered, vertical 9:16 kiosk viewport (`max-width: 540px`, `max-height: 960px`) on desktop and automatically expands on mobile screens. Ideal for testing, desktop browsing, and tablets: ``` http://localhost:3000 ``` ### 2. Fullscreen Kiosk Mode (`?mode=fullscreen`) For physical event touchscreens, vertical digital signage, or dedicated kiosk hardware, add `?mode=fullscreen` to the URL: ``` http://localhost:3000/?mode=fullscreen ``` **What this does:** 1. Expands the viewport to **100% screen width and 100% screen height** (`100vw` x `100vh`). 2. Removes all desktop borders, rounded corners, and margins. 3. Automatically triggers native browser fullscreen (`document.documentElement.requestFullscreen()`) upon the user's first tap. --- ## 🚀 Quick Start ### 1. Prerequisites - **Node.js** 18.17+ or 20+ - **npm** or **yarn** ### 2. Install Dependencies ```cmd cmd /c npm install ``` ### 3. Configure Environment Variables Copy `.env.example` to `.env.local` and add your API credentials: ```env # Google Gemini API Key (Primary Provider) GEMINI_API_KEY=your_gemini_api_key_here # OpenRouter API Key (Automatic Backup Provider) OPENROUTER_API_KEY=your_openrouter_api_key_here # Model Selection Override (Optional: "nanobanana 2", "nanobanana", "pro", "lite") GENERATION_MODEL=nanobanana 2 ``` *(If no keys are provided, the app will run gracefully in demo fallback mode using pre-rendered sample portraits).* ### 4. Run Development Server ```cmd cmd /c npm run dev ``` Open [http://localhost:3000](http://localhost:3000) (or [http://localhost:3000/?mode=fullscreen](http://localhost:3000/?mode=fullscreen)) in your browser. ### 5. Build for Production ```cmd cmd /c npm run build cmd /c npm start ``` --- ## âš™ī¸ Configuration Guide ### 1. General Settings (`config/booth.config.json`) All booth behaviors and visuals can be customized without editing code: ```json { "appName": "YEG SpookyBooth", "kioskMode": true, "theme": { "backgroundType": "color", "backgroundColor": "#0f091f", "primaryColor": "#ff6d00", "accentColor": "#22c55e", "surfaceColor": "#1e1136", "textColor": "#ffffff", "logoUrl": "/assets/brand/spooky_logo.svg", "logoWidth": 260 }, "camera": { "defaultFacingMode": "user", "aspectRatio": "9:16", "countdownSeconds": 3, "allowUpload": true, "maxUploadSizeMb": 10 }, "features": { "showQrCode": true, "showDownloadButton": true, "showPrintButton": true, "showRetakeButton": true }, "limits": { "maxGenerationsPerDevice": 0, "cooldownMinutes": 60 }, "kiosk": { "enableAutoReset": true, "idleTimeoutSeconds": 90 }, "labels": { "welcomeTitle": "YEG SPOOKY BOOTH", "welcomeSubtitle": "Edmonton Halloween Magic Portal", "welcomeCta": "Tap To Enter If You Dare, Eh! 🎃", "cameraInstruction": "Strike your most spooktacular pose!", "cameraSnap": "Snap Spooky Photo", "cameraUpload": "Upload Photo", "confirmTitle": "Review Your Spooky Shot", "styleSelectionTitle": "Pick Your Halloween Disguise", "styleSelectionSubtitle": "Choose an iconic local legend to transform into", "processingTitle": "Brewing Your Transformation Spell...", "processingSubtitle": "Mixing river valley mist, northern starlight & potion sparks...", "resultTitle": "Your Spooktacular Portrait! 🎃", "scanQrLabel": "Scan to take your treat home", "downloadLabel": "Save Portrait", "printLabel": "Print Photo", "startOverLabel": "Haunt Again" } } ``` ### 2. Styles & Prompts (`config/styles.json`) To add, remove, or modify character disguise presets, edit `config/styles.json`: ```json [ { "id": "yeg_hockey_phantom", "name": "YEG Hockey Phantom", "description": "Friendly vintage hockey ghost on river ice under the glowing Northern Lights", "thumbnail": "/assets/styles/hockey_ghost.jpg", "prompt": "Vibrant 3D cartoon animated character portrait based on the person in the user's photo... Bubbly cartoon animation style, Hotel Transylvania and Pixar aesthetics...", "negativePrompt": "scary, bloody, gore, grotesque, deformed hands, bad anatomy, realistic human skin pores, text watermark" } ] ``` --- ## 📁 Project Structure ``` ├── app/ │ ├── api/ │ │ ├── config/route.ts # API endpoint serving booth config & styles │ │ └── generate/route.ts # AI image transformation endpoint with failover │ ├── globals.css # Design tokens, cartoon button physics & animations │ ├── layout.tsx # Root HTML layout & meta tags │ └── page.tsx # Main state machine routing screens ├── components/ │ ├── KioskFrame.tsx # Kiosk frame, ?mode=fullscreen handler & footer │ ├── SpookyAtmosphere.tsx # Animated Edmonton skyline, aurora & falling leaves │ └── screens/ │ ├── StandbyScreen.tsx # Welcome screen with bouncy hero pumpkin │ ├── CameraScreen.tsx # Camera capture, countdown, and face guide │ ├── ConfirmScreen.tsx # Photo review with retake / confirm │ ├── StyleScreen.tsx # 2x2 grid of cartoon character cards │ ├── LoadingScreen.tsx # Cauldron animation with magical brewing steps │ ├── ResultScreen.tsx # Confetti celebration, download, QR code & Finish │ └── RateLimitedScreen.tsx# Rate-limit cooldown screen ├── config/ │ ├── booth.config.json # Main configuration file │ └── styles.json # Character styles and prompt presets ├── lib/ │ ├── ai/ # Gemini & OpenRouter provider orchestration │ ├── config.ts # Server-side configuration loader │ └── ratelimit.ts # Device generation limits & cooldown tracker └── public/ └── assets/ ├── brand/ # Spooky logo SVG & Sokaris Studio logos └── styles/ # Cartoon character artwork images ``` --- ## đŸˇī¸ Credits & License - Designed and developed for **YEG Halloween Photo Experiences**. - Attribution & branding by **Sokaris Studio** ([sokaris.com](https://sokaris.com)).