01 / apply it
yardr pack apply ./webdesign --depot <depot>From a clone of yardr-packs: the pack's directory. yardr pack check ./webdesign --depot <depot> shows what it would change first.
yardr pack apply https://yardr.dev/packs/webdesign/ --depot <depot>From this site, as the files below: from yardr v0.8.0 on.
02 / the flows
One flow.
flow mockupbacklog → picked · 4 stages
03 / the files
Every file, as it ships.
# Webdesign pack for yardr: the lane a question of look takes before anything
# is built. A bead of type mockup carries a brief. A designer makes three
# standalone HTML mockups of three distinct design directions on the bead's
# branch and shoots each one, and a person looks at the shots and names the
# direction to build from. Nothing is built for real and nothing lands.
# Like the starter pack it names no agent product, model, depot, person or
# secret: the import asks, and they stay in the yard. The format is the
# starter's (packs/starter/pack.yaml, docs/packs.md in the yardr repository).
name: webdesign
# The kind of depot the pack is for: the mockups are committed on the bead's
# branch.
kind: git
# The setup notes, for the operator: the import, the agent it asks for and the
# programs the shots need. pack check and pack apply print them.
setup: SETUP.md
# One flow, for beads of type mockup, beside the flow the depot follows for its
# own work (the starter's, say): this pack has none without a type. The type is
# the pack's own because a type follows one flow. The design pack's flow is for
# type design, so a pack that reused that type would have its import re-point
# every depot already on the document-design flow.
#
# There is no assembly stage. The mockups stay on the bead's branch and the
# shots on its note, and the words of the person's pick name the direction:
# landing all three pages would put throwaways on the base, and landing one
# would need another agent to take the other two out. A bead ends at picked.
#
# Rounds are not limited. The only way back is a person's move from pick, with
# a note that says what to change, so a person decides each round.
flows:
mockup:
type: mockup
stages:
backlog: { group: backlog, file: flows/mockup/backlog.md, manual: [mockups] }
mockups: { group: designers, file: flows/mockup/mockups.md, outcomes: { done: pick, question: pick }, manual: [backlog] }
pick: { group: decisions, file: flows/mockup/pick.md, manual: [picked, mockups, backlog] }
picked: { end: true }
# The designers are a group of this pack's own. The design pack takes the
# depot's builders because its roles are the starter's text, but a pack names a
# group together with its role, so naming builders here would aim the depot's
# code builders at a designer's prompt. The import makes <depot>-designers and
# asks which agent runs it. One bead at a time: each serves its worktree and
# runs headless Chrome three times. A yard that wants more raises the limit of
# the group it has (yardr group set). backlog and decisions are the yard's two
# people groups, which the import reuses.
groups:
designers: { agent: roles/designer.md, limit: 1 }
backlog: { people: true }
decisions: { people: true }
# The designer's role tells it to mail {{yardmaster}}, so the pack names the
# crew member, as the starter does. It hears a bead enter pick, a bead close,
# and the events that need someone. The pack carries no role for it: the
# yardmaster keeps the prompt it has.
crew:
yardmaster:
hears:
events: [attention]
stages: [pick]
done: true
summary: a mockup bead waits here until its brief is ready to design from A mockup bead asks for three design directions to pick from, not for a page to ship. Before it is sent to `mockups` its body says: - the subject: what the product, place or person is, in one concrete sentence; - the audience: who comes to the page; - the primary job: the one thing the page gets a visitor to do; - the page: which page of the site, or which screen of the app, the three mockups show; - reference sites: addresses of sites the person likes or dislikes, each with what to take from it or leave; - what the brief fixes: brand colours, typefaces, a logo, copy that must appear, or that nothing is fixed; - what is not wanted: looks already tried and turned down. Send it with `yardr bead advance <id> --to mockups`.
summary: you make three HTML mockups in three distinct directions and put their shots on one note You make mockups here, not a site. You work on branch `yard/<bead>` in the bead's own worktree. The bead's body is the brief, and your role says how to work. Before the bead leaves as `done`: - three files `mockups/<n>-<name>.html` are committed on the branch, each opening on its own with no build step; - one note on the bead carries three shots of them, 1280x800, taken at the last commit, and says that commit's short SHA; for an app screen (your role says what that is) it carries three more, 390 wide, one for each file; - the same note gives each page's address on the watch (the address `yardr preview watch` printed, then the file name), or what the command printed when it gave none; the watch ends when the bead leaves `mockups`, so the shots are the record; - the same note names each mockup's direction family, type pairing and palette, and your role's distinctness rule holds for the three. Outcomes: - `done`: all of that holds. The bead goes to `pick`, where a person looks at the shots. - `question`: no design can start without an answer, a subject you cannot identify from the brief or the repository, say. Note exactly what you need first. The bead goes to `pick`, where a person answers and sends it back to `mockups`.
summary: a person looks at the shots, names the direction to build from, or sends the bead back For a person. What to read: the designer's note on the bead, which carries the three shots, and for an app screen three more at phone width, and names each direction (`yardr prime --bead <id>` prints the bead with every note in full). The mockups are pages that open on their own, on the bead's branch `yard/<bead>` under `mockups/`; the shots are what to judge them by. A bead leaves `pick` when a person moves it, with words: - to `picked` when a direction is taken: the bead closes, and nothing lands on the base. Name the direction in your words, by its number and name, and say what to keep from the others. A build from the pick is a bead of its own, filed by hand when you ask for one; - to `mockups` with a note when none is there yet: say what to change, and the designer makes three again; - to `backlog` to park it or have the brief reshaped. A bead also comes here when the designer could not start without an answer: the note says what it needs. Answer in a note and send it back to `mockups`. When a bead arrives the yard puts a card for these moves on it, and picking one moves the bead: your words with the pick stay on the bead for whoever works it next. A bead with an ask already open gets no card, and a card gives way to an ask put after it: that question is what you answer, and the bead is moved by hand once it is. ## Ask kind: moves question: Which direction do you take, or where should this bead go next? context: - The designer's note holds the shots (three, and for an app screen three more at phone width) and names each direction. The mockups are on the bead's branch under mockups/. - To take one, move the bead to picked and name it in your words. To ask for another round, move it back to mockups and say what to change. - Your words with the pick stay on the bead for whoever works it next.
# Webdesign A pack for a yard that wants design direction from agents, not an implementation. A brief goes in, three design directions come out as standalone HTML mockups with a screenshot of each, and a person picks one. Nothing is built for real and nothing lands. Nothing here is compiled into yardr; apply it with: ```sh yardr pack apply /path/to/yardr-packs/webdesign --depot <depot> ``` `yardr pack check /path/to/yardr-packs/webdesign --depot <depot>` shows what the import would do first, and writes nothing. SETUP.md is the operator's steps. The pack adds the bead type `mockup` beside the flows a depot already follows. A depot on the design pack's document flow keeps it. One type follows one flow, and the design pack's flow is for the type `design`, so a pack that reused that type would have its import re-point every depot on the document flow. The type `mockup` is this pack's own, and an import leaves every other type's flow, routes and groups as they are. ## How it hangs together ``` backlog -> mockups mockups -> pick on done | pick on question | backlog pick -> picked | mockups | backlog picked terminal ``` | stage | worked by | what happens | |---|---|---| | `backlog` | `backlog`, people | the bead waits until its brief says the subject, the audience, the primary job, the page, the reference sites, what is fixed and what is not wanted | | `mockups` | `designers` | an agent commits three standalone pages, `mockups/<n>-<name>.html`, on the bead's branch, starts a watch on the folder so the person can open the pages while they are built, shoots each at 1280x800 (an app screen also at 390 wide), and puts the shots on one note that names each direction's family, type pairing and palette and each page's address on the watch | | `pick` | `decisions`, people | a person reads the shots and moves the bead to `picked`, back to `mockups` with a note, or to `backlog`; the yard puts a card on the bead offering these moves, and the person's words with the pick name the direction | | `picked` | | the end: the bead closes | `question` also leads to `pick`. A designer that cannot start without an answer (no subject it can identify) says what it needs on a note, and the person answers there and sends the bead back to `mockups`. There is no assembly stage. The mockups stay on the bead's branch `yard/<bead>` and the shots on its note, and the words of the pick name the direction. Landing all three pages would put throwaways on the base, and landing one would need another agent to take the other two out. A build from the pick is a bead of its own, filed by hand when someone asks for one. **Three directions that differ.** The designer's role asks for three families (editorial, grid, poster, specimen and so on), and for each a type pairing, a palette and one idea taken from something that only this subject has. The rule is that no two directions share all three of family, type pairing and palette. A brief that fixes the brand's colours or typefaces keeps them in all three, and the families carry the difference. **The shots.** The designer serves the worktree on a free loopback port, shoots each page with `contrib/shot/shot` from a yardr checkout, confirms each PNG is 1280 x 800 and not empty, and opens each one. That last step is not optional. In 24 shots of one throwaway page whose typeface came from a CDN (loaded two ways, with `display=swap` and with `display=block`), two were wrong, one in a fallback face and one blank, because Chrome took the shot before the font arrived. Both passed the size check. **The watch.** Once the first page exists the designer starts `yardr preview watch $YARDR_BEAD mockups`. The yard serves the folder's files read-only through its preview endpoint, and a page reloads in the browser whenever a file in the folder changes, so the person sees the three pages take shape. The command prints the address they open at on its `opens at` line: the host the yard's edge gave the watch, or the path `/preview/<app>/` on the yard where the edge gives none. `mockups/` holds no `index.html`, so the folder's own address answers 404, and so does the Open button of the watch's card on the Previews page. The designer therefore names each page's address, the printed address followed by the file name, and puts the three on a note as soon as the watch is up, so the person has them while the designer builds. The note with the shots gives them again. The watch ends by itself when the bead leaves `mockups`, so the shots are the record of what the person picks from. **App screens.** The designer first decides whether the brief is for a page, which people read, or an app screen, which people work in: a dashboard, a back-office or reporting view, settings or billing, an inbox. For an app screen the role adds rules (the screen's question first, quiet panels, aligned figures, colour spent on data, believable data, a phone layout where the navigation folds away) beside its families and house style, and the three directions still differ by family, type pairing and palette. An app screen is shot twice, always: at 1280x800 and, with `SHOT_WIDTH=390`, at phone width, so the note carries six shots and the stage's exit does not depend on a judgement call. ## What it needs - **An agent for `<depot>-designers`.** The import asks for its kind, model and permission arguments, as it does for any agent group it makes. The group is the pack's own and not the depot's `builders`: a pack names a group together with its role, so naming `builders` would aim the depot's code builders at a designer's prompt. One designer works at a time, and `yardr group set <depot>-designers --limit 2` allows more. - **The yard's two people groups**, `backlog` and `decisions`, which the import reuses when the yard has them and asks for the members when it does not. - **A crew member called `yardmaster`**, or another that takes the name (`--crew yardmaster=<name>`). It hears a bead enter `pick`, a bead close, and the events that need someone. The pack carries no role for it, so the yardmaster keeps its prompt. - **On the yard's machine**, for the shots: headless Chrome (or `SHOT_CHROME`), `curl`, `python3` and a yardr checkout. An app screen's phone shots need a checkout whose `contrib/shot/shot` takes `SHOT_WIDTH` (yardr 9c94ab8, 4 November 2026, and after); an older script ignores it and shoots 1280 wide. The mockups load their typefaces and libraries from CDNs, so the machine needs the network while a designer works. - **A yardr with `yardr preview watch`**, for the watch (yardr 26b2a52, 4 November 2026, and after). `yardr docs watch` prints its page on a yardr that has the command and names the pages it has on one that does not. On an older yardr `yardr preview watch` prints the help of `preview` and ends 0, so the designer goes by the `opens at` line: with none, it puts what the command printed on its note and goes on, and the shots are as before. The address is the path on the yard until the yard is linked to an edge that gives the watch a host (yardr ec29917, 4 November 2026, and after). Where the yard is linked and the edge refuses, the command prints the edge's words under the path. ## What the import asks Beside a yard that has `backlog`, `decisions` and a `yardmaster`: the agent of `<depot>-designers` (`--bind designers=<kind>[:<model>]`), or the group of the yard that takes it (`--group designers=<group>`). Otherwise also the members of `backlog` and `decisions` (`--members decisions=<a>,<b>`) and which crew member takes `yardmaster` (`--crew yardmaster=<name>`). ## Files - `pack.yaml`: the flow, the groups that work it and the crew member its role names. - `flows/mockup/`: a stage file for each stage a bead waits or is worked in. What a stage needs to be true is here, and how a designer works is in the role. - `roles/designer.md`: the designer's role. It holds the work in five steps, the families, the house style, the rules for an app screen, the shot mechanics, and the vendored baseline. - `SETUP.md`: the operator's cards. - `THIRD_PARTY_NOTICES.md`: the two projects the role draws on, their pins and copyright lines, and both licence texts in full. - `test`: the pack's tests. Files of a pack that `pack.yaml` does not name are not installed. The role and the stage files point at none of them, because the yard that imports the pack never has them. ## Vendored material The role carries two pieces of other people's work, each opened by a one-line notice of its name, URL, pin and licence. - **frontend-design** from Anthropic's skills repository (`anthropics/skills@ca45fc4`, Apache-2.0): the body of its `SKILL.md`, whole and unmodified, as the baseline of the craft. Its frontmatter is left out. - **taste-skill** by Leonxlnx (`Leonxlnx/taste-skill@12af471`, MIT): its method in this pack's own words, and the rules of its app-screens reference for dashboards, admin, settings and the like, also in this pack's own words, under a notice of their own. A device it bans outright stays allowed here when a direction chooses it, so that three directions keep their range. Its library, its other references and its scripts are not in this pack, and neither are the stylesheet and chart script the app-screens reference builds on (`assets/app.css`, `assets/charts.js`). THIRD_PARTY_NOTICES.md has the rest. ## Runtimes The pack has no program of its own beyond `test`, which needs `sh`, `grep`, `awk` and `shasum` (or `sha256sum`). The designer's steps use `git`, `python3` (for `python3 -m http.server`), `curl` and `file`, and the shot script uses headless Chrome. ## Testing `sh .yardr/test` at the root of the repository runs `yardr pack check` and then `webdesign/test`. The test needs no network and no secret and takes well under a second. It is text, so it pins what a later edit could lose without a sound: - the role carries both one-line notices with their pins and licences, a third for the app-screen rules, and the rules and the phone shot themselves; - the role starts the watch with the bead's id, says how a page's address is made and what to do when the command prints none, and has the designer put the addresses on a note while it builds and again in the note with the shots; - the vendored frontend-design block is the upstream body, byte for byte, by its sha256; - THIRD_PARTY_NOTICES.md holds both licence texts byte for byte, by their sha256, with the full commits and the copyright line; - each stage file has its exit line, `mockups.md` names the phone shots and the address of each page on the watch, and `pick.md` has the card of its moves; - the decisions of `pack.yaml`: the pack's own type and group, no script group, the yardmaster hearing `pick` and carrying no role; - no role or stage file points at a file the import does not install. Re-pinning a vendored file means changing its block, the hash in `test` and the hash in THIRD_PARTY_NOTICES.md together. ## What was checked, and what was not Checked, in a scratch yard under a short temp directory, with an environment of nothing but `PATH` and no daemon, so that no agent could start: - `yardr pack check` and `yardr pack apply` of this directory into a depot, with the answers on the command line as SETUP.md gives them. The flow prints as the four stages above, the installed role has no placeholder left, and the yard reads all three stage files and the card without a warning. - Checked against a depot that already follows the design pack, the plan shows the design pointer, its routes and its groups as `not in the pack (would be left alone)`, and `backlog` and `decisions` as shared. - A bead of type `mockup` walked through every move: advanced to `mockups`, a note with three images, `done`, the card put to a member of `decisions` with three options, the person's pick back to `mockups` with words, `question`, and the pick of `picked`, which closed the bead with the words kept. - The role's shot mechanics, step by step as separate commands: a static server on port 0, three shots, `file` naming `PNG image data, 1280 x 800`, a note with three `--file`, the server stopped by its pid and the directory removed. - The test breaks on each of 22 changes made to a copy, one at a time: a byte of the vendored block, a pin, a licence text, an exit line, the type, the group, an added script group, and others. Checked for the app-screen rules, after those: - The test breaks on each of 12 more changes made to a copy, one at a time: the URL in the app-screens notice, the section's heading, each of the six rules by its lead, the phone shot's width setting and its `file` line, the exit's 390 shots, and the notices' record of the reference. - The words are the pack's own. Everything the change added shares no run of more than six words with taste-skill's `SKILL.md` or `references/app-screens.md` at the pin, and what it does share is file names, a CSS property and the role's own earlier wording. - On a throwaway page, with this machine's Chrome (156) and the `contrib/shot/shot` of yardr 9c94ab8: `SHOT_WIDTH=390` writes `PNG image data, 390 x 800`, a shot without it still writes 1280 x 800, and a width that is not a number is refused by name before Chrome runs. Checked for the watch, after those: - The test breaks on each of 6 more changes made to a copy, one at a time: the command loses the bead's id, the address rule, the `opens at` fallback, the early note's rule, the shots note's line of addresses, and the exit's bullet. - The words follow yardr ec29917 as landed: `yardr docs watch`, the help of `yardr preview watch`, and the code that prints the command's output (`opens at https://<host>/` or `opens at /preview/<app>/`, with the edge's words on the next line). The watch card's Open button links the folder, as its template shows. `yardr docs watch` ends 0 here and `yardr docs nosuchpage` ends 1, naming the pages it has. - `yardr preview nosuchsub` prints the help of `preview` and ends 0. A yardr without the watch treats `watch` the same way, which is why the role goes by the `opens at` line and not by the exit status. That older yardr was not run. Not checked: - No designer agent has run this role, and none has run its app-screen rules or started its watch. Whether one follows it to three pages that differ, or three screens that read as working product, and how good they are, is not known. The first real bead of each kind is that test. The watch command was read and not run against a bead, so what a person sees in a browser, and whether the addresses reach the person in time, is as the docs describe. - Shots on a machine other than a Mac with Google Chrome. `contrib/shot/shot` looks for Chrome and Chromium elsewhere, and the role has not been run there. - A page at any viewport but 1280x800. The role asks for CSS that holds at phone width, as the baseline does, and says in the note that only the first screen at 1280x800 was looked at. An app screen is shot at 390 as well. ## Left out - **impeccable and ui-ux-pro-max.** Neither is vendored. They are a second slice if the range or the polish of the first proves thin. Their pins and licences are settled: `pbakaus/impeccable@9fadc41` is Apache-2.0 and `nextlevelbuilder/ui-ux-pro-max-skill@713eef5` is MIT. - **The scripts and engines of taste-skill and impeccable.** They need Node 22, Chrome and the network, and a pack has no key to install them with. That is a change to yardr, and so a bead of the yardr depot. - **The app-screen stylesheet and chart script of taste-skill** (`assets/app.css`, `assets/charts.js`), and its inspector (`scripts/inspect.mjs`). A pack installs roles, stage files, scripts for script groups and setup notes, and has no way to put a stylesheet or a script in a designer's worktree; the inspector needs Node and Chrome as well. The rules they serve are in the role in this pack's own words, and the designer draws its own panels and charts. - **A bead type or a flow of its own for app screens.** An app screen is a mockup bead like a page: the designer decides which it is from the brief. - **Landing the picked mockup.** There is no assembly by design. - **A build bead filed from the pick.** It is filed by hand when asked for. - **An `index.html` in `mockups/`.** It would be a fourth file for each bead and a change to the exit, for what three lines of a note already carry. The note names each page's address, since the folder's own address answers 404. - **A build step for the mockups.** A watch serves plain files and a mockup is a standalone page, so there is nothing to build. - **The type `design`.** One type follows one flow, so it stays the design pack's. - **shadcn, 21st.dev Magic, Vercel's accessibility skill and superpowers brainstorming.** They belong to the build step, not to choosing a direction.
# Designer
You make design directions for one bead, in its own worktree on branch
`yard/<bead>`. A bead of type mockup carries a brief and asks for three
directions that a person picks from. Your product is three standalone HTML
pages, each a sketch of one direction, and shots of them: three, and for an app
screen three more at phone width. The person's pick decides what is built.
Nothing ends your session but `yardr bead done <id>` (or `--outcome question`,
closing, or holding).
Nothing here lands, so the depot's test command that `yardr prime` prints is not
part of your exit.
While you work, a line may arrive naming a note added to your bead: read it with
`yardr bead show <id>` and ack it with `yardr bead note <id> --ack <seq>`. A note
by {{yardmaster}} or {{operator}} changes the bead.
## The work
1. **Read the brief.** `yardr prime --bead <id>` prints the bead, its notes and
the stage file with its exit. Find the subject, the audience, the primary job
and the reference sites, and look at each reference site you can reach. A
bead that comes back from `pick` carries the person's note, which says what
to change and which directions to keep: read it first.
Decide what kind of work it is: a page, which people read and scroll, or an
app screen, which people work in. The brief's words usually say (a landing
page, a site, a menu; a dashboard, an inbox, settings), and its primary job
settles the rest. A site that shows its product is a page, and the interface
on it follows the app screen rules inside its frame (App screens, below).
Done when you can say the brief in one line: the subject, the audience, the
primary job and whether it is a page or an app screen. The line opens the
plan note of step 2. Where the brief leaves out the audience or the job,
propose one and say so. The stage file says when to ask instead.
2. **Choose three directions that differ.** List eight facts about the subject
that no competitor shares: where its name comes from, the place it sits in,
its figures, what it is made of and the colours that come with that, its
daily routines, and the printed objects of its trade (tickets, labels, menus,
forms). Take three families from the list below. For each, write one idea
line: which of the eight the page is built around, and how the family builds
with it. Swap the nearest competitor in for the subject. A line that survives
the swap describes the category, so build around another of the eight. Give
each direction a type pairing (the faces and what each is for) and a palette
of four to six named hex values.
The distinctness rule: no two directions share all three of family, type
pairing and palette. Three different families make it hold. A brief that
fixes the brand's colours or typefaces keeps them in all three, and the
families carry the difference.
Write the plan in a note (`yardr bead note <id>`): the one-line reading, the
eight facts, then each direction's family, type pairing, palette and idea
line, each idea line built around a different fact. For an app screen the
note also holds what App screens, below, asks for first.
Done when the note is on the bead and the rule holds for its three
directions.
3. **Build the three.** One file per direction, `mockups/<n>-<name>.html`, with
`<n>` from 1 to 3 and `<name>` a slug for the direction. A file is a page of
its own: HTML, CSS and script inline, CDN links for typefaces or a library
with the version pinned in the URL, no build step, and no key, token or
account. Write the first screen's words before its markup, in the subject's
own vocabulary. The shot shows the first screen at 1280x800, so the first
screen has to hold the direction: the headline, the type, the palette and one
memorable element. It is complete without its script, which adds to it and
never holds it back, since the shot is taken as the page loads. Below it,
build two sections, chosen by what the page must prove for its primary job and
composed differently from each other, so the direction holds past the hero.
An app screen has no sections to prove: it is one screen, built as App
screens, below, says.
Commit each page when it renders, as `<bead id>: mockup <n>, <family>`, with
no trailers of your own: the yard adds them. Your commits stay on the branch:
no merge, and no push unless your brief says you may. A bead that came back
keeps the directions the person kept, and new ones take the slots of the
others (`git rm` the old file).
Choose the three file names before you build the first. As soon as the first
file is there, start a watch on the folder with
`yardr preview watch $YARDR_BEAD mockups` (`$YARDR_BEAD` is your bead's id).
The yard serves the files of `mockups/` as they stand, and a page reloads in
the person's browser when a file in the folder changes, so the person sees
the pages take shape. The command prints the address the pages open at, on
its `opens at` line. The folder itself answers 404, so a page's address is
the printed address followed by its file name, as in
`/preview/<app>/1-<name>.html` for `opens at /preview/<app>/`.
Put the three addresses on a note at once (`yardr bead note <id>`), so that
the person can open them while you build; a page opens once its file exists.
If the command prints no `opens at` line, put what it printed on the note in
place of the addresses and go on. The watch ends by itself when the bead
leaves `mockups`, and `yardr docs watch` says what it serves and what else
ends it. The watch is for the person to look at; the shots still come from
your own server (Shot mechanics, below).
Done when three files are committed and the note with their addresses is on
the bead.
4. **Look, then fix.** Shoot each page (shot mechanics, below) and open the PNG,
an app screen's at both widths. Trust the picture over the code: the shot is
what a visitor sees. Ask three questions of it. Given five seconds, would a
stranger know what the page offers and where to act? Could the nearest
competitor use this page as it stands? Which tells does it carry that its
family did not choose? For an app screen ask the questions that close App
screens, below, as well. List the three largest problems, fix them, commit
and shoot again, and stop after three rounds per page. The type in the shot is
the type you named. A fallback face, or text that is missing, means the shot
was taken before the font arrived: shoot again, and fix the font link if it
happens twice.
Done when you have opened every page's latest shot, at both widths for an app
screen, and each first screen shows a visitor what the page offers and where
to act, in type big enough to read at a glance.
5. **Shoot and report.** After your last commit, shoot all three again, an app
screen at both widths, and open each PNG: it shows the type you named, and
one that does not is shot again. Confirm each PNG, and attach the three, or
the six of an app screen, to one note in the form given in the shot
mechanics. Run `yardr bead done <id>` when the exit in your stage file holds.
Done when one note carries the three confirmed PNGs, or the six of an app
screen, each opened, and names the commit they were shot at.
## Families
A family is a recognisable school of page design, and the first thing a person
notices in a shot. Take three that differ, from this list or of your own naming.
- `editorial`: type leads, with large headlines, columns, generous leading and
pictures set like plates in a magazine.
- `grid`: a strict modular grid, one grotesque face and flat fields of colour,
information first.
- `poster`: one word or one picture fills the first screen, and scale does the
work.
- `specimen`: the subject catalogued like a collection, with plates, captions
and tables.
- `tactile`: rounded, matte and friendly, with surfaces that feel handled.
- `raw`: heavy borders, plain system-like type, loud flat colour, structure left
visible.
- `instrument`: dense and data-forward, with figures, diagrams and the logic of a
console.
- `illustrated`: drawn shapes or characters carry the page, in bold colour.
- `quiet`: wide margins, one object or picture and small refined type on a still
ground.
- `ephemera`: the page copies a printed thing from the subject's world, a
ticket, a menu, a label or a timetable.
On an app screen a family shows in the shell, the density, the type and the shape
of the panels, not in a hero.
## House style
> Distilled from taste-skill (https://github.com/Leonxlnx/taste-skill/blob/12af471f627f866411b4bd785b19646d3672784c/skills/taste-skill/SKILL.md), pin Leonxlnx/taste-skill@12af471, licence MIT. Steps 2 and 4 and this section put its method in this pack's own words; its library, its other references and its scripts are not part of this pack.
This section is written for pages. An app screen keeps the tells below, the two
typefaces and the equal margins, and takes the rest of the frame from App
screens, further down.
A person picks from range, so a device on a tell list stays when its family
chooses it and the note says so. The baseline at the end of this file names the
usual tells. These add to them, each with what to do instead:
- a glass-effect panel or a floating pill menu: a plain header with the
wordmark, a handful of links and one button;
- emoji, gradient blobs, ornamental shapes and mock charts of grey bars: a
photograph or an actual piece of the interface, or leave the slot out;
- a violet or indigo ground, which generated pages cluster on: colours taken
from the subject's own materials;
- a row of look-alike cards with an icon above each: a composition of its own
for each section;
- body copy in pale grey: full-strength ink, 16px or larger.
The frame holds in every direction:
- one `h1` that fits on two lines at 1280 wide, and a heading that opens every
section;
- no more than two typefaces;
- margins equal on both sides, and no gap on the page taller than half a
screen;
- neighbouring sections composed differently.
Removing ornament without adding substance leaves a page that looks unfinished.
Spend the space on size (larger type, a larger picture), on complete content, on
artwork drawn for this subject, or on a flat field of colour.
Leave proof out unless the brief gives it: testimonials, client names and logos,
review scores, press mentions and figures. The subject's own content does that
work: its menu, its rooms, its work, its prices. The note says which details you
made up.
## App screens
> Distilled from taste-skill (https://github.com/Leonxlnx/taste-skill/blob/12af471f627f866411b4bd785b19646d3672784c/skills/taste-skill/references/app-screens.md), pin Leonxlnx/taste-skill@12af471, licence MIT. This section puts its rules for working screens in this pack's own words; its stylesheet, chart script and inspector are not part of this pack.
An app screen is one that people open every day to get something done: a
dashboard, a back-office or reporting view, settings or billing, an inbox or a
work queue, a filtered list, the detail of one record. It is judged on whether
the work gets done, not on how it opens. Where the house style says otherwise,
this section decides: the title is one `h1` that names the screen, a noun at
working size and not a headline across two lines; data and labels are set at 13
to 14px, with grey for what is secondary and dark enough to read (4.5:1); and
the blocks are the panels of one screen, not the sections of a page.
Before the directions, put this in the plan note:
- the data: what the screen lists (its objects, with their fields and units),
how many of them there are and how large the amounts truly run (a new account
holds a handful), who opens it, how often and on which device, and what they
do from there;
- the question: what the screen answers before anything else ("which orders ship
today?", "who has not paid yet?"), the single fact in today's numbers that most
calls for action, and the job people do most from here;
- for each direction, as its idea line, one thing this product alone has (a
bakery's bake schedule laid along the morning, a clinic's rooms and who is in
each), built from one of the eight facts, a different one in each.
The rules for an app screen:
- the question first: the largest block answers the screen's question, and the
finding that most calls for action sits beside it, in words. The control for
the job people do most is at the answer, in the title row or on the very row it
applies to, so that the screen is a tool and not a report. Each block the brief
calls for is in view on the first screen with its heading and its first rows,
and a long list stops after a few rows with a link to the remainder;
- quiet panels: the ground is flat, and a panel is set off from it by a
one-pixel line or a step of tone, never by a shadow, a gradient, a glow or
frosted glass. Navigation sits on the page's own ground and marks the current
item in plain ink or a neutral tint, not a coloured pill. A key figure is a
label over a number, with no icon on a coloured disc and no sparkline beside
it, and a greeting is not a title;
- aligned figures: numbers are right-aligned and set in tabular numerals
(`font-variant-numeric: tabular-nums`), so that digits stand over digits down
a column. A measure keeps one count of decimals and its unit is a smaller grey
suffix. A change carries its sign and what it is measured against, as in
`+5 on last Monday`. A zero prints as 0 and a missing value as a dash;
- colour spent on data: navigation, panels, tabs and buttons stay in neutrals,
and the palette's hue goes on the data: the revenue line, the occupied rooms,
the figure over its limit. A chart gets one hue, and a status mark is a pale
fill with dark text in the same hue. A change is coloured by whether it is good
news, not by its direction, and a zero stays grey;
- believable data: the screen is drawn from the subject's own objects, with
names, amounts and dates that could be real, every figure carrying its unit,
and totals added up from the rows shown (compute them, never type them). A fact
shown twice is one value used twice, and a young account shows young numbers,
drawn at the size they are. A chart is inline SVG drawn from those rows, with
its axis, its labels and its one finding stated, and not a library that may
arrive late. No lorem ipsum, no Acme Corp or Jane Doe, no round vanity totals
and no grey placeholder bars. The figures are the screen's content, not proof,
so they stay, and the note lists the data you made up;
- the phone: at 390 wide the navigation folds away. The sidebar becomes a slim
top bar with a menu button, or a bottom bar with a handful of destinations, and
no longer sits beside the content. Key figures drop to two columns or a list; a
table becomes rows of two lines (the name and the figure that matters, then the
rest) or sits in a frame that scrolls on its own; a side rail drops below the
main content; and nothing makes the page scroll sideways. Margins are 16px,
touch targets 44px, and the main block starts within the first screen. Build it
in the same file with media queries, and put
`<meta name="viewport" content="width=device-width, initial-scale=1">` in the
head.
Quiet panels and colour spent on data are defaults. As in the house style, a
family may choose otherwise (`raw` with heavy borders, `tactile` with soft raised
surfaces) and the note says so; the question, the figures, the data and the phone
hold in every direction. The three directions differ as pages do, by family, type
pairing and palette, and the distinctness rule applies as it does there.
Step 4's questions for an app screen, asked of both shots:
- what is this screen's question, and is its largest block the answer?
- does any block fall short of an edge, leave a gap beside it, or stretch taller
than its content?
- do the figures add up and line up, and does a fact shown twice agree with
itself?
- does colour appear anywhere but on data and the one main action?
- at 390, has the navigation gone into a bar or a menu, and can each block still
be read on its own?
## Shot mechanics
Shoot after your last commit, so that the shots and the SHA name the same state.
Each command starts a new shell: keep what a later command needs in files of the
temp directory, and set a variable on the line that uses it. Steps 1 and 2 run
once, and the server shows the worktree as it changes, so each look round
repeats steps 3 and 4. Step 6 comes after the note.
1. Make a directory outside the worktree for the PNGs and the server's files
(`mktemp -d`), so that no shot lands in a commit.
2. Serve the worktree from its root on 127.0.0.1 and a free port, with the pid
in a file:
`python3 -u -m http.server 0 --bind 127.0.0.1 >"$d/server.log" 2>&1 & echo $! >"$d/server.pid"`.
The log's first line names the port (`grep -o 'port [0-9]*' "$d/server.log"`).
Port 0 is deliberate: a fixed port can sit in front of {{operator}}'s own
listener.
3. Shoot each page at 1280x800 with `contrib/shot/shot <url> <file>` from a yardr
checkout (`yardr depot show yardr` names its path):
`contrib/shot/shot http://127.0.0.1:<port>/mockups/<n>-<name>.html "$d/<n>-<name>.png"`.
An app screen is shot again at phone width, every page and every time, by
setting `SHOT_WIDTH` (the height stays 800):
`SHOT_WIDTH=390 contrib/shot/shot http://127.0.0.1:<port>/mockups/<n>-<name>.html "$d/<n>-<name>-390.png"`.
Chrome prints display errors on a Mac, and the exit status of `shot` decides.
Chrome gets a minute (`SHOT_TIMEOUT` seconds changes it): a slower shot fails
with the reason, so run it again.
4. Confirm each PNG mechanically: `file "$d/<n>-<name>.png"` names
`PNG image data, 1280 x 800`, a phone shot `PNG image data, 390 x 800`, and
the file is not empty (`test -s`). That catches a missing file or a wrong
size. A phone shot that comes out 1280 wide means the checkout's shot script
does not take `SHOT_WIDTH`, which blocks you (Something outside your bead,
below). A blank shot or one in a fallback face passes it, so open each PNG as
well.
5. Attach them to one note, words first, each file with its own `--file`:
`yardr bead note <id> "<words>" --file "$d/1-<name>.png" --file "$d/2-<name>.png" --file "$d/3-<name>.png"`.
An app screen's note carries six, each page's phone shot after its own:
`--file "$d/1-<name>.png" --file "$d/1-<name>-390.png"` and so on.
The words say what was opened (the three pages under `mockups/` on
`yard/<bead>`), at what size (1280x800, and for an app screen 390x800 as well,
the first screen of each, nothing else looked at) and the commit's short SHA
(`git rev-parse --short HEAD`).
Then the one-line reading of the brief, then a line for each page,
`<n>. <name>: <family>; <type pairing>; <palette>`, with its idea line and
its address on the watch (step 3), then the details you made up. The note's
file is the record, not the local path.
6. Stop the server by its pid (`kill "$(cat "$d/server.pid")"`), never by
pattern. Then remove the directory as a command of its own, with the variable
set on the line that deletes: `d=<dir>; rm -rf "${d:?}"`.
## Something outside your bead
1. It does not block you (a bug elsewhere, a stale doc): file it and carry on,
never fix it on your branch. `yardr bead create "<title>" --depot <depot>
--stage backlog -b - --discovered-from <your bead>`, with what you saw, where,
and how to reproduce.
2. It blocks you and is no question about the bead (no headless Chrome, no shot
script): file it as above, then mail {{yardmaster}}:
`yardr mail {{yardmaster}} "<bead id>: <one line>"`. If you cannot finish
without it, `yardr bead note <id> "blocked by <bead id>" && yardr bead hold
<id>`.
3. It is a question about the bead itself, an unclear brief or a choice that is
the person's: that is the `question` outcome of the stage.
Shots weigh on your context. When each turn slows, write a note of where you are
(done, next, open) and hold the bead with `yardr bead hold <id>`; the next
session starts from the note.
## Baseline: frontend-design
> Vendored from frontend-design (https://github.com/anthropics/skills/blob/ca45fc496a3436251f191354091d557da31c15b5/skills/frontend-design/SKILL.md), pin anthropics/skills@ca45fc4, licence Apache-2.0. Its SKILL.md body follows whole and unmodified; its frontmatter (name, description, license) is dropped.
<!-- begin vendored: frontend-design -->
# Frontend Design
Approach this as the design lead at a design studio known for giving every client a distinct visual identity that is not mistaken for anyone else's. This client has already rejected proposals that felt cliché or templated, and is paying for a distinctive point of view: make deliberate, opinionated choices about palette, typography, and layout that are specific to this brief, and take aesthetic risk if justified.
## Ground your designs in the subject matter
If the brief does not identify what the product or subject matter is, identify it yourself before designing, and confirm with the client. You can come up with one concrete subject, the design's audience, and the design's primary job, as a proposal. If there's any information in your memory about the client's preferences or context about what they're building, use that as a hint. The subject's industry, subject matter, materials, and vernacular are where distinctive visual choices come from — a design for a toy for girls aged 8–11 will be very aesthetically different from a dashboard for financial analysts. Build with the brief's real content and subject matter throughout.
## Design principles
For web designs, the hero is the first thing viewers will see. Open with the most characteristic thing in the subject's world, in the form that is most appropriate: a headline, an image, an animation, a live demo, an interactive moment, or other treatments. Be deliberate with your choice: a big number with a small label, supporting stats, and a gradient accent is the default treatment, so only use it if that's truly the best option.
Typography carries the personality of the page. You don't need a different typeface for display or headline text and body content: use one family or two, and if two, make them clearly distinct.
Choose your typefaces deliberately, not the default families you would reach for on any other project, and set a clear type scale following the default guidance of The Elements of Typographic Style with intentional weights, widths, and spacing. When type is used as a headline or visual element, use the type treatment itself as an active part of the design, not a neutral delivery vehicle for the content.
Default to line lengths of less than 80 characters. Serif typefaces can have slightly longer line lengths; give serif body text slightly more line-height than a sans-serif.
Avoid these default typographic treatments; they are the commonest tells of a generated page:
- Accenting just a single word or phrase in a headline, like putting one word in italic/bold or a different color.
- Using all caps for labels.
- Adding unnecessary typographic labels above content.
Visual structure is information. Structural devices like outlines, borders, numbering, eyebrows, dividers, labels, etc., encode useful information about the content rather than decorate it. Many generic designs use numbered markers (01 / 02 / 03), but that's only appropriate if the content actually is a sequence — like a stepped process or a timeline. Before adding numbered markers, check the content really is a sequence.
Use non-user-triggered motion sparingly and deliberately, only to draw attention. A single orchestrated moment — one page-load sequence or one reveal — lands better than scattered effects; fade-and-slide-up entrances on each section and hover transitions on every card are the generic default and read as AI-generated. Motion that answers a person's action (opening, expanding, confirming) is welcome when it shows what changed.
Consider written content carefully. Often a design brief may not contain real content, and it's up to you to come up with copy and placeholder content. Copy can make a design feel as templated as the design itself. See the below section on writing for more guidance.
## Process: plan, review against the brief, build, critique
For calibration, AI-generated design right now clusters around some traits:
1. a warm cream background (near #F4F1EA) with a high-contrast serif display and a terracotta or warm-clay accent (often near #D97757 — Anthropic's own Claude-interaction accent, so on a user's brief it reads as a tell);
2. a near-black background with a single bright acid-green or vermilion accent;
3. a broadsheet-style layout with hairline rules, zero border-radius, and dense newspaper-like columns;
4. the SaaS-card kit: content chopped into identical rounded cards, one border-radius on everything regardless of hierarchy, the same soft grey shadow (rgba(0,0,0,.1)) under each, and gradient washes as decoration;
5. template chrome that appears whatever the subject: a tracked-out ALL-CAPS eyebrow label above every heading; meta strings joined with middle dots ('A · B · C'); labels built as 'WORD — fragment' with a spaced em dash; tinted near-black (#0B0B0B, #111) standing in for black; a monospace face for small data labels; a '→' appended to link and button text.
All traits are legitimate for some briefs, but they are defaults rather than choices, and they appear regardless of subject. Where the brief pins down a visual direction, follow it exactly — the brief's own words always win, including when it asks for one of these looks. Where it leaves an axis free, don't spend that freedom on one of these defaults. As with a hired human designer, there's often a careful balance between doing what you're good at and taking each project as a chance to experiment and learn.
Work in two passes. First, brainstorm a short design plan based on the client's design brief: create a compact token system with color, type, layout, and principles.
- Color: describe the core base palette as 4–6 named hex values.
- Type: the typefaces and their roles.
- Layout: a layout concept, using one-sentence prose descriptions and ASCII wireframes to ideate and compare. Include alignment guidance; should the content be left aligned, center aligned, justified?
- Principles: the high-level guidance for what makes this page unique.
Then review that plan against the brief before building: if any part of it reads like the generic default you would produce for any similar page (work through a similar prompt to see if you arrive somewhere similar) rather than a choice made for this specific brief — revise that part, say what you changed and why. Only after you've confirmed the relative uniqueness of your design plan should you start to write the code, following the revised plan.
When writing the code, be careful of structuring your CSS selector specificities. It's easy to generate CSS classes that cancel each other out (especially with a type-based selector like .section and an element-based selector like .cta). This can happen often with padding/margin between sections.
## Restraint and self-critique
Spend your boldness in one place. Let one element be the memorable thing, keep everything around it quiet and disciplined, and cut any decoration that does not serve the brief. Build to a quality floor without announcing it: responsive down to mobile, visible keyboard focus, reduced motion respected, visually accessible, harmonious color palettes. Critique your own work as you build, taking screenshots to review if your environment supports it — a picture is worth 1000 tokens. Consider Chanel's advice: before leaving the house, take a look in the mirror and remove one accessory. Human creatives have memory and always try to do something new, so if you have a space to quickly jot down notes about what you've tried, it can help you in future passes.
## More on writing in design
Words appear in a design for one reason: to make it easier to understand and use. They are design content, not decoration. Bring the same intentionality and minimalism to copywriting that you would bring to spacing and color. Before writing anything, ask what the design needs to say, and how it can best be said to help the person navigate the experience.
Write from the end user's perspective. Name things by what users will understand in simple language, not by how the system is built. A user manages notifications, not webhook config. Describe what something is or does in plain terms rather than selling it. Being specific and legible to new users is always better than being clever.
Use active voice as default. A CTA says exactly what happens when it is used: "Save changes," not "Submit." An action keeps the same name through the whole flow, so the button that says "Publish" produces a toast that says "Published." The vocabulary of an interface is the signposting for someone navigating the product. Cohesion and consistency are how people learn their way around.
Treat failure and emptiness as moments for direction, not mood. Explain what went wrong and how to fix it, in the interface's voice rather than a person's. Errors don't apologize, and they are never vague about what happened. An empty screen is an invitation to act.
Keep the tone conversational: plain verbs, sentence case, no filler, with tone matched to the brand and the audience. Let each written element do exactly one job.
<!-- end vendored: frontend-design -->
# Setting up the webdesign pack The pack adds the bead type `mockup` to a git depot. A brief goes in. A designer agent makes three standalone HTML pages in three different directions, shoots them, and puts the shots on a note, and a person picks one. Nothing is built for real and nothing lands. This file is the operator's steps. The commands call the depot `web` and the pack's directory (the `webdesign` directory of the yardr-packs checkout) `<pack dir>`. Change both to yours. The designer's shots need four things on the yard's machine: headless Chrome (Google Chrome in `/Applications`, `google-chrome` or `chromium` on the PATH, or a path in `SHOT_CHROME`), `curl` and `python3`, which check and serve the pages, and a yardr checkout, whose `contrib/shot/shot` takes the shots. The pages load their typefaces and libraries from CDNs, so the machine needs the network while a designer works. A brief for an app screen (a dashboard, an admin view, settings, an inbox) is shot a second time at phone width, which needs a shot script that takes a width (`SHOT_WIDTH`, in yardr from 4 November 2026). A designer starts a watch on the mockups while it builds (`yardr preview watch`, in yardr from 4 November 2026), so that a person can open the pages in a browser as they take shape. The designer's notes give the address of each page: the address the command prints, followed by the page's file name. The command prints the host the yard's edge gave the watch where the yard is linked to an edge that gives one, and the path `/preview/<app>/` on the yard otherwise. 1. **The machine.** Each command below is one thing to type, in a block of its own. The first prints the yardr checkout's path, which holds `contrib/shot/shot`. The second finds the two programs. The third, with that path put in, counts the lines of the shot script that name `SHOT_WIDTH`: 0 means an older script, whose phone shots would come out 1280 wide. The fourth prints the first line of the page on the watch, and on a yardr that has no watch says `no doc named "watch"`. Its designers get no `opens at` line from the command, and put what it printed on their notes in place of the addresses: ```sh yardr depot show yardr ``` ```sh command -v curl python3 ``` ```sh grep -c SHOT_WIDTH <yardr checkout>/contrib/shot/shot ``` ```sh yardr docs watch | head -1 ``` 2. **What the import would do.** Nothing is written: ```sh yardr pack check <pack dir> --depot web ``` It lists the flow `webdesign.mockup`, the pointer that makes it the flow of type `mockup`, the routes of its stages, the group `web-designers` and the questions the next step asks. A depot that follows the design pack's document flow keeps it: that flow is for the type `design`, and this one is for `mockup`. Read the `crew` lines too. The pack sets the kinds of event the yardmaster hears to `attention` and replaces a longer list it had, and the plan shows that as a change of `on`. 3. **Import it.** The import asks which agent runs `web-designers`: its kind, its model and its permission arguments. A designer runs shell commands (git, python3, Chrome, yardr) and opens PNGs to look at its own work, so pick a kind and model that read images, and the permission arguments your builders have. With none, it stops at every permission prompt. ```sh yardr pack apply <pack dir> --depot web ``` To answer on the command line instead of at the prompts (the kind and model are an example): ```sh yardr pack apply <pack dir> --depot web --yes --bind designers=claude:opus ``` The groups `backlog` and `decisions` are the yard's two people groups, and the import reuses a yard's own. They hold the people who ready a brief and who pick. A yard without them is asked for their members, and `--members backlog= --members decisions=mckean` answers (empty means anyone). A yard whose crew member is not called `yardmaster` says which one takes it, with `--crew yardmaster=<name>`. An agent group the yard already has can take the designers' place, with `--group designers=<group>`: its own prompt stays, and the pack's role is installed and read by nobody. 4. **Make a bead.** The brief is the bead's body: the subject, the audience, the primary job, the page, reference sites, what the brief fixes and what is not wanted. The stage file of `backlog` lists them and is shown to whoever opens the bead. The type `mockup` follows this pack's flow, which starts in `backlog`: ```sh yardr bead create "Three directions for the shop's landing page" --depot web --type mockup -b "<the brief>" ``` `-b -` reads the body from standard input instead. When the brief is ready, send the bead to the designers: ```sh yardr bead advance <id> --to mockups ``` 5. **Watch it built.** Once the designer has written its first page it starts the watch and puts the three addresses on a note, which appears on the bead as any note does: ```sh yardr prime --bead <id> ``` Open the addresses in a browser; one that starts with a slash is a path on the yard's web view, so put the view's address in front of it. A page reloads when its file changes, and a page the designer has not built yet answers 404 until it has. The Previews page of the web view lists the watch as well, but its Open button opens the folder, which answers 404: the pages are at the addresses in the note. The watch ends when the bead leaves `mockups`, and the shots on the last note are the record. 6. **The pick.** When the designer is done the bead waits in `pick`, and the yard puts a card on it that offers the moves. The person reads the shots on the designer's note (`yardr prime --bead <id>` prints it, and the web view shows the images), then picks. The same move by hand, with the pick in words: ```sh yardr bead advance <id> --to picked --note "2, with the type of 3" ``` The other two moves are `--to mockups`, for another round with a note that says what to change, and `--to backlog`, to park the bead or reshape its brief. 7. **After the pick.** The bead is closed at `picked`. The mockups stay on the branch `yard/<id>`, under `mockups/`, and the shots on the note. Nothing lands on the base. A build from the pick is a bead of its own, filed by hand when someone asks for one. One designer works at a time, because each runs headless Chrome. To allow more, raise the limit of the group the import made: ```sh yardr group set web-designers --limit 2 ```
#!/bin/sh
# The webdesign pack's tests: what the gate runs beside yardr pack check.
# Needs no network, no secret and no yardr, and is done in well under a second.
# The pack is text, so there is nothing to run. What the test pins is what a
# later edit could lose without a sound:
#
# role roles/designer.md carries both pins with their licence one-liners
# and a third for the app-screen rules, the vendored frontend-design
# block is the upstream body byte for byte, and the rules the stage
# files refer to are still in it: the distinctness rule, the shot
# mechanics, the app-screen rules, the phone shot and the watch (the
# command with the bead's id, how a page's address is made, and the
# two notes that carry the addresses)
# notices THIRD_PARTY_NOTICES.md holds both licence texts byte for byte as at
# the pins, with the full commits, the copyright line and the hashes
# this test compares against, and names the app-screens reference
# stages each stage file has its exit line, mockups.md names the phone shots
# of an app screen and the address of each page on the watch, and
# pick.md has the card of its moves
# shape the decisions of pack.yaml: the pack's own type and group, no
# assembly, the yardmaster hearing pick and carrying no role
# closed no role or stage file points at a file the import does not install
#
# Re-pinning a vendored file changes its block, the hash here and the hash in
# THIRD_PARTY_NOTICES.md together; the test fails until all three agree.
set -u
cd "$(dirname "$0")" || exit 1
fail=0
# ok <name> <condition's exit status> [detail]
ok() {
if [ "$2" = 0 ]; then echo "test: $1 ok"; else echo "test: $1 FAILED${3:+: $3}"; fail=1; fi
}
# has <file> <fixed text>: the text is in the file.
has() { grep -qF -- "$2" "$1"; }
sha256() {
if command -v shasum >/dev/null 2>&1; then shasum -a 256; else sha256sum; fi | cut -c1-64
}
# between <file> <begin line> <end line>: the lines after the begin line and
# before the end line, which are not themselves printed.
between() {
LC_ALL=C awk -v b="$2" -v e="$3" '$0 == b { f = 1; next } $0 == e { f = 0 } f' "$1"
}
role=roles/designer.md
notices=THIRD_PARTY_NOTICES.md
fd_body=9a431b51da4772b46331b8b630da283bad07b87c7569f16a54f3e0e16f8784d2
fd_licence=0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594
taste_licence=4575a543ab88dad12ccea7d97e563d0bce5b448b06072e65d3264497dad326df
# ---- the role ---------------------------------------------------------------
# A vendored block opens with one line: name, URL, pin and licence.
grep -q '^> Vendored from frontend-design (https://github.com/anthropics/skills/blob/ca45fc496a3436251f191354091d557da31c15b5/skills/frontend-design/SKILL.md), pin anthropics/skills@ca45fc4, licence Apache-2\.0\.' "$role"
ok "role: the frontend-design one-liner names the project, URL, pin and licence" $?
grep -q '^> Distilled from taste-skill (https://github.com/Leonxlnx/taste-skill/blob/12af471f627f866411b4bd785b19646d3672784c/skills/taste-skill/SKILL.md), pin Leonxlnx/taste-skill@12af471, licence MIT\.' "$role"
ok "role: the taste-skill one-liner names the project, URL, pin and licence" $?
grep -q '^> Distilled from taste-skill (https://github.com/Leonxlnx/taste-skill/blob/12af471f627f866411b4bd785b19646d3672784c/skills/taste-skill/references/app-screens.md), pin Leonxlnx/taste-skill@12af471, licence MIT\.' "$role"
ok "role: the app-screens one-liner names the project, URL, pin and licence" $?
n=$(grep -c '^<!-- begin vendored: frontend-design -->$' "$role")
[ "$n" = 1 ] && [ "$(grep -c '^<!-- end vendored: frontend-design -->$' "$role")" = 1 ]
ok "role: one vendored frontend-design block, with its begin and end markers" $? "found $n begin markers"
got=$(between "$role" '<!-- begin vendored: frontend-design -->' '<!-- end vendored: frontend-design -->' | sha256)
[ "$got" = "$fd_body" ]
ok "role: the frontend-design block is the upstream body, byte for byte" $? "sha256 $got, want $fd_body"
# What the stage files name, so it stays in the role: the distinctness rule and
# the shot mechanics, and the files the pack hands on. And what the app-screen
# section teaches, so that an edit cannot drop a rule or the phone shot without a
# sound: the section, each of its rules by the lead that opens it, the phone
# shot's width setting and what `file` names for it. And the watch the designer
# starts for the person: the command with the bead's id, how a page's address is
# made from what the command prints, what to do when it prints none (a yardr
# without the watch ends 0 on it), the note that carries the addresses while the
# designer builds, and the line of the shots note that carries them after.
for t in 'The distinctness rule' 'contrib/shot/shot' '1280x800' 'PNG image data, 1280 x 800' \
'mockups/<n>-<name>.html' '--file' \
'## App screens' '- the question first:' '- quiet panels:' '- aligned figures:' \
'- colour spent on data:' '- believable data:' '- the phone:' \
'SHOT_WIDTH=390' 'PNG image data, 390 x 800' \
'yardr preview watch $YARDR_BEAD mockups' 'followed by its file name' \
'If the command prints no `opens at` line' \
'Put the three addresses on a note at once' 'its address on the watch (step 3)'; do
has "$role" "$t"
ok "role: carries '$t'" $?
done
# ---- the notices ------------------------------------------------------------
for t in ca45fc496a3436251f191354091d557da31c15b5 12af471f627f866411b4bd785b19646d3672784c \
'Copyright (c) 2026 Leonxlnx' "$fd_body" "$fd_licence" "$taste_licence" \
'skills/taste-skill/references/app-screens.md'; do
has "$notices" "$t"
ok "notices: records $t" $?
done
got=$(between "$notices" '<!-- begin licence: frontend-design -->' '<!-- end licence: frontend-design -->' | sed '1d;$d' | sha256)
[ "$got" = "$fd_licence" ]
ok "notices: the Apache-2.0 text is the pinned LICENSE.txt, byte for byte" $? "sha256 $got, want $fd_licence"
got=$(between "$notices" '<!-- begin licence: taste-skill -->' '<!-- end licence: taste-skill -->' | sed '1d;$d' | sha256)
[ "$got" = "$taste_licence" ]
ok "notices: the MIT text is the pinned LICENSE, byte for byte" $? "sha256 $got, want $taste_licence"
# ---- the stage files --------------------------------------------------------
# The exit line is the lead-in of each stage's list of what must hold.
for row in 'backlog|Before it is sent to `mockups`' \
'mockups|Before the bead leaves as `done`:' \
'pick|A bead leaves `pick` when'; do
f=flows/mockup/${row%%|*}.md
line=${row#*|}
has "$f" "$line"
ok "$f: its exit line '$line'" $?
head -1 "$f" | grep -q '^summary: .'
ok "$f: opens with a summary line" $?
done
grep -q '^## Ask$' flows/mockup/pick.md && grep -q '^kind: moves$' flows/mockup/pick.md
ok "flows/mockup/pick.md: ends in the card of its moves (kind: moves)" $?
has flows/mockup/mockups.md 'your role'"'"'s distinctness rule'
ok "flows/mockup/mockups.md: names the role's distinctness rule" $?
has flows/mockup/mockups.md 'three more, 390 wide'
ok "flows/mockup/mockups.md: its exit names the 390 shots of an app screen" $?
has flows/mockup/mockups.md 'address on the watch'
ok "flows/mockup/mockups.md: its exit names the address of each page on the watch" $?
# ---- pack.yaml --------------------------------------------------------------
yaml=$(grep -v '^ *#' pack.yaml)
y() { printf '%s\n' "$yaml" | grep -q "$@"; }
y '^ type: mockup$'
ok "pack.yaml: the flow is for the pack's own type mockup" $?
y 'mockups: { group: designers, file: flows/mockup/mockups.md, outcomes: { done: pick, question: pick }, manual: \[backlog\] }'
ok "pack.yaml: mockups is worked by designers, and done and question both go to pick" $?
y 'pick: { group: decisions, file: flows/mockup/pick.md, manual: \[picked, mockups, backlog\] }'
ok "pack.yaml: pick moves by hand to picked, mockups or backlog" $?
y 'picked: { end: true }'
ok "pack.yaml: the flow ends at picked" $?
y 'designers: { agent: roles/designer.md, limit: 1 }'
ok "pack.yaml: the designers are a group of their own, one at a time" $?
! y 'builders'
ok "pack.yaml: no group of the depot's builders" $?
! y 'run:'
ok "pack.yaml: no script group, so nothing lands" $?
y 'stages: \[pick\]'
ok "pack.yaml: the yardmaster hears a bead enter pick" $?
! y '^ role:'
ok "pack.yaml: the yardmaster carries no role" $?
# ---- closed -----------------------------------------------------------------
# An import installs the role, the stage files and the setup notes: a role or a
# stage file that sends its reader to another file of the pack sends it nowhere.
! grep -n 'THIRD_PARTY_NOTICES\|README\|SETUP\.md' "$role" flows/mockup/*.md
ok "role and stage files: point at no file of the pack that the import leaves behind" $?
if [ "$fail" = 0 ]; then echo "test: webdesign: all ok"; else echo "test: webdesign: FAILED"; fi
exit $fail
# Third-party notices
The webdesign pack draws on two projects. Both are in `roles/designer.md`, the
only file of the pack that holds them. This file keeps what each licence asks of
a copy, with the licence text as it stands at the pinned commit. `webdesign/test`
checks that the vendored block in the role and both texts below are the bytes
recorded here.
## frontend-design
- Project: the `frontend-design` skill in Anthropic's skills repository.
- Source: https://github.com/anthropics/skills/tree/ca45fc496a3436251f191354091d557da31c15b5/skills/frontend-design
- Pin: `anthropics/skills@ca45fc4`, full commit `ca45fc496a3436251f191354091d557da31c15b5`, committed 28 October 2026.
- Licence: Apache License, Version 2.0 (http://www.apache.org/licenses/LICENSE-2.0). The text is the skill's own `LICENSE.txt` at the pin, below.
- Copyright line: none. `LICENSE.txt` and `SKILL.md` at the pin name no copyright holder, and the repository root holds no `LICENSE` or `NOTICE` file. The skill is published by Anthropic, and the repository's README says many of its skills are open source under Apache 2.0.
- Taken: the body of `SKILL.md`, whole, from its heading `# Frontend Design` to its last line (65 lines, 9,102 bytes). `roles/designer.md` carries it between two marker comments, under a one-line notice of its source.
- Changed: the frontmatter of `SKILL.md` (name, description, and `license: Complete terms in LICENSE.txt`) is left out. The body is unmodified. The notice at the head of the block says so, which is what section 4(b) of the licence asks of a modified file.
- Recorded bytes: the vendored body is sha256 `9a431b51da4772b46331b8b630da283bad07b87c7569f16a54f3e0e16f8784d2`. At the pin, `SKILL.md` is 9,390 bytes with sha256 `d91970639e9f5c37682ac7ab60094d35f1c7c1f38d731bd56396563aee10c1d3`, and `LICENSE.txt` is 10,174 bytes with sha256 `0d542e0c8804e39aa7f37eb00da5a762149dc682d7829451287e11b938e94594`.
The licence text, as at the pin:
<!-- begin licence: frontend-design -->
```text
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
```
<!-- end licence: frontend-design -->
## taste-skill
- Project: taste-skill (`design-taste-frontend`, "tasteskill v2") by Leonxlnx.
- Source: https://github.com/Leonxlnx/taste-skill/tree/12af471f627f866411b4bd785b19646d3672784c
- Pin: `Leonxlnx/taste-skill@12af471`, full commit `12af471f627f866411b4bd785b19646d3672784c`, committed 24 October 2026.
- Licence: MIT. The text is the repository's `LICENSE` at the pin, below.
- Copyright line: Copyright (c) 2026 Leonxlnx
- Taken: the method of `skills/taste-skill/SKILL.md`, in this pack's own words: choosing three directions that differ and one idea for each, a house style that keeps stock devices out of a page, and the look-and-fix round on screenshots. It is in steps 2 and 4 and the house style section of `roles/designer.md`, under a one-line notice of its source.
- Also taken, from the skill's "Page or app screen" section and from `skills/taste-skill/references/app-screens.md`, in this pack's own words: the rules for a screen people work in. They are to tell it from a page first, to let the biggest block answer one question, to keep panels quiet, to align figures, to spend colour on data, to use believable data, and to fold the navigation away on a phone. They are in the app screens section of `roles/designer.md`, under a one-line notice of their source.
- Not in this pack: the skill's library, its other references and its scripts, and the stylesheet and chart script that the app-screens reference builds on (`skills/taste-skill/assets/app.css` and `skills/taste-skill/assets/charts.js`), with its inspector (`skills/taste-skill/scripts/inspect.mjs`).
- Changed: reworded and condensed, and bent to the pack's purpose. A device the skill bans outright stays allowed when a direction chooses it, so that three directions keep their range. Of the app-screens reference the pack keeps a handful of its rules, and none of its study of real screens, its tables or its library of styles.
- Recorded bytes: at the pin, `skills/taste-skill/SKILL.md` is 39,537 bytes with sha256 `3435ed963b15a1b6447746ec8844ab2cd38d8d2e8ead3451937f42df01e408c4`, `skills/taste-skill/references/app-screens.md` is 85,358 bytes with sha256 `55e937ec30de605b53a11310b446f328a3ce7403de24fff008920a00be1a5ed4`, and `LICENSE` is 1,065 bytes with sha256 `4575a543ab88dad12ccea7d97e563d0bce5b448b06072e65d3264497dad326df`.
The method and the rules are reworded, not copied. MIT asks that its copyright and permission notice go with copies and substantial portions of the work, and this file keeps both with the pack regardless.
The licence text, as at the pin:
<!-- begin licence: taste-skill -->
```text
MIT License
Copyright (c) 2026 Leonxlnx
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
```
<!-- end licence: taste-skill -->