Back to Projects
Postmark
CompletedNext.jsReactTypeScript+2 more

Postmark

A Jev-powered draft classifier that vibe-checks social posts in one call. Tone (Choice), viral potential (Score) and cringe risk (Noul) return as typed probabilities with confidence, rendered as bars plus a stamp verdict, no chat parsing.

Timeline

September 2026

Role

Creator & Developer

Status
Completed

Technology Stack

Next.js
React
TypeScript
TypeSafe Jev
SystemOne

Overview

Postmark is a single-page Decision Press that fakes a blunt editor directly in the browser, backed by TypeSafe's Jev System One model.

Paste any draft, it sends the text as state plus three typed questions to POST https://api.typesafe.ai/v1/systemone and gets back structured answers: tone as Choice (hot take / humble brag / inspirational / informative / funny / vulnerable), virality as Score (Ignored / Mild / Solid traction / Breakout on a 0 to 3 scale), and cringe_risk as Noul (0 to 1 likelihood). The UI draws probability bars off those fields and stamps a verdict (Hold up / Send it / You ate) from two plain thresholds (noul >= 0.6, score >= 2.2). No chat text, no JSON repair.

Open source at github.com/silky-x0/Postmark.

Postmark flow

Key Capabilities

  • Three Decisions, One Call: tone (Choice), virality (Score), cringe_risk (Noul) evaluate the same state in parallel via Jev's sampler, returned with probabilities + confidence instead of generated prose.
  • Verdict in Plain Code: useMemo reads virality.score and cringe_risk.noul and applies >= 0.6 / >= 2.2 cutoffs. No second model call, tweak one number to retune strictness.
  • Probability Bars: Tone bars sorted high to low, virality bars sorted by level 0 to 3, widths from Math.round(p * 100). Leading tone highlighted in stamp teal.
  • Server-Side Key: app/api/inspect/route.ts is the only place that touches TypeSafe. Validates non-empty + <= 2000 chars, forwards with Bearer TYPESAFE_API_KEY, passes through 429/529, maps the rest to 502. The client never sees the key.
  • Four Samples: Contrarian take, personal win, intentionally boring PSA (shows low virality), and a long emotional Series A post (shows mixed cringe signals). One click fills the textarea.
  • Paper & Stamp UI: Hand-written CSS, Special Elite + IBM Plex Sans, dotted paper texture, rotated verdict stamps. One column on phones, two at 860px, tighter rules at 640/480px, 16px textarea so iOS never zooms.
  • Custom Favicon: app/icon.svg (paper square, ink border, stamp P, teal dot) wired via metadata.icons.

How It Works

1. Compose (The Draft Card) Textarea with maxLength={2200} but API limit 2000, so the charCount/2000 (too long bestie) counter warns before the button disables. runInspection posts { draft } to /api/inspect and stores the typed InspectResponse.

2. Inspect (The Decision Call)

// buildQuestions: same state, three typed questions
const payload = {
  state: draft,
  model: "jev-latest",
  questions: {
    tone: { type: "choice", instructions, criteria: { "hot take": "...", ... } },
    virality: { type: "score", instructions, criteria: ["Ignored: ...", ...] },
    cringe_risk: { type: "noul", instructions, criteria: { true: "...", false: "..." } },
  },
};
const upstream = await fetch("https://api.typesafe.ai/v1/systemone", {
  method: "POST",
  headers: { Authorization: `Bearer ${apiKey}`, "Content-Type": "application/json" },
  body: JSON.stringify(payload),
});

3. Render (The Stamp) Response shape is trusted: choice + probabilities + confidence, score + legend + probabilities + confidence, noul as number. Bars + verdict render straight off those fields with zero string parsing.

LLM vs Jev Mental Model

Chat-model classifiers need Prompt -> tokens... -> text -> parse + validate -> decision, paying for output tokens and babysitting schema drift. Postmark skips all of that: State + Questions -> typed Decisions -> UI. That is the System One idea: fast calibrated calls for judgment work, slow reasoning models reserved for work that actually needs prose.

Trade-Offs

  • Drafts capped at 2000 chars, single draft at a time, no history or shareable result links yet
  • Tone list is fixed at six options, verdict cutoffs are hand-picked not learned
  • lib/ is empty, verdict logic untested (pure function, easy to cover next)
  • Needs a TYPESAFE_API_KEY, so no offline demo; wrong key surfaces as a red note, not a fallback
  • No postmark.png screenshot in public/blog/ yet, image slot above is a placeholder until one is added

What I Learned

Structured decisions beat structured text: when the model returns probabilities with confidence, the frontend becomes trivial sorting and bar widths. Thresholds belong in plain code next to the UI, not hidden in a prompt. And keeping the API key behind one tiny route is the whole security model.

Try the samples in order: boring PSA first (low everything), then the Series A post (high emotion, mixed cringe), then your own draft.