Changelog

What we shipped (and when)

The product moves continuously. This is the public record.

May 24, 2026

Share extension scaffold for iOS + Android (EAS Build only)

feature

title: "Share extension scaffold for iOS + Android (EAS Build only)" date: "2026-05-24" tag: "feature"

The Inksong mobile app can now appear in the iOS share sheet and respond to Android share intents — "Humanize this" lands in /humanize (for text and URL shares) or /upload (for file shares) with the payload pre-filled.

What landed

  • expo-share-intent config plugin in mobile/app.json with iOS activation rules for text + URLs + a single file, plus an Android intent filter for text/*.
  • mobile/src/lib/shareIntent.ts — a React hook that picks up incoming share payloads and routes them. Lazy-requires the native module so it gracefully no-ops when absent.
  • Root layout mounts useShareIntentRouter() so the subscription is always live.
  • /humanize and /upload screens accept the routed payload via useLocalSearchParams and pre-fill on mount.

Important caveat

This only runs in EAS Build, not Expo Go. Expo Go is a single fixed app bundle that can’t add an iOS share-extension target or register Android intent filters at runtime. To test the actual share-sheet behavior you need a development build:

eas build --profile development --platform ios
eas build --profile development --platform android

In Expo Go the share-intent code is a no-op and the rest of the app still works.

What this closes

This was the last item on the originally-decomposed mobile roadmap. We’ve shipped:

  • 5a — scaffold + auth + 3 screens
  • 5b — humanize-from-paste flow
  • 5c — in-app document upload
  • 5c.2 — system share extension (this one)
  • 5d — voice profile CRUD
  • 5e — push notifications
  • 5f — workspaces + webhooks read UIs

Source ships now. First App Store / Play Store submission is still a maintainer task (separate Apple Developer + Google Play accounts) and would happen via EAS Build / EAS Submit.

May 23, 2026

Push notifications on mobile

feature

title: "Push notifications on mobile" date: "2026-05-23" tag: "feature"

Your phone now buzzes when an Inksong humanization finishes. New Document ready and Humanize failed pushes land alongside any webhook deliveries you have set up.

What landed

  • Backend: a push_tokens table (alembic 0014) + two endpoints — POST /api/v1/push-tokens registers an Expo token, DELETE /api/v1/push-tokens/{token} revokes it. The mobile client uses both.
  • Service: app.services.push.push_notify(user_id, title, body, data) is a fire-and-forget helper that looks up the user’s registered tokens, batches a request to Expo’s push API, and deletes any tokens Expo reports as DeviceNotRegistered so we self-clean as users uninstall.
  • Pipeline integration: alongside the existing fire_event("document.completed", ...) for webhooks, the pipeline now also calls push_notify(...). Same on the failure path. Both paths fire after db.commit() so the push fires only if the state actually persisted.
  • Mobile: on the first successful humanize (or upload), the app asks for notification permission. If granted, it registers the device’s Expo push token (ExponentPushToken[...]) with the backend. Sign-out unregisters that token. The permission ask is opt-in and degrades silently if denied.

Why Expo’s push API

Expo wraps both APNs and FCM with a single endpoint. We don’t need Apple push certificates or Firebase service accounts in production — just an Expo project. The trade-off: Expo’s push service is best-effort, not enterprise-grade. Acceptable for “your humanization is ready”; not what we’d use for paging an on-call engineer.

Tests

Seven new backend tests cover the endpoint contract (register, idempotency, validation rejects non-Expo tokens, delete), the service’s send batching, and the DeviceNotRegistered cleanup path. Total backend: 126 → 133 passing.

What’s next on mobile

The system share extension + Android intent filter (5c.2) is the last piece of the mobile roadmap. After that, mobile + web reach parity on the surfaces that should be on mobile, with the trickier admin tasks intentionally staying on the desktop.

May 22, 2026

Workspaces and webhooks on mobile (read views)

feature

title: "Workspaces and webhooks on mobile (read views)" date: "2026-05-22" tag: "feature"

You can now see your workspaces, their members, and your webhook subscriptions + delivery history from the Inksong mobile app. Admin actions stay on the web — that’s deliberate.

What landed

  • /workspaces — list the teams you belong to with your role and member count.
  • /workspaces/[slug] — workspace detail with member list, role chips, pending-invite list. A "Manage on the web" link covers everything mobile doesn’t do.
  • /webhooks — list your webhook subscriptions, masked signing secret, active/paused status.
  • /webhooks/[id] — webhook detail with the recent delivery log (event type, HTTP status, attempt count, success/failure).
  • Home screen promotes both into "what works on mobile today".

Intentionally not on mobile

The desktop is the right surface for these:

  • Creating a workspace, renaming, inviting members, changing roles, removing members, deleting a workspace. All of these need careful confirmation states and longer-form input.
  • Creating webhooks, rotating signing secrets, pausing/deleting subscriptions. The signing-secret reveal-once flow is much safer on a desktop where you can paste straight into a notes app or password manager.

Each mobile detail screen has a "Manage on the web" link to the relevant /dashboard/... page so you’re one tap from doing the thing.

Implementation

No backend changes. Five new mobile API functions over existing endpoints. Existing 14/14 jest tests pass — no new tests added; these screens are pure list/detail reads against typed responses.

What’s next on mobile

Push notifications (5e) is next, then the iOS share extension + Android intent filter (5c.2).

May 21, 2026

Voice profiles on mobile

feature

title: "Voice profiles on mobile" date: "2026-05-21" tag: "feature"

Train Inksong on your own writing from the mobile app. New "Voice profiles" entry on the Home screen leads to a list of your existing profiles and a "New profile" button.

What landed

  • /voice-profiles — pull-to-refresh list of your trained profiles. Each row shows the profile name, sample count, and a delete button.
  • /voice-profiles/new — create form: name, optional description, and a sample-text TextInput. We accept any sample ≥ 200 characters; paragraphs separated by blank lines become individual samples.

What’s not in this release

  • Selecting a profile when humanizing. Phase 5d ships create + list + delete. The profile picker on /humanize and /upload comes next (5d.2). For now, mobile humanizations don’t apply a voice profile — use the web if you want to apply an existing profile during humanize.

Implementation

No backend changes. The mobile API client adds three new functions over the existing /api/v1/voice-profiles/ endpoints: getVoiceProfiles, createVoiceProfile, deleteVoiceProfile. Two new jest tests cover the body shape on create and the read-list path.

What’s next on mobile

Phases 5f (workspaces + webhooks read UIs), 5e (push notifications), and 5c.2 (system share extension via EAS Build) follow this one in sequence.

May 20, 2026

Document upload on mobile (DOCX, PDF, TXT, MD)

feature

title: "Document upload on mobile (DOCX, PDF, TXT, MD)" date: "2026-05-20" tag: "feature"

You can now humanize files from the Inksong mobile app. Tap "Or upload a file instead" on the Humanize tab, pick a document from your phone’s Files app, and get the humanized text back without bouncing out to the web.

What landed

  • New /upload screen on iOS and Android, pushed from the Humanize tab. Pick a DOCX, PDF, TXT, or MD file up to 50 MB. Tone + humanness controls match the paste-text flow.
  • expo-document-picker drives the file pick — system Files app on iOS, Android Storage Access Framework on Android. Works in Expo Go without any native config.
  • Result UI mirrors the humanize tab: before/after AI score chips, the humanized text selectable + shareable.
  • Home screen now lists "Upload a document" alongside the other working features. "File uploads" comes off the web-only list.

Under the hood

No backend changes — the mobile client just talks to the existing POST /api/v1/documents/upload endpoint. The new mobile helper builds a multipart/form-data body with React Native’s FormData and the same tone / humanness / voice_profile_id fields the web sends. Polling and result display reuse Phase 5b’s pollDocument machinery.

Honest scope

The system share extension — "Humanize this" in the iOS share sheet when you long-press a document or share from Files / Pages / a chat app — is not in this release. It needs a separate iOS target via a config plugin and only works through EAS Build (not Expo Go). Same story on Android with intent filters. Both are on the roadmap for a follow-up phase.

What’s next on mobile

  1. iOS share extension + Android intent filter (5c.2) — needs an EAS Build setup.
  2. Voice profiles (5d) — create, apply, manage.
  3. Push notifications (5e) — ping you when a long job finishes.
  4. Workspaces + webhook management UIs (5f) — both read-mostly.

Source ships now; first App Store / Play Store submission is still a maintainer task.

May 19, 2026

Humanize on mobile (paste → result, in-app)

feature

title: "Humanize on mobile (paste → result, in-app)" date: "2026-05-19" tag: "feature"

You can now humanize text from the Inksong mobile app without bouncing out to the web. New “Humanize” tab between Home and Documents.

What landed

  • /humanize screen on iOS and Android: paste up to 5,000 words (10,000 on Enterprise), pick a tone, set the humanness slider, hit Humanize. Live polling shows progress; the result card shows before/after AI-likelihood scores and the humanized text. Copy or share via the system share sheet.
  • Tab bar grows to four: Home, Humanize, Documents, Settings.
  • Home screen no longer lists humanize as a web-only thing — it now points at the new tab.
  • Tone selection on mobile starts with four options (balanced, academic, casual, professional). The longer tail of tones (pastoral, creative, journalistic) stays on the web; the screen calls that out honestly.

What’s under the hood

One new backend endpoint, POST /api/v1/documents/text, takes a Bearer token plus {text, tone, humanness_level, voice_profile_id?} and creates a Document the same way /documents/upload does — lands a synthetic .txt artifact in storage, enqueues the job, returns the job_id. The mobile client polls GET /documents/{job_id} with exponential backoff (1.2s → 4s cap) until status is completed or failed.

The web’s QuickHumanize component continues to fake a file upload for now; a future cleanup will migrate it to the new endpoint.

What’s next on mobile

In rough order:

  1. File uploads on mobile (Phase 5c) — document picker + the iOS share-extension entry point so “Humanize this” lives in the share sheet.
  2. Voice profiles — create, apply, manage.
  3. Push notifications — ping you when a long job finishes (and let you close the app while it runs).
  4. Workspaces UI + webhook management — both read-mostly.

Source ships now; first App Store / Play Store submission is still a maintainer task.

May 18, 2026

Inksong on iOS and Android (v1 — read-only)

feature

title: "Inksong on iOS and Android (v1 — read-only)" date: "2026-05-18" tag: "feature"

The Inksong mobile app source ships in this repo today. It runs on iOS and Android via Expo. App Store / Play Store submission is a separate step gated on developer-account credentials.

What works in v1

  • Sign in + register with the same email + password as the web.
  • Documents: read your previously-humanized documents. Tap a row to see the result; copy or share via the system share sheet.
  • Account view: plan, credits remaining, sign-out, web-dashboard link.
  • Token refresh via the device’s secure storage (iOS Keychain, Android Keystore).

What it doesn’t do yet (and won’t pretend to)

The home screen is explicit about this — no greyed-out menu items, no fake placeholders. Humanizing new text, uploading documents, voice-profile training, workspace management, and webhook setup are all linked out to the web dashboard until their mobile counterparts ship.

Architecture

  • Expo SDK 52 (managed workflow) + TypeScript strict mode + Expo Router for file-based routing — the same mental model as frontend/.
  • Uses expo-secure-store for the refresh token (the web’s httpOnly cookie isn’t portable to mobile). Backend opts into returning the refresh token in the JSON body when the request carries X-Client: mobile.
  • One small backend change: TokenResponse.refresh_token is now an optional field, populated only for mobile clients. Web behavior is unchanged.

Running it

cd mobile
npm install
npm start
# Scan the QR with Expo Go on your phone, or press i/a for a simulator.

What’s next on mobile

In rough priority order:

  1. Humanize flow — paste text, see job progress, see result, copy back to clipboard.
  2. Document upload — file picker plus the iOS share-extension entry point so you can “Humanize this” from anywhere.
  3. Voice profiles — create + manage.
  4. Push notifications for completion events.
  5. Workspaces & webhooks UIs — both read-mostly, both straightforward.

Source ships now; first App Store / Play Store submission is a maintainer task on the same shape as the SDK publish gates.

May 17, 2026

Webhooks (real delivery) + SDK source for JS and Python

feature

title: "Webhooks (real delivery) + SDK source for JS and Python" date: "2026-05-17" tag: "feature"

Closing out Phase 4 of the platform build. Two pieces, both honest about what shipped and what didn’t.

Webhooks

You can now subscribe an HTTPS endpoint at /dashboard/webhooks and Inksong will POST a signed JSON payload every time one of your documents completes or fails.

  • Events: document.completed, document.failed. One subscription receives all events for your account.
  • Signing: HMAC-SHA256 over "<timestamp>.<body>", with the signing secret as key. Header: Webhook-Signature: t=...,v1=.... We show you the secret exactly once at create time and at rotate-secret time.
  • Retries: 4 attempts total — initial + 3 retries at 1s, 5s, 30s backoff. ~36s worst case per delivery. Past that, the delivery is marked failed and you see it in the dashboard log.
  • HTTPS required in production. Private network targets are rejected.

Full reference: /docs/webhooks.

SDKs (source-only at this release)

The Inksong SDK source for Python and Node.js ships in this repo:

  • Python at sdks/inksong-python/ — targets Python 3.10+, single dependency on httpx.
  • JS / TypeScript at sdks/inksong-js/ — targets Node 18+ (and works in modern browsers).

Both expose an InksongClient for humanize / documents / voice profiles, plus a verify_signature / verifyWebhookSignature helper that pairs with the webhook signing format above.

Not yet published to npm or PyPI. First publish to those registries is a one-way commitment to a package name, and we want to do it deliberately. The READMEs document the publish steps. Install from the repo path until then.

What’s left in Phase 4

That’s the originally-decomposed Phase 4 done — marketing system (4a planning forward), trust + developer hub, dashboard restructure, status + transactions + mobile nav, team workspaces, and now webhooks + SDKs.

The remaining open items are:

  • Restoring Paystack live keys after the test-card walkthrough lands — gated on the maintainer’s confirmation.
  • npm and PyPI publish for the two SDKs — same shape: gated on maintainer credentials.
  • Workspace-scoped resources + per-seat billing (a follow-up to 4c, dependent on Paystack changes).

May 16, 2026

Team workspaces (structure-only release)

feature

title: "Team workspaces (structure-only release)" date: "2026-05-16" tag: "feature"

Inksong now has the concept of a workspace — a named team that owners can invite members to, with three roles: owner, admin, member.

This is a structure-only release. We’re shipping the team graph before we ship anything that depends on it, so we can validate the shape with real teams before we wire it into resources and billing.

What works today

  • Create a workspace from /dashboard/workspaces. You’re the owner.
  • Invite teammates by email. They receive a plain-text email with an accept link that expires in seven days.
  • Three roles: owner (full control), admin (manage members + invites, rename), member (read-only view of the workspace).
  • Revoke pending invites, remove members, rename the workspace, leave (members + admins), or delete (owner).

What does NOT work today (and we’re telling you up front)

  • Shared documents. Documents are still owned by the user who created them. Adding a teammate to your workspace does not let them see your documents.
  • Shared voice profiles. Same story.
  • Shared subscription / per-seat billing. Every member still has their own free or pro plan. We have not yet figured out the right billing shape for teams, and we’d rather get it right than ship something we’ll have to migrate off.
  • Ownership transfer. If you’re the owner and want to leave, you have to delete the workspace and have someone else recreate it. We’ll add proper transfer in a follow-up.

If any of those missing pieces are blocking for you, email hello@inksong.app and tell us — that’s the fastest way to influence the priority order on the follow-up phase.

What’s next

Workspace-scoped documents and voice profiles, followed by workspace-level subscriptions. Ownership transfer alongside that. The order depends on what teams tell us they need.

May 15, 2026

Status history, transaction history, mobile dashboard nav

improvement

title: "Status history, transaction history, mobile dashboard nav" date: "2026-05-15" tag: "improvement"

Three follow-ups to yesterday’s dashboard restructure, each closing a small but obvious gap.

Status history

/status now does more than tell you whether the API is up right this second. It also shows the last 90 days of incidents and scheduled maintenance windows. The history starts today — we’re not backfilling prior outages. Each entry includes what happened, what we did, and what we changed so it doesn’t happen again.

Incidents are MDX files in the repo. The editorial workflow is git commit. No admin panel, no third-party hosting bill. Same pattern as the blog, guides, and changelog.

Transaction history

/dashboard/billing now shows your past Paystack transactions — subscription renewals, initial payments, top-ups, plus any failed or abandoned attempts. Date, description, amount, status. Paginated.

We don’t store invoices locally; Paystack is the source of truth. The new endpoint is GET /api/v1/billing/transactions. Free-tier users without a Paystack customer code get an empty list immediately (no upstream call).

Mobile dashboard nav

On phones and tablets, the dashboard rail used to be invisible — you had to know the URLs to switch between pages. Now there’s a hamburger at the top of the dashboard column that opens a left-slide drawer with the same nav. Desktop is unchanged.

What’s next: team workspaces with multi-seat accounts.

May 14, 2026

Dashboard restructure + API key rotation

improvement

title: "Dashboard restructure + API key rotation" date: "2026-05-14" tag: "improvement"

The dashboard you signed into yesterday tried to do everything on a single scroll. It worked, but it was a lot. We’ve split it apart.

A new shape

/dashboard is now a hub: a greeting, the quick-paste humanizer, your quota at a glance, your last five documents, and links to the rest. Six new pages take the rest of the surface — each one does one thing.

  • /dashboard/documents — every document you’ve humanized, paginated.
  • /dashboard/voice-profiles — train Inksong on your existing prose so humanizations come back sounding like you.
  • /dashboard/api-keys — view your key, regenerate it, see the one-line curl example.
  • /dashboard/billing — plan, currency, top-up packs (moved out of settings).
  • /dashboard/usage — this-month volume and an AI-likelihood score distribution histogram so you can see what we’re actually shifting.
  • /dashboard/settings — now account-only: name, password, danger zone.

A sticky left rail on wide screens makes it easy to flip between them. On phones and tablets the rail collapses; we’ll ship a drawer for that in a follow-up.

Rotate your API key yourself

You can now rotate your API key from the dashboard. Hit Regenerate, confirm, and the old key stops working immediately. The new key is shown once for you to copy — we don’t email it, and there’s no recovery if you close the tab without saving it. Useful if you ever suspect a leak, or as a periodic hygiene thing.

If you’d rather script it, the endpoint is POST /api/v1/auth/rotate-api-key. Bearer token only — API-key-authenticated clients can’t rotate themselves (that would lock them out). Rate-limited to 5 rotations per hour per account.

A small honesty fix

Our docs at /docs/authentication said API keys are prefixed ink_live_… and that we store a hash you can’t recover. Neither was true. The real format is ink_ followed by 48 hex characters, and we store the key itself so you can copy it again from the dashboard. The docs now match reality.

What’s next: status history with incident detail, invoice and receipt history, and team workspaces.

May 13, 2026

Multi-page marketing system

design

title: "Multi-page marketing system" date: "2026-05-13" tag: "design"

The site has grown from a single-page prototype into a proper marketing system. 35+ routes — solutions and feature deep-dive pages, honest competitor comparisons, a blog with engineering essays, walkthrough guides, this changelog, an about page, a manifesto, and a security page that actually documents the architecture.

The bones are MDX content in the repo (no CMS, no editorial pipeline), route groups for marketing vs app chrome, and a mega-menu that fits the new surface area without becoming unwieldy. Privacy-friendly analytics (Plausible) load on the marketing side only; the app remains tracker-free.

If you've been waiting for the site to look like a product rather than a prototype, that work shipped today.

May 13, 2026

Developer hub + public roadmap + newsletter

design

title: "Developer hub + public roadmap + newsletter" date: "2026-05-13" tag: "design"

A coordinated set of additions for technical evaluators and people who want to follow the work.

Developer hub. What was a single /docs page is now nine — authentication, documents, voice profiles, webhooks (design documented, delivery in 2026-Q3), errors, rate limits, SDKs (Python and Node planned for 2026-Q3), API changelog, and a quickstart hub. Each page has curl, Python, and JavaScript examples.

Public roadmap. /roadmap — shipped, in flight, and considered. No fake dates. The considered section is where we admit uncertainty rather than dress it as a commitment.

Compliance trajectory on /security. Honest framing on SOC 2, pentests, GDPR DPA, ISO 27001, HIPAA. We don't hold these certifications today; the section says when we'd start each one and what triggers it.

Newsletter. /newsletter — twice a month, engineering posts and release notes, no spam. Signup in the footer and on a dedicated page. Powered by Buttondown.

Syntax highlighting. Code blocks across blog posts, guides, and the new developer hub now render with build-time syntax highlighting via Shiki. Zero client JavaScript for highlighting; the colored markup ships in the static HTML.

RSS feed. /rss.xml. Autodiscovery link in the HTML head.

If you're new here, start with the manifesto or subscribe to the newsletter.

May 13, 2026

Substantial content drop — 14 new pieces

design

title: "Substantial content drop — 14 new pieces" date: "2026-05-13" tag: "design"

The site now reads like a product that has been operating for a while. Eight new blog posts, four new guides, two new comparison pages — pulled from the engineering work we have actually done.

The blog leans into engineering depth: the prompt strategy for document-level humanization, why we use Claude over the alternatives, how the DOCX format pipeline works, and the design of the content-aware diff. Two product posts — an iteration story on AI detection scoring, and the math behind NGN-first pricing. Two use-case essays — researchers handling literature reviews, and marketing teams holding brand voice across writers.

The new guides cover the marketing-blog workflow end-to-end, a tone-and-humanness decision reference, API integration into CMS pipelines (WordPress, Sanity, Strapi), and the batch processing walkthrough.

Two new comparisons: vs Originality.ai (which is a detector, not a humanizer — they are complementary tools) and vs Phrasly (a budget humanizer, honest head-to-head).

If you are new here, start with the manifesto or jump straight into the blog.

May 12, 2026

Annual plans and webhook-free verification

feature

title: "Annual plans and webhook-free verification" date: "2026-05-12" tag: "feature"

Annual billing is now live for both Pro and Enterprise. The annual cadence is priced at roughly a 22% discount over monthly — ₦168,000 / year for Pro (effective ₦14,000/mo) and ₦528,000 / year for Enterprise (effective ₦44,000/mo). The currency toggle on the pricing page surfaces equivalent USD pricing where the merchant account has USD enabled.

Subscription state now syncs directly when the Paystack inline-checkout closes — the front end calls a /billing/verify endpoint that pulls the latest from Paystack. No more waiting on a webhook to know whether a customer's plan upgraded. The webhook handler still exists as a safety net and remains idempotent.

May 10, 2026

Overage top-up packs and cleaner currency UI

feature

title: "Overage top-up packs and cleaner currency UI" date: "2026-05-10" tag: "feature"

When you hit your monthly document quota, you can now buy a 25-document overage pack for ₦7,500 ($5). Overage credits live in a separate bucket from your monthly allowance and don't reset on the billing cycle — buy them when you need them, use them whenever.

We also fixed a small but annoying UX edge: the pricing page used to show a USD/NGN currency toggle even on merchant accounts where USD wasn't enabled, leading to a dead control and confusing pricing. The toggle now only appears when USD is actually available.

May 9, 2026

Paystack billing live in production

feature

title: "Paystack billing live in production" date: "2026-05-09" tag: "feature"

Billing is now live. Pro and Enterprise plans are available in monthly cadence, paid in NGN (and USD where the merchant account supports it). The pricing page handles the currency switch with a cookie-persisted preference.

Free tier remains 5 documents per month. Quota enforcement, overage gating, and dashboard subscription management all ship together. Cards processed through the Paystack inline checkout; we hold no card data ourselves.

May 8, 2026

Production deployment

ops

title: "Production deployment" date: "2026-05-08" tag: "ops"

Inksong is live at inksong.app. The production stack is a single-host VPS fronted by Caddy auto-TLS — Postgres for state, MinIO for document storage, Redis-backed ARQ for the humanization worker, Sentry for error tracking. Daily Postgres backups with retention are scheduled via cron.

The site is in Frankfurt — EU jurisdiction. We chose this region to keep European customer data on EU servers; the only out-of-region call is the Anthropic API for the actual humanization.

May 6, 2026

SEO foundations and missing MVP pages

design

title: "SEO foundations and missing MVP pages" date: "2026-05-06" tag: "design"

The site now has the operational basics that a real product is expected to have: Open Graph and Twitter Card metadata on every page, canonical URLs, JSON-LD structured data for the homepage FAQ, robots and sitemap files, and the missing pages every visitor reaches for — /docs (API reference), /status, /privacy, /terms.

This was overdue. None of it is marketing flash; it's the stuff that says "this is a real product, not a weekend project."

May 4, 2026

Per-document detail view

design

title: "Per-document detail view" date: "2026-05-04" tag: "design"

The dashboard now has a per-document detail view at /dashboard/documents/[jobId]. From a row in your documents list, you can open a full view showing the original alongside the humanized output, AI score gauges (before/after), the word-level diff, and a download button.

The single-page list still works for quick scanning; the detail view is where you actually review and download.

May 3, 2026

Dashboard and onboarding redesign

design

title: "Dashboard and onboarding redesign" date: "2026-05-03" tag: "design"

A 20-fix sweep across the dashboard. New users now get a guided first humanization — a short onboarding path that walks them from sign-in to their first downloaded document. Documents, voice profiles, and settings each have proper landing surfaces now instead of being smashed into one screen.

The empty states got attention too: instead of blank panels, every section explains what it'll show once you've used the feature.

May 2, 2026

Sixteen UI fixes across auth, landing, and brand

fix

title: "Sixteen UI fixes across auth, landing, and brand" date: "2026-05-02" tag: "fix"

A focused pass on the surfaces visitors hit first: login and registration polish, the landing page hero animation timing, the brand mark on small screens, dark-mode regressions in the dashboard, and a full mobile-responsive audit across the marketing pages.

The fixes are individually small. Together they're the difference between a product that feels handmade and one that feels half-finished.

May 1, 2026

Calamus becomes Inksong

design

title: "Calamus becomes Inksong" date: "2026-05-01" tag: "design"

We renamed.

Calamus was the working title — a Latin reed pen, fine, but mostly a name nobody could pronounce or spell. Inksong is what the product is now: ink (writing, craft) plus song (voice, but as an authorial style, not audio). The tagline that does the disambiguation work on first read: AI text. Your voice.

The rebrand is more than a name swap. We picked up a new palette (Ink + Vellum — deep ink on warm cream, terracotta as the single accent), a literary typography pair (Cormorant Garamond for display, Inter for UI), a new wordmark (Cormorant italic 600, set as a static SVG so it renders identically everywhere), and a new mark (an ink-trail "S" curve). The domain moved to inksong.app.

For the design rationale in full, the brand spec is in the repo.