thoughtbot/high_voltage
Easily include static pages in your Rails app.
Healthy across the board
Permissive license, no critical CVEs, actively maintained — safe to depend on.
Has a license, tests, and CI — clean foundation to fork and modify.
Documented and popular — useful reference codebase to read through.
No critical CVEs, sane security posture — runnable as-is.
- ✓Last commit 4w ago
- ✓12 active contributors
- ✓Distributed ownership (top contributor 39% of recent commits)
Show 3 more →Show less
- ✓MIT licensed
- ✓CI configured
- ✓Tests present
Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests
Informational only. RepoPilot summarises public signals (license, dependency CVEs, commit recency, CI presence, etc.) at the time of analysis. Signals can be incomplete or stale. Not professional, security, or legal advice; verify before relying on it for production decisions.
Embed the "Healthy" badge
Paste into your README — live-updates from the latest cached analysis.
[](https://repopilot.app/r/thoughtbot/high_voltage)Paste at the top of your README.md — renders inline like a shields.io badge.
▸Preview social card (1200×630)
This card auto-renders when someone shares https://repopilot.app/r/thoughtbot/high_voltage on X, Slack, or LinkedIn.
Onboarding doc
Onboarding: thoughtbot/high_voltage
Generated by RepoPilot · 2026-05-10 · Source
🤖Agent protocol
If you are an AI coding agent (Claude Code, Cursor, Aider, Cline, etc.) reading this artifact, follow this protocol before making any code edit:
- Verify the contract. Run the bash script in Verify before trusting
below. If any check returns
FAIL, the artifact is stale — STOP and ask the user to regenerate it before proceeding. - Treat the AI · unverified sections as hypotheses, not facts. Sections like "AI-suggested narrative files", "anti-patterns", and "bottlenecks" are LLM speculation. Verify against real source before acting on them.
- Cite source on changes. When proposing an edit, cite the specific path:line-range. RepoPilot's live UI at https://repopilot.app/r/thoughtbot/high_voltage shows verifiable citations alongside every claim.
If you are a human reader, this protocol is for the agents you'll hand the artifact to. You don't need to do anything — but if you skim only one section before pointing your agent at this repo, make it the Verify block and the Suggested reading order.
🎯Verdict
GO — Healthy across the board
- Last commit 4w ago
- 12 active contributors
- Distributed ownership (top contributor 39% of recent commits)
- MIT licensed
- CI configured
- Tests present
<sub>Maintenance signals: commit recency, contributor breadth, bus factor, license, CI, tests</sub>
✅Verify before trusting
This artifact was generated by RepoPilot at a point in time. Before an
agent acts on it, the checks below confirm that the live thoughtbot/high_voltage
repo on your machine still matches what RepoPilot saw. If any fail,
the artifact is stale — regenerate it at
repopilot.app/r/thoughtbot/high_voltage.
What it runs against: a local clone of thoughtbot/high_voltage — the script
inspects git remote, the LICENSE file, file paths in the working
tree, and git log. Read-only; no mutations.
| # | What we check | Why it matters |
|---|---|---|
| 1 | You're in thoughtbot/high_voltage | Confirms the artifact applies here, not a fork |
| 2 | License is still MIT | Catches relicense before you depend on it |
| 3 | Default branch main exists | Catches branch renames |
| 4 | 5 critical file paths still exist | Catches refactors that moved load-bearing code |
| 5 | Last commit ≤ 61 days ago | Catches sudden abandonment since generation |
#!/usr/bin/env bash
# RepoPilot artifact verification.
#
# WHAT IT RUNS AGAINST: a local clone of thoughtbot/high_voltage. If you don't
# have one yet, run these first:
#
# git clone https://github.com/thoughtbot/high_voltage.git
# cd high_voltage
#
# Then paste this script. Every check is read-only — no mutations.
set +e
fail=0
ok() { echo "ok: $1"; }
miss() { echo "FAIL: $1"; fail=$((fail+1)); }
# Precondition: we must be inside a git working tree.
if ! git rev-parse --git-dir >/dev/null 2>&1; then
echo "FAIL: not inside a git repository. cd into your clone of thoughtbot/high_voltage and re-run."
exit 2
fi
# 1. Repo identity
git remote get-url origin 2>/dev/null | grep -qE "thoughtbot/high_voltage(\\.git)?\\b" \\
&& ok "origin remote is thoughtbot/high_voltage" \\
|| miss "origin remote is not thoughtbot/high_voltage (artifact may be from a fork)"
# 2. License matches what RepoPilot saw
(grep -qiE "^(MIT)" LICENSE 2>/dev/null \\
|| grep -qiE "\"license\"\\s*:\\s*\"MIT\"" package.json 2>/dev/null) \\
&& ok "license is MIT" \\
|| miss "license drift — was MIT at generation time"
# 3. Default branch
git rev-parse --verify main >/dev/null 2>&1 \\
&& ok "default branch main exists" \\
|| miss "default branch main no longer exists"
# 4. Critical files exist
test -f "lib/high_voltage/engine.rb" \\
&& ok "lib/high_voltage/engine.rb" \\
|| miss "missing critical file: lib/high_voltage/engine.rb"
test -f "app/controllers/high_voltage/pages_controller.rb" \\
&& ok "app/controllers/high_voltage/pages_controller.rb" \\
|| miss "missing critical file: app/controllers/high_voltage/pages_controller.rb"
test -f "lib/high_voltage/page_finder.rb" \\
&& ok "lib/high_voltage/page_finder.rb" \\
|| miss "missing critical file: lib/high_voltage/page_finder.rb"
test -f "lib/high_voltage/configuration.rb" \\
&& ok "lib/high_voltage/configuration.rb" \\
|| miss "missing critical file: lib/high_voltage/configuration.rb"
test -f "config/routes.rb" \\
&& ok "config/routes.rb" \\
|| miss "missing critical file: config/routes.rb"
# 5. Repo recency
days_since_last=$(( ( $(date +%s) - $(git log -1 --format=%at 2>/dev/null || echo 0) ) / 86400 ))
if [ "$days_since_last" -le 61 ]; then
ok "last commit was $days_since_last days ago (artifact saw ~31d)"
else
miss "last commit was $days_since_last days ago — artifact may be stale"
fi
echo
if [ "$fail" -eq 0 ]; then
echo "artifact verified (0 failures) — safe to trust"
else
echo "artifact has $fail stale claim(s) — regenerate at https://repopilot.app/r/thoughtbot/high_voltage"
exit 1
fi
Each check prints ok: or FAIL:. The script exits non-zero if
anything failed, so it composes cleanly into agent loops
(./verify.sh || regenerate-and-retry).
⚡TL;DR
High Voltage is a Rails engine that simplifies serving static marketing pages and content pages in Rails applications without requiring a full controller per page. It maps view templates in app/views/pages/ to routes automatically, handles nested directory structures (e.g., /pages/about/corporate/policies), and provides helper methods like page_path() to link to pages and HighVoltage.page_ids to enumerate all available pages for sitemaps. Rails engine architecture: the core routing and controller logic lives in app/controllers/high_voltage/pages_controller.rb and app/controllers/concerns/high_voltage/static_page.rb; page discovery is handled by lib/high_voltage/page_finder.rb and lib/high_voltage/page_collector.rb; routes are dynamically drawn via lib/high_voltage/route_drawers/ classes; configuration is centralized in lib/high_voltage/configuration.rb and initialized in lib/high_voltage/engine.rb.
👥Who it's for
Rails developers building marketing websites, landing pages, or content-heavy applications who need to quickly add static pages without writing boilerplate controllers and routes. Particularly useful for teams using gems like sitemap_generator that need programmatic access to all page identifiers.
🌱Maturity & risk
Production-ready and stable; the gem is in maintenance mode (no new features planned per README), indicating maturity and long-term stability. It maintains compatibility across Rails 7.0–8.0 (via Appraisals gemfiles), has comprehensive test coverage (spec/ directory), and runs CI on every commit (GitHub Actions in .github/workflows/ci.yml). Last activity visible through CI workflow configuration suggests ongoing maintenance.
Low risk: the codebase is small (~27KB Ruby), has no external gem dependencies (only Rails itself), and follows thoughtbot's polished patterns. Maintenance-mode status means breaking changes are unlikely but new features won't land; monitor the SECURITY.md policy for any CVEs. Single maintainer risk exists but is mitigated by the simplicity of the code and long track record.
Active areas of work
The gem is in maintenance mode and not actively adding features. The presence of gemfiles for Rails 7.0, 7.1, 7.2, and 8.0 suggests recent updates to support the latest Rails versions. CI workflows (ci.yml, dynamic-readme.yml, dynamic-security.yml) indicate regular dependency and security checks are automated.
🚀Get running
Clone the repo, install dependencies, and run specs:
git clone https://github.com/thoughtbot/high_voltage.git
cd high_voltage
bundle install
bundle exec rake
To test against a specific Rails version:
bundle exec appraisal rails-8.0 bundle install
bundle exec appraisal rails-8.0 rake
Daily commands:
This is a library gem, not a standalone app. Run the test suite with bundle exec rake or bundle exec rspec. The spec/fake_app.rb sets up a minimal Rails app for testing. To integrate into your own Rails app: add gem 'high_voltage', '~> 5.0.0' to Gemfile, bundle, create app/views/pages/ directory, place .html.erb files there, and optionally configure via config/initializers/high_voltage.rb.
🗺️Map of the codebase
lib/high_voltage/engine.rb— Rails engine entry point that initializes High Voltage and loads routes into the host application.app/controllers/high_voltage/pages_controller.rb— Core controller that handles rendering static pages from the views directory based on page parameters.lib/high_voltage/page_finder.rb— Locates and validates page templates in the configured views directory, core to page resolution logic.lib/high_voltage/configuration.rb— Manages High Voltage configuration options like page directory and routing behavior that affects all page rendering.config/routes.rb— Defines the routing constraints and patterns that mount High Voltage routes into the host Rails app.lib/high_voltage/page_collector.rb— Discovers all available static pages from the filesystem to enable page enumeration and validation.app/controllers/concerns/high_voltage/static_page.rb— Shared concern providing page rendering logic that can be mixed into custom page controllers.
🧩Components & responsibilities
- HighVoltage::Engine (Rails Engine API) — Initializes the engine, loads routes, and registers High Voltage into the host Rails application
- Failure mode: If engine fails to load, routes are not mounted and page requests 404
- HighVoltage::PagesController (Rails ActionController) — Receives routed requests and delegates to page_finder and rendering logic to return static page content
- Failure mode: If controller crashes, the entire /pages route becomes unavailable; should validate page existence before rendering
- HighVoltage::PageFinder (File I/O, Rails view path resolution) — Locates page templates by name within the configured views directory and validates existence
- Failure mode: If finder fails to locate a page, controller returns 404; invalid paths could expose directory traversal risks if not validated
- HighVoltage::PageCollector (File globbing, Dir traversal) — Enumerates all available page templates for discovery and validation
- Failure mode: If collector fails, page discovery features break; large directories may cause slow enumeration
- HighVoltage::Configuration (Rails configuration DSL) — Manages user-configurable settings like page directory, layout, and route behavior
- Failure mode: If configuration is invalid, pages may render with wrong layout or routes may not work as expected
🔀Data flow
Browser→Rails Router— HTTP GET request to /pages/:id or configured root routeRails Router→PagesController— Routed request with page id parameterPagesController→PageFinder— Page id to locate template filePageFinder→File System— Query for page template in configured directory (app/views/pages by default)File System→PageFinder— Page template path if found, or nil if not foundPageFinder→PagesController— Page object with template path and metadataPagesController→Rails View System— Render template with layout and helpersRails View System→Browser— Rendered HTML content or 404 error response
🛠️How to make changes
Add a new static page
- Create a new ERB template in the configured pages directory (
app/views/pages/my_new_page.html.erb) - Link to the page using the page_path helper (
spec/fixtures/app/views/pages/about.html.erb) - Optionally add a spec to verify the page renders correctly (
spec/features/view_page_spec.rb)
Customize page configuration and routing
- Configure High Voltage in a Rails initializer using HighVoltage.configure (
lib/high_voltage/configuration.rb) - Set custom page directory, layout, or route options (
lib/high_voltage/configuration.rb) - Review the engine routes to understand mounted paths (
config/routes.rb)
Subclass the pages controller for custom behavior
- Create a custom controller inheriting from HighVoltage::PagesController (
spec/support/app/controllers/subclassed_pages_controller.rb) - Override render_page or other methods to customize page rendering (
app/controllers/high_voltage/pages_controller.rb) - Update routes to use your custom controller instead of the default (
config/routes.rb)
Use the static_page concern in custom controllers
- Include the static_page concern in your custom controller (
app/controllers/concerns/high_voltage/static_page.rb) - Rely on page_finder and render_page methods provided by the concern (
app/controllers/concerns/high_voltage/static_page.rb) - Define custom actions that call the concern's methods (
spec/support/app/controllers/alternative_finder_controller.rb)
🔧Why these technologies
- Rails Engine — Encapsulates static page functionality as a mountable plugin that integrates seamlessly into host Rails applications without modifying core app code.
- File-system based page discovery — Eliminates database dependency for simple static content, allows developers to manage pages as templates checked into version control.
- Concerns for code reuse — Allows custom page controllers to share common rendering and validation logic without tight coupling to the base PagesController.
⚖️Trade-offs already made
-
Maintenance-mode status with no new features
- Why: The gem has reached stability and thoughtbot prioritizes reliability and compatibility over feature expansion.
- Consequence: Users requiring advanced features must implement custom controllers or use alternative gems; community contributions are reviewed but not solicited.
-
Simple file-based page discovery over database storage
- Why: Reduces operational complexity and aligns with Rails conventions for content-heavy applications.
- Consequence: Pages cannot be dynamically created at runtime; all pages must exist as template files in the repository.
-
Catch-all routing with optional root route constraint
- Why: Provides flexibility for developers to define root routes independently or delegate to High Voltage.
- Consequence: Route precedence must be carefully managed in the host application to avoid conflicts.
🚫Non-goals (don't propose these)
- Does not provide a CMS or dynamic page creation interface
- Does not handle authentication or authorization of pages
- Does not provide SEO metadata management (except via templates)
- Does not support real-time page updates without server restart
- Does not manage page versioning or rollbacks
⚠️Anti-patterns to avoid
- Missing path traversal validation in page lookup —
lib/high_voltage/page_finder.rb: Page id parameter is not strictly validated to prevent directory traversal attacks (e.g., '../../../etc/passwd'). If page
🪤Traps & gotchas
Templates must live in app/views/pages/ or a custom path set via HighVoltage.configure { |c| c.routes_root = '...' }. The home_page configuration sets up a 301 redirect from /home to / if you route the root path to a page. Nested pages use directory separators (e.g., about/corporate/policies maps to app/views/pages/about/corporate/policies.html.erb and route /pages/about/corporate/policies). The gem assumes ERB templates by default; other template engines work if Rails can resolve them. No other significant gotchas; the codebase is straightforward.
🏗️Architecture
💡Concepts to learn
- Rails Engine — High Voltage is implemented as a mountable Rails engine; understanding engine conventions (lib/, app/, config/routes.rb structure) is essential to extending or debugging this gem
- Routing Constraints — The gem uses constraint classes in lib/high_voltage/constraints/ to conditionally match and route requests; this pattern prevents conflicts with application routes
- Dynamic Route Generation — Routes are not hardcoded but generated at boot time by route_drawers/ based on discovered page files; this is how the gem scales to hundreds of pages without explicit route declarations
- Convention over Configuration — High Voltage relies on file location conventions (app/views/pages/) and naming conventions (filename = route ID) to minimize boilerplate; understanding this principle helps predict behavior without reading docs
- Rails Concerns (Mixins) — The static_page concern in app/controllers/concerns/ is a reusable mixin that adds the page-rendering behavior to controllers; this pattern allows users to subclass PagesController if needed
- HTTP 301 Redirect — When routing a static page to the root path (/), the gem issues a 301 permanent redirect from /home to / for SEO; understanding this is critical if your app depends on specific URL semantics
🔗Related repos
thoughtbot/clearance— Complementary thoughtbot gem for authentication; often used alongside High Voltage for public marketing sites with user accountsthoughtbot/factory_bot— Testing companion gem from the same maintainer; used in High Voltage's own test suite for fixture managementrails/webpacker— Asset bundling for Rails; commonly paired with High Voltage static pages that need CSS and JavaScriptsitemap_generator/sitemap_generator— Directly integrated use case; High Voltage.page_ids is designed to feed page enumeration into sitemap generationrails/rails— Core dependency; High Voltage wraps Rails routing, controllers, and template rendering into a convenience layer
🪄PR ideas
To work on one of these in Claude Code or Cursor, paste:
Implement the "<title>" PR idea from CLAUDE.md, working through the checklist as the task list.
Add comprehensive tests for PageFinder with custom page directories
The lib/high_voltage/page_finder.rb is a critical component for locating static pages, but spec/controllers/ only tests it indirectly through controller specs. There are no dedicated unit tests for PageFinder's edge cases, such as handling non-existent directories, symlinks, or performance with many pages. This would improve reliability and make refactoring safer.
- [ ] Create spec/lib/high_voltage/page_finder_spec.rb with tests for finding pages in custom directories
- [ ] Add tests for edge cases: missing directories, nested directories, files without extensions
- [ ] Add tests for the PageCollector (spec/lib/high_voltage/page_collector_spec.rb) which scans directories
- [ ] Verify tests pass with all gemfiles (rails_7.0 through 8.0)
Add tests for Configuration class and custom route drawers
lib/high_voltage/configuration.rb and lib/high_voltage/route_drawers/ are core infrastructure files, but there are no dedicated unit tests. The route_drawers (default.rb and root.rb) control how static pages are routed, making them critical to test thoroughly. Currently only integration tests exist via spec/features/.
- [ ] Create spec/lib/high_voltage/configuration_spec.rb testing all configuration options
- [ ] Create spec/lib/high_voltage/route_drawers/default_spec.rb and root_spec.rb for route generation
- [ ] Test configuration defaults, custom page directories, and route constraint behavior
- [ ] Ensure tests cover the RootRoute constraint (spec/constraints/root_route_spec.rb already exists but may need expansion)
Add integration test for alternative view layouts with the current_page_helper
spec/fixtures/app/views/layouts/alternate.html.erb exists but is not tested. The current_page_helper (tested in spec/features/current_page_helper_spec.rb) should be verified to work correctly with alternate layouts, and there's no test ensuring pages can be rendered with non-default layouts. This validates a real-world use case.
- [ ] Add test case to spec/features/current_page_helper_spec.rb or create spec/features/alternate_layout_spec.rb
- [ ] Create a fixture page that uses the alternate layout in spec/fixtures/app/views/pages/
- [ ] Test that current_page_helper works correctly when alternate layouts are specified
- [ ] Verify layout selection works with the HighVoltage configuration and routing
🌿Good first issues
- Add integration test coverage for the dynamic route generation in route_drawers/ with various Rails versions (appraisals available but tests sparse)
- Document the complete configuration API with examples in a dedicated CONFIGURATION.md file, referencing the sparse README section
- Add helper method specs in spec/features/current_page_helper_spec.rb for edge cases like missing pages and deeply nested paths to catch 404 behaviors
⭐Top contributors
Click to expand
Top contributors
- @mjankowski — 39 commits
- @sbs-cats — 30 commits
- @dependabot[bot] — 8 commits
- @MatheusRich — 5 commits
- @github-actions[bot] — 5 commits
📝Recent commits
Click to expand
Recent commits
97b6148— Require MFA for gem pushes (#344) (MatheusRich)b8ce819— Bump actions/checkout from 4 to 6 (#343) (MatheusRich)2b47f3d— Require MFA for gem pushes (MatheusRich)f3a0f9c— Bump actions/checkout from 4 to 6 (dependabot[bot])7e8e621— Release version 5.0.0 (#342) (emilford)dff6caf— Automatically Generated: Update Dynamic Section in README (#339) (github-actions[bot])efe763d— Adjust routes drawing to be compatible with Rails main (#336) (seanpdoyle)950f527— Adjust routes drawing to be compatible with Rails main (luizkowalski)90102a2— Update rspec-rails requirement from ~> 5.1.2 to ~> 7.1.1 (#338) (dependabot[bot])49308ce— Update test matrix to supported Ruby + Rails versions (#337) (luizkowalski)
🔒Security observations
The high_voltage gem is a relatively simple Rails engine for rendering static pages. The main security concerns are potential path traversal vulnerabilities through improper page name validation and the fact that the project is in maintenance mode with limited active security support. The codebase follows good practices with proper documentation and CI/CD setup, but lacks visible automated security scanning. Input validation on the page parameter should be the priority focus for remediation. Overall security posture is moderate for a maintenance-mode gem with typical Rails conventions.
- Medium · Potential Path Traversal in Static Page Rendering —
lib/high_voltage/page_finder.rb, app/controllers/high_voltage/pages_controller.rb. The high_voltage gem renders static pages based on user-supplied parameters. If the page_finder or page routing logic doesn't properly validate and sanitize page names, an attacker could potentially use path traversal sequences (e.g., '../../../etc/passwd') to access files outside the intended pages directory. Fix: Ensure all page name parameters are properly validated and sanitized. Implement strict whitelisting of allowed characters and prevent directory traversal sequences like '..'. Verify that file resolution is constrained to the configured pages directory only. - Medium · Missing Input Validation on Page Parameters —
app/controllers/high_voltage/pages_controller.rb. The PagesController accepts a 'page' parameter from user input that is used to locate and render view files. Without proper validation, this could lead to unintended file access or rendering of sensitive templates. Fix: Implement strict input validation for the page parameter. Use a whitelist of allowed page names or implement robust path normalization and validation to ensure only intended pages can be accessed. - Low · Maintenance Mode - Limited Active Development —
README.md, SECURITY.md. According to the README, high_voltage is in maintenance-mode with no active feature development. This means security updates and compatibility patches may be delayed, and the gem may not receive timely responses to emerging security issues. Fix: Monitor the project's security announcements closely. Consider having a plan to migrate to an alternative solution or maintain a fork if critical security issues are discovered. Regularly review the gem's dependencies for vulnerabilities. - Low · Single Version Support Policy —
SECURITY.md. The SECURITY.md policy states that only the latest version is supported. This creates a hard requirement to always upgrade, which may introduce compatibility issues or regression risks for users unable to update immediately. Fix: Consider extending security support to at least the current and previous major versions to allow users reasonable time for testing and validation before forced upgrades. - Low · No Automated Dependency Scanning Visible —
.github/workflows/, Gemfile.lock. While the GitHub Actions workflows are present, there is no visible automated security scanning for known vulnerabilities in dependencies (e.g., Dependabot configured with security alerts). Fix: Enable GitHub's Dependabot security alerts or integrate OWASP Dependency-Check or similar tools into the CI/CD pipeline to automatically detect and flag vulnerable dependencies.
LLM-derived; treat as a starting point, not a security audit.
👉Where to read next
- Open issues — current backlog
- Recent PRs — what's actively shipping
- Source on GitHub
Generated by RepoPilot. Verdict based on maintenance signals — see the live page for receipts. Re-run on a new commit to refresh.