A web application for onboarding under-18 participants for in-person Hack Club events. Attend collects all information needed for safeguarding, travel, accommodation, and operational workflows—with a focus on security and data protection.
- Multi-event support — Manage multiple events with separate configurations
- Participant onboarding — Multi-step wizard for profile, travel, accommodation, health, and guardian info
- Guardian portal — Secure magic-link access for parents/guardians to complete consent forms
- Role-based access control — Global Admin, Event Admin, Ops Staff, Safeguarding Lead roles
- Sensitive data encryption — Medical and safeguarding information encrypted at rest
- Mobile wallet passes — Apple Wallet and Google Wallet support for event check-in
- Audit logging — Full trail of admin actions with PaperTrail and console1984
- QR code check-in — Scan participants at event venues
| Category | Technology |
|---|---|
| Framework | Ruby 3.4 / Rails 8.1 |
| Database | PostgreSQL with UUID primary keys |
| Frontend | Hotwire (Turbo + Stimulus), Tailwind CSS |
| Authentication | Devise + OmniAuth (Hack Club Auth) |
| Authorization | Pundit |
| Background Jobs | Solid Queue + Mission Control |
| Caching | Solid Cache |
| Real-time | Solid Cable (Action Cable) |
| Asset Pipeline | Propshaft + Importmap |
| Deployment | Docker |
| Storage | Active Storage with S3 (Cloudflare R2) |
- Ruby 3.4+
- PostgreSQL 15+
- Node.js 18+ (for Tailwind CSS watcher)
# Clone the repository
git clone https://github.com/hackclub/attend.git
cd attend
# Install Ruby dependencies
bundle install
# Setup database
rails db:create db:migrate db:seed
# Start development server (Rails + Tailwind watcher)
bin/devThe app will be available at https://localhost:3000.
After running seeds, these accounts are available:
| Password | Role | |
|---|---|---|
| admin@hackclub.com | password123 | Global Admin |
| eventadmin@hackclub.com | password123 | Event Admin |
| ops@hackclub.com | password123 | Ops Staff |
| safeguarding@hackclub.com | password123 | Safeguarding Lead |
| participant@example.com | password123 | Participant |
Copy .env.example to .env for development:
cp .env.example .envKey variables:
| Variable | Description |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
HACK_CLUB_CLIENT_ID / HACK_CLUB_CLIENT_SECRET |
OAuth credentials |
DOCUSEAL_API_KEY / DOCUSEAL_WEBHOOK_SECRET |
E-signature integration |
SENTRY_DSN |
Error monitoring |
For production secrets, use Rails encrypted credentials:
EDITOR="code --wait" rails credentials:editRequired credentials structure:
app_host: attend.hackclub.com
database_url: postgres://user:pass@host:5432/dbname
hack_club:
client_id: your_client_id
client_secret: your_client_secret
docuseal:
api_key: your_api_key
webhook_secret: your_secret
sentry:
dsn: https://your-sentry-dsn
# Encryption keys (generate with: bin/rails db:encryption:init)
active_record_encryption:
primary_key: generated_key
deterministic_key: generated_key
key_derivation_salt: generated_saltFor Apple Wallet passes, add PassKit configuration:
passkit:
web_service_host: https://attend.hackclub.com
apple_team_identifier: YOUR_TEAM_ID
pass_type_identifier: pass.com.hackclub.attend
certificate_key: your_p12_password
private_p12_certificate: /path/to/certificate.p12
apple_intermediate_certificate: /path/to/WWDR.cerFor Google Wallet, see Google Wallet Prerequisites.
| Role | Access |
|---|---|
| Participant | Complete onboarding for events, view their status |
| Guardian | Complete consent forms via magic link |
| Global Admin | Full access to all events and data |
| Event Admin | Full access for assigned events |
| Ops Staff | View/edit operational data (travel, accommodation) |
| Safeguarding Lead | Access to medical and safeguarding information |
Event
├── ParticipantEvent (join table with status)
│ ├── Participant
│ ├── GuardianParticipantEvent
│ │ ├── Guardian
│ │ └── EmergencyContact
│ ├── Travel (inbound/outbound)
│ │ └── TravelLeg
│ ├── Accommodation
│ ├── Medical (encrypted)
│ ├── Dietary
│ ├── Accessibility (encrypted)
│ ├── SafeguardingInfo (encrypted)
│ └── Consent (Docuseal tracking)
├── Incident (encrypted)
├── Note (encrypted)
├── Scan (check-in records)
└── EventRoleAssignment (staff roles)
| Service | Purpose |
|---|---|
| Docuseal | Embedded consent forms with webhook status updates |
# Start development server with Tailwind watcher
bin/dev
# Rails server only
rails server
# Rails console
rails console
# Database operations
rails db:migrate # Run pending migrations
rails db:seed # Seed development data
rails db:reset # Drop, create, migrate, seed
# Show all routes
rails routes
# Generate encryption keys
bin/rails db:encryption:init# Run all tests
bundle exec rspec
# Run specific test files
bundle exec rspec spec/models/
bundle exec rspec spec/features/
# Run a single test file
bundle exec rspec spec/models/participant_spec.rb# Run RuboCop
bin/rubocop
# Auto-fix safe violations
bin/rubocop -a
# Security audit
bundle exec brakeman
bundle exec bundler-audit checkJobs are processed by Solid Queue. In development, they run inline. View the job dashboard at /admin/jobs (requires Global Admin).
Build and run with Docker:
docker build -t attend .
docker run -d -p 80:80 \
-e RAILS_MASTER_KEY=<value from config/master.key> \
--name attend attendSet RAILS_MASTER_KEY as an environment variable on your production server. Hack Club's production instance builds this Dockerfile and deploys it on every merge to main.
- Fork the repository
- Create a feature branch:
git checkout -b feature/your-feature - Make your changes
- Run tests:
bundle exec rspec - Run linter:
bin/rubocop - Commit with clear messages
- Push and open a Pull Request
- Follow the Rails Omakase style guide
- Use UUID primary keys for all models
- Encrypt sensitive data with Active Record Encryption
- Add Pundit policies for new resources
- Write specs for new features
Use clear, descriptive commit messages:
Add flight tracking integration with FlightAware
- Implement FlightTrackingService with provider fallback
- Add TravelLeg model for multi-leg journeys
- Schedule background job for status updates
- Never commit secrets or credentials
- Use Rails credentials for sensitive configuration
- Report security issues via security.hackclub.com
GNU General Public License v3.0
For questions or issues, open a GitHub issue or contact the Events team through the 'chat feature' on Attend, or through #attend