Repository navigation
Conversation
…ds websites well Quackback AI had a list of fields it could set: the brand, the header, the band, the welcome message and the feed. It could not build Home, change the menu or the words, or write own wording. It now has one tool: set any field of the design document by its path, to any value it takes, each change checked by the schema and the contrast solver as a person's would be. Plain text stands for rich text and for a translated field's English, a font id for a bundled font, and a Home block can be written as its type and width. What it refuses comes back with why, in its reply. Its output is untrusted, so it may not bring in a stored file or a link the person did not give, or a Home block for a page that is off. It writes CSS only where PORTAL_DESIGN_AI_CSS is on, which it is not by default, and only CSS the check passes on a plan with custom CSS. Home is a section a person can pick in the preview. Reading a website for its brand now reads its CSS and manifest as well as its head: brand colours weighed by where the site uses them, its page background, dark or light, and its fonts. It says who it is, tries the address with and without www, follows a meta refresh once, and reports a site that answers with a bot check or a refusal as blocked, offering a screenshot instead, rather than reading the block page as the site. On 80 real sites it read 72 (before: 31 of 48) and found a brand colour on 63 (before: 5).
Three things the first AI-only designs showed. A Home layout with one block whose page is off was refused whole; the block is now left out and the layout kept. Own wording written as plain text was refused when the language had none yet. A dark colour was refused while the design had no dark colours at all.
…s, and Home has no holes What the first AI-only designs showed. A screenshot start reached the model only as colours, and the brand colour was the brightest one: a deep green or a navy never counted, so a forest- green brand came back sage with its copper accent leading. A brand colour is now judged by its saturation, fading only toward black, and the largest group of such pixels leads the palette. The image itself, downscaled, goes to the model too, so it can read the type and the shapes; a model that does not take images still has the colours. The website reader uses the same rule, so a deep brand colour on a site counts as well. A Home block left its row short when the next block would not fit beside it, or when a block beside it had its page off: a status block on a workspace with no status page left a hole. The row's last block now grows to fill it. Quackback AI is told to pair blocks of a like height, as a short composer beside a long list leaves white space below it.
…fits a phone A brand colour read from an image was the mean of its hue's pixels, so the edges anti-aliasing blends into a dark page pulled an electric lime down to olive. It is now the hue's most common shade, which a solid fill wins. On a phone the centred header's menu, wider than the screen, was cut off at its start where it could not be scrolled to, and the centred logo ran into the buttons at the end. The menu now centres only while it fits, and the logo leads on small screens.
A starting look set a preset, three colours, two fonts and a headline; Home, the words and the wording waited for later requests. Each look is now a complete design: mode and dark colours, fonts and heading weight, corners, header, menu, band, cards, density and width, both headlines, the words, the composer's prompt and button, and Home with its blocks for the pages the workspace has. The prompt is a short design system: how a brand becomes each choice. Each look goes through the same checks as any change from the model. The directions move to their own module.
…d brands keep their character Measured on twelve brands, the first look's weakest marks were for brand: every company showed a letter for a logo, monochrome brands came back with an accent picked from the edges of their CSS, and brands that fill their pages with colour came back softened. A website start now takes the site's logo as the workspace's when it has none and the person may change the workspace's settings, and only a logo the lookup is sure of. The website reader also notes the colour its buttons are filled with, neutrals included, and whether it fills large areas with its brand colour, and the design system keeps a monochrome brand monochrome and gives a bold one its full-colour band. The example look moves to a brand unlike any of those measured.
Measured with a smaller model, a quarter of starts came back with no looks: the complete looks are a long answer, and one that did not fit the schema ended the start. It is now asked for once more before the start fails.
…d button, and names a monochrome brand From the judges' notes on round two. A white site read as dark when its CSS painted the body black for dark mode, so dark-mode blocks and dark-theme rules are no longer read. A brand whose buttons are a colour now leads with that colour, over an accent used elsewhere. A brand whose buttons are black is named monochrome in the brief, so its first look stays monochrome.
Every start that failed in the eval was cut off mid-answer at 4000 tokens: three complete looks are long, and some models reason first.
Reading a site's CSS cannot see the page: generated class names hide its buttons, and dark-mode rules can read as its look. A screenshot shows the model the page as it is. With a website typed, adding a screenshot reads both together, and the website field says so. A look's text that runs past its field is trimmed at a word rather than refusing the start.
…decoded once The portal's Home and Appearance both imported home.ts once Home filled its rows, which split it into a chunk of its own and cost Appearance a request. Row filling now lives in home-spans.ts, which only the portal imports. The website reader decoded a page's entities one after another, so an escaped one, such as <, was decoded twice. It now decodes in one pass.
Stored designs were parsed strictly, so after a rollback a design with a field or option value only a newer build knows failed to parse: visitors saw the plain portal and Appearance could not open. Stored reads now set those aside and log them: an unknown key is dropped, an unknown option value reads as the default, and a menu item of an unknown kind is left out. Writes stay strict.
…sign chooses A design can now set its headline scale (standard, large or display), tight heading tracking, upper-case headlines and upper-case labels for the menu and buttons, and set a phrase of a headline apart in the accent colour or highlighted. The accent colour is moved until it reads on the band. Absent choices read as today's type. The header now follows the design's logo display: a wordmark file, with its dark file in dark mode; the mark alone; or, new, the name set in the heading font as a wordmark for brands without a logo file. A wordmark with no file yet shows the mark and name. The admin preview follows the draft's logo.
…placeholders A design can set a second brand colour, in light and optionally dark (dark keeps light's when it has none). Two new bands use it: support fills with it, and blend runs the brand colour into it, in a line or as a soft mesh beside the words with the page's own colour under them. A mesh gives way to the plain page on phones, where the words cross it. Band text is picked to read at 4.5:1 everywhere it sits, and a blend no text can read across is refused like any unreadable pair. Highlighted phrases take the second colour when there is one. Composer and title placeholders now use the secondary text colour, which the solver keeps at 4.5:1, rather than a faded copy of it.
… in the band A design can now align the band's words left or centre (absent follows a centred header, as before), shape the band as an inset panel within the page or set its words on a panel of the second colour, and put the header in the band's colour. On the band the header's button keeps the brand colour where it reads there, else takes the band's text colour. Home's composer can move into the band under the headline, with a filled button that takes its own line on phones; the grid keeps every other block's place. A full-width contact block lays out as one row, so it no longer leaves a gap beside the composer.
…rand's style A design can give buttons, and the composer that carries one, their own shape: square, rounded or pill, whatever the corners; absent follows the corners as today. The shape stays inside the portal. Status markers can be drawn in the ink colour, as tags tinted with each status's colour, or in the logo's own colours, where each status takes the logo colour nearest its hue and greys stay grey. Status dots now paint from a variable, so a design's style overrides them without !important.
…tton shape Buttons kept a radius of their own inside the portal, which dropped the rounded-item class every other control shares. The portal's item radius now follows the button shape, which follows the corners until a design sets one, so buttons, badges and tabs keep their one class.
A design's wordmark can now be uploaded as an SVG, the format most logos come in. Storage serves SVG as a sandboxed download, which an image tag still shows, so it never runs as a page; the workspace logo, which emails carry, keeps to raster images. A design can set an image in its band: beside the words (under them on phones), along the band's bottom on wider screens, behind the words under a veil of the band's colour, or tiled as a pattern under a lighter veil. Only images from the workspace's own storage are shown, and the admin preview follows the draft's image.
The band now reads the draft's band image, so the feedback page test's mock of the preview context provides it.
…faces among them Inter Tight, Sora, Outfit, Figtree, Work Sans, Instrument Sans, Noto Sans, Rubik, Karla, Libre Franklin, Barlow Condensed, Oswald and Source Serif 4, all open licence. Each loads only when a design uses it, at the weights a heading can take, and the build's font manifest picks them up from the loader as before.
The design's new bundled faces add their catalogue to the entry chunk. Five admin settings pages sat at their script ceiling and go over it by about 8 KB; their ceilings move to CI's readings. No request or render counts change.
This was referenced Nov 1, 2026
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. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Quackback AI can start a design from a website, and the design can carry a brand's character: its type, a second colour, bands, buttons and imagery.
In this PR
Replaces
#860, #861, #862, #863, #864, #865, #866, #867
Third of five stacked PRs.