Setup
git clone <repo-url> nalar && cd nalar
bun install
bun run dev # http://localhost:4321
Python 3.11+ is only needed when you write coding exercises.
Workflow
- Branch from
main:content/<course>-<topic>orweb/<topic>. - Make your change (see the guides below).
- Run the checks:
bun run format,bun run lint,bun run build, andbun run testwhen touchingcourses/. - Open a pull request and fill in the template. CI must be green before merging.
Commit messages follow Conventional Commits with a scope:
feat(content): hypothesis testing module, fix(quiz): answer key for week 4 question 3, feat(web): about page.
Adding a course
bun run new course <course-id> # lowercase words joined by hyphens, e.g. intro-statistics
Then fill in courses/<course-id>/course.json:
| Key | Required | Notes |
|---|---|---|
title |
yes | Course name |
code |
yes | Short code, e.g. STAT |
credits |
yes | Number of credits (SKS) |
description |
yes | 1-2 sentences: what is learned and why |
phases |
yes | { title, focus, illustration? } in learning order |
program |
no | Study program |
institution |
no | |
language |
no | "python" when the course has coding exercises |
illustration picks a scene: basket, book, clean, clusters, laptop, magnifier, server,
signpost, target. Need a new one? Open an issue or follow the Illustrations section of DESIGNS.md.
Adding a module
bun run new module <course-id> <week> <slug> # with a coding exercise
bun run new module <course-id> <week> <slug> --no-exercise # lesson + quiz only
One module = one week of the course:
| File | Required | Contents |
|---|---|---|
lesson.md |
yes | Front matter + lesson |
quiz.json |
no | choice / numeric / essay questions |
exercise.py |
no | Functions learners complete (paired with the tests) |
solution.py |
no | Answer key for the exercise |
test_*.py |
no | pytest tests that grade the exercise |
lab.ipynb |
no | Practice notebook, saved without outputs |
The learning material itself is written in Indonesian; file names and JSON keys stay in English.
Writing lessons
- Open with Capaian Pembelajaran (3-5 measurable outcomes) and close with Ringkasan.
- Main sections use
##(they feed the table of contents). One concept per section. - Follow every formula with a small worked example that can be done by hand.
- Prefer tables for comparisons over long paragraphs. Math:
$...$or$$...$$.
Writing quizzes
- 10-15 questions per module, mixed types. For topics with calculations, about a third should be
numeric. - Every question has an explanation of why, not just the answer.
- Multiple choice: 4 options, one correct, plausible distractors (common learner mistakes).
numeric: show the working in the explanation; settoleranceto a reasonable rounding margin.essay: case studies; the explanation contains a model answer.
Writing coding exercises
- One function = one concept; the docstring explains inputs, outputs and an example.
- In
exercise.py, the body is# TODOfollowed byraise NotImplementedError. - Tests use the
mfixture (def test_x(m): ...), run fast (< 3 s per file) and fail with clear messages. - Import only stdlib, numpy, pandas, scipy, scikit-learn, networkx and
common.*(so tests run in the browser). - Required:
SOLUTION=1passes everything and the untouchedexercise.pyfails withNotImplementedError.
Web code
Read AGENTS.md (architecture & conventions) and DESIGNS.md (design system).
In short: static pages, React islands only where state is needed, @almach/ui components, Phosphor icons,
semantic color tokens, English code, Indonesian UI copy, and always check narrow screens and dark mode.
Reporting problems
Use the issue templates: Bug report (web bug or incorrect content) or Content proposal (new course, module or questions). Include the page link and steps to reproduce.