@tutorialkit-rb/cli 0.1.5 → 0.1.7

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.
Files changed (185) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +1 -1
  3. package/template/.claude/skills/rails-file-management/SKILL.md +211 -0
  4. package/template/.claude/skills/rails-lesson-recipes/SKILL.md +415 -0
  5. package/template/.claude/skills/rails-wasm-author-constraints/SKILL.md +181 -0
  6. package/template/.claude/skills/tutorial-content-structure/SKILL.md +377 -0
  7. package/template/.claude/skills/tutorial-lesson-config/SKILL.md +389 -0
  8. package/template/.claude/skills/tutorial-quickstart/SKILL.md +440 -0
  9. package/template/.github/workflows/deploy.yml +85 -0
  10. package/template/.gitignore +10 -0
  11. package/template/CLAUDE.md +47 -0
  12. package/template/astro.config.ts +12 -0
  13. package/template/bin/build-pack +84 -0
  14. package/template/bin/build-ruby-base +180 -0
  15. package/template/bin/link-local +13 -0
  16. package/template/bin/unlink-local +7 -0
  17. package/template/cors-proxy/README.md +63 -0
  18. package/template/cors-proxy/package-lock.json +1504 -0
  19. package/template/cors-proxy/package.json +12 -0
  20. package/template/cors-proxy/src/index.ts +87 -0
  21. package/template/cors-proxy/wrangler.toml +7 -0
  22. package/template/netlify.toml +9 -0
  23. package/template/package.json +12 -4
  24. package/template/ruby-wasm/Gemfile +6 -0
  25. package/template/ruby-wasm/Gemfile.base +19 -0
  26. package/template/ruby-wasm/Gemfile.base.lock +50 -0
  27. package/template/ruby-wasm/Gemfile.lock +8 -0
  28. package/template/ruby-wasm/bin/pack-gems +368 -0
  29. package/template/ruby-wasm/package.json +6 -0
  30. package/template/src/components/FileManager.tsx +33 -0
  31. package/template/src/components/HeadTags.astro +6 -6
  32. package/template/src/components/HelpDropdown.tsx +1 -1
  33. package/template/src/components/RailsPathLinkHandler.tsx +2 -2
  34. package/template/src/components/ShellConfigurator.tsx +6 -1
  35. package/template/src/content/tutorial/1-getting-started/1-creating-your-first-rails-app/content.md +4 -4
  36. package/template/src/content/tutorial/1-getting-started/2-rails-console/content.md +4 -4
  37. package/template/src/content/tutorial/2-controllers/2-crud-operations/content.md +2 -2
  38. package/template/src/content/tutorial/9-outbound-http/1-making-http-requests/_files/.tk-config.json +3 -0
  39. package/template/src/content/tutorial/9-outbound-http/1-making-http-requests/_files/workspace/app/controllers/http_demo_controller.rb +65 -0
  40. package/template/src/content/tutorial/9-outbound-http/1-making-http-requests/_files/workspace/app/views/http_demo/index.html.erb +172 -0
  41. package/template/src/content/tutorial/9-outbound-http/1-making-http-requests/_files/workspace/config/routes.rb +8 -0
  42. package/template/src/content/tutorial/9-outbound-http/1-making-http-requests/content.md +97 -0
  43. package/template/src/content/tutorial/9-outbound-http/meta.md +4 -0
  44. package/template/src/content/tutorial/meta.md +5 -0
  45. package/template/src/middleware.ts +14 -0
  46. package/template/src/templates/default/lib/boot-progress.js +49 -0
  47. package/template/src/templates/default/lib/http-bridge.js +55 -0
  48. package/template/src/templates/default/lib/patches/http_bridge.rb +167 -0
  49. package/template/src/templates/default/lib/rails.js +52 -5
  50. package/template/src/templates/default/lib/server.js +33 -1
  51. package/template/src/templates/default/package.json +4 -1
  52. package/template/src/templates/default/scripts/rails.js +1 -1
  53. package/template/src/templates/default/scripts/smoke-test.js +349 -0
  54. package/template/src/templates/default/scripts/wasi-loader.mjs +10 -0
  55. package/template/src/templates/default/workspace/_debug_app/.github/dependabot.yml +12 -0
  56. package/template/src/templates/default/workspace/_debug_app/.github/workflows/ci.yml +51 -0
  57. package/template/src/templates/default/workspace/_debug_app/.ruby-version +1 -0
  58. package/template/src/templates/default/workspace/_debug_app/Gemfile +37 -0
  59. package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/views/layouts/application.html.erb +1 -2
  60. package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/views/pwa/manifest.json.erb +2 -2
  61. package/template/src/templates/default/workspace/_debug_app/bin/dev +2 -0
  62. package/template/src/templates/default/workspace/_debug_app/bin/rake +4 -0
  63. package/template/src/templates/default/workspace/_debug_app/bin/setup +34 -0
  64. package/template/src/templates/default/workspace/_debug_app/config/application.rb +30 -0
  65. package/template/src/templates/default/workspace/_debug_app/config/cable.yml +10 -0
  66. package/template/src/templates/default/workspace/_debug_app/config/credentials.yml.enc +1 -0
  67. package/template/src/templates/default/workspace/_debug_app/config/master.key +1 -0
  68. package/template/src/templates/default/workspace/_debug_app/config/routes.rb +14 -0
  69. package/template/src/templates/default/workspace/_debug_app/test/models/.keep +0 -0
  70. package/template/src/templates/default/workspace/_debug_app/test/test_helper.rb +15 -0
  71. package/template/src/templates/default/workspace/_debug_app/tmp/.keep +0 -0
  72. package/template/src/templates/default/workspace/_debug_app/tmp/pids/.keep +0 -0
  73. package/template/src/templates/default/workspace/_debug_app/tmp/storage/.keep +0 -0
  74. package/template/src/templates/default/workspace/_debug_app/vendor/.keep +0 -0
  75. package/template/src/templates/rails-app/workspace/README.md +24 -0
  76. package/template/src/templates/rails-app/workspace/Rakefile +6 -0
  77. package/template/src/templates/rails-app/workspace/app/assets/images/.keep +0 -0
  78. package/template/src/templates/rails-app/workspace/app/assets/stylesheets/application.css +534 -0
  79. package/template/src/templates/rails-app/workspace/app/controllers/application_controller.rb +2 -0
  80. package/template/src/templates/rails-app/workspace/app/helpers/application_helper.rb +2 -0
  81. package/template/src/templates/rails-app/workspace/app/jobs/application_job.rb +7 -0
  82. package/template/src/templates/rails-app/workspace/app/mailers/application_mailer.rb +4 -0
  83. package/template/src/templates/rails-app/workspace/app/models/application_record.rb +3 -0
  84. package/template/src/templates/rails-app/workspace/app/models/concerns/.keep +0 -0
  85. package/template/src/templates/rails-app/workspace/app/views/layouts/application.html.erb +38 -0
  86. package/template/src/templates/rails-app/workspace/app/views/layouts/mailer.html.erb +13 -0
  87. package/template/src/templates/rails-app/workspace/app/views/layouts/mailer.text.erb +1 -0
  88. package/template/src/templates/rails-app/workspace/bin/rails +4 -0
  89. package/template/src/templates/rails-app/workspace/{store/config → config}/application.rb +1 -1
  90. package/template/src/templates/rails-app/workspace/config/boot.rb +3 -0
  91. package/template/src/templates/rails-app/workspace/config/database.yml +32 -0
  92. package/template/src/templates/rails-app/workspace/config/environment.rb +5 -0
  93. package/template/src/templates/rails-app/workspace/config/environments/development.rb +69 -0
  94. package/template/src/templates/rails-app/workspace/config/environments/production.rb +89 -0
  95. package/template/src/templates/rails-app/workspace/config/environments/test.rb +54 -0
  96. package/template/src/templates/rails-app/workspace/config/initializers/assets.rb +7 -0
  97. package/template/src/templates/rails-app/workspace/config/initializers/content_security_policy.rb +25 -0
  98. package/template/src/templates/rails-app/workspace/config/initializers/filter_parameter_logging.rb +8 -0
  99. package/template/src/templates/rails-app/workspace/config/initializers/inflections.rb +16 -0
  100. package/template/src/templates/rails-app/workspace/config/locales/en.yml +31 -0
  101. package/template/src/templates/rails-app/workspace/config/puma.rb +41 -0
  102. package/template/src/templates/rails-app/workspace/{store/config → config}/routes.rb +1 -1
  103. package/template/src/templates/rails-app/workspace/config/storage.yml +34 -0
  104. package/template/src/templates/rails-app/workspace/config.ru +6 -0
  105. package/template/src/templates/rails-app/workspace/db/seeds.rb +9 -0
  106. package/template/src/templates/rails-app/workspace/log/.keep +0 -0
  107. package/template/src/templates/rails-app/workspace/public/400.html +114 -0
  108. package/template/src/templates/rails-app/workspace/public/404.html +114 -0
  109. package/template/src/templates/rails-app/workspace/public/406-unsupported-browser.html +114 -0
  110. package/template/src/templates/rails-app/workspace/public/422.html +114 -0
  111. package/template/src/templates/rails-app/workspace/public/500.html +114 -0
  112. package/template/src/templates/rails-app/workspace/public/icon.png +0 -0
  113. package/template/src/templates/rails-app/workspace/public/icon.svg +3 -0
  114. package/template/src/templates/rails-app/workspace/public/robots.txt +1 -0
  115. package/template/src/templates/rails-app/workspace/script/.keep +0 -0
  116. package/template/src/templates/rails-app/workspace/storage/.keep +0 -0
  117. package/template/src/templates/rails-app/workspace/test/controllers/.keep +0 -0
  118. package/template/src/templates/rails-app/workspace/test/helpers/.keep +0 -0
  119. package/template/src/templates/rails-app/workspace/test/integration/.keep +0 -0
  120. package/template/src/templates/rails-app/workspace/tmp/.keep +0 -0
  121. package/template/src/templates/rails-app/workspace/tmp/cache/.keep +0 -0
  122. package/template/src/templates/rails-app/workspace/tmp/pids/.keep +0 -0
  123. package/template/src/templates/rails-app/workspace/tmp/sockets/.keep +0 -0
  124. package/template/src/templates/rails-app/workspace/tmp/storage/.keep +0 -0
  125. package/template/src/templates/rails-app/workspace/vendor/javascripts/.keep +0 -0
  126. package/template/tsconfig.json +3 -1
  127. package/template/uno.config.ts +17 -0
  128. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/README.md +0 -0
  129. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/Rakefile +0 -0
  130. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/assets/images/.keep +0 -0
  131. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/assets/stylesheets/application.css +0 -0
  132. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/controllers/application_controller.rb +0 -0
  133. /package/template/src/templates/{rails-app/workspace/store/app/models → default/workspace/_debug_app/app/controllers}/concerns/.keep +0 -0
  134. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/helpers/application_helper.rb +0 -0
  135. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/jobs/application_job.rb +0 -0
  136. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/mailers/application_mailer.rb +0 -0
  137. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/models/application_record.rb +0 -0
  138. /package/template/src/templates/{rails-app/workspace/store/log → default/workspace/_debug_app/app/models/concerns}/.keep +0 -0
  139. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/views/layouts/mailer.html.erb +0 -0
  140. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/views/layouts/mailer.text.erb +0 -0
  141. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/views/pwa/service-worker.js +0 -0
  142. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/bin/rails +0 -0
  143. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/boot.rb +0 -0
  144. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/database.yml +0 -0
  145. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/environment.rb +0 -0
  146. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/environments/development.rb +0 -0
  147. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/environments/production.rb +0 -0
  148. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/environments/test.rb +0 -0
  149. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/initializers/assets.rb +0 -0
  150. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/initializers/content_security_policy.rb +0 -0
  151. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/initializers/filter_parameter_logging.rb +0 -0
  152. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/initializers/inflections.rb +0 -0
  153. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/locales/en.yml +0 -0
  154. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/puma.rb +0 -0
  155. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/storage.yml +0 -0
  156. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config.ru +0 -0
  157. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/db/seeds.rb +0 -0
  158. /package/template/src/templates/{rails-app/workspace/store/script → default/workspace/_debug_app/lib/tasks}/.keep +0 -0
  159. /package/template/src/templates/{rails-app/workspace/store/storage → default/workspace/_debug_app/log}/.keep +0 -0
  160. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/400.html +0 -0
  161. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/404.html +0 -0
  162. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/406-unsupported-browser.html +0 -0
  163. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/422.html +0 -0
  164. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/500.html +0 -0
  165. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/icon.png +0 -0
  166. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/icon.svg +0 -0
  167. /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/robots.txt +0 -0
  168. /package/template/src/templates/{rails-app/workspace/store/test/controllers → default/workspace/_debug_app/script}/.keep +0 -0
  169. /package/template/src/templates/{rails-app/workspace/store/test/helpers → default/workspace/_debug_app/storage}/.keep +0 -0
  170. /package/template/src/templates/{rails-app/workspace/store/test/integration → default/workspace/_debug_app/test/controllers}/.keep +0 -0
  171. /package/template/src/templates/{rails-app/workspace/store/tmp → default/workspace/_debug_app/test/fixtures/files}/.keep +0 -0
  172. /package/template/src/templates/{rails-app/workspace/store/tmp/pids → default/workspace/_debug_app/test/helpers}/.keep +0 -0
  173. /package/template/src/templates/{rails-app/workspace/store/tmp/storage → default/workspace/_debug_app/test/integration}/.keep +0 -0
  174. /package/template/src/templates/{rails-app/workspace/store/vendor/javascripts → default/workspace/_debug_app/test/mailers}/.keep +0 -0
  175. /package/template/src/templates/rails-app/workspace/{store/.ruby-version → .ruby-version} +0 -0
  176. /package/template/src/templates/rails-app/workspace/{store/Gemfile → Gemfile} +0 -0
  177. /package/template/src/templates/rails-app/workspace/{store/app → app}/javascript/application.js +0 -0
  178. /package/template/src/templates/rails-app/workspace/{store/app → app}/javascript/controllers/application.js +0 -0
  179. /package/template/src/templates/rails-app/workspace/{store/app → app}/javascript/controllers/index.js +0 -0
  180. /package/template/src/templates/rails-app/workspace/{store/bin → bin}/importmap +0 -0
  181. /package/template/src/templates/rails-app/workspace/{store/config → config}/cable.yml +0 -0
  182. /package/template/src/templates/rails-app/workspace/{store/config → config}/credentials.yml.enc +0 -0
  183. /package/template/src/templates/rails-app/workspace/{store/config → config}/importmap.rb +0 -0
  184. /package/template/src/templates/rails-app/workspace/{store/config → config}/master.key +0 -0
  185. /package/template/src/templates/rails-app/workspace/{store/test → test}/test_helper.rb +0 -0
@@ -0,0 +1,440 @@
1
+ ---
2
+ name: tutorial-quickstart
3
+ description: |
4
+ Use this skill whenever starting a new tutorial project, understanding the end-to-end
5
+ workflow from scaffold to deployment, or working with the rails-app template's built-in
6
+ features. Trigger when the user says 'new tutorial', 'create tutorial', 'getting started',
7
+ 'npx create-tutorialkit-rb', 'scaffold', 'first lesson', 'deploy tutorial', 'build:wasm',
8
+ 'COEP headers', 'COOP headers', 'hosting setup', 'CSS classes', 'BEM components',
9
+ 'design system', 'application.css', 'customize demo app', 'rails-app template',
10
+ 'branding', 'logo', 'favicon', 'accent color', 'theme color', 'look and feel',
11
+ 'customize colors', or asks how to set up, build, style, brand, or deploy a Rails
12
+ tutorial from scratch — even if they don't explicitly mention quickstart. This skill
13
+ provides the exact CLI commands, project structure, WASM build steps, rails-app template
14
+ features (CSS design system, layout), branding customization (logos, favicons, accent
15
+ colors, top bar title, component colors), demo app customization steps, deployment header
16
+ configuration, and common issue troubleshooting. Do NOT attempt project setup or deployment
17
+ without this skill. Do NOT use for detailed frontmatter reference (use tutorial-lesson-config)
18
+ or WASM compatibility questions (use rails-wasm-author-constraints).
19
+ ---
20
+
21
+ # Tutorial Quickstart
22
+
23
+ End-to-end guide: scaffold a project, write your first lesson, and deploy.
24
+
25
+ ## Step 1: Scaffold
26
+
27
+ ```bash
28
+ npx create-tutorialkit-rb my-tutorial
29
+ ```
30
+
31
+ The CLI prompts for:
32
+
33
+ | Prompt | Default | Notes |
34
+ |--------|---------|-------|
35
+ | Tutorial name | random (e.g., "fierce-turtle") | Used as `package.json` name |
36
+ | Directory | `./{name}` | Where files are created |
37
+ | Hosting provider | Skip | Vercel, Netlify, or Cloudflare — adds COEP/COOP headers |
38
+ | Package manager | npm | npm, yarn, pnpm, or bun |
39
+ | Init git repo? | Yes | Creates initial commit |
40
+ | Edit Gemfile? | Yes | Opens `ruby-wasm/Gemfile` in `$EDITOR` |
41
+
42
+ Skip all prompts with `--defaults`, or pass flags directly:
43
+
44
+ ```bash
45
+ npx create-tutorialkit-rb my-tutorial -p pnpm --provider netlify --git
46
+ ```
47
+
48
+ ### What Gets Created
49
+
50
+ ```
51
+ my-tutorial/
52
+ ├── src/
53
+ │ ├── content/tutorial/ ← Your tutorial content goes here
54
+ │ │ ├── meta.md ← Tutorial root config (already set up)
55
+ │ │ └── 1-getting-started/ ← Sample part with starter lessons
56
+ │ ├── templates/default/ ← WebContainer runtime (don't modify)
57
+ │ └── components/ ← UI components
58
+ ├── ruby-wasm/
59
+ │ └── Gemfile ← Add gems here, then rebuild WASM
60
+ ├── bin/build-wasm ← Rebuilds the WASM binary
61
+ ├── astro.config.ts
62
+ └── package.json
63
+ ```
64
+
65
+ ## Step 2: Add Your Gems
66
+
67
+ Edit `ruby-wasm/Gemfile` to include the gems your tutorial needs:
68
+
69
+ ```ruby
70
+ # ruby-wasm/Gemfile
71
+ source "https://rubygems.org"
72
+
73
+ gem "wasmify-rails", "~> 0.4.0"
74
+ gem "rails", "~> 8.0.0"
75
+
76
+ # Your tutorial's gems
77
+ gem "action_policy"
78
+ gem "devise"
79
+ ```
80
+
81
+ Then build the WASM binary:
82
+
83
+ ```bash
84
+ npm run build:wasm # Takes up to 20 minutes on first run
85
+ ```
86
+
87
+ Subsequent rebuilds are faster thanks to caching, but still take a few minutes.
88
+
89
+ ## Step 3: Start the Dev Server
90
+
91
+ ```bash
92
+ npm run dev # Starts at http://localhost:4321/
93
+ ```
94
+
95
+ The sample tutorial loads immediately. You'll see the starter lessons from the scaffold.
96
+
97
+ ## Step 4: Write Your First Lesson
98
+
99
+ ### 4a. Create the Directory Structure
100
+
101
+ ```
102
+ src/content/tutorial/
103
+ ├── meta.md ← Already exists (tutorial root)
104
+ └── 1-basics/
105
+ ├── meta.md ← Part metadata
106
+ └── 1-hello-rails/
107
+ ├── content.md ← Your lesson
108
+ ├── _files/ ← Starting code
109
+ │ └── workspace/
110
+ │ └── app/
111
+ │ └── controllers/
112
+ │ └── pages_controller.rb
113
+ └── _solution/ ← Solution code
114
+ └── workspace/
115
+ └── app/
116
+ └── controllers/
117
+ └── pages_controller.rb
118
+ ```
119
+
120
+ ### 4b. Write the Part Metadata
121
+
122
+ ```yaml
123
+ # src/content/tutorial/1-basics/meta.md
124
+ ---
125
+ type: part
126
+ title: The Basics
127
+ ---
128
+ ```
129
+
130
+ ### 4c. Write the Lesson
131
+
132
+ ```yaml
133
+ # src/content/tutorial/1-basics/1-hello-rails/content.md
134
+ ---
135
+ type: lesson
136
+ title: Hello Rails
137
+ focus: /workspace/app/controllers/pages_controller.rb
138
+ previews: [3000]
139
+ mainCommand: ['node scripts/rails.js server', 'Starting Rails server']
140
+ prepareCommands:
141
+ - ['npm install', 'Preparing Ruby runtime']
142
+ - ['node scripts/rails.js db:prepare', 'Prepare development database']
143
+ terminalBlockingPrepareCommandsCount: 2
144
+ custom:
145
+ shell:
146
+ workdir: '/workspace'
147
+ ---
148
+
149
+ # Hello Rails
150
+
151
+ Open `app/controllers/pages_controller.rb` and add a `home` action:
152
+
153
+ \`\`\`ruby title="app/controllers/pages_controller.rb" ins={2-4}
154
+ class PagesController < ApplicationController
155
+ def home
156
+ render plain: "Hello from Rails on WebAssembly!"
157
+ end
158
+ end
159
+ \`\`\`
160
+
161
+ Visit the preview to see your message.
162
+ ```
163
+
164
+ ### 4d. Add Starting Files
165
+
166
+ Put a skeleton file in `_files/`:
167
+
168
+ ```ruby
169
+ # _files/workspace/app/controllers/pages_controller.rb
170
+ class PagesController < ApplicationController
171
+ # Add your action here
172
+ end
173
+ ```
174
+
175
+ ### 4e. Add Solution Files
176
+
177
+ Put the completed code in `_solution/`:
178
+
179
+ ```ruby
180
+ # _solution/workspace/app/controllers/pages_controller.rb
181
+ class PagesController < ApplicationController
182
+ def home
183
+ render plain: "Hello from Rails on WebAssembly!"
184
+ end
185
+ end
186
+ ```
187
+
188
+ ### 4f. Delete the Sample Content
189
+
190
+ Remove the scaffold's starter lessons once you have your own:
191
+
192
+ ```bash
193
+ rm -rf src/content/tutorial/1-getting-started/
194
+ rm -rf src/content/tutorial/2-controllers/
195
+ ```
196
+
197
+ ## The `rails-app` Template
198
+
199
+ The scaffold includes a pre-built `rails-app` template at `src/templates/rails-app/` with a minimal Rails app skeleton and CSS design system. Most tutorials should extend this template rather than building from scratch.
200
+
201
+ ### What's Included
202
+
203
+ - **CSS design system** — modern BEM-based stylesheet with CSS custom properties
204
+ - **Layout** — nav bar with brand name; flash messages; `.container` wrapper
205
+ - **Minimal app skeleton** — `ApplicationController`, basic layout, empty routes and seeds
206
+
207
+ The template is intentionally minimal. Tutorial-specific features like authentication, models, controllers, and views should be added via lesson `_files/` overlays or custom templates that extend `rails-app`.
208
+
209
+ ### CSS Design System
210
+
211
+ The template's `application.css` uses pure CSS with custom properties and BEM naming. Use these classes in your lesson ERB files — no extra setup needed.
212
+
213
+ **CSS Custom Properties (`:root` variables):**
214
+
215
+ | Category | Variables | Example |
216
+ |----------|-----------|---------|
217
+ | Colors | `--color-primary`, `--color-danger`, `--color-success`, `--color-warning`, `--color-info` | `color: var(--color-primary)` |
218
+ | Text | `--color-text`, `--color-text-muted`, `--color-text-inverse` | `color: var(--color-text-muted)` |
219
+ | Background | `--color-bg`, `--color-bg-white`, `--color-border` | `background: var(--color-bg)` |
220
+ | Spacing | `--space-xs` through `--space-2xl` | `padding: var(--space-md)` |
221
+ | Typography | `--font-sans`, `--font-mono`, `--font-size-sm` through `--font-size-3xl` | `font-size: var(--font-size-lg)` |
222
+ | Radius | `--radius-sm` through `--radius-xl` | `border-radius: var(--radius-md)` |
223
+ | Shadows | `--shadow-sm`, `--shadow-md` | `box-shadow: var(--shadow-sm)` |
224
+
225
+ **BEM Components:**
226
+
227
+ | Component | Classes | Usage |
228
+ |-----------|---------|-------|
229
+ | Button | `.btn`, `.btn--primary`, `.btn--danger`, `.btn--small`, `.btn--link` | Links, submits, actions |
230
+ | Input | `.input`, `.input--error` | Text fields, selects, textareas |
231
+ | Card | `.card`, `.card__header`, `.card__body`, `.card__footer` | Content containers |
232
+ | Alert | `.alert`, `.alert--error`, `.alert--success`, `.alert--info`, `.alert--warning` | Flash messages, notices |
233
+ | Badge | `.badge`, `.badge--primary`, `.badge--success`, `.badge--danger`, `.badge--warning` | Status labels, role tags |
234
+ | Nav | `.nav`, `.nav__brand`, `.nav__link`, `.nav__user` | Top navigation (in layout) |
235
+ | Form | `.form__group`, `.form__label`, `.form__hint`, `.form__errors`, `.form__actions` | Form layout |
236
+ | Table | `.table` | Data tables with hover rows |
237
+ | Page header | `.page-header` | Title + action button row |
238
+ | Hero | `.hero`, `.hero__title`, `.hero__subtitle`, `.hero__actions` | Landing/home pages |
239
+ | Utility | `.text-muted`, `.text-sm`, `.mt-md`, `.mb-md`, `.inline-actions`, `.container` | Spacing, text helpers |
240
+
241
+ ### Customizing the Demo App for Your Domain
242
+
243
+ To turn the generic demo app into your tutorial's domain (e.g., a Help Desk, a Store, etc.):
244
+
245
+ **1. Rename the app module** in `config/application.rb`:
246
+
247
+ ```ruby
248
+ module Helpdesk # was DemoApp
249
+ class Application < Rails::Application
250
+ ```
251
+
252
+ **2. Add your models.** Create migrations in `db/migrate/` and models in `app/models/`. Update `db/schema.rb` to match.
253
+
254
+ **3. Add controllers and views.** Put CRUD controllers in `app/controllers/` and ERB views in `app/views/`. Use the BEM classes from the CSS design system.
255
+
256
+ **4. Update routes** in `config/routes.rb`.
257
+
258
+ **5. Update seeds** in `db/seeds.rb` with sample data for your domain.
259
+
260
+ **6. Update the layout** — change the brand name in `app/views/layouts/application.html.erb`, add nav links for your resources.
261
+
262
+ ## Step 5: Use a Template for Pre-Built State
263
+
264
+ If your lesson needs an existing Rails app (not just an empty workspace), create a template:
265
+
266
+ ```
267
+ src/templates/my-app/
268
+ ├── .tk-config.json → { "extends": "../default" }
269
+ └── workspace/
270
+ ├── app/
271
+ ├── config/
272
+ ├── db/
273
+ └── ...
274
+ ```
275
+
276
+ Then reference it from your lesson's `_files/.tk-config.json`:
277
+
278
+ ```json
279
+ {
280
+ "extends": "../../../../../templates/my-app"
281
+ }
282
+ ```
283
+
284
+ See the `rails-file-management` skill for details on template inheritance.
285
+
286
+ ## Step 6: Deploy
287
+
288
+ Tutorials need **Cross-Origin-Embedder-Policy** and **Cross-Origin-Opener-Policy** headers for WebContainers to work. If you chose a hosting provider during scaffold, these are already configured.
289
+
290
+ ### Build for Production
291
+
292
+ ```bash
293
+ npm run build # Produces a static site in dist/
294
+ ```
295
+
296
+ ### Manual Header Configuration
297
+
298
+ If you didn't choose a provider during scaffold, add these headers to every response:
299
+
300
+ ```
301
+ Cross-Origin-Embedder-Policy: require-corp
302
+ Cross-Origin-Opener-Policy: same-origin
303
+ ```
304
+
305
+ #### Vercel (`vercel.json`)
306
+
307
+ ```json
308
+ {
309
+ "headers": [
310
+ {
311
+ "source": "/(.*)",
312
+ "headers": [
313
+ { "key": "Cross-Origin-Embedder-Policy", "value": "require-corp" },
314
+ { "key": "Cross-Origin-Opener-Policy", "value": "same-origin" }
315
+ ]
316
+ }
317
+ ]
318
+ }
319
+ ```
320
+
321
+ #### Netlify (`netlify.toml`)
322
+
323
+ ```toml
324
+ [[headers]]
325
+ for = "/*"
326
+ [headers.values]
327
+ Cross-Origin-Embedder-Policy = "require-corp"
328
+ Cross-Origin-Opener-Policy = "same-origin"
329
+ ```
330
+
331
+ #### Cloudflare (`public/_headers`)
332
+
333
+ ```
334
+ /*
335
+ Cross-Origin-Embedder-Policy: require-corp
336
+ Cross-Origin-Opener-Policy: same-origin
337
+ ```
338
+
339
+ ## Customizing Look & Feel (Branding)
340
+
341
+ To match your tutorial's branding to your project's documentation site, update these files:
342
+
343
+ ### Logos
344
+
345
+ Replace `public/logo.svg` (light mode) and `public/logo-dark.svg` (dark mode) with your project's logo SVG. Use a dark fill (e.g., `#0F4D8A`) for the light-mode version and a light fill (e.g., `#E4E6E9`) for the dark-mode version.
346
+
347
+ ### Title in Top Bar
348
+
349
+ Edit `src/components/TopBar.astro` — add a `<span>` after the logo images inside the `<a>` tag:
350
+
351
+ ```html
352
+ <span class="ml-2 text-sm font-medium text-tk-elements-topBar-iconButton-iconColor whitespace-nowrap">
353
+ Your Tutorial Title
354
+ </span>
355
+ ```
356
+
357
+ ### Favicon
358
+
359
+ Replace `public/favicon.svg` with your project's icon. Optionally add a `public/favicon.ico` for broader browser support.
360
+
361
+ ### Accent Colors (UnoCSS Theme)
362
+
363
+ Override the `accent` palette in `uno.config.ts` to change buttons, links, active tabs, and badges site-wide:
364
+
365
+ ```ts
366
+ import { defineConfig } from '@tutorialkit-rb/theme';
367
+
368
+ export default defineConfig({
369
+ theme: {
370
+ colors: {
371
+ accent: {
372
+ 50: '#EFF6FF',
373
+ 100: '#E5F0FF',
374
+ 200: '#B6D4FF',
375
+ 300: '#75B5FF',
376
+ 400: '#4DA6FF', // dark mode accent
377
+ 500: '#0E7EF1', // primary interactive
378
+ 600: '#0F4D8A', // primary brand
379
+ 700: '#0C3F72',
380
+ 800: '#09325A',
381
+ 900: '#072848',
382
+ 950: '#041A30',
383
+ },
384
+ },
385
+ },
386
+ content: {
387
+ pipeline: { include: '**' },
388
+ },
389
+ });
390
+ ```
391
+
392
+ Generate your scale from your brand's primary color. The `600` slot is the main brand color; `500` is for hover/interactive states; `400` is used in dark mode.
393
+
394
+ ### Component Hardcoded Colors
395
+
396
+ Some components use hardcoded Tailwind color classes instead of theme tokens. Search for and replace these:
397
+
398
+ - **`src/components/HelpDropdown.tsx`** — Reload button uses `bg-blue-600`. Change to `bg-accent-600 hover:bg-accent-700`.
399
+ - **`src/components/HeadTags.astro`** — Rails path link colors. Update hex values to match your brand.
400
+
401
+ ### Rails Demo App CSS
402
+
403
+ Update the primary color in `src/templates/rails-app/workspace/app/assets/stylesheets/application.css`:
404
+
405
+ ```css
406
+ :root {
407
+ --color-primary: #0F4D8A; /* your brand color */
408
+ --color-primary-hover: #0C3F72; /* darker shade */
409
+ --color-primary-light: #EFF6FF; /* tinted background */
410
+ }
411
+ ```
412
+
413
+ ### GitHub Link
414
+
415
+ Update the repo URL in `src/components/GitHubLink.astro`:
416
+
417
+ ```html
418
+ <a href="https://github.com/your-org/your-repo" ...>
419
+ ```
420
+
421
+ ## Common Issues
422
+
423
+ | Problem | Cause | Fix |
424
+ |---------|-------|-----|
425
+ | `build:wasm` fails | Missing WASI SDK or build tools | Check `rbwasm` prerequisites |
426
+ | Preview shows nothing | Server not started | Add `mainCommand: ['node scripts/rails.js server', ...]` |
427
+ | Terminal stuck on "Preparing" | WASM binary not built | Run `npm run build:wasm` first |
428
+ | Files not appearing in editor | Wrong path | All Rails files must be under `workspace/<app>/` |
429
+ | Database empty | No `db:prepare` in prepareCommands | Add `['node scripts/rails.js db:prepare', '...']` |
430
+ | Deploy fails with blank page | Missing COEP/COOP headers | Add headers per provider instructions above |
431
+
432
+ ## Next Steps
433
+
434
+ | Want to... | See skill |
435
+ |------------|-----------|
436
+ | Structure parts, chapters, lessons | `tutorial-content-structure` |
437
+ | Configure frontmatter options | `tutorial-lesson-config` |
438
+ | Organize Rails files properly | `rails-file-management` |
439
+ | Check if a feature works in WASM | `rails-wasm-author-constraints` |
440
+ | Get a recipe for a specific lesson type | `rails-lesson-recipes` |
@@ -0,0 +1,85 @@
1
+ name: Deploy Tutorial
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+
8
+ concurrency:
9
+ group: deploy
10
+ cancel-in-progress: false
11
+
12
+ jobs:
13
+ build:
14
+ runs-on: ubuntu-latest
15
+ steps:
16
+ - uses: actions/checkout@v4
17
+
18
+ - uses: actions-rust-lang/setup-rust-toolchain@v1
19
+ with:
20
+ toolchain: 1.74.0
21
+
22
+ - name: Install wasi-vfs
23
+ env:
24
+ WASI_VFS_VERSION: 0.5.4
25
+ run: |
26
+ curl -LO "https://github.com/kateinoigakukun/wasi-vfs/releases/download/v${WASI_VFS_VERSION}/wasi-vfs-cli-x86_64-unknown-linux-gnu.zip"
27
+ unzip wasi-vfs-cli-x86_64-unknown-linux-gnu.zip
28
+ mv wasi-vfs /usr/local/bin/wasi-vfs
29
+
30
+ - uses: ruby/setup-ruby@v1
31
+ env:
32
+ BUNDLE_GEMFILE: ruby-wasm/Gemfile
33
+ BUNDLE_PATH: ruby-wasm/vendor
34
+ with:
35
+ ruby-version: 3.3
36
+ bundler-cache: true
37
+
38
+ - uses: actions/setup-node@v4
39
+ with:
40
+ node-version: 20
41
+ cache: npm
42
+
43
+ - name: Cache ruby.wasm build artifacts
44
+ uses: actions/cache@v4
45
+ with:
46
+ path: |
47
+ ruby-wasm/build
48
+ ruby-wasm/rubies
49
+ key: ${{ runner.os }}-ruby-wasm-${{ hashFiles('ruby-wasm/Gemfile.lock') }}
50
+ restore-keys: |
51
+ ${{ runner.os }}-ruby-wasm-
52
+
53
+ - name: Build ruby.wasm
54
+ run: npm run build:wasm
55
+
56
+ - name: Build tutorial
57
+ run: |
58
+ npm install
59
+ npm run build
60
+
61
+ - name: Upload dist
62
+ uses: actions/upload-artifact@v4
63
+ with:
64
+ name: tutorial-dist
65
+ path: ./dist
66
+
67
+ deploy:
68
+ needs: build
69
+ runs-on: ubuntu-latest
70
+ steps:
71
+ - uses: actions/checkout@v4
72
+
73
+ - uses: actions/download-artifact@v4
74
+ with:
75
+ name: tutorial-dist
76
+ path: dist
77
+
78
+ - uses: nwtgck/actions-netlify@v3
79
+ with:
80
+ publish-dir: ./dist
81
+ netlify-config-path: ./netlify.toml
82
+ production-deploy: true
83
+ env:
84
+ NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
85
+ NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
@@ -12,3 +12,13 @@ pnpm-debug.log*
12
12
 
13
13
  public/ruby.wasm
14
14
  public/ruby.wasm.hash
15
+
16
+ ruby-wasm/build
17
+ ruby-wasm/dist
18
+ ruby-wasm/tmp
19
+ ruby-wasm/vendor
20
+ ruby-wasm/.bundle
21
+ ruby-wasm/rubies
22
+
23
+ # Local development linking (created by npm run link:local)
24
+ pnpm-workspace.yaml
@@ -0,0 +1,47 @@
1
+ # Tutorial Authoring Guide
2
+
3
+ You are authoring an interactive Ruby on Rails tutorial that runs entirely in the browser using WebAssembly. Tutorial content lives in `src/content/tutorial/`. The Rails WASM runtime, templates, and infrastructure are already set up — your job is to write lessons.
4
+
5
+ ## Project Layout
6
+
7
+ ```
8
+ src/content/tutorial/ ← Your tutorial content (lessons, parts, chapters)
9
+ src/templates/ ← WebContainer file templates (base app states)
10
+ ruby-wasm/Gemfile ← Gems compiled into the WASM binary
11
+ bin/build-wasm ← Rebuild WASM after Gemfile changes
12
+ ```
13
+
14
+ ## Key Constraints
15
+
16
+ - **All Rails app files go under `workspace/`** — this is the WASI filesystem boundary
17
+ - **Each lesson should be self-contained** — don't rely on user actions from previous lessons persisting
18
+ - **Gems require a WASM rebuild** — edit `ruby-wasm/Gemfile`, then run `bin/build-wasm`
19
+ - **Outbound HTTP works** (`Net::HTTP`, Faraday, etc.) via JS fetch bridge — CORS restrictions apply, see `rails-wasm-author-constraints`
20
+ - **No threading or process spawning** from Ruby — see `rails-wasm-author-constraints`
21
+ - **Database resets on page reload** — use `prepareCommands` with `db:prepare` for lessons that need data
22
+ - **Use `node scripts/rails.js <cmd>`** in frontmatter commands, not bare `rails <cmd>`
23
+
24
+ ## Development
25
+
26
+ ```bash
27
+ npm install # Install dependencies (or pnpm/yarn/bun — whichever this project uses)
28
+ npm run dev # Start dev server at http://localhost:4321/
29
+ ```
30
+
31
+ ## Before Creating or Modifying Lessons
32
+
33
+ **MANDATORY:** Always invoke these skills before writing any lesson content:
34
+
35
+ - `rails-lesson-recipes` — lesson patterns, directory structures, and post-creation checklist
36
+ - `rails-file-management` — `_files/`, `_solution/`, template organization, and the file layering model
37
+ - `tutorial-lesson-config` — frontmatter options, inheritance rules, and invalid-combination constraints
38
+
39
+ Do NOT create lessons without loading these skills first. Incorrect structure causes silent runtime failures.
40
+
41
+ ## Additional Skills
42
+
43
+ | Question | Skill |
44
+ |----------|-------|
45
+ | How do I start a new tutorial from scratch? | `tutorial-quickstart` |
46
+ | How do I structure parts, chapters, and lessons? | `tutorial-content-structure` |
47
+ | Can I teach feature X in WASM? | `rails-wasm-author-constraints` |
@@ -6,6 +6,18 @@ export default defineConfig({
6
6
  devToolbar: {
7
7
  enabled: false,
8
8
  },
9
+ vite: {
10
+ server: {
11
+ watch: {
12
+ ignored: ['**/ruby-wasm/**'],
13
+ },
14
+ },
15
+ build: {
16
+ rollupOptions: {
17
+ external: [/ruby-wasm/],
18
+ },
19
+ },
20
+ },
9
21
  integrations: [
10
22
  tutorialkit({
11
23
  components: {
@@ -0,0 +1,84 @@
1
+ #!/bin/bash
2
+
3
+ set -e
4
+
5
+ # Dynamic gem packing: cross-compile gems and pack them into a pre-built
6
+ # Ruby WASM base binary via wasi-vfs.
7
+ #
8
+ # This is the fast path (~30s) compared to the monolithic `bin/build-wasm`
9
+ # (~5-20min). Requires a pre-built base binary (from bin/build-ruby-base
10
+ # or the @tutorialkit-rb/ruby-3.3 npm package).
11
+ #
12
+ # Usage: ./bin/build-pack
13
+
14
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
15
+ TEMPLATE_DIR="$(dirname "$SCRIPT_DIR")"
16
+ RUBY_WASM_DIR="$TEMPLATE_DIR/ruby-wasm"
17
+
18
+ echo "=== Dynamic gem packing ==="
19
+ echo
20
+
21
+ # --- Preflight checks --------------------------------------------------------
22
+
23
+ if ! command -v wasi-vfs &> /dev/null; then
24
+ echo "Error: wasi-vfs CLI not found"
25
+ echo "Install it with: cargo install wasi-vfs-cli"
26
+ echo "See: https://github.com/aspect-build/aspect-workflows/tree/main/packages/wasi-vfs"
27
+ exit 1
28
+ fi
29
+
30
+ # --- Resolve base binary -----------------------------------------------------
31
+
32
+ echo "Resolving base binary..."
33
+ BASE_WASM=""
34
+
35
+ # 1. Local build
36
+ if [ -f "$RUBY_WASM_DIR/dist/ruby-base.wasm" ]; then
37
+ BASE_WASM="$RUBY_WASM_DIR/dist/ruby-base.wasm"
38
+ echo " Found: local build (dist/ruby-base.wasm)"
39
+ fi
40
+
41
+ # 2. npm package fallback
42
+ if [ -z "$BASE_WASM" ]; then
43
+ NPM_BASE="$RUBY_WASM_DIR/node_modules/@tutorialkit-rb/ruby-3.3/dist/ruby-base.wasm"
44
+ if [ -f "$NPM_BASE" ]; then
45
+ BASE_WASM="$NPM_BASE"
46
+ echo " Found: @tutorialkit-rb/ruby-3.3 npm package"
47
+ fi
48
+ fi
49
+
50
+ if [ -z "$BASE_WASM" ]; then
51
+ echo
52
+ echo "Error: No base WASM binary found."
53
+ echo "Either run 'bin/build-ruby-base' to build one,"
54
+ echo "or install @tutorialkit-rb/ruby-3.3 npm package."
55
+ exit 1
56
+ fi
57
+
58
+ echo
59
+
60
+ # --- Cross-compile gems + pack -----------------------------------------------
61
+
62
+ echo "Installing host gems for cross-compilation..."
63
+ cd "$RUBY_WASM_DIR"
64
+ bundle install --path vendor/bundle
65
+ echo
66
+
67
+ echo "Running pack-gems..."
68
+ bundle exec ruby bin/pack-gems
69
+ echo
70
+
71
+ # --- Copy output to public/ --------------------------------------------------
72
+
73
+ echo "Copying ruby.wasm to public directory..."
74
+ cp "$RUBY_WASM_DIR/dist/ruby.wasm" "$TEMPLATE_DIR/public/ruby.wasm"
75
+ echo " ruby.wasm → public/"
76
+
77
+ # Generate hash of Gemfile.lock for cache versioning
78
+ GEMFILE_HASH=$(shasum -a 256 "$RUBY_WASM_DIR/Gemfile.lock" | cut -c1-16)
79
+ echo "$GEMFILE_HASH" > "$TEMPLATE_DIR/public/ruby.wasm.hash"
80
+ echo " ruby.wasm.hash: $GEMFILE_HASH"
81
+
82
+ echo
83
+ echo "=== Done ==="
84
+ echo "Run 'npm run dev' to test your tutorial."