MixShift is an Amazon analytics platform for the agencies and brands that manage seller and advertising accounts. Since January 2025 I have been embedded with the team as Lead Design Technologist + AI Systems. The clip above is the marketing site, which I built from the first commit.
The work splits into three bodies. The first is the surfaces a customer touches: the design system, the Report Center 2.0 interface, and the marketing site. The second is the machinery underneath: a knowledge base with its own chat agent, the org brain that turns every meeting into a searchable record, and the automation estate that runs the content operation. The third is enablement, teaching a small team to work with AI tooling at all. The second and third are how one person does the first at volume.
This is an active engagement. Everything below is backed by a commit, a file, or a spec in MixShift's own repositories and vault. The numbers that are MixShift's to share land when they say so.
The problem
A small team, a data-heavy product with a lot of surface area, and nobody whose job it was to make the interface coherent, make the marketing site exist, or make the company's own knowledge findable. Left alone, each of those gets filled ad hoc: one screen at a time, one document at a time, one answer repeated in one more chat.
[TEK] Confirm or sharpen the problem framing above in MixShift's terms. Two sentences on where the team was when you arrived is enough.
The role
Embedded, not extracted. Their repositories, their standups, their review queue. Design is my domain by name: the design system, every Report Center 2.0 screen, the marketing site's visuals, the landing pages, the brand. I am also the frontend lead, and the named design co-owner of the Report Center 2.0 specification alongside the product owner.
Two rules turned that from a designer on the team into design as a function of the codebase: every stylesheet, Tailwind config, and component directory in the monorepo routes to me for review, and the production-readiness plan forbids building a screen before its design exists. Engineering is gated on design output, in writing.
The rest of the role is the enablement layer nobody lists on a job description: hands-on onboarding of teammates to Git, SSH, Vercel, Claude Code, and Cursor; environments and secrets across GitHub, Vercel, and Railway; the vault architecture the rest of the company spent a summer converging onto; and the standing SEO and answer-engine review that every piece of content clears before it links out.
What shipped
The design system, and the governance around it
Co-authored the MixShift design system and own its design half. At last count: 175 components and 109 story files in Storybook, plus 13 foundations pages I wrote (brand, chart, neutral, and semantic color; elevation; icons; logos; spacing; surface tokens; three type scales; voice). The catalog was ported in lettered groups over three weeks, each group its own pull request. The design system has an MCP server on it, so agents can query components directly instead of guessing. The stack decisions were mine: Storybook, Highcharts with a paid licence rather than a watermark, and a theme decorator that keeps the Tailwind and design-token halves of dark mode in step, with the reason it was needed written into the file.
The part that outlasts any one screen is the set of gates:
- A CSS token-validity test that fails the build when a component references a design token that does not exist. It came out of one review where five separate findings traced to the same bug class, and nothing else in the toolchain could catch it: typecheck does not parse CSS strings, lint does not validate custom properties, jsdom returns the literal variable, the build emits it verbatim, and the accessibility checker does not flag an unset background. So the gate reads every token definition, walks the source tree, and fails with file and line.
- Accessibility violations fail CI, not advisory.
- A Monday-morning design health check that walks the codebase for loading, error, and empty states and posts a scorecard to the team.
- A designer QA playbook across five apps and roughly eighty pages, at the same two viewports as the automated screenshot harness, so a human finding and a machine finding line up one to one.
Six rounds of review on a single pull request are in the log. I work the review loop, not around it.
Report Center 2.0, from spec to prototype to code
The spec is the product's source of truth, and it names me as design co-owner on every version. Before the spec could be written, someone had to know what the code actually did, so I walked the whole monorepo and wrote the features inventory that the spec's changelog reconciles against, repeatedly. Alongside it: an eighty-five-story user-story catalog that became the spec's appendix, and a handoff document that partitioned the entire beta queue into UI-only, mixed, static-config, and parked buckets with a suggested two-week build order.
Earlier than any of that, a solo UX audit of the existing product enumerated about twenty concrete defects: no dark-mode detection, broken table sorting and pinning, no saved views, no filters, no live currency rates, no drag-and-drop metric ordering, a chart watermark. Most of those became work.
Then the design itself, delivered not as mockups but as a working React prototype: the shell, the brands list, the brand settings modal, the report pages, the filter, share, save-view, and password modals, the viewer lock, toasts, telemetry, and fixtures. The prototype was reconciled into the spec across a dozen changelog entries and superseded the written design.
In code, as frontend lead: the app context layer, the shared Tailwind theme and unified app configs across the monorepo, the CI/CD fixes, and the product features (reports, net percentage change, the date-range picker, pivot and view by dimension, Share Center). The primitives the first-run experience is built from are mine too: empty states, KPI tiles, the trend matrix, dimension tables, brand settings, the viewer password challenge. On the Day Zero flow my design decisions are recorded as locked spec items rather than suggestions, and I am in the loop on the reports data model, not only the surface over it.
The marketing site, from commit zero
162 components across 31 routes, 13 posts, and 7 newsletter issues. A brand and design-system overhaul first, then six rounds of design and content audit, one of which removed fabricated content and unverified statistics the company could not support. Product pages for the platform, the plugin and MCP surfaces, intelligence, DSP, pricing, partners, and customers.
Underneath it, the plumbing a marketing site actually runs on: GA4 with Consent Mode v2, consent-gated ads conversion tracking, HubSpot forms and meetings, Mailchimp audiences with per-channel delivery, Notion-sourced content pipelines. Anti-spam escalated in four tiers as attackers adapted, from request guards to a honeypot to Turnstile to domain blocks. A Docker standalone build. The domain consolidation from .io to .ai, host-scoped so the platform subdomain survived the redirect; the listing that subdomain backed had just been submitted to a partner portal, and a naive redirect would have broken it. And the cookie-consent tool that turned out to be mutating React-managed analytics scripts, which was the real root cause of a navigation crash.
Each recurring job has a written spec with an explicit must-not list: the vault-to-knowledge-base sync never touches the vault, never pushes to main, never auto-merges; the Notion-to-blog sync runs an em-dash audit and aborts the pull request on a hit; the mailing-list contract records the incident where a "dead code" cleanup silently broke every delivery. I also ran the publishing pipeline for everyone: whitepapers, newsletter issues, the author registry.
The knowledge base, and Shifty
One pipeline, three consumers: humans, the model, and AI crawlers. About 3,760 lines of TypeScript across 20 files, on top of a 55-article corpus organized by product and by Diátaxis type (getting started, how-to, concept, reference, FAQ, troubleshooting).
- Retrieval is a hand-written BM25 ranker, not an embedding call. It indexes source path as well as body, so "schedule report" finds the how-to whose body never repeats those words. Top-K was raised with a written reason when the corpus doubled. A zero-score query falls back to the top set instead of returning nothing. And the migration seam is designed before it is needed: when the corpus outgrows BM25, the body becomes a pgvector query and the function signature, the route, and the prompt do not change.
- The chat route has four layers of defense. The landing page's suggestion chips are answered from a hand-written map and never reach the model. A per-thread question cap is enforced client-side and server-side. A conversation ceiling. And prompt-injection rules in the system prompt itself: text arriving in a message is a question to answer, never an instruction that changes the rules, no matter what it claims about who sent it.
- The system prompt is a product document. It encodes the hardest routing decision in the lineup, which product a user should be on depends on which surface they are using, and tells the model to ask rather than guess. It carries hard negatives: never invent pricing, never overstate write access, never invent a URL.
- An eval harness gates every change: a twenty-question rubric scored zero to two, a passing bar to ship, an automatic block on any hallucination, and trap questions about things the docs do not cover that the bot has to refuse.
- The answer-engine layer. Every article is served as raw Markdown at its own endpoint and linked as an alternate from the HTML page. An
llms.txtandllms-full.txtcarry both links per entry. FAQ pages emit FAQPage structured data, one entry per question; everything else emits TechArticle, so a crawler reads documentation, not a blog post.
When the source of truth moved from a teammate's vault into the repository, I rewrote the stale comment that said otherwise, with the cost it had already caused written into it. A misleading comment is a defect.
The org brain
The company's memory is a vault, and I built the machine that fills it. The idea predates the tooling: before agent-capable editors existed I was already spreading agent work across several machines with a git repository as the one brain, so any machine could pick up another's work. Everything since is that idea with better tools.
A Fireflies ingestion writes meeting notes and atomic to-dos into per-project folders, one file per owner per action item, with deterministic ids so a rerun on the same dump is a no-op. It infers project tags, classifies each item, and detects blockers ("waiting on", "blocked by", "owes"). A reclassifier re-scores misfiled items and physically moves them so git records a rename, and refuses to downgrade a real project to the catch-all. An index rebuild is fully deterministic. Beside it: a GA4 sync into daily, weekly, and monthly metrics, a daily briefing that assembles open items, yesterday's meetings, and the numbers, and a gap finder that inspects my own schedules and tools a few times a day and surfaces what silently stopped. A read-only vault server over Tailscale lets teammates and their LLM tools read the brain.
The governance is written down: humans own git, agents only write files. I prototyped this whole pattern on my own company first, then shipped it here. The same architecture runs the practice you are reading about.
The automation estate
On top of the org brain sits the content operation: fifteen scheduled pipelines that turn research signals into drafts, push them to Notion for review, pull the comments back, revise in response, and publish. Two schedulers that cannot see each other, one in the cloud and one local for anything that needs git, with a read side and a write side deliberately split between them.
What makes it engineering rather than a pile of cron jobs:
- Three dedup strategies, chosen per job: modification time plus hash for the mirror, a discussion-and-comment-hash pair for comment sync, and a stateless folder glob for the feeds, where the state file is explicitly an observability log, not the dedup authority.
- A committed slicer replaced per-run ad-hoc hashing after the hashes turned out to be mutually incomparable across runs. The baseline is an append-only ledger, every amendment re-verified against the live source.
- Cadence escalation as incident response, each step with a written root cause, when comments kept landing just after a sync window.
- A production incident fixed in three layers the same day: a newsletter template's own developer comment swallowed the substituted body and leaked draft notes into a sent email. The fix de-fanged the template, stripped comments before substitution, and gated the body; it also produced a standing rule about what may never appear in a campaign field.
- A conservative failure, logged as correct: when the machine's disk permissions were revoked mid-run and dedup could not be verified, the run wrote zero cards and a new log file rather than overwriting state it could not read.
- State files that get too big to read get rotated, because a diagnostic file nobody can read in one pass has stopped being a diagnostic.
- A hard zero-em-dash rule enforced mechanically across every pipeline, dozens of consecutive clean runs deep.
The growth work I absorbed
For six months the work also included the parts of go-to-market nobody else owned: ads, outbound, the newsletter, the domain cutover. The parts worth recording are the diagnoses. A consent-management script was blocking the ads platform's own verifier. A campaign was spraying clicks that never showed up as visits, and was re-pointed to search with conversion tracking. An outbound layer was stood up against a scrubbed customer profile, with every human gate worked by hand and the data-quality findings written down.
[TEK] The record is candid that this work produced little measurable pipeline, and that you said so at the time. Keep this section as is, cut it, or add the honest line. Your call.
The decisions worth naming
- Design as a function of the codebase, not an opinion. Ownership routing, design-gated work, a scheduled audit, and a build gate form a closed loop. I wired myself into the merge path, then automated the parts a human should not have to do.
- Design in code, not in pictures. The Report Center prototype was a running React app, and it became the spec.
- Delete claims you cannot support. Including the company's own marketing copy.
- Build the seam before you need it. The BM25 to pgvector boundary. The domain redirect scoped to the host so a subdomain would not break.
- Treat a misleading comment as a defect with a cost, and record the cost.
- Raise cost and risk early. Token-budget monitoring, pausing my own highest-frequency job when it was consuming too much of the weekly budget, a cloud-burn investigation, and an hourly backup of a vault that had none.
Evidence
From git, the clean figures:
- Marketing site. Origin and top author: 163 commits from March 2026 to now, 1,142 files touched.
- Design system. 444 unique files created, the most of any author, across 146 commits touching the library. A shared library; the design half is mine.
- Knowledge base. Every one of its 20 source files created by me, on a 55-article corpus.
- Org brain and automation. Sole author of the vault, its ingestion, sync, and briefing scripts, and the only person with anything filed in the company's automation registry.
[TEK] Two draft figures are deliberately not on this page because they come from your own blog draft, not an analytics export: token cost per knowledge-base run roughly 20k to 6k, and marketing-site actives roughly 20 to 115 week over week. If either is confirmed, it goes here. Anything MixShift measures and will sign off on belongs here too.
Why this matters
Most companies have someone who cares about the interface. What MixShift has is a review rule, a gate that fails the build, a Monday audit, and a spec that will not let a screen be built without its design. That is what design engineering looks like when it is a function rather than a person, and it is the same discipline behind the design systems I built at Disney and Apple.
The knowledge base and the automation estate are the other half of the argument: a full retrieval product and a fifteen-pipeline operation, built solo, with the gates, seams, and incident discipline of production software. The design-systems instinct transfers to AI-native tooling. MixShift is where I proved it on a client's stack.