Mock Tests is a full-stack practice test app built with React, Vite, Tailwind, and Convex. It lets learners sign in quickly, take published tests in the browser, and resume unfinished work. It also includes an admin editor for creating, importing, editing, and publishing test content.
- Shows learners a list of published tests.
- Supports
mcq,tf,ms,matching, andfibquestion types. - Saves in-progress test state in
localStoragefor up to 3 days. - Includes keyboard shortcuts for faster test navigation.
- Lets admins manage draft and published tests from an in-app editor.
- Validates imported JSON before creating draft tests.
- Frontend: React 19, Vite, TypeScript, Tailwind CSS
- Backend: Convex
- Auth: Convex Auth
- Validation: Zod
- Tests: Vitest
- Node.js
- npm
- A Convex deployment
This project expects a .env.local file with these variables:
CONVEX_DEPLOY_KEY=...
CONVEX_DEPLOYMENT=...
VITE_CONVEX_URL=...If you are connecting this project to a new Convex deployment, run npx convex dev and follow the CLI prompts. That will typically populate the local Convex settings you need.
npm install
npm run devnpm run dev starts both:
- the Vite frontend
- the Convex development backend
Once the app is running, open the local Vite URL in your browser and sign in from the landing page.
npm run dev
npm run lint
npm run testnpm run dev: starts Vite and Convex in parallelnpm run lint: runs TypeScript checks, validates the Convex backend, and builds the frontendnpm run test: runs the Vitest suite
The admin UI is built into the app.
- Sign in to the app.
- Open
Adminfrom the header. - Enter the admin password.
- Create a draft test or import JSON.
- Edit questions, reorder them, then publish when ready.
Important: the admin password is currently hard-coded as admin123 in convex/admin.ts. That is fine for local development, but it is not acceptable for a real deployment. Change this before exposing the app to anyone else.
Tests can be imported as a single JSON object or an array of test objects. Imports are validated before they are written, and imported tests are created as drafts first.
See QUESTION_FORMAT_GUIDE.md for the full schema and examples.
At a high level, each imported test looks like this:
{
"name": "Sample Test",
"description": "Optional description",
"questions": [
{
"id": "q1",
"text": "What is the capital of France?",
"type": "mcq",
"options": ["London", "Paris", "Rome"],
"correctAnswers": ["Paris"]
}
]
}src/ React UI, hooks, and client-side utilities
convex/ Convex schema, queries, mutations, auth, and HTTP setup
shared/ Shared validation logic for admin editing and JSON imports
public/ Static assets
- Only published tests are visible to learners.
- Draft tests remain available in the admin editor until published.
- Auth is configured with both
PasswordandAnonymousproviders, but the current UI signs learners in anonymously. - Question text supports Markdown rendering in the test UI.