Same tools. Same content. Different decisions. Each principle below appears twice — once wrong, once right. The difference is never the tooling. It's the judgment applied before the first parameter is set.
The terms below — scheme, palette, semantic role — are defined in the chromatic language. One scheme per section. Max two schemes per page. Semantic roles (danger, success) are free — they carry meaning, not decoration. When every card has a hand-picked color, the reader sees variety and wonders what it means. It means nothing.
❌ Anti-pattern: Rainbow Circus — Four cards about billing processes. Each gets a hand-picked color. The palette is technically valid but communicates nothing. The reader's eye bounces between hues looking for a pattern that isn't there.
Plan selection, checkout, provisioning.
Feature flags, access control.
Consumption tracking, aggregation.
Billing runs, PDF rendering.
✅ Correct: Scheme Auto-Assign — Same four cards. One scheme parameter. The palette is harmonious because it was designed to be. The reader sees a cohesive group — four parts of one system, not four unrelated items.
Plan selection, checkout, provisioning.
Feature flags, access control.
Consumption tracking, aggregation.
Billing runs, PDF rendering.
Visual weight signals importance. If everything is the same size, nothing is primary. The reader's eye has no entry point — it scans randomly and gives up.
❌ Anti-pattern: Democracy — Four equal columns. The happy path (94% of traffic) gets the same visual weight as monitoring (background noise). The reader must scan all four to find what matters.
Customer selects plan → checkout → provisioned. 94% of all subscriptions.
Mid-cycle plan change. Prorated credit, new entitlements sync.
Card declined → dunning cycle. 3 retries over 14 days.
Health dashboard. Latency p99, error rates, queue depth.
✅ Correct: Weight Matches Importance — The happy path gets half the row because it is the dominant case. Edge cases share the remainder. The reader's eye goes where it should — to the thing that matters most.
Customer selects plan → checkout → provisioned. This is 94% of all subscriptions. Everything else on this page is an exception to this flow.
Mid-cycle plan change with prorated credit.
Card declined → dunning (3 retries, 14 days).
Every element must earn its place. The test: remove it. Does the reader lose anything? If two elements say the same thing, one is noise. Three is contempt for the reader's time.
❌ Anti-pattern: Belt and Suspenders — An info box states the lifecycle. A flow chain shows the lifecycle. Cards describe the lifecycle. The reader sees the same four words in three formats and wonders which one to trust.
Customer initiates a subscription through checkout.
Entitlements sync to the zone.
Service begins. Metering starts.
Invoice generated at cycle end.
✅ Correct: Each Element Does One Job — The flow chain carries the summary (sequence and direction). The cards carry the depth (what actually happens at each stage). No info box restating what's already visible twice.
Checkout validates payment, applies coupons, writes the subscription record. Provisioning begins asynchronously — the customer sees confirmation before entitlements exist.
Entitlement sync delivers feature flags to the zone. Activation is automatic on sync completion. Metering starts on activation, not on creation.
Billing run aggregates metered usage, applies rate cards, generates the invoice. Failed charges enter dunning — a separate lifecycle entirely.
Cards are for concepts that need visual separation and parallel comparison. If the content is a flat list of names, use a table. Cards promise depth — if they don't deliver, the format is lying.
❌ Anti-pattern: Anemic Cards — Five cards, each with a title and two words. This is a table wearing a disguise. The visual weight is wrong — cards promise depth and deliver nothing. The reader processes five boxes to learn what a five-row table would convey in a glance.
New subscription
Get details
Modify plan
Cancel subscription
Query subscriptions
✅ Correct: Table for Reference, Cards for Concepts — The CRUD endpoints are reference data — they belong in a table. Cards are reserved for the architectural decisions that actually need visual weight and parallel comparison.
| Endpoint | Method | Description | Auth |
|---|---|---|---|
/subscriptions | POST | Create a new subscription | Bearer token |
/subscriptions/:id | GET | Retrieve subscription details | Bearer token |
/subscriptions/:id | PATCH | Modify plan or quantity | Bearer token |
/subscriptions/:id | DELETE | Cancel (soft delete) | Bearer token |
/subscriptions | GET | List with filters and pagination | Bearer token |
Subscriptions carry financial history — invoices, payments, credits. Hard delete would orphan those records. Soft delete preserves the audit trail while removing the subscription from active queries. Reactivation within 30 days restores the original subscription ID.
Bulk plan changes require coordinated provisioning — each subscription's entitlements must sync independently. A collection PATCH would hide N async operations behind one synchronous response. Instead, clients issue individual PATCHes and track provisioning status per subscription.
Flow chains show temporal sequence — step A happens before step B. The arrows mean then. If the items aren't sequential, the arrows lie. A reader who trusts the arrows will build a wrong mental model.
❌ Anti-pattern: Topology as Sequence — These are system components, not a process. The dashboard doesn't "lead to" the API. The worker doesn't "become" a database. The arrows imply temporal ordering that doesn't exist.
✅ Correct: Actual Temporal Sequence — Each step happens after the previous one. A reader can trace the flow left to right and understand the order of operations. The arrows earn their meaning.
Every format has a natural content type. Cards compare concepts side by side. Tables organize reference data. Flow chains show sequences. Mismatching format and content creates friction — the reader fights the layout to extract meaning.
❌ Anti-pattern: Cards for Everything — Six API endpoints in six cards across two rows. No card has more content than its neighbor. No card needs visual separation from the others. This is a table forced into card format — all weight, no information density.
List all zones
Create a zone
Zone details
Update settings
Delete a zone
List DNS records
✅ Correct: Table for Reference, Cards for Decisions — The six endpoints go in a table where a reader can scan them in seconds. Cards are reserved for the two design decisions that actually benefit from visual weight and side-by-side comparison.
| Endpoint | Method | Description | Rate Limit |
|---|---|---|---|
/zones | GET | List all zones for the account | 1000 / 5min |
/zones | POST | Create a new zone | 5 / min |
/zones/:id | GET | Get zone details and settings | 1000 / 5min |
/zones/:id | PATCH | Update zone settings | 200 / 5min |
/zones/:id | DELETE | Permanently delete a zone | 5 / min |
/zones/:id/dns | GET | List DNS records for a zone | 1000 / 5min |
Zone creation triggers nameserver assignment — a globally distributed operation that takes 5-30 minutes to propagate. Allowing burst creation would queue thousands of NS assignments, degrading propagation time for everyone. The 5/min limit matches the operational reality.
Zone deletion stops DNS resolution immediately. A bulk endpoint deleting 100 zones in one call would be indistinguishable from an account compromise. Single-zone deletion with rate limiting gives operators time to notice and intervene. The friction is the feature.
Every anti-pattern above was produced by the same tools that produce the correct versions. Tools don't prevent bad design — principles do. If you can't articulate why a card exists instead of a table row, the card shouldn't exist.