Skip to content

Interactive examples in the docs - #193

Open
LuLaValva wants to merge 3 commits into
mainfrom
claude/marko-interactive-docs-qy0u6o
Open

Interactive examples in the docs#193
LuLaValva wants to merge 3 commits into
mainfrom
claude/marko-interactive-docs-qy0u6o

Conversation

@LuLaValva

@LuLaValva LuLaValva commented Jul 24, 2026

Copy link
Copy Markdown
Member

Two takes on interactive docs, both authored as plain markdown that reads normally on GitHub: examples in regular doc pages can opt into running live in place (see the Components and Reactivity tutorial), and a new guided flow at /learn pairs each lesson with a persistent editor and preview. Try both in the preview deployment.

Marko code fences tagged with a playground modifier now render as
runnable, editable examples directly in the docs, with consecutive
fences forming multi-file examples. Demonstrated throughout the
Components and Reactivity tutorial.
@changeset-bot

changeset-bot Bot commented Jul 24, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 2109050

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@github-actions

github-actions Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

PR Preview Deployed

Your changes are live at markojs.com/previews/pr-193.

commit 2109050

@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d5717d15-b9d3-45a7-a0b3-fa42a40f4379

📥 Commits

Reviewing files that changed from the base of the PR and between e12c637 and 2109050.

📒 Files selected for processing (2)
  • .gitignore
  • .marko-run/routes.d.ts

Walkthrough

The Markdown pipeline now compiles learn pages, manifests, checkpoints, and grouped marko playground fences. New learn-route components provide lesson navigation, workspace loading, checkpoints, live editing, debounced previews, error/loading states, and external playground links. New lessons and tutorial examples use playground rendering, lint configuration covers learn content, and a suspected client-only <let-debounce> issue is documented.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: adding interactive documentation examples.
Description check ✅ Passed The description is clearly related to the new live docs examples and the /learn flow.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/marko-interactive-docs-qy0u6o

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@agent-feedback/bugs.md`:
- Line 5: Shorten the bugs.md heading for the let-debounce return-value issue to
a concise 1–3 word title, such as “Return Binding,” while preserving the
detailed failure description in the body.

In `@src/tags/app-playground/app-playground.marko`:
- Around line 34-44: Update the dynamic import failure handler in app-playground
to store the rejected error in component state instead of only clearing loading.
Render that error through an alert or retry affordance in the playground UI,
while preserving the successful Live assignment and loading-state behavior.

In `@src/tags/app-playground/app-playground.style.scss`:
- Around line 32-35: Update both svg rules in
src/tags/app-playground/app-playground.style.scss at lines 32-35 and 55-58,
changing the fill value from currentColor to currentcolor to satisfy the
configured Stylelint value-keyword-case rule.

In `@src/tags/app-playground/tags/open-in-playground.marko`:
- Around line 8-18: Update the hash-generation logic in the script block to
clear or disable the playground link while compression is pending, preventing
navigation with an empty hash. Add a cancellation token or revision counter so
each compress completion only updates hash if it still corresponds to the latest
input.files, and invalidate prior work when the signal aborts or a new hash
starts.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2c56b038-486a-4bde-a1c4-1616c4c34432

📥 Commits

Reviewing files that changed from the base of the PR and between b8b4ad1 and 8ce7435.

📒 Files selected for processing (9)
  • agent-feedback/bugs.md
  • cspell.json
  • docs/tutorial/components-and-reactivity.md
  • src/tags/app-playground/app-playground.marko
  • src/tags/app-playground/app-playground.style.scss
  • src/tags/app-playground/tags/embed-result.marko
  • src/tags/app-playground/tags/open-in-playground.marko
  • src/tags/app-playground/tags/playground-live.marko
  • src/util/markodown.ts

Comment thread agent-feedback/bugs.md

Out-of-scope defects noticed while working on something else. Format and rules: [README.md](README.md).

## `<let-debounce>` return value never flows when client-rendered without server markup

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Shorten the heading.

Use a 1-3 word heading, such as ## Return Binding; retain the detailed failure description in the body. As per coding guidelines, headings must be 1-3 words maximum.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@agent-feedback/bugs.md` at line 5, Shorten the bugs.md heading for the
let-debounce return-value issue to a concise 1–3 word title, such as “Return
Binding,” while preserving the detailed failure description in the body.

Source: Coding guidelines

Comment on lines +34 to +44
loading = true;
import("./tags/playground-live.marko").then(
(live) => {
deactivate?.();
deactivate = () => (Live = null);
Live = live.default;
loading = false;
},
() => {
loading = false;
},

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.

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Surface live-editor load failures.

A rejected dynamic import only clears loading; the failed action has no feedback. Store an error and render an alert or retry affordance.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tags/app-playground/app-playground.marko` around lines 34 - 44, Update
the dynamic import failure handler in app-playground to store the rejected error
in component state instead of only clearing loading. Render that error through
an alert or retry affordance in the playground UI, while preserving the
successful Live assignment and loading-state behavior.

Comment on lines +32 to +35
svg {
height: 0.9em;
fill: currentColor;
}

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Resolve the Stylelint keyword-case errors.

currentColor is rejected by the configured value-keyword-case rule, so lint will fail.

  • src/tags/app-playground/app-playground.style.scss#L32-L35: change fill: currentColor to fill: currentcolor.
  • src/tags/app-playground/app-playground.style.scss#L55-L58: change fill: currentColor to fill: currentcolor.
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 34-34: Expected "currentColor" to be "currentcolor" (value-keyword-case)

(value-keyword-case)

📍 Affects 1 file
  • src/tags/app-playground/app-playground.style.scss#L32-L35 (this comment)
  • src/tags/app-playground/app-playground.style.scss#L55-L58
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tags/app-playground/app-playground.style.scss` around lines 32 - 35,
Update both svg rules in src/tags/app-playground/app-playground.style.scss at
lines 32-35 and 55-58, changing the fill value from currentColor to currentcolor
to satisfy the configured Stylelint value-keyword-case rule.

Source: Linters/SAST tools

Comment on lines +8 to +18
let/hash=""
script --
const timeout = setTimeout(() => {
compress(JSON.stringify(input.files)).then((h) => (hash = h));
}, 500);
$signal.onabort = () => clearTimeout(timeout);

a.playground-embed-open
,href=`${import.meta.env.BASE_URL}playground${hash && `#${hash}`}`
,target="_blank"
,rel="noopener"

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Prevent empty and stale playground hashes.

Before hashing completes, the link opens a blank workspace. Also, an older compress() promise can resolve after newer files and overwrite hash. Clear or disable the link while hashing and guard completions with a cancellation token or revision counter.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tags/app-playground/tags/open-in-playground.marko` around lines 8 - 18,
Update the hash-generation logic in the script block to clear or disable the
playground link while compression is pending, preventing navigation with an
empty hash. Add a cancellation token or revision counter so each compress
completion only updates hash if it still corresponds to the latest input.files,
and invalidate prior work when the signal aborts or a new hash starts.

Lessons under learn/ are plain markdown ordered by filename prefix.
They render at /learn with prose on the left and a persistent
editor and preview on the right; playground fences become checkpoints
that load their files into the shared workspace, with the first group
loading automatically.

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@learn/1-basics/1-templates.md`:
- Line 1: Add a `> [!TLDR]` callout containing 2–4 concise lesson-summary
bullets before the introduction in learn/1-basics/1-templates.md (line 1),
learn/1-basics/2-dynamic-content.md (line 1), learn/1-basics/3-state.md (line
1), and learn/1-basics/4-components.md (line 1); keep each summary specific to
its lesson.

In `@learn/1-basics/4-components.md`:
- Around line 21-25: Update the rating button markup in the component to add a
dynamic aria-label describing its rating value and an aria-pressed attribute
reflecting whether i is selected based on input.value. Preserve the existing
star rendering and valueChange behavior.

In `@src/tags/learn-checkpoint/learn-checkpoint.style.scss`:
- Around line 45-48: Update the SVG rules in
src/tags/learn-checkpoint/learn-checkpoint.style.scss lines 45-48 and
src/routes/learn/+layout.style.scss lines 50-53 to use the lowercase fill
keyword currentcolor instead of currentColor, resolving the configured Stylelint
value-keyword-case errors.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 05aea3ae-723c-4832-ae1c-82fa1f600a19

📥 Commits

Reviewing files that changed from the base of the PR and between 8ce7435 and e12c637.

📒 Files selected for processing (15)
  • cspell.json
  • learn/1-basics/1-templates.md
  • learn/1-basics/2-dynamic-content.md
  • learn/1-basics/3-state.md
  • learn/1-basics/4-components.md
  • package.json
  • src/routes/learn/+handler.ts
  • src/routes/learn/+layout.marko
  • src/routes/learn/+layout.style.scss
  • src/tags/app-playground/app-playground.style.scss
  • src/tags/app-playground/tags/embed-result.style.scss
  • src/tags/learn-checkpoint/learn-checkpoint.marko
  • src/tags/learn-checkpoint/learn-checkpoint.style.scss
  • src/util/learn-files.ts
  • src/util/markodown.ts

@@ -0,0 +1,36 @@
# Templates Are HTML

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.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Add TLDR callouts to all new lessons.

Each lesson begins without the required > [!TLDR] block.

  • learn/1-basics/1-templates.md#L1-L1: add a 2-4 bullet TLDR before the introduction.
  • learn/1-basics/2-dynamic-content.md#L1-L1: add a 2-4 bullet TLDR before the introduction.
  • learn/1-basics/3-state.md#L1-L1: add a 2-4 bullet TLDR before the introduction.
  • learn/1-basics/4-components.md#L1-L1: add a 2-4 bullet TLDR before the introduction.

As per coding guidelines, tutorial documents include a TLDR section. Based on learnings, Markdown files use the > [!TLDR] format.

📍 Affects 4 files
  • learn/1-basics/1-templates.md#L1-L1 (this comment)
  • learn/1-basics/2-dynamic-content.md#L1-L1
  • learn/1-basics/3-state.md#L1-L1
  • learn/1-basics/4-components.md#L1-L1
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@learn/1-basics/1-templates.md` at line 1, Add a `> [!TLDR]` callout
containing 2–4 concise lesson-summary bullets before the introduction in
learn/1-basics/1-templates.md (line 1), learn/1-basics/2-dynamic-content.md
(line 1), learn/1-basics/3-state.md (line 1), and learn/1-basics/4-components.md
(line 1); keep each summary specific to its lesson.

Sources: Coding guidelines, Learnings

Comment on lines +21 to +25
<button onClick() {
input.valueChange?.(i);
}>
${i <= input.value ? "★" : "☆"}
</button>

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.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Make the rating controls accessible.

Each button exposes only a star glyph, so assistive technology receives neither an accessible name nor the selected state. Add a dynamic aria-label and aria-pressed.

Suggested fix
   <for|i| from=1 to=5>
-    <button onClick() {
+    <button
+      aria-label=`Set rating to ${i} out of 5`
+      aria-pressed=(i <= input.value)
+      onClick() {
       input.valueChange?.(i);
     }>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<button onClick() {
input.valueChange?.(i);
}>
${i <= input.value ? "★" : "☆"}
</button>
<button
aria-label=`Set rating to ${i} out of 5`
aria-pressed=(i <= input.value)
onClick() {
input.valueChange?.(i);
}>
${i <= input.value ? "★" : "☆"}
</button>
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@learn/1-basics/4-components.md` around lines 21 - 25, Update the rating
button markup in the component to add a dynamic aria-label describing its rating
value and an aria-pressed attribute reflecting whether i is selected based on
input.value. Preserve the existing star rendering and valueChange behavior.

Comment on lines +45 to +48
svg {
height: 0.9em;
fill: currentColor;
}

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

Resolve the Stylelint keyword-case errors.

The configured value-keyword-case rule rejects currentColor, causing lint to fail.

  • src/tags/learn-checkpoint/learn-checkpoint.style.scss#L45-L48: change fill: currentColor to fill: currentcolor.
  • src/routes/learn/+layout.style.scss#L50-L53: change fill: currentColor to fill: currentcolor.
Proposed fix
- fill: currentColor;
+ fill: currentcolor;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
svg {
height: 0.9em;
fill: currentColor;
}
svg {
height: 0.9em;
fill: currentcolor;
}
🧰 Tools
🪛 Stylelint (17.14.0)

[error] 47-47: Expected "currentColor" to be "currentcolor" (value-keyword-case)

(value-keyword-case)

📍 Affects 2 files
  • src/tags/learn-checkpoint/learn-checkpoint.style.scss#L45-L48 (this comment)
  • src/routes/learn/+layout.style.scss#L50-L53
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/tags/learn-checkpoint/learn-checkpoint.style.scss` around lines 45 - 48,
Update the SVG rules in src/tags/learn-checkpoint/learn-checkpoint.style.scss
lines 45-48 and src/routes/learn/+layout.style.scss lines 50-53 to use the
lowercase fill keyword currentcolor instead of currentColor, resolving the
configured Stylelint value-keyword-case errors.

Source: Linters/SAST tools

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.

1 participant