export const EXAMPLE_CATEGORY_DEFINITIONS = [ { id: 'turtle', label: 'Turtle & composition', description: 'Movement, coordinates, transforms, and repeated motifs.', }, { id: 'geometry', label: 'Paths & geometry', description: 'Points, paths, regions, clipping, offsets, and guides.', }, { id: 'stitches', label: 'Stitches & lines', description: 'Running, bean, blanket, dashed, and decorative line work.', }, { id: 'satin', label: 'Satin & columns', description: 'Satin paths, rails, caps, corners, and wide columns.', }, { id: 'fills', label: 'Fills & regions', description: 'Tatami, hatching, contour, gradient, and programmable fills.', }, { id: 'generative', label: 'Generative patterns', description: 'Seeded variation, noise, simulations, and mathematical curves.', }, { id: 'language', label: 'Language patterns', description: 'Procedures, lists, recursion, higher-order code, and modules.', }, { id: 'production', label: 'Production embroidery', description: 'Hoops, materials, underlay, appliqué, routing, and preflight.', }, ] as const; export type ExampleCategoryId = (typeof EXAMPLE_CATEGORY_DEFINITIONS)[number]['id']; export type ExampleKind = 'recipe' | 'sampler' | 'design' | 'validation'; export const EXAMPLE_KIND_LABELS: Record = { recipe: 'Recipe', sampler: 'Sampler', design: 'Design', validation: 'Validation', }; interface ExampleCatalogSeed { id: string; title: string; summary: string; kind: ExampleKind; tags: readonly string[]; } export interface ExampleCatalogEntry extends ExampleCatalogSeed { category: ExampleCategoryId; } const catalogByCategory = { turtle: [ { id: 'bloom', title: 'Bloom', summary: 'Build a rose from overlapping circles and a simple repeat loop.', kind: 'recipe', tags: ['repeat', 'circles', 'parameters'], }, { id: 'doublespiral', title: 'Double spiral', summary: 'Sew an interleaved square spiral as one continuous non-crossing line.', kind: 'recipe', tags: ['for-loop', 'continuous-path', 'turns'], }, { id: 'flower', title: 'Parametric flower', summary: 'Define a reusable arc-based petal and arrange copies in nested rings.', kind: 'recipe', tags: ['procedures', 'arcs', 'repeat', 'parameters'], }, { id: 'shell', title: 'Growing shell', summary: 'Grow an arc spiral with a while loop and inspect values in the console.', kind: 'recipe', tags: ['while-loop', 'arcs', 'console'], }, { id: 'transforms', title: 'Transform a motif', summary: 'Stamp one leaf with translation, rotation, scaling, and mirroring.', kind: 'sampler', tags: ['transforms', 'motifs', 'procedures', 'composition'], }, { id: 'triangles', title: 'Triangle field', summary: 'Grow, rotate, and recolor a triangle motif with a for loop.', kind: 'recipe', tags: ['for-loop', 'trigonometry', 'color', 'parameters'], }, { id: 'wreath', title: 'Leaf wreath', summary: 'Turn a small arc procedure into a circular wreath of repeated leaves.', kind: 'recipe', tags: ['procedures', 'arcs', 'repeat', 'motifs'], }, { id: 'fern', title: 'Branching fern', summary: 'Use push and pop to return from branches while growing a fern.', kind: 'recipe', tags: ['push-pop', 'branching', 'repeat'], }, { id: 'ngon', title: 'N-gon rings', summary: 'Progress from triangles to near-circles by increasing polygon side counts.', kind: 'recipe', tags: ['polygons', 'repeat', 'parameters'], }, { id: 'snowflake', title: 'Parametric snowflake', summary: 'Construct a symmetric crystal from one configurable branch procedure.', kind: 'design', tags: ['procedures', 'symmetry', 'parameters', 'motifs'], }, { id: 'tree', title: 'Recursive tree', summary: 'Sew a branching tree out and back with a recursive procedure.', kind: 'recipe', tags: ['recursion', 'procedures', 'branching'], }, { id: 'extrude', title: 'Stacked extrusion', summary: 'Create a dimensional block by stacking translated copies of an L-shaped tile.', kind: 'design', tags: ['transforms', 'layering', 'motifs'], }, { id: 'turtle', title: 'Turtle portrait', summary: 'Draw a complete turtle as a tribute to NeedleScript’s Logo heritage.', kind: 'design', tags: ['turtle', 'procedures', 'composition'], }, ], geometry: [ { id: 'bars', title: 'Editable bars', summary: 'Build reusable filled rectangles from draggable opposite corners.', kind: 'recipe', tags: ['handles', 'assertions', 'regions', 'procedures'], }, { id: 'trace-regions', title: 'Trace regions', summary: 'Capture turtle drawing as reusable path data for clipping and scattering.', kind: 'recipe', tags: ['trace', 'paths', 'clipping', 'scatter'], }, { id: 'traceman', title: 'Trace and clip', summary: 'Subtract one traced circle from another and fill the resulting region.', kind: 'recipe', tags: ['trace', 'clipping', 'boolean-geometry', 'fill'], }, { id: 'crossings', title: 'Chord crossings', summary: 'Find segment intersections among random chords and mark every crossing.', kind: 'recipe', tags: ['segment-intersection', 'randomness', 'lists', 'circles'], }, { id: 'cutbar', title: 'Split bar', summary: 'Cut a filled bar with a draggable line and style each side independently.', kind: 'recipe', tags: ['clipping', 'handles', 'regions', 'fills'], }, { id: 'distancebands', title: 'Distance bands', summary: 'Sweep concentric stadium contours using distance to a line segment.', kind: 'recipe', tags: ['distance', 'segments', 'contours', 'sampling'], }, { id: 'snaptoguide', title: 'Snap to guide', summary: 'Project stitches onto the nearest point of a reusable path guide.', kind: 'recipe', tags: ['guides', 'nearest-point', 'paths', 'effects'], }, { id: 'trace-motifs', title: 'Trace and stamp motifs', summary: 'Capture one motif, transform its path data, and stamp many copies.', kind: 'recipe', tags: ['trace', 'paths', 'transforms', 'motifs'], }, { id: 'ornaline', title: 'Ornaments along a line', summary: 'Place a local-space ornament repeatedly along an arbitrary path.', kind: 'recipe', tags: ['path-layout', 'resampling', 'motifs', 'vectors'], }, { id: 'pivot', title: 'Draggable pivot points', summary: 'Use free, disc-constrained, and axis-constrained point handles.', kind: 'sampler', tags: ['handles', 'coordinates', 'constraints', 'vectors'], }, { id: 'editable-leaf', title: 'Editable leaf', summary: 'Shape a Bézier leaf and its veins with draggable anchors and tangents.', kind: 'design', tags: ['handles', 'bezier', 'paths', 'interactive'], }, ], stitches: [ { id: 'sampler', title: 'Four line weights', summary: 'Compare running, bean, satin, and blanket stitch on simple lines.', kind: 'sampler', tags: ['running-stitch', 'bean', 'satin', 'blanket-stitch'], }, { id: 'waves', title: 'Sashiko waves', summary: 'Build rows of running-stitch scallops with a reusable wave procedure.', kind: 'design', tags: ['running-stitch', 'arcs', 'procedures', 'sashiko'], }, { id: 'runner', title: 'Dashed runner', summary: 'Walk a figure as a custom dashed line made from stitches and jumps.', kind: 'recipe', tags: ['dashes', 'jumps', 'procedures', 'line-work'], }, { id: 'kantha-bands', title: 'Kantha bands', summary: 'Compare list-driven, reporter-driven, and spatial stitch rhythms.', kind: 'sampler', tags: ['stitch-length', 'reporters', 'noise', 'texture'], }, { id: 'lines', title: 'Decorative line sampler', summary: 'Compare twelve combinations of stitch treatment and path shape.', kind: 'sampler', tags: ['running-stitch', 'bean', 'satin', 'blanket-stitch', 'paths'], }, { id: 'functional', title: 'Functional stitches', summary: 'Construct bartacks, eyelets, buttonholes, blanket edges, and seam stitches.', kind: 'sampler', tags: ['bartack', 'buttonhole', 'eyelet', 'bean', 'lock'], }, { id: 'wildflower-garland', title: 'Wildflower garland', summary: 'Place reusable flower motifs along an arc-length-aware winding stem.', kind: 'design', tags: ['path-layout', 'motifs', 'imports', 'running-stitch'], }, ], satin: [ { id: 'customsatin', title: 'Programmable satin', summary: 'Write reporters that control satin advance, width, asymmetry, and rake.', kind: 'sampler', tags: ['custom-satin', 'reporters', 'density', 'columns'], }, { id: 'star', title: 'Satin star', summary: 'Trace a configurable star polygon as a simple satin ribbon.', kind: 'recipe', tags: ['satin', 'polygons', 'repeat', 'parameters'], }, { id: 'coilsatin', title: 'Coiled satin ribbon', summary: 'Vary satin density along tapered coiling columns.', kind: 'design', tags: ['satin', 'density', 'taper', 'columns'], }, { id: 'rail-pair-satin', title: 'Rail-pair satin leaf', summary: 'Join two independently authored Bézier rails into a satin ribbon.', kind: 'recipe', tags: ['satinbetween', 'rails', 'bezier', 'columns'], }, { id: 'triangle', title: 'Variable-width triangle', summary: 'Reveal a hidden triangle by varying satin width along a spiral.', kind: 'design', tags: ['satin', 'variable-width', 'spiral', 'geometry'], }, { id: 'triangle-bitmap', title: 'Bitmap satin triangle', summary: 'Sample bitmap data to control the width of a satin spiral.', kind: 'recipe', tags: ['bitmap', 'satin', 'sampling', 'variable-width'], }, { id: 'satin-cap-corner-sampler', title: 'Satin caps and corners', summary: 'Compare open-column cap styles and sharp satin join policies.', kind: 'sampler', tags: ['satin-caps', 'satin-joins', 'underlay', 'columns'], }, { id: 'wide-column-split-sampler', title: 'Wide-column splitting', summary: 'Compare safe interlocking splits across a range of satin widths.', kind: 'sampler', tags: ['wide-satin', 'split', 'overlap', 'production'], }, ], fills: [ { id: 'badge', title: 'Filled badge', summary: 'Combine a tatami-filled polygon with a bold bean-stitch border.', kind: 'recipe', tags: ['tatami', 'bean', 'border', 'polygons'], }, { id: 'boustrophedon', title: 'Boustrophedon fill', summary: 'Cover a square with one continuous serpentine path.', kind: 'recipe', tags: ['continuous-path', 'serpentine', 'repeat', 'routing'], }, { id: 'fish', title: 'Adaptive hatch fish', summary: 'Hatch between mirrored sine curves with spacing driven by their gap.', kind: 'design', tags: ['hatching', 'sine', 'adaptive-spacing', 'routing'], }, { id: 'japan1', title: 'Hidden circle lines', summary: 'Reveal an invisible circle by widening satin across parallel rows.', kind: 'design', tags: ['hatching', 'variable-width', 'satin', 'circles'], }, { id: 'japan2', title: 'Crowded circle lines', summary: 'Overlay a dense circular chord field on an independent line grid.', kind: 'design', tags: ['hatching', 'circles', 'chords', 'serpentine'], }, { id: 'vortex', title: 'Vortex fill', summary: 'Fill a circle with rows that follow a programmable swirl direction field.', kind: 'recipe', tags: ['custom-fill', 'direction-field', 'vectors', 'tatami'], }, { id: 'billiard', title: 'Billiard fill', summary: 'Bounce one continuous thread inside a rectangle until coverage is reached.', kind: 'recipe', tags: ['continuous-path', 'reflection', 'coverage', 'while-loop'], }, { id: 'contour-fill-paths', title: 'Contour fill paths', summary: 'Supply inset rings to a custom fill-path reporter, including a hole.', kind: 'recipe', tags: ['custom-fill', 'contours', 'holes', 'offset-path'], }, { id: 'gingham', title: 'Gingham hatching', summary: 'Interleave directional hatch colors to create an optically blended check.', kind: 'design', tags: ['hatching', 'color', 'grid', 'optical-mixing'], }, { id: 'lfowaves', title: 'LFO wave fill', summary: 'Drive spacing in a circular serpentine fill with two sine oscillators.', kind: 'design', tags: ['serpentine', 'sine', 'variable-spacing', 'circles'], }, { id: 'patch', title: 'Knit-ready patch', summary: 'Inset a fill beneath a satin border with fabric-aware compensation.', kind: 'recipe', tags: ['tatami', 'satin-border', 'knit', 'underlay'], }, { id: 'spiral-fill-paths', title: 'Spiral fill paths', summary: 'Generate a custom spiral path set for the fill-path interface.', kind: 'recipe', tags: ['custom-fill', 'spiral', 'reporters', 'paths'], }, { id: 'truchet-window', title: 'Truchet window', summary: 'Clip a generated Truchet maze into a softly framed region.', kind: 'design', tags: ['clipping', 'tiles', 'custom-fill', 'regions'], }, { id: 'venn', title: 'Hatched Venn diagram', summary: 'Combine independently hatched circles through physical stitch superposition.', kind: 'recipe', tags: ['hatching', 'procedures', 'lists', 'trigonometry', 'travel-planning'], }, { id: 'customfill', title: 'Programmable fills', summary: 'Write direction and texture reporters for streamlines and custom tatami.', kind: 'sampler', tags: ['custom-fill', 'reporters', 'direction-field', 'texture'], }, { id: 'echofill', title: 'Echo fill', summary: 'Inset a region repeatedly to build a concentric contour fill.', kind: 'recipe', tags: ['contours', 'offset-path', 'regions', 'continuous-path'], }, { id: 'fill', title: 'Fill pattern sampler', summary: 'Compare 81 hand-built fill textures across nine pattern families.', kind: 'sampler', tags: ['hatching', 'contours', 'spirals', 'texture'], }, { id: 'fill-and-border', title: 'Fill and satin border', summary: 'Build a production-ready inset fill with an overlapping satin border.', kind: 'recipe', tags: ['imports', 'tatami', 'satin-border', 'underlay'], }, { id: 'gradientfill', title: 'Two-color gradient fill', summary: 'Interleave two thread colors while preserving aggregate row density.', kind: 'recipe', tags: ['gradient', 'color', 'imports', 'density'], }, { id: 'gradientfill-n', title: 'Multi-color gradient fill', summary: 'Blend any number of thread colors with density-neutral serpentine rows.', kind: 'recipe', tags: ['gradient', 'color', 'imports', 'serpentine'], }, { id: 'stipple', title: 'Coverage-aware stipple', summary: 'Grow a closed-loop stipple by querying where stitches already provide coverage.', kind: 'recipe', tags: ['coverage', 'history', 'closed-loop', 'sampling'], }, ], generative: [ { id: 'eclipse', title: 'Noisy eclipse', summary: 'Arrange radial running stitches with smooth reproducible noise.', kind: 'design', tags: ['noise', 'seed', 'radial', 'running-stitch'], }, { id: 'fermat', title: 'Fermat spiral', summary: 'Build a mathematical spiral as point data and sew the resulting path.', kind: 'recipe', tags: ['spiral', 'trigonometry', 'paths', 'sampling'], }, { id: 'hilbert1', title: 'Recursive Hilbert curve', summary: 'Generate a self-similar space-filling curve with recursion.', kind: 'recipe', tags: ['recursion', 'fractal', 'continuous-path'], }, { id: 'hilbert2', title: 'Smoothed Hilbert curve', summary: 'Capture a Hilbert path and round its corners with Chaikin smoothing.', kind: 'recipe', tags: ['recursion', 'trace', 'smoothing', 'paths'], }, { id: 'humanize', title: 'Humanized hatching', summary: 'Add seeded coherent drift to create a hand-stitched appearance.', kind: 'recipe', tags: ['humanize', 'noise', 'seed', 'effects'], }, { id: 'lissajous', title: 'Lissajous curve', summary: 'Generate parametric curves from configurable frequency ratios and phase.', kind: 'recipe', tags: ['trigonometry', 'paths', 'parameters', 'sampling'], }, { id: 'pixelated', title: 'Progressive pixelation', summary: 'Stamp a smooth ring onto successively coarser stitch grids.', kind: 'design', tags: ['snap-to-grid', 'transforms', 'effects', 'quantization'], }, { id: 'snaptogrid', title: 'Snap to grid', summary: 'Quantize transformed motifs onto one fabric-space lattice.', kind: 'recipe', tags: ['snap-to-grid', 'transforms', 'cross-stitch', 'effects'], }, { id: 'spiderweb', title: 'Spiderweb', summary: 'Combine radial spokes, a sagging spiral, and seeded imperfection.', kind: 'design', tags: ['spiral', 'radial', 'randomness', 'seed'], }, { id: 'wander', title: 'Bounded random walk', summary: 'Turn a seeded random walk back whenever it reaches a circular boundary.', kind: 'recipe', tags: ['random-walk', 'seed', 'boundaries', 'repeat'], }, { id: 'warp', title: 'Programmable warp', summary: 'Pass emitted points through a custom nonlinear deformation reporter.', kind: 'recipe', tags: ['warp', 'reporters', 'noise', 'effects'], }, { id: 'ampmod1', title: 'Amplitude-modulated ring', summary: 'Wrap a carrier wave with a slower amplitude envelope around a circle.', kind: 'recipe', tags: ['trigonometry', 'modulation', 'radial', 'paths'], }, { id: 'ampmod2', title: 'Multicolor modulated rings', summary: 'Layer amplitude-modulated rings with independent color and wave parameters.', kind: 'design', tags: ['trigonometry', 'modulation', 'color', 'layering'], }, { id: 'complex-spirograph', title: 'Epicycle spirograph', summary: 'Layer several rotating arms to produce a complex spirograph mandala.', kind: 'design', tags: ['spirograph', 'trigonometry', 'epicycles', 'paths'], }, { id: 'disturbance', title: 'Fault-line disturbance', summary: 'Localize fractal noise inside an otherwise orderly parallel-line field.', kind: 'design', tags: ['noise', 'falloff', 'line-field', 'seed'], }, { id: 'flow', title: 'Noise flow field', summary: 'Steer multiple strands through a smooth seeded vector field.', kind: 'recipe', tags: ['noise', 'flow-field', 'boundaries', 'seed'], }, { id: 'logarithmic-spiral', title: 'Logarithmic spiral', summary: 'Recover spiral angle from radius and vary spacing analytically.', kind: 'recipe', tags: ['spiral', 'logarithms', 'trigonometry', 'math'], }, { id: 'lorenz-attractor', title: 'Lorenz attractor', summary: 'Integrate three coupled equations to stitch the classic butterfly attractor.', kind: 'recipe', tags: ['simulation', 'differential-equations', 'paths', 'math'], }, { id: 'meandering-spiral', title: 'Meandering spiral', summary: 'Increase smooth random displacement from the center toward a spiral rim.', kind: 'design', tags: ['spiral', 'noise', 'falloff', 'seed'], }, { id: 'morphing-medallion', title: 'Morphing medallion', summary: 'Interpolate aligned circle and star outlines into a layered medallion.', kind: 'design', tags: ['morphing', 'path-alignment', 'imports', 'layering'], }, { id: 'quantized', title: 'Quantized wave mesh', summary: 'Snap a family of sine-wave paths onto a fixed stitch grid.', kind: 'design', tags: ['sine', 'snap-to-grid', 'paths', 'quantization'], }, { id: 'sinewaves', title: 'Sine-wave mesh', summary: 'Generate, resample, and sew a configurable family of sine paths.', kind: 'recipe', tags: ['sine', 'paths', 'resampling', 'parameters'], }, { id: 'spirograph', title: 'Classic spirograph', summary: 'Trace a roulette curve from a circle rolling around another circle.', kind: 'recipe', tags: ['spirograph', 'trigonometry', 'paths', 'parameters'], }, { id: 'spirolateral', title: 'Spirolateral', summary: 'Repeat increasing segment lengths and a fixed turn until the path closes.', kind: 'recipe', tags: ['turns', 'repeat', 'continuous-path', 'parameters'], }, { id: 'threaded-orbits', title: 'Threaded orbits', summary: 'Create string-art caustics by connecting points around two poles.', kind: 'design', tags: ['string-art', 'trigonometry', 'lines', 'radial'], }, { id: 'waveforms', title: 'Waveform sampler', summary: 'Construct sine, triangle, sawtooth, and square oscillator paths.', kind: 'sampler', tags: ['waveforms', 'math', 'paths', 'procedures'], }, { id: 'wavefront', title: 'Traveling wavefront', summary: 'Move a localized Gaussian wave packet through a parallel-line field.', kind: 'design', tags: ['sine', 'gaussian', 'line-field', 'math'], }, { id: 'contour', title: 'Noise contour map', summary: 'Extract dashed and solid topographic contours from seeded fractal noise.', kind: 'design', tags: ['noise', 'marching-squares', 'contours', 'seed'], }, { id: 'shatter', title: 'Voronoi shatter', summary: 'Inset Voronoi cells and hatch them with a directional flow field.', kind: 'design', tags: ['voronoi', 'scatter', 'hatching', 'flow-field'], }, { id: 'snake', title: 'Self-avoiding snake', summary: 'Grow a seeded grid walk until it encounters itself or the hoop.', kind: 'recipe', tags: ['random-walk', 'grid', 'collision', 'seed'], }, { id: 'stained-glass', title: 'Stained glass', summary: 'Relax Voronoi panes inside a superellipse and border the resulting cells.', kind: 'design', tags: ['voronoi', 'regions', 'imports', 'satin-border'], }, { id: 'warpedlines1', title: 'Warped lines I', summary: 'Bend vertical lines horizontally with a programmable wave deformation.', kind: 'recipe', tags: ['warp', 'sine', 'line-field', 'effects'], }, { id: 'warpedlines2', title: 'Warped lines II', summary: 'Layer wave deformations to create a richer underwater ripple field.', kind: 'design', tags: ['warp', 'sine', 'line-field', 'layering'], }, { id: 'warpedlines3', title: 'Warped lines III', summary: 'Combine several spatial wave controls into a dense warped-line study.', kind: 'design', tags: ['warp', 'sine', 'line-field', 'parameters'], }, ], language: [ { id: 'compose', title: 'Function composition', summary: 'Build reusable transform pipelines and apply them to layered rings.', kind: 'recipe', tags: ['compose', 'higher-order-functions', 'transforms', 'lists'], }, { id: 'easing', title: 'Easing functions', summary: 'Define and compare a library of pure interpolation curves.', kind: 'sampler', tags: ['procedures', 'math', 'interpolation', 'pure-functions'], }, { id: 'starburst', title: 'Functional starburst', summary: 'Build a radial design with map, filter, reduce, and step ranges.', kind: 'recipe', tags: ['map', 'filter', 'reduce', 'higher-order-functions'], }, { id: 'echo', title: 'Record and replay', summary: 'Record a walk in a list, then replay mirrored and shuffled echoes.', kind: 'recipe', tags: ['lists', 'append', 'for-in', 'shuffle'], }, { id: 'meadow', title: 'Modern syntax meadow', summary: 'Tour modern syntax, procedures, recursion, loops, operators, and comments.', kind: 'sampler', tags: ['syntax', 'recursion', 'procedures', 'control-flow'], }, { id: 'needlescript1', title: 'Single-stroke font', summary: 'Define continuous glyph procedures and lay out a fixed wordmark.', kind: 'design', tags: ['procedures', 'lettering', 'coordinates', 'glyphs'], }, { id: 'needlescript2', title: 'String-powered font', summary: 'Look up glyph procedures while handling spaces, newlines, and errors.', kind: 'recipe', tags: ['strings', 'procedures', 'lettering', 'validation'], }, ], production: [ { id: 'anisotropic-material-compensation', title: 'Directional compensation', summary: 'Compare scalar and grain-aware pull compensation across stitch directions.', kind: 'sampler', tags: ['compensation', 'fabric-grain', 'stretch', 'sew-out'], }, { id: 'applique-with', title: 'Appliqué workflow', summary: 'Sequence placement, tack-down, stops, trimming, and satin cover stitches.', kind: 'recipe', tags: ['applique', 'imports', 'stops', 'satin-border'], }, { id: 'banner', title: 'Large-hoop banner', summary: 'Configure a large hoop and explicit stitch-budget override for a scatter field.', kind: 'design', tags: ['hoop', 'budgets', 'scatter', 'fabric'], }, { id: 'constrained-travel-plan', title: 'Constrained travel planning', summary: 'Reorder route groups while preserving atomic motifs and plan barriers.', kind: 'sampler', tags: ['routing', 'atomic', 'plan-barrier', 'travel'], }, { id: 'knockdown-fleece', title: 'Fleece knockdown', summary: 'Lay a sparse foundation beneath a bordered patch on high-loft fabric.', kind: 'recipe', tags: ['knockdown', 'fleece', 'topping', 'underlay'], }, { id: 'physical-sewout-validation-v1', title: 'Physical sew-out sheet', summary: 'Produce a fixed calibration sheet for repeatable material validation.', kind: 'validation', tags: ['sew-out', 'materials', 'calibration', 'hoop'], }, { id: 'preflight-issue-sampler', title: 'Preflight issue sampler', summary: 'Intentionally trigger production warnings for diagnostic teaching.', kind: 'validation', tags: ['preflight', 'warnings', 'hoop', 'diagnostics'], }, ], } satisfies Record; export const EXAMPLE_CATALOG: readonly ExampleCatalogEntry[] = EXAMPLE_CATEGORY_DEFINITIONS.flatMap( ({ id: category }) => catalogByCategory[category].map((entry) => ({ ...entry, category })) as ExampleCatalogEntry[], ); export const START_HERE_EXAMPLE_IDS = [ 'bloom', 'sampler', 'flower', 'transforms', 'trace-regions', 'badge', ] as const;