Contributing
Contributions are very welcome; please contact us by email or by filing an issue in our repository. All contributors must abide by our Code of Conduct.
Contributors
Greg Wilson is a programmer, author, and educator based in Toronto. He was the co-founder and first Executive Director of Software Carpentry and received ACM SIGSOFT's Influential Educator Award in 2020.
Many thanks to Rebecca for early feedback.
FAQ
- Do you need help?
- Yes—please see the issues in our repository.
- What sort of feedback would be useful?
- Everything is welcome, from pointing out mistakes to suggestions for better explanations.
- Can I add a new section?
- Possibly, but please reach out before doing so.
- Why is this material free?
- Because if we all give a little, we all get a lot.
Setup and Operation
- Install uv.
- Create a virtual environment by running
uv venvin the root directory. - Activate it by running
source .venv/bin/activatein your shell. - Install dependencies by running
uv sync. - Run
task --listto see a list of tasks.
Writing Style
These rules apply to all lesson prose.
- Write in a conversational tone. Rely on anecdotes about specific events rather than abstract generalizations.
- Use the active voice wherever possible.
- Readers are intelligent and have large vocabularies, but are not familiar with specialist terms beyond what they would learn in high school classes.
- Do not use bold in prose. Use italics sparingly, and only for emphasis or introducing a term.
- Use four-space indentation in bullet lists: a dash and three spaces for top-level items, four spaces then a dash and three spaces for nested items.
- Do not use tab characters anywhere in Markdown files.
- Use semicolons and em-dashes sparingly.
Never write
---in prose; if an em-dash is truly needed, use the actual character (—) with no spaces around it. - Do not attempt to be funny or offer generic positive feedback to readers.
- Each lesson must include citations or links for further reading.
Use
[text][key]for external links and definekeyin_extras/links.md.
Lesson Structure
- Each lesson lives in its own directory (
lessonname/index.md). - The lesson order is defined in
README.md. - Start each lesson with a
<div class="callout">listing the three to five key takeaways as sentences. - Write self-test questions as
<details>blocks (see any existing lesson for the exact format). - Write exercises under an H2 heading named
Exercises. Wrap each exercise in<div class="exercise">and include a time estimate in parentheses in the H3 heading. - Reference glossary terms with
<a class="gl-ref" href="@/glossary/#key">display text</a>. - Reference bibliography entries with
[<a class="bib-ref" href="@/bibliography/#Key1">Key1</a>, <a class="bib-ref" href="@/bibliography/#Key2">Key2</a>].
Gleam Code Style
Gleam source files live in lesson/src/; their tests are in lesson/test/
and their captured output is in lesson/out/.
- Run
gleam formaton every.gleamfile before committing. - All
gleam.tomlfiles must specifygleam_stdlib = ">= 1.0.0 and < 2.0.0". Do not use>= 0.34.0; that range predates the stable 1.0 release. - Annotate all public top-level functions and types with explicit type signatures. Type inference is fine for local bindings and private helpers.
- Use meaningful variable names (e.g.,
itemsinstead oflst). Avoid single-letter names except for genuinely generic type parameters (a,b) and short mathematical expressions. - Prefer
int.to_string,float.to_string, and similar concrete conversion functions overstring.inspectwhen printing known types. Reservestring.inspectfor debugging values whose type is not known statically. - Do not use
io.debug; it was removed from the standard library. Useio.printlnwith an explicit conversion rather thanecho. - Write tests using the
assertkeyword. Thegleeunit/shouldmodule is deprecated; do not useshould.equal,should.be_ok, or any other function from it. - Prefer custom error enum types over
Stringas the error type inResult. A custom type lets the compiler verify that every error case is handled. - Use
Optionfor optional record fields and optional parameters. For return types that can fail, preferResult, which can carry an error description. - Use
result.tryfor chaining fallible operations.result.mapis for single-step transformations;result.map_errortransforms the error side;result.unwrapextracts a value with a fallback. - Use the
useexpression when chaining three or more fallible operations. For one or two operations, acaseexpression is usually clearer. - Type aliases are rarely useful in normal code. Their main purpose is re-exporting opaque internal types from a module. Do not introduce type aliases just for readability.