Tiny Thoughts
Replaced $3,000/mo Rethink BA
ABA clinical data collection platform. Purpose-built replacement for Rethink BA — the $3,000/month enterprise software — at a pediatric therapy agency. Discrete trial recording, automated mastery detection, prompt fading, and assessment scoring built around what BCBAs and RBTs actually do on the floor.
What it is
A production data collection system for Applied Behavior Analysis therapy. Therapists record discrete trials on iPad and phone; the platform detects mastery, recommends phase changes, scores standardized assessments with basal/ceiling logic, and enforces per-role session concurrency. Multi-tenant by default with row-level security on every clinical table.
By the numbers
| Metric | Value |
|---|---|
| Users | 37 (28 BCBAs, 5 admins, 3 owners, 1 RBT) |
| Children managed | 79 |
| Discrete trials recorded | 22,940+ |
| Targets | 4,523 across 283 programs |
| Mastery events detected | 129 |
| Phase changes executed | 920 |
| Monthly active users | 27 (73% MAU) |
| Daily active users | 18 |
| Active therapists recording weekly | 19 |
| Assessments completed | 314 (97% completion rate) |
| Assessment responses | 3,351 across 12 templates |
| Trial accuracy rate | 76.1% |
| Growth | 10 to 5,370 trials/week over 9 weeks (537x) |
| Peak day | 1,490 trials |
| Average | 568 trials/day |
| Audit trail | 2,418 audit events + 23,447 PaperTrail versions |
Engineering metrics
| Metric | Value |
|---|---|
| Lines of code | 86,478 |
| Commits | 877 in 71 days |
| Database migrations | 94 |
| Production tables | 43 |
| Fly.io releases | 73 |
| Rails test files | 145 |
| Rails models | 33 |
| Controllers | 40 |
| Stimulus controllers | 51 |
| ERB views | 182 |
| Pundit policies | 23 |
Architecture
iPad / phone (PWA, offline-capable)
|
v
Turbo + Stimulus UI ---> Rails 8.1 controllers ---> Pundit policies
| |
v v
Service objects acts_as_tenant scope
|
+---------------+---------------+
| | |
v v v
Mastery engine Assessment scorer Phase-change recommender
(pure TS domain kernel, property-tested with fast-check)
|
v
PostgreSQL 16 (Neon)
- Row-Level Security on every clinical table
- PaperTrail versioning
- pg_search full-text on notes
|
v
Solid Queue background jobs
- mastery_check_job
- program_completion_check_job
- regression_check_jobThree-tier config cascade: organization defaults → program template → enrollment overrides. Mastery, fading, and assessment rules resolve top-down so one child's configuration never bleeds into another.
Key features
- Pure TypeScript domain kernel — Mastery detection engine with configurable criteria per program type per prompt level. Assessment scorer with basal/ceiling discontinuation (FR6/FR63 rules). Phase-change recommender for prompt fading. Property-tested with fast-check.
- Three program types — Regular, Mand, and Eye-Contact, each with type-specific prompt sequences and mastery rules.
- Five RBAC roles with session concurrency — Owner, admin, BCBA, RBT, read-only viewer. RBT capped at 1 concurrent session; BCBA+ capped at 3. Enforced server-side with advisory locks.
- PostgreSQL Row-Level Security — Tenant isolation on every clinical table, not just the application layer. acts_as_tenant scopes Rails queries; RLS is the backstop.
- HIPAA-grade audit trail — PaperTrail versions plus a dedicated audit_events table. 23,447 version entries and 2,418 audit events in production.
- Authentication — bcrypt (cost 12), TOTP 2FA, 10 backup codes, rate limiting via Upstash Redis, idle lock screen with session timeout, Cloudflare Turnstile on login.
- PWA with offline trial recording — Serwist service worker. Therapists collect trials when the facility wifi drops and sync on reconnect.
- Assessment engine — 12 templates, basal/ceiling auto-advance, Turbo Stream scoring with query optimization.
- Design system — OKLCH algorithmic palette (3 CSS variables control the entire color system), View Transitions API, full dark mode.
What makes it stand out
- Built for the floor, not the office. Every touch target sized for noisy classrooms and imprecise taps. Therapists are collecting trials, not navigating menus.
- 537x usage growth in 9 weeks — 10 trials/week to 5,370 trials/week with no marketing. Organic adoption by 19 weekly-active therapists.
- Defense in depth on tenant isolation — acts_as_tenant at the Rails layer, Pundit policies at the controller layer, PostgreSQL RLS at the row layer. Three independent boundaries on every clinical table.
- Domain logic as a typed kernel — Mastery, fading, and assessment rules live in a pure TypeScript module, property-tested with fast-check. Portable to the in-progress Next.js rewrite without rewriting the rules.
- 22,940 trials recorded, zero data loss. 2,418 audit events and 23,447 PaperTrail versions make every clinical mutation traceable.
Stack
| Layer | Technology |
|---|---|
| Framework | Rails 8.1.2 |
| Language | Ruby 3.3.4 |
| Database | PostgreSQL 16 (Neon) |
| Front end | Turbo + Stimulus (Hotwire) |
| Styling | Tailwind CSS |
| Background jobs | Solid Queue |
| Auth | bcrypt + TOTP 2FA + backup codes |
| Authorization | Pundit |
| Multi-tenancy | acts_as_tenant + PostgreSQL RLS |
| Audit | PaperTrail |
| Search | pg_search |
| Bot protection | Cloudflare Turnstile |
| Rate limiting | Upstash Redis |
| Error tracking | Sentry (with PHI filtering) |
| Resend | |
| Security scanning | Brakeman + bundler-audit |
| Style | rubocop-rails-omakase |
| Assets | Propshaft + importmap |
| HTTP | Puma + Thruster |
| Host | Fly.io (EWR, 73 releases) |
A Next.js 16 rewrite is in progress under nextjs/ (Convex, Better Auth,
Drizzle, ElectricSQL, Inngest, Playwright). The Rails app at the repo root
is the system of record in production.