The problem
Generative design tools produce markup that photographs well and breaks in a real application: arbitrary CSS, unbounded class soup, and no way to tell whether a change to the generation pipeline made the output better or merely different.
What I built
protoframe, an AI UI-design platform. I wrote the repository's root commit and led the build. It generates production React/Tailwind designs from a brief, runs the generation as background work, and keeps every artifact versioned so a design can be regenerated and compared rather than overwritten.
Two parts define it:
- A deny-by-default CSS allow-list. Generated styles must come from an explicitly permitted set; anything outside it is rejected rather than sanitised. This is what keeps generated output inside a design system instead of drifting toward whatever the model felt like emitting.
- An offline A/B evaluation harness for design quality, so a pipeline change is judged against previous output on the same briefs, before it reaches a user.
How it works
FastAPI serves the API; Celery runs generation as background jobs against Redis; LangGraph orchestrates the multi-step generation and repair path; PostgreSQL holds project and version state, and MinIO stores generated assets. The front end is Angular 21.
Evidence
Two design decisions are the evidence here, and both are in the repository: generated styles must come from an explicitly permitted set or be rejected outright, and every pipeline change is scored against previous output on the same briefs before it can reach a user. Design quality is compared, not asserted.
What I owned
I initiated protoframe and led it. I designed and built the LangGraph generation and repair pipeline, the deny-by-default CSS allow-list that keeps output inside a design system, the versioned-artifact model that makes a design regenerable rather than overwritable, and the offline A/B evaluation harness for design quality.
Stack
FastAPI · Celery · LangGraph · Angular 21 · PostgreSQL · Redis · MinIO · Python