Fizzy.do
by @christopher_sonnier in Agents 1 day ago

The AGENTS.md file from the Fizzy.do project

Download

Fizzy

This file provides guidance to AI coding agents working with this repository.

What is Fizzy?

Fizzy is a collaborative project management and issue tracking application built by 37signals/Basecamp. It's a kanban-style tool for teams to create and manage cards (tasks/issues) across boards, organize work into columns representing workflow stages, and collaborate via comments, mentions, and assignments.

Development Commands

Setup and Server

bin/setup              # Initial setup (installs gems, creates DB, loads schema)
bin/dev                # Start development server (runs on port 3006)

Development URL: http://fizzy.localhost:3006
Login with: david@example.com (development fixtures), password will appear in the browser console

Testing

bin/rails test                    # Run unit tests (fast)
bin/rails test test/path/file_test.rb  # Run single test file
bin/rails test:system             # Run system tests (Capybara + Selenium)
bin/ci                            # Run full CI suite (style, security, tests)

# For parallel test execution issues, use:
PARALLEL_WORKERS=1 bin/rails test

CI pipeline (bin/ci) runs:
1. Rubocop (style)
2. Bundler audit (gem security)
3. Importmap audit
4. Brakeman (security scan)
5. Application tests
6. System tests

Database

bin/rails db:fixtures:load   # Load fixture data
bin/rails db:migrate          # Run migrations
bin/rails db:reset            # Drop, create, and load schema

Other Utilities

bin/rails dev:email          # Toggle letter_opener for email preview
bin/jobs                     # Manage Solid Queue jobs
bin/kamal deploy             # Deploy (requires 1Password CLI for secrets)

Architecture Overview

Multi-Tenancy (URL-Based)

Fizzy uses URL path-based multi-tenancy:
- Each Account (tenant) has a unique external_account_id (7+ digits)
- URLs are prefixed: /{account_id}/boards/...
- Middleware (AccountSlug::Extractor) extracts the account ID from the URL and sets Current.account
- The slug is moved from PATH_INFO to SCRIPT_NAME, making Rails think it's "mounted" at that path
- All models include account_id for data isolation
- Background jobs automatically serialize and restore account context

Key insight: This architecture allows multi-tenancy without subdomains or separate databases, making local development and testing simpler.

Authentication & Authorization

Passwordless magic link authentication:
- Global Identity (email-based) can have Users in multiple Accounts
- Users belong to an Account and have roles: owner, admin, member, system
- Sessions managed via signed cookies
- Board-level access control via Access records

Core Domain Models

Account → The tenant/organization
- Has users, boards, cards, tags, webhooks
- Has entropy configuration for auto-postponement

Identity → Global user (email)
- Can have Users in multiple Accounts
- Session management tied to Identity

User → Account membership
- Belongs to Account and Identity
- Has role (owner/admin/member/system)
- Board access via explicit Access records

Board → Primary organizational unit
- Has columns for workflow stages
- Can be "all access" or selective
- Can be published publicly with shareable key

Card → Main work item (task/issue)
- Sequential number within each Account
- Rich text description and attachments
- Lifecycle: triage → columns → closed/not_now
- Automatically postpones after inactivity ("entropy")

Event → Records all significant actions
- Polymorphic association to changed object
- Drives activity timeline, notifications, webhooks
- Has JSON particulars for action-specific data

Entropy System

Cards automatically "postpone" (move to "not now") after inactivity:
- Account-level default entropy period
- Board-level entropy override
- Prevents endless todo lists from accumulating
- Configurable via Account/Board settings

UUID Primary Keys

All tables use UUIDs (UUIDv7 format, base36-encoded as 25-char strings):
- Custom fixture UUID generation maintains deterministic ordering for tests
- Fixtures are always "older" than runtime records
- .first/.last work correctly in tests

Background Jobs (Solid Queue)

Database-backed job queue (no Redis):
- Custom FizzyActiveJobExtensions prepended to ActiveJob
- Jobs automatically capture/restore Current.account
- Mission Control::Jobs for monitoring

Key recurring tasks (via config/recurring.yml):
- Deliver bundled notifications (every 30 min)
- Auto-postpone stale cards (hourly)
- Cleanup jobs for expired links, deliveries

Sharded Full-Text Search

16-shard MySQL full-text search instead of Elasticsearch:
- Shards determined by account ID hash (CRC32)
- Search records denormalized for performance
- Models in app/models/search/

Tools

Chrome MCP (Local Dev)

URL: http://fizzy.localhost:3006
Login: david@example.com (passwordless magic link auth - check rails console for link)

Use Chrome MCP tools to interact with the running dev app for UI testing and debugging.

Coding style

@STYLE.md