Skip to content

Azure Flash Cards#

TL;DR: flashcards.simondevs.com is a mobile-first Azure certification flashcard app. The interesting bit is the content pipeline: agents generate atomic cards from Microsoft Learn, validate every card against its cited source, and only then ship the JSON that the React app serves.

Open the site → Back to projects →

What it is#

The app is a React 19 + Vite static site that serves one complete-course deck plus module-level decks for each certification track. Current examples include AZ-900, AI-901, DP-900, SC-900, and GH-900 rather than a single monolithic deck.

At runtime the app eagerly loads all *.cards.json files with import.meta.glob, builds a course/module index, and exposes three stable routes:

  • /courses/{course}
  • /courses/{course}/complete
  • /courses/{course}/{module}

The complete-course view merges every module card in a course and shuffles the session client-side, while module pages keep the same study flow scoped to a single module.

How I generate the flashcards#

The content model is intentionally simple:

  • src/content/courses.json is the course registry.
  • src/content/{course_id}/{module-slug}.cards.json stores one module per file.
  • Each module file carries module_title, module_url, section_tag, topics, and a cards array.
  • Each card includes id, question, answer, explanation, source_module_url, and section_tag.

Generation is agent-driven rather than script-driven. The generator agent takes four inputs — course_id, display_name, course_url, and target_card_count — then:

  1. Registers or updates the course in courses.json.
  2. Builds a module matrix from Microsoft Learn learning paths and modules.
  3. Allocates the target card count across sections and modules.
  4. Spawns module-level work that reads the source content, skips filler and lab-only material, and writes atomic cards in mixed styles.

The cards are not all plain definitions. The generator uses a style guide that mixes direct recall, cloze, scenario, comparison, why, multiple choice, true/false, layered answers, and mnemonic cards so the deck feels like study material instead of a glossary dump.

How I review cards with agents#

There is a separate validation agent that reviews the generated cards before I consider them publishable. It fetches each distinct source_module_url, grounds every judgment in the cited Microsoft Learn page, and scores every card on:

  • correctness
  • explanation quality
  • usefulness
  • atomicity
  • citation quality
  • style fit

Anything below the normalized 0.9 threshold gets remade or refactored and sent back through validation. The validator also checks module-level style variety, writes a report to artifacts/<course_id>-validation.json, and leaves a final manual review step before publish.

That split between generator agent and validator agent matters: one agent optimizes for coverage and card quality, the other optimizes for source-grounded accuracy and review pressure.

Delivery details#

The site is built for static hosting on Azure Static Web Apps. Deep links work because staticwebapp.config.json rewrites unknown routes back to index.html, which keeps the React Router paths usable in production.

That means the whole flow stays lightweight:

  1. Agents produce JSON.
  2. The frontend bundles it at build time.
  3. Azure Static Web Apps serves the finished deck as a static site.

Agents Diagram#

This is the pipeline diagram for the generator and validator workflow:

flowchart TD
    A[Inputs: course_id, display_name,<br/>course_url, target_card_count] --> B[Step 1: Register course<br/>in courses.json]
    B --> C[Step 2: Build module matrix<br/>fetch learning paths and modules]
    C --> D[Step 3: Allocate cards<br/>across sections then modules]
    D --> E{For each module<br/>launch a subagent}

    subgraph GEN[Generation per module]
        E --> F[Read module source<br/>skip intro/filler/labs]
        F --> G[Write atomic cards<br/>mixed styles - flashcards-styles.md]
        G --> H[Add topics bullets]
    end

    H --> V

    subgraph VAL[Validation - CONTENT-VALIDATION.md]
        V[Fetch each source_module_url] --> W[Score 6 axes: correctness,<br/>explanation, usefulness,<br/>atomicity, citation, style_fit]
        W --> X{normalized score >= 0.9?}
        X -- No --> Y[Remake / refactor card]
        Y --> W
        X -- Yes --> Z[Keep card]
    end

    Z --> R[Schema validate + dedupe<br/>write artifacts/<course>-validation.json]
    R --> S[npm run lint and npm run build]
    S --> T[Publish: /courses/{course_id}]