Skip to content

Repository files navigation

Questify

A gamified learning platform with AI-assisted content generation, course management, and a mobile-first learner experience.

Questify is a monorepo containing three apps — API (Express + Prisma), Mobile (Expo + React Native), Admin (Vite + React) — and a shared types package.

License: MIT Node npm TypeScript


Features

  • Course, quest & stage system — multi-stage quests (informational, MCQ, boss battles) with progression tracking
  • Gamification — XP, levels, streaks, badges (5 families), achievements, daily/weekly challenges
  • Shop & inventory — purchasable items, equipped cosmetics, streak-freeze consumables
  • AI content generation — generate courses, quests, and stages from prompts
  • RAG-powered Q&A — ask AI about course content; documents/PDFs ingested into a vector pipeline
  • Leaderboards with daily/weekly/all-time snapshots
  • Admin dashboard — manage courses, users, badges, shop items, and analytics
  • Notifications — push and transactional email (Resend)
  • Auth — JWT + Google OAuth

Architecture

┌─────────────────┐      ┌──────────────────┐
│  Mobile (Expo)  │─────▶│                  │
│  iOS / Android  │      │                  │
└─────────────────┘      │   API            │      ┌──────────────────┐
                         │   Express +      │─────▶│  PostgreSQL      │
┌─────────────────┐      │   Prisma         │      │  (Prisma ORM)    │
│  Admin (Vite)   │─────▶│   (port 8080)    │      └──────────────────┘
│  React SPA      │      │                  │
└─────────────────┘      │                  │      ┌──────────────────┐
                         │                  │─────▶│  Cloudflare R2   │
                         │                  │      │  (file storage)  │
                         │                  │      └──────────────────┘
                         │                  │
                         │                  │─────▶┌──────────────────┐
                         │                  │      │  Resend (email)  │
                         └──────────────────┘      └──────────────────┘
                                  │
                                  │── pg-boss job queue
                                 

Tech stack

Layer Technology
Mobile Expo SDK 56, React Native 0.85, React 19.2.3, expo-router
Mobile state Zustand, TanStack Query
Mobile UX Reanimated 4, Gesture Handler, Lottie, expo-audio, expo-haptics
Admin Vite 8, React 19.2.3, React Router 7
Admin UI Radix UI, Recharts, TanStack Table, React Hook Form
Backend Express 5, Prisma 7, PostgreSQL 15+
Auth Passport.js (JWT + Google OAuth)
Validation Zod 4 (shared across all apps via @questify/schemas)
AI OpenAI SDK, Hugging Face, LangChain text splitters
Email Resend + React Email
Job queue pg-boss
File storage Cloudflare R2 (prod) / local (dev) via multer + sharp
Testing Vitest (API + Mobile + Admin)
Build TypeScript 5.9, npm workspaces, Turborepo

Quick start

Prerequisites

Tool Version Why Check
Node.js 22+ Workspace + Turbo node -v
npm 11.6.1 (pinned via packageManager) Repo uses npm workspaces — do not use pnpm/yarn npm -v
PostgreSQL 15+ API database psql --version
Xcode (macOS, iOS) latest stable iOS dev build xcodebuild -version
Android Studio + emulator latest stable Android dev build adb --version

Install

git clone https://github.com/linzi-v7/questify.git
cd questify
npm install

cp apps/api/.env.example    apps/api/.env
cp apps/admin/.env.example  apps/admin/.env
cp apps/mobile/.env.example apps/mobile/.env

Never commit .env files — they are in .gitignore.

Environment (minimum required to run)

APIapps/api/.env

Var Required Purpose
DATABASE_URL yes postgresql://user:password@localhost:5432/questify
JWT_SECRET yes Long random string. Generate with openssl rand -hex 32
PORT no Defaults to 8080
CORS_ORIGIN no Defaults to http://localhost:5173 (Admin)

Adminapps/admin/.env

Var Required Purpose
VITE_API_URL yes http://localhost:8080 in dev

Mobileapps/mobile/.env

Var Required Purpose
EXPO_PUBLIC_API_BASE_URL yes API URL as seen from device. http://localhost:8080/api for emulator, your LAN IP for a physical device (e.g. http://192.168.1.4:8080/api)
EXPO_PUBLIC_API_DEBUG_LOGGING no Verbose API logs in dev. true / false

For the full list of optional variables (Google OAuth, R2, Resend, RAG embeddings), see the comments in apps/api/.env.example.

Database setup

npm run build:schemas    # compile shared Zod schemas
npm run generate         # generate Prisma client
npm run migrate          # apply migrations
cd apps/api && npx prisma db seed

The seed creates a complete starter dataset: 3 users, 2 courses, multi-stage quests, 20 badge definitions, 10 achievements, 4 challenges.

Default credentials after seeding:

  • Admin: admin@questify.com / password123
  • Students: student@questify.com / password123, jane.smith@questify.com / password123

Run

npm run dev           # API + Admin + Mobile (Turborepo)

Or run individually:

npm run dev:api       # API      → http://localhost:8080
npm run dev:admin     # Admin    → http://localhost:5173
npm run android       # Mobile   → Android dev build (first run)
npm run ios           # Mobile   → iOS dev build (first run)

Once a dev build is installed on your device/emulator, subsequent JS changes hot-reload without a rebuild — see Mobile development build.


Scripts

All commands run from the repo root unless noted.

What Command Notes
Start everything npm run dev Turbo — API + Admin + Mobile
Start one app npm run dev:api / dev:admin / dev:mobile
Mobile native build (first run / native lib added) npm run android / npm run ios Wraps expo run:*
Build everything npm run build:all
Rebuild shared schemas npm run build:schemas After changing packages/schemas/
Generate Prisma client npm run generate After schema changes
Run migrations npm run migrate prisma migrate dev
Seed database (fresh) cd apps/api && npx prisma db seed Wipes DB first
Seed database (additive) cd apps/api && npx prisma db seed -- --keep Preserves existing data
Lint npm run lint ESLint
Run tests cd apps/api && npm test Vitest

Mobile development build

⚠️ This project uses native modules (reanimated, gesture-handler, lottie, expo-audio, react-native-svg, secure-store, vector-icons, …) and cannot run in Expo Go. You must use a development build.

First run

npm run android        # or: npm run ios

The first build compiles the native code for your target platform and installs the app on the connected device/emulator (~5–10 minutes). After that:

  • JS changes hot-reload instantly — no rebuild required.
  • Native dependency changes (e.g. adding a new expo-* package) require a rebuild.

Pointing the app at your dev API

In apps/mobile/.env:

  • Emulator on the same machine as the API → EXPO_PUBLIC_API_BASE_URL=http://localhost:8080/api
  • Physical device on the same Wi-Fi → use your machine's LAN IP, e.g. http://192.168.1.4:8080/api. Find it with ipconfig (Windows) or ipconfig getifaddr en0 (macOS).

Project structure

questify/
├── apps/
│   ├── api/        Express + Prisma REST API   (port 8080)
│   ├── admin/      Vite + React admin dashboard (port 5173)
│   └── mobile/     Expo + React Native app
├── packages/
│   └── schemas/    @questify/schemas — shared Zod types
├── turbo.json
└── package.json    workspace config
  • npm install at the root installs everything — one lockfile, one node_modules.
  • packages/schemas/ is built first (npm run build:schemas) so consuming apps can pick up new types.
  • turbo.json orchestrates build order across the workspace.

Environment variables reference

The .env.example files in each app are the source of truth, with inline comments and links for every variable. The README only documents the minimum required to run locally.

App File
API apps/api/.env.example
Admin apps/admin/.env.example
Mobile apps/mobile/.env.example

Production-only concerns (not exercised in dev):

  • DATABASE_URL → managed Postgres (RDS, Cloud SQL, Supabase, Neon, etc.)
  • RESEND_API_KEY + RESEND_FROM_EMAIL → verified sending domain
  • R2_* → Cloudflare R2 bucket + access tokens
  • GOOGLE_CLIENT_ID / GOOGLE_CLIENT_SECRET / GOOGLE_CALLBACK_URL → registered production OAuth client
  • APP_PUBLIC_URL, EMAIL_LOGO_URL → your public domain + CDN-hosted logo
  • NODE_ENV=production, CORS_ORIGIN set to the Admin origin

CLI tools

Run from apps/api:

cd apps/api
npx tsx src/scripts/createAdmin.ts          # create an admin user (prompts for email/password)
npx tsx src/scripts/leaderboard-diag.ts     # diagnose leaderboard state
npx tsx src/utils/importQuestStages.ts      # bulk-import quest stages from a file

The same scripts are also wired up as cli:create-admin and cli:leaderboard-diag in apps/api/package.json (npm run cli:create-admin -w apps/api).


Adding dependencies

App Command
Mobile (Expo) cd apps/mobile && npx expo install <package>
API npm install <package> -w apps/api
Admin npm install <package> -w apps/admin
Shared schemas npm install <package> -w packages/schemas
Root dev tool npm install --save-dev <package> -w root

Never edit package.json versions by hand. Run npm install from the root after any workspace change.


Deployment

Questify is a standard three-tier app and deploys to any cloud that can host Node.js, static sites, and a managed Postgres.

API — Run npm run build:api and serve the compiled output (apps/api/dist) with a Node 22 process manager (systemd, pm2, Docker, or a platform PaaS). Provision a managed PostgreSQL 15+ instance and set DATABASE_URL. Run prisma migrate deploy against the production DB on each release. The job worker can run in-process in dev; for production, run npm run worker -w apps/api as a separate process. Required env: NODE_ENV=production, DATABASE_URL, JWT_SECRET, CORS_ORIGIN, plus the optional integrations (R2, Resend, Google OAuth) you want enabled.

Admin — Run npm run build -w apps/admin to produce a static SPA in apps/admin/dist. Serve from any static host (object storage + CDN, Nginx, Vercel, Netlify, Cloudflare Pages). Set VITE_API_URL at build time to the production API URL.

Mobile — Use Expo Application Services (EAS): configure eas.json, then eas build --platform android|ios produces signed binaries for the Play Store / App Store. Use EAS Update for OTA delivery of JS-only changes between releases. Configure EAS env vars to match your production API URL.

A minimal self-hosted setup (VPS, e.g. Hetzner) — Docker Compose with three services: api (Node), admin (nginx serving the static build), db (Postgres), plus Caddy/Nginx as a reverse proxy terminating TLS in front of the API. Object storage can be Cloudflare R2 or a MinIO container; email via Resend.


Contributing

  1. Fork the repo and create a feature branch.
  2. Install as in Quick start.
  3. Make your changes. Keep PRs focused and small.
  4. Run npm run lint and cd apps/api && npm test before opening a PR.
  5. Use Conventional Commits for commit messages (feat:, fix:, chore:, …).
  6. If you change packages/schemas/, run npm run build:schemas and commit the generated output if your change is consumed by a built artifact.

Troubleshooting

npm install fails

rm -rf node_modules package-lock.json apps/*/node_modules apps/*/package-lock.json
npm install

Module not found / stale types

npm run build:schemas
npm install

Then restart the dev server.

Mobile can't reach the API

  • Confirm the API is running (curl http://localhost:8080/health or similar).
  • On a physical device, use your machine's LAN IP in EXPO_PUBLIC_API_BASE_URL, not localhost. Phone and computer must be on the same Wi-Fi.
  • Clear the dev build's cache: in the dev menu, shake the device / Cmd+M (iOS) / Cmd+M (Android emulator) → Reload.

Port 8081 (Metro) already in use

npx kill-port 8081
npm run dev:mobile -- --clear

Prisma migration drift

If npm run migrate complains about drift or a failed migration, inspect state with npx prisma migrate status -w apps/api. For a clean local DB, npx prisma migrate reset -w apps/api (this wipes the database) and re-run npx prisma db seed.

iOS build fails after pod install issues

cd apps/mobile/ios
pod install --repo-update
cd ..
npx expo run:ios --clean

License

MIT — Copyright (c) 2025 Faris Osama.


Acknowledgments

Built on top of Expo, Prisma, Express, Vite, Zod, TanStack Query, and the broader open-source ecosystem. Email delivery by Resend. File storage by Cloudflare R2.

About

Monorepo for Questify - A Gamified Educational Platform

Resources

Stars

3 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages