The few changes that clear the most. Most failures on most sites are one template line repeated on every page.
Ordered by how much each change clears per minute it takes. Where the same element repeats on every page it is priced as one template change, because that is what it is.
| # | Change | Who | Clears | Effort | Running total |
|---|---|---|---|---|---|
| 1 | Write alt text for images that have none 11 instances on 4 pages, 11 already written |
Content | 15% | 10 minutes | 15% |
| 2 | Give every link an accessible name 4 instances on 4 pages, 4 already written |
Content | 6% | 5 minutes | 21% |
| 3 | Replace placeholder alt text 1 instance on 1 page, 1 already written |
Content | 1% | 2 minutes | 23% |
| 4 | Replace alt text that is just the file name 1 instance on 1 page, 1 already written |
Content | 1% | 2 minutes | 24% |
| 5 | Title every embedded frame 1 instance on 1 page |
Content | 1% | 2 minutes | 25% |
| 6 | Fix the <head> of the page template 17 instances on 4 pages |
Developer | 16% | 25 minutes | 42% |
| 7 | Write titles and descriptions for every page template 9 instances on 4 pages, 9 already written |
Content | 8% | 12 minutes | 49% |
| 8 | Control is labelled only by its placeholder ("Your name"), which vanishes on input and is not a reliable accessible name 5 instances on 1 page, 5 already written |
Developer | 7% | 15 minutes | 56% |
| 9 | Label every form field 2 instances on 1 page, 2 already written |
Developer | 3% | 6 minutes | 59% |
| 10 | Give every button a name 1 instance on 1 page |
Developer | 1% | 4 minutes | 61% |
| 11 | Link returns 404 2 instances on 2 pages |
Developer | 3% | 10 minutes | 63% |
| 12 | Rewrite links that say "click here" or similar 1 instance on 1 page, 1 already written |
Content | 1% | 2 minutes | 64% |
| 13 | Fix skipped heading levels 3 instances on 3 pages |
Content | 2% | 9 minutes | 66% |
| 14 | Fix the stylesheet 19 instances on 4 pages, 4 already written |
Developer | 27% | 2.5 hours | 92% |
| 15 | Mark header cells in data tables 1 instance on 1 page |
Developer | 1% | 10 minutes | 94% |
| 16 | Fix how images are written into the page 4 instances on 4 pages |
Developer | 2% | 20 minutes | 96% |
| 17 | Fix the page layout template 4 instances on 4 pages |
Developer | 2% | 30 minutes | 98% |
| 18 | Replace the heavy image files 1 instance on 1 page |
Developer | 1% | 15 minutes | 99% |
| 19 | Main content is about 97 words once rendered 2 instances on 2 pages |
Content | 1% | 40 minutes | 100% |
The one-page version for whoever signs this off is in start-here/2-executive-summary.md.
None of this needs code. Where we could write the fix, it is shown in green. The full list is in for-your-content-team/ as CSV.
Grouped by where the fix lives. Ready-made files are in for-your-developer/: server config, optimised images, markup edits, link redirects.
Measured on the rendered page. Each entry is one colour pair, so one CSS change clears every instance.
The same data is in apply-with-ai/fixes.json if you would rather script it. We audited rendered pages and have never seen your source, so selectors point at what the browser received; the prompt tells the agent to search for where that comes from.
# Apply the Curbcut accessibility fixes for curbcuthq.com You are working in the repository that produces **curbcuthq.com**. An external audit found **54 accessibility failures** and **30 warnings** across 4 pages, plus 5 SEO and security errors, and wrote a replacement for each one it could. Your job is to apply them to the source — not to re-audit the site and not to write new copy. The accessibility failures are WCAG 2.1 Level A and AA, the standard that accessibility law in most jurisdictions measures against. Which law applies to this site, if any, is set out in start-here/4-which-law-applies.md; nothing here is legal advice. ## Rules 1. **Never invent content.** Every replacement below was written from the live page. Use it as given. Where a fix says UNKNOWN or is blank, leave the element alone and list it at the end for a human — do not guess. 2. **Find the source, do not create it.** These selectors come from rendered HTML. The real source may be a component, a template, a partial, a CMS field, or a build step. Search the repository for the surrounding text, class name, or file name. If you cannot find where something is generated, say so and move on — do not create a new file to hold it. 3. **One concern per commit.** Group changes by fix type (alt text, then labels, then headers), not by file. It makes review possible and a bad batch revertible. 4. **Do not reformat.** Match the surrounding indentation, quote style, and framework idiom. A diff full of unrelated whitespace hides the actual change. 5. **Server config is not code.** The header rules belong in the hosting config for this project. Identify which platform this repo deploys to and apply only that file. If you cannot tell, ask rather than applying all of them. 6. **Report what you could not do.** A short list of skipped items is far more useful than silent partial application. 7. **Confidence tags.** Items marked *(confirm)* were written by a model or inferred from size. Apply them, then list them at the end for a person to read in context; do not treat them as final. Untagged items are deterministic and safe to apply as given. ## Plan of attack **Where these live** — The stack isn't identified, so start by reading the repository root to work out the framework and templating language before touching anything. In most setups, the `<head>` work behind section 2, section 3 and much of section 7 sits in a single shared layout or document template, or in a per-route metadata export; search for the file that renders `<html>` and `<meta name="viewport">`. Section 4's form fields and section 6's embedded frame usually live in a contact or booking component. Section 1 and section 5 are content-level: the images and links are spread across page templates, partials, and possibly CMS or Markdown content, so search for `<img` and `<a` across both code and content directories. The contrast, focus and reflow items in section 7 belong in the global stylesheet or design-token file. Section 9's optimised images replace existing assets wherever static files are served from. **Order** — Do section 7 first: the `<head>` and stylesheet changes there are template-level and clear findings on all four pages at once. Then section 2 and section 3, which are the same template element filled per page. Then section 4, section 6 and section 5, which are contained to a small number of components. Section 1 and section 9 next, since alt text is per-image and slow. Section 8 last, as it needs judgement rather than mechanical edits. **Watch out for** — The 404 links noted in section 8 may be Vercel rewrites or redirects rather than broken markup, so check any `vercel.json` or routing config before rewriting hrefs. Don't fix the placeholder-as-label problem by deleting placeholders outright. And confirm the optimised images in section 9 match the dimensions and formats the existing markup requests. ## 1. Image alt text 9 images need descriptive alt text. Find each image in the source and set exactly this text: - **logo.png** - page: https://curbcuthq.com/demo/index.html - selector: `img[src$="logo.png"]` - set alt to: `Home` - **logo.png** - page: https://curbcuthq.com/demo/menu.html - selector: `img[src$="logo.png"]` - set alt to: `Home` - **logo.png** - page: https://curbcuthq.com/demo/about.html - selector: `img[src$="logo.png"]` - set alt to: `Home` - **logo.png** - page: https://curbcuthq.com/demo/order.html - selector: `img[src$="logo.png"]` - set alt to: `Home` - **hours.png** - page: https://curbcuthq.com/demo/index.html - selector: `img[src$="hours.png"]` - set alt to: `Open daily 7am to 3pm` *(confirm)* - **bread.png** - page: https://curbcuthq.com/demo/index.html - selector: `img[src$="bread.png"]` - set alt to: `Round golden-brown bread loaf, flat illustration` *(confirm)* - **bread.png** - page: https://curbcuthq.com/demo/index.html - selector: `img[src$="bread.png"]` - set alt to: `Round golden-brown bread loaf, flat illustration` *(confirm)* - **bread.png** - page: https://curbcuthq.com/demo/menu.html - selector: `img[src$="bread.png"]` - set alt to: `Round golden-brown bread loaf, flat illustration` *(confirm)* - **logo.png** - page: https://curbcuthq.com/demo/order.html - selector: `img[src$="logo.png"]` - set alt to: `Harbor Lane home` *(confirm)* 4 images are decorative and must be hidden from screen readers with an EMPTY alt (`alt=""`), not a description. Those marked *(confirm)* were judged by size alone: - `img[src$="croissant.png"]` on https://curbcuthq.com/demo/index.html (croissant.png) - `img[src$="croissant.png"]` on https://curbcuthq.com/demo/menu.html (croissant.png) - `img[src$="cake.png"]` on https://curbcuthq.com/demo/index.html (cake.png) - `img[src$="cake.png"]` on https://curbcuthq.com/demo/menu.html (cake.png) ## 2. Page titles Replace each page title with this. Lengths are chosen to avoid truncation in search results. Where a title is marked *(also the visible heading)*, it comes from content (frontmatter, a CMS field, a database row) rather than a template: change it there, or add a separate SEO title field and leave the heading alone. - https://curbcuthq.com/demo/index.html — `head > title` - currently: `Home` - set to: `Harbor Lane Bakery — Sausalito Sourdough & Pastries` *(confirm)* - https://curbcuthq.com/demo/menu.html — `head > title` - currently: `Home` - set to: `Harbor Lane Bakery menu` *(confirm)* - https://curbcuthq.com/demo/about.html — `head > title` - currently: `Our story - Harbor Lane Bakery, Sausalito - fresh sourdough bread, croissants, pastries and cakes baked daily in Marin County` - set to: `Our story — Harbor Lane Bakery` *(confirm)* - https://curbcuthq.com/demo/order.html — `head > title` - currently: `Order` - set to: `Order ahead — Curbcut` *(confirm)* ## 3. Meta descriptions Set the meta description for each page to exactly this text. It is written to fit within the length search results display. - https://curbcuthq.com/demo/index.html — `meta[name=description]` - set to: `Handmade sourdough from $9, three-day laminated croissants from $4.50 and order-ahead cakes, baked from 4am on Harbor Lane in Sausalito. Pickup available.` *(confirm)* - https://curbcuthq.com/demo/menu.html — `meta[name=description]` - currently: `Harbor Lane Bakery menu` - set to: `Sourdough loaves from $9, croissants and morning buns from $4.50, whole lemon cakes to order. Bread out of the oven at 7, pastry at 6, allergen details inside.` *(confirm)* - https://curbcuthq.com/demo/about.html — `meta[name=description]` - set to: `Harbor Lane Bakery began as a 2014 Sausalito market stall with one oven and one starter. Flour from Petaluma, butter from up the road, baked to sell out.` *(confirm)* - https://curbcuthq.com/demo/order.html — `meta[name=description]` - set to: `Order sourdough loaves, croissants and cakes for collection. Pickup only, order by 8pm for the next morning, and allow two days' notice for cakes.` *(confirm)* ## 4. Form labels Each control below has no accessible name. Add a visible <label> associated with the input by id, or an aria-label if the design genuinely has no room for visible text. - https://curbcuthq.com/demo/order.html — `input` - set to: `Your name` *(confirm)* - https://curbcuthq.com/demo/order.html — `input` - set to: `Email address` *(confirm)* - https://curbcuthq.com/demo/order.html — `input` - set to: `Phone number` *(confirm)* - https://curbcuthq.com/demo/order.html — `select` - set to: `Item` *(confirm)* - https://curbcuthq.com/demo/order.html — `input` - set to: `Pickup day and time` *(confirm)* - https://curbcuthq.com/demo/order.html — `textarea` - set to: `What you'd like to order` *(confirm)* - https://curbcuthq.com/demo/order.html — `input` - set to: `I agree to the terms` *(confirm)* ## 5. Link text Each link has no accessible name. Add text inside the link, or an aria-label if it must stay icon-only. - https://curbcuthq.com/demo/menu.html — `a` - set to: `Home` *(confirm)* - https://curbcuthq.com/demo/index.html — `a` - set to: `Home` *(confirm)* - https://curbcuthq.com/demo/about.html — `a` - set to: `Home` *(confirm)* - https://curbcuthq.com/demo/order.html — `a` - set to: `Home` *(confirm)* ## 6. Frame titles Add a title attribute to each iframe describing what it contains. - https://curbcuthq.com/demo/about.html — `iframe` - set to: `Bakery location map` *(confirm)* ## 7. Structural fixes These need a judgement call about the markup rather than a text replacement. Apply them where the intent is clear; flag the rest. ### missing-lang (4) > The page does not declare a language, so screen readers may read it with the wrong pronunciation rules. - https://curbcuthq.com/demo/index.html — `html` - https://curbcuthq.com/demo/menu.html — `html` - https://curbcuthq.com/demo/about.html — `html` - https://curbcuthq.com/demo/order.html — `html` ### zoom-disabled (4) > The viewport disables pinch zoom, which low-vision users depend on. - https://curbcuthq.com/demo/index.html — `meta[name=viewport]` - https://curbcuthq.com/demo/menu.html — `meta[name=viewport]` - https://curbcuthq.com/demo/about.html — `meta[name=viewport]` - https://curbcuthq.com/demo/order.html — `meta[name=viewport]` ### table-no-headers (1) > Table has 7 rows and 3 columns but no header cells, so screen-reader users cannot tell which column or row a value belongs to. - https://curbcuthq.com/demo/menu.html — `table` ### button-no-name (1) > Button has no text or label, so it is announced only as "button". - https://curbcuthq.com/demo/order.html — `button.icon-btn` ## 8. SEO and security errors to review These are not accessibility failures and mostly not markup edits: most are fixed by the server configuration section, a hosting setting, or a content decision. Read each one; do not attempt them blindly. - **seo-no-description** (3 pages): Page has no meta description. - **link-not-found** (2 pages): Link returns 404. - https://example.com/couriers (on https://curbcuthq.com/demo/order.html) - https://curbcuthq.com/demo/specials.html (on https://curbcuthq.com/demo/index.html) ## 9. Optimised images The pack includes recompressed images in `for-your-developer/images/`. Replace the originals with these and update any width/height attributes to the new dimensions. Where a file is offered as both WebP and a fallback, check `README.txt` — sometimes the fallback is the smaller one and the WebP should not be advertised. Rows marked CHECK BY EYE saved so much that a person should compare them with the original before they replace it; logos and og:images are kept lossless or in their original format for that reason. ## When you are done Report: how many of each fix type you applied, which you skipped and why, and any place the audit pointed at something you could not locate in the source. Then run the site's own tests and linters before proposing the change. --- Automated checks prove specific failures exist. They cannot prove a site is accessible. A person should confirm each replacement reads correctly in context before it ships.
Automated testing reaches a minority of the WCAG criteria. These are the checks a person has to make, scoped to what we found on your site. Tick them off here; the same list is in check-by-hand/CHECKLIST.md.
Take the findings somewhere else. Tickets are one per change on the roadmap, not one per finding: twelve well-formed tickets get picked up, a hundred and seventy rows get ignored.
This is what a screen reader announces, in order, on your key pages. It comes from the browser's accessibility tree, which is what screen readers read. Role first, then name: link, Contact or image, unlabelled. People navigate by jumping between headings and by pulling up the list of links, so both are shown.
banner landmark link, (no name) image, unlabelled navigation landmark link, Menu link, Our story link, Order link, Specials heading level 3, Sausalito, California heading level 1, Bread worth crossing the bridge for. link, Order for pickup link, click here to see this week's menu. image, unlabelled image, unlabelled image, image heading level 3, Croissants from $4.50 image, bread.png heading level 3, Sourdough $9 image, unlabelled heading level 3, Cakes from $38 footer landmark © Harbor Lane Bakery · 12 Harbor Lane, Sausalito CA · link, (415) 555-0142 link, Instagram We use cookies to make the site work and to see which pages people re…
banner landmark link, (no name) image, unlabelled navigation landmark link, Menu link, Our story link, Order heading level 3, This week heading level 1, Menu table, 7 rows image, unlabelled heading level 3, Pastry image, unlabelled heading level 3, Bread image, unlabelled heading level 3, Cakes footer landmark © Harbor Lane Bakery · link, Home
banner landmark link, (no name) image, unlabelled navigation landmark link, Menu link, Our story link, Order heading level 3, Since 2014 heading level 1, Our story The shop is small, so we bake to sell out rather than to have leftove… link, order ahead and we will keep it for you. heading level 4, Visit us iframe heading level 4, The team footer landmark © Harbor Lane Bakery · link, Home
banner landmark link, (no name) image, unlabelled navigation landmark link, Menu link, Our story link, Order heading level 3, Pickup only heading level 1, Order ahead edit text, Your name edit text, Email edit text, Phone (optional) combo box, (no label) option, Country sourdough option, Seeded sourdough option, Olive and rosemary option, Croissants (box of 6) option, Lemon cake edit text, Pickup day and time edit text, Anything else checkbox, not checked, (no label) I agree to the terms button, (no name) image, unlabelled Press the logo to send We do not deliver. If you need delivery, several local services will … link, see this list footer landmark © Harbor Lane Bakery · link, Home