develoz-rails 0.1.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.
Files changed (172) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +31 -0
  3. data/.github/workflows/release.yml +459 -0
  4. data/.rubocop.yml +52 -0
  5. data/.sisyphus/notepads/develoz-rails-template/learnings.md +855 -0
  6. data/.tool-versions +2 -0
  7. data/CHANGELOG.md +28 -0
  8. data/CONTRIBUTING.md +120 -0
  9. data/README.md +76 -0
  10. data/Rakefile +18 -0
  11. data/config/generators.yml +105 -0
  12. data/docs/guide/installation.md +574 -0
  13. data/exe/develoz +6 -0
  14. data/install +98 -0
  15. data/lib/develoz/canonical_fetcher.rb +56 -0
  16. data/lib/develoz/cli.rb +84 -0
  17. data/lib/develoz/generators/base.rb +134 -0
  18. data/lib/develoz/manifest.rb +44 -0
  19. data/lib/develoz/options.rb +55 -0
  20. data/lib/develoz/version.rb +5 -0
  21. data/lib/develoz/version_resolver.rb +103 -0
  22. data/lib/develoz.rb +15 -0
  23. data/lib/generators/develoz/active_resource/active_resource_generator.rb +25 -0
  24. data/lib/generators/develoz/active_resource/templates/application_resource.rb.tt +7 -0
  25. data/lib/generators/develoz/active_resource/templates/example_resource.rb.tt +5 -0
  26. data/lib/generators/develoz/admin/admin_generator.rb +44 -0
  27. data/lib/generators/develoz/admin/templates/admin_base_controller.rb.tt +7 -0
  28. data/lib/generators/develoz/admin/templates/admin_layout.html.erb.tt +38 -0
  29. data/lib/generators/develoz/admin/templates/dashboard_controller.rb.tt +7 -0
  30. data/lib/generators/develoz/admin/templates/dashboard_index.html.erb.tt +2 -0
  31. data/lib/generators/develoz/admin/templates/routes.rb.tt +3 -0
  32. data/lib/generators/develoz/agents_docs/agents_docs_generator.rb +50 -0
  33. data/lib/generators/develoz/agents_docs/templates/.github/pull_request_template.md.tt +13 -0
  34. data/lib/generators/develoz/agents_docs/templates/AGENTS.md.tt +36 -0
  35. data/lib/generators/develoz/agents_docs/templates/docs/development.md.tt +121 -0
  36. data/lib/generators/develoz/agents_docs/templates/docs/performance.md.tt +46 -0
  37. data/lib/generators/develoz/agents_docs/templates/docs/testing.md.tt +92 -0
  38. data/lib/generators/develoz/agents_docs/templates/spec/cassettes/Example_API/fetches_data_from_an_external_API.yml.tt +23 -0
  39. data/lib/generators/develoz/agents_docs/templates/spec/requests/example_api_spec.rb.tt +14 -0
  40. data/lib/generators/develoz/agents_docs/templates/spec/support/faraday.rb.tt +19 -0
  41. data/lib/generators/develoz/agents_docs/templates/spec/support/vcr.rb.tt +11 -0
  42. data/lib/generators/develoz/api/api_generator.rb +55 -0
  43. data/lib/generators/develoz/api/templates/app/blueprints/example_blueprint.rb.tt +6 -0
  44. data/lib/generators/develoz/api/templates/app/controllers/api/v1/base_controller.rb.tt +96 -0
  45. data/lib/generators/develoz/api/templates/config/initializers/blueprinter.rb.tt +16 -0
  46. data/lib/generators/develoz/api/templates/config/initializers/rswag_api.rb.tt +15 -0
  47. data/lib/generators/develoz/api/templates/config/initializers/rswag_ui.rb.tt +17 -0
  48. data/lib/generators/develoz/api/templates/spec/requests/api/v1/examples_spec.rb.tt +25 -0
  49. data/lib/generators/develoz/auth/auth_generator.rb +82 -0
  50. data/lib/generators/develoz/auth/templates/app/controllers/concerns/authentication.rb.tt +53 -0
  51. data/lib/generators/develoz/auth/templates/app/controllers/passwords_controller.rb.tt +35 -0
  52. data/lib/generators/develoz/auth/templates/app/controllers/sessions_controller.rb.tt +22 -0
  53. data/lib/generators/develoz/auth/templates/app/mailers/passwords_mailer.rb.tt +8 -0
  54. data/lib/generators/develoz/auth/templates/app/models/current.rb.tt +5 -0
  55. data/lib/generators/develoz/auth/templates/app/models/user.rb.tt +7 -0
  56. data/lib/generators/develoz/auth/templates/app/views/passwords/edit.html.erb.tt +9 -0
  57. data/lib/generators/develoz/auth/templates/app/views/passwords_mailer/reset.html.erb.tt +6 -0
  58. data/lib/generators/develoz/auth/templates/app/views/sessions/new.html.erb.tt +11 -0
  59. data/lib/generators/develoz/auth/templates/db/migrate/create_users.rb.tt +13 -0
  60. data/lib/generators/develoz/auth/templates/spec/requests/passwords_spec.rb.tt +60 -0
  61. data/lib/generators/develoz/auth/templates/spec/requests/sessions_spec.rb.tt +37 -0
  62. data/lib/generators/develoz/ci/ci_generator.rb +66 -0
  63. data/lib/generators/develoz/ci/templates/.github/workflows/ci.yml.tt +18 -0
  64. data/lib/generators/develoz/ci/templates/.haml-lint.yml.tt +12 -0
  65. data/lib/generators/develoz/ci/templates/.markdownlint.json.tt +10 -0
  66. data/lib/generators/develoz/ci/templates/.reek.yml.tt +28 -0
  67. data/lib/generators/develoz/ci/templates/.rubocop.yml.tt +22 -0
  68. data/lib/generators/develoz/ci/templates/.stylelintrc.json.tt +4 -0
  69. data/lib/generators/develoz/ci/templates/.yamllint.tt +14 -0
  70. data/lib/generators/develoz/ci/templates/Rakefile.tt +73 -0
  71. data/lib/generators/develoz/ci/templates/bin/ci.tt +6 -0
  72. data/lib/generators/develoz/ci/templates/biome.json.tt +41 -0
  73. data/lib/generators/develoz/ci/templates/config/ci.rb.tt +23 -0
  74. data/lib/generators/develoz/concerns/concerns_generator.rb +48 -0
  75. data/lib/generators/develoz/concerns/templates/app/models/concerns/configurable.rb.tt +120 -0
  76. data/lib/generators/develoz/concerns/templates/app/models/concerns/optimized_finders.rb.tt +93 -0
  77. data/lib/generators/develoz/concerns/templates/app/models/concerns/searchable_concern.rb.tt +31 -0
  78. data/lib/generators/develoz/concerns/templates/app/models/concerns/transitionable.rb.tt +144 -0
  79. data/lib/generators/develoz/concerns/templates/app/models/configuration.rb.tt +104 -0
  80. data/lib/generators/develoz/concerns/templates/db/migrate/add_status_transitions.rb.tt +30 -0
  81. data/lib/generators/develoz/concerns/templates/db/migrate/create_configurations.rb.tt +25 -0
  82. data/lib/generators/develoz/concerns/templates/spec/models/concerns/configurable_spec.rb.tt +172 -0
  83. data/lib/generators/develoz/concerns/templates/spec/models/concerns/optimized_finders_spec.rb.tt +200 -0
  84. data/lib/generators/develoz/concerns/templates/spec/models/concerns/searchable_concern_spec.rb.tt +84 -0
  85. data/lib/generators/develoz/concerns/templates/spec/models/concerns/transitionable_spec.rb.tt +234 -0
  86. data/lib/generators/develoz/concerns/templates/spec/models/configuration_spec.rb.tt +223 -0
  87. data/lib/generators/develoz/database/database_generator.rb +44 -0
  88. data/lib/generators/develoz/database/templates/config/database.yml.tt +53 -0
  89. data/lib/generators/develoz/database/templates/config/initializers/pg_search.rb.tt +5 -0
  90. data/lib/generators/develoz/database/templates/db/migrate/create_pg_extensions.rb.tt +13 -0
  91. data/lib/generators/develoz/db_backup/db_backup_generator.rb +47 -0
  92. data/lib/generators/develoz/db_backup/templates/backup_rake.tt +48 -0
  93. data/lib/generators/develoz/db_backup/templates/bin_db_backup.tt +25 -0
  94. data/lib/generators/develoz/db_backup/templates/compose_service.tt +14 -0
  95. data/lib/generators/develoz/doc_specs/doc_specs_generator.rb +33 -0
  96. data/lib/generators/develoz/doc_specs/templates/bin/generate-docs.tt +392 -0
  97. data/lib/generators/develoz/doc_specs/templates/lib/tasks/docs_check.rake.tt +8 -0
  98. data/lib/generators/develoz/doc_specs/templates/spec/support/doc_screenshot_helper.rb.tt +17 -0
  99. data/lib/generators/develoz/doc_specs/templates/spec/system/example_doc_spec.rb.tt +38 -0
  100. data/lib/generators/develoz/docker/docker_generator.rb +54 -0
  101. data/lib/generators/develoz/docker/templates/bin_dev.tt +5 -0
  102. data/lib/generators/develoz/docker/templates/bin_docker_entrypoint.tt +8 -0
  103. data/lib/generators/develoz/docker/templates/bin_run.tt +152 -0
  104. data/lib/generators/develoz/docker/templates/bin_setup.tt +15 -0
  105. data/lib/generators/develoz/docker/templates/docker-compose.yml.tt +59 -0
  106. data/lib/generators/develoz/docker/templates/dockerfile_dev.tt +24 -0
  107. data/lib/generators/develoz/docs_render/docs_render_generator.rb +46 -0
  108. data/lib/generators/develoz/docs_render/templates/app/assets/stylesheets/documentation.scss.tt +145 -0
  109. data/lib/generators/develoz/docs_render/templates/app/controllers/docs_controller.rb.tt +7 -0
  110. data/lib/generators/develoz/docs_render/templates/app/javascript/docs.js.tt +15 -0
  111. data/lib/generators/develoz/docs_render/templates/app/models/document.rb.tt +189 -0
  112. data/lib/generators/develoz/docs_render/templates/app/views/docs/show.html.erb.tt +7 -0
  113. data/lib/generators/develoz/docs_render/templates/config/initializers/redcarpet_rouge.rb.tt +16 -0
  114. data/lib/generators/develoz/frontend_core/frontend_core_generator.rb +40 -0
  115. data/lib/generators/develoz/frontend_core/templates/.annotaterb.yml.tt +16 -0
  116. data/lib/generators/develoz/frontend_core/templates/config/importmap.rb.tt +12 -0
  117. data/lib/generators/develoz/frontend_core/templates/config/initializers/pagy.rb.tt +10 -0
  118. data/lib/generators/develoz/install/install_generator.rb +51 -0
  119. data/lib/generators/develoz/kamal/kamal_generator.rb +59 -0
  120. data/lib/generators/develoz/kamal/templates/accessories_postgres.yml.tt +14 -0
  121. data/lib/generators/develoz/kamal/templates/deploy.yml.tt +43 -0
  122. data/lib/generators/develoz/kamal/templates/dockerfile_prod.tt +54 -0
  123. data/lib/generators/develoz/kamal/templates/kamal_secrets.tt +22 -0
  124. data/lib/generators/develoz/maintenance/maintenance_generator.rb +29 -0
  125. data/lib/generators/develoz/maintenance/templates/app/tasks/maintenance/example_task.rb.tt +20 -0
  126. data/lib/generators/develoz/maintenance/templates/lib/tasks/maintenance_counters.rake.tt +27 -0
  127. data/lib/generators/develoz/push/push_generator.rb +61 -0
  128. data/lib/generators/develoz/push/templates/app/javascript/pwa/subscription.js.tt +57 -0
  129. data/lib/generators/develoz/push/templates/app/models/push_subscription.rb.tt +14 -0
  130. data/lib/generators/develoz/push/templates/app/services/push_notification_service.rb.tt +36 -0
  131. data/lib/generators/develoz/push/templates/app/views/pwa/sw_push_handlers.js.tt +49 -0
  132. data/lib/generators/develoz/push/templates/constants_env.tt +5 -0
  133. data/lib/generators/develoz/push/templates/db/migrate/create_push_subscriptions.rb.tt +15 -0
  134. data/lib/generators/develoz/pwa/pwa_generator.rb +46 -0
  135. data/lib/generators/develoz/pwa/templates/app/controllers/pwa_controller.rb.tt +17 -0
  136. data/lib/generators/develoz/pwa/templates/app/javascript/pwa/registration.js.tt +25 -0
  137. data/lib/generators/develoz/pwa/templates/app/views/pwa/manifest.json.erb.tt +24 -0
  138. data/lib/generators/develoz/pwa/templates/app/views/pwa/offline.html.erb.tt +51 -0
  139. data/lib/generators/develoz/pwa/templates/app/views/pwa/service-worker.js.tt +109 -0
  140. data/lib/generators/develoz/pwa/templates/routes.rb.tt +3 -0
  141. data/lib/generators/develoz/solid/solid_generator.rb +52 -0
  142. data/lib/generators/develoz/solid/templates/app/jobs/application_job.rb.tt +7 -0
  143. data/lib/generators/develoz/solid/templates/config/cable.yml.tt +10 -0
  144. data/lib/generators/develoz/solid/templates/config/cache.yml.tt +16 -0
  145. data/lib/generators/develoz/solid/templates/config/initializers/mission_control.rb.tt +8 -0
  146. data/lib/generators/develoz/solid/templates/config/initializers/solid.rb.tt +7 -0
  147. data/lib/generators/develoz/solid/templates/config/queue.yml.tt +18 -0
  148. data/lib/generators/develoz/solid/templates/config/recurring.yml.tt +20 -0
  149. data/lib/generators/develoz/strict_loading/strict_loading_generator.rb +17 -0
  150. data/lib/generators/develoz/strict_loading/templates/config/initializers/strict_loading.rb.tt +13 -0
  151. data/lib/generators/develoz/testing/templates/rspec.tt +2 -0
  152. data/lib/generators/develoz/testing/templates/rspec_parallel.tt +2 -0
  153. data/lib/generators/develoz/testing/templates/spec/rails_helper.rb.tt +32 -0
  154. data/lib/generators/develoz/testing/templates/spec/spec_helper.rb.tt +31 -0
  155. data/lib/generators/develoz/testing/testing_generator.rb +39 -0
  156. data/lib/generators/develoz/tooling/templates/constants.rb.tt +17 -0
  157. data/lib/generators/develoz/tooling/templates/env.example.tt +4 -0
  158. data/lib/generators/develoz/tooling/templates/vscode/extensions.json.tt +8 -0
  159. data/lib/generators/develoz/tooling/templates/vscode/settings.json.tt +26 -0
  160. data/lib/generators/develoz/tooling/templates/vscode/tasks.json.tt +26 -0
  161. data/lib/generators/develoz/tooling/tooling_generator.rb +33 -0
  162. data/lib/generators/develoz/ui/templates/bin/setup_develoz_ui.tt +20 -0
  163. data/lib/generators/develoz/ui/ui_generator.rb +57 -0
  164. data/lib/generators/develoz/versioning/templates/app/helpers/application_helper.rb.tt +7 -0
  165. data/lib/generators/develoz/versioning/templates/app/views/shared/_app_version.html.erb.tt +3 -0
  166. data/lib/generators/develoz/versioning/templates/spec/helpers/application_helper_spec.rb.tt +11 -0
  167. data/lib/generators/develoz/versioning/versioning_generator.rb +48 -0
  168. data/lib/tasks/canonical.rake +27 -0
  169. data/templates/.keep +0 -0
  170. data/templates/CANONICAL_SOURCES.md +93 -0
  171. data/templates/pull_request_template.md.tt +13 -0
  172. metadata +383 -0
@@ -0,0 +1,574 @@
1
+ # Installation and usage
2
+
3
+ One command applies 13 core generators, while 10 opt-in flags let you add only
4
+ the product features you need. How do we get that payoff without guessing which
5
+ defaults, prerequisites, or follow-up steps are hidden behind the command?
6
+
7
+ By the end of this guide, you will be able to:
8
+
9
+ - install and verify the `develoz-rails` gem;
10
+ - create a new application interactively or with reproducible flags;
11
+ - adopt Develoz generators one feature at a time in an existing Rails app; and
12
+ - initialize `develoz-ui` and diagnose the most common setup failures.
13
+
14
+ ## Prerequisites
15
+
16
+ Develoz Rails requires:
17
+
18
+ - Ruby 3.4 or newer;
19
+ - Rails 8.1 (`railties ~> 8.1`);
20
+ - Git; and
21
+ - PostgreSQL 18 or newer for the generated database configuration.
22
+
23
+ Use one Ruby and tool-version manager consistently. Generated applications use
24
+ `.tool-versions`, which works directly with asdf and can also be consumed by
25
+ mise. The generator records runtime versions; it does not install or activate
26
+ them for the current shell.
27
+
28
+ Before continuing, check the executables that will do the work:
29
+
30
+ ```bash
31
+ ruby --version
32
+ rails --version
33
+ git --version
34
+ psql --version
35
+ ```
36
+
37
+ ## Install the gem
38
+
39
+ Install the command-line executable into the currently active Ruby:
40
+
41
+ ```bash
42
+ gem install develoz-rails
43
+ ```
44
+
45
+ Then verify the installation:
46
+
47
+ ```bash
48
+ develoz version
49
+ develoz help new
50
+ ```
51
+
52
+ If `develoz` is not found, the gem was usually installed under a different Ruby
53
+ or its executable directory is not on `PATH`. See [Troubleshooting](#troubleshooting).
54
+
55
+ ## Understand what `develoz new` does
56
+
57
+ The command has two stages:
58
+
59
+ 1. It runs `rails new APP_NAME --skip-test --skip-ci --skip-bundle`.
60
+ 2. It applies the Develoz core generators and any selected opt-in generators.
61
+
62
+ Rails' default test and CI files are skipped because Develoz installs its own
63
+ RSpec and CI setup. Bundling is also skipped, so run `bundle install` after you
64
+ have reviewed the generated `Gemfile` and initialized any selected submodules.
65
+
66
+ The core installation always includes tooling, RSpec, Solid Queue/Cache/Cable,
67
+ CI, PostgreSQL configuration, shared concerns, strict loading, maintenance
68
+ tasks, frontend foundations, documentation support, agent documentation, and
69
+ application versioning. Pagy is part of frontend core unless you opt out.
70
+
71
+ Every product feature is opt-in. In particular, `--yes` means "accept the
72
+ defaults without prompting"; it does not turn every feature on.
73
+
74
+ ## Create a new application interactively
75
+
76
+ Start with only an application name:
77
+
78
+ ```bash
79
+ develoz new dispatch
80
+ ```
81
+
82
+ The CLI asks, in order, whether to include:
83
+
84
+ 1. API layer
85
+ 2. authentication
86
+ 3. PWA support
87
+ 4. push notifications
88
+ 5. ActiveResource
89
+ 6. admin dashboard
90
+ 7. develoz-ui
91
+ 8. Kamal deployment
92
+ 9. Docker setup
93
+ 10. database backups
94
+
95
+ Answer `y` or `n` to each prompt. You can preselect one feature and continue
96
+ interactively for the rest:
97
+
98
+ ```bash
99
+ develoz new dispatch --auth
100
+ ```
101
+
102
+ Here, authentication is already selected, so the CLI does not ask its prompt.
103
+
104
+ ## Create a new application from flags
105
+
106
+ For a repeatable core-only application, use:
107
+
108
+ ```bash
109
+ develoz new dispatch --yes
110
+ ```
111
+
112
+ Unspecified opt-in features remain disabled. To build an API application with
113
+ authentication and no remaining prompts, make both choices explicit:
114
+
115
+ ```bash
116
+ develoz new dispatch --api --auth --yes
117
+ ```
118
+
119
+ A fully selected example looks like this:
120
+
121
+ ```bash
122
+ develoz new dispatch \
123
+ --api \
124
+ --auth \
125
+ --pwa \
126
+ --push \
127
+ --active-resource \
128
+ --admin \
129
+ --ui \
130
+ --kamal \
131
+ --docker \
132
+ --db-backup \
133
+ --ruby 4.0.5 \
134
+ --rails 8.1 \
135
+ --yes
136
+ ```
137
+
138
+ `--push` also selects PWA support, so `--pwa` is redundant in that example. It
139
+ is shown because an explicit feature list is easier to audit in scripts.
140
+
141
+ ### Finish the generated application
142
+
143
+ Move into the application and install the recorded tools and gems:
144
+
145
+ ```bash
146
+ cd dispatch
147
+ asdf install
148
+ bundle install
149
+ ```
150
+
151
+ With mise, replace `asdf install` with:
152
+
153
+ ```bash
154
+ mise install
155
+ ```
156
+
157
+ If you selected `--ui`, initialize that submodule before `bundle install`:
158
+
159
+ ```bash
160
+ bin/setup_develoz_ui
161
+ bundle install
162
+ ```
163
+
164
+ Before running migrations, inspect the generated files in `db/migrate`. Some
165
+ feature generators create reusable migration templates without timestamped
166
+ filenames. Give each one a unique Rails migration timestamp. The core
167
+ `add_status_transitions` template also uses a placeholder `:records` table;
168
+ replace it with the table that will include `Transitionable`.
169
+
170
+ After adapting those app-specific migrations and configuring PostgreSQL, run:
171
+
172
+ ```bash
173
+ bin/rails db:prepare
174
+ bin/ci
175
+ ```
176
+
177
+ ## Full flag reference
178
+
179
+ All flags below belong to `develoz new APP_NAME`.
180
+
181
+ | Flag | Type | Default | Effect |
182
+ | --- | --- | --- | --- |
183
+ | `--api` | Opt-in | Off | Adds a versioned REST API foundation with Blueprinter and RSwag. |
184
+ | `--auth` | Opt-in | Off | Adds bcrypt-based users, sessions, password resets, routes, and request specs. |
185
+ | `--pwa` | Opt-in | Off | Adds the manifest, service worker, offline page, registration JavaScript, and routes. |
186
+ | `--push` | Opt-in | Off | Adds web push subscriptions, a delivery service, browser code, and VAPID environment keys. PWA is enabled automatically. |
187
+ | `--active-resource` | Opt-in | Off | Adds the `activeresource` gem plus application and example resource models. |
188
+ | `--admin` | Opt-in | Off | Adds an admin namespace, base/dashboard controllers, layout, view, and root route. |
189
+ | `--ui` | Opt-in | Off | Wires the private `develoz-ui` repository as a submodule and gem, plus Importmap pins. |
190
+ | `--kamal` | Opt-in | Off | Adds Kamal, production deployment files, secrets configuration, and a PostgreSQL accessory. |
191
+ | `--docker` | Opt-in | Off | Adds the development Docker Compose stack, development image, scripts, and environment keys. |
192
+ | `--db-backup` | Opt-in | Off | Adds the database backup executable, Rake task, and backup ignore rule. |
193
+ | `--skip-pagy` | Opt-out | Off | Requests frontend core without the Pagy gem and initializer. Pagy is otherwise included. |
194
+ | `--ruby VERSION` | Override | Latest resolved version | Uses `VERSION` for `.tool-versions` and `.ruby-version`. It does not switch the Ruby running the command. |
195
+ | `--rails VERSION` | Override | Latest resolved version | Supplies `VERSION` to Rails version resolution. The `rails` executable already on `PATH` still performs `rails new`. |
196
+ | `--yes` | Execution | Off | Suppresses feature prompts and leaves every unspecified opt-in feature disabled. |
197
+
198
+ When version lookup is unavailable, the resolver falls back to Ruby `4.0.5`
199
+ and Rails `8.1`. The generated `.tool-versions` also records Node.js `24.15.0`
200
+ and PostgreSQL `18`.
201
+
202
+ Thor also exposes `--no-FLAG` and `--skip-FLAG` aliases for boolean options.
203
+ Those aliases explicitly decline one prompt. The dedicated `--skip-pagy` flag
204
+ is the supported product-level opt-out for Pagy.
205
+
206
+ ## Feature matrix
207
+
208
+ ### Always-on core
209
+
210
+ | Generator | What it adds |
211
+ | --- | --- |
212
+ | `develoz:tooling` | VS Code settings, `.env` files, constants initializer, and `dotenv-rails`. |
213
+ | `develoz:testing` | RSpec, Capybara, Selenium, SimpleCov, parallel tests, FactoryBot, and their configuration. |
214
+ | `develoz:solid` | Solid Queue, Solid Cache, Solid Cable, recurring jobs, Mission Control Jobs, and `/jobs`. |
215
+ | `develoz:ci` | `bin/ci`, GitHub Actions, Ruby/security/code-quality gems, and linter configuration. |
216
+ | `develoz:database` | PostgreSQL and `pg_search`, multi-database configuration, and the PostgreSQL 18 tool pin. |
217
+ | `develoz:concerns` | Searchable, optimized finder, transition, and configuration concerns with migrations and specs. |
218
+ | `develoz:strict_loading` | Strict-loading Active Record configuration. |
219
+ | `develoz:maintenance` | Maintenance Tasks, `/maintenance_tasks`, an example task, and maintenance Rake tasks. |
220
+ | `develoz:frontend_core` | Importmap, AnnotateRb, and Pagy by default. |
221
+ | `develoz:docs_render` | Markdown rendering with Redcarpet, Rouge, Mermaid JavaScript, views, styles, and `/docs`. |
222
+ | `develoz:doc_specs` | Screenshot-backed documentation specs, `bin/generate-docs`, and `docs:check`. |
223
+ | `develoz:agents_docs` | `AGENTS.md`, development/testing/performance docs, PR template, Faraday, VCR, and WebMock examples. |
224
+ | `develoz:versioning` | `APP_VERSION`, an `app_version` helper, and a shared version partial. |
225
+
226
+ ### Opt-in features
227
+
228
+ | Flag | Existing-app generator | Main output | Important relationship |
229
+ | --- | --- | --- | --- |
230
+ | `--api` | `develoz:api` | Blueprinter, RSwag, `/api-docs`, API v1 base controller, blueprint, and request spec. | Uses Pagy support from frontend core unless the app supplies an alternative. |
231
+ | `--auth` | `develoz:auth` | User/current models, authentication concern, session/password flows, mailer, migration, and specs. | No other opt-in flag is required. |
232
+ | `--pwa` | `develoz:pwa` | Manifest, service worker, offline page, registration code, and routes. | Required by push. |
233
+ | `--push` | `develoz:push` | `web-push`, subscription model/migration, notification service, browser handlers, and VAPID keys. | Automatically installs PWA output when invoked directly without `--pwa`. |
234
+ | `--active-resource` | `develoz:active_resource` | ActiveResource base and example models. | No other opt-in flag is required. |
235
+ | `--admin` | `develoz:admin` | Admin controllers, layout, dashboard, and namespace route. | Direct generator accepts `--ui` to render its UI-aware template variant. |
236
+ | `--ui` | `develoz:ui` | Local UI submodule for development/test, GitHub gem for production, setup script, and Importmap pins. | Run frontend core first. Requires repository access. |
237
+ | `--kamal` | `develoz:kamal` | Deploy configuration, production Dockerfile, secrets file, and PostgreSQL accessory. | Direct generator accepts `--push` for its push-aware template variant. |
238
+ | `--docker` | `develoz:docker` | Compose stack, development Dockerfile, setup/run scripts, and service environment keys. | Run tooling first so `.env` files exist. |
239
+ | `--db-backup` | `develoz:db_backup` | Backup script, Rake task, and ignored backup directory. | Run after Docker and pass `--docker` to inject the optional Compose service. |
240
+
241
+ ## Adopt Develoz in an existing Rails app
242
+
243
+ Use the application bundle for generators so the command runs against the same
244
+ Ruby and Rails versions as the app:
245
+
246
+ ```bash
247
+ bundle add develoz-rails --group=development
248
+ ```
249
+
250
+ Commit or otherwise back up the current app first. Generators are designed to
251
+ avoid duplicate gem, route, and environment entries, but they also create and
252
+ adapt real application files. Review each change before moving to the next
253
+ generator.
254
+
255
+ ### Apply the complete core baseline
256
+
257
+ From the Rails application root:
258
+
259
+ ```bash
260
+ bin/rails generate develoz:install
261
+ ```
262
+
263
+ Add the same opt-in flags used by `develoz new` when you want optional features:
264
+
265
+ ```bash
266
+ bin/rails generate develoz:install --api --auth --ui
267
+ ```
268
+
269
+ `rails g` is the short form of `rails generate`, so the equivalent command is:
270
+
271
+ ```bash
272
+ rails g develoz:install --api --auth --ui
273
+ ```
274
+
275
+ The installer preserves the manifest order. That makes it the safest choice
276
+ when adopting the complete baseline.
277
+
278
+ ### Apply core generators individually
279
+
280
+ Run only the slices the app needs, in this order when selecting several:
281
+
282
+ ```bash
283
+ rails g develoz:tooling
284
+ rails g develoz:testing
285
+ rails g develoz:solid
286
+ rails g develoz:ci
287
+ rails g develoz:database
288
+ rails g develoz:concerns
289
+ rails g develoz:strict_loading
290
+ rails g develoz:maintenance
291
+ rails g develoz:frontend_core
292
+ rails g develoz:docs_render
293
+ rails g develoz:doc_specs
294
+ rails g develoz:agents_docs
295
+ rails g develoz:versioning
296
+ ```
297
+
298
+ To omit Pagy during incremental adoption, use:
299
+
300
+ ```bash
301
+ rails g develoz:frontend_core --skip-pagy
302
+ ```
303
+
304
+ ### Add one optional feature
305
+
306
+ Each flag maps to a generator that can be run independently:
307
+
308
+ ```bash
309
+ rails g develoz:api
310
+ rails g develoz:auth
311
+ rails g develoz:pwa
312
+ rails g develoz:push
313
+ rails g develoz:active_resource
314
+ rails g develoz:admin
315
+ rails g develoz:ui
316
+ rails g develoz:kamal
317
+ rails g develoz:docker
318
+ rails g develoz:db_backup
319
+ ```
320
+
321
+ Respect these ordering rules:
322
+
323
+ - Run `develoz:tooling` before versioning, push, or Docker so constants and
324
+ environment files exist.
325
+ - Run `develoz:frontend_core` before `develoz:ui` so `config/importmap.rb`
326
+ exists.
327
+ - `develoz:push` installs the PWA prerequisite automatically when needed.
328
+ - Run `develoz:docker` before `develoz:db_backup --docker` if you want the
329
+ backup service inserted into `docker-compose.yml`.
330
+
331
+ For example, to add the UI and an admin dashboard that uses its template
332
+ variant:
333
+
334
+ ```bash
335
+ rails g develoz:frontend_core
336
+ rails g develoz:ui
337
+ rails g develoz:admin --ui
338
+ bin/setup_develoz_ui
339
+ bundle install
340
+ ```
341
+
342
+ After any generator changes the `Gemfile`, run `bundle install`. Review and
343
+ timestamp generated migration templates before running `bin/rails db:migrate`.
344
+
345
+ ## Set up the develoz-ui submodule
346
+
347
+ The UI generator deliberately uses two sources:
348
+
349
+ - development and test load `develoz_ui` from `vendor/develoz-ui`; and
350
+ - production loads `develoz_ui` from `develoz-com/develoz-ui` on GitHub.
351
+
352
+ The generated `.gitmodules` entry uses the SSH URL
353
+ `git@github.com:develoz-com/develoz-ui.git`.
354
+
355
+ ### Check UI prerequisites
356
+
357
+ You need:
358
+
359
+ 1. **asdf or mise.** The app records Ruby, Node.js, and PostgreSQL in
360
+ `.tool-versions`.
361
+ 2. **PostgreSQL 18+.** The database config, Docker stack, and deployment
362
+ accessory target PostgreSQL 18.
363
+ 3. **GitHub access.** Your account and SSH key must be able to read the private
364
+ `develoz-com/develoz-ui` repository. The `gh` CLI is a practical way to
365
+ confirm account-level access; Git still uses SSH for the submodule.
366
+
367
+ Check access before running Bundler:
368
+
369
+ ```bash
370
+ gh auth status
371
+ gh repo view develoz-com/develoz-ui
372
+ ssh -T git@github.com
373
+ ```
374
+
375
+ Install the recorded runtimes with one tool manager:
376
+
377
+ ```bash
378
+ asdf install
379
+ ```
380
+
381
+ or:
382
+
383
+ ```bash
384
+ mise install
385
+ ```
386
+
387
+ ### Initialize the submodule
388
+
389
+ From the generated app root, run:
390
+
391
+ ```bash
392
+ bin/setup_develoz_ui
393
+ ```
394
+
395
+ The script executes:
396
+
397
+ ```bash
398
+ git submodule update --init --recursive vendor/develoz-ui
399
+ ```
400
+
401
+ It exits with an error if `vendor/develoz-ui` is missing or empty. Once the
402
+ script succeeds, install the bundle:
403
+
404
+ ```bash
405
+ bundle install
406
+ ```
407
+
408
+ For a fresh clone of an app that already contains the UI integration, either
409
+ clone recursively or run the setup script after cloning:
410
+
411
+ ```bash
412
+ git clone --recurse-submodules REPOSITORY_URL
413
+ ```
414
+
415
+ or:
416
+
417
+ ```bash
418
+ git clone REPOSITORY_URL
419
+ cd APP_DIRECTORY
420
+ bin/setup_develoz_ui
421
+ ```
422
+
423
+ Production builds also need credentials that let Bundler fetch the private
424
+ GitHub gem source.
425
+
426
+ ## Troubleshooting
427
+
428
+ ### `develoz: command not found`
429
+
430
+ Confirm that the active Ruby owns the installed gem:
431
+
432
+ ```bash
433
+ ruby -v
434
+ gem environment home
435
+ gem list develoz-rails
436
+ ruby -S develoz version
437
+ ```
438
+
439
+ Activate the intended asdf or mise Ruby, reinstall the gem, and ensure that
440
+ Ruby's gem executable directory is on `PATH`.
441
+
442
+ ### `rails new` fails
443
+
444
+ The CLI delegates application creation to the `rails` executable on `PATH`.
445
+ Check it directly:
446
+
447
+ ```bash
448
+ which rails
449
+ rails --version
450
+ rails new scratch_app --skip-test --skip-ci --skip-bundle
451
+ ```
452
+
453
+ Remove the scratch app after the check. `--ruby` records the selected Ruby in
454
+ the generated version files. `--rails` supplies a version to the resolver, but
455
+ the CLI still uses the Rails executable already on `PATH`. Neither flag switches
456
+ the current shell's executables.
457
+
458
+ ### A non-interactive build is prompting
459
+
460
+ Add `--yes`. Feature flags select only the named features; without `--yes`, the
461
+ CLI still asks about every unspecified opt-in feature.
462
+
463
+ ### `--yes` produced only the core stack
464
+
465
+ That is the intended default. List every desired feature before `--yes`, for
466
+ example:
467
+
468
+ ```bash
469
+ develoz new dispatch --api --auth --docker --yes
470
+ ```
471
+
472
+ ### Pagy appeared after `--skip-pagy`
473
+
474
+ The direct frontend generator applies the opt-out itself:
475
+
476
+ ```bash
477
+ rails g develoz:frontend_core --skip-pagy
478
+ ```
479
+
480
+ The top-level installer currently accepts `--skip-pagy` but does not forward
481
+ sub-generator options to frontend core. For a new app, remove the `pagy` Gemfile
482
+ entry and `config/initializers/pagy.rb` before bundling. For an existing app,
483
+ prefer the direct command above when Pagy must be excluded.
484
+
485
+ ### Rails cannot find `develoz:*` generators
486
+
487
+ Make the gem part of the existing application's bundle and use its Rails
488
+ executable:
489
+
490
+ ```bash
491
+ bundle add develoz-rails --group=development
492
+ bundle install
493
+ bin/rails generate develoz:install --help
494
+ ```
495
+
496
+ Run the command from the app root, where `Gemfile` and `config/routes.rb` exist.
497
+
498
+ ### The UI submodule is empty or Bundler cannot find `develoz_ui`
499
+
500
+ First verify both repository and SSH access, then retry setup:
501
+
502
+ ```bash
503
+ gh repo view develoz-com/develoz-ui
504
+ ssh -T git@github.com
505
+ bin/setup_develoz_ui
506
+ ```
507
+
508
+ Do not run `bundle install` before the local submodule exists in development or
509
+ test, because the Gemfile points to `vendor/develoz-ui` in those environments.
510
+
511
+ ### The UI generator did not add Importmap pins
512
+
513
+ The UI generator injects pins into an existing `config/importmap.rb`. Install
514
+ frontend core first, then rerun the idempotent UI generator:
515
+
516
+ ```bash
517
+ rails g develoz:frontend_core
518
+ rails g develoz:ui
519
+ ```
520
+
521
+ ### PostgreSQL cannot connect or reports an incompatible version
522
+
523
+ Confirm PostgreSQL 18 is active:
524
+
525
+ ```bash
526
+ psql --version
527
+ asdf current postgres
528
+ ```
529
+
530
+ With mise, use `mise current` instead of `asdf current postgres`. Then verify
531
+ the app's `DATABASE_URL` or the connection values in `config/database.yml`
532
+ before running `bin/rails db:prepare`.
533
+
534
+ If you selected Docker, the generated Compose stack uses PostgreSQL 18 and the
535
+ default development credentials from `.env`:
536
+
537
+ ```bash
538
+ docker compose up --build -d
539
+ docker compose logs -f postgres
540
+ ```
541
+
542
+ ### Migrations are missing or reference `records`
543
+
544
+ The generators provide reusable migration templates. Prefix generated migration
545
+ filenames with unique Rails timestamps so Rails discovers them. Replace the
546
+ `:records` placeholder in `add_status_transitions` with your model's table name
547
+ before migrating.
548
+
549
+ ### Push was selected without PWA
550
+
551
+ No manual repair is needed. The manifest enables PWA whenever push is selected,
552
+ and the direct `develoz:push` generator also installs its PWA prerequisite.
553
+
554
+ ### The backup service is absent from Docker Compose
555
+
556
+ The backup script and Rake task do not require Docker. To add the optional
557
+ Compose service during existing-app adoption, run Docker first and pass the
558
+ dependency explicitly:
559
+
560
+ ```bash
561
+ rails g develoz:docker
562
+ rails g develoz:db_backup --docker
563
+ ```
564
+
565
+ ## In summary
566
+
567
+ Install `develoz-rails`, use interactive prompts for exploration, and use
568
+ explicit flags plus `--yes` for reproducible builds. The core baseline is always
569
+ installed; product features remain opt-in, with PWA automatically following
570
+ push and Pagy included by default. Existing apps are safest with
571
+ `develoz:install`, while individual generators give finer control when you
572
+ preserve their dependency order. For `develoz-ui`, verify PostgreSQL 18,
573
+ asdf/mise, and GitHub SSH access before initializing the submodule and running
574
+ Bundler.
data/exe/develoz ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require "develoz"
5
+
6
+ Develoz::CLI.start(ARGV)
data/install ADDED
@@ -0,0 +1,98 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ APP_NAME=""
5
+ FLAGS=""
6
+ YES_FLAG=""
7
+
8
+ usage() {
9
+ cat <<EOF
10
+ Usage: curl -fsSL https://raw.githubusercontent.com/develoz-com/rails-template/main/install | bash -s -- APP_NAME [FLAGS]
11
+
12
+ Examples:
13
+ curl -fsSL https://raw.githubusercontent.com/develoz-com/rails-template/main/install | bash -s -- my_app
14
+ curl -fsSL https://raw.githubusercontent.com/develoz-com/rails-template/main/install | bash -s -- my_app --yes --auth --docker
15
+ curl -fsSL https://raw.githubusercontent.com/develoz-com/rails-template/main/install | bash -s -- my_app --yes --api --auth --ui --admin --pwa --push --docker --kamal --db-backup
16
+
17
+ Flags are passed through to develoz new. Use --yes for non-interactive runs.
18
+ EOF
19
+ exit 1
20
+ }
21
+
22
+ for arg in "$@"; do
23
+ case "$arg" in
24
+ --help|-h)
25
+ usage
26
+ ;;
27
+ --yes)
28
+ YES_FLAG="--yes"
29
+ ;;
30
+ *)
31
+ if [ -z "$APP_NAME" ]; then
32
+ APP_NAME="$arg"
33
+ else
34
+ FLAGS="$FLAGS $arg"
35
+ fi
36
+ ;;
37
+ esac
38
+ done
39
+
40
+ if [ -z "$APP_NAME" ]; then
41
+ echo "Error: APP_NAME is required."
42
+ echo
43
+ usage
44
+ fi
45
+
46
+ REPO_URL="${DEVELOZ_RAILS_REPO:-https://github.com/develoz-com/rails-template.git}"
47
+ REPO_REF="${DEVELOZ_RAILS_REF:-main}"
48
+
49
+ if ! command -v ruby &>/dev/null; then
50
+ echo "Error: ruby is not installed."
51
+ echo "Install Ruby 3.4+ (or 4.0+) via asdf, rbenv, or your system package manager."
52
+ exit 1
53
+ fi
54
+
55
+ if ! command -v gem &>/dev/null; then
56
+ echo "Error: gem is not installed."
57
+ exit 1
58
+ fi
59
+
60
+ if ! command -v git &>/dev/null; then
61
+ echo "Error: git is not installed."
62
+ exit 1
63
+ fi
64
+
65
+ if ! command -v rails &>/dev/null; then
66
+ echo "rails not found — installing rails..."
67
+ gem install rails --no-document
68
+ fi
69
+
70
+ CLONE_DIR="$(mktemp -d)"
71
+ cleanup() { rm -rf "$CLONE_DIR"; }
72
+ trap cleanup EXIT
73
+
74
+ echo "Fetching develoz-rails ($REPO_REF)..."
75
+ git clone --depth 1 --branch "$REPO_REF" "$REPO_URL" "$CLONE_DIR" &>/dev/null
76
+
77
+ echo "Building and installing develoz-rails gem..."
78
+ (
79
+ cd "$CLONE_DIR"
80
+ gem build develoz-rails.gemspec &>/dev/null
81
+ gem install ./develoz-rails-*.gem --no-document &>/dev/null
82
+ )
83
+
84
+ echo ""
85
+ echo "Generating Rails app: $APP_NAME"
86
+ echo "Flags: $YES_FLAG$FLAGS"
87
+ echo ""
88
+
89
+ develoz new "$APP_NAME" $YES_FLAG $FLAGS
90
+
91
+ echo ""
92
+ echo "Done! Created $APP_NAME with Develoz Rails template."
93
+ echo ""
94
+ echo "Next steps:"
95
+ echo " cd $APP_NAME"
96
+ echo " bundle install"
97
+ echo " bin/rails db:prepare"
98
+ echo " bin/rails server"