Templates and formatting for Data 8's Discussion and Tutoring Worksheets, Reference Sheet, Notes and Exams.
This library was first created for UC Berkeley's Data 8 in the Fall 2025 semester.
- automatic point totalling and incrementing sections (for exams or graded assignments)
- multiple choice questions (single select and multiselect, or mix of bubble types)
- answer boxes for long answer questions
- native typst indentation for subquestions
- syntax highlighting for code blocks
- custom answer blank for coding questions
- callouts for notes and information boxes
- assignment and exam template, see below
- togglable document modes (print, screen, answer), see below
Example PDFs can be found in the examples/ directory and quick start templates in the quickstart/ directory.
There are three library files: utils.typ which defines the different question components and other niceties, assignment.typ which formats for assignment documents (worksheets, notes), and exam.typ which formats for exams.
Quick Navigation:
Long answer question with an optional answer box/space.
#question(ansbox, height, ansheight, ansalign, points)[<question>][<answer>]Parameters
question(content, required): question statementanswer(content, required): answer contentansbox(bool, default:false): draw a box underneath the questionheight(length | auto, default:auto): height of the entire question blockansheight(length | auto, default: see notes below): height of the entire question when the answer is shownansalign(alignment, default:horizon): alignment of the contentpoints(float, default:""): points assigned to the question
Examples
#question(ansbox: true, ansheight: 3cm, points: 4.0)[ What is $2 + 2$? Write a statement to evaluate in Python. // since this is just Typst content, it can be anything (could include tables, math, images, code blocks, etc...) ][ `2 + 2 # 4` ]
When the answer box is not shown, the default ansheight is auto (fits to content). When the answer box is shown, the default ansheight is the same as the height defined.
You may override ansheight to your liking if you don't want this behaviour
Multiple choice questions that support different bubble types (circle, box) with optional answer explanations.
#mcq(question, choices, answer,
cols, multi, color,
ansbox, height, ansheight, ansalign, explanation, points)Parameters
question(content, required): question statementchoices(array ofcontent, required): choicesanswer(intor array ofint): index (0-indexed) of correct answer choice OR array of correct answer choicescols(intor array oflength, default:1): number of answer choice columns. defaults to1so options are shown vertically. For horizontal use column count equivalent to number of choices. You may also specify array of lengths, where each length corresponds to the length of that choice displayed horizontallycolor(color, default:colorblue): sets color of bubble fill in answer modemulti(boolor array ofbool, default:false): display box as square (multi =true) or circle (multi =false). You may specify an array of booleans to customise each bubbleexplanation(content, default:""): an explanation of the selected answer option displayed underneath the question. Only shown when answers are shownansbox, height, ansheight, ansalign, points: same as#question(see above)
Examples
#mcq([What will the following Python expression be equivalent to? #align(center)[`2 + 2`] ], ( `4`, `len(np.array([1, 2, 3, 4]))`, `2`, `6`, "None of the above" ), (0, 1), points: 3.0, multi: (true, true, true, true, false) )#mcq([You can display options with different column lengths.], ( [Option 1], [Option 2], [Option 3], [Option 4] ), 2, points: 3.0, multi: false, cols: (2.5cm, 5cm, 7cm, 4cm), )
A bank of answer choices to select from.
#ansbank(cols, choices) Parameters
cols(int, required): number of columns to display answer choiceschoices(array ofcontent, required): choices
Examples
#ansbank(cols: 3, choices: ( [$x^2$], "Any linear function", `x ** 2`, "Any quadratic function", $x dot.c x dot.c x$, `pow(x, 3)`, $sin(x)$, "Any quartic function", $cos(x)$ )) #mcq([ What of the following functions are even? ], range(9).map(i => [*#str.from-unicode(65 + i)*]) + ("None of the above",), (0,2,8), points: 1.0, cols: range(9).map(i => 1.53cm) + (10cm,), multi: range(9).map(i => true) + (false,) )
#section(title, height, number, points, content)Parameters
title(int): number of columns to display answer choicesheight(length, default:auto): height of entire sectionnumber(bool, default:true): boolean to automatically count up sections (add1.,2., ...etc in front of title)points(bool, default:false): boolean to count up points in section
Examples
#section("First Section")[ Content in this section does not total up points of sub questions. ] #v(12pt) #section("Second Section", points: true)[ Content in this second section does total up points + #question(points:2.0)[Subquestion][Subquestion answer] + #question(points:2.0)[Subquestion][Subquestion answer] + #question(points:2.0)[Subquestion][Subquestion answer] ]
A #section will automatically total up all subquestion point values wrapped in that section. You can choose to display this counter in front of the question with the points parameter.
If you would like each section to start on a new page, insert a #pagebreak() between section blocks.
For exams/worksheets that want all questions to display points and number, you can use this let statement at the top of the document. This will enable number and points for every section and you do not need to specify these parameters for each section block.
#let section = section.with(number: true, points: true)#callout(t, content)Parameters
t(str): type of callout. Special callout types areDefinition, Formula, Method, Example. Use empty string""to omit the title.
Example
#callout("")[ You may create a callout with an empty string `""` to omit the title. Any non-special typed callout will be grey by default. ] Special callout types (`Definition, Formula, Method, Example`) #callout("Definition")[ A definition callout ] #callout("Formula")[ A formula callout ] #callout("Method")[ A method callout ] #callout("Example")[ An example callout ]
Blanks for coding questions can be used in between code blocks to draw a labelled line for students to fill in.
#blank(width, placeholder, answer)Examples
`def distance(p1, p2, row):` ` arr = np.array(row)` ` v1 = arr.`#blank(150pt, "[A]") ` v2 = arr.`#blank(150pt, "[B]") ` distances = `#blank(250pt, "[C]") ` `#blank(200pt, "[D]")
You can draw boxes (like Latex) around answers with #boxed(...).
Example
$ y = 1/10x ==> boxed(x = 10 y) $
Indicator to skip a page / indicate it is blank.
Example
#blankpage([This page intentionally left blank The exam begins on the next page. ])
Indicator to see next page.
Example
#nextpage([See next page])
#bubble(content, color)Example
The #bubble(`def`, colorred) keyword is used for creating functions in Python. To return a value in the function, use the #bubble(`return`, colorgreen) keyword.
Examples
#section("Section Title", number: false)[ Some content in the section #subtitle("A smaller title") More stuff ]
This library provides a few colours that can be used, and are defined as follows:
| colour | hex | |
|---|---|---|
colorblue |
#2A40E2 |
|
colorcyan |
#6993BF |
|
colorred |
#DD4466 |
|
colorgreen |
#59B279 |
|
colorgrey |
#808C80 |
|
colorlightcyan |
#E8EDF4 |
|
colorlightred |
#F4E8EC |
|
colorlightgreen |
#E8F4EC |
|
colorlightgrey |
#F6F6F6 |
This library provides two templates, one for writing assignments/worksheets, and the other for exams. You can find examples for assignment templates here (discussion) and here (note). You can find an example exam here. The quickstart templates for assignments and exams can be found in the quickstart/ directory.
#show: doc => assignment(doc,
courseid: "Data C8",
coursename: "Foundations of Data Science",
school: "UC Berkeley",
semester: "Fall 2025",
assignment: "Discussion 01",
title: "Introduction"
)#show: doc => exam(doc,
courseid: "Data C8",
coursename: "Foundations of Data Science",
school: "UC Berkeley",
semester: "Fall 2025",
instructor: "",
examtitle: "Midterm",
date: "7:10–9:00pm Friday, October 17th 2025",
length: "110 minutes",
blanks: ("Your Name", "Your Student ID", "Your Exam Room", "the Name of Person to your Left", "the Name of Person to your Right", "Your GSI's Name (Write N/A if in Self-Service)"),
instructions: include("instructions.typ"),
extra: include("extra.typ"),
sols: false
)The blanks parameter allows you to pass in an array of strings that create blanks for students to fill out. instructions and include take in any content which are filled in inside instructions, and underneath it respectively. You may find creating separate files for instructions and extra and using include(...) to be more modular.
There are three document modes to choose from, screen, print, and sol.
screen: does not display solutions, and code blocks are highlighted with colourprint: does not display solutions, and all code blocks are displayed as black. Accessible exports so printed code can be easily read on paper.sol: displays solutions and code blocks in colour
These can be controlled with the Typst state variable #docmode and you can use .update(mode) to set the mode at the top of the page, which will affect all components underneath it through to end of page, or another #docmode.update() statement.
#docmode.update(mode)Examples
#docmode.update("print")#docmode.update("screen")#docmode.update("sol")















