maquina-generators 0.5.0 → 0.7.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 (109) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +125 -15
  3. data/lib/generators/maquina/app/app_generator.rb +9 -4
  4. data/lib/generators/maquina/app/templates/README.md.erb +6 -4
  5. data/lib/generators/maquina/app/templates/app/views/home/index.html.erb +18 -5
  6. data/lib/generators/maquina/app/templates/config/database.yml.tt +12 -0
  7. data/lib/generators/maquina/clave/clave_generator.rb +48 -0
  8. data/lib/generators/maquina/clave/templates/app/controllers/registration/verifications_controller.rb.tt +10 -1
  9. data/lib/generators/maquina/clave/templates/app/controllers/session/verifications_controller.rb.tt +10 -1
  10. data/lib/generators/maquina/clave/templates/app/models/email_verification.rb.tt +18 -0
  11. data/lib/generators/maquina/clave/templates/config/locales/clave.en.yml +2 -0
  12. data/lib/generators/maquina/clave/templates/config/locales/clave.es.yml +2 -0
  13. data/lib/generators/maquina/csp_reports/USAGE +18 -0
  14. data/lib/generators/maquina/csp_reports/csp_reports_generator.rb +231 -0
  15. data/lib/generators/maquina/csp_reports/templates/app/controllers/csp_reports_controller.rb +24 -0
  16. data/lib/generators/maquina/csp_reports/templates/app/models/security/csp_violation.rb +89 -0
  17. data/lib/generators/maquina/csp_reports/templates/app/models/security/csp_violation_report.rb +30 -0
  18. data/lib/generators/maquina/csp_reports/templates/app/views/backstage/security/_csp_violations.html.erb +42 -0
  19. data/lib/generators/maquina/csp_reports/templates/db/create_csp_violations.rb.tt +23 -0
  20. data/lib/generators/maquina/mission_control_jobs/mission_control_jobs_generator.rb +32 -1
  21. data/lib/generators/maquina/mission_control_jobs/templates/app/controllers/backstage_dashboard_controller.rb +47 -0
  22. data/lib/generators/maquina/mission_control_jobs/templates/app/views/backstage_dashboard/index.html.erb.tt +93 -0
  23. data/lib/generators/maquina/mission_control_jobs/templates/app/views/layouts/_admin_navigation.html.erb.tt +18 -6
  24. data/lib/generators/maquina/mission_control_jobs/templates/app/views/layouts/admin.html.erb +21 -0
  25. data/lib/generators/maquina/rack_attack/USAGE +8 -6
  26. data/lib/generators/maquina/rack_attack/rack_attack_generator.rb +6 -2
  27. data/lib/generators/maquina/rack_attack/templates/config/initializers/rack_attack.rb.tt +139 -57
  28. data/lib/generators/maquina/security/USAGE +15 -0
  29. data/lib/generators/maquina/security/security_generator.rb +278 -0
  30. data/lib/generators/maquina/security/templates/app/controllers/backstage/security_controller.rb.tt +45 -0
  31. data/{test/tmp/app/controllers/backstage_controller.rb → lib/generators/maquina/security/templates/app/controllers/backstage_controller.rb.tt} +0 -1
  32. data/lib/generators/maquina/security/templates/app/controllers/backstage_dashboard_controller.rb +47 -0
  33. data/lib/generators/maquina/security/templates/app/models/security/abuse_event.rb +36 -0
  34. data/lib/generators/maquina/security/templates/app/models/security/abuse_report.rb +112 -0
  35. data/lib/generators/maquina/security/templates/app/models/security/record.rb +6 -0
  36. data/lib/generators/maquina/security/templates/app/views/backstage/security/_addresses.html.erb +37 -0
  37. data/lib/generators/maquina/security/templates/app/views/backstage/security/_blocked.html.erb +53 -0
  38. data/lib/generators/maquina/security/templates/app/views/backstage/security/_by_day.html.erb +33 -0
  39. data/lib/generators/maquina/security/templates/app/views/backstage/security/_hosts.html.erb +31 -0
  40. data/lib/generators/maquina/security/templates/app/views/backstage/security/_paths.html.erb +33 -0
  41. data/lib/generators/maquina/security/templates/app/views/backstage/security/_recent.html.erb +37 -0
  42. data/lib/generators/maquina/security/templates/app/views/backstage/security/_utc_time.html.erb +2 -0
  43. data/lib/generators/maquina/security/templates/app/views/backstage/security/show.html.erb +47 -0
  44. data/lib/generators/maquina/security/templates/app/views/backstage_dashboard/index.html.erb.tt +93 -0
  45. data/lib/generators/maquina/security/templates/app/views/layouts/_admin_navigation.html.erb.tt +40 -0
  46. data/lib/generators/maquina/security/templates/app/views/layouts/admin.html.erb +21 -0
  47. data/{test/tmp/app/views/layouts/solid_errors/application.html.erb → lib/generators/maquina/security/templates/app/views/layouts/backstage/security.html.erb} +1 -1
  48. data/lib/generators/maquina/security/templates/config/initializers/rack_attack_events.rb +34 -0
  49. data/lib/generators/maquina/security/templates/db/security_schema.rb.tt +27 -0
  50. data/lib/generators/maquina/solid_errors/solid_errors_generator.rb +32 -1
  51. data/lib/generators/maquina/solid_errors/templates/app/controllers/backstage_dashboard_controller.rb +47 -0
  52. data/lib/generators/maquina/solid_errors/templates/app/views/backstage_dashboard/index.html.erb.tt +93 -0
  53. data/lib/generators/maquina/solid_errors/templates/app/views/layouts/_admin_navigation.html.erb.tt +18 -6
  54. data/lib/generators/maquina/solid_errors/templates/app/views/layouts/admin.html.erb +21 -0
  55. data/lib/generators/maquina/solid_errors/templates/app/views/solid_errors/error_mailer/error_occurred.html.erb +65 -0
  56. data/lib/generators/maquina/solid_errors/templates/app/views/solid_errors/error_mailer/error_occurred.text.erb +30 -0
  57. data/lib/generators/maquina/solid_errors/templates/config/initializers/solid_errors.rb.tt +12 -0
  58. data/lib/maquina_generators/version.rb +1 -1
  59. data/test/generators/maquina/app_generator_test.rb +21 -0
  60. data/test/generators/maquina/clave_generator_test.rb +74 -0
  61. data/test/generators/maquina/csp_reports_generator_test.rb +151 -0
  62. data/test/generators/maquina/mission_control_jobs_generator_test.rb +28 -4
  63. data/test/generators/maquina/rack_attack_generator_test.rb +41 -19
  64. data/test/generators/maquina/security_generator_test.rb +380 -0
  65. data/test/generators/maquina/solid_errors_generator_test.rb +59 -4
  66. data/test/tmp/.gitignore +5 -0
  67. data/test/tmp/.rubocop.yml +11 -0
  68. data/test/tmp/.standard.yml +1 -0
  69. data/test/tmp/Gemfile +12 -2
  70. data/test/tmp/Procfile.dev +3 -0
  71. data/test/tmp/README.md +89 -0
  72. data/test/tmp/app/controllers/home_controller.rb +6 -0
  73. data/test/tmp/app/javascript/application.js +1 -0
  74. data/test/tmp/app/views/home/index.html.erb +204 -0
  75. data/test/tmp/app/views/layouts/application.html.erb +10 -0
  76. data/test/tmp/config/application.rb +15 -0
  77. data/test/tmp/config/database.yml +90 -0
  78. data/test/tmp/config/database.yml.example +90 -0
  79. data/test/tmp/config/environments/development.rb +8 -0
  80. data/test/tmp/config/environments/production.rb +6 -0
  81. data/test/tmp/config/initializers/generators.rb +4 -0
  82. data/test/tmp/config/routes.rb +1 -1
  83. metadata +60 -32
  84. data/test/tmp/app/agents/error_redactor.rb +0 -34
  85. data/test/tmp/app/agents/errors_query.rb +0 -84
  86. data/test/tmp/app/agents/failure_triage.rb +0 -21
  87. data/test/tmp/app/agents/get_exception_tool.rb +0 -26
  88. data/test/tmp/app/agents/list_failures_tool.rb +0 -20
  89. data/test/tmp/app/agents/top_exceptions_tool.rb +0 -18
  90. data/test/tmp/app/helpers/solid_errors_helper.rb +0 -9
  91. data/test/tmp/app/javascript/controllers/backtrace_filter_controller.js +0 -27
  92. data/test/tmp/app/javascript/controllers/clipboard_controller.js +0 -36
  93. data/test/tmp/app/views/layouts/_admin_navigation.html.erb +0 -28
  94. data/test/tmp/app/views/solid_errors/errors/_actions.html.erb +0 -22
  95. data/test/tmp/app/views/solid_errors/errors/_delete_button.html.erb +0 -10
  96. data/test/tmp/app/views/solid_errors/errors/_error_card.html.erb +0 -63
  97. data/test/tmp/app/views/solid_errors/errors/_resolve_button.html.erb +0 -11
  98. data/test/tmp/app/views/solid_errors/errors/index.html.erb +0 -37
  99. data/test/tmp/app/views/solid_errors/errors/show/_actions.html.erb +0 -33
  100. data/test/tmp/app/views/solid_errors/errors/show/_error_details.html.erb +0 -95
  101. data/test/tmp/app/views/solid_errors/errors/show/_header.html.erb +0 -18
  102. data/test/tmp/app/views/solid_errors/errors/show/_properties.html.erb +0 -65
  103. data/test/tmp/app/views/solid_errors/errors/show.html.erb +0 -23
  104. data/test/tmp/app/views/solid_errors/occurrences/_backtrace_line.html.erb +0 -27
  105. data/test/tmp/app/views/solid_errors/occurrences/_collection.html.erb +0 -80
  106. data/test/tmp/app/views/solid_errors/occurrences/_occurrence.html.erb +0 -129
  107. data/test/tmp/bin/failures +0 -37
  108. data/test/tmp/bin/failures-mcp +0 -21
  109. data/test/tmp/config/initializers/solid_errors.rb +0 -12
@@ -96,25 +96,61 @@ class Maquina::Generators::SolidErrorsGeneratorTest < Rails::Generators::TestCas
96
96
  test "adds route with prefix" do
97
97
  run_generator %w[--prefix /admin]
98
98
 
99
- assert_file "config/routes.rb", %r{mount SolidErrors::Engine, at: "/admin/solid_errors"}
99
+ assert_file "config/routes.rb", %r{mount SolidErrors::Engine, at: "/admin/errors"}
100
100
  end
101
101
 
102
102
  test "adds route with custom prefix" do
103
103
  run_generator %w[--prefix /backstage]
104
104
 
105
- assert_file "config/routes.rb", %r{mount SolidErrors::Engine, at: "/backstage/solid_errors"}
105
+ assert_file "config/routes.rb", %r{mount SolidErrors::Engine, at: "/backstage/errors"}
106
106
  end
107
107
 
108
108
  test "generates admin navigation partial" do
109
109
  run_generator %w[--prefix /admin]
110
110
 
111
111
  assert_file "app/views/layouts/_admin_navigation.html.erb" do |content|
112
- assert_match(%r{/admin/solid_errors}, content)
113
- assert_match(%r{/admin/mission_control_jobs}, content)
112
+ assert_match(%r{/admin/errors}, content)
113
+ assert_match(%r{/admin/jobs}, content)
114
114
  assert_match(/main_app\.root_path/, content)
115
115
  end
116
116
  end
117
117
 
118
+ test "navigation includes an Overview tab pointing at the prefix root" do
119
+ run_generator %w[--prefix /admin]
120
+
121
+ assert_file "app/views/layouts/_admin_navigation.html.erb" do |content|
122
+ assert_match(/<span>Overview<\/span>/, content)
123
+ assert_match(%r{link_to "/admin",}, content)
124
+ end
125
+ end
126
+
127
+ test "installs the backstage dashboard" do
128
+ run_generator %w[--prefix /admin]
129
+
130
+ assert_file "app/controllers/backstage_dashboard_controller.rb" do |content|
131
+ assert_match(/class BackstageDashboardController < BackstageController/, content)
132
+ assert_match(/authenticate_or_request_with_http_basic/, content)
133
+ assert_match(/@metrics = \[\]/, content)
134
+ end
135
+ assert_file "app/views/layouts/admin.html.erb", /admin_navigation/
136
+ assert_file "app/views/backstage_dashboard/index.html.erb" do |content|
137
+ assert_match(/Overview/, content)
138
+ assert_match(%r{defined\?\(SolidErrors::Engine\)}, content)
139
+ assert_match(%r{"/admin/errors"}, content)
140
+ assert_match(%r{"/admin/jobs"}, content)
141
+ end
142
+ assert_file "config/routes.rb", %r{get "/admin" => "backstage_dashboard#index"}
143
+ end
144
+
145
+ test "does not duplicate the dashboard route when run twice" do
146
+ run_generator %w[--prefix /admin]
147
+ run_generator %w[--prefix /admin]
148
+
149
+ assert_file "config/routes.rb" do |content|
150
+ assert_equal 1, content.scan("backstage_dashboard#index").length
151
+ end
152
+ end
153
+
118
154
  test "does not overwrite existing admin navigation" do
119
155
  mkdir_p("app/views/layouts")
120
156
  File.write(
@@ -152,6 +188,25 @@ class Maquina::Generators::SolidErrorsGeneratorTest < Rails::Generators::TestCas
152
188
  assert_file "app/views/solid_errors/occurrences/_backtrace_line.html.erb"
153
189
  end
154
190
 
191
+ test "copies self-contained mailer templates that avoid dashboard-only helpers" do
192
+ run_generator %w[--prefix /admin]
193
+
194
+ %w[
195
+ app/views/solid_errors/error_mailer/error_occurred.html.erb
196
+ app/views/solid_errors/error_mailer/error_occurred.text.erb
197
+ ].each do |path|
198
+ assert_file path do |content|
199
+ # The mailer renders without the BackstageController helpers, so these
200
+ # templates must not reuse the themed dashboard partials or their
201
+ # icon_for/Stimulus dependencies (the cause of the email render loop).
202
+ body = content.gsub(/<%#.*?%>/m, "")
203
+ assert_no_match(/icon_for/, body)
204
+ assert_no_match(/data-controller/, body)
205
+ assert_no_match(%r{render\s+["']solid_errors/}, body)
206
+ end
207
+ end
208
+ end
209
+
155
210
  test "copies layout with admin navigation and updated title" do
156
211
  run_generator %w[--prefix /admin]
157
212
 
@@ -0,0 +1,5 @@
1
+ /log/*
2
+ /tmp/*
3
+
4
+ # Ignore database configuration
5
+ config/database.yml
@@ -0,0 +1,11 @@
1
+ # standard.rb's runner bridge, not custom RuboCop rules.
2
+ #
3
+ # This is the entry point RuboCop (and editors/LSP) need to run the Standard
4
+ # ruleset — all style comes from the `standard` gem via config/base.yml below.
5
+ # Keep this file even though general guidance says "no .rubocop.yml": for
6
+ # standard.rb this IS the runner config, not a custom rule set.
7
+ require:
8
+ - standard
9
+
10
+ inherit_gem:
11
+ standard: config/base.yml
@@ -0,0 +1 @@
1
+ ruby_version: 3.2
data/test/tmp/Gemfile CHANGED
@@ -1,5 +1,15 @@
1
1
  source "https://rubygems.org"
2
2
 
3
- gem "solid_errors"
3
+ gem "brakeman", group: :development
4
4
 
5
- gem "mcp"
5
+ gem "bundle-audit", group: :development
6
+
7
+ gem "letter_opener", group: :development
8
+
9
+ gem "standard", ">= 1.54", group: :development
10
+
11
+ gem "rails-i18n"
12
+
13
+ gem "maquina-components"
14
+
15
+ gem "aws-sdk-s3", group: :production
@@ -0,0 +1,3 @@
1
+ web: bin/rails server -p 3000
2
+ css: bin/rails tailwindcss:watch
3
+ solid_queue: bin/rails solid_queue:start
@@ -0,0 +1,89 @@
1
+ # Tmp
2
+
3
+ Built with [maquina.app](https://maquina.app) — production-tested tools for developers who ship alone.
4
+
5
+ ## Getting Started
6
+
7
+ ### Prerequisites
8
+
9
+ - Ruby 3.2+
10
+ - Rails 8+
11
+ - PostgreSQL (or SQLite for development)
12
+
13
+ ### Setup
14
+
15
+ ```bash
16
+ bin/setup # Install dependencies and prepare databases
17
+ bin/dev # Start all processes (web, css, solid_queue)
18
+ ```
19
+
20
+ Your app will be running at **http://localhost:3000**.
21
+
22
+ ## What's Included
23
+
24
+ | Feature | Description |
25
+ |---------|-------------|
26
+ | **Background Jobs** | Solid Queue with Mission Control Jobs dashboard |
27
+ | **Error Tracking** | Solid Errors with custom UI |
28
+ | **Rate Limiting** | Rack::Attack with sensible defaults |
29
+ | **UI Components** | Maquina Components (ERB partials + Tailwind + Stimulus) |
30
+ | **Caching** | Solid Cache |
31
+ | **WebSockets** | Solid Cable |
32
+ | **Rich Text** | Action Text |
33
+ | **File Storage** | Active Storage (S3-ready in production) |
34
+ | **Multi-database** | Separate databases for queue, cache, cable, errors, and security |
35
+
36
+ ## Development URLs
37
+
38
+ | URL | Description |
39
+ |-----|-------------|
40
+ | http://localhost:3000 | Application |
41
+ | http://localhost:3000/admin | Admin overview |
42
+ | http://localhost:3000/admin/errors | Errors dashboard |
43
+ | http://localhost:3000/admin/jobs | Jobs dashboard |
44
+ | http://localhost:3000/admin/security | Security dashboard |
45
+
46
+ ## Scripts
47
+
48
+ - `bin/setup` — Install dependencies and prepare databases
49
+ - `bin/dev` — Start all processes (web, css, solid_queue)
50
+
51
+ ## Credentials
52
+
53
+ Edit credentials with:
54
+
55
+ ```bash
56
+ bin/rails credentials:edit
57
+ ```
58
+
59
+ Add backstage credentials for the admin dashboards (overview, errors, jobs, security):
60
+
61
+ ```yaml
62
+ backstage:
63
+ username: your_user
64
+ password: your_password
65
+ ```
66
+
67
+ ## Maquina Ecosystem
68
+
69
+ ### UI Components
70
+
71
+ [Maquina Components](https://maquina.app/documentation/components/) — a library of ERB partials, Tailwind CSS styles, and Stimulus controllers for building consistent, accessible UIs in Rails.
72
+
73
+ ### AI Tools
74
+
75
+ Maquina provides a suite of AI-powered tools to accelerate your Rails development:
76
+
77
+ - **Rails MCP Server** — Model Context Protocol server for Rails applications
78
+ - **Rails Simplifier** — simplify and refine Rails code following 37signals patterns
79
+ - **Rails Upgrade Assistant** — comprehensive Rails upgrade reports and migration guides
80
+ - **Maquina UI Standards** — build consistent UIs using maquina_components
81
+ - **Neovim MCP Server** — MCP server for Neovim integration
82
+
83
+ Learn more at [maquina.app/documentation/ai-tools](https://maquina.app/documentation/ai-tools/).
84
+
85
+ ## Learn More
86
+
87
+ Visit [maquina.app](https://maquina.app) for full documentation.
88
+
89
+ Maquina is built for the one-person framework philosophy: production-first, standard Rails, designed to scale with a small team.
@@ -0,0 +1,6 @@
1
+ class HomeController < ApplicationController
2
+ allow_unauthenticated_access if respond_to?(:allow_unauthenticated_access)
3
+
4
+ def index
5
+ end
6
+ end
@@ -0,0 +1 @@
1
+ // Entry point for the build script
@@ -0,0 +1,204 @@
1
+
2
+ <section class="bg-primary/5 border-b border-border">
3
+ <div class="max-w-5xl mx-auto px-5 py-20 sm:py-28">
4
+ <h1 class="text-4xl sm:text-5xl font-bold tracking-tight text-foreground mb-5">
5
+ Tools for Rails developers<br class="hidden sm:block"> who ship alone
6
+ </h1>
7
+ <p class="text-lg text-muted-foreground leading-relaxed max-w-2xl mb-8">
8
+ Maquina is a growing collection of open-source tools extracted from production Rails applications.
9
+ UI components, background jobs, error tracking, and authentication — configured and ready to go.
10
+ </p>
11
+
12
+
13
+ </div>
14
+ </section>
15
+
16
+
17
+
18
+
19
+ <section class="max-w-5xl mx-auto px-5 py-12">
20
+ <p class="text-sm font-semibold uppercase tracking-wider text-primary mb-6">What's Included</p>
21
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-4">
22
+
23
+
24
+
25
+ <%= render "components/card" do %>
26
+ <%= render "components/card/header" do %>
27
+ <%= render "components/card/title", text: "Background Jobs" %>
28
+ <% end %>
29
+ <%= render "components/card/content" do %>
30
+ <p class="text-sm text-muted-foreground">Solid Queue backed by SQLite. Includes Mission Control dashboard for monitoring and managing jobs.</p>
31
+ <% end %>
32
+ <% end %>
33
+
34
+ <%= render "components/card" do %>
35
+ <%= render "components/card/header" do %>
36
+ <%= render "components/card/title", text: "Error Tracking" %>
37
+ <% end %>
38
+ <%= render "components/card/content" do %>
39
+ <p class="text-sm text-muted-foreground">Solid Errors captures exceptions automatically. Browse, resolve, and clean up — no external service needed.</p>
40
+ <% end %>
41
+ <% end %>
42
+
43
+ <%= render "components/card" do %>
44
+ <%= render "components/card/header" do %>
45
+ <%= render "components/card/title", text: "Rate Limiting" %>
46
+ <% end %>
47
+ <%= render "components/card/content" do %>
48
+ <p class="text-sm text-muted-foreground">Rack::Attack bans scanners and floods and throttles sign-in. Every refusal shows on the Security dashboard.</p>
49
+ <% end %>
50
+ <% end %>
51
+
52
+ <%= render "components/card" do %>
53
+ <%= render "components/card/header" do %>
54
+ <%= render "components/card/title", text: "Caching" %>
55
+ <% end %>
56
+ <%= render "components/card/content" do %>
57
+ <p class="text-sm text-muted-foreground">Solid Cache with SQLite backend. No Redis or Memcached to manage.</p>
58
+ <% end %>
59
+ <% end %>
60
+
61
+ <%= render "components/card" do %>
62
+ <%= render "components/card/header" do %>
63
+ <%= render "components/card/title", text: "Real-time" %>
64
+ <% end %>
65
+ <%= render "components/card/content" do %>
66
+ <p class="text-sm text-muted-foreground">Solid Cable for WebSocket support. Action Cable backed by SQLite — zero external dependencies.</p>
67
+ <% end %>
68
+ <% end %>
69
+
70
+ <%= render "components/card" do %>
71
+ <%= render "components/card/header" do %>
72
+ <%= render "components/card/title", text: "UI Components" %>
73
+ <% end %>
74
+ <%= render "components/card/content" do %>
75
+ <p class="text-sm text-muted-foreground">maquina_components — ERB partials styled with Tailwind CSS and Stimulus controllers. No React, no build step.</p>
76
+ <% end %>
77
+ <% end %>
78
+
79
+ <%= render "components/card" do %>
80
+ <%= render "components/card/header" do %>
81
+ <%= render "components/card/title", text: "Standard Rails" %>
82
+ <% end %>
83
+ <%= render "components/card/content" do %>
84
+ <p class="text-sm text-muted-foreground">Importmaps, Turbo, Stimulus. No webpack, no bundler, no extra frameworks to learn.</p>
85
+ <% end %>
86
+ <% end %>
87
+
88
+ </div>
89
+ </section>
90
+
91
+
92
+ <section class="max-w-5xl mx-auto px-5 pb-12">
93
+ <%= render "components/card" do %>
94
+ <%= render "components/card/header" do %>
95
+ <%= render "components/card/title", text: "Maquina Components" %>
96
+ <%= render "components/card/description", text: "UI components for Rails — ERB partials styled with Tailwind CSS 4.0 and Stimulus controllers. Inspired by shadcn/ui, built for the Rails way." %>
97
+ <% end %>
98
+ <%= render "components/card/content" do %>
99
+ <div class="flex flex-wrap gap-2">
100
+ <%= render "components/badge", variant: :outline, size: :sm do %>Card<% end %>
101
+ <%= render "components/badge", variant: :outline, size: :sm do %>Badge<% end %>
102
+ <%= render "components/badge", variant: :outline, size: :sm do %>Table<% end %>
103
+ <%= render "components/badge", variant: :outline, size: :sm do %>Sidebar<% end %>
104
+ <%= render "components/badge", variant: :outline, size: :sm do %>Calendar<% end %>
105
+ <%= render "components/badge", variant: :outline, size: :sm do %>Combobox<% end %>
106
+ <%= render "components/badge", variant: :outline, size: :sm do %>Date Picker<% end %>
107
+ <%= render "components/badge", variant: :outline, size: :sm do %>Toast<% end %>
108
+ <%= render "components/badge", variant: :outline, size: :sm do %>Dropdown Menu<% end %>
109
+ <%= render "components/badge", variant: :outline, size: :sm do %>Toggle Group<% end %>
110
+ <%= render "components/badge", variant: :outline, size: :sm do %>Pagination<% end %>
111
+ <%= render "components/badge", variant: :outline, size: :sm do %>Breadcrumbs<% end %>
112
+ <%= render "components/badge", variant: :outline, size: :sm do %>Alert<% end %>
113
+ <%= render "components/badge", variant: :outline, size: :sm do %>Empty State<% end %>
114
+ <%= render "components/badge", variant: :outline, size: :sm do %>Forms<% end %>
115
+ </div>
116
+ <% end %>
117
+ <%= render "components/card/footer" do %>
118
+ <%= link_to "Browse Components", "https://maquina.app/documentation/components/", target: "_blank", rel: "noopener noreferrer", data: { component: "button", variant: "primary" } %>
119
+ <% end %>
120
+ <% end %>
121
+ </section>
122
+
123
+ <div class="max-w-5xl mx-auto px-5">
124
+ <%= render "components/separator" %>
125
+ </div>
126
+
127
+
128
+ <section class="max-w-5xl mx-auto px-5 py-12">
129
+ <p class="text-sm font-semibold uppercase tracking-wider text-primary mb-6">Ecosystem</p>
130
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-4">
131
+
132
+ <%= render "components/card" do %>
133
+ <%= render "components/card/header" do %>
134
+ <%= render "components/card/title", text: "Rails MCP Server" %>
135
+ <% end %>
136
+ <%= render "components/card/content" do %>
137
+ <p class="text-sm text-muted-foreground">A Model Context Protocol server for Rails projects. Analyze models, routes, schemas, and execute read-only Ruby code in your Rails context.</p>
138
+ <% end %>
139
+ <% end %>
140
+
141
+ <%= render "components/card" do %>
142
+ <%= render "components/card/header" do %>
143
+ <%= render "components/card/title", text: "Neovim MCP Server" %>
144
+ <% end %>
145
+ <%= render "components/card/content" do %>
146
+ <p class="text-sm text-muted-foreground">MCP server for Neovim integration. Read and update buffers, coordinate file changes across your editor and AI assistants.</p>
147
+ <% end %>
148
+ <% end %>
149
+
150
+ <%= render "components/card" do %>
151
+ <%= render "components/card/header" do %>
152
+ <%= render "components/card/title", text: "Rails Upgrade Assistant" %>
153
+ <% end %>
154
+ <%= render "components/card/content" do %>
155
+ <p class="text-sm text-muted-foreground">A Claude Skill that analyzes Rails applications and generates upgrade guides. Covers Rails 7.0 through 8.1 with breaking changes and migration steps.</p>
156
+ <% end %>
157
+ <% end %>
158
+
159
+ <%= render "components/card" do %>
160
+ <%= render "components/card/header" do %>
161
+ <%= render "components/card/title", text: "Rails Simplifier" %>
162
+ <% end %>
163
+ <%= render "components/card/content" do %>
164
+ <p class="text-sm text-muted-foreground">Code simplification following 37signals patterns and the One Person Framework philosophy.</p>
165
+ <% end %>
166
+ <% end %>
167
+
168
+ </div>
169
+ <div class="mt-6 text-center">
170
+ <%= link_to "Explore All Tools", "https://maquina.app/", target: "_blank", rel: "noopener noreferrer", data: { component: "button", variant: "outline" } %>
171
+ </div>
172
+ </section>
173
+
174
+ <div class="max-w-5xl mx-auto px-5">
175
+ <%= render "components/separator" %>
176
+ </div>
177
+
178
+
179
+ <section class="max-w-5xl mx-auto px-5 py-12">
180
+ <p class="text-sm font-semibold uppercase tracking-wider text-primary mb-8 text-center">Philosophy</p>
181
+ <div class="grid grid-cols-1 sm:grid-cols-3 gap-10">
182
+ <div>
183
+ <h3 class="font-bold text-lg text-foreground mb-2">Production First</h3>
184
+ <p class="text-sm text-muted-foreground leading-relaxed">Every tool starts in a real application. No theoretical exercises — only code that has shipped.</p>
185
+ </div>
186
+ <div>
187
+ <h3 class="font-bold text-lg text-foreground mb-2">Standard Rails</h3>
188
+ <p class="text-sm text-muted-foreground leading-relaxed">ERB, Tailwind, Stimulus. No new paradigms to learn, no complex build pipelines.</p>
189
+ </div>
190
+ <div>
191
+ <h3 class="font-bold text-lg text-foreground mb-2">One Person Scale</h3>
192
+ <p class="text-sm text-muted-foreground leading-relaxed">Built for developers who ship alone. Simple tools that stay out of your way.</p>
193
+ </div>
194
+ </div>
195
+ </section>
196
+
197
+
198
+ <section class="bg-primary/5 border-t border-border">
199
+ <div class="max-w-5xl mx-auto px-5 py-16 text-center">
200
+ <h2 class="text-2xl font-bold text-foreground mb-4">Start building today</h2>
201
+ <p class="text-muted-foreground mb-6">Visit maquina.app to explore the full ecosystem.</p>
202
+ <%= link_to "Visit maquina.app", "https://maquina.app/", target: "_blank", rel: "noopener noreferrer", data: { component: "button", variant: "primary" } %>
203
+ </div>
204
+ </section>
@@ -0,0 +1,10 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>TestApp</title>
5
+ <%= yield :head %>
6
+ </head>
7
+ <body data-turbo-refresh-method="morph" data-turbo-refresh-scroll="preserve">
8
+ <%= yield %>
9
+ </body>
10
+ </html>
@@ -0,0 +1,15 @@
1
+ require_relative "boot"
2
+ require "rails/all"
3
+
4
+ module TestApp
5
+ class Application < Rails::Application
6
+
7
+ # Use Solid Queue as the Active Job backend in all environments except test
8
+ config.active_job.queue_adapter = :solid_queue unless Rails.env.test?
9
+ config.solid_queue.connects_to = {database: {writing: :queue}}
10
+
11
+ # Don't wrap form fields with errors in an extra div
12
+ config.action_view.field_error_proc = proc { |html_tag, _instance| html_tag }
13
+ config.load_defaults 7.2
14
+ end
15
+ end
@@ -0,0 +1,90 @@
1
+ # SQLite. Versions 3.8.0 and up are supported.
2
+ # gem install sqlite3
3
+ #
4
+ # Ensure the SQLite 3 gem is defined in your Gemfile
5
+ # gem "sqlite3"
6
+ #
7
+ default: &default
8
+ adapter: sqlite3
9
+ max_connections: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
10
+ timeout: 5000
11
+
12
+ development:
13
+ primary:
14
+ <<: *default
15
+ database: storage/development.sqlite3
16
+ queue:
17
+ <<: *default
18
+ database: storage/development_queue.sqlite3
19
+ migrations_paths: db/queue_migrate
20
+ cache:
21
+ <<: *default
22
+ database: storage/development_cache.sqlite3
23
+ migrations_paths: db/cache_migrate
24
+ cable:
25
+ <<: *default
26
+ database: storage/development_cable.sqlite3
27
+ migrations_paths: db/cable_migrate
28
+ errors:
29
+ <<: *default
30
+ database: storage/development_errors.sqlite3
31
+ migrations_paths: db/errors_migrate
32
+ security:
33
+ <<: *default
34
+ database: storage/development_security.sqlite3
35
+ migrations_paths: db/security_migrate
36
+
37
+ # Warning: The database defined as "test" will be erased and
38
+ # re-generated from your development database when you run "rake".
39
+ # Do not set this db to the same as development or production.
40
+ test:
41
+ primary:
42
+ <<: *default
43
+ database: storage/test.sqlite3
44
+ queue:
45
+ <<: *default
46
+ database: storage/test_queue.sqlite3
47
+ migrations_paths: db/queue_migrate
48
+ cache:
49
+ <<: *default
50
+ database: storage/test_cache.sqlite3
51
+ migrations_paths: db/cache_migrate
52
+ cable:
53
+ <<: *default
54
+ database: storage/test_cable.sqlite3
55
+ migrations_paths: db/cable_migrate
56
+ errors:
57
+ <<: *default
58
+ database: storage/test_errors.sqlite3
59
+ migrations_paths: db/errors_migrate
60
+ security:
61
+ <<: *default
62
+ database: storage/test_security.sqlite3
63
+ migrations_paths: db/security_migrate
64
+
65
+ # Store production database in the storage/ directory, which by default
66
+ # is mounted as a persistent Docker volume in config/deploy.yml.
67
+ production:
68
+ primary:
69
+ <<: *default
70
+ database: storage/production.sqlite3
71
+ queue:
72
+ <<: *default
73
+ database: storage/production_queue.sqlite3
74
+ migrations_paths: db/queue_migrate
75
+ cache:
76
+ <<: *default
77
+ database: storage/production_cache.sqlite3
78
+ migrations_paths: db/cache_migrate
79
+ cable:
80
+ <<: *default
81
+ database: storage/production_cable.sqlite3
82
+ migrations_paths: db/cable_migrate
83
+ errors:
84
+ <<: *default
85
+ database: storage/production_errors.sqlite3
86
+ migrations_paths: db/errors_migrate
87
+ security:
88
+ <<: *default
89
+ database: storage/production_security.sqlite3
90
+ migrations_paths: db/security_migrate
@@ -0,0 +1,90 @@
1
+ # SQLite. Versions 3.8.0 and up are supported.
2
+ # gem install sqlite3
3
+ #
4
+ # Ensure the SQLite 3 gem is defined in your Gemfile
5
+ # gem "sqlite3"
6
+ #
7
+ default: &default
8
+ adapter: sqlite3
9
+ max_connections: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
10
+ timeout: 5000
11
+
12
+ development:
13
+ primary:
14
+ <<: *default
15
+ database: storage/development.sqlite3
16
+ queue:
17
+ <<: *default
18
+ database: storage/development_queue.sqlite3
19
+ migrations_paths: db/queue_migrate
20
+ cache:
21
+ <<: *default
22
+ database: storage/development_cache.sqlite3
23
+ migrations_paths: db/cache_migrate
24
+ cable:
25
+ <<: *default
26
+ database: storage/development_cable.sqlite3
27
+ migrations_paths: db/cable_migrate
28
+ errors:
29
+ <<: *default
30
+ database: storage/development_errors.sqlite3
31
+ migrations_paths: db/errors_migrate
32
+ security:
33
+ <<: *default
34
+ database: storage/development_security.sqlite3
35
+ migrations_paths: db/security_migrate
36
+
37
+ # Warning: The database defined as "test" will be erased and
38
+ # re-generated from your development database when you run "rake".
39
+ # Do not set this db to the same as development or production.
40
+ test:
41
+ primary:
42
+ <<: *default
43
+ database: storage/test.sqlite3
44
+ queue:
45
+ <<: *default
46
+ database: storage/test_queue.sqlite3
47
+ migrations_paths: db/queue_migrate
48
+ cache:
49
+ <<: *default
50
+ database: storage/test_cache.sqlite3
51
+ migrations_paths: db/cache_migrate
52
+ cable:
53
+ <<: *default
54
+ database: storage/test_cable.sqlite3
55
+ migrations_paths: db/cable_migrate
56
+ errors:
57
+ <<: *default
58
+ database: storage/test_errors.sqlite3
59
+ migrations_paths: db/errors_migrate
60
+ security:
61
+ <<: *default
62
+ database: storage/test_security.sqlite3
63
+ migrations_paths: db/security_migrate
64
+
65
+ # Store production database in the storage/ directory, which by default
66
+ # is mounted as a persistent Docker volume in config/deploy.yml.
67
+ production:
68
+ primary:
69
+ <<: *default
70
+ database: storage/production.sqlite3
71
+ queue:
72
+ <<: *default
73
+ database: storage/production_queue.sqlite3
74
+ migrations_paths: db/queue_migrate
75
+ cache:
76
+ <<: *default
77
+ database: storage/production_cache.sqlite3
78
+ migrations_paths: db/cache_migrate
79
+ cable:
80
+ <<: *default
81
+ database: storage/production_cable.sqlite3
82
+ migrations_paths: db/cable_migrate
83
+ errors:
84
+ <<: *default
85
+ database: storage/production_errors.sqlite3
86
+ migrations_paths: db/errors_migrate
87
+ security:
88
+ <<: *default
89
+ database: storage/production_security.sqlite3
90
+ migrations_paths: db/security_migrate
@@ -0,0 +1,8 @@
1
+ Rails.application.configure do
2
+ config.cache_classes = false
3
+
4
+ # Use letter_opener for email delivery
5
+ config.action_mailer.delivery_method = :letter_opener
6
+ config.action_mailer.perform_deliveries = true
7
+ config.action_mailer.default_url_options = {host: "localhost", port: 3000}
8
+ end
@@ -0,0 +1,6 @@
1
+ Rails.application.configure do
2
+ config.cache_classes = true
3
+
4
+ # Set host for URL generation
5
+ config.action_mailer.default_url_options = {host: ENV.fetch("APPLICATION_HOST", "example.com")}
6
+ end
@@ -0,0 +1,4 @@
1
+ Rails.application.config.generators do |g|
2
+ g.stylesheets false
3
+ g.helper false
4
+ end