Last updated: September 2026

Building a post scorer on Jev

A draft goes out as one request carrying seven questions. Four are Score rubrics, three are Nouls. One round trip returns all seven answers with their probability distributions, while you are still typing.

Jev launched on 15 September 2026. This is a write-up of what it takes to put a scorer behind a public endpoint, including the parts that are more annoying than the launch posts suggest. You can try the thing described here at /tools/will-it-go-viral, free and without an account.

The seven questions

TypeSafe documents that Jev takes a state and a map of typed questions, and evaluates every declared question in one parallel pass. That shape decides the design: asking seven questions is one round trip, so there is no reason to ask one. The state here is the draft plus the platform it is headed for.

Question
Primitive
Shape
Why that primitive
strength
Score
5 levels
Reach is ordered, not categorical. Flops sits below typical, which sits below breakout, so the rubric is a ladder and the answer is a point on it.
hook
Score
3 levels
How hard the opening line stops a scroll. The only rubric carrying worked examples, because "strong hook" is too vague to score without them.
clarity
Score
3 levels
Whether a reader with no context understands it on one pass.
specificity
Score
3 levels
Whether the post names real numbers and events, or gestures at them.
slop
Noul
0 to 1
Reads as machine written. Independent of the other flags, so it cannot be a Choice.
bait
Noul
0 to 1
Explicitly asks for likes, reposts, replies, follows or bookmarks.
toxicity
Noul
0 to 1
Slurs, harassment, sexual content or abuse. Gates whether a scored draft can appear in the public feed.

The split between Score and Noul is the whole design. Reach, hook, clarity and specificity are ladders, so they are Scores. Slop, bait and toxicity are independent properties that can all be true at once, so they are Nouls rather than one Choice across categories.

Writing a rubric that scores the same way twice

The interesting work is not the API call. It is writing rubric levels concrete enough that the same draft lands on the same rung tomorrow. The reach rubric below spells out what each level means in terms a person could apply:

lib/viralScore.ts
const STRENGTH_LEVELS = [
  'Flops. Gets less attention than a typical post from the same account.',
  'Typical. Performs about the same as the account usually does.',
  'Above typical. Noticeably more reach and replies than usual.',
  'Strong. Several times the usual reach. Spreads past the existing audience.',
  'Breakout. Orders of magnitude beyond usual. Reaches people who have never heard of the author.',
] as const;

Note what the levels are anchored to: a typical post from the same account. Without that anchor the model scores fame rather than the writing, and every draft from a small account scores low for reasons the writer cannot act on.

One rubric needed more than prose. Hook quality is vague enough that it takes worked examples alongside each level, which the Score primitive supports:

lib/viralScore.ts
hook: score('How well does the opening line stop someone mid scroll?', [
  { level: 'No hook. Opens with context, throat clearing, or a greeting.',
    examples: ['So I was thinking about', 'Here is a thread about'] },
  { level: 'Functional. States the subject plainly without creating a reason to continue.',
    examples: ['3 things I learned shipping a side project'] },
  { level: 'Strong. Creates tension, a gap, or a surprise in the first line.',
    examples: ['I deleted 90% of our code and revenue went up.'] },
]),

The legend comes back in two different shapes

A rubric written as plain strings returns a legend of strings. A rubric written with worked examples returns a legend of objects with a level field. If you read one shape and assume it everywhere, the labels silently come back empty for the other rubrics. Read whichever shape arrived rather than the one you expect.

This matters because the UI names the level a draft reached using the model's own words instead of copy invented afterwards. When the rubric changes, the page changes with it, and there is no second source of truth to drift.

Showing the distribution, not just the number

A Score question does not return a label. It returns a probability for every rung, a probability-weighted float, and a confidence value. A draft the model reads as clearly typical and a draft it is genuinely torn between typical and strong can produce a similar float while meaning very different things.

So the meter renders the confidence band. It is not a design flourish, it is the second half of the answer. If you collapse a Jev Score to one number you have thrown away the part that tells a writer whether to trust it.

Nouls do not carry a confidence field

A Noul returns exactly one thing, a float from 0 to 1. There is no separate confidence value on it, because the float already is the probability. Plenty of third-party write-ups show a Noul with a confidence field. It does not exist. See the primitives reference.

Measuring what each line is worth, instead of guessing

Telling someone their draft scores 2.4 is not useful on its own. What helps is knowing which part is carrying it. Because a score is cheap enough to run repeatedly, you can answer that by measurement rather than heuristics: strip one element, re-score, and report the difference.

lib/viralCorpus.ts
export async function measureAblations(text: string, baseline: number): Promise<Ablation[]> {
  const candidates = ABLATIONS.map((a) => ({ ...a, variant: tidy(a.apply(text)) })).filter(
    (a) => a.variant !== tidy(text) && a.variant.length >= MIN_SCOREABLE
  );

  const scores = await Promise.all(
    candidates.map((c) => scoreStrengthOnly(c.variant).catch(() => null))
  );

  return candidates
    .map((c, i) => ({ key: c.key, label: c.label,
      delta: scores[i] === null ? 0 : baseline - (scores[i] as number) }))
    .filter((a) => Math.abs(a.delta) >= 0.05)
    .sort((a, b) => Math.abs(b.delta) - Math.abs(a.delta));
}

Two details worth copying. Only elements that are actually present and that leave a scoreable draft behind get measured, so you never report a number for something the post did not contain. And deltas under 0.05 are dropped, because below that you are showing the reader noise and asking them to act on it.

Ablations are four extra model calls, so they only run when a draft settles rather than on every keystroke. The strength-only variant exists for exactly this: asking the other six questions would be paying for answers nobody reads.

The configuration to decide up front

These are the values set in the scorer's own code. They are product choices, not measurements of the model.

Figure
Value
Why
What is billed
$0.042 / 1M input tokens
TypeSafe's published list price. Output tokens are not metered, so only the draft and the rubrics are billed.
Client timeout
4,000 ms
A score that arrives late is useless to someone mid sentence.
Retries
1, 200 ms backoff
One retry absorbs a transient failure. More would push past the timeout budget.
Score cap
150 per hour per IP
Invisible to a person writing, useless to someone treating the endpoint as a free API.
Commit cap
30 per hour per IP
Lower, because a commit triggers ablations and a database write.
Percentile floor
200 drafts
Below that the corpus is too small for a percentile to mean anything, so it is hidden rather than printed.

The rate limits are the part most people get wrong when they first ship a Jev endpoint. The usual reflex is to cap by cost, but at the price Jev lists, cost is not what you are defending against. A page that scores on every keystroke needs a cap high enough to be invisible to someone writing a paragraph and low enough that the endpoint is worthless as a free scoring API. Those two constraints, not the bill, picked the number.

What Jev is not doing here

Worth stating plainly, because the category is new enough that people assume more than is there.

  • Jev writes nothing. It cannot. It never emits text, only typed answers. Every word a user sees is either their own draft or our rubric copy.
  • Jev does not write anything in AI Studio either. Generation there runs on a large language model. Jev only scores what comes back, which is work a System One model can do and a writing model cannot do cheaply.
  • A score is a prior, not a result. It is a model's read of a draft before anyone has seen it. Published performance is the real number, and that lives in analytics.
  • Calibrated does not mean correct. Jev always returns a valid answer inside your schema. It can still be confidently wrong, which is a different claim from the one the launch coverage made. See can Jev hallucinate.

7-day free trial. Cancel anytime.

Frequently asked questions

What does the scorer ask?

Every draft goes out as one request carrying seven questions: four Score questions covering reach strength, hook, clarity and specificity, and three Noul questions covering AI-slop, engagement bait and toxicity. One round trip returns all seven answers with their probability distributions.

What does a single Jev score cost?

Jev lists $0.042 per million input tokens, per docs.typesafe.ai/models, and does not meter output, so a short post carrying seven questions is a small fraction of a cent. Model spend is not the constraint on a scorer like this. Abuse is, which is why the endpoint is rate limited by IP rather than by cost.

Why show a distribution instead of a single score?

Because a distribution is what Jev returns. A Score question comes back with a probability for every rubric level plus a probability-weighted float and a confidence value. Collapsing that to one number throws away the part that tells you whether the model is certain or torn between two levels.

Does Jev write the posts in AI Studio?

No, and it cannot. Generation runs on a large language model, because Jev never emits text. Jev scores what the language model produces, so a generated draft arrives with a quality read attached. Writing and judging are separate jobs and they want different models.

Can I use the scorer without an account?

Yes. The scorer is free, needs no signup, and scores whatever you paste into it. Rate limits apply per IP so that the endpoint cannot be used as a free scoring API.

Score a draft, then ship it

The scorer is free and needs no account. When you want the rest of it, scheduling, multi-platform publishing and an API your agent can call, plans start at $11.99 a month.

7-day free trial. Cancel anytime.