Architecture Overview
System layout, the request/response shape, and where each concern lives
Loop is a Next.js web app backed by a database, with two outbound integrations (Slack and the Anthropic API) and one browser-only integration (Web Speech API). Managers use the dashboard in a browser; employees follow a Slack DM link to a per-reminder page.
The visual map is on System diagram. The sketch below is the same shape in text.
High-level diagram
+----------------------+
| Manager browser |
| (dashboard, send |
| form, voice input) |
+----------+-----------+
|
| HTTPS
v
+-----------------+ +----------------------+ +-----------------+
| Database |<->| Web app |-->| Anthropic API |
| (employees, | | (Next.js, server | | (AI note |
| processes, | | routes + UI) | | writer) |
| reminders) | +----------+-----------+ +-----------------+
+-----------------+ |
| Slack Web API (chat.postMessage)
v
+---------------+
| Slack DM |
| to employee |
+-------+-------+
|
| DM contains link to
| /reminder/[id]
v
+-------------------+
| Employee browser |
| /reminder/[id] |
| (read, optional |
| feedback, ack) |
+-------------------+The browser also opens the SOP url from the linked process — that link goes directly to whichever external tool hosts the SOP (Trainual, Notion, Google Docs, etc.) and does not pass through the Loop server.
Where each integration runs
- Slack — server-side only. The brief states "Slack API calls must be server-side. Token never exposed to browser." The bot token is held by the server; the web app calls Slack from a server route after persisting the reminder.
- Anthropic Claude API — server-side. The brief lists the Anthropic API key as "server-side recommended" and the Slack token as server-side only; the AI note writer endpoint should run on the server so the key never reaches the browser.
- Web Speech API (
SpeechRecognition) — browser-only. Voice-to-text runs in the manager's browser on the note field (and on the AI note writer's input field). Tap to start, tap to stop, transcript populates the field. There is no server component for voice.
Request/response shape
Two write paths drive the system:
- Send a reminder (manager) — browser POSTs the form (employee, process, type, note, priority for corrections) to a server route. The server inserts the row in
reminders, then calls Slackchat.postMessagewith the manager note, process name + source, the SOP link, and a link to/reminder/[id]. Recognitions follow the same path; corrections start withstatus = 'pending'. - Acknowledge a correction (employee) — browser POSTs from
/reminder/[id]with optionalemployee_feedback. The server updates the row:status = 'acknowledged',acknowledged_at = now(),employee_feedback = <text or null>. Recognitions do not require this step — they are "logged but no action required".
Read paths (dashboard, employee profile, process detail, reminder detail) are straightforward queries against the three tables, with the derived counts described in the Derived Queries page.
Auth model
The brief specifies "Basic auth (manager vs employee role distinction)". There are two roles, gated by the is_manager boolean on employees:
- Manager (
is_manager = true) — has access to the dashboard, send form, reminder detail, employee profile, and process list/detail. - Employee (
is_manager = false) — has access to their own inbox and to/reminder/[id]pages reached from a Slack DM link.
The brief does not specify the auth mechanism beyond "basic auth" and explicitly lists "SSO or OAuth" under "Not required for v1", so the implementation choice (session cookie, simple credentials, magic link, etc.) is open. User registration / self-service onboarding is also out of scope, which means the user list is seeded rather than self-served.
Multi-tenancy
The brief flags multi-tenancy under "Keep in mind for later":
Multi-tenancy — don't hardcode single team. Use org-level scoping where practical.
For v1 this means: do not hardcode a single team's identifier into queries, fixtures, or environment assumptions. Where it is cheap to add an org-scoping column or filter (for example on employees, processes, and reminders, and on every query that lists or aggregates them), do so. Where it would be expensive or speculative, leave a clear seam rather than building a full tenancy layer now. The brief does not prescribe the exact shape of the org boundary, so the schema choice (org id column vs. separate schema vs. row-level security) is left open.