A cross-platform application for bulk-downloading Cambridge International (CAIE) past examination papers. Built with Svelte 5, Hono, SQLite, and Tailwind CSS.
App versions (desktop builds) coming soon. The web version is fully functional today.
| Configure Options |
Review & Start |
Download Library |
 |
 |
 |
| Download Progress |
Settings |
 |
 |
- Multi-source scraping — Downloads from XtremePapers (primary) and PapaCambridge (fallback) with automatic failover
- Bulk downloads — Select subjects, year ranges, exam sessions, and paper types in a single session
- 200+ Cambridge subjects — IGCSE, O Level, AS and A Level syllabi with pre-configured subject bundles
- Real-time progress — Live download progress via Server-Sent Events (SSE)
- Smart deduplication — SHA-256 hash-based and path-based deduplication to avoid re-downloading
- Pause / Resume / Cancel / Retry — Control downloads at both session and individual file levels
- Download library — Browse, search, sort, and paginate all downloaded papers
- Download history — View past session details and retry failed items
- Archive statistics — Total files, disk usage, subjects covered, years, and content type breakdown
- File organisation — Structured directory hierarchy:
{subject}_{code}/{year}/{session}/
- Theming — Dark and light theme toggle
| Layer |
Technology |
| Frontend |
Svelte 5, TypeScript, Tailwind CSS v4, DaisyUI v5 |
| Backend |
Node.js, Hono, SQLite (better-sqlite3) |
| Scraping |
undici (HTTP), Cheerio (HTML parsing) |
| DevOps |
pnpm, Vite, esbuild, Vitest, GitHub Actions |
PastPaper-Downloader/
├── index.html # Vite entry point
├── package.json # Dependencies and scripts
├── subjects.config.json # 200+ Cambridge subjects
├── sources.config.json # Scraping source definitions
├── bundles.config.json # Quick-select subject bundles
│
├── src/
│ ├── shared/
│ │ └── types.ts # Shared TypeScript types
│ │
│ ├── client/ # Svelte 5 frontend
│ │ ├── main.ts # Mount entry point
│ │ ├── App.svelte # Root component
│ │ ├── app.css # Tailwind + DaisyUI
│ │ ├── components/
│ │ │ ├── Sidebar.svelte # Navigation + theme toggle
│ │ │ ├── ConfigPanel.svelte # 3-step download wizard
│ │ │ ├── StepSubjects.svelte # Step 1: subject selection
│ │ │ ├── StepOptions.svelte # Step 2: year/session/type config
│ │ │ ├── StepReview.svelte # Step 3: review and start
│ │ │ ├── ProgressPanel.svelte # Live download progress
│ │ │ ├── ProgressTable.svelte # Per-file progress table
│ │ │ ├── HistoryPanel.svelte # Past session history
│ │ │ ├── SessionDetail.svelte # Session file breakdown
│ │ │ ├── LibraryPanel.svelte # Downloaded papers browser
│ │ │ ├── StatsPanel.svelte # Archive statistics
│ │ │ └── Toast.svelte # Notification toasts
│ │ └── lib/
│ │ ├── api.ts # REST API client
│ │ ├── events.ts # SSE event bridge
│ │ ├── stores.svelte.ts # Svelte 5 runes state
│ │ └── utils.ts # Formatting utilities
│ │
│ └── server/ # Node.js Hono backend
│ ├── index.ts # Server entry point
│ ├── config/
│ │ ├── sources.ts # Load scraping sources
│ │ └── subjects.ts # Load subjects
│ ├── db/
│ │ ├── client.ts # SQLite connection + schema
│ │ └── queries.ts # Database queries
│ ├── routes/
│ │ ├── config.ts # /api/config/*
│ │ ├── download.ts # /api/download/*
│ │ ├── health.ts # /api/health
│ │ ├── library.ts # /api/library
│ │ ├── sessions.ts # /api/sessions/*
│ │ └── stats.ts # /api/stats
│ ├── scrapers/
│ │ └── xtreme-papers.ts # XtremePapers scraper
│ ├── services/
│ │ ├── deduplication.ts # SHA-256 + path dedup
│ │ ├── download-manager.ts # Core download engine
│ │ ├── file-organiser.ts # Directory structure builder
│ │ └── session-registry.ts # Session tracking
│ └── utils/
│ ├── emitter.ts # Typed event emitter
│ ├── errors.ts # AppError class
│ └── logger.ts # pino logger
│
├── tests/
│ ├── unit/ # Unit tests
│ ├── integration/ # API integration tests
│ ├── e2e/ # Playwright E2E tests
│ └── fixtures/ # Test HTML fixtures
│
├── docs/ # Documentation
│ ├── screenshots/ # App screenshots
│ ├── DESIGN-BRIEF.md # Visual design brief
│ ├── project-description.md # Architecture overview
│ ├── dev-plan.md # Development roadmap
│ └── agent-instructions.md # AI agent coding guidelines
│
├── scripts/
│ ├── build-server.js # esbuild server bundle
│ ├── dev-both.mjs # Launch Vite + Hono dev servers
│ └── sync-subjects.ts # Scrape XtremePapers for subjects
│
└── .github/workflows/
└── build.yml # CI: build, lint, test
- Node.js 22+
- pnpm (package manager)
git clone https://github.com/KofiiDeKoder/PastPaper-Downloader.git
cd PastPaper-Downloader
pnpm install
| Variable |
Default |
Description |
PORT |
3000 |
Backend server port |
VITE_PORT |
5173 |
Frontend dev server port |
DOWNLOAD_ROOT |
./downloads |
Default download directory |
LOG_LEVEL |
info |
Logging level (debug/info/warn/error) |
# Start both Vite and Hono dev servers
pnpm dev
Open http://localhost:5173
| Command |
Description |
pnpm dev:server |
Start Hono server only (port 3000) |
pnpm build |
Build frontend for production |
pnpm build:server |
Bundle server with esbuild |
pnpm test |
Run Vitest tests |
pnpm test:e2e |
Run Playwright E2E tests |
pnpm type-check |
TypeScript type checking |
pnpm lint |
ESLint |
| Method |
Endpoint |
Description |
GET |
/api/health |
Server health status |
| Method |
Endpoint |
Description |
GET |
/api/config/subjects |
List all Cambridge subjects |
GET |
/api/config/sources |
List scraping sources |
GET |
/api/config/bundles |
List subject bundles |
GET |
/api/config/settings |
Get app settings |
PUT |
/api/config/settings |
Update app settings |
GET |
/api/config/download-root |
Get configured download path |
| Method |
Endpoint |
Description |
POST |
/api/download/start |
Start a download session |
POST |
/api/download/pause |
Pause active session |
POST |
/api/download/resume |
Resume paused session |
POST |
/api/download/cancel |
Cancel active session |
POST |
/api/download/retry |
Retry failed files from a session |
GET |
/api/download/progress |
SSE event stream for real-time progress |
DELETE |
/api/download/:id |
Delete a downloaded file and record |
| Method |
Endpoint |
Description |
GET |
/api/library |
Paginated, searchable list of downloaded papers |
GET |
/api/sessions |
List all download sessions |
GET |
/api/sessions/:id |
Get session details with files |
GET |
/api/stats |
Global archive statistics |
The /api/download/progress endpoint streams events with a type field in the data payload:
| Event Type |
Description |
discovery:start |
Paper discovery phase started |
file:discovered |
Individual file discovered |
discovery:complete |
Discovery phase finished |
file:start |
File download started |
file:progress |
Download progress update |
file:complete |
File download completed |
file:skipped |
File skipped (duplicate) |
file:failed |
File download failed |
queue:progress |
Overall queue progress |
queue:paused |
Queue paused |
queue:resumed |
Queue resumed |
session:complete |
Entire session finished |
Contains 200+ Cambridge subjects with their syllabus codes, qualification levels, and available exam sessions.
{
"name": "Physics",
"code": "9702",
"level": "AS/A Level",
"sessions": ["s", "w", "m"]
}
Session codes: s = Summer (May/June), w = Winter (Oct/Nov), m = March
Defines scraping sources with priorities, URL patterns, CSS selectors, and rate limits.
| Source |
Priority |
Status |
| XtremePapers |
2 |
Enabled |
| PapaCambridge |
1 |
Disabled |
| Cambridge Official |
3 |
Disabled |
Quick-select groups for common subject combinations:
- Sciences — Biology (9700), Chemistry (9701), Physics (9702), Sciences (0610), Chemistry (0620), Physics (0625), Physics (5090), Chemistry (5070), Physics (5054)
- Maths — Maths (9709), Further Maths (9231), IGCSE Maths (0580), Additional Maths (0606), Maths (4024), Maths (4037)
- Humanities — Economics (9708), History (9609), Geography (9489), Psychology (9990), English Language (9093), Accounting (9706), Business Studies (2281), Accounting (7115), Commerce (2251)
- IGCSE Core — Maths (0580), Sciences (0610), Chemistry (0620), Physics (0625)
Downloaded papers are saved with this structure:
downloads/
├── physics_9702/
│ ├── 2024/
│ │ ├── s24/
│ │ │ ├── 9702_s24_qp_1.pdf
│ │ │ ├── 9702_s24_ms_1.pdf
│ │ │ └── 9702_s24_qp_2.pdf
│ │ └── w24/
│ │ ├── 9702_w24_qp_1.pdf
│ │ └── 9702_w24_ms_1.pdf
│ └── 2023/
│ └── ...
├── chemistry_9701/
│ └── ...
└── mathematics_9709/
└── ...
| Code |
Type |
qp |
Question Paper |
ms |
Mark Scheme |
er |
Examiner Report |
sp |
Specimen Paper |
in |
Insert |
See docs/agent-instructions.md for coding guidelines and docs/dev-plan.md for the development roadmap.
For personal educational use only. Cambridge past papers are copyrighted by Cambridge Assessment International Education.