Skip to content

feat(slides): Slidev deck for the Kotlin Nexus workshop - #11

Merged
nadvolod merged 9 commits into
mainfrom
slides-deck
Aug 18, 2026
Merged

feat(slides): Slidev deck for the Kotlin Nexus workshop#11
nadvolod merged 9 commits into
mainfrom
slides-deck

Conversation

@nadvolod

@nadvolod nadvolod commented Aug 14, 2026

Copy link
Copy Markdown
Collaborator

A Slidev deck for the Kotlin Nexus workshop, opening the hands-on lab in the
nexus-kotlin-decouple-monolith Instruqt track (merged in #9).

Only kotlin/slides/. The original design and plan are #8 — see the note at the
bottom, because the deck has moved away from it.

The deck, 19 slides

# Slide
1 Cover
2 Speaker intro, with the dog revealed on a click
3–11 Nexus overview: what teams reach for today and why it leaks
12 Open the labt.mp/nexus-kotlin, video left, CTA right
13 Nexus Fundamentals section divider
14–19 Service, Operation, Endpoint, Caller, Handler, sync vs async

The lab opens before the vocabulary, deliberately: nothing on slide 12 needs a
Nexus term, so attendees can be waiting on the sandbox while the concepts are
still being introduced. Each concept then gets one slide pairing a definition
with real Kotlin from the solution tree.

Registry is deliberately absent from the concept block. The lab names it once in
challenge 2's notes and no challenge ever touches it.

What reviewers may want to weigh in on

The theme is vendored at kotlin/slides/theme/ (~1.1MB, 29 layouts) rather
than installed as a dependency, and it is most of this PR's line count. pnpm add github:temporalio/slidev-theme-temporal installs fine and then fails the build:
pnpm names the store directory for a git dependency with a #<commit> suffix, and
Vite's CSS url() resolver treats # as a fragment separator, so the theme's five
background images resolve to a truncated path. Vendoring is Option 2 in the theme's
own README and what the Replay workshop deck does.

Slides 3–11 are rendered images, not rebuilt slides. They come from pages 4–12
of the internal Temporal Nexus Overview 2026 deck. Their diagrams are intricate
enough that redrawing them in HTML would lose more than it gained, and they are
already on brand for a dark deck. Rendered at 160 dpi and converted to WebP: 11MB
of PNG became 516KB for all nine. Consequence to know about: the text is not
editable or searchable, and re-syncing means re-rendering from the source deck.

Two project-local layouts in kotlin/slides/layouts/, kept out of the vendored
theme so a theme update cannot clobber them:

  • code-stack — code above, definition below, both panes auto-shrinking so no
    slide scrolls or clips. Three CSS traps are documented in comments, each found
    by measuring the live DOM rather than reasoning about it.
  • full-image — one image, no footer. The overview pages carry their own page
    number and logo, so the theme's footer doubled up on both.

Verification

node scripts/probe-fit.mjs

Drives the dev server with Playwright and reports the settled font size and
overflow for every code slide. It caught two clipping bugs that eyeballing missed.
All six currently report zero overflow.

prettier-plugin-slidev is pinned and configured. Without it a format-on-save
pass silently destroys every per-slide frontmatter block: in Markdown a line of
text followed by --- is a setext H2, which is exactly what Slidev frontmatter
looks like.

Still open

Two definitions are unwritten — Handler and sync vs async still carry the
scaffolding note rather than prose.

segments/00-parked.md holds two superseded slides (the 3 AM failure, and a
before-and-after architecture diagram). slides.md does not import it, so nothing
renders from it.

This deck no longer matches the plan in #8. That plan describes six interleaved
segments, one per challenge; those placeholder files were deleted and the deck is
now a single continuous run into the lab. #8 is worth reading as the record of the
original design, but it should not be treated as a description of this deck.

🤖 Generated with Claude Code

nadvolod and others added 3 commits August 14, 2026 10:15
Slidev 52. slides.md holds headmatter plus src: imports only; each segment is
its own file so one can be rewritten or cut without touching its neighbours.

The theme is vendored at slides/theme rather than installed as a dependency.
`pnpm add github:temporalio/slidev-theme-temporal` installs fine and then fails
the build: pnpm names the store directory for a git dep with a #<commit> suffix,
and Vite's CSS url() resolver treats # as a fragment separator, so the theme's
five background images resolve to a truncated path and error with ENOENT.
Vendoring is Option 2 in the theme's own README and what the Replay workshop
deck does.

Also pins prettier-plugin-slidev. Without it a format-on-save pass rewrites
every per-slide frontmatter block: in Markdown a line of text followed by ---
is a setext H2, which is exactly what Slidev frontmatter looks like, so
`layout: default` between two --- lines becomes the heading "## layout: default"
and the slide loses its layout entirely.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
A project-local layout rather than an edit to the vendored theme, so pulling a
newer theme cannot clobber it. Code across the top, definition across the full
width below.

The definition takes only the height it needs and the code claims the slack, so
a one-line definition hands its space to the code instead of reserving an empty
third of the slide. Both panes then measure themselves after render and step
their font size down until the content fits, watching for resizes and content
changes, so no slide scrolls or clips.

Three CSS traps are documented in comments, each found by measuring the live DOM
rather than reasoning:

- `title` is reserved by Slidev for slide metadata and never reaches a layout as
  a prop, so the heading prop is `heading`.
- minmax(0, auto) collapses the prose track: with a zero floor its min-content
  contribution is zero and the greedy 1fr code row eats the space.
- A percentage max-height on a grid item resolves against its own track, so
  capping an auto-sized track at 40% yields 40% of its own content. fit-content()
  resolves against the grid container, which is what we want.

scripts/probe-fit.mjs drives the dev server with Playwright and reports the
settled font size and overflow for every code slide. It caught two clipping bugs
that eyeballing missed, and it walks the deck rather than hardcoding slide
numbers so it survives slides being added or removed.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Three opener slides, a section divider, then one definition-plus-code slide per
Nexus concept: Service, Operation, Endpoint, Caller, Handler, sync vs async.
Every concept is taught with real Kotlin from the solution tree before anyone
opens the editor, which lets segments 2 through 4 shrink to recall rather than
first exposure.

Registry is deliberately absent from the concept block. The lab names it once in
challenge 2's notes and no challenge ever touches it.

The architecture diagram on the before-and-after slide comes from
temporalio/temporal-learning -> docs/tutorials/nexus/ui/architecture-overview.svg,
rendered in the Overview of the Java sync tutorial. It labels exactly the pieces
this workshop builds. Bound as :src rather than src: Vite statically analyses a
literal src in the compiled Vue template and tries to resolve it as a module,
which fails for a public/ path inside Slidev's virtual modules.

Presenter notes on each slide carry the source file:line for the snippet and,
where a definition is still unwritten, what it needs to establish.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a Slidev-based slide deck for the Kotlin Nexus workshop and vendors an expanded slidev-theme-temporal theme (layouts/components/styles + example decks) to support the workshop’s design and pacing goals.

Changes:

  • Introduces a full Slidev deck under kotlin/slides/, segmented into workshop sections and backed by a Playwright-based “fit probe” script for code-slide overflow checks.
  • Vendors and extends the Temporal Slidev theme under kotlin/slides/theme/ (palette + Shiki + Mermaid + 29 layouts + reusable components + example decks + scaffolding script).
  • Adds a project-local code-stack layout to support “code + definition” slides with auto-fitting panes.

Reviewed changes

Copilot reviewed 70 out of 77 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
kotlin/slides/theme/styles/layout.css Global palette, typography, layout primitives, and background helpers for the vendored theme
kotlin/slides/theme/styles/index.ts Theme styles entrypoint wiring layout + code CSS
kotlin/slides/theme/styles/code.css Code block typography and panel styling
kotlin/slides/theme/spec.md Theme parity/audit spec vs 2026 PPT template and build plan/reference
kotlin/slides/theme/setup/temporal.json Shiki token theme JSON for “temporal”
kotlin/slides/theme/setup/shiki.ts Registers Shiki theme for Slidev
kotlin/slides/theme/setup/mermaid.ts Mermaid themeVariables aligned with Temporal palette
kotlin/slides/theme/scripts/new-deck.sh Script to scaffold a new deck wired to the vendored theme
kotlin/slides/theme/README.md Theme documentation (usage, layouts, examples, brand rules)
kotlin/slides/theme/package.json Theme package metadata + Slidev defaults
kotlin/slides/theme/LICENSE Theme license
kotlin/slides/theme/layouts/two-cols.vue Two-column layout with footer + grid background
kotlin/slides/theme/layouts/two-cols-header.vue Two-column layout with shared title + optional eyebrows
kotlin/slides/theme/layouts/toc.vue Agenda/TOC layout using configurable TOC component
kotlin/slides/theme/layouts/timeline.vue Timeline layout using TimelineRail component
kotlin/slides/theme/layouts/success-story.vue Customer success story layout with logo slot + challenges/solution columns
kotlin/slides/theme/layouts/subsection.vue Sub-section divider layout with eyebrow label
kotlin/slides/theme/layouts/section.vue Section divider layout
kotlin/slides/theme/layouts/release-stages.vue 3-stage release explainer layout
kotlin/slides/theme/layouts/quote.vue Quote card layout with avatar + attribution
kotlin/slides/theme/layouts/qa.vue Minimal Q&A divider layout
kotlin/slides/theme/layouts/profile.vue Profile card layout with avatar + attribution block
kotlin/slides/theme/layouts/model-diagram.vue Model diagram layout with asset-pending placeholder slot
kotlin/slides/theme/layouts/image-right.vue Text-left, image-right layout
kotlin/slides/theme/layouts/image-left.vue Image-left, text-right layout
kotlin/slides/theme/layouts/feature-grid.vue N-column feature grid layout driven by items prop
kotlin/slides/theme/layouts/feature-card.vue Feature card layout with release-stage chip + 3 body slots
kotlin/slides/theme/layouts/eyebrow-hero.vue Eyebrow + large heading hero layout
kotlin/slides/theme/layouts/exercise.vue Workshop exercise timer layout
kotlin/slides/theme/layouts/end.vue Closing slide layout with logo + brand rule enforcement
kotlin/slides/theme/layouts/default.vue Default content layout with footer pinned via flex
kotlin/slides/theme/layouts/cta-icons.vue CTA icon grid layout (asset-pending icons)
kotlin/slides/theme/layouts/cta-banner.vue Single CTA banner layout
kotlin/slides/theme/layouts/cover.vue Cover layout using BackgroundLayer variants + logo brand rule
kotlin/slides/theme/layouts/comparison.vue Two-card comparison layout with checkmark feature lists
kotlin/slides/theme/layouts/code-explain.vue Code + prose side-by-side layout
kotlin/slides/theme/layouts/checklist.vue Checklist grid layout with checkmarks
kotlin/slides/theme/layouts/chart.vue Chart slot + caption layout
kotlin/slides/theme/layouts/big-stat.vue Big stat hero layout with optional ribbon slot
kotlin/slides/theme/layouts/architecture.vue Architecture diagram layout with before/after variant + placeholder slot
kotlin/slides/theme/justfile Dev/build/export recipes for running theme example decks
kotlin/slides/theme/example/workshop.md Example workshop deck demonstrating TOC + exercise layout
kotlin/slides/theme/example/slides.md Full reference deck exercising every layout
kotlin/slides/theme/example/README.md Documentation for running/maintaining example decks
kotlin/slides/theme/example/feature-launch.md Example mini-deck for feature launches
kotlin/slides/theme/example/customer-story.md Example mini-deck for customer stories
kotlin/slides/theme/components/WorkshopToc.vue Configurable TOC driven by themeConfig.toc
kotlin/slides/theme/components/TimelineRail.vue Timeline rail primitive used by timeline layout
kotlin/slides/theme/components/TemporalLogo.vue Inline SVG Temporal mark with brand rule reminder
kotlin/slides/theme/components/TemporalFooter.vue Footer component (deck title + page indicator)
kotlin/slides/theme/components/ReleaseStageChip.vue Pill chip for release stages
kotlin/slides/theme/components/QuoteAttribution.vue Name + role attribution block
kotlin/slides/theme/components/ProfileAvatar.vue Avatar primitive with placeholder fallback
kotlin/slides/theme/components/FeatureBlock.vue Title/body block primitive
kotlin/slides/theme/components/Checkmark.vue Inline SVG checkmark primitive
kotlin/slides/theme/components/BackgroundLayer.vue Background variant → CSS class mapping wrapper
kotlin/slides/theme/CHANGELOG.md Theme changelog describing parity work and breaking changes
kotlin/slides/slides.md Main Slidev deck entry referencing segment files
kotlin/slides/segments/06-close.md Placeholder workshop segment 6
kotlin/slides/segments/05-durability.md Placeholder workshop segment 5
kotlin/slides/segments/04-caller.md Placeholder workshop segment 4
kotlin/slides/segments/03-handlers.md Placeholder workshop segment 3
kotlin/slides/segments/02-contract.md Placeholder workshop segment 2
kotlin/slides/segments/01-coupling.md Placeholder workshop segment 1
kotlin/slides/segments/00-open.md Segment 0 draft (concept slides + diagram slide)
kotlin/slides/scripts/probe-fit.mjs Playwright-driven overflow/font-size probe for code-stack slides
kotlin/slides/public/nexus-architecture.svg Animated architecture diagram asset used in slides
kotlin/slides/package.json Slides project devDependencies + Slidev scripts
kotlin/slides/layouts/code-stack.vue Project-local auto-fitting code+definition layout
kotlin/slides/.prettierrc Prettier config using prettier-plugin-slidev for deck/segments
kotlin/slides/.gitignore Slidev/build output ignore rules

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment on lines +119 to +122
# Copy the example deck, rewriting its in-repo `theme: ../` reference to
# the relative path from the new deck back to the theme repo.
sed "s|^theme: \.\./\$|theme: $rel_theme|" "$src_file" > "$target_abs/slides.md"
fi
Comment on lines +25 to +30
<template>
<div class="temporal-footer">
<span>{{ $slidev.themeConfigs?.footer ?? '' }}</span>
<span class="page">{{ pageLabel }}</span>
</div>
</template>
Comment on lines +1 to +38
<!--
ABOUTME: Inline SVG check mark used by checklist and POC layouts.
ABOUTME: Inherits color via currentColor so any layout can tint it.

Usage:
<Checkmark />
<Checkmark label="Completed" /> <!-- announces to screen readers -->
-->
<script setup lang="ts">
defineProps<{ label?: string }>()
</script>

<template>
<svg
class="checkmark"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2.5"
stroke-linecap="round"
stroke-linejoin="round"
:aria-hidden="label ? undefined : 'true'"
:aria-label="label"
:role="label ? 'img' : undefined"
>
<polyline points="4 12 10 18 20 6" />
</svg>
</template>

<style scoped>
.checkmark {
display: inline-block;
width: 1.1em;
height: 1.1em;
color: var(--temporal-green);
vertical-align: -0.15em;
}
</style>
Comment on lines +156 to +173
```kotlin {1-8|10|all}
//The Caller Workflow
public val NexusCallerWorkflowImpl implements NexusCallerWorkflow {

private val complianceService: ComplianceNexusService =
//Nexus stub: The delivery app. Use it to place orders
Workflow.newNexusServiceStub(
//The menu tells you what you can order
ComplianceNexusService::class.java,
NexusServiceOptions.newBuilder()
.setOperationOptions(/* scheduleToCloseTimeout */)
.build(),
)

// ...
//One of the menu items is checkCompliance()
val compliance = complianceService.checkCompliance(compReq)
```
nadvolod and others added 6 commits August 18, 2026 07:58
A cta-banner slide carrying t.mp/nexus-kotlin, the one URL attendees have to
type all day. Sits last in segment 0 so it can stay up while the sandbox warms.

Distinct from the per-challenge handoffs, which use the theme's exercise layout
and its countdown timer at the end of each later segment.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Drops the subheadline and rebuilds the slide as two full-height halves: the
portrait clip edge to edge on the left, eyebrow/headline/link on the right.

cta-banner could not do this -- it centres a single column -- so the slide is
inline markup using the theme's own colour variables rather than a new layout
file for one slide. object-cover crops the letterbox bars baked into the source.

The .mov is remuxed to .mp4 with -c copy: the codecs were already H.264/AAC, so
it is lossless, and Chromium's .mov support is inconsistent, which matters
because PDF export runs through Chromium. +faststart so it starts without
buffering the whole file. Bound as :src for the same reason as the SVG.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Rebuilt from slide 2 of the Agentic AI Summit 2026 deck, keeping every element:
both photos as circles, the name, the role line, the Dog Dad line, and the two
social handles with their icons, now as working links.

The photos are circles because the source shapes carry prstGeom prst="ellipse",
which is easy to miss when only the text is read out of the XML. Assets came from
ppt/media, the four images referenced by slide2.xml.rels.

The theme underlines every link with a border-bottom, which put a stray rule
under both handles, so .intro-social clears it. Mia's crop needs
object-position 50% 30%: a portrait centre-cropped to a circle cuts her ears off.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The intro slide now opens on the headshot alone and Mia appears on the first
click.

v-click alone was not enough: it fades opacity but leaves the element in flow,
so Mia's 248px stayed reserved and pushed the headshot off centre in the first
state, which read as a mistake rather than a build. Collapsing her with
display: none while hidden keeps state one centred and lets the pair re-centre
when she lands.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
New order: Nikolay's intro, the nine-page Nexus overview, the hands-on lab
slide, then the concept block. The lab slide moves ahead of the concepts
because it needs no Nexus vocabulary, so attendees can be opening the sandbox
while the terms are still being introduced.

Pages 4 to 12 of the [External] Temporal Nexus Overview Slides 2026 deck come
in as rendered images. Their diagrams -- the child-workflow and activity-wrapper
comparisons, the bespoke gateway, the Nexus lozenge -- are intricate enough that
redrawing them in HTML would lose more than it gained, and they are already on
brand for a dark deck.

Rendered at 160 dpi with PyMuPDF and converted to WebP: 11 MB of PNG became
516 KB for all nine. Each carries a per-page presenter note and its source page.

Adds a full-image layout with no footer, since these pages have their own page
number and logo baked in and the theme's footer doubled up on both. Its prop is
`image`, not `src`, because Slidev reserves `src` in frontmatter for importing
slides.

Renames "The six words" to "Nexus Fundamentals".

The 3 AM failure and the before-and-after slide move to segments/00-parked.md,
which slides.md does not import, so nothing renders from it. The overview pages
now tell that story in more detail, which makes those two redundant rather than
wrong. They are kept intact in case either is wanted back.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
All six were seven-line stubs pointing at the plan; no written content is lost.
Removes their files and their src: imports, leaving the deck at 19 slides: the
cover plus segment 0.

The interleaved per-challenge segments the plan describes are no longer part of
the deck. If they come back, the plan and its Mermaid diagram states are still
in PR #8.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@nadvolod
nadvolod merged commit 1b418dd into main Aug 18, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants