Bohdan Kryvenko UX Writer / Content Designer
Senior / Lead · Content Design

Copy as a governed system, not a queue of tickets.

Good UX writing cleans up after design. Great UX writing shapes it before production.

I build the frameworks, pattern libraries, and tooling that put it there — voice consistent and standards enforced, across iOS, Android, and web.

OBRIO (Genesis) · Nebula & NebulaX UX Writer & Content Designer · 2025–26
Flagship · System

Copy governance systemA closed loop from Figma to a living canon — two tools with a self-updating source of truth between them.

The problem

The product ships copy across three platforms from one Figma source that doubles as dev handoff. At ~1,600 strings, four things kept breaking:

  • Drift. The same string worded differently across platforms; regressions reintroduced in new versions.
  • Canon rot. The voice & tone guide lived in Notion as a doc nobody re-read; review decisions never made it back in.
  • Bottleneck. Every “is this on-brand?” routed through one writer. Copy QA didn’t scale past one person.
  • No line on pressure. Where persuasion ends and pressure begins got decided screen by screen, by whoever wrote it — nobody was tracking it as a class.

What I built

Deterministic · scale

copy-parityNode.js · Figma REST API

extract pair lint report comment
  • Pulls every text node, pairs equivalents across platforms, lints each against rules.yaml — the copy canon as code, where adding a rule means one regex in a config file.
  • Posts findings back onto Figma frames as node-anchored comments. Read + comment only — never mutates the canvas.
  • Catches the machine-checkable class across 1,600+ strings in one pass: casing, broken tokens, drift, banned constructions.
Judgment · on-demand

ux-copy-auditAI skill · Notion via MCP

screenshot in check canon before/after out
  • Anyone — PM, designer, writer — drops a screenshot or Figma frame. No briefing; the skill carries the context.
  • Reads the live authority stack from Notion: the UX Copy Patterns DB (Status = Active), tone-of-voice pillars, naming rules — then judges the screen against canon.
  • Returns a before/after with rationale. Approved calls graduate back into the Patterns DB and land in Field Notes with per-writer attribution.
How the loop closes
1Figma / screenshotany surface
2Auditregex + judgment
3Before / after+ rationale
4Human approvalwriter / PM
5Graduate to canonPatterns DB
↩ feedback Every approved decision sharpens the canon — so the next audit starts smarter. The canon lives as the system’s runtime state, kept current by every audit. And it’s team-scoped: multiple writers feed and draw from the same source.

Impact

1,600+
copy changes triaged into a Notion review pipeline
Team
standard for UX-copy audit — writer capacity removed as the bottleneck
30+
high-stakes surfaces rewritten — monetization, error taxonomy, onboarding, the intake funnel
I treat copy as an owned system — methodology, canon-as-code, tooling, and a feedback loop that keeps voice consistent at team scale.

Next: merge the deterministic and judgment halves into one LLM-in-the-loop linter.

A slice of the parity matrix — what pair + lint emit
CanoniOSAndroidWebStatus
Not nowNot nowNot nowNot nowidentical
See psychicsSee psychicSee psychicsSee psychicsdrift
Chat longer and saveChat longer & SaveChat longer and saveChat longer and savestyle
Recommended for youRecomended for YouRecomended for You— missingtypo · gap
[Name][Name][ExpertName][Name]token

Caught as a pattern, fixed once

The payoff, in one number. One unverifiable claim — Voted most accurate — had quietly shipped across the product:

81screens carried it
6surfaces
1ruling in the canon
Chat flows33
Premium hub17
Calls16
Membership9
Catalogue4
Post-chat2

One claim, shipped to 81 screens. Plain text-similarity linting misses this class — it isn’t visible “drift,” it’s a canon issue. The system surfaced every instance; one ruling fixed them all.

What the linter clears

A sample of the machine-checkable class the linter now clears on every run, so judgment goes to the calls that need it. Examples are illustrative.

− [placeholder]+ Incorrect email or password. Please try again.
Dev placeholder text reaching a live error state.
− You need >30 credits on the balance+ You need more than 30 credits in your balance
A math symbol in reader-facing paywall copy.
− Need an account? Sign up+ Already have an account? Log in
Backwards — the link sat on the Sign Up screen itself.
− We sent you an email instructions to reset your password+ We sent you an email with instructions to reset your password.
Password reset — a broken noun phrase.
− once or every time they\re available+ once or every time they’re available
An escaped backslash rendering as literal text.
− You can archive unnecessary chats!+ You can archive chats you don't need. Swipe left to try it.
Calling a user’s own chats “unnecessary” works against an empathetic voice.
Case study
Case study · Trust

Trust by designResonance without pressure — in a product built on hope, for people who arrive at vulnerable moments.

People come to a psychic-chat product mid-breakup, in grief, or facing a hard decision. That’s the moment copy has to earn trust rather than spend it — and the frictionless version always pulls harder than it should. I held the line between resonance and pressure on every surface a user meets — the conversation, the promos, and the money flow — and encoded it into the system so the line holds without me.

Part 1 · In the conversation
Auditing a chatbot intake funnel where the whole conversation is the unit of analysis

The brief was “here’s the flow, fix the copy” — a ~220-string chatbot funnel steering new users toward a trial psychic chat. I reframed the problem before touching a word.

A line can be perfect alone and broken in sequence — “Got it.” landing four times in a row. So the unit of audit isn’t the string. It’s the assembled dialogue.
Path-level finding · assembled transcript
answers genderGot it.
answers statusGot it.
taps “Other”Got it.
answers focusGot it — this is an internal journey.
Each line is fine on its own. Four “Got it” openers in a row read like a machine — and nothing in a string-by-string review would ever surface it. The fix below changes what each reaction is doing, step by step.

I ran two passes: a string-level pass, and a path-level pass — programmatically assembling seven end-to-end transcripts and reading them as real conversations for rhythm, repetition, and cumulative tone. The audit framework had no conversational lenses, so I built five and added them as a reusable pattern family:

PersonaTurn designSequence rhythmPromise vs. intentBot → human handoff
One of the most common and most painful fears. You're not alone in it.
+So many people secretly carry "am I enough" — you're not alone in it.
Vulnerable-moment reaction. “Common” quietly devalues the very fear the user just admitted. Normalize without diminishing.
Your psychic will show you where closure actually comes from.
+Waiting for closure that never came — that ache is real. It deserves a real answer.
Outcome guarantee → process. Process verbs (read, tune into, look at) are fine; guaranteeing an outcome is a hard voice prohibition for an entertainment-only service.
The future feels uncertain right now. I want to understand why.
POV bug (flagged 🔴). The bot speaks in the user’s own voice, then answers itself. Persona integrity: the assistant prepares the question, the human psychic reads.

The lead moment — give each line a job

After the PM signed off, the real question surfaced: how are these responses even formed? The whole corpus ran on one generator — mirror the user, weigh the feeling, bridge to the psychic — so it read like a catalog of captions. The assistant never responded — it evaluated. The fix wasn’t another polish pass. It was giving authors a palette of conversational jobs and a quota per path.

User taps: “I work hard but I’m invisible and overlooked”
Mirror

Being good at what you do and still not being seen — that chips away at you.

Presence

That’s an exhausting way to work. I’m glad you said it straight.

Normalize

More people carry this one than ever say it out loud.

Silence · bridge

Noted — word for word. This goes to your psychic as is.

One option, four different jobs. The rule: on a ~7-reaction path — 3 mirrors · 2 presence · 1 normalize · 1 bridge. A constitution for the copy — the rules authors write to. And it’s a trust question, not only a style one: a corpus that weighs every feeling on the same scale is performing care rather than offering it, and users hear the difference.
44
changes shipped (13 critical / 31 refinements) across the funnel
7
end-to-end transcripts assembled to audit at the path level
232
assistant replies mapped — including the bot → human handoff I wrote for the end of the flow
Part 2 · On the promo surfaces
Promises a product can’t keep

Outside the chat, pressure shows up as certainty: a result stated as fact, a card that “confirms” your path. Each rewrite below keeps the emotional pull — what goes is the guarantee.

Quiz — result screen
Before

Your result: You’ve already met

There’s a high chance that you’ve already met your soulmate from a past life. Those intense feelings you have are real soul nudges, not just daydreams. Who is it: an old friend, a chance encounter, or someone close?

Tips to recognize your soulmate
  • Don’t wait for the perfect timing — some soul contacts appear wrapped in chaos, not clarity
  • Notice when time slows down — it may be your soul’s way of signaling something real
FINISH
After

Your result: A familiar connection

Some people describe feelings like this when they’ve crossed paths with someone important before. Who is it: an old friend, a chance encounter, or someone close?

Tips to recognize your soulmate
  • Don’t wait for the perfect timing — some soul contacts appear wrapped in chaos, not clarity
  • Notice when time slows down — it may be your soul’s way of signaling something real
FINISH
A destiny promise, stated as fact — twice. The headline declares the reunion happened and the body backs it up with “real soul nudges,” to someone who arrived hopeful. Both hedge in the rewrite: the pull survives, the claim the product can’t make doesn’t.
Tarot — daily insight
Before
📖 Description

The Star encourages you to open your heart and believe in the possibility of a better future. Let go of fear and cynicism, and reconnect with a sense of wonder and purpose. This card confirms that you are on the right path — keep moving forward with serenity and confidence. Your wishes have been heard.

Personal Tarot Reading

Get the best guidance and advice! Whether you are looking for insight, guidance, or comfort, you can be sure to find it in your Tarot Reading.

After
📖 Description

The Star encourages you to open your heart and believe in the possibility of a better future. Let go of fear and cynicism, and reconnect with a sense of wonder and purpose. This card is an encouraging sign — keep moving forward with confidence.

Personal Tarot Reading

Want to go deeper? Chat with a psychic for guidance tailored to you.

Two guarantees on one screen. A card that “confirms” your path and “wishes have been heard” is destiny language; “you can be sure to find it” promises an outcome. Encouragement and an honest CTA do the same job without the promise.
Catalogue screen, audited 1
Catalogue — the “Most Accurate” shelf
1
Most Accurate — Psychics our community rates most accurate
+Top-rated psychics — highly rated by our community
Unverifiable accuracy claim. “Most accurate” promises prediction accuracy no one can measure; a community rating is defensible, an accuracy guarantee isn’t. The web wording of this same claim had shipped to 81 screens — see the flagship.
Same principle · other surfaces
✨ In 8 days, you won’t feel alone anymore. You’ll know someone special is just around the corner…
+After these 8 days, you’ll have a clearer sense of what you’re looking for — and the signs to recognize it when it shows up.
Interval reading. A manufactured emotional guarantee (“you won’t feel alone”) → a promise the product can actually keep.
Part 3 · In the money flow
Holding the line in the money flow

Money flows are where the canon has to be strictest — the stakes are highest, and every subscription product feels the pull to press harder there. Four patterns came out of the standards work; three are now encoded as lint rules, so every future instance gets flagged without me re-reading a single screen.

1Confirmshaming caught by rules.yaml
Before

Before you go

Your subscription renews on June 14. Cancel now and you keep access until then.

We can also add one free week to your plan — no charge, no commitment.

Add a free week
I don’t want free week of usage — I want to cancel my subscription
After

Before you go

Your subscription renews on June 14. Cancel now and you keep access until then.

We can also add one free week to your plan — no charge, no commitment.

Add a free week
Cancel subscription
Guilt as the price of leaving. An exit link worded this way makes the user decline a gift out loud to cancel. The offer stays — it just stops being the toll on the exit.
2Manufactured urgency caught by rules.yaml
Before

Don’t miss your chat: share your phone number to get instant notifications

We’ll text you when your psychic replies, so you don’t have to keep the app open.

+1 (555) 000-0000
Continue
Not now
After

Get notified when your psychic replies

We’ll text you when your psychic replies, so you don’t have to keep the app open.

+1 (555) 000-0000
Continue
Not now
Urgency doing the work a benefit should do. Nothing is expiring, and what’s being asked for is personal data. Lead with the benefit, then ask. The same rule catches “Don’t miss out on a single perk” and “Don’t miss a thing.”
3Manufactured anxiety → upsell
Your energy is blocked but we have the tools to help you. Explore … our Qi Gong video course and shield yourself from energy drains.
+Feeling drained is common — some people find breathwork helps. Explore our Qi Gong course.
A diagnosis a product can’t make, used as the reason to buy. Naming a feeling is fine; asserting a blocked energy state and charging for the cure isn’t. No regex catches this one — it takes a read.
4Directive pressure caught by rules.yaml
You have to accept
+Accept to continue
“Have to / must / should” removes the user’s standing to decline. The directive-modality rule flags all three across the product.
Encoded once, enforced everywhere

Three of the four aren’t found by reading screens one at a time. confirmshaming, urgency-scarcity and directive-modality are rules I encoded in rules.yaml, so the linter flags every instance on every screen — including the ones written after me.

What came of it

44
copy changes signed off by the PM and written into the next version of the flow
5
new review criteria for chat copy — adopted into the standards the whole writing team works from
4
dark-pattern checks built into the linter — they run automatically, for every writer

One line runs through all of it — the conversation, the promos, the paywall: a product built on hope can’t grow by spending users’ trust, and the honest choice should never be the harder one.

Let’s talk.

I’m after senior/lead content design where copy is owned as a system.