From f064c540a8027b3bf334d64e57673631cfaf314a Mon Sep 17 00:00:00 2001 From: eugenioenko Date: Tue, 24 Mar 2026 20:43:47 -0700 Subject: [PATCH] feat: live demos self hosted --- docs-web/astro.config.mjs | 6 +- docs-web/public/llms.txt | 6 + docs-web/public/playground/index.html | 358 +++++++++++++++++++ docs-web/src/components/SocialIcons.astro | 20 ++ docs-web/src/content/docs/guides/examples.md | 130 +++++++ docs-web/src/content/docs/index.mdx | 8 +- pnpm-lock.yaml | 29 -- 7 files changed, 521 insertions(+), 36 deletions(-) create mode 100644 docs-web/public/playground/index.html create mode 100644 docs-web/src/components/SocialIcons.astro create mode 100644 docs-web/src/content/docs/guides/examples.md diff --git a/docs-web/astro.config.mjs b/docs-web/astro.config.mjs index 29c02d2..2e4d3f9 100644 --- a/docs-web/astro.config.mjs +++ b/docs-web/astro.config.mjs @@ -4,6 +4,9 @@ import starlight from '@astrojs/starlight'; export default defineConfig({ integrations: [ starlight({ + components: { + SocialIcons: './src/components/SocialIcons.astro', + }, customCss: ['./src/styles/custom.css'], head: [ { @@ -48,7 +51,8 @@ gtag('config', 'G-04FFNYJXWM');`, { label: 'Lazy Loading', link: '/guides/lazy-loading/' }, { label: 'Without a Build Pipeline', link: '/guides/without-a-build/' }, { label: 'AI-Driven Development', link: '/guides/agents/' }, - { label: 'Vite Integration', link: '/guides/vite/' } + { label: 'Vite Integration', link: '/guides/vite/' }, + { label: 'Examples', link: '/guides/examples/' } ] }, { label: 'Reference', autogenerate: { directory: 'reference' } }, diff --git a/docs-web/public/llms.txt b/docs-web/public/llms.txt index cb31490..d81866e 100644 --- a/docs-web/public/llms.txt +++ b/docs-web/public/llms.txt @@ -289,6 +289,12 @@ user.value.name = 'Alice'; // does NOT trigger ✗ + +
+link + + + diff --git a/docs-web/public/playground/index.html b/docs-web/public/playground/index.html new file mode 100644 index 0000000..836ea10 --- /dev/null +++ b/docs-web/public/playground/index.html @@ -0,0 +1,358 @@ + + + + + + Kasper.js Playground + + + + + + +
+
+
+
+
+
+ +
+
+ + + + + + + diff --git a/docs-web/src/components/SocialIcons.astro b/docs-web/src/components/SocialIcons.astro new file mode 100644 index 0000000..7f2dd21 --- /dev/null +++ b/docs-web/src/components/SocialIcons.astro @@ -0,0 +1,20 @@ +--- +import Default from '@astrojs/starlight/components/SocialIcons.astro'; +--- + +Playground + + + diff --git a/docs-web/src/content/docs/guides/examples.md b/docs-web/src/content/docs/guides/examples.md new file mode 100644 index 0000000..980ec7f --- /dev/null +++ b/docs-web/src/content/docs/guides/examples.md @@ -0,0 +1,130 @@ +--- +title: Examples +description: Live demo applications built with Kasper.js on StackBlitz. +--- + +The examples below run on StackBlitz and showcase real Kasper.js applications. **If the preview gets stuck on loading, refresh the browser tab** — StackBlitz requires a one-time Service Worker boot that occasionally needs a second load. + +All examples use the `.kasper` single-file component format with `vite-plugin-kasper`. + +[Open all examples on StackBlitz](https://stackblitz.com/github/eugenioenko/kasper-js/tree/main/demos) + +--- + +## Counter + +Basic signal usage with `signal()`, `computed()`, and `@on:click`. A good first component to read if you're new to Kasper. + +**Showcases:** `signal`, `computed`, template interpolation `{{}}`, event handling. + +--- + +## Todo App + +Classic todo list with add, complete, and delete. Demonstrates `@each` over a signal array and conditional rendering with `@if`. + +**Showcases:** `@each`, `@if`, `@else`, signal arrays, event handling. + +--- + +## Kanban Board + +Drag-and-drop task board with columns and cards. Multiple components communicating via shared signals and component args (`@:`). + +**Showcases:** multi-component architecture, `@:` props, shared state, `@each` with `@key`. + +--- + +## Product Catalog + +Filterable product grid with a detail form. Shows list filtering via `computed` and a form bound to signals. + +**Showcases:** `computed` for derived lists, form inputs, component slots. + +--- + +## Shopping Cart + +Product grid with a cart panel and running total. State lives in a shared store module (plain signal exports), consumed by two sibling components. + +**Showcases:** external signal store, cross-component state, `computed` aggregation. + +--- + +## Data Table + +Sortable, paginated table over a dataset. All sort/page state is signals; the displayed rows are a `computed` slice. + +**Showcases:** `computed` for derived data, `@each` with `@key`, stateful UI without a library. + +--- + +## Signup Form + +Multi-field form with validation. A `use-form.ts` helper manages field state and error signals. + +**Showcases:** form validation pattern, reusable non-component logic, signal-per-field approach. + +--- + +## Dashboard + +Metrics panel that polls a simulated API and updates charts. Uses `onMount` / `onDestroy` for polling lifecycle and a shared metrics store. + +**Showcases:** `onMount`, `onDestroy`, async data fetching, signal store. + +--- + +## Toast Notifications + +Global toast system triggered from anywhere in the app. The store exposes `push` / `dismiss` functions that mutate a signal array. + +**Showcases:** global event-driven store, `@each` with `@key`, programmatic component interaction. + +--- + +## Tree View + +Recursive collapsible tree rendered from nested data. Each `TreeNode` renders its own children, demonstrating recursive component composition. + +**Showcases:** recursive components, `@if`/`@each` nesting, tree data structures. + +--- + +## Markdown Editor + +Split-pane editor with live preview. The rendered HTML is a `computed` from the raw markdown signal. + +**Showcases:** `computed` for transformations, `innerHTML` binding, two-pane layout. + +--- + +## Wizard + +Multi-step form with back/next navigation and per-step validation. Step index is a signal; each step is a separate component. + +**Showcases:** step-based navigation, conditional component rendering, shared wizard state. + +--- + +## Game of Life + +Conway's Game of Life running in a Kasper component. The grid is a signal array updated on each tick via `setInterval` registered in `onMount`. + +**Showcases:** `onMount`, `onDestroy` cleanup, high-frequency signal updates, `@each` grid rendering. + +--- + +## Hex Explorer + +Interactive hex color picker with live preview and history. + +**Showcases:** input binding, `computed` color derivation, signal-backed history list. + +--- + +## Pipeline Demo + +Demonstrates the `|>` pipeline operator in template expressions, chaining transformation functions inline. + +**Showcases:** pipeline operator `|>`, expression language depth, functional data transformations. diff --git a/docs-web/src/content/docs/index.mdx b/docs-web/src/content/docs/index.mdx index 2a26a7a..4e516f2 100644 --- a/docs-web/src/content/docs/index.mdx +++ b/docs-web/src/content/docs/index.mdx @@ -9,12 +9,8 @@ hero: - text: Get Started link: /getting-started/installation/ icon: right-arrow - - text: Try Live - link: https://stackblitz.com/github/eugenioenko/kasper-starter - icon: external - variant: secondary - - text: Live Demos - link: https://stackblitz.com/github/eugenioenko/kasper-js/tree/main/demos + - text: Playground + link: /playground/ icon: external variant: secondary - text: View on GitHub diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b78df18..8bc56d1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -566,105 +566,89 @@ packages: resolution: {integrity: sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-arm@1.2.4': resolution: {integrity: sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-ppc64@1.2.4': resolution: {integrity: sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-riscv64@1.2.4': resolution: {integrity: sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==} cpu: [riscv64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-s390x@1.2.4': resolution: {integrity: sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-libvips-linux-x64@1.2.4': resolution: {integrity: sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.2.4': resolution: {integrity: sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.2.4': resolution: {integrity: sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-linux-arm64@0.34.5': resolution: {integrity: sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [glibc] '@img/sharp-linux-arm@0.34.5': resolution: {integrity: sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm] os: [linux] - libc: [glibc] '@img/sharp-linux-ppc64@0.34.5': resolution: {integrity: sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [ppc64] os: [linux] - libc: [glibc] '@img/sharp-linux-riscv64@0.34.5': resolution: {integrity: sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [riscv64] os: [linux] - libc: [glibc] '@img/sharp-linux-s390x@0.34.5': resolution: {integrity: sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [s390x] os: [linux] - libc: [glibc] '@img/sharp-linux-x64@0.34.5': resolution: {integrity: sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [glibc] '@img/sharp-linuxmusl-arm64@0.34.5': resolution: {integrity: sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [arm64] os: [linux] - libc: [musl] '@img/sharp-linuxmusl-x64@0.34.5': resolution: {integrity: sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} cpu: [x64] os: [linux] - libc: [musl] '@img/sharp-wasm32@0.34.5': resolution: {integrity: sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==} @@ -787,79 +771,66 @@ packages: resolution: {integrity: sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==} cpu: [arm] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.59.0': resolution: {integrity: sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==} cpu: [arm] os: [linux] - libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.59.0': resolution: {integrity: sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==} cpu: [arm64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.59.0': resolution: {integrity: sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==} cpu: [arm64] os: [linux] - libc: [musl] '@rollup/rollup-linux-loong64-gnu@4.59.0': resolution: {integrity: sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==} cpu: [loong64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-loong64-musl@4.59.0': resolution: {integrity: sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==} cpu: [loong64] os: [linux] - libc: [musl] '@rollup/rollup-linux-ppc64-gnu@4.59.0': resolution: {integrity: sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==} cpu: [ppc64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-ppc64-musl@4.59.0': resolution: {integrity: sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==} cpu: [ppc64] os: [linux] - libc: [musl] '@rollup/rollup-linux-riscv64-gnu@4.59.0': resolution: {integrity: sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==} cpu: [riscv64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-riscv64-musl@4.59.0': resolution: {integrity: sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==} cpu: [riscv64] os: [linux] - libc: [musl] '@rollup/rollup-linux-s390x-gnu@4.59.0': resolution: {integrity: sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==} cpu: [s390x] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.59.0': resolution: {integrity: sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==} cpu: [x64] os: [linux] - libc: [glibc] '@rollup/rollup-linux-x64-musl@4.59.0': resolution: {integrity: sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==} cpu: [x64] os: [linux] - libc: [musl] '@rollup/rollup-openbsd-x64@4.59.0': resolution: {integrity: sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==}