stream_weaver 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.beads/.gitignore +77 -0
- data/.beads/README.md +81 -0
- data/.beads/config.yaml +54 -0
- data/.beads/metadata.json +7 -0
- data/.rspec +3 -0
- data/AGENTS.md +91 -0
- data/CHANGELOG.md +294 -0
- data/CLAUDE.md +67 -0
- data/LICENSE.txt +21 -0
- data/README.md +565 -0
- data/Rakefile +13 -0
- data/assets/streamweaver-hero.jpg +0 -0
- data/bench/baselines/ledger.rb +58 -0
- data/bench/baselines/warroom.rb +51 -0
- data/bench/fixtures/ledger.rb +76 -0
- data/bench/fixtures/warroom.rb +60 -0
- data/bench/results/6daf8b8.md +102 -0
- data/bench/results/c8d749b.md +102 -0
- data/bench/results/eb06ab9.md +102 -0
- data/bench/run.rb +151 -0
- data/bench/support.rb +84 -0
- data/copy_this/dto_run_sample_run_7631.html +220 -0
- data/docs/SERVICE_MODE.md +302 -0
- data/docs/architecture/how_streamweaver_works.md +772 -0
- data/docs/blog/2026-01-16-streamweaver-introduction.md +515 -0
- data/docs/bug-2026-08-31-canvas-bridge-socket-collision.md +83 -0
- data/docs/canvas-ipc-session-summary.md +127 -0
- data/docs/canvas-panel-workflow.md +172 -0
- data/docs/canvas-read.md +147 -0
- data/docs/canvas-roadmap.md +275 -0
- data/docs/case-studies/2026-09-03-didx-canvas-read-shelf.md +147 -0
- data/docs/claude-code-companion-skill-spec.md +567 -0
- data/docs/components_reference.md +1223 -0
- data/docs/crud-patterns.md +265 -0
- data/docs/endpoints.md +122 -0
- data/docs/for_llms.md +1 -0
- data/docs/form-patterns.md +165 -0
- data/docs/frontend-only.md +169 -0
- data/docs/html-artifact-audit.md +238 -0
- data/docs/ideas/2025-01-01-as-a-service.md +203 -0
- data/docs/ideas/2026-01-16-charm-tui-exploration.md +542 -0
- data/docs/ideas/2026-08-27-static-doc-shelf-export.md +153 -0
- data/docs/ideas/dhh-review-future-refactors.md +142 -0
- data/docs/opal-jamstack.md +47 -0
- data/docs/opal-npm-direction.md +184 -0
- data/docs/opal-spike-findings.md +194 -0
- data/docs/plans/2025-12-16-form-blocks-design.md +124 -0
- data/docs/plans/2025-12-30-examples-browser-design.md +152 -0
- data/docs/plans/2026-01-02-charts-design.md +288 -0
- data/docs/plans/2026-01-10-canvas-ipc-design.md +247 -0
- data/docs/plans/2026-01-19-cabinet-control-components.md +176 -0
- data/docs/plans/2026-01-26-gem-release-and-panel.md +140 -0
- data/docs/plans/canvas-claude-project-design.md +238 -0
- data/docs/plans/canvas-doc-location-and-discovery.md +32 -0
- data/docs/plans/org-doc-preview-surfaces.md +293 -0
- data/docs/plans/shadcn-polish-plan.md +417 -0
- data/docs/porting-artifacts.md +252 -0
- data/docs/reference/agent-skills-comparison.md +369 -0
- data/docs/reference/travel-state-prd.artifact.html +780 -0
- data/docs/research/2026-08-17-hotwire-alike-landscape.md +268 -0
- data/docs/research/2026-08-17-hotwire-concept-map.md +404 -0
- data/docs/research/2026-08-22-lazy-fragments-trigger-decision.md +246 -0
- data/docs/research/2026-08-22-learnhotwire-syllabus-coverage.md +239 -0
- data/docs/research/frontend-only-matrix.md +278 -0
- data/docs/research/streamweaver-way-spike-findings.md +529 -0
- data/docs/resource-dsl.md +342 -0
- data/docs/routing.md +302 -0
- data/docs/ruby-ui-comparison.md +319 -0
- data/docs/shared-dsl-fragments.md +356 -0
- data/docs/streamweaver-for-ai-agents.md +401 -0
- data/docs/streamweaver-frontend-vision.md +123 -0
- data/docs/streamweaver_canvas/glimmer_initial_final_layer.rb +77 -0
- data/docs/streamweaver_canvas/save_example.rb +9 -0
- data/docs/templates.md +213 -0
- data/docs/testing.md +155 -0
- data/docs/theming-hooks.md +281 -0
- data/docs/tutorials/the-streamweaver-way.md +882 -0
- data/docs/university/capability-inventory.md +137 -0
- data/docs/university/dependency-survey.md +114 -0
- data/docs/university/design-spec.md +217 -0
- data/docs/university/mockups/code-block-doc-theme-dark.png +0 -0
- data/docs/university/mockups/code-block-doc-theme-light.png +0 -0
- data/docs/university/mockups/course-list-dark.png +0 -0
- data/docs/university/mockups/course-list-light.png +0 -0
- data/docs/university/mockups/course_canvas_mockup.rb +741 -0
- data/docs/university/mockups/step-screen-dark.png +0 -0
- data/docs/university/mockups/step-screen-light.png +0 -0
- data/docs/university/roadmap.md +72 -0
- data/docs/university/send-to-coworker.md +77 -0
- data/docs/university/worker-session-mining.md +109 -0
- data/docs/visual/browser-rendering-spike.md +173 -0
- data/docs/visual/builder-visual-plan-analysis.md +378 -0
- data/docs/visual/sw-plan-format-exploration.md +511 -0
- data/docs/visual/sw-plan-rendering-deep-dive.md +453 -0
- data/docs/visual-skills/PROGRESS.md +60 -0
- data/docs/visual-skills/SESSION-CONTEXT.md +207 -0
- data/docs/visual-skills/analysis/components.md +317 -0
- data/docs/visual-skills/analysis/overlap.md +360 -0
- data/docs/visual-skills/analysis/pi-design-deck.md +1102 -0
- data/docs/visual-skills/analysis/streamweaver-inventory.md +93 -0
- data/docs/visual-skills/analysis/unified-specs.feature +1003 -0
- data/docs/visual-skills/analysis/visual-explainer.md +964 -0
- data/docs/visual-skills/blog/blog-series-outline.md +39 -0
- data/docs/visual-skills/blog/token-efficiency.md +73 -0
- data/docs/visual-skills/design/architecture.md +1725 -0
- data/docs/visual-skills/design/codex-review.md +340 -0
- data/docs/visual-skills/design/dhh-review.md +209 -0
- data/docs/visual-skills/design/evolution.md +100 -0
- data/docs/visual-skills/design/gemini-review.md +55 -0
- data/docs/visual-skills/design/review-synthesis.md +149 -0
- data/docs/visual-skills/implementation/STATE.md +22 -0
- data/docs/visual-skills/implementation/plan.md +347 -0
- data/docs/visual-skills/implementation/spike-findings.md +237 -0
- data/docs/visual-skills/implementation/tasks.md +702 -0
- data/docs/visual-skills/lessons-learned/process.md +145 -0
- data/examples/README.md +96 -0
- data/examples/advanced/all_components.rb +177 -0
- data/examples/advanced/examples_browser.rb +394 -0
- data/examples/advanced/teachables_browser.rb +261 -0
- data/examples/advanced/theme_tweaker.rb +366 -0
- data/examples/advanced/tutorial.rb +1528 -0
- data/examples/agentic/agentic_form.rb +30 -0
- data/examples/agentic/agentic_form_autoclose.rb +30 -0
- data/examples/agentic/cultivation_tracker.rb +69 -0
- data/examples/basic/hello_world.rb +22 -0
- data/examples/basic/opal_tabs_table.rb +44 -0
- data/examples/basic/todo_list.rb +39 -0
- data/examples/button_loading_test.rb +36 -0
- data/examples/canvas/mermaid_canvas_demo.sh +151 -0
- data/examples/charts/bar_chart_demo.rb +57 -0
- data/examples/charts/line_chart_demo.rb +73 -0
- data/examples/charts/pie_area_demo.rb +87 -0
- data/examples/charts/stacked_bar_chart_demo.rb +69 -0
- data/examples/claude_code/README.md +85 -0
- data/examples/claude_code/codebreaker/.claude/commands/infiltrate.md +632 -0
- data/examples/claude_code/codebreaker/.claude/settings.json +11 -0
- data/examples/claude_code/codebreaker/.claude/settings.local.json +17 -0
- data/examples/claude_code/codebreaker/.claude/skills/infiltrate.md +0 -0
- data/examples/claude_code/codebreaker/README.md +213 -0
- data/examples/claude_code/tutorial/.claude/commands/learn.md +453 -0
- data/examples/claude_code/tutorial/README.md +102 -0
- data/examples/claude_code/verification_flow/.claude/commands/verify.md +171 -0
- data/examples/claude_code/verification_flow/README.md +126 -0
- data/examples/components/annotated_code_demo.rb +54 -0
- data/examples/components/callout_demo.rb +33 -0
- data/examples/components/checkbox_group_demo.rb +46 -0
- data/examples/components/design_review.css +468 -0
- data/examples/components/design_review_demo.rb +44 -0
- data/examples/components/design_review_dsl.rb +300 -0
- data/examples/components/diff_block_demo.rb +112 -0
- data/examples/components/events_demo.rb +184 -0
- data/examples/components/form_demo.rb +62 -0
- data/examples/components/lesson_demo.rb +53 -0
- data/examples/components/markdown_demo.rb +110 -0
- data/examples/components/mermaid_demo.rb +166 -0
- data/examples/components/pareto_set.rb +64 -0
- data/examples/components/prd_demo.rb +21 -0
- data/examples/components/prd_dsl.rb +385 -0
- data/examples/components/quiz_demo.rb +47 -0
- data/examples/components/run_viewer_demo.rb +100 -0
- data/examples/components/score_and_collapsible_demo.rb +82 -0
- data/examples/components/select_stale_value_smoke_test.rb +39 -0
- data/examples/components/table_demo.rb +247 -0
- data/examples/components/timer_with_state_demo.rb +58 -0
- data/examples/components/todo_due_dates.rb +63 -0
- data/examples/components/uat_gaps_demo.rb +112 -0
- data/examples/dashboard/feed_simulator.rb +60 -0
- data/examples/dashboard/live_dashboard.rb +80 -0
- data/examples/dashboard_components.rb +108 -0
- data/examples/deferred_fragments_demo.rb +62 -0
- data/examples/generate_more_spike/README.md +63 -0
- data/examples/generate_more_spike/app.rb +441 -0
- data/examples/git_health.sh +401 -0
- data/examples/layout/layout_components_demo.rb +174 -0
- data/examples/layout/modal_demo.rb +215 -0
- data/examples/layout/navigation_demo.rb +227 -0
- data/examples/layout/route_tabs_demo.rb +52 -0
- data/examples/layout/routing_demo.rb +52 -0
- data/examples/layout/scroll_box_demo.rb +154 -0
- data/examples/lazy_fragments_demo.rb +151 -0
- data/examples/my_todos/README.md +29 -0
- data/examples/my_todos/my_todos.rb +312 -0
- data/examples/my_todos/store.rb +86 -0
- data/examples/opal/reactive_demo.rb +62 -0
- data/examples/opal/scenarios/s1_counter.rb +15 -0
- data/examples/opal/scenarios/s2_search_filter.rb +17 -0
- data/examples/opal/scenarios/s3_sibling_tabs.rb +25 -0
- data/examples/opal/scenarios/s4_shopping_cart.rb +34 -0
- data/examples/opal/scenarios/s5_watch.rb +39 -0
- data/examples/opal/scenarios/s6_on_start.rb +20 -0
- data/examples/opal/scenarios/s7_wizard.rb +33 -0
- data/examples/opal/scenarios/s8_loan_calculator.rb +21 -0
- data/examples/opal/scenarios/s9_dashboard.rb +27 -0
- data/examples/operations_dashboard_demo.rb +167 -0
- data/examples/panel_demo.sh +447 -0
- data/examples/parity/assets/tyrion_slice.css +86 -0
- data/examples/parity/rivet_people_slice.rb +182 -0
- data/examples/parity/tyrion_components.css +777 -0
- data/examples/parity/tyrion_warroom_components.rb +414 -0
- data/examples/parity/tyrion_warroom_slice.rb +549 -0
- data/examples/puma_dev/README.md +124 -0
- data/examples/puma_dev/config.ru +34 -0
- data/examples/puma_dev/standalone_app.rb +34 -0
- data/examples/scaffolding/blog.rb +49 -0
- data/examples/scaffolding/utf_lite.rb +105 -0
- data/examples/styling/feedback_demo.rb +229 -0
- data/examples/styling/style_showcase.rb +172 -0
- data/examples/styling/theme_demo.rb +508 -0
- data/examples/timer_health_checker.rb +111 -0
- data/examples/timer_showcase.rb +131 -0
- data/examples/tutorials/render_markdown.rb +112 -0
- data/examples/tutorials/streamweaver_way_tutorial.rb +44 -0
- data/examples/tutorials/tutorial_content.rb +1082 -0
- data/examples/visual_skills/design_deck_demo.rb +314 -0
- data/examples/visual_skills/explainer_demo.rb +499 -0
- data/exe/streamweaver +9 -0
- data/gsd/ROADMAP-1.0.md +167 -0
- data/gsd/STATE.md +13 -0
- data/gsd/research/market-positioning-research.md +139 -0
- data/gsd/research/production-patterns-research.md +270 -0
- data/gsd/research/repo-audit-1.0.md +274 -0
- data/lib/stream_weaver/action_token.rb +58 -0
- data/lib/stream_weaver/adapter/alpinejs.rb +8249 -0
- data/lib/stream_weaver/adapter/base.rb +591 -0
- data/lib/stream_weaver/adapter/opal.rb +334 -0
- data/lib/stream_weaver/adapter/static.rb +1118 -0
- data/lib/stream_weaver/admin.rb +176 -0
- data/lib/stream_weaver/app.rb +1821 -0
- data/lib/stream_weaver/assets/js/sw-copy.js +50 -0
- data/lib/stream_weaver/assets/js/sw-heredoc-rewrite.js +68 -0
- data/lib/stream_weaver/assets/js/sw-keyboard.js +165 -0
- data/lib/stream_weaver/assets/js/sw-mermaid-zoom.js +621 -0
- data/lib/stream_weaver/assets/js/sw-route-tabs.js +53 -0
- data/lib/stream_weaver/assets/js/sw-sidebar-toc.js +116 -0
- data/lib/stream_weaver/assets/js/sw-slide-nav.js +103 -0
- data/lib/stream_weaver/canvas/bridge.rb +239 -0
- data/lib/stream_weaver/canvas/bridge_server.rb +646 -0
- data/lib/stream_weaver/canvas/client.rb +298 -0
- data/lib/stream_weaver/canvas/doc_roots.rb +233 -0
- data/lib/stream_weaver/canvas/doc_store.rb +252 -0
- data/lib/stream_weaver/canvas/gist_publisher.rb +264 -0
- data/lib/stream_weaver/canvas/gist_save_handler.rb +89 -0
- data/lib/stream_weaver/canvas/gist_store.rb +135 -0
- data/lib/stream_weaver/canvas/helpers.rb +109 -0
- data/lib/stream_weaver/canvas/history.rb +90 -0
- data/lib/stream_weaver/canvas/protocol.rb +86 -0
- data/lib/stream_weaver/canvas/reader.rb +853 -0
- data/lib/stream_weaver/canvas/save_doc_widget.rb +457 -0
- data/lib/stream_weaver/canvas/scroll_top_hint.rb +21 -0
- data/lib/stream_weaver/canvas/session.rb +132 -0
- data/lib/stream_weaver/cli.rb +3235 -0
- data/lib/stream_weaver/component_assets.rb +70 -0
- data/lib/stream_weaver/component_registry.rb +67 -0
- data/lib/stream_weaver/component_renderer.rb +48 -0
- data/lib/stream_weaver/components/annotated_code.rb +53 -0
- data/lib/stream_weaver/components/api_endpoint.rb +42 -0
- data/lib/stream_weaver/components/callout.rb +59 -0
- data/lib/stream_weaver/components/chart.rb +84 -0
- data/lib/stream_weaver/components/code_block.rb +77 -0
- data/lib/stream_weaver/components/comparison.rb +39 -0
- data/lib/stream_weaver/components/decision.rb +38 -0
- data/lib/stream_weaver/components/deck/close_overlay.rb +84 -0
- data/lib/stream_weaver/components/deck/confirmation_bar.rb +60 -0
- data/lib/stream_weaver/components/deck/deck_option.rb +61 -0
- data/lib/stream_weaver/components/deck/deck_slide.rb +77 -0
- data/lib/stream_weaver/components/deck/deck_state.rb +469 -0
- data/lib/stream_weaver/components/deck/deck_summary.rb +73 -0
- data/lib/stream_weaver/components/deck/design_deck.rb +60 -0
- data/lib/stream_weaver/components/deck/generate_more_controls.rb +84 -0
- data/lib/stream_weaver/components/deck/model_selector.rb +84 -0
- data/lib/stream_weaver/components/deck/skeleton_placeholder.rb +36 -0
- data/lib/stream_weaver/components/diff_block.rb +125 -0
- data/lib/stream_weaver/components/doc_header.rb +57 -0
- data/lib/stream_weaver/components/image_block.rb +70 -0
- data/lib/stream_weaver/components/implementation_map.rb +33 -0
- data/lib/stream_weaver/components/keyboard_shortcuts.rb +94 -0
- data/lib/stream_weaver/components/kpi_dashboard.rb +78 -0
- data/lib/stream_weaver/components/mermaid.rb +79 -0
- data/lib/stream_weaver/components/pipeline.rb +63 -0
- data/lib/stream_weaver/components/sidebar_toc.rb +46 -0
- data/lib/stream_weaver/components/slide_container.rb +141 -0
- data/lib/stream_weaver/components/timeline_event.rb +58 -0
- data/lib/stream_weaver/components/wireframe.rb +29 -0
- data/lib/stream_weaver/components/wireframe_block.rb +34 -0
- data/lib/stream_weaver/components.rb +2711 -0
- data/lib/stream_weaver/css.rb +230 -0
- data/lib/stream_weaver/dev_fallback_overlay.rb +61 -0
- data/lib/stream_weaver/display_dsl.rb +1004 -0
- data/lib/stream_weaver/export/html_exporter.rb +478 -0
- data/lib/stream_weaver/feed.rb +34 -0
- data/lib/stream_weaver/feed_builder.rb +31 -0
- data/lib/stream_weaver/fonts.rb +33 -0
- data/lib/stream_weaver/interaction_runner.rb +487 -0
- data/lib/stream_weaver/iterm.rb +460 -0
- data/lib/stream_weaver/layout_registry.rb +92 -0
- data/lib/stream_weaver/opal/bridge.rb +52 -0
- data/lib/stream_weaver/opal/builder.rb +193 -0
- data/lib/stream_weaver/opal/env.rb +29 -0
- data/lib/stream_weaver/opal/reactive_state.rb +75 -0
- data/lib/stream_weaver/opal/regexp_anchor_patch.rb +62 -0
- data/lib/stream_weaver/opal/renderer.rb +77 -0
- data/lib/stream_weaver/opal/runtime.rb +250 -0
- data/lib/stream_weaver/opal/shell.rb +145 -0
- data/lib/stream_weaver/opal/string_bridge.rb +50 -0
- data/lib/stream_weaver/opal/stubs/diff.min.js +1 -0
- data/lib/stream_weaver/opal/stubs/digest.rb +15 -0
- data/lib/stream_weaver/opal/stubs/marked.umd.js +79 -0
- data/lib/stream_weaver/opal/stubs/md5.rb +3 -0
- data/lib/stream_weaver/opal/stubs/morphdom.min.js +775 -0
- data/lib/stream_weaver/opal/stubs/prism-tomorrow.min.css +1 -0
- data/lib/stream_weaver/opal/stubs/prism.min.js +1967 -0
- data/lib/stream_weaver/opal_entry.rb +136 -0
- data/lib/stream_weaver/org/inline.rb +95 -0
- data/lib/stream_weaver/org/reader.rb +561 -0
- data/lib/stream_weaver/org/recording_context.rb +86 -0
- data/lib/stream_weaver/org/source_splitter.rb +63 -0
- data/lib/stream_weaver/org/writer.rb +300 -0
- data/lib/stream_weaver/page_shell.rb +530 -0
- data/lib/stream_weaver/portfile.rb +79 -0
- data/lib/stream_weaver/pushable.rb +42 -0
- data/lib/stream_weaver/resource/default_views.rb +111 -0
- data/lib/stream_weaver/resource/field_input.rb +25 -0
- data/lib/stream_weaver/resource/state_keys.rb +16 -0
- data/lib/stream_weaver/resource/store.rb +18 -0
- data/lib/stream_weaver/resource.rb +104 -0
- data/lib/stream_weaver/server.rb +1471 -0
- data/lib/stream_weaver/service.rb +1240 -0
- data/lib/stream_weaver/service_client.rb +104 -0
- data/lib/stream_weaver/session_store.rb +186 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/SKILL.md +66 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/examples/canvas-safe-showcase.rb +98 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/actions-and-buttons.md +47 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/charts-and-diagrams.md +38 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/deck.md +32 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/inputs-and-forms.md +65 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/tabs-and-navigation.md +53 -0
- data/lib/stream_weaver/skills/streamweaver-doc-builder/SKILL.md +298 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/SKILL.md +130 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example.css +468 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example.rb +39 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example_dsl.rb +300 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/doc-parity-example.rb +24 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/doc-parity-example_dsl.rb +385 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/checkpoints-and-forms.md +28 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/cleanup-and-panel.md +44 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/example-gallery.md +8 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/persistence.md +58 -0
- data/lib/stream_weaver/skills/streamweaver-way/SKILL.md +396 -0
- data/lib/stream_weaver/skills/visual-plan/SKILL.md +201 -0
- data/lib/stream_weaver/skills/visual-recap/SKILL.md +244 -0
- data/lib/stream_weaver/streamer.rb +63 -0
- data/lib/stream_weaver/templates/choices.rb +149 -0
- data/lib/stream_weaver/templates/code.rb +157 -0
- data/lib/stream_weaver/templates/confirm.rb +110 -0
- data/lib/stream_weaver/templates/diff.rb +195 -0
- data/lib/stream_weaver/templates/info.rb +142 -0
- data/lib/stream_weaver/templates/table.rb +169 -0
- data/lib/stream_weaver/templates/wizard.rb +271 -0
- data/lib/stream_weaver/theme/auto_mode.rb +116 -0
- data/lib/stream_weaver/theme/presets.rb +555 -0
- data/lib/stream_weaver/theme.rb +639 -0
- data/lib/stream_weaver/university/canvas.rb +924 -0
- data/lib/stream_weaver/university/course.rb +699 -0
- data/lib/stream_weaver/university/demos/counter.rb +33 -0
- data/lib/stream_weaver/university/demos/dashboard.rb +147 -0
- data/lib/stream_weaver/university/demos/decision_form.rb +143 -0
- data/lib/stream_weaver/university/demos.rb +50 -0
- data/lib/stream_weaver/university/listener.rb +467 -0
- data/lib/stream_weaver/university/progress.rb +201 -0
- data/lib/stream_weaver/university/runner.rb +138 -0
- data/lib/stream_weaver/university/scripts/growing_doc.rb +609 -0
- data/lib/stream_weaver/university/scripts/growing_doc_state.rb +91 -0
- data/lib/stream_weaver/utils.rb +31 -0
- data/lib/stream_weaver/version.rb +5 -0
- data/lib/stream_weaver/views/canvas/reader_layout.erb +800 -0
- data/lib/stream_weaver/views.rb +3940 -0
- data/lib/stream_weaver.rb +122 -0
- data/llms.txt +1269 -0
- data/sig/stream_weaver.rbs +4 -0
- metadata +598 -0
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
# Landscape Scan: Is There a "Hotwire for htmx/Alpine"?
|
|
2
|
+
|
|
3
|
+
Date: 2026-08-17
|
|
4
|
+
|
|
5
|
+
## Research question
|
|
6
|
+
|
|
7
|
+
Rails/Hotwire works as a system because the backend (REST resources, `dom_id`,
|
|
8
|
+
partials, scaffolding) and the frontend library (Turbo Frames/Streams,
|
|
9
|
+
Stimulus) were designed together by the same team, with shared conventions
|
|
10
|
+
and defined failure semantics. htmx and Alpine.js are deliberately
|
|
11
|
+
backend-agnostic transport/behavior libraries — they don't prescribe how your
|
|
12
|
+
server organizes routes, partials, or IDs. The hypothesis under test: **no
|
|
13
|
+
one has built the unifying "omakase" layer that gives htmx/Alpine the same
|
|
14
|
+
zero-custom-JS, convention-driven power Hotwire gives Rails.** This scan
|
|
15
|
+
verifies or refutes that hypothesis against the current (August 2026)
|
|
16
|
+
landscape.
|
|
17
|
+
|
|
18
|
+
## Method
|
|
19
|
+
|
|
20
|
+
Web search + primary-source reading across the projects most often cited as
|
|
21
|
+
"Hotwire-adjacent" for htmx/Alpine, plus a sweep for any 2024-2026 project
|
|
22
|
+
explicitly pitched as filling this gap. Findings below are organized by
|
|
23
|
+
project, then a verdict.
|
|
24
|
+
|
|
25
|
+
## Findings by project
|
|
26
|
+
|
|
27
|
+
### Alpine AJAX (imacrayon/alpine-ajax)
|
|
28
|
+
|
|
29
|
+
**What it is**: An Alpine.js plugin, explicitly Hotwire-inspired, that adds
|
|
30
|
+
`x-target`, `x-merge`, and similar attributes so links/forms can swap HTML
|
|
31
|
+
fragments without full-page reloads — Alpine's version of "AJAX navigation."
|
|
32
|
+
|
|
33
|
+
**Layer**: Transport + light conventions, framework-agnostic. It is an Alpine
|
|
34
|
+
plugin, not a full-stack system.
|
|
35
|
+
|
|
36
|
+
**Backend assumption**: None. The project's own comparison page states the
|
|
37
|
+
appeal directly — the server just needs to respond with plain HTML; no JSON
|
|
38
|
+
contract, no special response headers, no required framework. This is a
|
|
39
|
+
deliberate rejection of Turbo's approach, where Turbo requires the server to
|
|
40
|
+
distinguish "Turbo requests" from regular requests and often maintain two
|
|
41
|
+
templates.
|
|
42
|
+
|
|
43
|
+
**Opinionation**: Convention-over-configuration *within Alpine's own idiom*
|
|
44
|
+
(their docs literally use that phrase), but only at the DOM-targeting level —
|
|
45
|
+
which attribute swaps which fragment. It does not touch routing, resource
|
|
46
|
+
naming, model-to-partial mapping, or ID generation.
|
|
47
|
+
|
|
48
|
+
**What it lacks vs. Hotwire**:
|
|
49
|
+
- No `dom_id`-equivalent convention for naming targets consistently across
|
|
50
|
+
create/update/destroy responses.
|
|
51
|
+
- No Turbo Streams equivalent — no standard way to push multiple
|
|
52
|
+
out-of-band fragment updates from one response; Alpine AJAX instead relies
|
|
53
|
+
on custom JS/DOM events for anything beyond the single fragment a request
|
|
54
|
+
targets.
|
|
55
|
+
- No scaffolding/generator layer, no ActionCable-style broadcast integration,
|
|
56
|
+
no mobile-app bridge (Turbo Native has no analog here).
|
|
57
|
+
- No opinion on backend resource conventions at all — every project invents
|
|
58
|
+
its own routes/partials from scratch.
|
|
59
|
+
|
|
60
|
+
**Maturity**: Small, active, single-maintainer-driven; genuinely popular in
|
|
61
|
+
the Alpine niche but nowhere near Hotwire's ecosystem depth (generators,
|
|
62
|
+
gems, native bridges, broadcast helpers).
|
|
63
|
+
|
|
64
|
+
Sources: [Alpine AJAX comparisons](https://alpine-ajax.js.org/comparisons/), [htmx alternatives essay](https://htmx.org/essays/alternatives/)
|
|
65
|
+
|
|
66
|
+
### Datastar (data-star.dev)
|
|
67
|
+
|
|
68
|
+
**What it is**: A from-scratch hypermedia framework (~11KB) that merges
|
|
69
|
+
htmx-style backend-driven DOM patching with Alpine-style client-side
|
|
70
|
+
reactive state ("signals"), unified around Server-Sent Events as the
|
|
71
|
+
transport. Originally conceived as a TypeScript rewrite of htmx before
|
|
72
|
+
becoming an independent project.
|
|
73
|
+
|
|
74
|
+
**Layer**: This is the most ambitious of the group — it operates as
|
|
75
|
+
*transport + client reactivity* in one package, explicitly positioning
|
|
76
|
+
itself as a replacement for *both* htmx and Alpine simultaneously, not a
|
|
77
|
+
layer on top of them.
|
|
78
|
+
|
|
79
|
+
**Backend assumption**: None fixed, but strongly SSE-centric — "the backend
|
|
80
|
+
is the source of truth for state," and the framework expects your server to
|
|
81
|
+
emit signal/fragment updates as an SSE stream rather than one-shot HTTP
|
|
82
|
+
responses. It has moved to JSON-in for form/event data (a deliberate
|
|
83
|
+
departure from htmx's FormData-first model) and ships a `ServerSentEventGenerator`
|
|
84
|
+
convention that every SDK re-implements per language, which is the closest
|
|
85
|
+
thing to a cross-language shared convention in this whole landscape.
|
|
86
|
+
|
|
87
|
+
**Opinionation**: Moderate-to-high at the *protocol* level (SSE events,
|
|
88
|
+
signal naming, `data-*` attribute vocabulary) but zero at the *backend
|
|
89
|
+
architecture* level — no resource/routing/partial conventions, no
|
|
90
|
+
scaffolding. Official SDKs exist for Go, Python, Rust, Ruby, PHP, .NET,
|
|
91
|
+
Java, Kotlin, Clojure and more, each providing the SSE-generator primitive,
|
|
92
|
+
but none prescribe how you structure a full application (no equivalent to
|
|
93
|
+
Rails controllers/resources, no generators).
|
|
94
|
+
|
|
95
|
+
**What it lacks vs. Hotwire**:
|
|
96
|
+
- Pre-1.0 (RC as of this scan) — explicitly unstable, "not yet a complete
|
|
97
|
+
full-stack opinionated ecosystem comparable to Rails" by its own author's
|
|
98
|
+
framing.
|
|
99
|
+
- No backend framework of its own — it's a client+protocol layer that any
|
|
100
|
+
backend can target, same category gap as htmx.
|
|
101
|
+
- No scaffolding/generators, no resource-naming or `dom_id` convention, no
|
|
102
|
+
official ORM/partial-rendering integration.
|
|
103
|
+
- Community/ecosystem is much younger and smaller than Turbo's.
|
|
104
|
+
|
|
105
|
+
**Maturity**: Fast-growing mindshare in the htmx-adjacent community as of
|
|
106
|
+
2026, praised for being "one ~11KB library instead of htmx+Alpine," but
|
|
107
|
+
still pre-1.0 and without full-stack scaffolding.
|
|
108
|
+
|
|
109
|
+
Sources: [Why another framework?](https://data-star.dev/essays/why_another_framework), [Datastar SDKs reference](https://data-star.dev/reference/sdks), [htmx alternatives essay](https://htmx.org/essays/alternatives/)
|
|
110
|
+
|
|
111
|
+
### Unpoly
|
|
112
|
+
|
|
113
|
+
**What it is**: The oldest and most mature entrant here — a
|
|
114
|
+
progressive-enhancement library (10+ years old, heavily used in the Ruby
|
|
115
|
+
community pre-dating Hotwire) that intercepts links/forms and swaps HTML
|
|
116
|
+
fragments, with a genuinely sophisticated **layers** system (modals,
|
|
117
|
+
drawers, popups as first-class navigation layers) that goes beyond what
|
|
118
|
+
Turbo Frames offers.
|
|
119
|
+
|
|
120
|
+
**Layer**: Transport + fairly deep conventions at the fragment-targeting and
|
|
121
|
+
navigation-layer level. Closest philosophical cousin to Turbo of anything in
|
|
122
|
+
this scan — multiple comparison sources use the analogy "htmx is to Unpoly
|
|
123
|
+
as Django is to Rails," i.e., Unpoly is the more convention-driven, batteries-included
|
|
124
|
+
member of the htmx-adjacent family.
|
|
125
|
+
|
|
126
|
+
**Backend assumption**: Explicitly none — works with "any language," plain
|
|
127
|
+
HTML in, no special headers required by default (though it offers optional
|
|
128
|
+
headers for smarter responses). This is the same trade Alpine AJAX makes:
|
|
129
|
+
buy convention on the client, ask nothing of the server.
|
|
130
|
+
|
|
131
|
+
**Opinionation**: Highest of the transport-layer libraries surveyed — built-in
|
|
132
|
+
scroll-position preservation, form validation-without-reload, caching,
|
|
133
|
+
preloading, and true nested layers (Turbo can only approximate nesting by
|
|
134
|
+
re-rendering frames). But again, *zero* backend/resource conventions —
|
|
135
|
+
no scaffolding, no `dom_id` equivalent, no generator ecosystem. One comparison
|
|
136
|
+
source frames the trade directly: Unpoly requires "almost no training" and
|
|
137
|
+
no server cooperation, in exchange for less architectural guidance than
|
|
138
|
+
Hotwire gives a Rails app.
|
|
139
|
+
|
|
140
|
+
**What it lacks vs. Hotwire**: No resource/routing conventions, no
|
|
141
|
+
scaffolding/generators, no broadcast (ActionCable-equivalent) integration,
|
|
142
|
+
no mobile bridge. It solves the *frontend* half of Hotwire's value
|
|
143
|
+
proposition very well and does not attempt the backend half at all.
|
|
144
|
+
|
|
145
|
+
**Maturity**: High — long track record, stable API, real production usage
|
|
146
|
+
predating the htmx/Hotwire split. The most mature project in this scan by
|
|
147
|
+
calendar age.
|
|
148
|
+
|
|
149
|
+
Sources: [unpoly.com](https://unpoly.com/), [Hotwire vs HTMX vs Unpoly](https://www.mendelowski.com/blog/2024/11/hotwire-htmx-unpoly), [Alpine AJAX comparisons](https://alpine-ajax.js.org/comparisons/)
|
|
150
|
+
|
|
151
|
+
### Backend-side "omakase" attempts
|
|
152
|
+
|
|
153
|
+
These are the projects that take the opposite approach from Alpine AJAX/Datastar/Unpoly:
|
|
154
|
+
instead of building a smarter client, they build an opinionated *backend*
|
|
155
|
+
around plain htmx.
|
|
156
|
+
|
|
157
|
+
| Project | Backend | What it prescribes | Gap vs. Hotwire |
|
|
158
|
+
|---|---|---|---|
|
|
159
|
+
| Loco.rs | Rust | Rails-inspired full-stack framework (routes, models, jobs, CLI) with `cargo loco generate scaffold --htmx` producing CRUD views wired to htmx | No fragment-update protocol equivalent to Turbo Streams; scaffolds views but doesn't define a shared `dom_id`/broadcast convention |
|
|
160
|
+
| FastHTML (Python) | Starlette/ASGI | Python objects *are* HTML elements; htmx bundled by default; encourages server-driven interactivity with minimal JS | No resource/REST scaffolding comparable to Rails; conventions are about Python-as-HTML ergonomics, not app architecture |
|
|
161
|
+
| Django + django-htmx / django-htmx-patterns | Django | Documented *patterns* (separate-partials, inline-partials) for structuring views/templates around htmx requests | These are community pattern docs, not a shipped convention layer — every team still hand-rolls the plumbing; explicitly flags the "locality of behaviour" problem Hotwire's `dom_id` + partials solve natively |
|
|
162
|
+
| turbo-laravel (Hotwired-Laravel) | Laravel | Literally a Turbo/Turbo Streams port for Laravel — closest thing to "Rails' actual conventions, transplanted" | Not htmx-based at all — it's Hotwire itself ported to another backend, which supports the paper's premise rather than refuting it |
|
|
163
|
+
| Laravel Livewire | Laravel | Full component-based reactive framework (closer to LiveView than Hotwire) | Different paradigm entirely — server-rendered stateful components, not a hypermedia/htmx layer |
|
|
164
|
+
| Ruby: htmx-rails / rails-htmx gems | Rails | Thin helpers for including htmx script tags and reading htmx request headers in Rails | Genuinely minimal — no scaffolding, no conventions beyond header detection; nowhere near Turbo-rails' depth |
|
|
165
|
+
| Go + Templ + htmx "stack" | Go (Echo/Chi + Templ) | Community-standardized *stack* (Templ for typed templates, sqlc, htmx, Tailwind) reused across many starter templates | A popular stack, not a framework — no shared project prescribes resource/fragment conventions; every starter kit reinvents its own partial/target naming |
|
|
166
|
+
|
|
167
|
+
None of these back-end-side efforts reach parity with `turbo-rails` (the
|
|
168
|
+
actual Rails gem), which provides `dom_id`, `broadcasts_to`, automatic
|
|
169
|
+
Turbo Stream responses from `respond_to`, and scaffolding that wires all of
|
|
170
|
+
it together. The closest analog to "Hotwire's actual conventions" is
|
|
171
|
+
**turbo-laravel**, and it works by porting Hotwire itself rather than
|
|
172
|
+
building an equivalent for htmx.
|
|
173
|
+
|
|
174
|
+
Sources: [Loco.rs htmx casts](https://loco.rs/casts/007-htmx/), [FastHTML overview](https://mikelev.in/futureproof/fast-html-framework-opinions/), [django-htmx-patterns](https://github.com/spookylukey/django-htmx-patterns), [turbo-laravel](https://github.com/hotwired-laravel/turbo-laravel), [htmx-rails gem](https://rubygems.org/gems/htmx-rails)
|
|
175
|
+
|
|
176
|
+
### Different-mechanism cousins (worth noting, not competing directly)
|
|
177
|
+
|
|
178
|
+
**Phoenix LiveView** achieves Hotwire's "no custom JS" promise via a
|
|
179
|
+
fundamentally different mechanism: persistent per-connection server
|
|
180
|
+
processes and stateful diffing over WebSockets, rather than stateless HTML
|
|
181
|
+
fragments over HTTP. It *is* a fully opinionated, single-vendor,
|
|
182
|
+
backend+frontend co-designed system — arguably the strongest existing
|
|
183
|
+
counter-example to "no one builds these anymore" — but it isn't htmx/Alpine
|
|
184
|
+
at all, and its statefulness (one live process per user) is a different
|
|
185
|
+
operational model than Hotwire's stateless-server / stateful-browser split.
|
|
186
|
+
It's evidence that the *idea* of an omakase hypermedia system is alive, just
|
|
187
|
+
not manifesting on top of htmx or Alpine specifically.
|
|
188
|
+
|
|
189
|
+
Sources: [Hotwire vs Phoenix LiveView (HN)](https://news.ycombinator.com/item?id=25510116), [Benjamin Oakes: Hotwire vs LiveView](http://www.benjaminoakes.com/programming/2021/05/19/Hotwire-by-Basecamp-vs-Phoenix-LiveView/)
|
|
190
|
+
|
|
191
|
+
### Hypermedia Systems (the book, Carson Gross et al.)
|
|
192
|
+
|
|
193
|
+
The book is explicitly a *philosophy and technique* text, not a framework
|
|
194
|
+
spec. It teaches HATEOAS principles and htmx/Hyperview patterns through
|
|
195
|
+
worked examples, and is candid that this is "HTML/XML/hypermedia purism" —
|
|
196
|
+
some reviewers find it prescriptive in *values* (favor hypermedia over
|
|
197
|
+
JSON APIs, keep state on the server) but it does not prescribe a concrete
|
|
198
|
+
convention set (no canonical partial-naming scheme, no scaffolding spec).
|
|
199
|
+
It leaves "how do I structure my Django/Rails/Express app around this" as
|
|
200
|
+
an exercise for the reader — which is itself evidence for the hypothesis:
|
|
201
|
+
even htmx's own creator's book stops short of shipping the Hotwire-style
|
|
202
|
+
opinionated backend layer.
|
|
203
|
+
|
|
204
|
+
Sources: [Hypermedia Systems book review](https://acritelli.medium.com/book-review-hypermedia-systems-65a9379767cf), [Ben Nadel's review](https://www.bennadel.com/blog/4769-hypermedia-systems-by-carson-gross.htm)
|
|
205
|
+
|
|
206
|
+
### Explicit "Hotwire for htmx" pitches
|
|
207
|
+
|
|
208
|
+
A targeted search for projects explicitly marketed as "Hotwire alternative
|
|
209
|
+
for htmx" or "Rails-like conventions for hypermedia apps" turned up nothing
|
|
210
|
+
new in 2024-2026 beyond the projects already covered above. The framing
|
|
211
|
+
that keeps recurring across independent comparison articles is the same
|
|
212
|
+
Django/Rails analogy: **htmx ≈ Django (flexible, minimal-opinion), Unpoly ≈
|
|
213
|
+
Rails (convention-rich, still backend-agnostic)** — but even that framing is
|
|
214
|
+
about frontend/transport conventions, not the backend-resource conventions
|
|
215
|
+
that make Hotwire+Rails a single designed system.
|
|
216
|
+
|
|
217
|
+
## Verdict
|
|
218
|
+
|
|
219
|
+
**The hypothesis holds.** No project currently occupies the "Hotwire-grade
|
|
220
|
+
omakase layer over htmx/Alpine" slot — the slot that requires *both* a
|
|
221
|
+
convention-rich frontend behavior layer *and* a co-designed backend
|
|
222
|
+
convention set (resource naming, partial/`dom_id` mapping, scaffolding,
|
|
223
|
+
broadcast integration) shipped as one opinionated system, the way
|
|
224
|
+
`turbo-rails` + Rails scaffolding + Turbo/Stimulus are one thing from one
|
|
225
|
+
team.
|
|
226
|
+
|
|
227
|
+
What exists instead is a landscape split cleanly along the fault line the
|
|
228
|
+
premise predicts:
|
|
229
|
+
|
|
230
|
+
- **Frontend-side convention layers** (Alpine AJAX, Datastar, Unpoly) each
|
|
231
|
+
add real opinion about DOM-targeting and swap semantics, but explicitly
|
|
232
|
+
and proudly ask *nothing* of the backend — that's their whole pitch versus
|
|
233
|
+
Turbo. This is a deliberate design choice, not an oversight: it's what
|
|
234
|
+
lets them claim "works with any backend."
|
|
235
|
+
- **Backend-side attempts** (Loco.rs scaffolding, FastHTML, django-htmx
|
|
236
|
+
patterns, Go+Templ starter stacks) add real opinion about server code
|
|
237
|
+
structure, but none of them define the missing middle piece — a shared,
|
|
238
|
+
cross-project convention for how server-rendered fragments get IDed,
|
|
239
|
+
targeted, and multiplexed the way `dom_id` + Turbo Streams do together.
|
|
240
|
+
- The one project that *did* port Hotwire's actual conventions to a new
|
|
241
|
+
backend (turbo-laravel) did it by transplanting Hotwire itself, not by
|
|
242
|
+
building an htmx-based equivalent — which is arguably confirmation rather
|
|
243
|
+
than refutation.
|
|
244
|
+
- Phoenix LiveView proves the *appetite* for a fully co-designed,
|
|
245
|
+
zero-custom-JS omakase system is real and satisfiable — just not via
|
|
246
|
+
htmx/Alpine's request/response model.
|
|
247
|
+
|
|
248
|
+
**Closest approaches, ranked:**
|
|
249
|
+
1. **Unpoly** — most mature, most opinionated at the transport/DOM layer,
|
|
250
|
+
closest "feel" to Turbo, but zero backend conventions by design.
|
|
251
|
+
2. **Datastar** — most technically ambitious unification of htmx+Alpine
|
|
252
|
+
into one coherent protocol (SSE + signals), with the beginnings of a
|
|
253
|
+
cross-language shared convention (the SDK `ServerSentEventGenerator`
|
|
254
|
+
pattern) — but pre-1.0 and still backend-architecture-agnostic.
|
|
255
|
+
3. **Loco.rs's `--htmx` scaffolding** — the only project that ships an
|
|
256
|
+
actual Rails-style generator producing wired-up htmx views, but it's
|
|
257
|
+
scoped to one young Rust framework and doesn't define a portable
|
|
258
|
+
fragment/ID convention others could adopt.
|
|
259
|
+
|
|
260
|
+
**Remaining gap**: nobody has shipped the htmx/Alpine equivalent of
|
|
261
|
+
`dom_id` + `broadcasts_to` + scaffold-generated Turbo Stream responses —
|
|
262
|
+
a small, named, cross-project convention for "how a fragment gets an ID,
|
|
263
|
+
how a create/update/destroy action knows which fragments to patch, and how
|
|
264
|
+
that travels over the wire" that a backend framework and a frontend library
|
|
265
|
+
could both implement once and share. Every project surveyed either declines
|
|
266
|
+
to specify that convention (frontend-side libraries, by design) or invents
|
|
267
|
+
its own local, non-portable version of it (backend-side scaffolding
|
|
268
|
+
attempts).
|