Translation BYOK: assisted setup flow for self-hosters using their own DeepL account #1

Open
opened 2026-04-06 11:31:29 -07:00 by pyr0ball · 0 comments
Owner

Problem

Translation (DeepL) cannot be Free-tier without either CF absorbing per-character costs or the user providing their own DeepL key. The tension:

  • CF can't sustainably absorb DeepL costs at Free tier at any meaningful volume
  • Gating translation entirely at Paid fails the accessibility mission — the users most likely to need translation (immigrants, elderly, limited English, low technical literacy) are exactly the users least able to afford Paid or navigate a technical BYOK setup
  • DeepL requires account signup; unlike Ollama (a technical choice), this is a bureaucratic step with real friction

The BYOK gap

Standard BYOK assumes a technically capable user who knows what an API key is. That's not the primary linnet translation audience. Asking a non-technical user to "enter your DeepL API key" without guidance is a soft failure — the feature exists but is inaccessible in practice.

Two onboarding paths

The setup flow should detect which path the user wants and offer both at the entry point.


Path A: Guided (non-technical users)

When the user first enables translation on a Free account:

  1. Explain the situation plainly: "Translation uses DeepL. To use it for free, you'll need a free DeepL account (500,000 characters/month — enough for regular use)."
  2. Walk them through account creation: link to DeepL free tier, brief step-by-step (~2 minutes)
  3. Paste your key: simple field with validation, masked display
  4. Confirm it works: test translation on the spot before saving

The flow should feel like onboarding, not configuration. No jargon. No assumed knowledge. Completable on a phone screen without leaving the app.


Path B: Developer / self-hoster

For users who already have a key or are deploying linnet programmatically:

  • DEEPL_API_KEY environment variable — picked up automatically, no UI required
  • ~/.config/circuitforge/linnet.yaml key (translation.deepl_api_key) — persistent, survives restarts
  • CLI flag at startup: --deepl-key <key> — for scripted/automated use
  • Skip the wizard entirely if any of the above are present at launch

The developer path should be documented in the README and the self-hosting guide. No wizard friction for users who know what they're doing.


Path detection

At first translation use, linnet checks in order:

  1. Env var present → use silently, skip wizard entirely
  2. Config file key present → use silently, skip wizard
  3. Paid tier → use CF-managed DeepL, skip wizard
  4. Neither → show wizard entry point with "I already have a key" (skip to paste step) and "Help me get one" (full guided flow) options

Tier paths

Path Who it's for How it works
Developer BYOK Self-hosters, technical users Env var / config file / CLI flag — no wizard
Assisted BYOK (Free) Non-technical users Guided wizard → own DeepL free-tier key
Paid Zero-friction users CF manages DeepL, no setup

Design constraints

  • Guided path: completable on mobile without leaving the app
  • Developer path: zero UI friction if env var or config is set
  • If wizard is abandoned mid-flow: save progress
  • Key storage: encrypted at rest, never transmitted to CF servers
  • On key failure: clear, calm error with specific guidance (expired key, quota exceeded, wrong key type)

What NOT to do

  • Don't show only the guided wizard to developers — they'll resent the hand-holding
  • Don't show only a bare key field to non-technical users — it's inaccessible
  • Don't silently degrade translation without a clear explanation
  • Don't gate the translation UI entirely with no Free path shown
  • Translation milestone: Translation — v1.1
  • cf-core has_byok abstraction needs per-service variant (has_byok_translation) — file separately on circuitforge-core
## Problem Translation (DeepL) cannot be Free-tier without either CF absorbing per-character costs or the user providing their own DeepL key. The tension: - CF can't sustainably absorb DeepL costs at Free tier at any meaningful volume - Gating translation entirely at Paid fails the accessibility mission — the users most likely to need translation (immigrants, elderly, limited English, low technical literacy) are exactly the users least able to afford Paid or navigate a technical BYOK setup - DeepL requires account signup; unlike Ollama (a technical choice), this is a bureaucratic step with real friction ## The BYOK gap Standard BYOK assumes a technically capable user who knows what an API key is. That's not the primary linnet translation audience. Asking a non-technical user to "enter your DeepL API key" without guidance is a soft failure — the feature exists but is inaccessible in practice. ## Two onboarding paths The setup flow should detect which path the user wants and offer both at the entry point. --- ### Path A: Guided (non-technical users) When the user first enables translation on a Free account: 1. **Explain the situation plainly**: "Translation uses DeepL. To use it for free, you'll need a free DeepL account (500,000 characters/month — enough for regular use)." 2. **Walk them through account creation**: link to DeepL free tier, brief step-by-step (~2 minutes) 3. **Paste your key**: simple field with validation, masked display 4. **Confirm it works**: test translation on the spot before saving The flow should feel like onboarding, not configuration. No jargon. No assumed knowledge. Completable on a phone screen without leaving the app. --- ### Path B: Developer / self-hoster For users who already have a key or are deploying linnet programmatically: - `DEEPL_API_KEY` environment variable — picked up automatically, no UI required - `~/.config/circuitforge/linnet.yaml` key (`translation.deepl_api_key`) — persistent, survives restarts - CLI flag at startup: `--deepl-key <key>` — for scripted/automated use - Skip the wizard entirely if any of the above are present at launch The developer path should be documented in the README and the self-hosting guide. No wizard friction for users who know what they're doing. --- ### Path detection At first translation use, linnet checks in order: 1. Env var present → use silently, skip wizard entirely 2. Config file key present → use silently, skip wizard 3. Paid tier → use CF-managed DeepL, skip wizard 4. Neither → show wizard entry point with "I already have a key" (skip to paste step) and "Help me get one" (full guided flow) options --- ## Tier paths | Path | Who it's for | How it works | |---|---|---| | Developer BYOK | Self-hosters, technical users | Env var / config file / CLI flag — no wizard | | Assisted BYOK (Free) | Non-technical users | Guided wizard → own DeepL free-tier key | | Paid | Zero-friction users | CF manages DeepL, no setup | ## Design constraints - Guided path: completable on mobile without leaving the app - Developer path: zero UI friction if env var or config is set - If wizard is abandoned mid-flow: save progress - Key storage: encrypted at rest, never transmitted to CF servers - On key failure: clear, calm error with specific guidance (expired key, quota exceeded, wrong key type) ## What NOT to do - Don't show only the guided wizard to developers — they'll resent the hand-holding - Don't show only a bare key field to non-technical users — it's inaccessible - Don't silently degrade translation without a clear explanation - Don't gate the translation UI entirely with no Free path shown ## Related - Translation milestone: Translation — v1.1 - cf-core `has_byok` abstraction needs per-service variant (`has_byok_translation`) — file separately on circuitforge-core
pyr0ball added this to the Translation — v1.1 milestone 2026-04-06 11:31:29 -07:00
pyr0ball added the
a11y
ux
design
labels 2026-04-06 11:31:29 -07:00
Sign in to join this conversation.
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference: Circuit-Forge/linnet#1
No description provided.