MK-QuizFlow

MK QuizFlow

Turn PDFs, notes and pasted text into quizzes, flashcards and practice tests — right in your browser.

License: MIT Next.js TypeScript

Live

What it does

Turn PDFs, notes and pasted text into quizzes, flashcards, practice tests and study material. Paste your material or upload a text-based PDF, choose how many questions you want and which types, and QuizFlow builds a quiz you can play, score and export — or a flashcard deck you can review with spaced repetition.

It works offline in Quick mode with no AI key needed. Nothing about your document leaves your device in Quick mode. An optional AI layer is available for higher-quality generation, and it is always clearly labelled.

Features

Screenshots

Home Quiz player
MK QuizFlow home page MK QuizFlow quiz player in Quick mode

Tech stack

No database, no accounts, no signup. The app is fully usable with zero configuration.

Project structure

Tests live next to the code they cover as *.test.ts files; only the source modules are listed below.

src/
├── app/                         # Next.js App Router — pages, routes and metadata
│   ├── layout.tsx               # Root layout: metadata, theme, consent and analytics wiring
│   ├── page.tsx                 # Landing page
│   ├── globals.css              # Tailwind v4 theme + design tokens
│   ├── loading.tsx              # Global loading UI
│   ├── error.tsx                # Root error boundary
│   ├── not-found.tsx            # Custom 404 page
│   ├── robots.ts                # robots.txt generator
│   ├── sitemap.ts               # XML sitemap generator
│   ├── opengraph-image.tsx      # Open Graph social card (rendered with next/og)
│   ├── twitter-image.tsx        # Twitter/X social card
│   ├── api/ai/[capability]/route.ts  # Serverless AI endpoint: rate-limit → quota → gateway
│   ├── tool/                    # Main quiz workspace (upload → configure → generate → play)
│   ├── flashcards/              # Flashcard deck player
│   ├── dashboard/               # Local stats dashboard
│   ├── history/                 # Past quizzes, decks and results
│   ├── settings/                # Data export/import, consent, BYOK key, ad flag
│   ├── docs/                    # In-app documentation page
│   ├── guides/                  # Guide index + guides/[slug] article pages
│   ├── use-cases/               # Use-case index + use-cases/[slug] pages
│   ├── faq/                     # FAQ (FAQPage structured data)
│   ├── changelog/               # Changelog page
│   ├── about/                   # About the product
│   ├── creator/                 # Creator profile (Person structured data)
│   ├── open-source/             # Open-source page
│   ├── privacy/                 # Privacy policy
│   ├── terms/                   # Terms of use
│   ├── cookies/                 # Cookie policy + consent controls
│   └── contact/                 # Contact page
│
├── components/                  # UI components
│   ├── layout/                  # Header, footer, theme toggle + no-flash theme script,
│   │                            #   consent banner, and analytics loaders (GTM/GA, Vercel)
│   ├── tool/                    # SourceInput (paste/PDF + page range), GenerateConfig,
│   │                            #   QuestionEditor, ExportMenu, and the reserved AdUnit slot
│   ├── player/                  # QuizPlayer (MCQ/TF/short/fill) and QuizResults
│   ├── flashcards/              # FlashcardPlayer (flip + self-grading)
│   ├── analytics/               # TrackOnMount helper
│   └── ui/                      # Design-system primitives: Button, Badge, ConfirmDialog,
│                                #   EmptyState, ProgressRing, icons
│
└── lib/                         # Pure logic, framework-free where possible
    ├── types.ts                 # Shared domain types
    ├── generator.ts             # Deterministic Quick-mode question generator
    ├── text.ts                  # Sentence/keyword text heuristics
    ├── pdf.ts                   # In-browser PDF text extraction (pdfjs-dist)
    ├── scoring.ts               # Quiz scoring
    ├── dedupe.ts                # Duplicate-question detection
    ├── srs.ts                   # SM-2-style spaced-repetition scheduler
    ├── stats.ts                 # Derived dashboard stats from local history
    ├── storage.ts               # IndexedDB persistence behind one interface (idb)
    ├── prefs.ts                 # Small localStorage preferences
    ├── share.ts                 # Share-by-URL encode/decode (zod-validated)
    ├── export.ts                # JSON / CSV / Markdown / printable-HTML exporters
    ├── id.ts                    # crypto.randomUUID id generation (with fallback)
    ├── cn.ts                    # className merge (clsx + tailwind-merge)
    ├── analytics.ts             # Typed track() with the consent gate
    ├── audio.ts                 # Web Audio click sounds
    ├── tips.ts                  # Rotating study tips
    ├── site.ts                  # Site + creator constants
    ├── guides.ts                # Guides content data
    ├── use-cases.ts             # Use-cases content data
    ├── og-image.tsx             # Shared OG image renderer
    └── ai/                      # AI layer: catalog, capabilities, models (env defaults),
                                 #   quota (daily), rate-limit (per-IP), errors, request, client

Getting started

Prerequisites: Node 20+ (Next.js 16 needs Node 20.9+) and pnpm.

pnpm i          # install dependencies
pnpm dev        # start the dev server at http://localhost:3000
pnpm build      # production build
pnpm test       # run the unit tests (Vitest)

Other useful scripts: pnpm lint, pnpm typecheck, pnpm test:coverage, and pnpm e2e (Playwright smoke).

Environment variables

Every variable is optional. The app builds and the deterministic Quick mode works with none of them set — when AI credentials are missing, AI mode shows a graceful “AI unavailable” fallback and everything else keeps working. Copy .env.example to .env.local to set any of them.

Variable Purpose Required?
AI_GATEWAY_API_KEY Server Vercel AI Gateway key (vck_…) for AI mode. On Vercel, OIDC can supply this automatically. No — unset means Quick mode only
VERCEL_OIDC_TOKEN Ambient AI Gateway credential injected by vercel dev and by Vercel at deploy time. No — managed by Vercel, do not set by hand
AI_MODEL Fast-tier gateway model string. No — defaults to anthropic/claude-haiku-4.5
AI_MODEL_QUALITY Quality-tier gateway model string. No — defaults to anthropic/claude-sonnet-4-5
NEXT_PUBLIC_SITE_URL Canonical/OG base URL for SEO and the sitemap. No — defaults to https://quizflow.mkazi.live
NEXT_PUBLIC_GTM_ID Google Tag Manager container id. No — unset disables analytics entirely
NEXT_PUBLIC_GA_ID Google Analytics id. No — unset disables analytics entirely
NEXT_PUBLIC_ADSENSE_ENABLED Master switch for reserved ad slots. No — defaults to false (no ad scripts load)
NEXT_PUBLIC_ADSENSE_CLIENT_ID AdSense publisher id, only used when ads are enabled. No
NEXT_PUBLIC_SPONSOR_URL Optional sponsor/”buy me a coffee” link shown in the fallback ad slot. No

Privacy

QuizFlow is local-first. Your material is processed in your browser, and your quizzes, decks, results and settings live in IndexedDB on your device.

See docs/PRIVACY.md and docs/SECURITY.md for the full guarantees and threat model.

Documentation

Deeper reference docs live in docs/:

Deployment & launch guide

Why Vercel

Vercel is the recommended host and the path this project uses:

Deploy it

  1. Fork or clone this repository to your own GitHub account.
  2. Import the repo into Vercel (New Project → import from GitHub). Vercel detects Next.js and uses pnpm automatically.
  3. Set environment variables if you want AI mode or analytics — see the table above. You can skip this entirely; the app deploys and works in Quick mode with nothing set.
  4. Deploy. Vercel builds and gives you a *.vercel.app URL (this project’s is mk-quizflow.vercel.app).

Custom domain (quizflow.mkazi.live)

  1. In the Vercel project, open Settings → Domains and add quizflow.mkazi.live.
  2. At the DNS provider (Cloudflare, which manages mkazi.live), add the record Vercel asks for:

    A   quizflow.mkazi.live   76.76.21.21
    

    If you use Cloudflare’s proxy, set this record to DNS only (grey cloud) so Vercel can validate it.

  3. SSL issues automatically once the DNS record resolves — no manual certificate step.

Future standalone domain (mkquizflow.com)

If QuizFlow graduates to its own domain (candidate: mkquizflow.com):

  1. Buy the domain and add it in Settings → Domains as the new primary, pointing its apex A record to 76.76.21.21 (and a CNAME for www to cname.vercel-dns.com).
  2. Keep quizflow.mkazi.live attached and set it to redirect to the new primary domain in Vercel’s domain settings, so old links keep working.

Roadmap

About the creator

Kazi Musharraf — AI Engineer · Full-Stack Developer · Open-Source Builder.

License

MIT © 2026 Kazi Musharraf.


Built and maintained by Kazi Musharraf. Open source for everyone.