A ← Ashley Kim
Ashley Kim · Design, build, and operation · Spotstars

Every screen in this app was produced by an agent reading a file I wrote.

What does a design system become when the thing reading it is a machine?

Spotstars answers one question: what is this friend to me. Your friends sit on a printed star chart, sorted into six roles, and the app tells you who to stay close to today. I designed it, wrote it, built it, and I operate it. Six people use it daily on their own accounts. Sixteen days from an empty folder to version 11.7.

16 days
Empty folder to live v11.7
August 24 to September 8, 2026. About four hours a day, alongside a full-time job.
28×
Rules and language vs calculation
650 KB of content and rules against 23 KB of engine. Measured from the source.
6
People using it every day
Real accounts, real birth data, real friend lists. Not a click-through demo.
RoleSole designer, writer, builder, operator
Scope14 screens, English and Korean
StackVanilla JS, Supabase, astronomy-engine, Netlify
StatusLive, in private testing
Prototype

The app, running here

This is the real build, not a click-through. Every score below is computed live from the birth data of eight synthetic people.

The frame runs a copy of the production app with the database credentials removed, so it seeds a demo account in memory and makes no network calls at all. The maps, the roles, the scores, the readings and the copy pools are the shipped code. Try the three map views, open a friend, switch between Today, Month and Life.

Live build · offline · synthetic data

Open full screen →

The eight people in this prototype are fictional and were already in the codebase as a demo fixture. The production app runs on real accounts with a login, which is why it cannot be embedded directly.
The product

A map of the people around you

Astrology apps are read alone, or one friend at a time. This one puts everyone on the same page and gives each person a job.

The people I built this for read their horoscope and then talk about it, with a partner, a sibling, a group chat, the person at the next desk. The existing apps do not support that conversation. They give you a paragraph about yourself, or a compatibility score against one other person, and the talking has to happen somewhere else.

So the unit of this product is not the reading. It is the map. Thirteen friends, six roles, one chart you can point at. Distance from the center is how good that person is for you today, which means the picture changes every morning and gives you something new to say.

Three views of the same thirteen people
My Star map
My StarCloser to the center is better for you today. The black sun is you.
Roles map
RolesSix sectors. The sixth is defined by the user.
Zodiac wheel
Zodiac wheelEveryone sits in their own sun sign.
The six roles are the product decision
Role definitions sheet
What the six meanEvery term in the app is one tap from a plain-language definition. No degrees, no houses, no aspect names anywhere in body text.
Friends list
FriendsRole, sign, today score, and one line. The grid is the only place in the app where content sits in a card.
A reading
Me today
Me, todayOne large serif number, one headline, then the day in plain sentences.
Luck and do dont
Luck, do and don'tNouns rather than sentences, for reasons the research section explains.
Friend reading
A friendThe same skeleton, pointed at one person.
Friend names in every screenshot are replaced. The people testing this app agreed to test it, not to appear in a portfolio. The layout, the name lengths, and the overlaps are unchanged.
The shape of the work

935 KB of source. 23 KB of it is math.

The artifact is the rule that produced the screen. The screen is what falls out of it.

I measured the source when the case study was written. The astrology engine, the part that positions planets and computes a score, is the smallest thing in the project. Everything above it is language and rules: what the app is allowed to say, in what tone, in two languages, under which conditions.

Source by folder, September 8 2026
content650 KB
data147 KB
ui92 KB
engine23 KB
db15 KB

That ratio is the whole argument. When an agent writes the code, the scarce thing stops being implementation and becomes specification. A screen I do not like is rarely a screen problem. It is a rule that was missing, or a rule that was wrong, and the fix has to land in the rule or it comes back on the next screen.

Working this way changed the question I ask in a review. It used to be what does this screen look like. Now it is which rule produced this screen, and is that rule right.

The system

Three files, three kinds of failure

The design system is not one document. It is three, and they exist because three different things kept going wrong. Each one is a markdown file an agent reads before it touches anything.

What it looks likeDESIGN.md

119 lines. 43 rules across color, type, layout, components, do and don't, and hierarchy. 19 color tokens, 12 type steps, and an image-prompt paragraph so generated art comes back in the same world.

Without it: icons rendered as iOS colour emoji and broke the ivory palette on the first build.

What it saysspotstars-writing

Every user-facing sentence in both languages. Bans raw astrology vocabulary in body text. Enforces one test on every line: so what, for my day.

Without it: every reading resolved to some version of "reach out to them today".

What it must not breakCLAUDE.md

Operating rules for the agent itself. Exact-string replacement only, never range deletion. Read and report, wait for confirmation, change, test, boot-check, commit.

Without it: a single line edit was one keystroke away from deleting 4,407 cities.

The third file is the one most design systems do not have, and it is the one that saved the project. A design system that a machine executes needs a section about what the machine is forbidden to do, not only what it should produce.

How the rules got written

Five rules, and the failure that produced each one

None of these were written in advance. Every one is the scar of something that went wrong in a build, got diagnosed, and got turned into a line an agent now reads before it starts.

RULE 01

Never delete by range. Exact string replacement, and parse before writing.

What happened

The city database is a single enormous one-line object. An agent asked to remove some entries proposed a line deletion, which in that file means deleting all 4,407 cities.

Why it matters

The failure is silent. Tests pass, the app boots, and the country picker is empty three commits later.

After the rule

The North Korea exclusion ran cleanly: 4,407 cities to 4,391, 248 countries to 247, verified by a test that guards those two counts.

RULE 02

Every score surface gets its own calibration curve. Never share one.

What happened

The Life score on my own tab quietly reused the curve built for friend compatibility. Every result landed between 47 and 68. The screen looked fine. The numbers were wrong.

Why it matters

Given no rule, an agent reaches for the nearest existing thing that fits the shape. Reuse is its default, and reuse of a curve is invisible in a screenshot.

After the rule

Six named curves, one per surface. Life on the Me tab now spans 55 to 100 with its centre in the seventies, like every other surface.

RULE 03

What appears in every comparison must be weighted down, not up.

What happened

All thirteen friends rose and fell together on the same days. My own chart is the one input present in every pair, so it was driving all thirteen scores at once.

Why it matters

This is a design failure that only shows up in aggregate. On any single friend's screen the number is plausible. Only the map makes it visible.

After the rule

My chart weighted at 0.3 against the friend's 1.0. Correlation between friends fell to zero, and the map now moves the way the concept promised.

RULE 04

Copy variety is a pool problem, not a generation problem.

What happened

Headlines were selected by which planet was strongest that day. Planets move slowly, so the same sentence held for four or five days and the app felt broken.

Why it matters

The obvious fix is to generate fresh text. That trades a copy problem for a quality problem and a cost. The real fix was structural.

After the rule

Band-keyed pools with a running no-repeat cursor. 88 lines for the Me headline, 528 for friend headlines. Probability of a repeat inside 60 days is 6 percent, calculated rather than guessed.

RULE 05

Dark mode is a recolour of the light asset, never a second generation.

What happened

The dark constellation set was generated separately from the light one. The poses came back different, so switching theme moved the artwork.

Why it matters

Two generations of the same prompt are two different drawings. Consistency across themes has to come from the pipeline, not from a better prompt.

After the rule

One 4K sheet, twelve crops, then a colour transform for dark. 24 assets, 4.6 MB, pixel-identical across themes. It also corrected an older note in my own files: high-resolution sheets work fine, low-resolution ones do not.

The same system in both themes
Light map
LightIvory canvas, hairline rings, serif names.
Light me tab
Light, readingSame skeleton, same type scale.
Light sheet
Light, sheetRole colours carry meaning in both themes.
Research

Two competitor findings that changed the writing

I read the four apps people in this category actually use, and two of them changed a rule rather than confirming one.

Co-Star writes its Do and Don't as nouns, not sentences. "Bubble tea." "Imposter syndrome." Why it mattered: when I wrote mine as sentences, every one collapsed into an instruction to contact someone. The noun form carries a mood without pretending to know your day. I rewrote the whole set.
CHANI structures a daily reading like a weather forecast, not a fortune. Why it mattered: it gave me the order for the reading body. What is happening in the sky, where it lands on you, how the day is likely to run. Three beats, in that order, every time.
Sanctuary uses many colours and many cards. Why it mattered: this one became a rule about what not to do. Reading screens in Spotstars have no cards at all. Hierarchy comes from type size and hairlines. If a screen needs a third colour, the design is wrong.
Open problems

What is still wrong, on the day this was written

The design system has a Known Gaps section. It is the section I trust most.

These are four defects visible in the screenshots above, taken from the live build on September 8. Three of them the rule files already predicted.

Predicted by the system

Names collide in crowded sectors

On the Roles map, two friends in the same sector render as one unreadable string. DESIGN.md lists cluster marks for crowded sectors under Known Gaps. The gap was documented before it became visible, and it is now visible.

Open since Aug 31

Light mode contrast on the map

The ring lines and the constellation artwork behind them sit at similar values in light mode, which competes with the friend names. Raised in an audit two weeks ago, still unresolved. The candidate fixes are lowering the artwork opacity in light only, or dropping it there entirely.

Scale conflict

90 at the top, 38 below it

A friend screen shows a today score of 90 and area scores of 54, 41 and 38 on the same scroll. They are different scales, and nothing on the screen says so. A reader is right to ask which number to believe.

Content bug

The same sentence twice

When one planet forms two aspects with the same meaning, the reading prints the identical clause twice in a row. The selection logic has no deduplication step. Reproducible, and small to fix.

Two of them, in the build
Roles map with colliding names
CollisionTwo names in one sector render as one string.
Friend areas
Scale conflict90 above, 38 below, no explanation between them.
Next

The promise the app has not kept yet

The reason to build this was that people talk about their horoscope together. Right now every user still looks at their own map alone. Sharing is an invite link and nothing more. That is the largest gap between the concept and the build, and it is bigger than any of the four defects above.

The next version has to make the map a thing two people look at at once. Everything else on the roadmap, the account system, the paid tier, the ad placements, is downstream of that.

The part I will carry into any team is the working method. A design system written for a machine to execute, with a section on what the machine must not do, and a rule for every failure that has already happened once.

I can walk you through any rule in this system and the failure that wrote it.

The prototype above is the shipped code. The three markdown files and the commit history are available on request.

Ashley Kim · ashleykim1229@gmail.com

SPOT OM case study → · Platform Modernization → · Service Platform →