Certification study app

Forge your way to certification.

CertForge is a self-hosted study app for IT certification exams. It pairs a written study guide built from each exam’s official outline with a bank of 500 exam-style questions per certification, then puts them behind practice tests that score you the way the real exam does — and, more usefully, tell you exactly which domains to go back and study.

Certifications
2

GH-300 · AZ-204

Questions
1,000

500 per certification

Explanations
5,143

one per question and option

Study guide
20k

words of written material

What it is

A study tool that teaches, not a pile of flashcards.

Most certification prep gives you a score and a list of question numbers you got wrong. That tells you almost nothing. CertForge is built around the opposite idea: the value is in the explanation and the diagnosis, so every part of the app works backwards from “what should I study next?”

Study guides built on the official outline

Each certification gets a written guide organised by the exam’s real domains, in the same order and carrying the same weightings the vendor publishes.

  • Every objective in the official skills-measured outline is covered — nothing is summarised away.
  • Rendered from Markdown, so guides carry headings, tables, code blocks, and callouts.
  • A domain sidebar lets you jump straight to the area your last test flagged as weak.
  • Roughly 20,000 words across the two certifications currently loaded.

A 500-question bank per certification

Questions are written to match the style, format, and difficulty of the real exam — not trivia, and not flashcards.

  • Distributed across domains in proportion to the official weightings, exactly.
  • Single-answer and select-all-that-apply, mirroring how the real exams ask.
  • A deliberate spread of easy, medium, and hard items so a full-length test feels realistic.
  • Every question is tagged with the domain it belongs to, which is what makes the diagnostics work.

Practice tests you configure

Choose the certification and how long you want the test to be — from a quick ten questions up to the full length of the real exam.

  • Questions are drawn at random from the bank; no question repeats inside a test.
  • Answer in any order, jump between questions, and change your mind before submitting.
  • Progress is saved as you go, so a test survives a closed tab.
  • Unanswered questions count as incorrect — the same way they do on exam day.

Results that tell you what to study next

A score is the least interesting thing a practice test can give you. The review is the point.

  • Scored against the real exam’s passing threshold, with a clear pass or fail.
  • A per-domain breakdown showing exactly where you are strongest and weakest.
  • Every question you got wrong, with the answer you chose and why it is wrong.
  • The correct answer alongside it, with an explanation of why it is right.

Certifications

Two exams covered end to end, with room for more.

Each certification is an independent set of study material and questions. Nothing about the app is specialised to a particular exam — adding another is a data change, not a code change.

GH-300

GitHub Copilot

GitHub

Validates your skills in using, managing, and understanding GitHub Copilot: plans and features, how suggestions are generated, prompt engineering, privacy controls, and responsible AI.

Who it’s for: Developers and administrators who use Copilot day to day and need to prove they understand its plans, data handling, and limits.

Questions
75
Minutes
100
To pass
70%
In bank
500

7 exam domains · questions allocated by weight

  • Responsible AI7% · 35 Q
  • GitHub Copilot plans and features31% · 155 Q
  • How GitHub Copilot works and handles data15% · 75 Q
  • Prompt crafting and prompt engineering9% · 45 Q
  • Developer use cases for AI14% · 70 Q
  • Testing with GitHub Copilot9% · 45 Q
  • Privacy fundamentals and context exclusions15% · 75 Q
AZ-204

Microsoft Azure Developer Associate

Microsoft

Validates your skills in developing Azure solutions: compute, storage, security, monitoring and optimization, and connecting to Azure and third-party services.

Who it’s for: Developers who build, deploy, and maintain cloud applications on Azure and want the associate-level developer credential.

Questions
55
Minutes
100
To pass
70%
In bank
500

5 exam domains · questions allocated by weight

  • Develop Azure compute solutions30% · 150 Q
  • Develop for Azure storage19% · 95 Q
  • Implement Azure security19% · 95 Q
  • Monitor, troubleshoot, and optimize Azure solutions8% · 40 Q
  • Connect to and consume Azure services and third-party services24% · 120 Q

Adding a certification

Append the exam’s domains and weightings to the shared catalog, drop a study guide and a set of question files into seed-data/, and re-run the seeder. The catalog, the practice-test engine, and the results breakdown all read from that data — no page, endpoint, or database change is needed. The seeder is idempotent, so re-running it only adds what is missing.

How it works

What a study session actually looks like.

The loop is deliberately short: study a domain, test yourself on it, read why you were wrong, go back. Everything in the app exists to make that loop fast.

  1. 1

    Pick a certification

    The catalog shows each exam’s real format up front — how many questions, how many minutes, the score you need, and how the domains are weighted.

  2. 2

    Read the study guide

    Work through the domains in order, or jump straight to the ones a previous test exposed. The guide is organised the same way the exam is.

  3. 3

    Set the test length

    Ten questions to warm up, twenty-five over a lunch break, or the full exam length when you want to know whether you are actually ready.

  4. 4

    Sit the test

    One question at a time, with a progress bar and a map of which questions you have answered. Move around freely and submit when you are done.

  5. 5

    Review every mistake

    Read why each wrong option is wrong and why the right one is right. Then look at the domain breakdown and go back to the guide for whatever is lagging.

  6. Every test you sit is kept in your history, so you can watch a weak domain climb over successive attempts instead of guessing whether you have improved.

Question quality

Every question has to teach something.

The questions are the part of this app that matters most, so they are held to a fixed contract. A question is not finished until a reader who got it wrong understands why.

The contract

  • One correct answer set, unambiguous against the official documentation.
  • An explanation of the underlying concept — not a restatement of the correct option.
  • A separate explanation for every incorrect option, saying what it confuses and why it fails.
  • A domain tag, so the question feeds the per-domain diagnostics.
  • Wording, format, and difficulty that match how the real exam asks.

What’s in the banks today

Questions
1,000
Answer options
4,143
Written explanations
5,143
Select-all-that-apply
143
Difficulty mix
201 easy · 557 medium · 242 hard
Sample questionResponsible AIGH-300 · easy

Which of the following is a commonly cited risk of using generative AI coding assistants such as GitHub Copilot?

ASuggestions may contain security vulnerabilities or outdated, insecure patterns.

Correct. Generative models learn from large volumes of public code, which includes insecure examples, so suggestions can reproduce vulnerable patterns such as injection-prone queries or weak cryptography. This is why generated code must be reviewed and scanned like any other code.

BThe assistant permanently locks any file it generates code into.

Incorrect. AI coding assistants only propose text in the editor; they do not take exclusive control of files or restrict who can edit them. This confuses AI suggestions with version-control locking mechanisms.

CSuggestions are always copied verbatim from a single source repository.

Incorrect. Suggestions are generated token by token from learned statistical patterns, not retrieved as wholesale copies of one repository. Rare near-matches to public code can occur, but “always copied verbatim” misdescribes how generative models work.

DThe assistant automatically executes any code it generates.

Incorrect. Code-completion tools insert suggestions into the editor for the developer to accept or reject; they do not run the code. Execution remains a deliberate human (or CI) action, which is part of what keeps a human in the loop.

Why: A core risk of generative AI coding tools is that they can suggest code containing security vulnerabilities, because the public code they learned from includes insecure examples. The rule of thumb: treat AI-generated code with at least the same scrutiny (review, testing, security scanning) as human-written code.

This is a real item from the GH-300 bank, rendered the way the results page shows it after a test.

Under the hood

How the app is put together.

CertForge started as a React front end talking to a Python API. It is now a single Next.js application: the same screens and the same API surface, with the server layered the way the original backend was.

One Next.js application

Next.js 16 App Router with React 19 and TypeScript. The pages and the API ship as a single deployable — there is no separate backend service to run or keep in sync.

A layered server

Route handlers do HTTP only: authenticate, parse, delegate, map the response. Business rules live in services, and every query lives in a repository. Nothing reaches past its layer.

PostgreSQL via Drizzle

A typed schema with SQL migrations under version control. Random question draws, per-domain aggregation, and pagination are done in the database rather than in memory.

Session handling

JWT access tokens with a rotating refresh token: reusing an old refresh token fails. Passwords are stored as PBKDF2-SHA256 hashes with 200,000 iterations.

RTK Query on the client

Each feature injects its own endpoints into one shared API slice, with cache tags for invalidation and a transparent token refresh when an access token expires.

Tests against real Postgres

The API suite drives the actual route handlers against an in-process Postgres, so scoring, tenant isolation, and the rule that answers never leak early are all covered without an external database.

The API surface

Every screen is driven by a small JSON API. It is the same set of paths and payloads the original Python backend served, so either implementation can sit behind the same client.

  • POST/api/auth/registerCreate an account and start a session
  • POST/api/auth/loginExchange credentials for tokens
  • POST/api/auth/refreshRotate the refresh token
  • GET/api/certificationsThe catalog, with domains and bank sizes
  • GET/api/certifications/:id/study-guideGuide content per domain
  • POST/api/practice-testsDraw a new test
  • PUT/api/practice-tests/:id/answersSave an answer
  • POST/api/practice-tests/:id/submitScore and finish
  • GET/api/practice-tests/:id/resultsBreakdown and review

Project layout

Organised by feature on the client and by layer on the server. Dependencies point one way: route handler, then service, then repository, then schema.

src/
  app/          routes — pages and API handlers
  features/     one folder per feature: api, types, pages
  shared/       UI primitives, catalog data, helpers
  server/
    api/        request schemas and response mapping
    services/   business rules and scoring
    repositories/  every database query
    db/         Drizzle schema and client
seed-data/      study guides and question banks
tests/          API tests on in-process Postgres

Status

Where this deployment stands.

This is a personal project, deployed publicly so it can be looked at. Being straight about what does and does not work right now:

No database attached yet

The app is built so the database connection is optional at build time and opened lazily at runtime. That means it deploys and serves pages with nothing attached — but anything that needs data (signing up, browsing the catalog, sitting a test) answers with a clear “the database is not configured yet” message instead of failing obscurely.

Point DATABASE_URL at a Postgres instance, redeploy, then run the migration and the seeder — the full app comes to life with both question banks loaded.

Running it yourself

With Node 20+ and a local PostgreSQL, the whole thing is four commands:

npm install
npm run db:migrate   # create the schema
npm run db:seed      # load guides + 1,000 questions
npm run dev          # http://localhost:3000

In development the login page offers seeded test credentials, so you can be inside the app within a minute of the seeder finishing.

Ready to start studying?

Create an account, pick GH-300 or AZ-204, and take a ten-question test to see where you stand before you read a single page of the guide.