Sai Meghna Dance School
production website for a 25+ year Kuchipudi classical dance academy
Project metadata
Overview
Website for Sai Meghna Dance School, a 25+ year Kuchipudi classical dance academy based in Houston, TX, run by my mother. Dark, cinematic, and photography-forward, built to feel like a prestigious performing arts institution rather than a template.
Architecture
A single Next.js project using the App Router. Pages are Server Components by default; 'use client' is added only where interactivity is required.
Rendering model
Server Components handle data-free, static sections. Client Components ('use client') are scoped to things that need the browser: the sticky/blurring Navigation, the ChatButton/ChatModal pair, the contact form, in-view scroll animations (Framer Motion), and the theme toggle.
Design system
Full spec in docs/DESIGN-SYSTEM.md.
Palette, "Temple Maroon": deep maroon background, warm sandalwood-ivory text, turmeric gold accent for CTAs and highlights used sparingly, kumkum red secondary reserved for the saree-border ornament. Never pure white, never system blue or purple.
Two site-wide themes: Dusk (maroon, dark, default) and Diya (cream, light), toggled from the footer and applied via a data-tone attribute on <html>, persisted to localStorage. All colors are CSS custom-property tokens (--bg-primary, --text-primary, --accent) consumed through Tailwind (bg-bg-primary, text-text-primary), so every component recolors automatically. Components never hardcode a theme-specific hex value.
Ornaments: cultural motifs (jaali lattice, kolam dividers, torana frame, mandala watermark, saree border) are hand-built SVG/CSS components in components/ornaments/, not clip-art. Token-driven and Framer Motion draw-in ready.
Motion: graceful, slow reveals only. No spring or bounce easing, no parallax, no AOS.
Media
All photography and video is hosted on Cloudinary and referenced by public ID from lib/cloudinary.ts, which builds delivery URLs with automatic format and quality (f_auto, q_auto) and responsive transforms. /public holds only the favicon and static SVGs. No photos or video live in the repo.
Data and integrations
Contact form (app/api/contact/route.ts): validates input server-side, writes a Contact document to MongoDB Atlas via a cached Mongoose connection (lib/db.ts), and emails a formatted notification via Resend. IP-based rate limiting at 5 requests/hour plus a honeypot field.
Chatbot (app/api/chat/route.ts): proxies to Gemini 2.5 Flash server-side; the API key is never exposed to the client. Grounded on static school info in lib/school-knowledge.ts. Rate-limited per IP at 30/hour, burst-limited to 5 per 10 seconds, with input length caps and retry/backoff on transient Gemini errors.
SEO
app/layout.tsx sets full metadata (Open Graph, Twitter cards, canonical URLs) plus JSON-LD PerformingArtsTheater structured data. app/sitemap.ts and app/robots.ts generate the sitemap and robots rules.
Documentation
Recorded 2026-09-07. This was previously buried in the project-structure listing and captured nowhere as an accomplishment, which meant it never reached a resume. It is the only written documentation deliverable anywhere in the vault, so reach for it whenever a job description names documentation, user guides, runbooks, or "explain software to others" as a responsibility. Those appear on most IT, internal-tools, and automation postings.
Full stack
Next.js 15 · React 19 · TypeScript · Tailwind CSS 4 · Framer Motion 12 · Cloudinary · MongoDB Atlas · Mongoose · Resend · Gemini 2.5 Flash · Vercel
Results
Live in production at saimeghna.com | Yes | |
Dual theme via CSS custom-property tokens and `data-tone` | Yes | |
Contact form rate limit | 5/hour + honeypot | |
Chat rate limit | 30/hour, burst 5 per 10s, server-side key | |
SEO | JSON-LD PerformingArtsTheater, generated sitemap and robots | |
Build time | About 2 days end to end |
