Skip to content

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

Open
nadvolod wants to merge 3 commits into
mainfrom
slides-deck
Open

feat(slides): Slidev deck for the Kotlin Nexus workshop#11
nadvolod wants to merge 3 commits into
mainfrom
slides-deck

Conversation

@nadvolod

Copy link
Copy Markdown
Collaborator

A Slidev deck for the 90-minute Kotlin Nexus workshop, interleaved with the five
challenges of the nexus-kotlin-decouple-monolith Instruqt track (merged in #9).

Only kotlin/slides/. The design and plan behind it are #8.

Approach

Interleaved, not front-loaded. Slide segments between challenges rather than a
lecture followed by a lab. ~35 speaking minutes against the track's 40-minute lab
block, leaving ~15 for Q&A.

Question-first spine. Each segment opens with the framing question already
written in that challenge's Instruqt notes, so the notes and the slides reinforce
rather than duplicate.

A concept block in Segment 0. One definition-plus-code slide per Nexus concept —
Service, Operation, Endpoint, Caller, Handler, sync vs async — each showing real
Kotlin from the solution tree, taught before anyone opens the editor. Segments 2
through 4 shrink correspondingly: they become recall, not first exposure.

Registry is deliberately absent. 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.

kotlin/slides/layouts/code-stack.vue is a project-local layout so a theme
update cannot clobber it. Code on top, definition below, both panes auto-shrinking
so no slide scrolls or clips. Three CSS traps are documented in comments there,
each found by measuring the live DOM rather than reasoning about it.

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.

Still to write

Segments 1 through 6 are placeholder files. Segment 0 is drafted apart from the
sync-vs-async definition.

🤖 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)
```
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