Issued is a Rails 8 app for a Hack Club-style flow where users can design apparel with code, track effort through Hackatime, RSVP for an event/launch, and submit orders.
The app includes:
- Hack Club OAuth sign-in
- RSVP flow with open/closed state toggles
- User dashboard with design and order pipeline visibility
- Design editor flow with optional Hackatime project linking
- Admin area for user/product/order management plus RSVP CSV import
- What Is Issued
- Current Feature Set
- Tech Stack
- Architecture Overview
- Data Model Snapshot
- Local Setup
- Environment Variables
- Authentication (Hack Club OAuth)
- Developer Workflow
- Testing, Linting, and Security
- Admin Operations
- Deployment
- Project Structure
- Known Gaps / Notes
YS: Make Designs with code either using hackatime or the integrated svg editor WS: Get custom clothes made with your designss
From an admin perspective:
- Manage users and roles.
- Manage products.
- View/manage orders (some order admin actions are currently stubs).
- Import RSVP records via CSV.
- Home page (
/) - About page (
/about) - FAQ page (
/faq) - RSVP page (
/rsvp) - RSVP count page (
/rsvps) - Dynamic RSVP OG image (
/rsvps/og-image.svg)
- OAuth login entry (
/login) - OmniAuth callback (
/auth/:provider/callback) - Auth failure handler (
/auth/failure) - Logout (
/logout)
- Dashboard (
/dashboard) - Designs CRUD-ish flow (
/designs, plus editor routes) - Orders pages (
/orders,/orders/new, etc.)
- Admin dashboard (
/admin) - Admin users/products/orders resources
- Admin RSVP listing/import/delete
- Ruby:
3.4.9 - Rails:
8.1.2.1 - Database: SQLite (
storage/*.sqlite3) - Assets: Propshaft + Importmap (no Node bundler required for app runtime)
- Frontend behavior: Turbo + Stimulus
- Auth: OmniAuth + custom Hack Club strategy
- Background/cache/cable: Solid Queue, Solid Cache, Solid Cable
- Deployment support: Docker + Kamal
- Quality/security tooling: RuboCop, Brakeman, bundler-audit, importmap audit
At a high level:
- Controllers handle web flows for home/dashboard/designs/orders/rsvp/admin.
SessionsController+ custom OmniAuth strategy manage Hack Club OAuth.HackatimeServicewraps Hackatime API calls for trust/project stats.- Models connect the design-order-user lifecycle.
- Active Storage stores uploaded assets (SVG previews, product/design images).
Key integration services:
- Hack Club OAuth provider (
lib/omniauth/strategies/hackclub.rb) - Hackatime API integration (
app/services/hackatime_service.rb)
Main entities:
User- OAuth identity (
slack_id, name, tokens) - Role enum (
user,admin,superadmin) - Trust + verification + YSWS eligibility fields
- OAuth identity (
Design- Belongs to a user
- Optional Hackatime project metadata
- Active Storage attachments (
svg,image)
DesignEditSession- Tracks edit intervals and duration
Product- Catalog item (with optional image)
Order- Connects
User,Design, andProduct - Status pipeline (
pending,processing,production,completed,cancelled)
- Connects
Rsvp- Simple association to
User
- Simple association to
See db/schema.rb for source-of-truth schema details.
- Ruby
3.4.9(matches.ruby-version) - Bundler
- SQLite3
Optional but useful:
- Docker (for containerized runs)
ghCLI (if you use optional CI signoff flow)
git clone https://github.com/Acidicts/Issued.git
cd Issued
bundle installlcp .env.example .envSet at least OAuth variables (see Environment Variables).
bin/rails db:preparebin/devThen open http://localhost:3000.
If you prefer, use:
bin/setupbin/setup installs dependencies, prepares DB, clears logs/tmp, and starts the dev server unless --skip-server is passed.
Environment is typically loaded via dotenv-rails in development/test.
HACKCLUB_CLIENT_IDHACKCLUB_CLIENT_SECRET
Without these, /login redirects back with an OAuth-not-configured alert.
HACKCLUB_REDIRECT_URI- Explicit callback URL for OAuth provider config.
APP_URL- Used to build absolute URLs/OG metadata in helpers/admin views.
HACKATIME_API_KEYHACKATIME_START_DATE(default is 30 days ago)HACKATIME_CACHE_TTL_SECONDS(default300)HACKATIME_BYPASS_CACHE(presence disables cache)
HACKCLUB_ACCESS_TOKENHACKCLUB_REFRESH_TOKEN
These are fallback sources if user/session tokens are unavailable.
RUNNINGENDEDRSVP_OPEN
Used to drive RSVP and home-page CTA behavior.
EXCHANGE_RATE_API_KEY- Enables GBP->USD conversion utility used in product-related helpers.rs.
PORT(Puma default is3000)PIDFILE(optional)SOLID_QUEUE_IN_PUMA(enables Solid Queue plugin inside Puma)RAILS_MASTER_KEY(required for encrypted credentials in environments that need it)
OAuth flow details:
- User visits
/login. - App redirects to
/auth/hackclub. - Callback hits
/auth/hackclub/callback. - Session is established (
session[:user_id], token fields). - User record is created/updated from OAuth profile.
Implementation files:
- Initializer:
config/initializers/omniauth.rb - Strategy:
lib/omniauth/strategies/hackclub.rb - Controller:
app/controllers/sessions_controller.rb
# Start local server
bin/dev
# Rails console
bin/rails console
# Prepare DB
bin/rails db:prepare
# Reset DB (destructive)
bin/setup --reset --skip-serverrbin/devcurrently execsbin/rails serverdirectly.- This app uses Importmap, so there is no JS bundler build step required for standard development.
bin/cibin/ci performs setup, style checks, security scans, tests, and seed replant in test.
# Tests
bin/rails test
bin/rails test:system
# Style
bin/rubocop
# Security
bin/brakeman --quiet --no-pager --exit-on-warn --exit-on-error
bin/bundler-audit
bin/importmap auditditWorkflow at .github/workflows/ci.yml runs:
- Ruby security scans
- JS dependency audit (importmap)
- RuboCop
- Rails tests
- Optional system tests when present
Admin access requires current_user.admin? (admin or superadmin role).
- Endpoint/UI: Admin RSVP page
- Expected CSV headers:
slack_id(required)name(optional)
The importer creates or updates users by slack_id, then creates RSVP records if missing.
- Role changes in admin user update are restricted to
superadminusers.
This repository ships a production-ready multi-stage Dockerfile.
docker build -t issued .
docker run --rm -p 3000:3000 --env-file .env issueddContainer details:
- Entrypoint:
bin/docker-entrypoint(prepares DB on startup) - Health endpoint:
/up - Default server: Puma with
config/puma.rb
config/deploy.yml is present for Kamal deploys.
Before using it:
- Replace placeholder hosts/registry values.
- Configure secrets (especially
RAILS_MASTER_KEY) in.kamal/secrets. - Validate persistent volume strategy (
issued_storage:/rails/storage) for SQLite and Active Storage data.
app/
controllers/ # user, auth, RSVP, admin flows
models/ # User, Design, Order, Product, Rsvp, DesignEditSession
services/ # Hackatime integration
views/ # ERB templates
config/
routes.rb # route map
initializers/ # OmniAuth and framework setup
db/
schema.rb # current schema state
lib/
omniauth/strategies/hackclub.rb
bin/
setup, dev, ci, rails, rubocop, brakeman, bundler-audit
undler-audit
Admin::OrdersControllermethods are currently stubs and should be completed before relying on full admin order operations.Designenforces global uniqueness forhackatime_project; if project sharing across users is desired, that constraint may need redesign..env.exampleincludes some placeholders and may contain redundant entries; keep local.envaligned with actual variables used in code.
- Create a branch.
- Make changes with tests.
- Run
bin/cilocally. - Open a PR.
If you are introducing new env vars, migrations, or operational scripts, update this README in the same PR.