Skip to content

Commit deee022

Browse files
committed
feat: add slides TOC, promote Exercise 4, make Ex1 profile TODO explicit
Adds a numbered section table of contents that renders before every major section divider in the deck, with the current section highlighted in Temporal green. Reworks the intro slide to lead with Tailscale outcomes rather than the AI agent. Promotes the Go agent (Exercise 4) from a take-home stretch goal to a 15-minute in-session exercise. Makes the "switch profiles to switch environments" lesson explicit in Exercise 1 by turning the profile load into a required code TODO instead of an implicit default. Adds a presenter guide for the Slidev deck so someone cloning the repo can stand it up without reading `slides/package.json`. - `slides/theme-temporal/components/WorkshopToc.vue` lists the eight workshop sections and highlights the active row in mint; `slides/theme-temporal/layouts/toc.vue` wraps it in a two-column layout over the existing perspective-grid background. Eight new `layout: toc` dividers seeded through `slides/slides.md` with the right `current` id for each section - `slides/theme-temporal/styles/layout.css` gains numbered-list styling: Temporal-green leading-zero markers, tabular-nums, indented code blocks inside list items so the numbered Exercise slides read cleanly - "What We're Building Today" becomes "What You'll Learn Today." Four outcome bullets now lead with infrastructure (Temporal server on a tailnet, one config file for local/remote/tailnet, identity based rate limits on a shared key) and treat the durable agent as the last bullet rather than the framing. Drops the "By the end of this workshop, you will be able to" preamble - Exercise 4 promoted to in-session: `README.md`, `docs/workshop-overview.md`, and the deck's Exercise 4 preview slide updated. Ex3 tightened from 25 to 15 minutes to make room, take-home language removed everywhere - Exercise 1 gets a third TODO. `worker.py` and `starter.py` now ship with a no-arg `ClientConfig.load_client_connect_config()` call plus a TODO instructing learners to pass `profile="tailnet"`. Solution files updated to match. `exercises/01_hello_tailnet/README.md` renumbered (Step 2 creates the config, Step 3 is the new profile load, Step 4 is the workflow-ID TODO, Steps 5-7 are run/verify) - `docs/slides.md` walks through installing pnpm via corepack, `pnpm install`, `pnpm dev`, presenter mode, PDF export, and theme tweaks. Linked from `docs/index.md` (sixth audience card), `mkdocs.yml` nav under "Teach the workshop", `docs/run-with-instruqt.md`, and `docs/run-without-instruqt.md` - Smaller fixes: Kartik's surname corrected from Venugopal to Bharath; Mason's deck bio updated to Senior Solutions Architect with the programmer/teacher quote and PSF/PyTexas credits; Aperture sequence diagram participant renamed VM to Your Worker in the deck and in `docs/architecture.md`; `temporal-ts-net` flags in the deck updated to match the VPS (`--max-connections 500`, `--connection-rate-limit 50`); section divider "temporal-ts-net & Go Agent" becomes "and" for the keyboard-only sweep; leftover em-dashes in `exercises/01_hello_tailnet/README.md` replaced with commas and periods
1 parent ba46a2a commit deee022

17 files changed

Lines changed: 426 additions & 103 deletions

File tree

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,8 +46,8 @@ Then start with [Exercise 1](exercises/01_hello_tailnet/README.md).
4646
|---|----------|------|-------------|
4747
| 1 | [Hello Tailnet](exercises/01_hello_tailnet/README.md) | 15 min | Run a geo-IP workflow on the shared Temporal server via Tailscale |
4848
| 2 | [Explore Tailscale](exercises/02_explore_tailscale/README.md) | 15 min | Discover your network, understand Aperture, run a Go worker over `tsnet` |
49-
| 3 | [Weather Agent](exercises/03_weather_agent/README.md) | 25 min | Build a durable AI agent with LLM calls routed through Aperture |
50-
| 4 | [Go Agent](exercises/04_go_agent/README.md) | Stretch | Same agent pattern in Go (take-home challenge) |
49+
| 3 | [Weather Agent](exercises/03_weather_agent/README.md) | 15 min | Build a durable AI agent with LLM calls routed through Aperture |
50+
| 4 | [Go Agent](exercises/04_go_agent/README.md) | 15 min | The same weather agent, in Go |
5151

5252
## Temporal Web UI
5353

docs/architecture.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ The LLM reasons through multiple steps on its own. The workshop's weather agent
8080
```mermaid
8181
sequenceDiagram
8282
autonumber
83-
participant VM as Attendee VM
83+
participant VM as Your Worker
8484
participant AP as Aperture
8585
participant OAI as OpenAI
8686
VM->>AP: POST /v1/responses<br/>(no API key needed)

docs/index.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,12 @@ If you are *attending* a session, the [GitHub README](https://github.com/tempora
4646

4747
[Infrastructure](infrastructure.md) covers the persistent VPS that runs `temporal-ts-net` and the Tailscale and Aperture pieces behind it.
4848

49+
- **I just want to run the slides**
50+
51+
---
52+
53+
[Present the slides](slides.md) covers installing pnpm, running the deck locally, presenter mode, and exporting to PDF.
54+
4955
</div>
5056

5157
## Source material

docs/run-with-instruqt.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ The Aperture endpoint the workshop points at (`http://ai`) must be reachable fro
6262
- [ ] One test workflow runs end-to-end from an Instruqt VM
6363
- [ ] Slides loaded
6464

65+
## Slides
66+
67+
The deck lives at `slides/slides.md` and runs under Slidev. See [Present the slides](slides.md) for installing pnpm, running the deck, presenter mode, and exporting to PDF.
68+
6569
## Backup plan
6670

6771
If the shared server fails mid-workshop:

docs/run-without-instruqt.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,10 @@ Pick (1) if your audience are pro devs with their own accounts. Pick (2) if you
9797
- [ ] Auth key queued up for sharing (QR code printed, or paste-ready in chat)
9898
- [ ] Slides open
9999

100+
## Slides
101+
102+
The deck lives at `slides/slides.md` and runs under Slidev. See [Present the slides](slides.md) for installing pnpm, running the deck, presenter mode, and exporting to PDF.
103+
100104
## Backup plan
101105

102106
If the shared server fails mid-workshop:

docs/slides.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Present the slides
2+
3+
The deck lives at `slides/slides.md` and runs under [Slidev](https://sli.dev). It ships with a Temporal-branded theme at `slides/theme-temporal/` (Inter typography, mint + purple palette, grid + planet backgrounds) and a custom Shiki theme for code blocks.
4+
5+
## Prerequisites
6+
7+
- Node.js 20+
8+
- `pnpm` (the lockfile in `slides/pnpm-lock.yaml` pins versions for pnpm specifically; npm will work but you will lose reproducible installs)
9+
10+
```shell
11+
# If you don't have pnpm yet:
12+
corepack enable
13+
corepack prepare pnpm@10.33.0 --activate
14+
```
15+
16+
## Install
17+
18+
```shell
19+
cd slides
20+
pnpm install
21+
```
22+
23+
This pulls in `@slidev/cli` and links the local `slidev-theme-temporal` theme from `slides/theme-temporal/`.
24+
25+
## Run the deck locally
26+
27+
```shell
28+
pnpm dev
29+
```
30+
31+
Slidev starts on `http://localhost:3030`. Useful endpoints:
32+
33+
| URL | What it is |
34+
|---|---|
35+
| `http://localhost:3030/` | The slideshow |
36+
| `http://localhost:3030/presenter/` | Presenter mode (current + next slide, speaker notes, timer) |
37+
| `http://localhost:3030/overview/` | All slides at a glance |
38+
39+
The dev server hot-reloads whenever you edit `slides.md` or anything under `theme-temporal/`.
40+
41+
## Presenting
42+
43+
Run `pnpm dev` on the presenter laptop. Open `http://localhost:3030/presenter/` on your laptop screen and `http://localhost:3030/` on the projector / shared screen. Slidev keeps them in sync. Speaker notes come from HTML comments in `slides.md` (look for the `<!-- ... -->` blocks after each slide).
44+
45+
Handy keyboard shortcuts while presenting:
46+
47+
| Key | Action |
48+
|---|---|
49+
| `space`, `right arrow`, `click` | next step (advances through v-click reveals) |
50+
| `left arrow` | previous step |
51+
| `f` | toggle fullscreen |
52+
| `o` | open overview |
53+
| `d` | toggle dark / light mode |
54+
55+
## Export to PDF
56+
57+
```shell
58+
pnpm export
59+
```
60+
61+
Produces `slides-export.pdf` in `slides/`. Needs Chromium; Slidev pulls in `playwright-chromium` automatically on first run.
62+
63+
For a PDF that shows every v-click reveal expanded (useful for handouts):
64+
65+
```shell
66+
pnpm export -- --with-clicks
67+
```
68+
69+
For PNGs per slide:
70+
71+
```shell
72+
pnpm export -- --format png
73+
```
74+
75+
## Build static HTML
76+
77+
```shell
78+
pnpm build
79+
```
80+
81+
Writes a static site to `slides/dist/`. Useful if you want to host the deck somewhere alongside the docs site, or serve it from a USB stick at a conference with sketchy wifi.
82+
83+
## Tweaking the theme
84+
85+
The theme is local, not installed from npm, so you can edit it in place and see changes instantly in the dev server:
86+
87+
| File | What to change |
88+
|---|---|
89+
| `slides/theme-temporal/styles/layout.css` | Typography, palette custom properties, heading sizes, footer style, background helpers |
90+
| `slides/theme-temporal/styles/code.css` | Code-block padding, inline-code styling |
91+
| `slides/theme-temporal/setup/temporal-dark.json` | Shiki token colors for fenced code blocks |
92+
| `slides/theme-temporal/setup/mermaid.ts` | Mermaid palette (node colors, edge colors, actor styles) |
93+
| `slides/theme-temporal/layouts/*.vue` | Per-layout structure and overrides |
94+
| `slides/theme-temporal/assets/*.webp` | Backgrounds (grid, teal planet, purple planet, rex constellation, glow) |
95+
96+
If you replace a background image, keep it WebP at ~1920 wide and ~200-300 KB for good projector quality without a slow page load. The originals are 16:9.

docs/workshop-overview.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ Every LLM call goes through Aperture, which holds the real OpenAI key and applie
3131
| Exercise 1 - Hello Tailnet | 15 min |
3232
| Exercise 2 - Explore Tailscale + Aperture | 15 min |
3333
| AI agents on Temporal (talk) | 10 min |
34-
| Exercise 3 - Weather agent | 25 min |
34+
| Exercise 3 - Weather agent | 15 min |
3535
| Rate-limit demo (everyone fires at once) | 5 min |
36-
| `temporal-ts-net` + Go agent preview | 5 min |
36+
| Exercise 4 (Go agent) + `temporal-ts-net` walk-through | 15 min |
3737
| Wrap-up + Q&A | 5 min |
3838

39-
Exercise 4 (the Go agent) is a take-home stretch goal. Files are stubbed and ready.
39+
Exercise 4 translates the weather agent to Go, reusing the same Temporal server, Aperture endpoint, and tailnet.
4040

4141
## What attendees need
4242

exercises/01_hello_tailnet/README.md

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,22 @@
11
# Exercise 1: Hello Tailnet
22

3-
Your first workflow on the shared Temporal server accessed through the Tailscale network.
3+
Your first workflow on the shared Temporal server, accessed through the Tailscale network.
44

55
## Goal
66

77
Connect your worker to the shared Temporal dev server running on the tailnet, run a simple geo-IP workflow, and see it in the Temporal Web UI.
88

99
## Background
1010

11-
A Temporal dev server is running on a remote VPS, exposed to this Tailscale network via [temporal-ts-net](https://github.com/temporal-community/temporal-ts-net). You can reach it at `temporal-dev:7233` (gRPC) and `http://temporal-dev:8233` (Web UI) — no VPN setup, no port forwarding, just Tailscale.
11+
A Temporal dev server is running on a remote VPS, exposed to this Tailscale network via [temporal-ts-net](https://github.com/temporal-community/temporal-ts-net). You can reach it at `temporal-dev:7233` (gRPC) and `http://temporal-dev:8233` (Web UI). No VPN setup, no port forwarding, just Tailscale.
1212

1313
The workflow you'll run is simple: it gets your machine's public IP address, then geolocates it. Two activities, one result.
1414

1515
### How Environment Configuration Works
1616

17-
Instead of hardcoding server addresses in your code, the Temporal SDK reads connection settings from a [TOML configuration file](https://docs.temporal.io/develop/environment-configuration). This lets you switch between environments (local dev, tailnet, cloud) without changing any code — just switch profiles.
17+
Instead of hardcoding server addresses in your code, the Temporal SDK reads connection settings from a [TOML configuration file](https://docs.temporal.io/develop/environment-configuration). This lets you switch between environments (local dev, tailnet, cloud) without changing any code. Just switch profiles.
1818

19-
The code already uses `ClientConfig.load_client_connect_config()` to load the active profile. Your job is to create the config file and tell it about the tailnet server.
19+
Your job is to create the config file, then point the worker and starter at the `tailnet` profile so they connect to the shared server.
2020

2121
## Instructions
2222

@@ -28,9 +28,9 @@ From the repository root:
2828
uv run scripts/verify_setup.py
2929
```
3030

31-
All dependency checks should pass. The Temporal connectivity check will fail that's expected, you haven't configured the connection yet.
31+
All dependency checks should pass. The Temporal connectivity check will fail, that's expected, you haven't configured the connection yet.
3232

33-
### Step 2: Complete TODO 1 Create the Temporal config file
33+
### Step 2: Complete TODO 1 - Create the Temporal config file
3434

3535
Create the file `~/.config/temporalio/temporal.toml` (you can copy the template from the repo root):
3636

@@ -47,23 +47,23 @@ address = "temporal-dev:7233"
4747
namespace = "default"
4848
```
4949

50-
Then make sure your `.env` file sets the active profile:
50+
### Step 3: Complete TODO 2 - Load the tailnet profile
5151

52-
```bash
53-
TEMPORAL_PROFILE=tailnet
54-
```
52+
Open `practice/worker.py` and `practice/starter.py`. Each one calls `ClientConfig.load_client_connect_config()` with no arguments, which would load the `default` profile (localhost). Change both calls to load the `tailnet` profile:
5553

56-
The worker and starter code use `ClientConfig.load_client_connect_config()` which automatically reads this profile. No code changes needed for the connection — just the config file.
54+
```python
55+
config = ClientConfig.load_client_connect_config(profile="tailnet")
56+
```
5757

58-
### Step 3: Complete TODO 2 — Add your name to the workflow ID
58+
### Step 4: Complete TODO 3 - Add your name to the workflow ID
5959

60-
Open `practice/starter.py`. Find the TODO (~line 31) and add your `USER_ID` to the workflow ID so you can find it in the shared Temporal UI:
60+
Still in `practice/starter.py`. Find the TODO near the `execute_workflow` call and add your `USER_ID` to the workflow ID so you can find it in the shared Temporal UI:
6161

6262
```python
6363
id=f"{USER_ID}-geo-ip-{uuid.uuid4()}",
6464
```
6565

66-
### Step 4: Start the worker
66+
### Step 5: Start the worker
6767

6868
In one terminal:
6969

@@ -74,7 +74,7 @@ uv run worker.py
7474

7575
You should see: `Connecting to Temporal at temporal-dev:7233` followed by `Starting worker on task queue: <your-user-id>-hello-tailnet`
7676

77-
### Step 5: Run the workflow
77+
### Step 6: Run the workflow
7878

7979
In a second terminal:
8080

@@ -85,15 +85,15 @@ uv run starter.py
8585

8686
You should see your public IP address and location printed.
8787

88-
### Step 6: Open the Temporal Web UI
88+
### Step 7: Open the Temporal Web UI
8989

9090
Open your browser and go to:
9191

9292
```
9393
http://temporal-dev:8233
9494
```
9595

96-
Find your workflow by searching for your user ID. Click into it to see the execution history — both activities (get_ip, get_location_info) should show as completed.
96+
Find your workflow by searching for your user ID. Click into it to see the execution history. Both activities (get_ip, get_location_info) should show as completed.
9797

9898
You're now running workflows on a shared Temporal server, accessible only through your Tailscale network. The same config file works for the worker, the starter, and the Temporal CLI:
9999

exercises/01_hello_tailnet/practice/starter.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616

1717

1818
async def main() -> None:
19+
# TODO: Load the "tailnet" profile from ~/.config/temporalio/temporal.toml
20+
# so this connects to the shared Temporal server instead of localhost.
21+
# Pass profile="tailnet" to load_client_connect_config().
1922
config = ClientConfig.load_client_connect_config()
2023
client = await Client.connect(**config)
2124

exercises/01_hello_tailnet/practice/worker.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717

1818

1919
async def main() -> None:
20+
# TODO: Load the "tailnet" profile from ~/.config/temporalio/temporal.toml
21+
# so this connects to the shared Temporal server instead of localhost.
22+
# Pass profile="tailnet" to load_client_connect_config().
2023
config = ClientConfig.load_client_connect_config()
2124
logging.info(f"Connecting to Temporal at {config.get('target_host')}")
2225
client = await Client.connect(**config)

0 commit comments

Comments
 (0)