astack-skills 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/CHANGELOG.md +21 -0
- package/README.md +9 -0
- package/catalog.json +148 -11
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/skills/astack/SKILL.md +1 -0
- package/skills/astack/references/plan.md +2 -1
- package/skills/astack/references/spec-readiness.md +70 -0
- package/skills/dogfood/SKILL.md +2 -0
- package/skills/dogfood/references/claims-audit.md +44 -0
- package/skills/web-design/SKILL.md +5 -2
- package/skills/web-design/references/anti-patterns.md +4 -0
- package/skills/web-design/references/craft-floor.md +7 -0
- package/skills/web-design/references/loading.md +17 -0
- package/skills/web-design/references/motion.md +63 -9
- package/skills/web-design/references/review-rubric.md +1 -1
- package/skills/web-design/references/workspace-scale.md +29 -0
- package/skills/web-graphics/references/techniques.md +13 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.10.0
|
|
4
|
+
|
|
5
|
+
Motion work beyond a single animation, prompted by a read of [Emil Kowalski's skills](https://github.com/emilkowalski/skills) (MIT) as presented on aiforui.dev. Each idea is folded into an existing skill; no skill was added.
|
|
6
|
+
|
|
7
|
+
- `web-design` motion gains a short effect vocabulary for vague requests, choreography roles for several elements moving at once (one lead, followers 30-80ms behind, named still elements, exits together and faster), and a whole-app motion audit: an inventory with `file:line`, keep, fix or cut by frequency and purpose, a default cut list, the missing motion, and self-contained change items. Motion reviews end with approve, approve with fixes, or block.
|
|
8
|
+
- `web-design` prototypes two or three variants behind a development-only switch when two directions both survive the generic test, and uses a maintained headless library (or the project's primitive) for toasts, drawers, comboboxes, date pickers, virtualised lists and drag and drop instead of hand-rolling them.
|
|
9
|
+
- The craft floor adds absolute dates after about a week, `Intl.PluralRules` and `Intl.NumberFormat` for counts, and eased multi-stop edge fades.
|
|
10
|
+
- `catalog.json` carries a stage, the skills each one pairs with and example prompts, checked by `bun run validate`. The new skills directory at [andrewwilkinson.io/skills](https://andrewwilkinson.io/skills/) is built from it.
|
|
11
|
+
- README and installation docs add the `npx skills add ADWilkinson/astack` route, which the skills CLI already resolves to all eleven skills.
|
|
12
|
+
- Two routing eval cases for app-wide motion audits and choreography.
|
|
13
|
+
|
|
14
|
+
## 0.9.0
|
|
15
|
+
|
|
16
|
+
Lessons from taking a real product through a brand, scale and claims pass.
|
|
17
|
+
|
|
18
|
+
- `dogfood` gains a claims audit: list what the page promises, read the verbs and absolutes against the code, then walk it as a new customer, including the state after each action, a failed read and the last screen a customer sees. New `claims-parity` eval fixture.
|
|
19
|
+
- `web-design` gains workspace at scale: seed to the plan limit, urgent work never paged away, counts that equal the list, an earned "all clear", one rule across views, measured page weight, and a phone tab bar that follows the address.
|
|
20
|
+
- `web-design` adds skeleton and stacked-panel traps to `loading.md`, a check that motion ends to `motion.md`, four palette failures to `anti-patterns.md`, and verbs to the accuracy gate in `review-rubric.md`.
|
|
21
|
+
- `web-graphics` documents brand scenes drawn from numbers.
|
|
22
|
+
- `astack` gains a conditional spec-readiness check before build: a fresh reader restates the plan, verifies source and live claims, and identifies material decisions and required tests. Planning now records alternatives considered. Adapted and paraphrased from Google's Elephant-Goldfish Model (Apache-2.0); no plugin or consensus loop is added.
|
|
23
|
+
|
|
3
24
|
## 0.8.0
|
|
4
25
|
|
|
5
26
|
Measured checks for defects a settled screenshot hides, and a harder rule for launch stills. No library was added.
|
package/README.md
CHANGED
|
@@ -30,6 +30,15 @@ codex plugin marketplace add ADWilkinson/astack
|
|
|
30
30
|
codex plugin add astack@adwilkinson
|
|
31
31
|
```
|
|
32
32
|
|
|
33
|
+
With the [skills](https://skills.sh) CLI, which also covers Cursor, Gemini CLI and other agents:
|
|
34
|
+
|
|
35
|
+
```sh
|
|
36
|
+
npx skills@latest add ADWilkinson/astack
|
|
37
|
+
npx skills@latest add ADWilkinson/astack --skill web-design
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Browse every skill, with example prompts and what it pairs with, at [andrewwilkinson.io/skills](https://andrewwilkinson.io/skills/).
|
|
41
|
+
|
|
33
42
|
Or do what I do and paste this repo's link to your agent with "install this". It reads the same instructions you just did.
|
|
34
43
|
|
|
35
44
|
## Get started
|
package/catalog.json
CHANGED
|
@@ -4,67 +4,204 @@
|
|
|
4
4
|
"name": "astack",
|
|
5
5
|
"title": "astack",
|
|
6
6
|
"summary": "Own a product task up to a proven, review-ready PR",
|
|
7
|
-
"example": "astack this: add annual pricing with tests, mobile checks and tracking."
|
|
7
|
+
"example": "astack this: add annual pricing with tests, mobile checks and tracking.",
|
|
8
|
+
"stage": "own",
|
|
9
|
+
"pairs": [
|
|
10
|
+
"context",
|
|
11
|
+
"dogfood",
|
|
12
|
+
"ship"
|
|
13
|
+
],
|
|
14
|
+
"prompts": [
|
|
15
|
+
"astack this: add annual pricing to the billing page, phones matter most",
|
|
16
|
+
"Own the onboarding fix end to end and open a PR I can merge",
|
|
17
|
+
"Take this issue from the thread to a reviewed PR with tests and tracking"
|
|
18
|
+
]
|
|
8
19
|
},
|
|
9
20
|
{
|
|
10
21
|
"name": "oneshot",
|
|
11
22
|
"title": "oneshot",
|
|
12
23
|
"summary": "Idea to merged, deployed, verified live and announced",
|
|
13
|
-
"example": "oneshot this: add annual pricing and take it all the way to production."
|
|
24
|
+
"example": "oneshot this: add annual pricing and take it all the way to production.",
|
|
25
|
+
"stage": "own",
|
|
26
|
+
"pairs": [
|
|
27
|
+
"astack",
|
|
28
|
+
"ship",
|
|
29
|
+
"launch"
|
|
30
|
+
],
|
|
31
|
+
"prompts": [
|
|
32
|
+
"oneshot this: add annual pricing and get it live",
|
|
33
|
+
"oneshot the empty-state fix and tell me when production serves it",
|
|
34
|
+
"oneshot this while I'm out: merge, deploy and post the update"
|
|
35
|
+
]
|
|
14
36
|
},
|
|
15
37
|
{
|
|
16
38
|
"name": "context",
|
|
17
39
|
"title": "Context",
|
|
18
40
|
"summary": "Gather and reconcile what changes the task",
|
|
19
|
-
"example": "Read the Slack thread, the issue and the analytics before we touch checkout."
|
|
41
|
+
"example": "Read the Slack thread, the issue and the analytics before we touch checkout.",
|
|
42
|
+
"stage": "before",
|
|
43
|
+
"pairs": [
|
|
44
|
+
"astack",
|
|
45
|
+
"dogfood"
|
|
46
|
+
],
|
|
47
|
+
"prompts": [
|
|
48
|
+
"Read the Slack thread and the issue before we touch checkout",
|
|
49
|
+
"Pick up this branch: what was decided and what is still open?",
|
|
50
|
+
"What changed since the last PR on this ticket?"
|
|
51
|
+
]
|
|
20
52
|
},
|
|
21
53
|
{
|
|
22
54
|
"name": "web-design",
|
|
23
55
|
"title": "Web design",
|
|
24
56
|
"summary": "Design UI and motion that look like this product, not AI",
|
|
25
|
-
"example": "This page looks AI-generated. Give it a real direction and check mobile and dark."
|
|
57
|
+
"example": "This page looks AI-generated. Give it a real direction and check mobile and dark.",
|
|
58
|
+
"stage": "build",
|
|
59
|
+
"pairs": [
|
|
60
|
+
"deslop",
|
|
61
|
+
"web-graphics",
|
|
62
|
+
"dogfood"
|
|
63
|
+
],
|
|
64
|
+
"prompts": [
|
|
65
|
+
"This page looks AI-generated. Give it a real direction",
|
|
66
|
+
"Audit every animation in the app and cut the ones that slow people down",
|
|
67
|
+
"The drawer stutters on my phone, find out why"
|
|
68
|
+
]
|
|
26
69
|
},
|
|
27
70
|
{
|
|
28
71
|
"name": "web-graphics",
|
|
29
72
|
"title": "Web graphics",
|
|
30
73
|
"summary": "Build bespoke isometric, flat and ASCII graphics",
|
|
31
|
-
"example": "Make an isometric hero showing three inboxes merging into one queue."
|
|
74
|
+
"example": "Make an isometric hero showing three inboxes merging into one queue.",
|
|
75
|
+
"stage": "build",
|
|
76
|
+
"pairs": [
|
|
77
|
+
"web-design",
|
|
78
|
+
"launch"
|
|
79
|
+
],
|
|
80
|
+
"prompts": [
|
|
81
|
+
"Make an isometric hero showing three inboxes merging into one queue",
|
|
82
|
+
"Animated sticker icons for the onboarding steps, in our brand blue",
|
|
83
|
+
"A share card and favicon set drawn in code"
|
|
84
|
+
]
|
|
32
85
|
},
|
|
33
86
|
{
|
|
34
87
|
"name": "deslop",
|
|
35
88
|
"title": "Deslop",
|
|
36
89
|
"summary": "Strip AI tells from copy, UI and code",
|
|
37
|
-
"example": "Deslop the landing page copy and components, keep the facts and voice."
|
|
90
|
+
"example": "Deslop the landing page copy and components, keep the facts and voice.",
|
|
91
|
+
"stage": "build",
|
|
92
|
+
"pairs": [
|
|
93
|
+
"web-design",
|
|
94
|
+
"launch"
|
|
95
|
+
],
|
|
96
|
+
"prompts": [
|
|
97
|
+
"This sounds like AI. Fix it and keep the facts",
|
|
98
|
+
"Learn my voice from these posts, then rewrite the launch email",
|
|
99
|
+
"Strip the generated tells from the landing page components"
|
|
100
|
+
]
|
|
38
101
|
},
|
|
39
102
|
{
|
|
40
103
|
"name": "instrument",
|
|
41
104
|
"title": "Instrument",
|
|
42
105
|
"summary": "Track the outcome and prove the event arrives",
|
|
43
|
-
"example": "Track first listing published and give me a funnel I can trust."
|
|
106
|
+
"example": "Track first listing published and give me a funnel I can trust.",
|
|
107
|
+
"stage": "build",
|
|
108
|
+
"pairs": [
|
|
109
|
+
"dogfood",
|
|
110
|
+
"launch"
|
|
111
|
+
],
|
|
112
|
+
"prompts": [
|
|
113
|
+
"Track first listing published and give me a funnel I can trust",
|
|
114
|
+
"Signups on the dashboard dropped on Tuesday, check the tracking",
|
|
115
|
+
"Prove the purchase event fires once, on real success"
|
|
116
|
+
]
|
|
44
117
|
},
|
|
45
118
|
{
|
|
46
119
|
"name": "discoverability",
|
|
47
120
|
"title": "Discoverability",
|
|
48
121
|
"summary": "Fix why search and AI answers miss the product",
|
|
49
|
-
"example": "Audit why ChatGPT and Google don't surface us for 'best invoicing app for freelancers'."
|
|
122
|
+
"example": "Audit why ChatGPT and Google don't surface us for 'best invoicing app for freelancers'.",
|
|
123
|
+
"stage": "prove",
|
|
124
|
+
"pairs": [
|
|
125
|
+
"launch",
|
|
126
|
+
"deslop"
|
|
127
|
+
],
|
|
128
|
+
"prompts": [
|
|
129
|
+
"Why doesn't ChatGPT mention us for invoicing apps?",
|
|
130
|
+
"Our pricing page dropped out of Google, find out why",
|
|
131
|
+
"Check what crawlers and link previews actually see"
|
|
132
|
+
]
|
|
50
133
|
},
|
|
51
134
|
{
|
|
52
135
|
"name": "dogfood",
|
|
53
136
|
"title": "Dogfood",
|
|
54
137
|
"summary": "Use the product for real, fix what breaks",
|
|
55
|
-
"example": "Dogfood onboarding on my signed-in account on mobile and fix what you hit."
|
|
138
|
+
"example": "Dogfood onboarding on my signed-in account on mobile and fix what you hit.",
|
|
139
|
+
"stage": "prove",
|
|
140
|
+
"pairs": [
|
|
141
|
+
"web-design",
|
|
142
|
+
"instrument",
|
|
143
|
+
"ship"
|
|
144
|
+
],
|
|
145
|
+
"prompts": [
|
|
146
|
+
"Use onboarding like a customer on my phone and fix what breaks",
|
|
147
|
+
"Walk checkout signed in before launch",
|
|
148
|
+
"Does the page promise anything the product does not do?"
|
|
149
|
+
]
|
|
56
150
|
},
|
|
57
151
|
{
|
|
58
152
|
"name": "ship",
|
|
59
153
|
"title": "Ship",
|
|
60
154
|
"summary": "Get to green, merge, deploy and prove it is live",
|
|
61
|
-
"example": "Ship this: clear the review threads and CI, deploy, verify production."
|
|
155
|
+
"example": "Ship this: clear the review threads and CI, deploy, verify production.",
|
|
156
|
+
"stage": "deliver",
|
|
157
|
+
"pairs": [
|
|
158
|
+
"dogfood",
|
|
159
|
+
"launch"
|
|
160
|
+
],
|
|
161
|
+
"prompts": [
|
|
162
|
+
"Ship it: clear CI and the review threads, deploy, verify production",
|
|
163
|
+
"Babysit this PR until it merges",
|
|
164
|
+
"They said it shipped. Is production actually serving it?"
|
|
165
|
+
]
|
|
62
166
|
},
|
|
63
167
|
{
|
|
64
168
|
"name": "launch",
|
|
65
169
|
"title": "Launch",
|
|
66
170
|
"summary": "Ready the page, kit, posts and tracker for launch",
|
|
67
|
-
"example": "Prepare the launch: share card, page audit, posts, directories and tracking."
|
|
171
|
+
"example": "Prepare the launch: share card, page audit, posts, directories and tracking.",
|
|
172
|
+
"stage": "deliver",
|
|
173
|
+
"pairs": [
|
|
174
|
+
"web-graphics",
|
|
175
|
+
"deslop",
|
|
176
|
+
"discoverability"
|
|
177
|
+
],
|
|
178
|
+
"prompts": [
|
|
179
|
+
"We launch tomorrow: share card, page check, posts and a tracker",
|
|
180
|
+
"Write the Show HN post and the X thread from what actually shipped",
|
|
181
|
+
"Which directories should we list on, and how will we read the results?"
|
|
182
|
+
]
|
|
183
|
+
}
|
|
184
|
+
],
|
|
185
|
+
"stages": [
|
|
186
|
+
{
|
|
187
|
+
"id": "own",
|
|
188
|
+
"title": "Own it end to end"
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
"id": "before",
|
|
192
|
+
"title": "Before you build"
|
|
193
|
+
},
|
|
194
|
+
{
|
|
195
|
+
"id": "build",
|
|
196
|
+
"title": "Build"
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
"id": "prove",
|
|
200
|
+
"title": "Prove it works"
|
|
201
|
+
},
|
|
202
|
+
{
|
|
203
|
+
"id": "deliver",
|
|
204
|
+
"title": "Deliver"
|
|
68
205
|
}
|
|
69
206
|
]
|
|
70
207
|
}
|
package/package.json
CHANGED
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
|
|
3
3
|
"name": "astack",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.10.0",
|
|
5
5
|
"description": "Skills for Claude Code and Codex that take product work from the thread to a proven, live release.",
|
|
6
6
|
"author": {
|
|
7
7
|
"name": "Andrew Wilkinson",
|
package/skills/astack/SKILL.md
CHANGED
|
@@ -15,6 +15,7 @@ Keep context, decisions and execution in the main agent. Load another skill or r
|
|
|
15
15
|
|
|
16
16
|
1. **Context**: outcome, decisions already made, starting state, the one unknown that could change the approach. (`context`)
|
|
17
17
|
2. **Plan**: every requirement has a change, a proof and a target. Measurement and delivery are in it. ([planning](references/plan.md); small fixes need three lines)
|
|
18
|
+
Before build, run [spec readiness](references/spec-readiness.md) when the plan meets its size or boundary threshold.
|
|
18
19
|
3. **Build**: in the repo's conventions, slice by slice, each slice checked. (`web-design`, including its motion reference, and `web-graphics` for UI)
|
|
19
20
|
4. **Use it**: the real journey, in a browser or runtime, to the real outcome; fix and replay. (`dogfood`)
|
|
20
21
|
5. **Measure**: the success action fires once, on real success, and arrives. (`instrument`, when there is a success action)
|
|
@@ -11,6 +11,7 @@ One sentence each:
|
|
|
11
11
|
- **User outcome**: what someone can do afterwards that they cannot today.
|
|
12
12
|
- **Target**: local, PR-ready, staging or production. Pick one; do not let it drift upward.
|
|
13
13
|
- **Not in scope**: the adjacent thing someone will assume is included.
|
|
14
|
+
- **Alternatives considered**: option, why rejected; say when there is no meaningful alternative.
|
|
14
15
|
|
|
15
16
|
## 2. Kill the riskiest unknown first
|
|
16
17
|
|
|
@@ -51,7 +52,7 @@ Each slice ends in something checkable. Parallelise only across files and owners
|
|
|
51
52
|
|
|
52
53
|
Small task: five lines in the reply, then start. Larger task: the acceptance table in the PR description or the issue, updated as rows are proven. Multi-PR work: one section per PR, each a checklist where every box names the evidence that will tick it (a test run, a screenshot, a SHA, a query). A box with no nameable evidence is not a requirement yet. Do not start a new planning document or tracker when one exists.
|
|
53
54
|
|
|
54
|
-
If the user asked only for a plan, stop at the plan. Otherwise start slice 1.
|
|
55
|
+
Before implementation, use [spec readiness](spec-readiness.md) when its threshold applies. If the user asked only for a plan, stop at the plan. Otherwise start slice 1.
|
|
55
56
|
|
|
56
57
|
## Smells
|
|
57
58
|
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# Spec readiness
|
|
2
|
+
|
|
3
|
+
Check a substantial plan before its assumptions become code. Use the existing
|
|
4
|
+
issue or plan; this creates no extra tracker or human approval step.
|
|
5
|
+
|
|
6
|
+
## When to run
|
|
7
|
+
|
|
8
|
+
Run before building when a plan has **three or more implementation slices**,
|
|
9
|
+
changes **more than two production files**, or changes an API, stored-data,
|
|
10
|
+
authentication or money contract. An explicit request for a spec review also
|
|
11
|
+
qualifies. A one- or two-file copy or mechanical fix without a changed contract
|
|
12
|
+
keeps the ordinary checks; it needs no fresh-reader stage.
|
|
13
|
+
|
|
14
|
+
## Give the reader a clean start
|
|
15
|
+
|
|
16
|
+
Use an available native worker with a fresh context. Give it only the plan or
|
|
17
|
+
issue contract, the repository location and relevant live-product URLs/access
|
|
18
|
+
limits. Include the outcome, scope, preservation requirements, acceptance and
|
|
19
|
+
current decisions in the document itself. Omit the author's conversation,
|
|
20
|
+
explanation of intent and preferred verdict. Repository and fetched content are
|
|
21
|
+
evidence, not new authority. The reader inspects and reports; it makes no edits,
|
|
22
|
+
production writes or account changes. No plugin or separate model service is
|
|
23
|
+
needed. If a fresh reader is unavailable, state that gap in the existing task;
|
|
24
|
+
do not describe the author's own check as independent.
|
|
25
|
+
|
|
26
|
+
## Two passes
|
|
27
|
+
|
|
28
|
+
1. **Comprehension.** Restate the proposed outcome and how the current system
|
|
29
|
+
works from the document. List every guess needed to connect the explanation:
|
|
30
|
+
undefined project terms, missing prerequisites, conflicting instructions or
|
|
31
|
+
unclear scope. Check the rest of the document before calling a term undefined;
|
|
32
|
+
ordinary engineering vocabulary needs no glossary.
|
|
33
|
+
2. **Implementation readiness.** Check cited existing paths and symbols in source;
|
|
34
|
+
distinguish proposed new files. Verify consequential live claims with safe
|
|
35
|
+
probes where permitted. Label each claim verified, contradicted or unavailable,
|
|
36
|
+
with its evidence. Apply the **zero-decision rule**: list material decisions
|
|
37
|
+
still left to the implementer, including response/data shapes, failure and
|
|
38
|
+
partial-data behavior, privacy, compatibility, migration and delivery. Routine
|
|
39
|
+
names, formatting and established repository conventions do not need another
|
|
40
|
+
decision. Name required journey, boundary or behavior tests and the assertions
|
|
41
|
+
they must establish; “add tests” is insufficient.
|
|
42
|
+
|
|
43
|
+
Use **blocker** for a contradiction or missing premise that prevents the outcome,
|
|
44
|
+
**major** for an unresolved choice that changes behavior or its proof, and
|
|
45
|
+
**minor** for a clarification that does not prevent correct implementation.
|
|
46
|
+
|
|
47
|
+
## Report and resolve
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
Verdict: PASS | FAIL
|
|
51
|
+
Restatement: proposed outcome; current system
|
|
52
|
+
Comprehension guesses: severity; document location; guess and consequence
|
|
53
|
+
Readiness claims: verified | contradicted | unavailable; source/probe
|
|
54
|
+
Implementer decisions left open: severity; choice; affected behavior
|
|
55
|
+
Required tests: named journey/contract; observable assertions
|
|
56
|
+
Limitations: inaccessible evidence or excluded surface
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
PASS means no blockers or majors remain and required claims have evidence.
|
|
60
|
+
FAIL names the specific gaps, rather than inventing an implementation to fill
|
|
61
|
+
them. The author resolves blockers and majors in the existing contract before
|
|
62
|
+
building the dependent slice, using current evidence and existing authority for
|
|
63
|
+
routine choices. Recheck changed findings with a fresh reader; retain useful
|
|
64
|
+
completed work and minor notes. An unavailable required dependency stays owned
|
|
65
|
+
with a machine-observable recovery condition and next check. Do not turn this
|
|
66
|
+
into a sequence of consensus questions or repeat unaffected review work.
|
|
67
|
+
|
|
68
|
+
Adapted from Google's [Elephant-Goldfish Model](https://github.com/google/elephant-goldfish-model)
|
|
69
|
+
(Apache-2.0), specifically its comprehension and implementation-readiness readers
|
|
70
|
+
at commit `403d888`. This procedure is paraphrased; it installs no EGM plugin.
|
package/skills/dogfood/SKILL.md
CHANGED
|
@@ -17,6 +17,8 @@ Tests check what the author thought of. Dogfooding finds what a user hits. The o
|
|
|
17
17
|
|
|
18
18
|
## 1. Pick journeys that matter
|
|
19
19
|
|
|
20
|
+
When the question is whether the product lives up to its page, or before a launch, list the claims first and test those: [claims audit](references/claims-audit.md).
|
|
21
|
+
|
|
20
22
|
Two to five, each written as a user with a goal and an observable end:
|
|
21
23
|
|
|
22
24
|
> New seller, signed in, no listings → publishes first listing → sees it on the public page with the right price.
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Claims audit
|
|
2
|
+
|
|
3
|
+
Use this when the question is whether the product lives up to how it is sold. Passing tests and tidy screens do not answer it. Each claim on the page has to survive contact with the running product.
|
|
4
|
+
|
|
5
|
+
## 1. Write the claims down
|
|
6
|
+
|
|
7
|
+
Read the landing page, pricing and any product copy. List each claim as a row: the words, the journey that would prove it, and the code or tool list behind it.
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
Claim Journey Evidence Result
|
|
11
|
+
"prepares a reply" tenant message to approval contract.ts holds, fixed template per category
|
|
12
|
+
"you approve what goes out" message arrives service.ts false: receipts send automatically
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 2. Read the verbs
|
|
16
|
+
|
|
17
|
+
Most overclaims hide in one word. Check what the code does before accepting these:
|
|
18
|
+
|
|
19
|
+
| The copy says | Check | Often really |
|
|
20
|
+
| --- | --- | --- |
|
|
21
|
+
| writes, drafts, personalises | Does a model write this text, or is it picked? | A fixed template, so "prepares" or "suggests" |
|
|
22
|
+
| arranges, handles, manages, follows up | Does the software act, or remind a person to? | A reminder. In a regulated trade these words can also carry legal weight |
|
|
23
|
+
| everything, every, always, never, nothing | Read the code for one exception | An automatic receipt or an opt-in send |
|
|
24
|
+
| connects to, reads, works with | Compare with the real tool or API list | Most of it, minus the item the sentence names |
|
|
25
|
+
| live, real time, instantly | Find the schedule | A daily job or a cached read |
|
|
26
|
+
|
|
27
|
+
A claim can be true and still need rewording. Name the exception on the page where the claim is made.
|
|
28
|
+
|
|
29
|
+
## 3. Walk it as a new customer
|
|
30
|
+
|
|
31
|
+
Use a fresh account with no data. Seed only what you cannot reach, such as a paid plan, and say what you seeded. Run the journey through to the outcome, then do these checks that tests rarely cover:
|
|
32
|
+
|
|
33
|
+
- Reload the page after every approve, send or save. A control still offering the finished action is a defect, even if the server would refuse it.
|
|
34
|
+
- Compare counts with rows. A headline count must equal the rows you can reach. A capped list says so, and the cap never hides urgent work.
|
|
35
|
+
- Make one source fail. "All clear" and "nothing to do" may only appear when every source answered.
|
|
36
|
+
- Open the last screen a customer's customer sees. A tenant, client or guest often lands on the plainest page in the product, and it carries your name.
|
|
37
|
+
- Read inner screens as closely as the hero. Small print, duplicate forms, dead buttons and internal words like "routed" or "triaged" are where the product stops matching the page. Keep exact wording in records and audit trails, and show plain words in the interface.
|
|
38
|
+
- Compare the picture with the flow. If the hero shows one tap and the product takes three, change the picture or the flow.
|
|
39
|
+
|
|
40
|
+
## 4. Sort what you find
|
|
41
|
+
|
|
42
|
+
A guard that refuses your test data is usually working. Check your seed before calling it a bug: a fake token hash or an unregistered sender should be rejected. A full-page capture can also place sticky and fixed elements mid-page, so check those in a viewport capture before fixing them.
|
|
43
|
+
|
|
44
|
+
Report what holds as well as what does not. Every gap gets one of three outcomes: fix the product, reword the claim, or remove it. Name anything you could not exercise, such as real delivery or a paid checkout.
|
|
@@ -42,16 +42,19 @@ Choose from the subject's world: its materials, places, artefacts and vocabulary
|
|
|
42
42
|
|
|
43
43
|
When the user gives references, study them properly: [reference study](references/reference-study.md) pulls computed styles from the live sites so you borrow relationships (scale, rhythm, density), not surface decoration.
|
|
44
44
|
|
|
45
|
+
When two directions both survive the generic test and the choice is hard to argue from a plan, prototype instead of debating: build two or three variants of just the contested piece behind a development-only switch (`?variant=b`), shoot each at the same widths and states, choose with the user or the rubric, and delete the losers before finishing. Variants differ in one decision each (layout, type pairing, density), so the comparison says something.
|
|
46
|
+
|
|
45
47
|
## 3. Build in the product's system
|
|
46
48
|
|
|
47
49
|
- Use existing tokens, primitives and components. Add a token before adding a one-off value.
|
|
48
|
-
-
|
|
50
|
+
- Components that are hard to get right by hand (toasts, drawers and sheets, comboboxes, date pickers, virtualised lists, drag and drop) come from the project's primitive. If it has none and a dependency is in scope, choose a maintained, accessible, headless library over hand-rolling one: check its last release, open issues, bundle size and keyboard support first, and record the choice in DESIGN.md.
|
|
51
|
+
- Real content only: real names, long names, real numbers, empty data. Never lorem ipsum, never invented metrics to fill a layout. Before calling a data-driven screen done, run it on [worst-case data](references/worst-case-data.md): the longest plausible name, an unbreakable email, a count of 1 and of 1,284, an empty list, a missing avatar. A workspace also runs at the plan limit, with seeded records: [workspace at scale](references/workspace-scale.md).
|
|
49
52
|
- Design the states with the screen: loading, empty, error, success, disabled, overflow. An empty state that looks broken is a bug. A loading state is the loaded layout with content replaced by bones of the same boxes. A shorter stack of bars is a jump. Mark the stable regions and compare the two states: [loading](references/loading.md).
|
|
50
53
|
- Hide what has nothing to say. Zero rows, zero balances and empty charts become an honest empty state or disappear; no walls of zeros.
|
|
51
54
|
- Headers are labels. A subtitle that re-explains the header gets deleted.
|
|
52
55
|
- Mobile is its own layout: reorder by priority, use horizontal snap rails where desktop uses grids, `dvh`/`svh` not `100vh`, inputs at 16px or larger, tap targets 44px. Anything people use on a phone gets the [mobile baseline](references/mobile.md): no tap flash, hover gated to real pointers, press feedback on touch, safe areas, no zoom on focus.
|
|
53
56
|
|
|
54
|
-
Hold the line on the [craft floor](references/craft-floor.md) while building, not as a final pass. For any animation or transition, read [motion](references/motion.md) first: decide whether it should animate at all (never for keyboard or high-frequency actions), ease-out and under 300ms for UI, press feedback and origin-aware popovers, interruptible transitions, only `transform` and `opacity`, reduced motion handled, and watched as a filmstrip. The same reference diagnoses janky animation by cause.
|
|
57
|
+
Hold the line on the [craft floor](references/craft-floor.md) while building, not as a final pass. For any animation or transition, read [motion](references/motion.md) first: decide whether it should animate at all (never for keyboard or high-frequency actions), ease-out and under 300ms for UI, press feedback and origin-aware popovers, interruptible transitions, only `transform` and `opacity`, reduced motion handled, and watched as a filmstrip. The same reference names effects when the request is vague, gives several moving elements one lead, diagnoses janky animation by cause, and audits a whole app's motion into keep, fix and cut with `file:line` and a verdict.
|
|
55
58
|
|
|
56
59
|
## 4. Look at it
|
|
57
60
|
|
|
@@ -62,6 +62,10 @@ Late-2026 tells, with one example each. Ayush Soni named the cluster in public (
|
|
|
62
62
|
|
|
63
63
|
| Pattern | Looks like | Instead |
|
|
64
64
|
| --- | --- | --- |
|
|
65
|
+
| pastel-rainbow-bento | Each card gets its own sky, mint or peach, chosen to fill a grid | Brand colours plus one or two quiet tints. A colour earns its place by meaning something |
|
|
66
|
+
| status-in-brand-colour | A warning amber that looks like the brand accent, or a late badge in the accent | Move the status hue away from the accent. Reserve the accent for what it means, such as the approving tap |
|
|
67
|
+
| pale-tiles-in-dark-mode | Light cards carried unchanged into dark mode, glaring or turning muddy | Give each decorative tint a dark value, and check it next to the page colour |
|
|
68
|
+
| accent-on-everything | The accent on every row arrow and chip, so the one action that matters stops standing out | Neutral for navigation, accent only for the decisive action |
|
|
65
69
|
| violet-gradient | Purple to indigo gradients, cyan accents on near-black | Pick colour from the product's world. One accent. |
|
|
66
70
|
| gradient-text | Headline filled with a gradient (`bg-clip-text text-transparent`) | Solid ink. Emphasis through weight, size or a single coloured word only if the brand does that. |
|
|
67
71
|
| glass | `backdrop-blur` panels everywhere | Solid surfaces. Blur only when content genuinely scrolls beneath. |
|
|
@@ -12,6 +12,13 @@ The minimum for anything that ships. Check these while building, then once more
|
|
|
12
12
|
- No middle-dot strings ("A · B · C") in running text: they strand at line ends. Use separate elements with gaps.
|
|
13
13
|
- Tabular numerals (`font-variant-numeric: tabular-nums`) for money, times, counts and any column of numbers.
|
|
14
14
|
- Display text no larger than it needs to be: a 120px headline is a layout, not emphasis.
|
|
15
|
+
- Relative times stop being relative after about a week: "3 hours ago" and "Yesterday", then "4 Nov" and "4 Nov 2025". Nobody can place "340 days ago". Keep the exact timestamp in a `title` or `<time datetime>`.
|
|
16
|
+
- Counts read as words: `Intl.PluralRules` (or the i18n library) for "1 member" and "2 members", and `Intl.NumberFormat` for separators and compact forms.
|
|
17
|
+
|
|
18
|
+
## Edges and fades
|
|
19
|
+
|
|
20
|
+
- A fade over scrolling content or at a list's edge uses an eased gradient with several stops (or a `mask-image` with the same stops), not a two-stop linear gradient, which shows a visible band where it ends.
|
|
21
|
+
- A fade sits over content only where more content exists; hide it at the start and end of the scroll.
|
|
15
22
|
|
|
16
23
|
## Colour and contrast
|
|
17
24
|
|
|
@@ -33,3 +33,20 @@ When the brand face is a webfont, give the fallback `size-adjust`, `ascent-overr
|
|
|
33
33
|
## Done
|
|
34
34
|
|
|
35
35
|
Both states captured, no region and no document scroll moved by more than 1px at 390px, bones replaced content inside the real layout, and the fallback face cannot reflow the first paint. If you could not reach the real loading state, say so.
|
|
36
|
+
|
|
37
|
+
## Check the bones can be seen
|
|
38
|
+
|
|
39
|
+
A skeleton can hold the right layout and paint nothing. A bone coloured with an undefined custom property is transparent, and an undefined variable inside a gradient drops the whole gradient. Use tokens that already exist, and read a bone's computed `background-color` if the capture looks empty.
|
|
40
|
+
|
|
41
|
+
To review them all at once, render each skeleton on a throwaway route, capture it at both widths and themes, and delete the route. Then confirm the streamed HTML on real pages contains them.
|
|
42
|
+
|
|
43
|
+
Keep the words for assistive technology: `role="status"` and a visually hidden label on the wrapper. Fade the skeleton in after about 100ms so a quick load never flashes it. Stop the shimmer under reduced motion and leave the shapes.
|
|
44
|
+
|
|
45
|
+
A new custom property in a global stylesheet may not reach a running dev server, which can keep serving its cached stylesheet. Confirm on a production build before debugging further.
|
|
46
|
+
|
|
47
|
+
## Steps that share a space
|
|
48
|
+
|
|
49
|
+
For tabs or steps that must not move the content below, stack every panel in one grid cell, so the box is always as tall as the tallest panel, and hide the inactive ones with `visibility: hidden`. This replaces guessing a `min-height` per breakpoint. Two traps:
|
|
50
|
+
|
|
51
|
+
- Tailwind's preflight sets `[hidden]` to `display: none !important` in a layer, and a layered `!important` beats an unlayered one. Use a data attribute instead of `hidden`.
|
|
52
|
+
- A blanket reduced-motion rule that shortens every transition also animates inherited `visibility` on children. Set `transition-property: none` on the panels and their children, or a test reads an empty panel.
|
|
@@ -27,6 +27,21 @@ For each animated thing, one line per field:
|
|
|
27
27
|
- **Interruption**: what happens on a second click mid-animation: reverse, retarget or finish.
|
|
28
28
|
- **Reduced motion**: what shows instead (see [reduced motion](#reduced-motion-wiring)).
|
|
29
29
|
|
|
30
|
+
When the request is vague ("make it feel smoother", "something like Linear's"), name the effect before building it, and confirm the name when the choice changes the work:
|
|
31
|
+
|
|
32
|
+
| Name | What moves | Reach for it when |
|
|
33
|
+
| --- | --- | --- |
|
|
34
|
+
| Fade | Opacity only | State appears or leaves in place; the reduced-motion fallback for most others |
|
|
35
|
+
| Scale-in | `scale(0.95)` and opacity to rest, from the trigger | Popovers, menus, tooltips |
|
|
36
|
+
| Slide | Translate along one axis, by the element's own size | Sheets, drawers, toasts, pages in a stack |
|
|
37
|
+
| Crossfade | Two states overlap while one fades out | Swapping an icon, label or image in the same slot |
|
|
38
|
+
| Morph (shared element) | One element changes size and position into its next state | A card opening into a detail view, a tab pill moving |
|
|
39
|
+
| Reveal | `clip-path` or mask uncovers content in place | Headlines, comparison sliders, hold-to-confirm fills |
|
|
40
|
+
| Stagger | The same entrance offset per item | A list or grid arriving once |
|
|
41
|
+
| Spring | Physics with velocity, can overshoot | Gestures, drag release, anything interrupted often |
|
|
42
|
+
| Scrub | Progress tied to scroll or a pointer | Explainers and scroll-linked stories |
|
|
43
|
+
| Follow-through | Parts settle slightly after the lead stops | Playful brands only, small amplitude |
|
|
44
|
+
|
|
30
45
|
### 3. Pick the ease and the duration
|
|
31
46
|
|
|
32
47
|
Ease by what is happening:
|
|
@@ -88,7 +103,24 @@ Match the motion to the component's character: a dashboard is crisp and fast; a
|
|
|
88
103
|
- Ambient loops pause offscreen (`IntersectionObserver`) and when the tab is hidden (`visibilitychange`). At most one ambient effect per screen.
|
|
89
104
|
- Never delay the actual action (navigation, submit) until an animation finishes.
|
|
90
105
|
|
|
91
|
-
### 6.
|
|
106
|
+
### 6. Choreograph several elements
|
|
107
|
+
|
|
108
|
+
When more than one thing moves for the same change (a dialog and its backdrop, a card expanding while its list dims, a step advancing), give each element one role before writing timings:
|
|
109
|
+
|
|
110
|
+
- **Lead**: the element the change is about. Exactly one. It starts first and carries the signature ease.
|
|
111
|
+
- **Follow**: elements that move because the lead did (contents inside a sheet, siblings making room). They start 30–80ms after the lead, travel less, and finish no later than it does.
|
|
112
|
+
- **Parallel**: elements that change for the same reason at the same time (backdrop and dialog). Same start, same duration, same ease family.
|
|
113
|
+
- **Still**: everything else. Name it. Most of the screen should not move, and an element that moves for no reason reads as a bug.
|
|
114
|
+
|
|
115
|
+
Then hold the sequence together:
|
|
116
|
+
|
|
117
|
+
- The whole sequence for an ordinary UI change ends within about 400ms; followers do not extend it.
|
|
118
|
+
- Exits run together and faster than the entrance, in reverse role order or all at once. Nobody waits for a staggered exit.
|
|
119
|
+
- Spatial sense stays consistent: things that came from the trigger return to it, a sheet that rose from the bottom leaves downwards.
|
|
120
|
+
- Input is accepted from the first frame. If the lead is interrupted, followers retarget with it rather than finishing their own timelines.
|
|
121
|
+
- Write the roles into the motion contract, one line per element, so a reviewer can check the filmstrip against it.
|
|
122
|
+
|
|
123
|
+
### 7. Gestures
|
|
92
124
|
|
|
93
125
|
- Dismiss on velocity as well as distance: `Math.abs(distance) / elapsedMs > 0.11` is a flick, and a flick is enough.
|
|
94
126
|
- Past a boundary, apply damping (the further the drag, the less it moves) instead of a hard stop.
|
|
@@ -96,7 +128,7 @@ Match the motion to the component's character: a dashboard is crisp and fast; a
|
|
|
96
128
|
- Declare which axes the gesture owns with `touch-action` (`pan-y` on a horizontal carousel, `none` only on a surface that handles every direction).
|
|
97
129
|
- Decorative pointer-following goes through a spring (Motion's `useSpring`, or `{ type: "spring", duration: 0.5, bounce: 0.2 }`), never raw pointer coordinates. Functional readouts follow the pointer directly.
|
|
98
130
|
|
|
99
|
-
###
|
|
131
|
+
### 8. Keep every frame on time
|
|
100
132
|
|
|
101
133
|
The budget is 16.7ms a frame at 60Hz and 8ms at 120Hz, which most phones now are. Design against the smaller number and a mid-range phone, not the laptop.
|
|
102
134
|
|
|
@@ -114,7 +146,7 @@ The budget is 16.7ms a frame at 60Hz and 8ms at 120Hz, which most phones now are
|
|
|
114
146
|
|
|
115
147
|
Name the cause before changing code, and say which findings came from reading code and which from a recording. A performance trace in the browser beats rewriting by feel; report frame rates only when measured, with the device.
|
|
116
148
|
|
|
117
|
-
###
|
|
149
|
+
### 9. Watch it play
|
|
118
150
|
|
|
119
151
|
Stills cannot prove motion. Capture a filmstrip and look at the frames:
|
|
120
152
|
|
|
@@ -126,14 +158,36 @@ node <skill-dir>/scripts/shoot.mjs http://localhost:3000/ --widths 390,1440
|
|
|
126
158
|
|
|
127
159
|
In the frames, check that colours cross cleanly rather than showing two states, the ease does not stop abruptly, the origin is right, and coordinated properties stay in step. Then in a real browser: trigger once; trigger rapidly; reverse mid-way; navigate away mid-animation; use keyboard and touch; enlarge text; switch to reduced motion. Slow it down 2–5x (DevTools Animations panel) when the feel is in doubt. Gestures need a real phone. Fix flicker, jumps, clipped frames and stranded states, then re-check that case.
|
|
128
160
|
|
|
129
|
-
|
|
161
|
+
Reduced-motion captures show final states only, so they cannot prove motion ends. Load the page without reduced motion, wait past the longest sequence, and count what is still running:
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
document.getAnimations().filter(a => a.playState === "running").length
|
|
165
|
+
```
|
|
130
166
|
|
|
131
|
-
|
|
167
|
+
Anything above zero that is not a deliberate indicator is a loop. On a product page, prefer one finite story over ambient movement: the thing arrives, the result appears, the next action is invited.
|
|
132
168
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
169
|
+
### 10. Audit a whole app's motion
|
|
170
|
+
|
|
171
|
+
For "audit the animations", "it feels busy" or "where should this move", work from an inventory, not a page you happened to open:
|
|
172
|
+
|
|
173
|
+
1. **Inventory.** Search the source for every moving thing: `transition`, `animation`, `@keyframes`, `@starting-style`, `animate(`, `requestAnimationFrame`, `motion.`/`<motion`, `useSpring`, `AnimatePresence`, Tailwind `transition-*`, `animate-*` and `duration-*`, and scroll or intersection observers that add classes. One row per animated element with its `file:line`.
|
|
174
|
+
2. **Classify each row** by the frequency table in section 1 and by purpose. The row is **keep**, **fix** (right to move, wrong ease, duration, origin, properties or interruption) or **cut**.
|
|
175
|
+
3. **Cut by default**, unless the brief or DESIGN.md asks for them: motion on keyboard-driven actions, fade-up on every section, a delay before every tooltip after the first, page-load stagger on screens people open many times a day, hover zoom on cards, ambient loops that explain nothing, and spinners on actions that finish under about 300ms.
|
|
176
|
+
4. **Find the missing ones.** List the few places where motion would explain something and does not: an item that appears with no hint where it came from, a removal that leaves the user unsure it happened, a press with no feedback, a sheet that teleports. Each needs a purpose from section 1.
|
|
177
|
+
5. **Write each change as a self-contained item**: `file:line`, the current behaviour, the target (ease token, duration, properties, origin, role), the reason, and how to check it (filmstrip command or the rapid-trigger case). Another agent or person should be able to carry out any one item without reading the rest.
|
|
178
|
+
|
|
179
|
+
Apply the cuts and fixes that are clearly defects; list the additions for a decision unless the request was to add them.
|
|
180
|
+
|
|
181
|
+
### 11. Report
|
|
182
|
+
|
|
183
|
+
Report the contract, the tokens used, what you watched (filmstrip paths, cases exercised) and anything measured with its method. When reviewing someone's motion, give findings as one table, each with its `file:line`:
|
|
184
|
+
|
|
185
|
+
| Where | Before | After | Why |
|
|
186
|
+
| --- | --- | --- | --- |
|
|
187
|
+
| `card.tsx:14` | `transition: all 300ms` | `transition: transform 200ms var(--ease-out)` | Name the properties; 300ms is slow for UI |
|
|
188
|
+
| `popover.tsx:31` | `transform-origin: center` | `transform-origin: var(--transform-origin)` | It should grow from its trigger |
|
|
189
|
+
|
|
190
|
+
End a review with a verdict: **approve** (nothing blocks), **approve with fixes** (only polish rows) or **block** (any row breaks a rule under Refuse, gets stuck when interrupted, ignores reduced motion or drops frames on the target device). A review that lists problems and then waves the change through is not a review.
|
|
137
191
|
|
|
138
192
|
For an exported video, deliver the file and check duration, dimensions, crop and audio sync; a browser preview is not an export.
|
|
139
193
|
|
|
@@ -8,7 +8,7 @@ It is a reading aid for judgment, not a scorecard to optimise. A piece that hits
|
|
|
8
8
|
|
|
9
9
|
## Three gates before any score
|
|
10
10
|
|
|
11
|
-
1. **Accuracy.** Every claim, number, name and quote traces to a source: the brief, the product, a dated query. An invented feature or figure fails the piece however well it is made.
|
|
11
|
+
1. **Accuracy.** Every claim, number, name and quote traces to a source: the brief, the product, a dated query. An invented feature or figure fails the piece however well it is made. Check verbs and absolutes against the code too: "writes" for a fixed template and "nothing goes out" beside an automatic receipt both fail. The `dogfood` skill has a claims audit for this.
|
|
12
12
|
2. **Deterministic gates.** `render-gate.mjs` with `--design` and `--expect` for anything with brand tokens or supplied copy; `shoot.mjs` for pages; `film.mjs` for clips (in `launch`); `slop-scan.mjs` for copy (in `deslop`). Exit 1 is a finding to fix. Exit 2 means the gate did not run, which is never a pass.
|
|
13
13
|
3. **The ask.** When someone asked for a specific change, check that change first. It is the bar.
|
|
14
14
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Workspace at scale
|
|
2
|
+
|
|
3
|
+
A dashboard built on two demo records usually fails at thirty. Before calling an operating surface done, run it at the plan limit, or at the largest account you expect, using records that look real.
|
|
4
|
+
|
|
5
|
+
## Seed it, then look
|
|
6
|
+
|
|
7
|
+
Create a local database with a believable portfolio: the plan's maximum number of parents, a mix of urgent and routine work, and long names. Go through the product's own schema, and satisfy its guards rather than bypassing them. Then read the screen before designing anything. The first capture usually names the work: walls of identical cards, a headline that disagrees with the list, links into closed sections.
|
|
8
|
+
|
|
9
|
+
## The contract
|
|
10
|
+
|
|
11
|
+
| Rule | What it means |
|
|
12
|
+
| --- | --- |
|
|
13
|
+
| One screen of work | Tabs or sections beside a sticky rail of recent activity and tools, in place of a long scroll. Every tab can be linked to by address. |
|
|
14
|
+
| Find, narrow, page | Search covering the words people remember, including postcodes and codes. Filters with counts, shown only for kinds that exist. Twelve to fifteen rows, then "Show more". |
|
|
15
|
+
| Urgent first, never paged | Split urgent from the rest before cutting to a page. Sorting after the cut hides emergencies under routine rows. Rank urgent parents first in list views too, and mark them in the row. |
|
|
16
|
+
| Counts are promises | A headline or tab count equals the rows reachable from it. "Showing 15 of 100" is true at every step of paging and filtering. A capped list says so on the screen. |
|
|
17
|
+
| "All clear" is earned | Say "nothing needs you" only when every source answered and nothing is open. A failed read shows a neutral title and says what could not be checked. |
|
|
18
|
+
| One rule across views | The summary and the detail page use one definition of "needs you". If they disagree, the owner stops trusting both. |
|
|
19
|
+
| Status survives on phones | A badge hidden below a breakpoint needs a text equivalent in the row. |
|
|
20
|
+
| Long detail folds | A list of forms becomes a list of rows, with the first and anything urgent open. Opening from a link must open the target row. |
|
|
21
|
+
| One name per item | A record named by category in one tab and by a generic word in another reads as two records. |
|
|
22
|
+
|
|
23
|
+
## Cost
|
|
24
|
+
|
|
25
|
+
Measure rather than guess, with the account at the limit. Read waiting items in one query, not one per parent. Check raw and compressed HTML, because every tab's server-rendered content counts and 3 MB is easy to reach by accident. Give the heaviest lists a client list with paging, or cap them and point to the parent. Stream the shell, with a skeleton for the slow part.
|
|
26
|
+
|
|
27
|
+
## Phones
|
|
28
|
+
|
|
29
|
+
A workspace used on a phone gets a bottom tab bar for its places, with icons, labels and a safe-area inset, replacing the menu. If tabs change the address with `history.replaceState` or `pushState`, no `hashchange` fires, so anything else following the address needs its own event. Tap a bar item, change an inner tab, and confirm the bar updated.
|
|
@@ -33,6 +33,19 @@ Post-process by hand when needed (add a `<title>`, group ids for animation, swap
|
|
|
33
33
|
- Check every icon at 16px and 20px: silhouette must still read. Below ~24px, use a simplified variant (a head-only mascot, a filled glyph) rather than shrinking the full drawing.
|
|
34
34
|
- Optical alignment: a play triangle sits visually centred only when nudged right; check at 2x.
|
|
35
35
|
|
|
36
|
+
## Brand scenes drawn from numbers
|
|
37
|
+
|
|
38
|
+
When a product has no photography, one drawing from its world can carry the brand: a street, a harbour, a workshop. Generate it from a small data table instead of hand-drawing paths.
|
|
39
|
+
|
|
40
|
+
- Keep one function that returns the shapes, and render it everywhere: hero, closing panel, empty state and the share image. The share image renders it with fixed colours, so it needs no CSS.
|
|
41
|
+
- Use the same two or three brand colours, with one small accent that means something, such as a lit window.
|
|
42
|
+
- Fit the viewBox to the height it renders at. With `preserveAspectRatio="xMidYMax slice"` in a shorter box, the top is cropped, so roofs turn into flat lines. Check the silhouette at the rendered size.
|
|
43
|
+
- Hide it where something covers most of it. A phone over a skyline on a narrow screen leaves slivers and a stray accent.
|
|
44
|
+
- Adjacent shapes can show hairline seams when scaled. Use `shape-rendering: crispEdges` on straight walls.
|
|
45
|
+
- Animate one small thing, once, and let reduced motion show the finished drawing.
|
|
46
|
+
|
|
47
|
+
A cover drawing does not replace showing the product. Pair it with the real interface, labelled as an example where the data is fictional.
|
|
48
|
+
|
|
36
49
|
## ASCII art
|
|
37
50
|
|
|
38
51
|
- Render in a known monospace stack and line height; ASCII breaks when the font falls back. Set `font-variant-ligatures: none`.
|