---
title: My actual taste file
description: "The full contents of the taste file my agents read before they write a line of UI. Not a template. A decision record from years of corrections, published as is."
date: 2026-07-29
tags: [ai, design, taste, claude-code]
url: "https://mahdif.com/blog/my-actual-taste-file/"
---

# My actual taste file

The full contents of the taste file my agents read before they write a line of UI. Not a template. A decision record from years of corrections, published as is.

Yesterday I wrote that I keep my taste in a file the AI reads. Since then, one question has come back more than any other, in the comments and in DMs: can I see it?

Here it is. The real file, lightly cleaned of internal project names. This is what sits behind everything I've shipped this year: the rebuilt portfolio, the app that runs my writing pipeline, the tools that ran my job search. Every one of them started from these lines.

What this is not: a template. If you copy it, you'll get my products, not yours. The useful part is the shape of it, and how it got written. Both below.

## The file

<figure style="margin:2.75rem 0;">
<div style="border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;background:var(--card);">
<svg viewBox="0 0 1200 566" xmlns="http://www.w3.org/2000/svg" style="display:block;width:100%;height:auto" role="img" aria-label="An outline of the taste file, split into three modes. Mode A, minimal tool, the default: light by default, hairlines never shadows, one table over stat tiles, collapse detail until asked, days not dates. Mode B, juicy consumer: dark and saturated, shadows are a feature, motion haptics and sound, buttons that feel pressable. Mode C, editorial brand: quiet where you read, juice at the brand moments, one gradient and one shader, ambient never loud.">
<defs><linearGradient id="tf" x1="0" y1="0" x2="1200" y2="570" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#6366F1"/><stop offset="0.5" stop-color="#A855F7"/><stop offset="1" stop-color="#EC4899"/></linearGradient></defs>
<style>.tf-bg{fill:var(--card)}.tf-line{stroke:var(--border);stroke-width:1}.tf-file{fill:var(--foreground);font-family:var(--font-mono);font-size:20px}.tf-meta{fill:var(--muted-foreground);font-family:var(--font-mono);font-size:13px}.tf-h{fill:var(--foreground);font-family:var(--font-heading);font-size:38px;font-weight:600}.tf-sub{fill:var(--muted-foreground);font-family:var(--font-sans);font-size:18px}.tf-mode{fill:var(--foreground);font-family:var(--font-heading);font-size:22px;font-weight:600}.tf-tag{fill:var(--muted-foreground);font-family:var(--font-mono);font-size:13px;letter-spacing:1px}.tf-rule{fill:var(--foreground);font-family:var(--font-sans);font-size:17px}</style>
<rect class="tf-bg" width="1200" height="566"/>
<text class="tf-h" x="80" y="82">One file. Three modes.</text>
<text class="tf-sub" x="80" y="116">Pick the mode by product type, then apply it without mixing.</text>
<line class="tf-line" x1="80" y1="154" x2="1120" y2="154"/>
<g>
<rect x="80" y="186" width="34" height="3" rx="1.5" fill="url(#tf)"/>
<text class="tf-tag" x="80" y="222">MODE A</text>
<text class="tf-mode" x="80" y="254">Minimal tool</text>
<text class="tf-tag" x="80" y="280">THE DEFAULT</text>
<g>
<rect x="80" y="307" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="104" y="316">Light by default</text>
<rect x="80" y="347" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="104" y="356">Hairlines, never shadows</text>
<rect x="80" y="387" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="104" y="396">One table over stat tiles</text>
<rect x="80" y="427" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="104" y="436">Collapse detail until asked</text>
<rect x="80" y="467" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="104" y="476">Days, not dates</text>
</g>
</g>
<line class="tf-line" x1="450" y1="186" x2="450" y2="496"/>
<g>
<rect x="490" y="186" width="34" height="3" rx="1.5" fill="url(#tf)"/>
<text class="tf-tag" x="490" y="222">MODE B</text>
<text class="tf-mode" x="490" y="254">Juicy consumer</text>
<text class="tf-tag" x="490" y="280">THE OPPOSITE OF A</text>
<g>
<rect x="490" y="307" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="514" y="316">Dark and saturated</text>
<rect x="490" y="347" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="514" y="356">Shadows are a feature</text>
<rect x="490" y="387" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="514" y="396">Motion, haptics, sound</text>
<rect x="490" y="427" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="514" y="436">Buttons that feel pressable</text>
</g>
</g>
<line class="tf-line" x1="830" y1="186" x2="830" y2="496"/>
<g>
<rect x="870" y="186" width="34" height="3" rx="1.5" fill="url(#tf)"/>
<text class="tf-tag" x="870" y="222">MODE C</text>
<text class="tf-mode" x="870" y="254">Editorial brand</text>
<text class="tf-tag" x="870" y="280">PORTFOLIO, BLOG</text>
<g>
<rect x="870" y="307" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="894" y="316">Quiet where you read</text>
<rect x="870" y="347" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="894" y="356">Juice at the brand moments</text>
<rect x="870" y="387" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="894" y="396">One gradient, one shader</text>
<rect x="870" y="427" width="9" height="9" rx="2" fill="url(#tf)"/><text class="tf-rule" x="894" y="436">Ambient, never loud</text>
</g>
</g>
</svg>
</div>
<figcaption style="margin-top:0.85rem;text-align:center;font-size:0.85rem;color:var(--muted-foreground);">The whole file in outline. Every rule below came from a correction I repeated more than twice.</figcaption>
</figure>

Three modes, a handful of rules under each, one page. Scroll through the full text right here. The [copy on GitHub](https://github.com/MahdiF/agent-files) annotates every rule with the reasoning behind it.

<style>.tf-act{position:relative;display:inline-flex;align-items:center;justify-content:center;width:30px;height:30px;border-radius:6px;color:var(--muted-foreground);background:none;border:none;padding:0;cursor:pointer;transition:background-color .15s ease,color .15s ease;}a.tf-act,button.tf-act{color:var(--muted-foreground);text-decoration:none;}a.tf-act:hover,button.tf-act:hover{background:rgba(125,125,140,0.09);color:var(--foreground);text-decoration:none;}.tf-act:focus-visible{outline:2px solid var(--ring,currentColor);outline-offset:2px;}.tf-act::after{content:attr(data-tip);position:absolute;top:calc(100% + 9px);left:50%;transform:translateX(-50%) scale(0.96);background:var(--foreground,#18181b);color:var(--background,#fafafa);font-family:var(--font-sans);font-size:0.72rem;line-height:1;padding:0.42rem 0.6rem;border-radius:6px;white-space:nowrap;opacity:0;pointer-events:none;z-index:30;transition:opacity .15s ease,transform .15s ease;}.tf-act::before{content:"";position:absolute;top:calc(100% + 5px);left:50%;transform:translateX(-50%) rotate(45deg);width:8px;height:8px;background:var(--foreground,#18181b);opacity:0;pointer-events:none;z-index:31;transition:opacity .15s ease;}.tf-act:hover::after,.tf-act:focus-visible::after{opacity:1;transform:translateX(-50%) scale(1);}.tf-act:hover::before,.tf-act:focus-visible::before{opacity:1;}</style><div style="margin:2.25rem 0;border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--background);"><div style="display:flex;align-items:center;gap:0.75rem;padding:0.6rem 0.8rem 0.6rem 1.15rem;border-bottom:1px solid var(--border);background:var(--card);border-radius:var(--radius-lg) var(--radius-lg) 0 0;"><span style="font-family:var(--font-mono);font-size:0.82rem;font-weight:600;color:var(--foreground);">taste.md</span><span style="font-family:var(--font-mono);font-size:0.74rem;color:var(--muted-foreground);">52 lines</span><span style="margin-left:auto;display:flex;align-items:center;gap:0.15rem;"><button type="button" class="tf-act" data-tip="Copy" aria-label="Copy the file" onclick="navigator.clipboard.writeText(document.getElementById('taste-src').innerText);var i=this.querySelector('.cp-i'),k=this.querySelector('.cp-k');i.style.display='none';k.style.display='block';this.setAttribute('data-tip','Copied');var b=this;setTimeout(function(){i.style.display='block';k.style.display='none';b.setAttribute('data-tip','Copy');},1600);"><span class="cp-i" style="display:block;"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" style="display:block;"><rect width="13" height="13" x="9" y="9" rx="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg></span><span class="cp-k" style="display:none;color:#16a34a;"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" style="display:block;"><path d="M20 6 9 17l-5-5"/></svg></span></button><a href="https://raw.githubusercontent.com/MahdiF/agent-files/main/taste.md" class="tf-act" data-tip="Download" aria-label="Download taste.md"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" style="display:block;"><path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"/><path d="m7 10 5 5 5-5"/><path d="M12 15V3"/></svg></a><a href="https://github.com/MahdiF/agent-files/blob/main/taste.md" class="tf-act" data-tip="Open on GitHub" aria-label="Open on GitHub"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" style="display:block;"><path d="M15 22v-4a4.8 4.8 0 0 0-1-3.5c3 0 6-2 6-5.5.08-1.25-.27-2.48-1-3.5.28-1.15.28-2.35 0-3.5 0 0-1 0-3 1.5-2.64-.5-5.36-.5-8 0C6 2 5 2 5 2c-.3 1.15-.3 2.35 0 3.5A5.4 5.4 0 0 0 4 9c0 3.5 3 5.5 6 5.5-.39.49-.68 1.05-.85 1.65-.17.6-.22 1.23-.15 1.85v4"/><path d="M9 18c-4.51 2-5-2-7-2"/></svg></a></span></div><pre id="taste-src" style="margin:0;padding:1.4rem 1.5rem;max-height:430px;overflow-y:auto;background:transparent;border:none;white-space:pre-wrap;word-break:break-word;font-size:0.84rem;line-height:1.7;border-radius:0 0 var(--radius-lg) var(--radius-lg);"><code style="background:transparent;padding:0;"># taste.md&#10;&#10;Read this before writing any UI. These are my defaults.&#10;When they conflict with a library default, mine win.&#10;&#10;## Pick a mode by product type&#10;&#10;Taste is not one look. Pick the mode first, then apply it&#10;without mixing.&#10;&#10;Mode A: minimal tool. Dashboards, admin, internal tools,&#10;reports. The default.&#10;Mode B: juicy consumer. Games and playful consumer apps.&#10;The deliberate opposite of A.&#10;Mode C: editorial brand. Portfolio, blog, marketing. A quiet&#10;reading base with expressive brand moments.&#10;&#10;## Mode A: minimal tool (the default)&#10;&#10;- Light mode by default. Dark is a toggle, never the opener.&#10;- No drop shadows. Separate elements with hairline borders&#10;  and tonal layering. One exception: a soft shadow on a true&#10;  floating layer, like a modal.&#10;- Declutter aggressively. One rich table beats a page of&#10;  stat tiles. If I don't look at a widget, cut it.&#10;- Progressive disclosure over density. Show the essentials,&#10;  collapse everything else behind a tap or a hover.&#10;- This applies to documents too. Organize a report around&#10;  the reader's questions, answer visible, evidence collapsed.&#10;- Strong typography. Tight type scale, hierarchy from weight&#10;  and spacing, tabular numerals for anything with figures.&#10;- Time reads as days, not dates. "7d ago", never "July 21".&#10;&#10;## Mode B: juicy consumer&#10;&#10;- Dark, saturated, tactile. Shadows, motion, haptics and&#10;  sound are features here, not clutter.&#10;- An expressive display font. Buttons that feel pressable.&#10;&#10;## Mode C: editorial brand&#10;&#10;- Quiet where you read, expressive at the brand moments.&#10;- A refined minimal base with juice layered on top. One&#10;  gradient wordmark, one shader moment, subtle sound.&#10;&#10;## All modes&#10;&#10;- Clear hierarchy, deliberate typography, no clutter.&#10;- Self-hosted variable fonts, never a font CDN.&#10;- Every product forks its theme from one shared base, so&#10;  they share DNA without looking identical.&#10;- Always ship a reduced motion and mute opt-out.</code></pre></div>

## Every line is a correction I got tired of repeating

Nothing in this file came from a design book. Every line is something I said to an agent, or to myself, more than twice.

"No drop shadows" is there because I kept getting card grids with soft shadows on every edge, and I find that dated. I corrected it on three projects in a row before I wrote it down. "One rich table beats a page of stat tiles" is a sentence I actually said while reviewing a dashboard that had seven charts I never looked at. The progressive disclosure line exists because a tool once showed me seven score bars per row and I couldn't read any of them.

That's the test for what earns a line: not "do I believe this," but "have I corrected this specific thing more than twice." A principle you admire but never enforce doesn't belong in the file. It's noise the agent will misapply.

## Taste is a mode, not a look

The part of the file that does the most work is the top: pick a mode by product type.

My dashboards are light, quiet, and hairline-thin. The game I shipped this summer is dark, loud, and every button has a fat pressable shadow. Both are my taste. If the file only described one look, every product would come out wearing the same outfit, and half of them would be wrong.

Here are three things I built, in three modes, from the same file.

<figure style="margin:2.75rem 0;">
<div style="border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;background:var(--card);">
<img src="/images/blog/my-actual-taste-file/mode-a-tool.png" alt="A stock watchlist dashboard in Mode A: light background, hairline card borders, no drop shadows, prices set in tabular numerals, one sparkline per ticker." style="display:block;width:100%;height:auto;" />
</div>
<figcaption style="margin-top:0.85rem;text-align:center;font-size:0.85rem;color:var(--muted-foreground);">Mode A, a tool I use daily. Light, hairlines, tabular numbers, nothing floating.</figcaption>
</figure>

<figure style="margin:2.75rem 0;">
<div style="border:1px solid var(--border);border-radius:var(--radius-lg);background:var(--card);padding:3rem 1.5rem 0;display:flex;justify-content:center;overflow:hidden;">
<img src="/images/blog/my-actual-taste-file/mode-b-game.jpg" alt="The home screen of a mobile game in Mode B: a dark purple cosmic background, a thick rounded display logo, a winking emoji mascot in a hoodie, and a fat three-dimensional play button." style="display:block;width:100%;max-width:300px;height:auto;border-radius:14px 14px 0 0;" />
</div>
<figcaption style="margin-top:0.85rem;text-align:center;font-size:0.85rem;color:var(--muted-foreground);">Mode B, a game on the App Store. Every rule above, deliberately inverted.</figcaption>
</figure>

<figure style="margin:2.75rem 0;">
<div style="border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden;background:var(--card);">
<img src="/images/blog/my-actual-taste-file/mode-c-brand.jpg" alt="A personal site homepage in Mode C: a quiet light reading base with a soft gradient bloom behind the headline and a handwritten gradient wordmark." style="display:block;width:100%;height:auto;" />
</div>
<figcaption style="margin-top:0.85rem;text-align:center;font-size:0.85rem;color:var(--muted-foreground);">Mode C, the site you're reading. Quiet where you read, expressive at the brand moments.</figcaption>
</figure>

Same person, same file, same workflow. Three different outfits, picked on purpose.

This is the difference between a taste file and a brand guideline. A brand guideline makes everything match. A taste file makes everything judged. The judgment "this is a playful consumer app, so shadows are a feature here" is as much my taste as the shadows themselves.

## What the file actually changes

The mechanics are boring on purpose. The file lives in the repo. The agent reads it before writing UI, the same way it reads the conventions doc before writing code.

The effect is not that the output gets good. The effect is that the output starts from my defaults instead of the model's. Models have taste defaults, and they're nobody's: dark hero sections, gradient buttons, shadows everywhere, a stat tile row on every dashboard. Without the file, I spend the first three rounds of review removing those. With the file, round one already looks like mine, and review time goes to the decisions that matter.

## Where the file stops working

The honest part. The file captures taste. It does not generate it.

The agent applies the letter, not the eye. It will hairline everything, including the one place a shadow was right. It will collapse detail that should have stayed visible. The file gets it to my defaults; my eyes in the browser get it to done. I have never shipped a screen I didn't look at, and the file hasn't changed that.

It also drifts. Twice now I've deleted lines that stopped being true. A taste file you never prune becomes a brand guideline for who you used to be.

## If you're writing yours

Don't start from principles. Start from your last ten corrections. Open your recent projects, find the things you changed after the first AI pass, and write down the ones that showed up more than twice. That list is your actual taste. The principles you'd have written from scratch are the taste you wish you had.

Write the why next to the what. "No shadows" is a rule. "Separation comes from hairlines and tone, not shadows" is a rule an agent can extend to cases you didn't list.

And keep it to one page. One file, read in full, every session. The moment it needs a table of contents, it's documentation, and nobody reads documentation. Including the agent.

## Get the file

It's on GitHub, free, in a repo I'm using to publish the files my agents read: [github.com/MahdiF/agent-files](https://github.com/MahdiF/agent-files). That version annotates every rule with the reason behind it, which is the part worth stealing. More files will land there as I clean them up.

People keep asking whether publishing this means anyone can copy my taste. They can copy the file. The file is the output of years of corrections; copying it skips the part where it becomes yours. Taste was never the secret. Applying it on every screen, every session, without getting tired, was. That's the part the file automates.
