A web-based tool for managing two-way radio programming data. Create a single canonical codeplug and export it to multiple radio-specific CSV formats.
The Codeplug Application serves as a "Rosetta Stone" for radio programming files (codeplugs). Users create their radio configuration once in a universal format, then export it to CSV files compatible with dozens of different radio makes and models - each with their own programming software and data layout requirements.
Key Features:
- Universal Codeplug Format: Define channels, zones, systems, and talkgroups once
- Multi-Radio Export: Generate CSV files for Motorola, Baofeng, Kenwood, and more
- Analog & Digital Support: Handle analog, DMR, P25, NXDN, and other modes
- Shared Resources: Community-maintained database of repeaters and talkgroups
- Custom Layouts: Create and share CSV export formats for unsupported radios
- Backend: Ruby on Rails 8 with PostgreSQL
- Frontend: Hotwire (Turbo + Stimulus) with Bootstrap 5
- Testing: Minitest with Capybara for system tests
- Deployment: Kamal with Docker
- Development: TDD (Test-Driven Development) workflow
See docs/ARCHITECTURE.md for detailed architectural decisions and patterns.
The application manages several key entities:
- Codeplugs: User's complete radio configuration
- Zones: Standalone templates defining systems and talkgroups (public/private)
- Channels: Generated from zones or manually created
- Systems: Repeater/simplex frequencies with technical specs (shared resource)
- TalkGroups: Digital radio talkgroup definitions organized by networks
- Radio Models: Radio hardware specifications and capabilities
- Codeplug Layouts: CSV export format definitions for specific radios
Zones use a template-based approach:
- Zones are standalone entities owned by users (not embedded in codeplugs)
- Zones can be public (shareable) or private
- Zones define which systems and talkgroups to include
- Channels are generated from zones when the user is ready
- Generated channels can be customized (changes persist until regeneration)
See docs/MODELS.md for complete data model documentation.
- Ruby: See
.ruby-version(Ruby 3.x) - Node.js: See
.node-version(for esbuild) - Database: PostgreSQL (version 12 or higher recommended)
- Bundler: Latest version
- Yarn: Latest version
git clone https://github.com/livitup/codeplug_app.git
cd codeplug_app# Install Ruby gems
bundle install
# Install JavaScript dependencies
yarn install# Database configuration is already set up for PostgreSQL
# Edit config/database.yml if you need custom settings
# Default assumes PostgreSQL on localhost with standard settings# Create database, run migrations, and seed initial data
bin/rails db:setupSeed User Credentials (Development):
- Email:
dev@example.com - Password:
password123
The seed data creates:
- 1 development user account
- 10 radio manufacturers
- 10 realistic radio models with specifications
- Sample networks (Brandmeister, TGIF, P25 Network)
- Sample systems (analog and DMR repeaters)
- Sample talkgroups
- Sample zones with systems and talkgroups
- Sample codeplug with generated channels
# Starts Rails server, CSS bundler, and JS bundler
bin/devThe application will be available at http://localhost:3000
This project follows strict TDD. All features and bug fixes must:
- Start with failing tests
- Implement minimum code to pass
- Refactor while keeping tests green
- Ensure ALL tests pass before committing
No exceptions.
# Run all tests
rails test
# Run specific test file
rails test test/models/channel_test.rb
# Run system tests
rails test:system
# Run all tests including system tests
rails test:all# Run RuboCop (auto-fix and check style/lint)
rubocop -a
# Run Brakeman (security scanner)
brakemanALL of the following must pass:
# 1. Run full test suite
rails test:all
# 2. Auto-fix and check code style
rubocop -a
# 3. Check security
brakemanImportant: If any test fails (even if unrelated to your changes), you MUST fix it before creating a PR. No exceptions.
app/
├── controllers/ # HTTP request handling
├── models/ # Data models and business logic
├── views/ # HTML templates (ERB)
├── javascript/ # Stimulus controllers and JS
├── assets/ # Stylesheets (Bootstrap SCSS)
├── services/ # Business logic (exporters, importers, etc.)
├── forms/ # Form objects for complex forms
└── queries/ # Complex database queries
test/
├── models/ # Model unit tests
├── controllers/ # Controller integration tests
├── system/ # End-to-end browser tests (Capybara)
├── services/ # Service object tests
└── fixtures/ # Test data
docs/
├── MODELS.md # Complete data model documentation
├── ARCHITECTURE.md # Architecture decisions and patterns
└── CLAUDE.md # AI assistant instructions (optional)
config/
├── database.yml # Database configuration
├── routes.rb # URL routing
└── deploy.yml # Kamal deployment config
# Generate model with migrations
rails generate model Channel name:string codeplug:references system:references
# Run TDD workflow
# 1. Write tests in test/models/channel_test.rb
# 2. Run: rails test test/models/channel_test.rb
# 3. Implement model logic
# 4. Repeat until green# Generate controller with views
rails generate controller Channels index show new create edit update destroy
# Write controller tests first
# test/controllers/channels_controller_test.rb
# Write system tests for user workflows
# test/system/channel_management_test.rb# Create service in app/services/
touch app/services/codeplug_exporter.rb
# Create test first
touch test/services/codeplug_exporter_test.rb
# Follow TDD workflow# Create migration
rails generate migration AddBandwidthToSystems bandwidth:string
# Edit migration file in db/migrate/
# Run migration
rails db:migrate
# Rollback if needed
rails db:rollback-
Create mode detail model (polymorphic)
rails generate model NxdnModeDetail ran:integer
-
Add mode to System enum
-
Update forms to show/hide mode-specific fields
-
Write tests for new mode
-
Update export logic to handle new mode
- User registers/logs in
- Navigates to "Zones" in the navigation menu
- Creates a new Zone (name, optional long/short names)
- Adds Systems to the zone (analog repeaters, DMR repeaters, etc.)
- For digital systems, adds Talkgroups (with timeslot info)
- Optionally marks the zone as "Public" to share with other users
- User creates a new Codeplug
- Adds Zones to the codeplug (own zones or public zones from other users)
- Reorders zones as desired using drag-and-drop
- Clicks "Generate Channels" to create channels from the zone templates
- Optionally customizes generated channels (name, power level, etc.)
- Exports Codeplug for specific Radio Model
If you modify zones (add systems/talkgroups) after generating channels:
- Navigate to the codeplug
- Click "Regenerate Channels"
- Confirm the regeneration (existing channels will be replaced)
- New channels are generated from the updated zone templates
- Any previous customizations will be lost
- User selects Codeplug to export
- Selects target Radio Model
- System checks Zone sizes against radio limits
- If needed, prompts for Zone split strategy
- Generates CSV using CodeplugLayout for that radio
- User downloads CSV file
- User imports CSV into radio programming software
- Admin/User creates Manufacturer (if needed)
- Creates Radio Model with specs (zones, channels, name lengths)
- Uses field picker interface to define CSV layout
- Saves CodeplugLayout associated with Radio Model
- Other users can now export to this radio format
# First-time setup
kamal setup
# Deploy updates
kamal deploy
# View logs
kamal app logs
# Rollback to previous version
kamal rollbackSee config/deploy.yml for deployment configuration.
Required environment variables for production:
RAILS_MASTER_KEY=<from config/master.key>
DATABASE_URL=<production database connection string>- Test-Driven Development: Write tests first, always
- Follow Rails Conventions: Use Rails idioms and patterns
- Code Style: Pass RuboCop checks (run with -a to auto-fix)
- Security: Pass Brakeman checks
- Documentation: Update docs for significant changes
- Create feature branch from
main - Write failing tests for new feature/fix
- Implement feature/fix following TDD
- Ensure ALL tests pass (
rails test:all) - Ensure RuboCop passes (
rubocop -a) - Ensure Brakeman passes (
brakeman) - Create PR with clear description
- Address code review feedback
- Squash merge to main after approval
Add feature/fix description (present tense)
- Bullet points for details
- What changed and why
- Reference issue numbers
Closes #123
- Unit Tests: Test individual models, methods, validations
- Integration Tests: Test controller actions, request/response
- System Tests: Test complete user workflows with browser
- All Tests Must Pass: No failing tests allowed in PRs
# Check database is running
# macOS with Homebrew:
brew services list | grep postgresql
# Linux:
systemctl status postgresql
# Verify credentials in config/database.yml
# Test connection manually
psql -U postgres -d codeplug_app_development# Rebuild assets
rails assets:clobber
rails assets:precompile
# Or restart dev server
bin/dev# Reset test database
RAILS_ENV=test rails db:reset
# Re-run tests
rails test:all# Reinstall node modules
rm -rf node_modules
yarn install
# Restart esbuild
bin/dev- Data Models Documentation - Complete model specifications
- Architecture Documentation - Design decisions and patterns
- Rails Guides - Rails framework documentation
- Hotwire Documentation - Turbo and Stimulus guides
- Bootstrap Documentation - UI component library
- Issues: Report bugs and request features via GitHub Issues
- Discussions: Ask questions in GitHub Discussions
[Add your license here]
Built with:
Status: Active Development
Version: 0.1.0 (Initial Development)
Last Updated: 2025-12-17