Skip to content

feat(design): an optional website reader that renders a page - #882

Closed
mortondev wants to merge 6 commits into
feat/portal-design-v2-4-fidelityfrom
feat/portal-design-v2-5-reader
Closed

mortondev wants to merge 6 commits into
feat/portal-design-v2-4-fidelityfrom
feat/portal-design-v2-5-reader

Conversation

@mortondev

@mortondev mortondev commented Nov 1, 2026 •

Copy link
Copy Markdown
Member

An optional service that reads a website's home page as a browser renders it, so Quackback AI starts from a brand's exact type, colours and buttons and a clean screenshot. Without it, websites are read from their HTML and CSS as before.

In this PR

  • docker/browser: Chromium behind a small read service, one read at a time, each in its own process; an optional compose profile
  • It identifies itself, keeps the browser's automation flag, respects robots.txt, declines optional cookies and never works around a bot check
  • A guard proxy inside each read: secure tunnels on the standard port only, DNS-pinned checks that refuse private, internal and metadata addresses
  • QUACKBACK_BROWSER_URL and QUACKBACK_BROWSER_TOKEN; the design start uses the rendered read when it arrives within 40 seconds
  • The rendered brand colour comes only from the main call to action or a full-width hero; the screenshot's colours are read by pixel
  • The static reader leaves out every script however its tags are split (the code-scanning thread on feat/portal design v2 tune #877)

Measured

Against what an honest browser renders, the reader's type, button and colour reads went from 47% correct to 89% on twelve sites it was never tuned on, and to 74% on thirty more. Designs started from a rendered read stopped losing brand colours on sites that theme themselves with scripts.

Fifth of five stacked PRs.

An optional service beside Quackback that reads a website's home page as a
browser renders it: the type, colours and shapes of its headline, headings,
main button, cards and fields, the colours its first screen is painted in,
and a screenshot of that screen.

It says what it is. It sends its own agent, keeps the browser's automation
flag, respects robots.txt, and never works around a bot check. Consent
notices are answered by declining optional cookies, from a maintained set
of rules for common consent managers and then by its own pass, and what is
left over the page is hidden for the screenshot.

Every request a page makes goes through a guard proxy inside the read. It
tunnels secure connections on the standard port only, resolves each host
itself, refuses private, internal and metadata addresses, and connects to
the address it checked, so a page cannot reach the network the reader runs
on. Chromium's own UDP paths are off.

The service answers POST /read for callers holding its token, one read at
a time, each in a process of its own that ends if it overruns. It ships as
its own image (docker/browser) and an optional compose profile, with no
secret but its token.
…er when one is set up

With QUACKBACK_BROWSER_URL and QUACKBACK_BROWSER_TOKEN set, starting a
design from a website asks the reader for the page as a browser renders it,
alongside the read of its HTML and CSS. What the render shows leads: the
main button and its colours, the hero's fill, the type of each role and
the page's colours by area. The rendered first screen stands in for a
screenshot when none is given. A reader that is waking is asked once more;
without a reader, or no answer within the budget, nothing changes.
… does

Two ways the rendered read led looks away from a brand:

- A colour that merely covered much of the first screen, such as a
  promotion's panel, became the brand colour on a page with no call to
  action, displacing the colour the site's CSS and logo name. The rendered
  read now names a brand colour only from the main call to action's fill
  or a hero filled edge to edge; other colours join the palette.
- The colours given with the rendered screen came from painted
  backgrounds alone, so imagery, gradients and canvases were missing and a
  look took its second colour from elsewhere. The reader now reads the
  screenshot's main colours by pixel, as an uploaded screenshot's are,
  and the site's brand colour leads them, since a screen's own leading
  colour can be a photo's.
… a website

A heavy site can take half a minute to render, more when reads queue, and
the design started without it. A design starts once, so it waits longer.
…een hardly shows

The colours given with a rendered screen now carry the site's own leading
colours after the screen's. A second brand colour used only in small places,
such as a coral link colour, could fall out of a palette read from the first
screen alone.
…tags are split

Script, style and drawing blocks come out of a page repeatedly until
nothing changes, since taking one out can join the pieces of another.
A block left open runs to the end of the page, as a browser reads it,
so nothing inside it is read as a link.
@mortondev
mortondev added this pull request to stack #883 November 1, 2026 00:25
@mortondev mortondev changed the title feat/portal design v2 5 reader feat(design): an optional website reader that renders a page Nov 1, 2026
This was referenced Nov 1, 2026
This was referenced Nov 1, 2026
@mortondev

Copy link
Copy Markdown
Member Author

Superseded by the re-cut builder stack on current main: #917 (engine) → #918 (server) → #919 (portal) → #920 (builder) → #921 (AI) → #922 (tooling), with the critique's wave 1 in #924. The new stack merges main once, renumbers the migrations to 0310+, and has CI green with all review threads addressed.

@mortondev mortondev closed this Nov 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant