diff --git a/README.md b/README.md
index 618fc9577..29a917149 100644
--- a/README.md
+++ b/README.md
@@ -91,3 +91,15 @@ For each module you import, add a `replace` directive to your `go.mod` file - if
## To locally develop your site
Check [org-cyf/README.md](/org-cyf/README.md) on how to set up your local environment. Once that is done you can `cd` into the site you wish to develop, and run `npm run start:dev` to get a live preview.
+
+## Shortcodes
+
+### `next-class-day-plan`
+
+The `next-class-day-plan` shortcode pulls sprint pages from the existing `syllabus`/`module` menu hierarchy.
+
+Example:
+
+```
+{{< next-class-day-plan >}}
+```
diff --git a/common-theme/layouts/shortcodes/next-class-day-plan.html b/common-theme/layouts/shortcodes/next-class-day-plan.html
new file mode 100644
index 000000000..6cb55f46a
--- /dev/null
+++ b/common-theme/layouts/shortcodes/next-class-day-plan.html
@@ -0,0 +1,41 @@
+{{/* Compute link to next class day plan */}}
+{{ $weekdays := dict "Sunday" 0 "Monday" 1 "Tuesday" 2 "Wednesday" 3 "Thursday" 4 "Friday" 5 "Saturday" 6 }}
+
+{{/* Resolve base time: prefer .Page.Date (shortcode context), else .Date, else now */}}
+{{ $now := now }}
+{{ with .Page }}
+ {{ with .Date }}
+ {{ $now = . }}
+ {{ end }}
+{{ else }}
+ {{ with .Date }}
+ {{ $now = . }}
+ {{ end }}
+{{ end }}
+
+{{ $todayIdx := index $weekdays ($now.Format "Monday") }}
+{{ $daysUntilSat := mod (add (sub 6 $todayIdx) 7) 7 | int }}
+{{ $nextClass := $now.AddDate 0 0 $daysUntilSat }}
+
+{{ $year := int ($nextClass.Format "2006") }}
+{{ $month := int ($nextClass.Format "1") }}
+{{ $quarterMonth := add (mul (div (sub $month 1) 3) 3) 1 }}
+{{ $start := time (printf "%04d-%02d-01" $year $quarterMonth) }}
+{{ $startIdx := index $weekdays ($start.Format "Monday") }}
+{{ $daysToSat := mod (add (sub 6 $startIdx) 7) 7 | int }}
+{{ $courseStart := $start.AddDate 0 0 $daysToSat }}
+
+{{ $startUnix := $courseStart.Unix }}
+{{ $classUnix := $nextClass.Unix }}
+{{ $daysFromStart := div (sub $classUnix $startUnix) 86400 }}
+{{ $sprint := add 1 (div $daysFromStart 7) }}
+
+{{/* Gather day plan pages within the current module */}}
+{{ $module := .Page.CurrentSection }}
+{{ $dayPlans := sort (where $module.Pages "Params.menu_level" "intersect" (slice "module")) "Weight" }}
+
+{{ with index $dayPlans (sub $sprint 1) }}
+ Day plan for sprint {{ $sprint }}
+{{ else }}
+ Day plan coming soon
+{{ end }}
diff --git a/org-cyf-itp/content/_index.md b/org-cyf-itp/content/_index.md
index 5c6e10ce6..64fd13222 100644
--- a/org-cyf-itp/content/_index.md
+++ b/org-cyf-itp/content/_index.md
@@ -1,6 +1,8 @@
-+++
-title="Intro to Programming"
-menus_to_map=["start here", "course schedule", "next steps"]
-description="New? Lost? [Quickstart](how-this-works/prep/#overview)"
-emoji= "π§πΏβπ«"
-+++
++++
+title="Intro to Programming"
+menus_to_map=["start here", "course schedule", "next steps"]
+description="New? Lost? [Quickstart](how-this-works/prep/#overview)"
+emoji= "π§πΏβπ«"
++++
+
+Hereβs how you find out what to do when: {{< next-class-day-plan >}}
diff --git a/org-cyf-theme/package-lock.json b/org-cyf-theme/package-lock.json
new file mode 100644
index 000000000..f5bd26923
--- /dev/null
+++ b/org-cyf-theme/package-lock.json
@@ -0,0 +1,58 @@
+{
+ "name": "org-cyf-theme",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "org-cyf-theme",
+ "version": "1.0.0",
+ "devDependencies": {
+ "prettier": "^2.8.8",
+ "prettier-plugin-go-template": "^0.0.13"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin-prettier.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-plugin-go-template": {
+ "version": "0.0.13",
+ "resolved": "https://registry.npmjs.org/prettier-plugin-go-template/-/prettier-plugin-go-template-0.0.13.tgz",
+ "integrity": "sha512-gG/xT5kd+kCzoMaTchXvdfBdsunyRCV6G8cgdPGPd2V5JGGKXUG7SjzBKU7jaGh2RTeblcAdBb/E+S/duOAMsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ulid": "^2.3.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "prettier": "^2.0.0"
+ }
+ },
+ "node_modules/ulid": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/ulid/-/ulid-2.4.0.tgz",
+ "integrity": "sha512-fIRiVTJNcSRmXKPZtGzFQv9WRrZ3M9eoptl/teFJvjOzmpU+/K/JH6HZ8deBfb5vMEpicJcLn7JmvdknlMq7Zg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "ulid": "bin/cli.js"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/org-cyf-theme/package.json b/org-cyf-theme/package.json
new file mode 100644
index 000000000..650e5e8f5
--- /dev/null
+++ b/org-cyf-theme/package.json
@@ -0,0 +1,13 @@
+{
+ "name": "org-cyf-theme",
+ "version": "1.0.0",
+ "private": true,
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "fix-instructions": "echo 'Fix: pass .Date to the partial or change the partial to use .Date when available. Example partial snippet: {{ $base := time.Now }} {{ with .Date }}{{ $base = . }}{{ end }} {{ $next := $base.AddDate 0 0 7 }} Next class: {{ $next.Format \"Jan 2, 2006\" }}'"
+ },
+ "devDependencies": {
+ "prettier": "^2.8.8",
+ "prettier-plugin-go-template": "^0.0.13"
+ }
+}
\ No newline at end of file