ActiveCanvas Documentation
Complete reference for installing, configuring, and extending ActiveCanvas — the open-source CMS engine for Rails 8+.
Installation
Add ActiveCanvas to your Gemfile:
gem "active_canvas"
Then run the install generator:
bundle install
bin/rails generate active_canvas:install
bin/rails db:migrate
The interactive installer will:
- Copy and run database migrations
- Create
config/initializers/active_canvas.rbwith configuration options - Mount the engine in your routes (default:
/canvas) - Prompt you to choose a CSS framework (Tailwind, Bootstrap 5, or none)
- Optionally configure AI API keys
Once the installer finishes, visit /canvas/admin to start building pages.
Quick Start
Get a page live in five steps:
- Go to
/canvas/admin— open the admin dashboard - Create a Page Type — for example, "Landing Page" or "Blog Post"
- Create a Page — give it a title and slug, then click Editor to open the visual builder
- Build your page — drag blocks onto the canvas, use AI to generate content, upload images from the media library
- Publish — your page is immediately live at
/canvas/your-slug
Configuration
All configuration lives in config/initializers/active_canvas.rb. Below is the complete reference of every option, grouped by category.
Authentication
| Option | Default | Description |
|---|---|---|
authenticate_admin |
nil |
Method name (symbol), :http_basic_auth, or a lambda. Controls access to the admin interface. |
authenticate_public |
nil |
Same options as above. nil means public pages are accessible without authentication. |
current_user_method |
:current_user |
Method name used for version tracking and AI feature attribution. |
admin_parent_controller |
nil |
Set to a controller class name (string) to inherit authentication from your app. |
public_parent_controller |
nil |
Same as above, for public-facing page controllers. |
CSS Framework
| Option | Default | Description |
|---|---|---|
css_framework |
:tailwind |
Choose :tailwind, :bootstrap5, or :none. |
Media Uploads
| Option | Default | Description |
|---|---|---|
enable_uploads |
true |
Enable or disable file uploads entirely. |
max_upload_size |
10.megabytes |
Maximum allowed file size for uploads. |
allow_svg_uploads |
false |
SVG uploads are disabled by default for security. |
storage_service |
nil |
Active Storage service name. nil uses the default service. |
public_uploads |
false |
false serves files via signed URLs; true uses public URLs. |
Editor
| Option | Default | Description |
|---|---|---|
enable_ai_features |
true |
Toggle AI content generation in the editor. |
enable_code_editor |
true |
Show the inline HTML/CSS code editor panel. |
enable_asset_manager |
true |
Show the media library inside the editor. |
autosave_interval |
60 |
Seconds between auto-saves. Set to 0 to disable. |
Pages
| Option | Default | Description |
|---|---|---|
max_versions_per_page |
50 |
Maximum version history entries per page. Set to 0 for unlimited. |
Security
| Option | Default | Description |
|---|---|---|
sanitize_content |
true |
Sanitize page HTML content on save. |
ai_rate_limit_per_minute |
30 |
Maximum AI requests allowed per minute per user. |
Full Example
# config/initializers/active_canvas.rb
ActiveCanvas.configure do |config|
# Authentication
config.authenticate_admin = :authenticate_user!
config.authenticate_public = nil
config.current_user_method = :current_user
# CSS Framework
config.css_framework = :tailwind
# Media Uploads
config.enable_uploads = true
config.max_upload_size = 10.megabytes
config.allow_svg_uploads = false
config.storage_service = nil
config.public_uploads = false
# Editor
config.enable_ai_features = true
config.enable_code_editor = true
config.enable_asset_manager = true
config.autosave_interval = 60
# Pages
config.max_versions_per_page = 50
# Security
config.sanitize_content = true
config.ai_rate_limit_per_minute = 30
end
Authentication
The admin interface is open by default. Configure authentication before deploying to production. ActiveCanvas supports four approaches.
1. Devise
If your app uses Devise, point authenticate_admin to the Devise helper method:
ActiveCanvas.configure do |config|
config.authenticate_admin = :authenticate_user!
end
2. Custom Controller
Inherit from a controller that already handles authentication:
ActiveCanvas.configure do |config|
config.admin_parent_controller = "Admin::ApplicationController"
end
All ActiveCanvas admin controllers will inherit from the specified controller, picking up its before_action filters, layout, and helper methods.
3. HTTP Basic Auth
Simple password protection without a user model:
ActiveCanvas.configure do |config|
config.authenticate_admin = :http_basic_auth
config.http_basic_user = "admin"
config.http_basic_password = Rails.application.credentials.active_canvas_password
end
4. Lambda
For completely custom logic, pass a lambda that runs in the controller context:
ActiveCanvas.configure do |config|
config.authenticate_admin = -> {
unless current_user&.admin?
redirect_to main_app.root_path, alert: "Access denied"
end
}
end
CSS Framework
ActiveCanvas supports three CSS framework options:
:tailwind— Tailwind CSS v4. Uses the CDN in the editor for instant live preview. On save, compiles only the CSS classes used on that page. Public pages serve compiled CSS inline with zero CDN dependency.:bootstrap5— Bootstrap 5 loaded via CDN in the editor and on public pages.:none— No framework. Write vanilla CSS or bring your own.
Tailwind Setup
For production-grade Tailwind compilation, add the tailwindcss-ruby gem:
gem "tailwindcss-ruby", ">= 4.0"
Then set the framework in your initializer:
ActiveCanvas.configure do |config|
config.css_framework = :tailwind
end
That is all the setup required. CSS compiles automatically when pages are saved. If the gem is not installed, ActiveCanvas falls back to serving the Tailwind CDN on public pages.
You can customize the Tailwind theme (colors, fonts, spacing) from the admin settings panel, and trigger a bulk recompile of all pages when the theme changes.
AI Setup
ActiveCanvas uses RubyLLM to provide AI-powered content generation directly in the editor. Supported capabilities:
| Feature | Description | Supported Models |
|---|---|---|
| Chat | Generate and edit HTML content with streaming | GPT-4o, Claude Sonnet 4, Claude 3.5 Haiku |
| Image Generation | Create images from text prompts | DALL-E 3, GPT Image 1 |
| Screenshot to Code | Upload a screenshot, get production-ready HTML/CSS | GPT-4o, Claude Sonnet 4 (vision models) |
API Keys
Configure keys via environment variables or Rails credentials in your initializer:
# config/initializers/active_canvas.rb
Rails.application.config.after_initialize do
# Via environment variables
ActiveCanvas::Setting.ai_openai_api_key = ENV["OPENAI_API_KEY"]
ActiveCanvas::Setting.ai_anthropic_api_key = ENV["ANTHROPIC_API_KEY"]
ActiveCanvas::Setting.ai_openrouter_api_key = ENV["OPENROUTER_API_KEY"]
# Or via Rails credentials
credentials = Rails.application.credentials.active_canvas || {}
ActiveCanvas::Setting.ai_openai_api_key = credentials[:openai_api_key]
end
You can also configure API keys from the admin UI at /canvas/admin/settings (AI tab).
Sync Models
After setting your API keys, sync the available models:
bin/rails active_canvas:sync_models
Or use the Sync Models button on the admin settings page. This fetches the list of available models from each configured provider.
Server Timeout
AI requests — especially image generation and screenshot-to-code — can take longer than typical web requests. If you run Puma in clustered mode, increase the worker timeout:
# config/puma.rb
worker_timeout 180
Or set the environment variable:
PUMA_WORKER_TIMEOUT=180
If you are behind a reverse proxy (Nginx, Apache), also increase its read timeout for the ActiveCanvas routes:
# Nginx example
location /canvas {
proxy_read_timeout 180s;
proxy_send_timeout 180s;
}
Media Library
Upload and manage images directly from the admin dashboard or from within the editor's built-in asset manager.
Supported Formats
- Images: JPEG, PNG, GIF, WebP, AVIF
- Documents: PDF
- Vector: SVG (disabled by default — enable with
config.allow_svg_uploads = true)
Storage
Media files are stored through Active Storage, so any backend works: local disk, Amazon S3, Google Cloud Storage, or Azure Blob Storage. Set config.storage_service to the name of your Active Storage service, or leave it as nil to use the default.
URL Mode
config.public_uploads = false— serves files via signed, expiring URLs (default)config.public_uploads = true— serves files via permanent public URLs
File Size
The maximum upload size defaults to 10 MB. Change it with:
config.max_upload_size = 25.megabytes
Page Versioning
Every content change creates a version automatically. View the version history from the page admin panel to see:
- What changed — visual before/after diffs of the HTML content
- Who made the change — attributed via your
current_user_method - When it was made — timestamped for auditing
- Content size differences — see how much was added or removed
Roll back to any previous version with a single click.
Configuring Retention
By default, ActiveCanvas keeps the last 50 versions per page. Adjust with:
config.max_versions_per_page = 100 # keep more history
config.max_versions_per_page = 0 # unlimited (no pruning)
When the limit is reached, the oldest versions are automatically pruned on each new save.
Customization
Mount Path
By default the engine mounts at /canvas. Change it in your routes:
# config/routes.rb
mount ActiveCanvas::Engine => "/pages" # or "/cms", "/blog", "/"
Override Views
Copy any ActiveCanvas view into your application to customize its markup. Rails will prefer your local copy over the engine's default:
app/views/active_canvas/pages/show.html.erb
app/views/active_canvas/admin/pages/index.html.erb
app/views/layouts/active_canvas/admin/application.html.erb
Extend Models
Add validations, scopes, or methods to ActiveCanvas models using class_eval:
ActiveCanvas::Page.class_eval do
validates :content, presence: true
def excerpt
content.to_s.truncate(200)
end
end
Place model extensions in an initializer or in config/initializers/active_canvas_extensions.rb so they load on boot.
Rake Tasks
ActiveCanvas ships with two rake tasks for managing AI model availability:
| Task | Description |
|---|---|
active_canvas:sync_models |
Fetches the latest available models from all configured AI providers (OpenAI, Anthropic, OpenRouter) and stores them in the database. |
active_canvas:list_models |
Lists all synced AI models with their provider, type, and status. |
Usage
bin/rails active_canvas:sync_models # Sync AI models from configured providers
bin/rails active_canvas:list_models # List all synced AI models
Run sync_models after adding or changing API keys, or periodically via a scheduled job to keep the model list up to date.