CS50 Lab
Note
CS50 Lab will be decommissioned on July 1, 2023. A new-and-improved version will be built into Visual Studio Code for CS50 instead! Documentation coming soon.
CS50 is a programming environment at lab.cs50.io for scaffolded learning that enables
teachers to create step-by-step programming lessons (labs), providing incremental feedback at each step, and
students to progress from an empty file (or starter code) to working code, with hints and feedback along the way.
To create a lab as a teacher, all you need is a GitHub account and a (public or private) repository. To log into and work on a lab as a student, all you need is the former. Neither use case requires familiarity with git
itself though if or once comfortable with git
, you can create labs even more quickly via a command line!
CS50 Lab is essentially an extension of CS50 Sandbox that allows teachers to embed interactive instructions alongside a sandbox. As such, CS50 Lab is, also, essentially a lightweight version of CS50 IDE with problems’ specifications embedded in students’ actual programming environments.
URLs of labs are of the form https://lab.cs50.io/{owner}/{repo}/{branch}/{path}
, where
owner
is the lab’s owner, a GitHub user or organization, on github.com,repo
is that owner’s repository in which the lab’s source can be found,branch
is the branch on which the lab’s source can be found in that repository, andpath
is the path to the lab’s source on that branch.
The source for a lab like lab.cs50.io/cs50/labs/2019/fall/mario/less/ can thus be found in https://github.com/cs50/labs/tree/2019/fall/mario/less/, wherein
cs50
is the lab’s owner (hey, that’s us),labs
is the lab’s repository,2019/fall
is the lab’s branch,mario/less
is the lab’s path, andtree
is just a GitHub-specific trick, sandwiched between:repo
and:branch
, via which you can browse that branch and path.
Creation
To create a lab:
Sign up for a (free) GitHub account, if you don’t have one already.
Create a repository, if you don’t have one (that you’d like to use) already.
Create a file in that repository called
.cs50.yml
, optionally inside of one or more directories, using GitHub’s website. Or create (and push) the same usinggit
itself. Configure.cs50.yml
per below.Optionally create another file in the same directory as
.cs50.yml
calledREADME.md
, configured per below. While technically optional, without this file your lab won’t have instructions!Optionally create in or upload to that directory (or any descendent thereof) any files you’d like to install in a student’s environment (and automatically open in the text editor’s tabs).
You can then (assuming no mistakes!) visit https://lab.cs50.io/:owner/:repo/:branch/:path
, where each of those placeholders is as above, to see your lab!
Configuration
.cs50.yml
To define a lab, it suffices to create a file called .cs50.yml
in the root (or subdirectory) of a branch in a repository that contains, minimally, a top-level lab50
key, the value of which is true
:
lab50: true
window
It turns out the above is an abbreviation of (and equivalent to)
lab50:
window:
- editor
- readme
- terminal
wherein
editor
signifies that the lab should have an embedded text editor,readme
signifies that the lab has instructions (written inREADME.md
), andterminal
signifies that the lab should have an embedded terminal window.
A value of terminal
(implicit or explicit) is required.
Also available as values for window
are
browser
, which signifies that the lab should have an embedded browser, andx
, which signifies that the lab should have an embedded X window,
but those two values are mutually exclusive.
It’s worth noting that a lab without readme
is functionally similar to CS50 Sandbox. Whereas sandboxes are intended to be temporary, labs are persistent: if a student logs into a lab and makes changes, those changes will persist indefinitely (unless the student resets the lab).
files
To install files in students’ environments (e.g., foo.c
and foo.h
), add a key below lab50
called files
(as a sibling of window
, if explicitly present):
lab50:
files:
- !include foo.c
- !include foo.h
That !include
is a (confusing) feature of YAML; it indeed means “include,” not “don’t include,” as a programmer might otherwise assume.
If those files exist (in the same directory as .cs50.yml
), they will be copied into students’ environments and opened automatically (if recognized as text files). If those files don’t exist, they will be created as empty (and opened).
Files (e.g., bar.c
and bar.h
) can also be in subdirectories (of whatever directory .cs50.yml
is in):
lab50:
files:
- !include foo/bar.c
- !include foo/bar.h
Alternatively, you can specify subdirectories:
lab50:
files:
- !include foo/
Globbing is also supported, but asterisks have special meaning in YAML, so take care to quote any strings that have wildcards:
lab50:
files:
- !include "foo/*.c"
- !include "foo/*.h"
You can also exclude files, as with:
lab50:
files:
- !exclude "*"
- !include "foo.*"
The value of files
is an ordered list, top to bottom, so the above means that all files are excluded by default but foo.*
is then included, thereby overriding their exclusion.
cmd
To specify a command to be run in the sandbox’s terminal window (e.g., python
), add a key below lab50
called cmd
:
lab50:
cmd: python
The (implicit) default is:
lab50:
cmd: bash
README.md
A lab’s instructions should be written in README.md
(which must be in the same directory as .cs50.yml
), using
GitHub-flavored Markdown. Via CS50-specific “tags” can you add interactive features to those instructions. If present, each should appear on a line of its own but might very work in other contexts too (e.g., in ordered or unordered lists).
Your Markdown can also contain, if need, raw HTML, but not these tags.
Your Markdown can also contain emoji.
next
To paginate a lab’s instructions, inserting a Next button and hiding, until clicked, everything below it, you can use this tag:
{% next %}
You can override the button’s label with a quoted string:
{% next "Step 2" %}
spoiler
To provide students with a spoiler, code or information they should only by clicking a Spoiler button, you can use these tags:
{% spoiler %}
The Answer to the Great Question...
Of Life, the Universe and Everything...
Is...
Forty-two.
{% endspoiler %}
You can override the button’s label with a quoted string. Accordingly, via
{% spoiler "Hint" %}
You're really not going to like it.
{% endspoiler %}
could you provide students with a hint. And via
{% spoiler "Solution" %}
Forty-two.
{% endspoiler %}
could you provide students with a solution.
video
To embed a YouTube video (responsively) in a lab’s instructions, you can use this tag, wherein the URL can be any URL of a video on YouTube:
{% video https://www.youtube.com/watch?v=oHg5SJYRHA0 %}
Acknowledgements
Special thanks to CS50’s friends at Google and Pluralsight for their support of this app!