@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.
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/template/.claude/skills/rails-file-management/SKILL.md +211 -0
- package/template/.claude/skills/rails-lesson-recipes/SKILL.md +415 -0
- package/template/.claude/skills/rails-wasm-author-constraints/SKILL.md +181 -0
- package/template/.claude/skills/tutorial-content-structure/SKILL.md +377 -0
- package/template/.claude/skills/tutorial-lesson-config/SKILL.md +389 -0
- package/template/.claude/skills/tutorial-quickstart/SKILL.md +440 -0
- package/template/.github/workflows/deploy.yml +85 -0
- package/template/.gitignore +10 -0
- package/template/CLAUDE.md +47 -0
- package/template/astro.config.ts +12 -0
- package/template/bin/build-pack +84 -0
- package/template/bin/build-ruby-base +180 -0
- package/template/bin/link-local +13 -0
- package/template/bin/unlink-local +7 -0
- package/template/cors-proxy/README.md +63 -0
- package/template/cors-proxy/package-lock.json +1504 -0
- package/template/cors-proxy/package.json +12 -0
- package/template/cors-proxy/src/index.ts +87 -0
- package/template/cors-proxy/wrangler.toml +7 -0
- package/template/netlify.toml +9 -0
- package/template/package.json +12 -4
- package/template/ruby-wasm/Gemfile +6 -0
- package/template/ruby-wasm/Gemfile.base +19 -0
- package/template/ruby-wasm/Gemfile.base.lock +50 -0
- package/template/ruby-wasm/Gemfile.lock +8 -0
- package/template/ruby-wasm/bin/pack-gems +368 -0
- package/template/ruby-wasm/package.json +6 -0
- package/template/src/components/FileManager.tsx +33 -0
- package/template/src/components/HeadTags.astro +6 -6
- package/template/src/components/HelpDropdown.tsx +1 -1
- package/template/src/components/RailsPathLinkHandler.tsx +2 -2
- package/template/src/components/ShellConfigurator.tsx +6 -1
- package/template/src/content/tutorial/1-getting-started/1-creating-your-first-rails-app/content.md +4 -4
- package/template/src/content/tutorial/1-getting-started/2-rails-console/content.md +4 -4
- package/template/src/content/tutorial/2-controllers/2-crud-operations/content.md +2 -2
- package/template/src/content/tutorial/9-outbound-http/1-making-http-requests/_files/.tk-config.json +3 -0
- package/template/src/content/tutorial/9-outbound-http/1-making-http-requests/_files/workspace/app/controllers/http_demo_controller.rb +65 -0
- package/template/src/content/tutorial/9-outbound-http/1-making-http-requests/_files/workspace/app/views/http_demo/index.html.erb +172 -0
- package/template/src/content/tutorial/9-outbound-http/1-making-http-requests/_files/workspace/config/routes.rb +8 -0
- package/template/src/content/tutorial/9-outbound-http/1-making-http-requests/content.md +97 -0
- package/template/src/content/tutorial/9-outbound-http/meta.md +4 -0
- package/template/src/content/tutorial/meta.md +5 -0
- package/template/src/middleware.ts +14 -0
- package/template/src/templates/default/lib/boot-progress.js +49 -0
- package/template/src/templates/default/lib/http-bridge.js +55 -0
- package/template/src/templates/default/lib/patches/http_bridge.rb +167 -0
- package/template/src/templates/default/lib/rails.js +52 -5
- package/template/src/templates/default/lib/server.js +33 -1
- package/template/src/templates/default/package.json +4 -1
- package/template/src/templates/default/scripts/rails.js +1 -1
- package/template/src/templates/default/scripts/smoke-test.js +349 -0
- package/template/src/templates/default/scripts/wasi-loader.mjs +10 -0
- package/template/src/templates/default/workspace/_debug_app/.github/dependabot.yml +12 -0
- package/template/src/templates/default/workspace/_debug_app/.github/workflows/ci.yml +51 -0
- package/template/src/templates/default/workspace/_debug_app/.ruby-version +1 -0
- package/template/src/templates/default/workspace/_debug_app/Gemfile +37 -0
- package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/views/layouts/application.html.erb +1 -2
- package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/views/pwa/manifest.json.erb +2 -2
- package/template/src/templates/default/workspace/_debug_app/bin/dev +2 -0
- package/template/src/templates/default/workspace/_debug_app/bin/rake +4 -0
- package/template/src/templates/default/workspace/_debug_app/bin/setup +34 -0
- package/template/src/templates/default/workspace/_debug_app/config/application.rb +30 -0
- package/template/src/templates/default/workspace/_debug_app/config/cable.yml +10 -0
- package/template/src/templates/default/workspace/_debug_app/config/credentials.yml.enc +1 -0
- package/template/src/templates/default/workspace/_debug_app/config/master.key +1 -0
- package/template/src/templates/default/workspace/_debug_app/config/routes.rb +14 -0
- package/template/src/templates/default/workspace/_debug_app/test/models/.keep +0 -0
- package/template/src/templates/default/workspace/_debug_app/test/test_helper.rb +15 -0
- package/template/src/templates/default/workspace/_debug_app/tmp/.keep +0 -0
- package/template/src/templates/default/workspace/_debug_app/tmp/pids/.keep +0 -0
- package/template/src/templates/default/workspace/_debug_app/tmp/storage/.keep +0 -0
- package/template/src/templates/default/workspace/_debug_app/vendor/.keep +0 -0
- package/template/src/templates/rails-app/workspace/README.md +24 -0
- package/template/src/templates/rails-app/workspace/Rakefile +6 -0
- package/template/src/templates/rails-app/workspace/app/assets/images/.keep +0 -0
- package/template/src/templates/rails-app/workspace/app/assets/stylesheets/application.css +534 -0
- package/template/src/templates/rails-app/workspace/app/controllers/application_controller.rb +2 -0
- package/template/src/templates/rails-app/workspace/app/helpers/application_helper.rb +2 -0
- package/template/src/templates/rails-app/workspace/app/jobs/application_job.rb +7 -0
- package/template/src/templates/rails-app/workspace/app/mailers/application_mailer.rb +4 -0
- package/template/src/templates/rails-app/workspace/app/models/application_record.rb +3 -0
- package/template/src/templates/rails-app/workspace/app/models/concerns/.keep +0 -0
- package/template/src/templates/rails-app/workspace/app/views/layouts/application.html.erb +38 -0
- package/template/src/templates/rails-app/workspace/app/views/layouts/mailer.html.erb +13 -0
- package/template/src/templates/rails-app/workspace/app/views/layouts/mailer.text.erb +1 -0
- package/template/src/templates/rails-app/workspace/bin/rails +4 -0
- package/template/src/templates/rails-app/workspace/{store/config → config}/application.rb +1 -1
- package/template/src/templates/rails-app/workspace/config/boot.rb +3 -0
- package/template/src/templates/rails-app/workspace/config/database.yml +32 -0
- package/template/src/templates/rails-app/workspace/config/environment.rb +5 -0
- package/template/src/templates/rails-app/workspace/config/environments/development.rb +69 -0
- package/template/src/templates/rails-app/workspace/config/environments/production.rb +89 -0
- package/template/src/templates/rails-app/workspace/config/environments/test.rb +54 -0
- package/template/src/templates/rails-app/workspace/config/initializers/assets.rb +7 -0
- package/template/src/templates/rails-app/workspace/config/initializers/content_security_policy.rb +25 -0
- package/template/src/templates/rails-app/workspace/config/initializers/filter_parameter_logging.rb +8 -0
- package/template/src/templates/rails-app/workspace/config/initializers/inflections.rb +16 -0
- package/template/src/templates/rails-app/workspace/config/locales/en.yml +31 -0
- package/template/src/templates/rails-app/workspace/config/puma.rb +41 -0
- package/template/src/templates/rails-app/workspace/{store/config → config}/routes.rb +1 -1
- package/template/src/templates/rails-app/workspace/config/storage.yml +34 -0
- package/template/src/templates/rails-app/workspace/config.ru +6 -0
- package/template/src/templates/rails-app/workspace/db/seeds.rb +9 -0
- package/template/src/templates/rails-app/workspace/log/.keep +0 -0
- package/template/src/templates/rails-app/workspace/public/400.html +114 -0
- package/template/src/templates/rails-app/workspace/public/404.html +114 -0
- package/template/src/templates/rails-app/workspace/public/406-unsupported-browser.html +114 -0
- package/template/src/templates/rails-app/workspace/public/422.html +114 -0
- package/template/src/templates/rails-app/workspace/public/500.html +114 -0
- package/template/src/templates/rails-app/workspace/public/icon.png +0 -0
- package/template/src/templates/rails-app/workspace/public/icon.svg +3 -0
- package/template/src/templates/rails-app/workspace/public/robots.txt +1 -0
- package/template/src/templates/rails-app/workspace/script/.keep +0 -0
- package/template/src/templates/rails-app/workspace/storage/.keep +0 -0
- package/template/src/templates/rails-app/workspace/test/controllers/.keep +0 -0
- package/template/src/templates/rails-app/workspace/test/helpers/.keep +0 -0
- package/template/src/templates/rails-app/workspace/test/integration/.keep +0 -0
- package/template/src/templates/rails-app/workspace/tmp/.keep +0 -0
- package/template/src/templates/rails-app/workspace/tmp/cache/.keep +0 -0
- package/template/src/templates/rails-app/workspace/tmp/pids/.keep +0 -0
- package/template/src/templates/rails-app/workspace/tmp/sockets/.keep +0 -0
- package/template/src/templates/rails-app/workspace/tmp/storage/.keep +0 -0
- package/template/src/templates/rails-app/workspace/vendor/javascripts/.keep +0 -0
- package/template/tsconfig.json +3 -1
- package/template/uno.config.ts +17 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/README.md +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/Rakefile +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/assets/images/.keep +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/assets/stylesheets/application.css +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/controllers/application_controller.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store/app/models → default/workspace/_debug_app/app/controllers}/concerns/.keep +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/helpers/application_helper.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/jobs/application_job.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/mailers/application_mailer.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/models/application_record.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store/log → default/workspace/_debug_app/app/models/concerns}/.keep +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/views/layouts/mailer.html.erb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/views/layouts/mailer.text.erb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/app/views/pwa/service-worker.js +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/bin/rails +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/boot.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/database.yml +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/environment.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/environments/development.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/environments/production.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/environments/test.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/initializers/assets.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/initializers/content_security_policy.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/initializers/filter_parameter_logging.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/initializers/inflections.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/locales/en.yml +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/puma.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config/storage.yml +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/config.ru +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/db/seeds.rb +0 -0
- /package/template/src/templates/{rails-app/workspace/store/script → default/workspace/_debug_app/lib/tasks}/.keep +0 -0
- /package/template/src/templates/{rails-app/workspace/store/storage → default/workspace/_debug_app/log}/.keep +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/400.html +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/404.html +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/406-unsupported-browser.html +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/422.html +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/500.html +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/icon.png +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/icon.svg +0 -0
- /package/template/src/templates/{rails-app/workspace/store → default/workspace/_debug_app}/public/robots.txt +0 -0
- /package/template/src/templates/{rails-app/workspace/store/test/controllers → default/workspace/_debug_app/script}/.keep +0 -0
- /package/template/src/templates/{rails-app/workspace/store/test/helpers → default/workspace/_debug_app/storage}/.keep +0 -0
- /package/template/src/templates/{rails-app/workspace/store/test/integration → default/workspace/_debug_app/test/controllers}/.keep +0 -0
- /package/template/src/templates/{rails-app/workspace/store/tmp → default/workspace/_debug_app/test/fixtures/files}/.keep +0 -0
- /package/template/src/templates/{rails-app/workspace/store/tmp/pids → default/workspace/_debug_app/test/helpers}/.keep +0 -0
- /package/template/src/templates/{rails-app/workspace/store/tmp/storage → default/workspace/_debug_app/test/integration}/.keep +0 -0
- /package/template/src/templates/{rails-app/workspace/store/vendor/javascripts → default/workspace/_debug_app/test/mailers}/.keep +0 -0
- /package/template/src/templates/rails-app/workspace/{store/.ruby-version → .ruby-version} +0 -0
- /package/template/src/templates/rails-app/workspace/{store/Gemfile → Gemfile} +0 -0
- /package/template/src/templates/rails-app/workspace/{store/app → app}/javascript/application.js +0 -0
- /package/template/src/templates/rails-app/workspace/{store/app → app}/javascript/controllers/application.js +0 -0
- /package/template/src/templates/rails-app/workspace/{store/app → app}/javascript/controllers/index.js +0 -0
- /package/template/src/templates/rails-app/workspace/{store/bin → bin}/importmap +0 -0
- /package/template/src/templates/rails-app/workspace/{store/config → config}/cable.yml +0 -0
- /package/template/src/templates/rails-app/workspace/{store/config → config}/credentials.yml.enc +0 -0
- /package/template/src/templates/rails-app/workspace/{store/config → config}/importmap.rb +0 -0
- /package/template/src/templates/rails-app/workspace/{store/config → config}/master.key +0 -0
- /package/template/src/templates/rails-app/workspace/{store/test → test}/test_helper.rb +0 -0
package/dist/index.js
CHANGED
|
@@ -14,7 +14,7 @@ import "yargs-parser";
|
|
|
14
14
|
// package.json
|
|
15
15
|
var package_default = {
|
|
16
16
|
name: "@tutorialkit-rb/cli",
|
|
17
|
-
version: "0.1.
|
|
17
|
+
version: "0.1.7",
|
|
18
18
|
description: "Interactive tutorials powered by WebContainer API",
|
|
19
19
|
author: "StackBlitz Inc.",
|
|
20
20
|
type: "module",
|
package/package.json
CHANGED
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rails-file-management
|
|
3
|
+
description: |
|
|
4
|
+
Use this skill whenever organizing files for Rails tutorial lessons — _files/, _solution/,
|
|
5
|
+
templates, workspace paths. Trigger on: 'create _files', 'add _solution', 'template
|
|
6
|
+
inheritance', '.tk-config.json', 'extends path', 'workspace path', 'which files go where',
|
|
7
|
+
'add a gem', 'Gemfile', 'build-wasm', 'create a template', 'protected files', 'do not
|
|
8
|
+
override', or asking where to put Rails app code — even without mentioning file management.
|
|
9
|
+
Covers the three-layer merge model, built-in templates, `.tk-config.json` path formula for
|
|
10
|
+
different nesting depths, protected infrastructure files, and WASM gem build workflow. Do
|
|
11
|
+
NOT attempt file organization without this skill. Do NOT use for frontmatter (use
|
|
12
|
+
tutorial-lesson-config) or content hierarchy (use tutorial-content-structure).
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# Rails File Management
|
|
16
|
+
|
|
17
|
+
How to organize files across templates, `_files`, and `_solution` directories for Rails tutorial lessons.
|
|
18
|
+
|
|
19
|
+
## The File Layering Model
|
|
20
|
+
|
|
21
|
+
When a lesson loads, TutorialKit merges files from multiple sources in this order:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
Template (base) ← Runtime infrastructure, package.json, bin/, lib/
|
|
25
|
+
↓ overlaid by
|
|
26
|
+
_files/ (lesson) ← Lesson-specific Rails app code
|
|
27
|
+
↓ replaced on "Solve"
|
|
28
|
+
_solution/ (lesson) ← Completed/answer code
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Files from each layer **overlay** the previous — same-path files are replaced, new files are added.
|
|
32
|
+
|
|
33
|
+
**Two template mechanisms (don't confuse them):**
|
|
34
|
+
- **`template` frontmatter field** (e.g., `template: default`) — selects which base template JSON is loaded as the "Template (base)" layer. Almost always set in the part's `meta.md`. The tutorial's root `meta.md` contains `rails-app`—a minimal demo app used in the tutotiral.
|
|
35
|
+
- **`_files/.tk-config.json` with `extends`** — extends the `_files` layer with files from another template directory. These provide the source code that overlays on top of the template used. Use it to share many files between lessons. Otherwise, prefer duplication and the `template` frontmatter..
|
|
36
|
+
|
|
37
|
+
IMPORTANT: Files added via the `template` frontmatter are not visible in the editor; only the `_files` contents (including `_files/.tk-config.json`'s contents) are shown in the editor.
|
|
38
|
+
|
|
39
|
+
## Templates
|
|
40
|
+
|
|
41
|
+
Templates live in `src/templates/` and provide the base project structure for WebContainer.
|
|
42
|
+
|
|
43
|
+
### Built-in Templates
|
|
44
|
+
|
|
45
|
+
| Template | Purpose | Inherits From |
|
|
46
|
+
|----------|---------|---------------|
|
|
47
|
+
| `default` | Base Rails WASM runtime — Node.js wrappers, Express server, PGLite, WASM loader. Selected via `template: default` in frontmatter (the default). | (none) |
|
|
48
|
+
| `rails-app` | Pre-generated Rails app at `workspace/`. Update this template to set up the base Rails app for the tutorial | `default` |
|
|
49
|
+
|
|
50
|
+
### Template Inheritance
|
|
51
|
+
|
|
52
|
+
Templates can extend other templates via `.tk-config.json`:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"extends": "../rails-app"
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
The child template's files overlay on top of the parent's files.
|
|
61
|
+
|
|
62
|
+
### Creating a New Template
|
|
63
|
+
|
|
64
|
+
Create a directory under `src/templates/` with:
|
|
65
|
+
|
|
66
|
+
1. A `.tk-config.json` extending the appropriate parent
|
|
67
|
+
2. The files that differ from the parent
|
|
68
|
+
|
|
69
|
+
**Example:** A template for a blog tutorial:
|
|
70
|
+
|
|
71
|
+
```
|
|
72
|
+
src/templates/blog-app/
|
|
73
|
+
.tk-config.json → { "extends": "../rails-app" }
|
|
74
|
+
workspace/
|
|
75
|
+
app/
|
|
76
|
+
models/post.rb
|
|
77
|
+
controllers/posts_controller.rb
|
|
78
|
+
views/posts/
|
|
79
|
+
index.html.erb
|
|
80
|
+
show.html.erb
|
|
81
|
+
config/routes.rb
|
|
82
|
+
db/
|
|
83
|
+
migrate/001_create_posts.rb
|
|
84
|
+
seeds.rb
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### What Belongs in a Template vs. a Lesson
|
|
88
|
+
|
|
89
|
+
| In a Template | In a Lesson's `_files/` |
|
|
90
|
+
|---------------|------------------------|
|
|
91
|
+
| Shared app structure used by multiple lessons | Files specific to one lesson |
|
|
92
|
+
| Models, migrations, seeds for a baseline state | Modifications the user will build upon |
|
|
93
|
+
| Routes and config shared across a chapter | One-off configuration changes |
|
|
94
|
+
| Complete working app states (scaffolded code) | Starter/skeleton files the user will complete |
|
|
95
|
+
|
|
96
|
+
**Rule of thumb:** If 3+ lessons need the same base state, create a template. If only one lesson uses it, put it in `_files/`.
|
|
97
|
+
|
|
98
|
+
## `_files/` Directory
|
|
99
|
+
|
|
100
|
+
The `_files/` directory contains files shown to the user when the lesson loads. These are the **starting state** for the lesson.
|
|
101
|
+
|
|
102
|
+
### Path Convention
|
|
103
|
+
|
|
104
|
+
All Rails app files **must** live under `workspace/` to match the WASI preopen at `/workspace`:
|
|
105
|
+
|
|
106
|
+
```
|
|
107
|
+
_files/
|
|
108
|
+
workspace/
|
|
109
|
+
app/
|
|
110
|
+
controllers/
|
|
111
|
+
products_controller.rb
|
|
112
|
+
models/
|
|
113
|
+
product.rb
|
|
114
|
+
views/
|
|
115
|
+
products/
|
|
116
|
+
index.html.erb
|
|
117
|
+
config/
|
|
118
|
+
routes.rb
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### `.tk-config.json` Path Formula
|
|
122
|
+
|
|
123
|
+
The `extends` path in `.tk-config.json` is **relative to the directory containing the `.tk-config.json` file**. To reach `src/templates/<name>`, count the `../` segments based on your content nesting depth:
|
|
124
|
+
|
|
125
|
+
| Content structure | `../` count | Example `extends` value |
|
|
126
|
+
|-------------------|-------------|------------------------|
|
|
127
|
+
| `tutorial/lesson/_files/` | 4 | `"../../../../templates/rails-app"` |
|
|
128
|
+
| `tutorial/part/lesson/_files/` | 5 | `"../../../../../templates/rails-app"` |
|
|
129
|
+
| `tutorial/part/chapter/lesson/_files/` | 6 | `"../../../../../../templates/rails-app"` |
|
|
130
|
+
|
|
131
|
+
The count is: 1 (`_files/`) + 1 (lesson dir) + N (intermediate dirs: part, chapter) + 1 (`tutorial/`) + 1 (`content/`) = **4 + number of intermediate levels**.
|
|
132
|
+
|
|
133
|
+
For the standard `tutorial/part/lesson/_files/` structure used by most Rails tutorials, the path is always `"../../../../../templates/<name>"` (5 segments).
|
|
134
|
+
|
|
135
|
+
## `_solution/` Directory
|
|
136
|
+
|
|
137
|
+
The `_solution/` directory contains the **completed code** for the lesson. When the user clicks "Solve", solution files replace the corresponding `_files/`.
|
|
138
|
+
|
|
139
|
+
### Structure
|
|
140
|
+
|
|
141
|
+
Mirror the `_files/` directory structure:
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
_solution/
|
|
145
|
+
workspace/
|
|
146
|
+
store/
|
|
147
|
+
app/
|
|
148
|
+
controllers/
|
|
149
|
+
products_controller.rb ← completed version
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
### When to Use
|
|
153
|
+
|
|
154
|
+
- **Code-editing lessons** where the user modifies files — provide the finished version
|
|
155
|
+
- **Not needed** for terminal-only lessons (e.g., running `rails new`, using the console)
|
|
156
|
+
|
|
157
|
+
### Tips
|
|
158
|
+
|
|
159
|
+
- `_solution/` can include files not present in `_files/` (e.g., a new file the user was asked to create)
|
|
160
|
+
- Only include files that differ from the template + `_files/` — unchanged files don't need to appear
|
|
161
|
+
|
|
162
|
+
## Do Not Override These Files
|
|
163
|
+
|
|
164
|
+
The following files are **runtime infrastructure** provided by the `default` template. Lessons should never include these in `_files/` or `_solution/`:
|
|
165
|
+
|
|
166
|
+
| Path | Purpose |
|
|
167
|
+
|------|---------|
|
|
168
|
+
| `package.json` | npm dependencies (WASM runtime, Express, PGLite) |
|
|
169
|
+
| `bin/rails`, `bin/ruby`, `bin/console`, `bin/rackup` | Node.js CLI wrappers |
|
|
170
|
+
| `lib/rails.js`, `lib/server.js`, `lib/database.js` | WASM runtime, HTTP bridge, DB |
|
|
171
|
+
| `lib/boot-progress.js`, `lib/commands.js`, `lib/irb.js` | Boot progress, command dispatch, IRB |
|
|
172
|
+
| `lib/server/frame_location_middleware.js` | Express middleware for frame location |
|
|
173
|
+
| `lib/patches/authentication.rb` | Auto-login patch |
|
|
174
|
+
| `lib/patches/app_generator.rb` | Rails generator WASM compat patch |
|
|
175
|
+
| `scripts/` | Build and automation scripts |
|
|
176
|
+
| `pgdata/` | PGLite database storage |
|
|
177
|
+
|
|
178
|
+
## Managing Gems
|
|
179
|
+
|
|
180
|
+
### Adding Gems
|
|
181
|
+
|
|
182
|
+
Gems are compiled into the WASM binary. To add a gem:
|
|
183
|
+
|
|
184
|
+
1. Edit `ruby-wasm/Gemfile` in the project root
|
|
185
|
+
2. Run `bin/build-wasm` to rebuild the WASM binary
|
|
186
|
+
|
|
187
|
+
```ruby
|
|
188
|
+
# ruby-wasm/Gemfile
|
|
189
|
+
source "https://rubygems.org"
|
|
190
|
+
|
|
191
|
+
gem "wasmify-rails", "~> 0.4.0"
|
|
192
|
+
gem "rails", "~> 8.0.0"
|
|
193
|
+
|
|
194
|
+
# Add your gems here
|
|
195
|
+
gem "devise" # Authentication
|
|
196
|
+
gem "friendly_id" # Slugs
|
|
197
|
+
gem "pagy" # Pagination
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
### Gem Constraints
|
|
201
|
+
|
|
202
|
+
- **Pure Ruby gems** work without issues
|
|
203
|
+
- **Gems with native C extensions** need WASM-compatible builds — many common ones are already shimmed (see `rails-wasm-author-constraints` skill)
|
|
204
|
+
- Rebuilding the WASM binary takes several minutes
|
|
205
|
+
- The resulting binary is ~80MB and includes all gems
|
|
206
|
+
|
|
207
|
+
### Gemfile in Templates
|
|
208
|
+
|
|
209
|
+
The `ruby-wasm/Gemfile` is the **single source of truth** for which gems are available. Individual lessons cannot add gems at runtime — the Gemfile is baked into the WASM binary at build time.
|
|
210
|
+
|
|
211
|
+
If your tutorial teaches the user to "add a gem to the Gemfile", be aware that this is a **conceptual exercise** — the gem must already be compiled into the WASM binary for it to actually work when they run `bundle install`.
|
|
@@ -0,0 +1,415 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: rails-lesson-recipes
|
|
3
|
+
description: |
|
|
4
|
+
Use this skill whenever creating a new lesson, choosing a lesson pattern, or validating
|
|
5
|
+
lesson structure. Trigger on: 'create a lesson', 'lesson recipe', 'lesson pattern',
|
|
6
|
+
'terminal-only lesson', 'code editing lesson', 'database lesson', 'console lesson',
|
|
7
|
+
'lesson sequence', 'multi-step lesson', 'validate lesson', 'check lesson', or asking
|
|
8
|
+
how to structure a Rails lesson — even without mentioning recipes. Provides five tested
|
|
9
|
+
blueprints (terminal-only, code-editing, database, full-app, console/IRB) with correct
|
|
10
|
+
frontmatter, directory layouts, content examples, and a post-creation validation
|
|
11
|
+
checklist. Do NOT create lessons without this skill — incorrect structure causes silent
|
|
12
|
+
failures. Do NOT use for frontmatter reference (use tutorial-lesson-config) or file
|
|
13
|
+
organization (use rails-file-management).
|
|
14
|
+
---
|
|
15
|
+
|
|
16
|
+
# Rails Lesson Recipes
|
|
17
|
+
|
|
18
|
+
Ready-to-use patterns for common Rails tutorial lesson types.
|
|
19
|
+
|
|
20
|
+
## Recipe 1: Terminal-Only Lesson
|
|
21
|
+
|
|
22
|
+
**Use for:** Running generators, using the console, exploring CLI tools.
|
|
23
|
+
**Example:** `rails new`, `rails console`, `rails generate`.
|
|
24
|
+
|
|
25
|
+
### Directory Structure
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
1-creating-your-first-rails-app/
|
|
29
|
+
content.md
|
|
30
|
+
_files/
|
|
31
|
+
workspace/
|
|
32
|
+
.keep
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
### Frontmatter
|
|
36
|
+
|
|
37
|
+
```yaml
|
|
38
|
+
---
|
|
39
|
+
type: lesson
|
|
40
|
+
title: Creating your first Rails app
|
|
41
|
+
editor: false
|
|
42
|
+
custom:
|
|
43
|
+
shell:
|
|
44
|
+
workdir: "/workspace"
|
|
45
|
+
---
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Key Decisions
|
|
49
|
+
|
|
50
|
+
- `editor: false` — the user only interacts via terminal
|
|
51
|
+
- `previews: false` — inherited from tutorial root (no server running)
|
|
52
|
+
- Empty `workspace/.keep` — user creates the app from scratch
|
|
53
|
+
- `workdir: "/workspace"` — terminal starts at the workspace root (before app exists)
|
|
54
|
+
|
|
55
|
+
### Content Pattern
|
|
56
|
+
|
|
57
|
+
```markdown
|
|
58
|
+
# Creating Your First Rails App
|
|
59
|
+
|
|
60
|
+
Run the following command to generate a new Rails application:
|
|
61
|
+
|
|
62
|
+
\`\`\`bash
|
|
63
|
+
$ rails new store
|
|
64
|
+
\`\`\`
|
|
65
|
+
|
|
66
|
+
:::info
|
|
67
|
+
This may take a moment as Rails generates the application structure.
|
|
68
|
+
:::
|
|
69
|
+
|
|
70
|
+
After your new application is created, switch to its directory:
|
|
71
|
+
|
|
72
|
+
\`\`\`bash
|
|
73
|
+
$ cd store
|
|
74
|
+
\`\`\`
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
---
|
|
78
|
+
|
|
79
|
+
## Recipe 2: Code-Editing Lesson (with Preview)
|
|
80
|
+
|
|
81
|
+
**Use for:** Writing controllers, models, views, routes — any lesson where the user edits code and sees results.
|
|
82
|
+
**Example:** Adding a new action, modifying a view, updating routes.
|
|
83
|
+
|
|
84
|
+
### Directory Structure
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
3-adding-a-controller/
|
|
88
|
+
content.md
|
|
89
|
+
_files/
|
|
90
|
+
.tk-config.json
|
|
91
|
+
workspace/
|
|
92
|
+
app/
|
|
93
|
+
controllers/
|
|
94
|
+
pages_controller.rb ← starter/skeleton code
|
|
95
|
+
config/
|
|
96
|
+
routes.rb
|
|
97
|
+
_solution/
|
|
98
|
+
workspace/
|
|
99
|
+
app/
|
|
100
|
+
controllers/
|
|
101
|
+
pages_controller.rb ← completed code
|
|
102
|
+
views/
|
|
103
|
+
pages/
|
|
104
|
+
home.html.erb ← new file the user creates
|
|
105
|
+
config/
|
|
106
|
+
routes.rb
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Frontmatter
|
|
110
|
+
|
|
111
|
+
```yaml
|
|
112
|
+
---
|
|
113
|
+
type: lesson
|
|
114
|
+
title: Adding a Controller
|
|
115
|
+
focus: /workspace/app/controllers/pages_controller.rb
|
|
116
|
+
previews: [3000]
|
|
117
|
+
mainCommand: ['node scripts/rails.js server', 'Starting Rails server']
|
|
118
|
+
custom:
|
|
119
|
+
shell:
|
|
120
|
+
workdir: '/workspace'
|
|
121
|
+
---
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
### `.tk-config.json`
|
|
125
|
+
|
|
126
|
+
```json
|
|
127
|
+
{
|
|
128
|
+
"extends": "../../../../../templates/rails-app"
|
|
129
|
+
}
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
### Key Decisions
|
|
133
|
+
|
|
134
|
+
- `focus` opens the file the user will edit
|
|
135
|
+
- `previews: [3000]` shows the Rails app in a preview pane
|
|
136
|
+
- `mainCommand` starts the Rails server after prepare commands finish
|
|
137
|
+
- `_solution/` includes both modified files and new files the user was asked to create
|
|
138
|
+
- Inherits `prepareCommands` (npm install) from tutorial root
|
|
139
|
+
|
|
140
|
+
### Content Pattern
|
|
141
|
+
|
|
142
|
+
```markdown
|
|
143
|
+
# Adding a Controller
|
|
144
|
+
|
|
145
|
+
Open `app/controllers/pages_controller.rb` in the editor. Add a `home` action:
|
|
146
|
+
|
|
147
|
+
\`\`\`ruby title="app/controllers/pages_controller.rb" ins={2-4}
|
|
148
|
+
class PagesController < ApplicationController
|
|
149
|
+
def home
|
|
150
|
+
@message = "Welcome to our store!"
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
\`\`\`
|
|
154
|
+
|
|
155
|
+
Now create the view at `app/views/pages/home.html.erb`:
|
|
156
|
+
|
|
157
|
+
\`\`\`erb title="app/views/pages/home.html.erb"
|
|
158
|
+
<h1><%= @message %></h1>
|
|
159
|
+
\`\`\`
|
|
160
|
+
|
|
161
|
+
:::tip
|
|
162
|
+
Click **Solve** to see the completed code if you get stuck.
|
|
163
|
+
:::
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Recipe 3: Database Lesson
|
|
169
|
+
|
|
170
|
+
**Use for:** Migrations, models, seeds, ActiveRecord queries.
|
|
171
|
+
**Example:** Creating a model, running migrations, seeding data.
|
|
172
|
+
|
|
173
|
+
### Directory Structure
|
|
174
|
+
|
|
175
|
+
```
|
|
176
|
+
1-creating-a-model/
|
|
177
|
+
content.md
|
|
178
|
+
_files/
|
|
179
|
+
.tk-config.json
|
|
180
|
+
workspace/
|
|
181
|
+
db/
|
|
182
|
+
migrate/
|
|
183
|
+
20240101000000_create_products.rb
|
|
184
|
+
seeds.rb
|
|
185
|
+
app/
|
|
186
|
+
models/
|
|
187
|
+
product.rb
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Frontmatter
|
|
191
|
+
|
|
192
|
+
```yaml
|
|
193
|
+
---
|
|
194
|
+
type: lesson
|
|
195
|
+
title: Creating a Product Model
|
|
196
|
+
focus: /workspace/app/models/product.rb
|
|
197
|
+
previews: [3000]
|
|
198
|
+
mainCommand: ['node scripts/rails.js server', 'Starting Rails server']
|
|
199
|
+
prepareCommands:
|
|
200
|
+
- ['npm install', 'Preparing Ruby runtime']
|
|
201
|
+
- ['node scripts/rails.js db:prepare', 'Prepare development database']
|
|
202
|
+
terminalBlockingPrepareCommandsCount: 2
|
|
203
|
+
custom:
|
|
204
|
+
shell:
|
|
205
|
+
workdir: '/workspace'
|
|
206
|
+
---
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Key Decisions
|
|
210
|
+
|
|
211
|
+
- `prepareCommands` includes `db:prepare` — this runs migrations and seeds **before** the lesson becomes interactive
|
|
212
|
+
- Migration files must have timestamps in filenames (Rails convention)
|
|
213
|
+
- Seeds provide starting data so the user sees something immediately
|
|
214
|
+
- Override `prepareCommands` at the lesson level (doesn't inherit the tutorial root's single command)
|
|
215
|
+
|
|
216
|
+
### Content Pattern
|
|
217
|
+
|
|
218
|
+
```markdown
|
|
219
|
+
# Creating a Product Model
|
|
220
|
+
|
|
221
|
+
Your Product model is defined in `app/models/product.rb`. Let's add validations:
|
|
222
|
+
|
|
223
|
+
\`\`\`ruby title="app/models/product.rb"
|
|
224
|
+
class Product < ApplicationRecord
|
|
225
|
+
validates :name, presence: true
|
|
226
|
+
validates :price, numericality: { greater_than: 0 }
|
|
227
|
+
end
|
|
228
|
+
\`\`\`
|
|
229
|
+
|
|
230
|
+
The migration has already been run. Try it in the console:
|
|
231
|
+
|
|
232
|
+
\`\`\`bash
|
|
233
|
+
$ bin/rails console
|
|
234
|
+
\`\`\`
|
|
235
|
+
|
|
236
|
+
\`\`\`irb
|
|
237
|
+
store(dev)> Product.create(name: "Widget", price: 9.99)
|
|
238
|
+
store(dev)> Product.all
|
|
239
|
+
\`\`\`
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
---
|
|
243
|
+
|
|
244
|
+
## Recipe 4: Full-App Lesson (Pre-Built State)
|
|
245
|
+
|
|
246
|
+
**Use for:** Teaching concepts that require a fully scaffolded app — CRUD, associations, authentication.
|
|
247
|
+
**Example:** CRUD operations on an existing scaffold.
|
|
248
|
+
|
|
249
|
+
### Directory Structure
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
2-crud-operations/
|
|
253
|
+
content.md
|
|
254
|
+
_files/
|
|
255
|
+
.tk-config.json
|
|
256
|
+
workspace/
|
|
257
|
+
.keep
|
|
258
|
+
```
|
|
259
|
+
|
|
260
|
+
### Frontmatter
|
|
261
|
+
|
|
262
|
+
```yaml
|
|
263
|
+
---
|
|
264
|
+
type: lesson
|
|
265
|
+
title: CRUD Operations
|
|
266
|
+
focus: /workspace/app/controllers/products_controller.rb
|
|
267
|
+
previews: [3000]
|
|
268
|
+
mainCommand: ['node scripts/rails.js server', 'Starting Rails server']
|
|
269
|
+
prepareCommands:
|
|
270
|
+
- ['npm install', 'Preparing Ruby runtime']
|
|
271
|
+
- ['node scripts/rails.js db:prepare', 'Prepare development database']
|
|
272
|
+
terminalBlockingPrepareCommandsCount: 2
|
|
273
|
+
custom:
|
|
274
|
+
shell:
|
|
275
|
+
workdir: '/workspace'
|
|
276
|
+
---
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
### `.tk-config.json`
|
|
280
|
+
|
|
281
|
+
```json
|
|
282
|
+
{
|
|
283
|
+
"extends": "../../../../../templates/crud-products"
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
### Key Decisions
|
|
288
|
+
|
|
289
|
+
- Uses `crud-products` template which provides a complete scaffolded app
|
|
290
|
+
- `_files/` only contains `.tk-config.json` and a `.keep` — the template provides everything
|
|
291
|
+
- `focus` points to the file being discussed in the lesson
|
|
292
|
+
- No `_solution/` needed — this is an exploration/explanation lesson, not a coding exercise
|
|
293
|
+
|
|
294
|
+
---
|
|
295
|
+
|
|
296
|
+
## Recipe 5: Console/IRB Lesson
|
|
297
|
+
|
|
298
|
+
**Use for:** Interactive Ruby exploration, testing models, querying the database.
|
|
299
|
+
|
|
300
|
+
### Directory Structure
|
|
301
|
+
|
|
302
|
+
```
|
|
303
|
+
2-rails-console/
|
|
304
|
+
content.md
|
|
305
|
+
_files/
|
|
306
|
+
.tk-config.json
|
|
307
|
+
workspace/
|
|
308
|
+
.keep
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
### Frontmatter
|
|
312
|
+
|
|
313
|
+
```yaml
|
|
314
|
+
---
|
|
315
|
+
type: lesson
|
|
316
|
+
title: Rails Console
|
|
317
|
+
custom:
|
|
318
|
+
shell:
|
|
319
|
+
workdir: "/workspace"
|
|
320
|
+
---
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
### Key Decisions
|
|
324
|
+
|
|
325
|
+
- No `editor`, no `previews`, no `mainCommand` — user works entirely in the terminal
|
|
326
|
+
- Inherits `editor: true` by default but doesn't need to set `editor: false` since the user can still browse files
|
|
327
|
+
- Uses a pre-built template via `.tk-config.json` so there's an app to explore
|
|
328
|
+
|
|
329
|
+
---
|
|
330
|
+
|
|
331
|
+
## Building Lesson Sequences
|
|
332
|
+
|
|
333
|
+
### Progressive State Pattern
|
|
334
|
+
|
|
335
|
+
For a series of lessons that build on each other, use **template layering**:
|
|
336
|
+
|
|
337
|
+
```
|
|
338
|
+
src/templates/
|
|
339
|
+
default/ ← Base WASM runtime
|
|
340
|
+
rails-app/ ← Empty Rails app (extends default)
|
|
341
|
+
blog-base/ ← Blog app with Post model (extends rails-app)
|
|
342
|
+
blog-with-comments/ ← Blog app + Comment model (extends blog-base)
|
|
343
|
+
|
|
344
|
+
src/content/tutorial/
|
|
345
|
+
1-blog/
|
|
346
|
+
meta.md ← type: part
|
|
347
|
+
1-setup/
|
|
348
|
+
content.md ← Uses rails-app template
|
|
349
|
+
_files/.tk-config.json → ../../../../../templates/rails-app
|
|
350
|
+
2-posts/
|
|
351
|
+
content.md ← Uses blog-base template
|
|
352
|
+
_files/.tk-config.json → ../../../../../templates/blog-base
|
|
353
|
+
3-comments/
|
|
354
|
+
content.md ← Uses blog-with-comments template
|
|
355
|
+
_files/.tk-config.json → ../../../../../templates/blog-with-comments
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
Each template captures the **expected state** at the start of that lesson. This way:
|
|
359
|
+
- Users can jump to any lesson without completing previous ones
|
|
360
|
+
- Each lesson starts from a known-good state
|
|
361
|
+
- Template inheritance keeps file duplication minimal
|
|
362
|
+
|
|
363
|
+
### When to Create a New Template vs. Use `_files/`
|
|
364
|
+
|
|
365
|
+
| Create a Template | Use `_files/` |
|
|
366
|
+
|-------------------|---------------|
|
|
367
|
+
| State is reused by 3+ lessons | Only this lesson needs these files |
|
|
368
|
+
| State is complex (many files) | Just 1-3 files differ from the template |
|
|
369
|
+
| You want users to jump to this lesson directly | Sequential lessons where order matters |
|
|
370
|
+
|
|
371
|
+
### Lesson-to-Lesson Expectations
|
|
372
|
+
|
|
373
|
+
**Always assume each lesson starts fresh.** The WASM runtime reinstalls on lesson navigation. Design each lesson to be self-contained:
|
|
374
|
+
|
|
375
|
+
1. Use `prepareCommands` for setup (npm install, db:prepare) and `terminalBlockingPrepareCommandsCount: <number of commands>` to ensure terminal is not used before the prepare commands finish.
|
|
376
|
+
2. Use templates or `_files/` for starting code state
|
|
377
|
+
3. Don't rely on user actions from a previous lesson
|
|
378
|
+
|
|
379
|
+
## Post-Creation Checklist
|
|
380
|
+
|
|
381
|
+
After creating a lesson, verify these structural requirements. Violations cause silent failures at runtime.
|
|
382
|
+
|
|
383
|
+
### Required
|
|
384
|
+
|
|
385
|
+
- [ ] `content.md` exists in the lesson directory and has `type: lesson` in frontmatter
|
|
386
|
+
- [ ] `content.md` has a `title` in frontmatter
|
|
387
|
+
- [ ] All file paths in `_files/` start with `workspace/` (not `/workspace/`)
|
|
388
|
+
- [ ] All file paths in `_solution/` start with `workspace/` (not `/workspace/`)
|
|
389
|
+
- [ ] If `.tk-config.json` exists in `_files/`, its `extends` path resolves to an existing template directory under `src/templates/`
|
|
390
|
+
- [ ] `_solution/` mirrors the `_files/` directory structure (paths must match for "Solve" to replace correctly)
|
|
391
|
+
- [ ] `custom.shell.workdir` is set on the lesson itself (it does NOT inherit from parent `meta.md`)
|
|
392
|
+
|
|
393
|
+
### If previews are enabled
|
|
394
|
+
|
|
395
|
+
- [ ] `previews` is set (e.g., `previews: [3000]`)
|
|
396
|
+
- [ ] `mainCommand` is set to start the server (e.g., `['node scripts/rails.js server', 'Starting Rails server']`)
|
|
397
|
+
- [ ] `prepareCommands` includes `npm install` (either inherited from tutorial root or set explicitly)
|
|
398
|
+
|
|
399
|
+
### If database is used
|
|
400
|
+
|
|
401
|
+
- [ ] `prepareCommands` includes **both** `npm install` and `node scripts/rails.js db:prepare` (remember: arrays replace, not merge)
|
|
402
|
+
- [ ] Migration files have timestamp prefixes in filenames
|
|
403
|
+
- [ ] Seeds file exists if the lesson needs starting data
|
|
404
|
+
|
|
405
|
+
### If focus is set
|
|
406
|
+
|
|
407
|
+
- [ ] `focus` path is absolute from WebContainer root (e.g., `/workspace/app/...`)
|
|
408
|
+
- [ ] The file at `focus` path exists in `_files/` or in the referenced template
|
|
409
|
+
- [ ] `editor` is not set to `false` (focus is silently ignored when editor is hidden)
|
|
410
|
+
|
|
411
|
+
### Path verification
|
|
412
|
+
|
|
413
|
+
- [ ] `.tk-config.json` `extends` uses correct `../` count: 4 + number of intermediate levels above the lesson (typically 5 for `tutorial/part/lesson/_files/`)
|
|
414
|
+
- [ ] `focus` paths use `/workspace/...` (absolute), while `_files/` paths use `workspace/...` (relative, no leading slash)
|
|
415
|
+
- [ ] `scope` paths use `/workspace/...` (absolute)
|