Skip to content

feat(design): Quackback AI in Appearance - #840

Closed
mortondev wants to merge 2 commits into
feat/portal-design-v2-phase2-finishfrom
feat/portal-design-v2-phase3-ai
Closed

mortondev wants to merge 2 commits into
feat/portal-design-v2-phase2-finishfrom
feat/portal-design-v2-phase3-ai

Conversation

@mortondev

@mortondev mortondev commented Oct 30, 2026 •

Copy link
Copy Markdown
Member

The eighth of the stack that builds a new design engine for the portal, and the first of phase 3. It puts Quackback AI into Appearance: a conversation that changes the design draft as it goes, three starting looks from a website or a few words, and a composer under every tab that follows the section picked in the preview. Behind the portalDesignV2 Labs switch; with it off, nothing changes.

Changes go into the draft, with no apply step

A request returns a list of changes to design fields, and each is applied on its own. The fields are an allowlist: colours, mode, fonts and heading weight, corners, header, menu style, band, cards, density, width, filters, the feedback headline, the welcome message switch and the default sort. Quackback AI never writes CSS. A change is kept only when the design still passes the schema and the contrast solver, so an unknown value or an unreadable colour drops out without taking the good changes with it. The server saves the result as the draft for the person who asked; a request that changes nothing leaves the draft alone. Nothing reaches visitors until a person publishes, as before.

The answer shows a card of what changed, with Undo on each row and Undo all. When a change makes the solver adjust something to keep text readable, the card says what, from the same report Review and publish uses.

Replies say only what happened

The change card is the record of what changed. When a request changes nothing, the server writes the reply: "That is outside the header, so nothing changed", or "Nothing changed: the design does not offer that". So the model's prose can never claim a change the draft does not have.

Scope

Clicking a section in the preview already opens its controls; it now also scopes the composer to that section, shown as a chip. A section scope reaches only that section's fields, enforced on the server, and the model is told which section was picked. The Brand tab scopes to brand fields. Clearing the chip asks about the whole site. When a request reaches outside the section picked, the answer offers "Ask about the whole site", which asks again without the section.

Starting points

Before the first request, Ask AI offers three starts: match a website, describe the brand in a few words, or open the presets. A website is read with the same safe fetch the logo lookup uses: its title, description and theme colour, when that colour can carry white text. Nothing from it is stored. Both return three looks, each built on a preset with its own colours, fonts and headline, and checked like any other change. Each is drawn with its layout and named fonts; picking one puts it in the draft.

Without AI

When no model is set up, Appearance opens on Brand, the Ask AI tab says why in one line, and there is no composer. Brand and Sections work in full.

Events

appearance_start_chosen (website, words or preset), appearance_look_picked, and appearance_published with its source, ai when Quackback AI changed the draft in that session, otherwise manual.

Notes

  • The composer and the change card have the shape of the admin chat composer and settings change card, but are Appearance's own. The settings card is keyed to workspace settings proposals, and importing either into Appearance would split it into a chunk Home loads.
  • The server functions need the branding permission and use the assistant model and the AI token budget, like the other AI features.

Verification

  • Typecheck, lint, the production build and the server-function manifest check pass. The authz matrix and dependency graph documents are regenerated for the three new server functions.
  • The core perf bench passes locally. Appearance's code stays out of the pages visitors load, and the settings click-through keeps its request count.
  • New tests: applying changes (allowlist, schema and solver refusals, scope, clearing an optional colour), the model layer with the model mocked (no model, mixed answers, off-schema answers, readability notes, directions built on presets), the server functions (permission, saving only when something changed, an unreadable website), reading a website offline, the panel (starts, per-row undo, looks), and the view (opening tab with and without AI, a scoped request landing in the draft, the publish event's source). Each was checked by breaking the code it covers.

Ask AI changes the portal design draft as it goes, with no apply step.
Each change is one of an allowlist of design fields and is kept only when
the design still passes the schema and the contrast solver; Quackback AI
never writes CSS. The answer lists what changed with an Undo per row, and
names what the solver adjusted to keep text readable.

The composer sits under every tab and follows the section picked in the
preview; a section scope reaches only that section's fields. Before the
first request, Ask AI offers three looks from a website or a few words,
or the presets. Without a model, Appearance opens on Brand.
@mortondev
mortondev added this pull request to stack #833 October 30, 2026 22:09
Designing eight brands end to end through Appearance turned up these:

- A subtitle was written to the headline, because its path ends in "title".
- A reply could claim a change the draft never got. When nothing was
  applied, the server now says why, and the change card is the record.
- A request outside the section picked in the preview was refused with no
  way on. It now says so and offers to ask about the whole site.
- The model knew fields only by path, so "tabs for the menu" missed the
  menu style. Each field is described in plain words, and a section lists
  the fields it reaches.
- Each look writes a headline, so a look with a band never shows it empty.
- The change card names values as the tiles do, each look is drawn with its
  layout and fonts, and the composer stays clear of the draft bar.
@mortondev

Copy link
Copy Markdown
Member Author

Condensed into #878. The stack is now five PRs, #878 to #882; this branch is kept as it was.

@mortondev mortondev closed this Nov 1, 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