Focused German C-Test practice from A1 to C2, with useful feedback after every attempt.
SimDaF is a community-focused platform for learners preparing for German as a foreign language (DaF) certifications. It recreates the focused pressure of a language exam while keeping practice approachable, private, and easy to repeat.
The project currently concentrates on practice exams—not lessons or study materials. Its goal is simple: let learners reconstruct German texts, understand their mistakes in context, and try again with better insight.
Independent project: SimDaF is not affiliated with, endorsed by, or operated by any certification institute, educational organization, or official examination body. Scores and CEFR levels shown by the platform are practice estimates, not official results.
Source code and issue tracking are available on GitHub.
- 14 bundled C-Tests across A1–C2, covering everyday life, work, communities, science, cities, decision-making, and advanced abstract topics.
- Natural reading flow. Missing word endings appear inline with the passage instead of as disconnected questions.
- Keyboard-inclusive practice. Insert
ä,ö,ü, andßfrom a quick-access row or open the complete German QWERTZ keyboard. - Detailed answer review. See the complete text, your answer, the expected completion, nearby context, and a custom linguistic explanation for each mistake.
- Flexible grading. Exams can use strict matching or learner-friendly matching with German character equivalences and limited typo tolerance.
- Three timer modes. Easy uses the exam's full duration, Medium halves it, and Hard reduces it to one quarter.
- Indicative CEFR feedback. Each exam defines realistic thresholds that never assess above that exam's declared difficulty.
- Private progress history. Results are saved in the browser only after consent and can be exported or deleted.
- Comfortable practice at any hour. The responsive interface includes automatic dark mode and a manual theme toggle.
No account, subscription, or remote database is required.
A C-Test measures grammar, vocabulary, spelling, and contextual reading together. The learner reads a short text and reconstructs missing parts of selected words.
SimDaF's generated passages follow these rules:
- The first sentence remains complete to establish context.
- Starting with the second sentence, every second eligible word becomes a blank.
- The beginning of the target word remains visible and its ending must be entered.
- Numbers, single-letter words, and explicitly protected terms are skipped.
- Punctuation and whitespace are preserved so the result still reads like a normal paragraph.
The platform also supports authored sequences with hand-written inputs and dropdown choices when an exercise needs more deliberate control.
Learners do not need a physical German or Latin-script keyboard. After selecting a blank, they can:
- Insert
ä,ö,ü, orßfrom the compact character row beneath the passage. - Open an optional German QWERTZ keyboard containing Latin letters, German characters, numbers, punctuation, and shifted symbols.
- Use Shift, Space, Backspace, and Next blank controls without leaving the passage.
Virtual keys insert at the current caret, replace selected text, and respect the exact maximum length of the missing word ending. The selected blank remains visibly highlighted so it is always clear where the next character will appear.
SimDaF has no authentication or server-side learner profile.
- The active result is kept in session storage so its review page remains available in the current browser session.
- Attempt history is written to local storage only when the learner explicitly chooses to save it.
- Saved history can be exported as JSON or deleted from the History screen.
- Imported exam files stay in the browser and are not uploaded.
- Theme and timer preferences are stored locally on the device.
BYE—Bring Your Exam—is SimDaF's memorable route for power users who want to create and check their own practice content. Download data/exams/exam-example.json as the canonical starting point; the same file is available from the BYE import screen.
The current importer validates the basic C-Test metadata and stages valid JSON for the browser session. Running an imported exam directly from the catalog is still planned; bundled exams are registered in code today.
- Deno 2.x
- Git
The application uses Next.js npm packages through Deno's npm compatibility layer. Use Deno for dependency installation and every project task—npm is not required.
git clone https://github.com/gurgelff/simdaf.git
cd simdaf
deno install
deno task devOpen http://localhost:3000.
| Command | Purpose |
|---|---|
deno task dev |
Start the Next.js development server |
deno task test |
Run C-Test, exam-content, timer, and virtual-keyboard tests |
deno task lint |
Run ESLint |
deno task build |
Create and validate a production build |
deno task start |
Serve a completed production build |
The project uses manual Node module resolution through deno.json.
- Runtime and tooling: Deno 2
- Framework: Next.js 16 App Router
- UI: React 19 and TypeScript
- Styling: Tailwind CSS 4 plus project CSS
- Content: Versioned local JSON exam definitions
- Persistence: Browser session storage and opt-in local storage
- Testing: Deno's built-in test runner
Server Components are used for catalog and exam routes. Client Components are limited to interactive concerns such as filters, practice inputs, virtual keyboards, timers, themes, imports, results, and local history.
app/
├── api/exam-example/ Downloadable example exam
├── exams/[examId]/ Overview, practice, and result routes
├── history/ Opt-in local attempt history
├── import/ JSON import interface
└── *.tsx Catalog and interactive UI components
data/exams/ Bundled, versioned exam JSON files
lib/exams/ Types, C-Test generation, grading, and catalog
lib/timer-mode.ts Global timer-mode rules
lib/virtual-keyboard.ts Caret-aware virtual-key editing
TECH.md Engineering conventions
PLAN.md Product scope and implementation plan
Every exam uses the shared shape defined in lib/exams/types.ts. A minimal raw-text exam looks like this:
{
"schemaVersion": "1.0",
"id": "ctest-german-a2-example",
"version": 1,
"type": "c-test",
"title": "Ein Tag in der Stadt",
"description": "Ein C-Test über einen alltäglichen Weg durch die Stadt.",
"language": "de",
"level": "A2",
"durationSeconds": 600,
"gradingProfile": "strict",
"cefrThresholds": [
{ "minimumPercentage": 0, "level": "A1" },
{ "minimumPercentage": 60, "level": "A2" }
],
"passages": [
{
"id": "passage-1",
"title": "Unterwegs",
"content": {
"kind": "raw-text",
"text": "Die erste Aussage schafft einen klaren Kontext. Danach beginnt die automatische Erzeugung der Lücken."
},
"protectedTokens": [],
"explanations": {
"passage-1-input-12": "Explain the spelling, grammar, or contextual clue required by this specific answer."
}
}
]
}| Field | Meaning |
|---|---|
id |
Stable, unique exam identifier used in routes and saved attempts |
version |
Increment when answer-relevant content changes |
level |
Maximum CEFR level the exam is designed to assess |
durationSeconds |
Easy-mode baseline; Medium and Hard derive their time from it |
gradingProfile |
strict or learner-friendly |
cefrThresholds |
Percentage-to-level mapping; no threshold may exceed level |
passages |
One or more raw-text or authored-sequence passages |
protectedTokens |
Terms the raw-text generator must leave complete |
explanations |
Custom feedback keyed by generated input ID |
Raw-text input IDs depend on token positions. After changing passage text, run the tests and update every explanation key. Bundled content is expected to provide a specific explanation for every input or dropdown.
For exact examples of both passage formats, inspect exam-example.json.
- Copy the example JSON and give the exam a unique
id, title, version, and appropriate CEFR level. - Write original German passages and define realistic thresholds that do not exceed the exam level.
- Add a custom explanation for every generated blank or authored answer.
- Import the JSON file and add it to
bundledExamsinlib/exams/catalog.ts. - Update the expected bundled-exam count in
lib/exams/ctest.test.ts. - Run the full validation sequence:
deno task test
deno task lint
deno task buildThe content test checks unique IDs, CEFR coverage, threshold limits, answer availability, and explanation coverage across every bundled JSON file.
Contributions can improve exam content, accessibility, language feedback, grading behavior, tests, or the platform itself.
Before changing code:
- Read
TECH.mdfor the project's implementation philosophy. - Check
PLAN.mdfor current scope and deliberate exclusions. - Read the relevant local Next.js guide under
node_modules/next/dist/docs/; this project uses a version with conventions that may differ from older Next.js releases.
Please keep changes focused, preserve strict TypeScript checks, and use Deno rather than npm for package and task commands. The repository follows concise Conventional Commit messages such as:
feat(exams): add B2 workplace C-Test
fix(styles): improve mobile timer spacing
test(exams): validate explanation coverage
Prefer one changed file per commit when practical so content and implementation changes remain easy to review.
SimDaF currently provides C-Test practice only. It intentionally does not include:
- Study lessons or general learning materials
- Official certificate scoring
- User accounts or cloud synchronization
- A remote exam database
- Live integrations with certification providers
This narrow scope keeps the platform fast, inspectable, and useful as both a learner-facing tool and a foundation for community-authored mock exams.
PLAN.md— product behavior, assumptions, and planned architectureTECH.md— strict development and code-quality conventionsexam-example.json— canonical content fixture
SimDaF is available under the ISC License.