# App Domain Analysis

> Use when the user provides a folder of screenshots from an existing app and wants the backend domain model reverse-engineered, OR when designing a backend for a new app where reference screens exist. Optionally consumes an OpenAPI spec / engineering docs as a secondary signal. Produces a teardown report — domain primitives + temporal invariants + minimal schema + common mistakes — grounded in specific screens and (when available) specific endpoints.

- Skill: `chakshugautam/app-domain-analysis` (Agent Skill, multi-file: 6 files)
- Install (CLI): `npx skillmds@latest add chakshugautam/app-domain-analysis`
- Raw SKILL.md: https://api.skillmd.com/api/skills/chakshugautam/app-domain-analysis/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: AI & ML
- Author: chakshugautam (https://skillmd.com/u/chakshugautam)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/chakshugautam/app-domain-analysis

---


# App Domain Analysis

## Overview

Engineers asked to design the backend for an app typically jump straight to a schema, miss the non-obvious primitives, and discover them only after a painful migration. This skill prevents that by **looking at the app's screens first** to derive the true domain model from observable evidence, then cross-checking against the OpenAPI spec when available.

**Two core principles:**

1. **Screen-grounded, not theory-driven.** Hypotheses come from what the UI actually shows, not from generic domain templates. Every finding cites the specific screen (and endpoint, when available) it derives from.
2. **Hunt the patterns engineers reliably miss.** The patterns table below lists 12 non-obvious design choices — identity-vs-surface, append-only logs as truth, time-versioned config, idempotency, projections, lifecycle states, etc. — each rendered as observable screen-tells AND API-tells. Walk every row; mark `confirmed / contradicted / no-evidence`.

Distilled from two teardowns: Atoms (one-domain habit tracker → `references/habit-tracking.md`) and Bevel (multi-domain health-tracking app → in the `bevel-teardown` repo).

## When to use

- The user provides a folder path of screenshots and asks for a backend / domain model.
- The user is designing a new app where reference screens exist (e.g., "model my app like Whoop").
- The user provides an OpenAPI spec / engineering docs and asks for a teardown.
- Reviewing such a design — use the patterns table as a checklist.

## When NOT to use

- No screens available → use `superpowers:brainstorming` instead.
- User wants frontend / visual-design critique → different skill.
- User wants source-code-level review of an existing repo → different skill (codebase analysis).

## Procedure

```
1. Intake
   - List image files in the provided folder, sorted (numeric prefix preferred).
   - If user names an OpenAPI spec / engineering docs, load them.
   - If no screens → refuse: "This skill is screen-grounded; share a folder of screenshots
     or use brainstorming for idea-only work."

2. Catalog
   a. Screen catalog: for each screen (or near-duplicate cluster), record
      { id, title, primary surface, affordances (buttons / inputs / states),
        language used (verbs + nouns) }.
   b. API catalog (if spec present): for each operation, record
      { method, path, summary, request shape, response shape,
        headers of interest (Idempotency-Key, If-Match, etc.),
        status codes (especially 409 / 422 / 412 / 402) }.

3. Cluster
   - Screens cluster by domain concept (creation flows / detail / lifecycle / settings / pricing).
   - API endpoints cluster by resource and READ-vs-WRITE.
   - Note where the two streams map (a "create habit" screen → POST /habits).

4. Hunt patterns (the table below)
   - Run each row as a hypothesis against BOTH streams.
   - Mark each finding: confirmed-by-screens / confirmed-by-api / corroborated-by-both
     / contradicted / no-evidence.

5. Report (use references/report-template.md)
   - Domain primitives (with evidence citations: "screen 04 + POST /habits body")
   - Temporal invariants
   - Minimal schema (Postgres-flavored)
   - Common mistakes table
   - Open questions (where evidence is missing or contradictory)

6. Validate
   - Surface focused questions citing specific screens or endpoints:
     "Screen 11 shows a confidence slider 1–5 but no corresponding endpoint in
      the spec — is reflection stored server-side or local-only?"
   - Sort question priority:
       1. contradicted rows from step 4
       2. no-evidence rows where the pattern is category-likely
       3. corroborated rows that have ambiguity in detail
```

## The patterns hunt table (the skill's spine)

| # | Pattern | Screen-tell | API-tell | Domain implication |
|---|---|---|---|---|
| 1 | **Identity vs surface noun** | Onboarding asks "who do you want to be?" / display sentences combine fragments / typed-memory store | POST body has `identity`/`intent`/`why` separate from `action`/`title` | First-class identity fields, not one `name` |
| 2 | **Append-only log = truth, counters = cache** | Heatmap, history, "edit a past day" | GET `/x/history`; `backfilled` bool; no PUT on a fact row | Source of truth is the log; counters rebuildable |
| 3 | **Time-versioned configuration** | "Schedule changed" history; per-metric calculation window setting | `/x/versions` sub-resource; `effective_from`/`effective_to` | Close-and-insert a version, not UPDATE |
| 4 | **Idempotent write on natural key** | "Already logged today" toast on retry | `Idempotency-Key` header; 409 on dup POST; UNIQUE hint in responses | UNIQUE `(entity, day)` + ON CONFLICT DO NOTHING |
| 5 | **Projection, not stored future** | Reminders / upcoming view derived from rules | No `POST /reminders`; only `GET` with date range | Worker computes from rules; doesn't persist future rows |
| 6 | **Timezone-local truth** | "Local time" labels; calendar correct after travel | `tz` / `offset` on user; date params (not timestamps) for day-bounded ops | Day = user tz-local date, not server clock |
| 7 | **Lifecycle states with slot impact** | Pause / snooze / "graduated" / archive / activity-status UIs | PATCH state endpoints; 409 on illegal transition; `plan_slots_used` derived | State machine; slot accounting on transitions |
| 8 | **Server-driven content vs user data** | Curated library, "suggestions you might like", feature-flagged greyed items | Read-only catalog endpoints; versioned content blobs | Content versionable + plan-gateable; not user-owned rows |
| 9 | **Plan-gating enforced server-side** | Upsell modal on cap; "upgrade to unlock"; explicit tier feature list | 402/403 on create past cap; `plan` on user; cap field exposed | Cap check in service layer, not just UI |
| 10 | **Ordinal feedback at cadence** | Periodic 1–5 / mood / RPE prompt (not every action) | Reflection endpoint; `prompted_after_n_logs` or similar config | Cadence-gated ordinal stream, trended for "struggling" detection |
| 11 | **Notifications as multi-trigger projection** | Multiple times-of-day per item; multiple alarm types | Reminder endpoints accept array of times; offsets enumerated | Time × offset × scheduled-day, not per-row |
| 12 | **Soft delete with cascade clarity** | "Delete" vs "Archive" distinct in UI; "All recorded data will be saved" warning | DELETE returns 204; archive is a PATCH state | Two operations, two semantics — pick deliberately |

### How the table is used at runtime

1. After cataloging, walk every row.
2. For each pattern, mark `confirmed-by-screens` / `confirmed-by-api` / `corroborated-by-both` / `contradicted` / `no-evidence`.
3. `contradicted` rows → top of the validation question list ("Screens imply X, API implies Y — which is true?").
4. `no-evidence` rows where the pattern is *likely-relevant given the app category* → second tier of validation questions.
5. `corroborated-by-both` rows → top of the report (highest confidence).

The table is the skill's spine. Future teardowns add rows to `references/patterns-catalog.md` (e.g., feed app → "feed ranking is a projection over engagement log"); the SKILL.md table stays as the 10–12 most generalizable.

## Multi-domain apps

When the app spans more than one domain (Atoms = 1, Bevel = 6), add one more step to the procedure between Catalog and Hunt:

**Step 3a — Identify cross-domain dependencies.**

Look for **formulas where one category's score depends on another's**: Bevel's `Sleep Needed = Sleep Goal + Recent Strain + Sleep Debt` is the clearest example — Sleep depends on Strain depends on workout events depends on the sensor pipeline. The presence of a cross-domain formula is the strongest signal that the domains are *projections over shared storage*, not independent silos. The minimal schema must reflect that: shared `sensor_samples` + shared event log + per-domain materialized summaries, not six separate databases.

## Engineering-doc "double click" — what to look for in an OpenAPI spec

When an OpenAPI spec is available, drill into these signals beyond the patterns table:

- `Idempotency-Key` header → idempotent writes (`#4`).
- `ETag`/`If-Match` → optimistic concurrency.
- Cursor vs offset pagination → storage model hints (cursor → time-ordered log).
- 409 on state-transition endpoints → lifecycle truth (`#7`).
- Sub-resource shapes (e.g. `/habits/{id}/schedule-versions`) → time-versioned config (`#3`).
- Nullable/required mix → optionality semantics; required `tz` on user means TZ-local truth.
- Batch endpoints → consistency boundaries.
- `HTTP 402` → plan-gating enforced server-side (`#9`).
- `HTTP 412` → preconditional on aggregate state (e.g. "Need 90 days of data to auto-calc Sleep Goal").
- `oneOf` request bodies on a single endpoint → multi-modal ingestion (e.g. sync vs async meal creation paths).

When a hypothesis from screens contradicts the OpenAPI, **that's the highest-value validation question** to bring to the user.

## References

- `references/habit-tracking.md` — the original Atoms teardown. The worked example for **single-domain identity-tracker apps**. Demonstrates patterns #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12 in one focused domain.
- `references/bevel-multi-domain.md` — a digest of the Bevel teardown's findings. Demonstrates the multi-domain extension (Step 3a above) and patterns #1, #2, #3, #4, #5, #6, #7, #8, #9, #10, #11, #12 across six interacting domains.
- `references/report-template.md` — the canonical output shape for the deliverable.
- `references/patterns-catalog.md` — growable catalog: each new teardown contributes a row mapping its observation to the patterns table.
- `references/openapi-tells.md` — list of API signals + the domain implications they suggest.

## Red flags — stop and reconsider

- The skill produced a domain model without citing any specific screens → the procedure was skipped.
- All findings are "no-evidence" → you haven't actually catalogued; restart at step 2.
- The schema has 1–2 entities and no event logs → you're modeling the UI, not the domain. Patterns #2 and #5 are not being applied.
- No `Open Questions` section in the report → either the app is impossibly simple or you're glossing over contradictions.
- Cross-domain dependencies aren't called out in a multi-domain app → step 3a was skipped.

