- MC registrations: notification toggles (confirm/remind) with urgency - Group bookings: save to DB from BookingModal, admin CRUD at /admin/bookings - Open Day: full event system with schedule grid (halls × time), per-class booking, discount pricing (30 BYN / 20 BYN from 3+), auto-cancel threshold - Unified SignupModal replaces 3 separate forms — consistent fields (name, phone, instagram, telegram), Instagram DM fallback on network error - Centralized /admin/bookings page with 3 tabs (classes, MC, Open Day), collapsible sections, notification toggles, filter chips - Unread booking badge on sidebar + dashboard widget with per-type breakdown - Pricing: contact hint (Instagram/Telegram/phone) on price & rental tabs, admin toggle to show/hide - DB migrations 5-7: group_bookings table, open_day tables, unified fields Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
9.2 KiB
9.2 KiB
BLACK HEART DANCE HOUSE — Project Context
About
Landing page for "BLACK HEART DANCE HOUSE" — a pole dance school in Minsk, Belarus. Instagram: @blackheartdancehouse Content language: Russian
Tech Stack
- Next.js 16 (App Router, TypeScript, Turbopack)
- Tailwind CSS v4 (dark mode only, gold/black theme)
- lucide-react for icons
- better-sqlite3 for SQLite database
- Fonts: Inter (body) + Oswald (headings) via
next/font - Hosting: Vercel (planned)
Code Style
- Function declarations for components (not arrow functions)
- PascalCase for component files, camelCase for utils
@/path alias for importsnext/imagewithunoptimizedfor PNGs that need transparency preserved- Header nav uses
lg:breakpoint (1024px) for desktop/mobile switch (9 nav links + CTA need the space)
Project Structure
src/
├── app/
│ ├── layout.tsx # Root layout, fonts, metadata
│ ├── page.tsx # Landing: Hero → [OpenDay] → About → Team → Classes → MasterClasses → Schedule → Pricing → News → FAQ → Contact
│ ├── globals.css # Tailwind imports
│ ├── styles/
│ │ ├── theme.css # Theme variables, semantic classes
│ │ └── animations.css # Keyframes, scroll reveal, modal animations
│ ├── admin/
│ │ ├── page.tsx # Dashboard with 13 section cards
│ │ ├── login/ # Password auth
│ │ ├── layout.tsx # Sidebar nav shell (14 items)
│ │ ├── _components/ # SectionEditor, FormField, ArrayEditor, NotifyToggle
│ │ ├── meta/ # SEO editor
│ │ ├── hero/ # Hero editor
│ │ ├── about/ # About editor
│ │ ├── team/ # Team list + [id] editor
│ │ ├── classes/ # Classes editor with icon picker
│ │ ├── master-classes/ # MC editor with registrations + notification toggles
│ │ ├── open-day/ # Open Day event editor (settings + grid + bookings)
│ │ ├── schedule/ # Schedule editor
│ │ ├── bookings/ # Group booking management with notification toggles
│ │ ├── pricing/ # Pricing editor
│ │ ├── faq/ # FAQ editor
│ │ ├── news/ # News editor
│ │ └── contact/ # Contact editor
│ └── api/
│ ├── auth/login/ # POST login
│ ├── logout/ # POST logout
│ ├── admin/
│ │ ├── sections/[key]/ # GET/PUT section data
│ │ ├── team/ # CRUD team members
│ │ ├── team/[id]/ # GET/PUT/DELETE single member
│ │ ├── team/reorder/ # PUT reorder
│ │ ├── upload/ # POST file upload (whitelisted folders)
│ │ ├── mc-registrations/ # CRUD registrations + notification toggle
│ │ ├── group-bookings/ # CRUD group bookings + notification toggle
│ │ ├── open-day/ # CRUD events
│ │ ├── open-day/classes/ # CRUD event classes
│ │ ├── open-day/bookings/ # CRUD event bookings + notification toggle
│ │ └── validate-instagram/ # GET check username
│ ├── master-class-register/ # POST public MC signup
│ ├── group-booking/ # POST public group booking
│ └── open-day-register/ # POST public Open Day booking
├── components/
│ ├── layout/
│ │ ├── Header.tsx # Sticky nav, mobile menu, booking modal ("use client")
│ │ └── Footer.tsx
│ ├── sections/
│ │ ├── Hero.tsx # Hero with animated logo, floating hearts
│ │ ├── About.tsx # About with stats (trainers, classes, locations)
│ │ ├── Team.tsx # Carousel + profile view
│ │ ├── Classes.tsx # Showcase layout with icon selector
│ │ ├── MasterClasses.tsx # Cards with signup modal
│ │ ├── OpenDay.tsx # Open Day schedule grid + booking (conditional)
│ │ ├── Schedule.tsx # Day/group views with filters
│ │ ├── Pricing.tsx # Tabs: prices, rental, rules
│ │ ├── News.tsx # Featured + compact articles
│ │ ├── FAQ.tsx # Accordion with show more
│ │ └── Contact.tsx # Info + Yandex Maps iframe
│ └── ui/
│ ├── Button.tsx
│ ├── SectionHeading.tsx
│ ├── BookingModal.tsx # Booking form → Instagram DM + DB save
│ ├── MasterClassSignupModal.tsx # MC registration form → API
│ ├── OpenDaySignupModal.tsx # Open Day class booking → API
│ ├── NewsModal.tsx # News detail popup
│ ├── Reveal.tsx # Intersection Observer scroll reveal
│ ├── BackToTop.tsx
│ └── ...
├── data/
│ └── content.ts # Fallback Russian text (DB takes priority)
├── lib/
│ ├── constants.ts # BRAND constants, NAV_LINKS
│ ├── config.ts # UI_CONFIG (thresholds, counts)
│ ├── db.ts # SQLite DB, 6 migrations, CRUD for all tables
│ ├── auth.ts # Token signing (Node.js)
│ ├── auth-edge.ts # Token verification (Edge/Web Crypto)
│ ├── content.ts # getContent() — DB with fallback
│ └── openDay.ts # getActiveOpenDay() — server-side Open Day loader
├── proxy.ts # Middleware: auth guard for /admin/*
└── types/
├── index.ts
├── content.ts # SiteContent, TeamMember, ClassItem, MasterClassItem, etc.
└── navigation.ts
Brand / Styling
- Accent: gold (
#c9a96e/hsl(37, 42%, 61%)) - Background:
#050505–#0a0a0a(dark only) - Surface:
#171717dark cards - Logo: transparent PNG heart with gold glow, uses
unoptimized
Content Data
- Primary source: SQLite database (
db/blackheart.db) - Fallback:
src/data/content.ts(auto-seeds DB on first access) - Admin panel edits go to DB, site reads from DB via
getContent() - 12 team members with photos, Instagram links, bios, victories, education
- 6 class types (Exotic Pole Dance, Pole Dance, Body Plastic, etc.)
- Master classes with date/time slots and public registration
- 2 addresses in Minsk, Yandex Maps embed with markers
- Contact: phone, Instagram (no email)
Admin Panel
- Password-based auth with HMAC-SHA256 signed JWT (24h TTL)
- Cookie:
bh-admin-token(httpOnly, secure in prod) - Auto-save with 800ms debounce on all section editors
- Team members: drag-reorder, photo upload, rich bio (experience, victories, education)
- Master classes: slots, registration viewer with notification tracking (confirm + reminder), trainer/style autocomplete
- Group bookings: saved to DB from BookingModal, admin page at
/admin/bookingswith notification toggles - Open Day: event settings (date, pricing, discount rules, min bookings), schedule grid (halls × time slots), per-class booking with auto-cancel threshold, public section after Hero
- Shared
NotifyTogglecomponent (src/app/admin/_components/NotifyToggle.tsx) used across MC registrations, group bookings, and Open Day bookings - File upload: whitelisted folders (
team,master-classes,news,classes), max 5MB, image types only
Security Notes
- CSRF protection: Double-submit cookie pattern. Login sets
bh-csrf-tokencookie (JS-readable). All admin fetch calls useadminFetch()fromsrc/lib/csrf.tswhich sends the token asX-CSRF-Tokenheader. Middleware (proxy.ts) validates header matches cookie on POST/PUT/DELETE to/api/admin/*. Always useadminFetch()instead offetch()for admin API calls. - File upload validates: MIME type, file extension, whitelisted folder (no path traversal)
- API routes validate: input types, string lengths, numeric IDs
- Public MC registration: length-limited but no rate limiting yet (add before production)
Upcoming Features
- Rate limiting on public endpoints (
/api/master-class-register,/api/group-booking,/api/open-day-register) - DB backup mechanism — automated/manual backup of
db/blackheart.dbwith rotation
AST Index
- Always use the AST index at
memory/ast-index.mdwhen searching for components, props, hooks, types, or styles - Contains: component tree, all exports, props, hooks, client/server status, CSS classes, keyframes
- Update the index when adding/removing/renaming files or exports
Database Migrations
- Never drop/recreate the database — admin data (photos, edits, registrations) lives there
- Schema changes go through versioned migrations in
src/lib/db.ts(migrationsarray) - Add a new entry with the next version number; never modify existing migrations
- Migrations run automatically on server start via
runMigrations()and are tracked in the_migrationstable - Use
CREATE TABLE IF NOT EXISTSand column-existence checks (PRAGMA table_info) for safety
Git
- Remote: Gitea at
git.dolgolyov-family.by - User: diana.dolgolyova
- Branch: main