Skip to content

kabir2004/WiseDrive

Repository files navigation

WiseDrive

The free, modern Ontario DriveTest preparation platform.

Study smarter for your G1, M1, or Commercial licence — with practice tests, mock exams, flashcards, road signs, and progress tracking. All in one place. Always free.


Next.js React TypeScript Tailwind CSS NextAuth.js

GitHub last commit GitHub repo size License Free Forever Ontario MTO


Overview

WiseDrive is a full-stack Ontario DriveTest preparation app built with Next.js 16 and React 19. It covers the G1 (car), M1 (motorcycle), and Commercial (A/D) knowledge tests with government-standard content sourced from the Ontario Driver's Handbook (MTO).

Everything runs in the browser — progress is saved to localStorage, content is static JSON, and there is no external database. Authentication is handled by NextAuth.js, making the app trivially self-hostable.


Features

Study Modes

Mode Description Feedback
Practice Unlimited questions with instant explanations ✅ Immediate
Mock Test 20-question timed exam (20 min, 80% pass mark) ❌ After submit
Flashcards 3D flip cards — All, Weak Spots, or By Category ✅ On reveal
Weak Spots Targeted review of previously missed questions ✅ Immediate
Road Signs SVG-rendered gallery of 25 Ontario signs
Lessons Structured study reading for each licence class

Progress Tracking

  • Readiness Score — Rolling average of last 5 mock test results
  • Category Accuracy — Tracks correct/total per topic across all sessions
  • Weak Spots System — Wrong answers are automatically queued for review; correct answers remove them
  • Daily Streak — Increments on any activity; shown on dashboard
  • Mock Test History — Chart with real dates on the X-axis, score on the Y-axis

Content

  • 64 G1 questions (Rules of the Road, Signs, Novice Driver Rules, Sharing the Road)
  • 40 M1 questions (Motorcycle Operation, Licensing & Safety Gear)
  • 30 Commercial questions (Air Brakes, Inspection, Cargo, Hours of Service)
  • 25 Ontario road signs — SVG-rendered with authentic shapes, colours, and labels
  • 10 comprehensive HTML lessons covering all 3 licence classes

UX & Quality

  • Dark / light mode — persisted in localStorage, respects system preference on first load
  • Fully responsive — mobile-first layout with collapsible sidebar
  • Zero external fonts or analytics — no third-party tracking
  • Keyboard hints — flashcards support keyboard navigation
  • Session summaries — practice and weak spots sessions end with a detailed results screen showing every missed question, correct answer, and explanation

Tech Stack

Layer Technology Version
Framework Next.js App Router 16.1.6
UI Library React 19
Language TypeScript 5 (strict mode)
Styling Tailwind CSS v4 + shadcn/ui 4.x
Animations Framer Motion 12.x
Charts Recharts 3.x
Auth NextAuth.js (Credentials + OAuth) 5.0 beta
Icons Lucide React 0.57x
Password Hashing bcryptjs 3.x

Architecture

WiseDrive is intentionally simple and dependency-light:

User → NextAuth Session → Middleware (route guard) → App Router Pages
                                                            ↓
                                              Static JSON (src/data/)
                                              useUserProgress hook
                                              localStorage (wisedrive_progress)

No external database. All question content, lessons, signs, and licence metadata live as static JSON files in src/data/. User credentials are stored in a local .wisedrive-users.json file (file-based, intended for development and self-hosting). User progress (scores, streaks, weak spots, category accuracy) is stored entirely in the browser via localStorage.

Key Design Decisions

  • useUserProgress hook — Single source of truth for all progress state. Reads from and writes to localStorage synchronously. Exposes addWeakSpots(ids[]) as a batch method to prevent React state-update race conditions when saving multiple wrong answers at once (e.g. after a mock test).
  • answersRef pattern in mock test — A useRef mirrors the answers state so the finishTest callback always reads current data regardless of React's render cycle. A finishedRef guard prevents double-invocation when the timer and the Submit button fire simultaneously.
  • Static-first data — No API routes for content. src/utils/data.ts loads JSON at module level, making every page server/client compatible with zero fetch latency.
  • CSS variable design tokens — All colours use Tailwind v4 CSS custom properties (--border, --muted, --foreground, etc.) so dark/light mode is a single dark class toggle on <html>.

Project Structure

wisedrive/
├── src/
│   ├── app/
│   │   ├── (app)/                   # Protected routes (auth required)
│   │   │   ├── dashboard/           # KPIs, readiness score, charts
│   │   │   ├── practice/            # Study hub + category selector
│   │   │   │   ├── page.tsx
│   │   │   │   ├── study/           # Question practice (immediate feedback)
│   │   │   │   └── read/            # Lesson viewer
│   │   │   │       └── [licenceId]/[slug]/
│   │   │   ├── mock-test/           # Timed exam (no feedback until done)
│   │   │   ├── flashcards/          # 3D flip card sessions by mode
│   │   │   ├── weak-spots/          # Targeted review of missed questions
│   │   │   ├── signs/               # SVG Ontario road sign gallery
│   │   │   ├── onboarding/          # Licence class selection
│   │   │   └── settings/            # Change licence, reset progress
│   │   ├── api/auth/[...nextauth]/  # NextAuth route handler
│   │   ├── sign-in/                 # Credentials sign-in page
│   │   ├── sign-up/                 # Account creation page
│   │   └── page.tsx                 # Public marketing/landing page
│   │
│   ├── components/
│   │   ├── features/
│   │   │   ├── QuestionCard.tsx     # Multiple-choice card w/ optional feedback
│   │   │   └── Timer.tsx            # Countdown timer (turns red < 5 min)
│   │   ├── layout/
│   │   │   ├── AppSidebar.tsx       # Collapsible nav with tooltip labels
│   │   │   └── AppHeader.tsx        # Theme toggle + user dropdown
│   │   ├── providers/               # SessionProvider wrapper
│   │   └── ui/                      # shadcn/ui components
│   │
│   ├── data/                        # Static content (no API calls)
│   │   ├── g1.json                  # 64 G1 knowledge questions
│   │   ├── m1.json                  # 40 M1 motorcycle questions
│   │   ├── commercial.json          # 30 Commercial (A/D) questions
│   │   ├── lessons.json             # 10 structured study lessons (HTML)
│   │   ├── signs.json               # 25 Ontario road signs (shape/colour/SVG)
│   │   └── licences.json            # Licence class metadata
│   │
│   ├── hooks/
│   │   └── useUserProgress.ts       # localStorage read/write + all state methods
│   ├── types/index.ts               # Question, LicenceClass, UserProgress
│   ├── utils/
│   │   ├── data.ts                  # JSON loaders + category filters
│   │   └── quiz.ts                  # shuffleArray, getRandomItems, calculateReadiness
│   ├── lib/utils.ts                 # cn() helper
│   ├── auth.ts                      # NextAuth config (credentials + OAuth)
│   └── middleware.ts                # Redirect unauthenticated users to /sign-in
│
├── .wisedrive-users.json            # File-based user store (gitignored)
├── public/                          # Logos, static SVGs
└── .env.local                       # Environment variables (not committed)

Licence Classes

Licence Vehicle Questions Key Topics
G1 Car / Light truck 64 Rules of the Road, Road Signs & Markings, Novice Driver System, Sharing the Road
M1 Motorcycle 40 Motorcycle Operation, Hazard Avoidance, M1/M2/M Licensing, T-CLOCS Inspection, Gear
Commercial A/D Truck / Bus 30 Air Brakes, Pre-Trip Inspection, Cargo Securement, Hours of Service & Logbooks

Content is aligned with the Ontario Driver's Handbook and MTO Commercial Vehicle Operator's Registration guidelines.


Getting Started

Prerequisites

  • Node.js 18.18+ (LTS recommended)
  • npm, yarn, pnpm, or bun

Installation

# 1. Clone the repository
git clone https://github.com/kabir2004/WiseDrive.git
cd WiseDrive

# 2. Install dependencies
npm install

# 3. Set up environment variables
cp .env.example .env.local
# Edit .env.local and add your AUTH_SECRET (see below)

# 4. Start the development server
npm run dev

Open http://localhost:3000 in your browser.

Environment Variables

Create a .env.local file in the project root:

# Required — any random string (min 32 chars)
# Generate one: openssl rand -base64 32
AUTH_SECRET=your-random-secret-here

# Optional — Google OAuth
GOOGLE_CLIENT_ID=
GOOGLE_CLIENT_SECRET=

# Optional — Azure AD OAuth
AZURE_AD_CLIENT_ID=
AZURE_AD_CLIENT_SECRET=
AZURE_AD_TENANT_ID=

Note: Without OAuth credentials, the app falls back to email/password authentication using the file-based user store (.wisedrive-users.json). This is created automatically on the first sign-up.

Build for Production

npm run build
npm start

Linting

npm run lint

Data Model

interface Question {
  id: string;
  category: string;
  difficulty: 'Easy' | 'Medium' | 'Hard';
  text: string;
  options: string[];
  correctAnswer: string;
  explanation: string;
  image?: string;
}

interface UserProgress {
  activeLicence: string;
  streak: {
    current: number;
    lastActiveDate: string | null;
  };
  weakSpots: string[];          // Question IDs answered incorrectly
  history: {
    date: string;               // ISO date string
    mode: 'MockTest' | 'Practice';
    score: number;
    total: number;
    passed: boolean;
  }[];
  categoryAccuracy: Record<string, {
    correct: number;
    total: number;
  }>;
}

Progress & Scoring Logic

Metric Calculation
Readiness Score Average score across the last 5 mock tests
Category Accuracy (correct / total) × 100 per category, rolling across all sessions
Pass Mark 80% — matches the Ontario G1/M1/Commercial knowledge test standard
Weak Spots Added on wrong answer; removed when answered correctly in Practice or Weak Spots review
Daily Streak Increments if any activity is completed and the previous active date was yesterday

Self-Hosting

WiseDrive is designed to be trivially self-hostable on any Node.js server or PaaS platform.

Vercel (recommended):

Deploy with Vercel

Set AUTH_SECRET in your Vercel project environment variables and deploy.

Docker / VPS:

npm run build
AUTH_SECRET=your-secret node .next/standalone/server.js

Roadmap

  • Spaced repetition algorithm (SM-2) for flashcards
  • G2 exit test content
  • Offline PWA support
  • Question image support (road sign photos)
  • Shareable progress reports
  • Admin content panel for question management
  • Supabase/Postgres option for multi-device sync

Contributing

Contributions are welcome! If you spot a content error, have a question suggestion, or want to add a feature:

  1. Fork the repository
  2. Create a feature branch: git checkout -b feat/your-feature
  3. Commit your changes: git commit -m "feat: describe your change"
  4. Push to the branch: git push origin feat/your-feature
  5. Open a Pull Request

For content corrections (questions, lessons, signs), open an issue with the MTO handbook reference so changes can be verified against the official source.


License

This project is licensed under the MIT License — see LICENSE for details.

Content (questions, lessons, signs) is based on publicly available Ontario Ministry of Transportation materials and is provided for educational purposes.


Built with care for Ontario drivers studying for their licence.

⭐ Star this repo if WiseDrive helped you pass your test!

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors