backstage 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 (44) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +27 -0
  3. data/CONTRIBUTING.md +70 -0
  4. data/LICENSE +21 -0
  5. data/README.md +195 -0
  6. data/app/assets/stylesheets/backstage/backstage.css +5 -0
  7. data/app/controllers/backstage/actions_controller.rb +27 -0
  8. data/app/controllers/backstage/application_controller.rb +21 -0
  9. data/app/controllers/backstage/dashboards_controller.rb +15 -0
  10. data/app/controllers/backstage/home_controller.rb +14 -0
  11. data/app/controllers/backstage/resources_controller.rb +94 -0
  12. data/app/views/backstage/dashboards/show.html.erb +36 -0
  13. data/app/views/backstage/fields/_belongs_to.html.erb +7 -0
  14. data/app/views/backstage/fields/_boolean.html.erb +1 -0
  15. data/app/views/backstage/fields/_date.html.erb +1 -0
  16. data/app/views/backstage/fields/_datetime.html.erb +1 -0
  17. data/app/views/backstage/fields/_enum.html.erb +4 -0
  18. data/app/views/backstage/fields/_has_many.html.erb +19 -0
  19. data/app/views/backstage/fields/_image_url.html.erb +5 -0
  20. data/app/views/backstage/fields/_integer.html.erb +1 -0
  21. data/app/views/backstage/fields/_string.html.erb +1 -0
  22. data/app/views/backstage/fields/_text.html.erb +1 -0
  23. data/app/views/backstage/fields/_thumbnails.html.erb +13 -0
  24. data/app/views/backstage/home/index.html.erb +24 -0
  25. data/app/views/backstage/resources/edit.html.erb +18 -0
  26. data/app/views/backstage/resources/index.html.erb +54 -0
  27. data/app/views/backstage/resources/new.html.erb +13 -0
  28. data/app/views/layouts/backstage/backstage.html.erb +59 -0
  29. data/config/routes.rb +15 -0
  30. data/lib/backstage/association_config.rb +31 -0
  31. data/lib/backstage/auto_discovery.rb +58 -0
  32. data/lib/backstage/configuration.rb +31 -0
  33. data/lib/backstage/dashboard_config.rb +15 -0
  34. data/lib/backstage/engine.rb +11 -0
  35. data/lib/backstage/field.rb +39 -0
  36. data/lib/backstage/registry.rb +32 -0
  37. data/lib/backstage/resource_config.rb +91 -0
  38. data/lib/backstage/sidebar_config.rb +15 -0
  39. data/lib/backstage/version.rb +3 -0
  40. data/lib/backstage.rb +56 -0
  41. data/lib/generators/backstage/install/install_generator.rb +29 -0
  42. data/lib/generators/backstage/install/templates/SKILL.md +221 -0
  43. data/lib/generators/backstage/install/templates/backstage.yml +16 -0
  44. metadata +95 -0
@@ -0,0 +1,221 @@
1
+ ---
2
+ name: backstage-install
3
+ description: Install and configure the Backstage admin engine gem. Checks compatibility, wires up authentication, registers models, optionally configures per-resource DSL and associations, and verifies the admin interface is reachable.
4
+ ---
5
+
6
+ # backstage-install
7
+
8
+ Complete installation and setup of the Backstage admin engine in this Rails app. Work through each step in order, confirming with the user before making any changes.
9
+
10
+ ---
11
+
12
+ ## Step 1 — Compatibility check
13
+
14
+ Read `Gemfile`, `Gemfile.lock`, and `.ruby-version` (if present) to check:
15
+
16
+ - **Ruby >= 3.2** — stop with a clear error if not met
17
+ - **Rails >= 8.0** — check `Gemfile.lock` for the rails gem version; stop if not met
18
+ - **Asset pipeline** — check Gemfile for `propshaft`. Backstage vendors its own CSS and serves it via Propshaft. If the app uses Sprockets instead, warn the user and note that they may need to add `//= link backstage/backstage.css` to `app/assets/config/manifest.js`
19
+ - **Conflicts** — check for other admin gems (`rails_admin`, `activeadmin`, `administrate`). Note any found but do not block installation
20
+
21
+ Report findings before proceeding.
22
+
23
+ ---
24
+
25
+ ## Step 2 — Add gem to Gemfile
26
+
27
+ Check if `backstage` already appears in the Gemfile. If not:
28
+
29
+ - Add `gem "backstage"` to the Gemfile
30
+ - Run `bundle install`
31
+
32
+ If already present, skip to Step 3.
33
+
34
+ ---
35
+
36
+ ## Step 3 — Run the install generator
37
+
38
+ Check `config/routes.rb` for an existing `mount Backstage::Engine` line.
39
+
40
+ If absent, run the generator:
41
+
42
+ ```bash
43
+ bin/rails generate backstage:install
44
+ ```
45
+
46
+ This creates `config/backstage.yml` and adds the mount to `config/routes.rb`. If the generator has already been run, skip this step and proceed with the existing files.
47
+
48
+ ---
49
+
50
+ ## Step 4 — Configure authentication
51
+
52
+ Backstage calls a method on `current_user` to check admin access. You must tell it how to find the current user.
53
+
54
+ Ask the user:
55
+
56
+ 1. **How is the current user provided?** Common answers: Devise (`current_user`), a custom session helper, a JWT token — or "I don't have auth yet"
57
+ 2. **What method on the user object indicates admin access?** (default: `is_admin?`)
58
+ 3. **Where should non-admins be redirected?** (default: `/`)
59
+
60
+ Check `config/initializers/` for an existing Backstage initializer. If none exists, create `config/initializers/backstage.rb`:
61
+
62
+ ```ruby
63
+ Rails.application.config.to_prepare do
64
+ Backstage::ApplicationController.class_eval do
65
+ def current_user
66
+ # TODO: replace with your actual current_user lookup
67
+ # e.g. User.find_by(id: session[:user_id])
68
+ # e.g. Current.user (if using Current attributes)
69
+ nil
70
+ end
71
+ end
72
+ end
73
+ ```
74
+
75
+ Then update `config/backstage.yml` with the answers from above:
76
+
77
+ ```yaml
78
+ admin_user_method: is_admin? # or whatever method they specified
79
+ redirect_on_failure: /login # or wherever they want non-admins to go
80
+ ```
81
+
82
+ If the user doesn't have authentication set up yet, add the TODO comment and note that the admin will redirect everyone until it's wired up.
83
+
84
+ ---
85
+
86
+ ## Step 5 — Register models
87
+
88
+ Read `app/models/` to list the available ActiveRecord models (skip `ApplicationRecord` and concerns).
89
+
90
+ Show the list and ask: **Which models should appear in the admin?**
91
+
92
+ Update the `models:` list in `config/backstage.yml` with their choices:
93
+
94
+ ```yaml
95
+ models:
96
+ - Article
97
+ - User
98
+ - Tag
99
+ ```
100
+
101
+ Backstage auto-discovers columns for each model — no further configuration is needed for basic CRUD.
102
+
103
+ ---
104
+
105
+ ## Step 6 — Optional: per-resource DSL
106
+
107
+ Ask the user: **"Would you like to configure any field overrides, associations, or sidebar links for these models? (optional — you can always add these later)"**
108
+
109
+ If yes, for each model they want to configure, create `config/backstage/<model_name_lowercase>.rb`. Common patterns:
110
+
111
+ **Set the display column** (used in belongs-to dropdowns and search):
112
+ ```ruby
113
+ Backstage.resource(:Article) do |c|
114
+ c.display_column :title
115
+ end
116
+ ```
117
+
118
+ **Override a field type:**
119
+ ```ruby
120
+ Backstage.resource(:Article) do |c|
121
+ c.field :body, as: :text
122
+ c.field :cover_image_url, as: :image_url
123
+ end
124
+ ```
125
+
126
+ **Belongs-to association** (replaces the raw foreign key field with a dropdown):
127
+ ```ruby
128
+ Backstage.resource(:Article) do |c|
129
+ c.belongs_to :author, display_column: :name, class_name: "User"
130
+ end
131
+ ```
132
+
133
+ **Has-many checkbox list:**
134
+ ```ruby
135
+ Backstage.resource(:Article) do |c|
136
+ c.has_many :tags, display_column: :name
137
+ end
138
+ ```
139
+
140
+ **Sidebar links on the edit page:**
141
+ ```ruby
142
+ Backstage.resource(:Article) do |c|
143
+ c.sidebar do |s|
144
+ s.link "View on site", ->(record) { "/posts/#{record.id}" }
145
+ end
146
+ end
147
+ ```
148
+
149
+ Only create files for models where the user wants customisation. Skip this step entirely if they prefer to configure later.
150
+
151
+ ---
152
+
153
+ ## Step 7 — Optional: dashboard
154
+
155
+ Ask: **"Would you like a dashboard — a filtered view of a model with a named scope? (optional)"**
156
+
157
+ If yes, ask for:
158
+ 1. The model name
159
+ 2. The scope name (must be a named scope on the model, e.g. `published`, `pending`)
160
+ 3. A display name for the dashboard (e.g. "Published Articles")
161
+
162
+ Add to `config/backstage.yml`:
163
+
164
+ ```yaml
165
+ dashboards:
166
+ - name: "Published Articles"
167
+ model: Article
168
+ scope:
169
+ status: published
170
+ ```
171
+
172
+ Note: the scope value must match a value that `Model.where(scope_hash)` can accept. For integer-backed enums, use the integer value (e.g. `status: 1`).
173
+
174
+ ---
175
+
176
+ ## Step 8 — Verify
177
+
178
+ Start the Rails server (if not already running) and ask the user to visit `/admin` (or whatever path the engine is mounted at).
179
+
180
+ Check `config/routes.rb` to confirm the mount path. If the path is not `/admin`, tell the user the correct URL.
181
+
182
+ Expected results:
183
+ - Non-admin users (or unauthenticated users) are redirected to `redirect_on_failure`
184
+ - Admin users see the Backstage home page listing registered models and their record counts
185
+ - Each model links to a paginated, searchable index table
186
+ - Each record has an edit form with auto-discovered fields
187
+
188
+ If the user reports a problem, help diagnose:
189
+ - 404 → engine not mounted, or wrong path
190
+ - Redirect loop → `current_user` method raises or returns unexpected value
191
+ - Empty model list → `config/backstage.yml` not loaded, or model names misspelled
192
+ - Missing columns → model table may not exist yet; run `rails db:migrate`
193
+
194
+ ---
195
+
196
+ ## Step 9 — Optional commit
197
+
198
+ Ask: **"Would you like to commit these changes?"**
199
+
200
+ If yes, stage only the files created or modified during this setup:
201
+
202
+ ```bash
203
+ git add Gemfile Gemfile.lock config/routes.rb config/backstage.yml \
204
+ config/initializers/backstage.rb
205
+ # add any DSL files created in Step 6:
206
+ # git add config/backstage/article.rb config/backstage/user.rb
207
+ git commit -m "Install Backstage admin engine"
208
+ ```
209
+
210
+ Do not use `git add -A` — only stage Backstage-related files.
211
+
212
+ ---
213
+
214
+ ## Summary
215
+
216
+ After all steps complete, print a summary of:
217
+ - Mount path and admin URL
218
+ - Models registered
219
+ - Authentication method wired up (or TODOs remaining)
220
+ - Any DSL or dashboard configuration added
221
+ - Any manual steps remaining (implementing `current_user`, adding `is_admin?` to the User model, Sprockets manifest updates if applicable)
@@ -0,0 +1,16 @@
1
+ # Backstage configuration
2
+ #
3
+ # List the models you want to manage:
4
+ # models:
5
+ # - Article
6
+ # - User
7
+ models: []
8
+
9
+ # Method called on current_user to check admin access (default: is_admin?)
10
+ # admin_user_method: is_admin?
11
+
12
+ # Where to redirect non-admin users (default: /)
13
+ # redirect_on_failure: /
14
+
15
+ # Records per page (default: 25)
16
+ # per_page: 25
metadata ADDED
@@ -0,0 +1,95 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: backstage
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Gareth James
8
+ bindir: bin
9
+ cert_chain: []
10
+ date: 2026-05-18 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: railties
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '8.0'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '8.0'
26
+ email:
27
+ - g.claude@bemused.org
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - CHANGELOG.md
33
+ - CONTRIBUTING.md
34
+ - LICENSE
35
+ - README.md
36
+ - app/assets/stylesheets/backstage/backstage.css
37
+ - app/controllers/backstage/actions_controller.rb
38
+ - app/controllers/backstage/application_controller.rb
39
+ - app/controllers/backstage/dashboards_controller.rb
40
+ - app/controllers/backstage/home_controller.rb
41
+ - app/controllers/backstage/resources_controller.rb
42
+ - app/views/backstage/dashboards/show.html.erb
43
+ - app/views/backstage/fields/_belongs_to.html.erb
44
+ - app/views/backstage/fields/_boolean.html.erb
45
+ - app/views/backstage/fields/_date.html.erb
46
+ - app/views/backstage/fields/_datetime.html.erb
47
+ - app/views/backstage/fields/_enum.html.erb
48
+ - app/views/backstage/fields/_has_many.html.erb
49
+ - app/views/backstage/fields/_image_url.html.erb
50
+ - app/views/backstage/fields/_integer.html.erb
51
+ - app/views/backstage/fields/_string.html.erb
52
+ - app/views/backstage/fields/_text.html.erb
53
+ - app/views/backstage/fields/_thumbnails.html.erb
54
+ - app/views/backstage/home/index.html.erb
55
+ - app/views/backstage/resources/edit.html.erb
56
+ - app/views/backstage/resources/index.html.erb
57
+ - app/views/backstage/resources/new.html.erb
58
+ - app/views/layouts/backstage/backstage.html.erb
59
+ - config/routes.rb
60
+ - lib/backstage.rb
61
+ - lib/backstage/association_config.rb
62
+ - lib/backstage/auto_discovery.rb
63
+ - lib/backstage/configuration.rb
64
+ - lib/backstage/dashboard_config.rb
65
+ - lib/backstage/engine.rb
66
+ - lib/backstage/field.rb
67
+ - lib/backstage/registry.rb
68
+ - lib/backstage/resource_config.rb
69
+ - lib/backstage/sidebar_config.rb
70
+ - lib/backstage/version.rb
71
+ - lib/generators/backstage/install/install_generator.rb
72
+ - lib/generators/backstage/install/templates/SKILL.md
73
+ - lib/generators/backstage/install/templates/backstage.yml
74
+ homepage: https://github.com/gjtorikian/backstage
75
+ licenses:
76
+ - MIT
77
+ metadata: {}
78
+ rdoc_options: []
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - ">="
84
+ - !ruby/object:Gem::Version
85
+ version: 3.2.0
86
+ required_rubygems_version: !ruby/object:Gem::Requirement
87
+ requirements:
88
+ - - ">="
89
+ - !ruby/object:Gem::Version
90
+ version: '0'
91
+ requirements: []
92
+ rubygems_version: 3.6.2
93
+ specification_version: 4
94
+ summary: A lightweight, configurable admin interface for Rails 8
95
+ test_files: []