Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/hetari/creative-coding/llms.txt

Use this file to discover all available pages before exploring further.

The routing system in this playground is fully automatic. Categories, breadcrumbs, and sketch routes are all derived at runtime from src/config/sketches.ts β€” you never create route files or category index pages by hand. The entire src/pages/ directory contains exactly two files: index.vue (the root dashboard renderer) and [...all].vue (the catch-all router seam that handles every other path).

How Categories Work

Every sketch has a category field. Single-segment values like 'shader' place the sketch directly under a top-level category. Multi-segment values like 'gsap/footer' create an intermediate sub-category level automatically. The buildDashboardItems() utility reads the current URL path and computes which cards to show at each depth β€” no static category configuration exists anywhere else. Using the real entries from src/config/sketches.ts, the full dashboard hierarchy looks like this:
SKETCHES category β†’ Dashboard structure

root (/):
  πŸ“ shader    β†’ /shader
  πŸ“ images    β†’ /images
  πŸ“ gsap      β†’ /gsap

/shader:
  ✦ Learn      β†’ /shader/learn

/images:
  ✦ Swiper     β†’ /images/swiper

/gsap:
  πŸ“ footer    β†’ /gsap/footer
  πŸ“ loading   β†’ /gsap/loading

/gsap/footer:
  ✦ Ascii Hand β†’ /gsap/footer/ascii-hand

/gsap/loading:
  ✦ Reveal Loader β†’ /gsap/loading/reveal-loader
Each πŸ“ card is a category folder card β€” clicking it navigates one level deeper. Each ✦ card is a leaf sketch card β€” clicking it navigates directly to the sketch route and dynamically loads the component. No intermediate page files are created for any of these routes.

The Catch-All Router Seam

src/pages/[...all].vue is a single Vue component that handles every URL not matched by index.vue. When a navigation occurs, the component checks the path against the registry and chooses one of three rendering branches:

Leaf Sketch

getSketchByPath(route.path) returns a match β†’ dynamically imports the sketch component factory and renders the result. Shows a loading spinner during the async import and an error state if the import fails.

Category Dashboard

isCategoryPath(route.path) returns true β†’ renders <IndexPage /> (the same root dashboard component) with the current path as context, causing buildDashboardItems() to return the filtered child list for that depth.

404 Fallback

Neither condition matches β†’ renders a styled 404 page with a β€œReturn to Playground” link. This occurs when a path exists in neither the SKETCHES registry nor as a valid category prefix.
The key functions that power this decision tree are both exported from src/config/sketches.ts:
// Returns the SketchMeta entry if `path` is a registered sketch route
getSketchByPath(path: string): SketchMeta | undefined

// Returns true if `path` is a prefix that matches any sketch's category
isCategoryPath(path: string): boolean

URL Slug Formatting

The slugToLabel() function from src/utils/slug.ts converts raw URL path segments into human-readable display labels used in card headers and the dashboard page title. It handles two transformations:
  1. Strips numeric sort prefixes β€” a leading digits- prefix is removed so filesystem ordering conventions never leak into the UI (000-learn β†’ learn).
  2. Title-cases the result β€” hyphens and underscores become spaces, and each word is capitalized (my-sketch β†’ My Sketch).
// src/utils/slug.ts

export function stripSortPrefix(slug: string): string {
  return slug.replace(/^\d+-/, '')
}

export function slugToLabel(slug: string): string {
  return stripSortPrefix(slug)
    .replace(/[-_]/g, ' ')
    .replace(/\b\w/g, char => char.toUpperCase())
}
Example conversions:
SlugLabel
000-learnLearn
010-webgl-earthWebgl Earth
ascii-handAscii Hand
reveal-loaderReveal Loader
shadersShaders

The buildDashboardItems() Utility

buildDashboardItems() in src/utils/dashboard.ts is the function that builds the card list rendered on each dashboard page. Its signature is:
buildDashboardItems(
  sketches: SketchMeta[] = SKETCHES,  // defaults to the full registry
  currentPath: string = '/',          // e.g. '/', '/gsap', '/gsap/footer'
): DashboardItem[]
The function walks the full SKETCHES array for each call and applies the following logic:
  1. Compute current depth β€” split currentPath into segments and measure depth (root / = 0, /gsap = 1, /gsap/footer = 2).
  2. Filter by prefix β€” keep only sketches whose URL path starts with currentPath.
  3. Group by next segment β€” collect all sketches that share the same path segment at depth + 1 (the immediate children).
  4. Classify each child:
    • If any sketch in the group has path segments beyond depth + 1, the child is a category folder card (isCategory: true, icon πŸ“).
    • If the group contains exactly one sketch at depth + 1, the child is a leaf sketch card (isCategory: false, icon ✦).
  5. Sort by order β€” the returned array is sorted ascending by the minOrder of each group.
The returned DashboardItem[] array is consumed directly by index.vue to render the card grid.
The isCategoryPath(path) helper checks whether a given path prefix matches any registered sketch’s category field. This is the signal [...all].vue uses to decide whether to render the category dashboard (<IndexPage />) rather than attempt a sketch component load β€” preventing false 404s for valid category paths that have no sketch registered at that exact URL.

Build docs developers (and LLMs) love