active_canvas 0.0.1

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 (80) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +318 -0
  4. data/Rakefile +6 -0
  5. data/app/assets/javascripts/active_canvas/editor/ai_panel.js +1607 -0
  6. data/app/assets/javascripts/active_canvas/editor/asset_manager.js +498 -0
  7. data/app/assets/javascripts/active_canvas/editor/blocks.js +1083 -0
  8. data/app/assets/javascripts/active_canvas/editor/code_panel.js +572 -0
  9. data/app/assets/javascripts/active_canvas/editor/component_toolbar.js +394 -0
  10. data/app/assets/javascripts/active_canvas/editor/panels.js +460 -0
  11. data/app/assets/javascripts/active_canvas/editor/utils.js +56 -0
  12. data/app/assets/javascripts/active_canvas/editor.js +295 -0
  13. data/app/assets/stylesheets/active_canvas/application.css +15 -0
  14. data/app/assets/stylesheets/active_canvas/editor.css +2929 -0
  15. data/app/controllers/active_canvas/admin/ai_controller.rb +181 -0
  16. data/app/controllers/active_canvas/admin/application_controller.rb +56 -0
  17. data/app/controllers/active_canvas/admin/media_controller.rb +61 -0
  18. data/app/controllers/active_canvas/admin/page_types_controller.rb +57 -0
  19. data/app/controllers/active_canvas/admin/page_versions_controller.rb +23 -0
  20. data/app/controllers/active_canvas/admin/pages_controller.rb +133 -0
  21. data/app/controllers/active_canvas/admin/partials_controller.rb +88 -0
  22. data/app/controllers/active_canvas/admin/settings_controller.rb +256 -0
  23. data/app/controllers/active_canvas/application_controller.rb +20 -0
  24. data/app/controllers/active_canvas/pages_controller.rb +18 -0
  25. data/app/controllers/concerns/active_canvas/current_user.rb +12 -0
  26. data/app/controllers/concerns/active_canvas/rate_limitable.rb +75 -0
  27. data/app/controllers/concerns/active_canvas/tailwind_compilation.rb +39 -0
  28. data/app/helpers/active_canvas/application_helper.rb +4 -0
  29. data/app/jobs/active_canvas/application_job.rb +4 -0
  30. data/app/jobs/active_canvas/compile_tailwind_job.rb +64 -0
  31. data/app/mailers/active_canvas/application_mailer.rb +6 -0
  32. data/app/models/active_canvas/ai_model.rb +136 -0
  33. data/app/models/active_canvas/application_record.rb +5 -0
  34. data/app/models/active_canvas/media.rb +141 -0
  35. data/app/models/active_canvas/page.rb +85 -0
  36. data/app/models/active_canvas/page_type.rb +22 -0
  37. data/app/models/active_canvas/page_version.rb +80 -0
  38. data/app/models/active_canvas/partial.rb +73 -0
  39. data/app/models/active_canvas/setting.rb +292 -0
  40. data/app/services/active_canvas/ai_configuration.rb +40 -0
  41. data/app/services/active_canvas/ai_models.rb +128 -0
  42. data/app/services/active_canvas/ai_service.rb +289 -0
  43. data/app/services/active_canvas/content_sanitizer.rb +112 -0
  44. data/app/services/active_canvas/tailwind_compiler.rb +156 -0
  45. data/app/views/active_canvas/admin/media/index.html.erb +401 -0
  46. data/app/views/active_canvas/admin/media/show.html.erb +297 -0
  47. data/app/views/active_canvas/admin/page_types/_form.html.erb +25 -0
  48. data/app/views/active_canvas/admin/page_types/edit.html.erb +13 -0
  49. data/app/views/active_canvas/admin/page_types/index.html.erb +29 -0
  50. data/app/views/active_canvas/admin/page_types/new.html.erb +9 -0
  51. data/app/views/active_canvas/admin/page_types/show.html.erb +18 -0
  52. data/app/views/active_canvas/admin/page_versions/show.html.erb +469 -0
  53. data/app/views/active_canvas/admin/pages/_form.html.erb +62 -0
  54. data/app/views/active_canvas/admin/pages/content.html.erb +139 -0
  55. data/app/views/active_canvas/admin/pages/edit.html.erb +335 -0
  56. data/app/views/active_canvas/admin/pages/editor.html.erb +710 -0
  57. data/app/views/active_canvas/admin/pages/index.html.erb +149 -0
  58. data/app/views/active_canvas/admin/pages/new.html.erb +19 -0
  59. data/app/views/active_canvas/admin/pages/show.html.erb +258 -0
  60. data/app/views/active_canvas/admin/pages/versions.html.erb +333 -0
  61. data/app/views/active_canvas/admin/partials/edit.html.erb +182 -0
  62. data/app/views/active_canvas/admin/partials/editor.html.erb +703 -0
  63. data/app/views/active_canvas/admin/partials/index.html.erb +131 -0
  64. data/app/views/active_canvas/admin/settings/show.html.erb +1864 -0
  65. data/app/views/active_canvas/pages/no_homepage.html.erb +45 -0
  66. data/app/views/active_canvas/pages/show.html.erb +113 -0
  67. data/app/views/layouts/active_canvas/admin/application.html.erb +960 -0
  68. data/app/views/layouts/active_canvas/admin/editor.html.erb +826 -0
  69. data/app/views/layouts/active_canvas/application.html.erb +55 -0
  70. data/config/routes.rb +48 -0
  71. data/db/migrate/20260202000001_create_active_canvas_tables.rb +113 -0
  72. data/db/migrate/20260202000002_create_active_canvas_ai_models.rb +26 -0
  73. data/lib/active_canvas/configuration.rb +232 -0
  74. data/lib/active_canvas/engine.rb +44 -0
  75. data/lib/active_canvas/version.rb +3 -0
  76. data/lib/active_canvas.rb +26 -0
  77. data/lib/generators/active_canvas/install/install_generator.rb +263 -0
  78. data/lib/generators/active_canvas/install/templates/initializer.rb.tt +163 -0
  79. data/lib/tasks/active_canvas_tasks.rake +69 -0
  80. metadata +150 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d4b96c0042fa7c12334c67d92ab53a6a59766099111c0abbb854b386f95c69fa
4
+ data.tar.gz: 4c49e4bdcaea61447a43c4b2a4b7111904354f6f343a8a5ff17eaa08525ee0bd
5
+ SHA512:
6
+ metadata.gz: 177d5257bac30fe5da6e91cb5c65bd9584648a5173fbe7c654bbd2dd1f85f6b85d357d3a56cfc07dd3d6595a8ca7de71a8ff38f8f3ae5cc6e1215e0d7dcc50c7
7
+ data.tar.gz: e02cc03e5f88c357338b92e627e707c392fa9de486157925156d619b86061db8d3079a7b4cc2278e4969f37a4a12fa324e84140fa1d737844ed5e29b1fe7918c
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright Giovanni Panasiti
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,318 @@
1
+ # ActiveCanvas
2
+
3
+ A mountable Rails engine that turns any Rails app into a full-featured CMS. Includes a visual drag-and-drop editor (GrapeJS), AI-powered content generation, Tailwind CSS compilation, media management, page versioning, and SEO controls -- all behind an admin interface that works out of the box.
4
+
5
+ ## Features
6
+
7
+ - **Visual Editor** -- Drag-and-drop page builder powered by GrapeJS
8
+ - **AI Content Generation** -- Text, images, and screenshot-to-code via OpenAI, Anthropic, or OpenRouter
9
+ - **Tailwind CSS Compilation** -- Per-page compiled CSS for production (no CDN dependency)
10
+ - **Media Library** -- Upload and manage images/files with Active Storage
11
+ - **Page Versioning** -- Automatic version history with diffs and rollback
12
+ - **Header & Footer Partials** -- Reusable components, togglable per page
13
+ - **SEO** -- Meta tags, Open Graph, Twitter Cards, JSON-LD structured data
14
+ - **Page Types** -- Categorize pages (blog posts, landing pages, etc.)
15
+ - **Authentication** -- Pluggable auth (Devise, custom, or HTTP Basic)
16
+ - **Isolated Namespace** -- No conflicts with your host application
17
+
18
+ ## Requirements
19
+
20
+ - Ruby 3.1+
21
+ - Rails 8.0+
22
+
23
+ ## Installation
24
+
25
+ Add to your Gemfile:
26
+
27
+ ```ruby
28
+ gem "active_canvas"
29
+ ```
30
+
31
+ Run the install generator:
32
+
33
+ ```bash
34
+ bundle install
35
+ bin/rails generate active_canvas:install
36
+ ```
37
+
38
+ The interactive installer will:
39
+ - Copy and run database migrations
40
+ - Create `config/initializers/active_canvas.rb` with configuration options
41
+ - Mount the engine in your routes (default: `/canvas`)
42
+ - Prompt you to choose a CSS framework (Tailwind, Bootstrap 5, or none)
43
+ - Optionally configure AI API keys
44
+
45
+ Then visit `/canvas/admin` to start building pages.
46
+
47
+ ## Quick Start
48
+
49
+ 1. Go to `/canvas/admin`
50
+ 2. Create a **Page Type** (e.g., "Landing Page")
51
+ 3. Create a **Page**, then click **Editor** to open the visual builder
52
+ 4. Drag blocks, use AI to generate content, upload images
53
+ 5. Publish the page -- it's live at `/canvas/your-slug`
54
+
55
+ ## Visual Editor
56
+
57
+ The GrapeJS editor provides:
58
+
59
+ - Drag-and-drop blocks (text, images, columns, forms, etc.)
60
+ - Code editor panel for direct HTML/CSS editing
61
+ - Asset manager integrated with the media library
62
+ - AI assistant panel for content generation
63
+ - Component-level AI toolbar (edit, rewrite, expand)
64
+ - Auto-save (configurable interval, default: 60s)
65
+
66
+ ## AI Integration
67
+
68
+ ActiveCanvas uses [RubyLLM](https://github.com/crmne/ruby_llm) to provide AI features directly in the editor.
69
+
70
+ ### Capabilities
71
+
72
+ | Feature | Description | Supported Models |
73
+ |---------|-------------|-----------------|
74
+ | **Chat** | Generate and edit HTML content with streaming | GPT-4o, Claude Sonnet 4, Claude 3.5 Haiku |
75
+ | **Image Generation** | Create images from text prompts | DALL-E 3, GPT Image 1 |
76
+ | **Screenshot to Code** | Upload a screenshot, get HTML/CSS | GPT-4o, Claude Sonnet 4 (vision models) |
77
+
78
+ ### Setup
79
+
80
+ Add your API keys via environment variables or Rails credentials:
81
+
82
+ ```ruby
83
+ # config/initializers/active_canvas.rb
84
+ Rails.application.config.after_initialize do
85
+ # Via environment variables
86
+ ActiveCanvas::Setting.ai_openai_api_key = ENV["OPENAI_API_KEY"]
87
+ ActiveCanvas::Setting.ai_anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
88
+ ActiveCanvas::Setting.ai_openrouter_api_key = ENV["OPENROUTER_API_KEY"]
89
+
90
+ # Or via Rails credentials
91
+ credentials = Rails.application.credentials.active_canvas || {}
92
+ ActiveCanvas::Setting.ai_openai_api_key = credentials[:openai_api_key]
93
+ end
94
+ ```
95
+
96
+ You can also configure API keys from the admin UI at `/canvas/admin/settings` (AI tab).
97
+
98
+ Once configured, sync available models:
99
+
100
+ ```bash
101
+ bin/rails active_canvas:sync_models
102
+ ```
103
+
104
+ Or use the **Sync Models** button in admin settings.
105
+
106
+ ### Server Timeout
107
+
108
+ AI requests (especially image generation and screenshot-to-code) can take longer than typical web requests. If you're running Puma in clustered mode (multiple workers), increase the worker timeout to avoid requests being killed mid-flight:
109
+
110
+ ```ruby
111
+ # config/puma.rb
112
+ worker_timeout 180
113
+ ```
114
+
115
+ Or via environment variable:
116
+
117
+ ```bash
118
+ PUMA_WORKER_TIMEOUT=180
119
+ ```
120
+
121
+ If you're behind a reverse proxy (Nginx, Apache), also increase its read timeout for the ActiveCanvas routes:
122
+
123
+ ```nginx
124
+ location /canvas {
125
+ proxy_read_timeout 180s;
126
+ proxy_send_timeout 180s;
127
+ }
128
+ ```
129
+
130
+ ## Tailwind CSS Compilation
131
+
132
+ ActiveCanvas can compile Tailwind CSS at runtime so your public pages don't need the Tailwind CDN.
133
+
134
+ ### How it works
135
+
136
+ - **In the editor**: Uses Tailwind CDN for instant live preview
137
+ - **On save**: Compiles only the CSS classes used on that page
138
+ - **Public pages**: Serves compiled CSS inline (fast, no CDN)
139
+
140
+ ### Setup
141
+
142
+ Add the `tailwindcss-ruby` gem (optional -- falls back to CDN if missing):
143
+
144
+ ```ruby
145
+ gem "tailwindcss-ruby", ">= 4.0"
146
+ ```
147
+
148
+ Select "Tailwind CSS" as the CSS framework in your initializer or admin settings. That's it -- CSS compiles automatically when you save pages.
149
+
150
+ You can customize the Tailwind theme (colors, fonts) from admin settings, and trigger a bulk recompile of all pages when needed.
151
+
152
+ ## Media Library
153
+
154
+ Upload and manage images directly from the admin or from within the editor's asset manager.
155
+
156
+ - Supports JPEG, PNG, GIF, WebP, AVIF, and PDF
157
+ - SVG uploads available (disabled by default for security)
158
+ - Configurable max file size (default: 10MB)
159
+ - Works with any Active Storage backend (local, S3, GCS, etc.)
160
+ - Public or signed URL modes
161
+
162
+ ## Page Versioning
163
+
164
+ Every content change creates a version automatically. View the version history from the page admin to see:
165
+
166
+ - What changed (before/after diffs)
167
+ - Who made the change
168
+ - When it was made
169
+ - Content size differences
170
+
171
+ Configure the maximum versions kept per page (default: 50, set to 0 for unlimited).
172
+
173
+ ## Authentication
174
+
175
+ **The admin interface is open by default.** Configure authentication before deploying to production.
176
+
177
+ ### With Devise
178
+
179
+ ```ruby
180
+ ActiveCanvas.configure do |config|
181
+ config.authenticate_admin = :authenticate_user!
182
+ end
183
+ ```
184
+
185
+ ### With a custom controller
186
+
187
+ ```ruby
188
+ ActiveCanvas.configure do |config|
189
+ config.admin_parent_controller = "Admin::ApplicationController"
190
+ end
191
+ ```
192
+
193
+ ### With HTTP Basic Auth
194
+
195
+ ```ruby
196
+ ActiveCanvas.configure do |config|
197
+ config.authenticate_admin = :http_basic_auth
198
+ config.http_basic_user = "admin"
199
+ config.http_basic_password = Rails.application.credentials.active_canvas_password
200
+ end
201
+ ```
202
+
203
+ ### With custom logic
204
+
205
+ ```ruby
206
+ ActiveCanvas.configure do |config|
207
+ config.authenticate_admin = -> {
208
+ unless current_user&.admin?
209
+ redirect_to main_app.root_path, alert: "Access denied"
210
+ end
211
+ }
212
+ end
213
+ ```
214
+
215
+ ## Configuration
216
+
217
+ Full configuration reference:
218
+
219
+ ```ruby
220
+ # config/initializers/active_canvas.rb
221
+ ActiveCanvas.configure do |config|
222
+ # === Authentication ===
223
+ config.authenticate_admin = :authenticate_user! # method name, lambda, or :http_basic_auth
224
+ config.authenticate_public = nil # nil = public access
225
+ config.current_user_method = :current_user # for version tracking & AI features
226
+
227
+ # === CSS Framework ===
228
+ config.css_framework = :tailwind # :tailwind, :bootstrap5, or :none
229
+
230
+ # === Media Uploads ===
231
+ config.enable_uploads = true
232
+ config.max_upload_size = 10.megabytes
233
+ config.allow_svg_uploads = false
234
+ config.storage_service = nil # Active Storage service name
235
+ config.public_uploads = false # false = signed URLs
236
+
237
+ # === Editor ===
238
+ config.enable_ai_features = true
239
+ config.enable_code_editor = true
240
+ config.enable_asset_manager = true
241
+ config.autosave_interval = 60 # seconds (0 = disabled)
242
+
243
+ # === Pages ===
244
+ config.max_versions_per_page = 50 # 0 = unlimited
245
+
246
+ # === Security ===
247
+ config.sanitize_content = true
248
+ config.ai_rate_limit_per_minute = 30
249
+ end
250
+ ```
251
+
252
+ ## Customization
253
+
254
+ ### Mount path
255
+
256
+ ```ruby
257
+ # config/routes.rb
258
+ mount ActiveCanvas::Engine => "/pages" # or "/cms", "/blog", "/"
259
+ ```
260
+
261
+ ### Override views
262
+
263
+ Copy any view into your app to customize it:
264
+
265
+ ```
266
+ app/views/active_canvas/pages/show.html.erb
267
+ app/views/active_canvas/admin/pages/index.html.erb
268
+ app/views/layouts/active_canvas/admin/application.html.erb
269
+ ```
270
+
271
+ ### Extend models
272
+
273
+ ```ruby
274
+ ActiveCanvas::Page.class_eval do
275
+ validates :content, presence: true
276
+
277
+ def excerpt
278
+ content.to_s.truncate(200)
279
+ end
280
+ end
281
+ ```
282
+
283
+ ## Rake Tasks
284
+
285
+ ```bash
286
+ bin/rails active_canvas:sync_models # Sync AI models from configured providers
287
+ bin/rails active_canvas:list_models # List all synced AI models
288
+ ```
289
+
290
+ ## Development
291
+
292
+ ```bash
293
+ git clone https://github.com/giovapanasiti/active_canvas.git
294
+ cd active_canvas
295
+ bundle install
296
+ bin/rails db:migrate
297
+ bin/rails test
298
+ ```
299
+
300
+ Start the dummy app:
301
+
302
+ ```bash
303
+ bin/rails server
304
+ ```
305
+
306
+ Then visit `http://localhost:3000/canvas/admin`.
307
+
308
+ ## Contributing
309
+
310
+ 1. Fork the repository
311
+ 2. Create your feature branch (`git checkout -b feature/my-feature`)
312
+ 3. Commit your changes
313
+ 4. Push to the branch (`git push origin feature/my-feature`)
314
+ 5. Create a Pull Request
315
+
316
+ ## License
317
+
318
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/setup"
2
+
3
+ APP_RAKEFILE = File.expand_path("test/dummy/Rakefile", __dir__)
4
+ load "rails/tasks/engine.rake"
5
+
6
+ require "bundler/gem_tasks"