Skip to content

devAxick/soprano_next

Repository files navigation

Soprano Quiz

A mobile-first multi-step quiz app that tests musical ear. Users listen to audio clips, answer questions, receive a scored result, and leave contact details for a free first lesson.

Built with Next.js 16, React, Tailwind CSS v4, TypeScript.


Architecture

src/
  app/                        # Next.js routing, layouts, API routes
    [lang]/
      layout.tsx              # Root layout: fonts, metadata, html shell
      page.tsx                # Server entry: fetches dictionary, renders MainPage
    api/
      lead/route.ts           # POST — sends lead email via Resend
      sheet/route.ts          # POST — writes booking to Google Sheets via Apps Script
      types.ts                # Shared request body types for API routes
    globals.css               # Tailwind import + @theme color/font tokens
  proxy.ts                    # Locale detection & redirect (cookie → Accept-Language)
  lib/
    api.ts                    # Base ApiClient class (fetch wrapper with shared headers)
    appApi.ts                 # AppApi extends ApiClient — submitLead, bookLesson
    quizConfig.ts             # Quiz questions, answers, audio sources
    i18n/
      config.ts               # Locale list, Dictionary type, createTranslator()
      server.ts               # getDictionary() — server-only
    schemas/
      contactStep.ts          # Zod schema for contact form
  dictionaries/
    en.json                   # English
    ua.json                   # Ukrainian
    pl.json                   # Polish
  react/                      # Pure React — no Next.js APIs
    pages/
      MainPage.tsx            # Hero screen (server component)
      FormPage.tsx            # Multi-step form screen (client component)
    components/               # Shared UI components
    context/
      FormContext.tsx         # Form state: step, answers, navigation
      LangContext.tsx         # Active locale for client components
public/
  audio/                      # Quiz audio clips (.mp3)
  images/                     # Brand assets (logo.svg, soprano.svg)

Key design decisions

  • Server / client splitMainPage is a server component for SEO. The form overlay is client-only, mounted on demand by FormTrigger.
  • i18n — route-based (/en, /ua, /pl). Dictionary is fetched server-side and passed as a plain object to avoid crossing the server→client boundary with functions.
  • Colors & fonts — defined once in globals.css under @theme. Use bg-accent, text-accent, font-bebas, etc. as Tailwind utilities everywhere.
  • API layerAppApi extends ApiClient. To add a new endpoint, add a method to AppApi and a type to api/types.ts.

Getting started

npm install
npm run dev

Copy .env.local.example to .env.local and fill in the required variables:

APPS_SCRIPT_URL=       # Google Apps Script web app URL
APPS_SCRIPT_SECRET=    # Shared secret validated by the script
RESEND_API_KEY=        # Resend API key for email delivery
CRM_EMAIL=             # Address that receives lead notifications

Commands

Command Description
npm run dev Start dev server with hot reload
npm run build Production build
npm run i18n:extract Scan t() calls and sync all dictionary files

About

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors