222 lines
9.3 KiB
Markdown
222 lines
9.3 KiB
Markdown
# 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)).
|