# dsh-typography **Typography plugin for DeepSeek Harness** — independent interface & code fonts · online presets · zero-conversion local font library [![GitHub stars](https://img.shields.io/github/stars/Gan332/dsh-typography)](https://github.com/Gan332/dsh-typography/stargazers) [![GitHub issues](https://img.shields.io/github/issues/Gan332/dsh-typography)](https://github.com/Gan332/dsh-typography/issues) [![License](https://img.shields.io/github/license/Gan332/dsh-typography)](./LICENSE) 中文 | [English](./README.md)
## Introduction The DeepSeek Harness Web UI exposes two font entry points as CSS variables: `--dsw-font-family` (interface) and `--ds-font-family-code` (code), consumed by every component through `var()`. dsh-typography turns them into two **fully independent** selections: - **Separate interface / code fonts**: each group has its own preset cards, import editor, and persisted state - **Online presets**: Inter + JetBrains Mono, IBM Plex Sans + Fira Code, Noto Sans SC (full Simplified Chinese coverage); font files ship via the jsDelivr CDN and fall back to system stacks offline - **Local font library**: drop any `woff2/ttf/otf` into `%DSH_HOME%\typography\`, refresh, apply with one click — **TTF works directly, no woff2 conversion needed** - **Variable-font friendly**: pick "variable · all weights" to emit a `font-weight: 100 900` descriptor with real weight rendering - **Hands-off defaults**: a group set to "Default" writes no styles at all, coexisting with other font plugins - **Cross-DSH-version compatibility**: `defineStore` moved between 0.1.1-rc.x (`dsh-client-runtime/client`) and 0.1.2-alpha.1+ (`dsh-client-store`); the plugin ships a `try/catch` shim that picks whichever the host provides, and the `dsh.client.inject` list only names the core services present in every supported DSH version ## Usage This is a dual-face plugin: the host half serves local font files while the browser half provides the registry and settings row. After install it appears under **Settings → General → Fonts (interface / code)**. **Install:** DeepSeek Harness has two entry points with independent profiles — install into whichever you use: ```sh # DSH Desktop app (default port 43120) dsh plugin --profile desktop add github:Gan332/dsh-typography # CLI `dsh web` (default port 3080) dsh plugin --profile web add -w /path/to/dsh-typography # local directory (the profile dir is a pnpm workspace root; -w is required) ``` Then restart the matching entry. Desktop note: a terminal install records a recovery transaction that the app **verifies and clears on its next start**; when installing several plugins in a row, restart between installs. **Switching fonts:** click a card in either group to apply live; "Default" restores the system stack. **Importing custom fonts:** fill three fields in the group's editor and press "Add": | Field | Description | | --- | --- | | Family | any name used in the font stack (e.g. `MiSans`) | | Font URL | see "Font URL formats" below; woff2 / ttf / otf supported | | Weight | 400 Regular · 500 Medium · 600 Semibold · 700 Bold · **Variable · all weights**. For static fonts choose the weight matching the file; for variable fonts (e.g. MiSans VF) choose "Variable · all weights" to get every real weight | Entries apply immediately, survive refreshes; re-adding the same family + weight replaces the old one, "Remove" deletes. **Local font library:** ```powershell copy C:\Users\fish\Downloads\MiSansVF.ttf $env:USERPROFILE\.dsh\typography\ ``` Refresh → your group → Local font library → click `MiSansVF`. Zero conversion, all variable weights. **Font URL formats** — same-origin relative paths are recommended (port-independent): ``` /plugins/dsh-typography/files/MiSansVF.ttf ✅ recommended (same-origin) http://127.0.0.1:43120/plugins/dsh-typography/... ⚠️ works, but breaks if the port shifts https://cdn.example.com/some-font.woff2 ✅ external CDN direct link ``` ## Plugin API The browser half provides the registry on the root context; other plugins can consume it via `ctx.get("typography")`: ```ts const typography = ctx.get("typography") // two independent groups: "ui" | "code" typography?.select("code", "inter-jetbrains") typography?.setCustom("ui", [ { family: "MiSans", weight: "100 900", src: ["/plugins/dsh-typography/files/MiSansVF.ttf"] }, ]) const off = typography?.subscribe((snapshot) => { console.log(snapshot.ui.selected, snapshot.revision) }) ``` Full types live in `lib/types/client/index.d.ts`. ## How it works - On `apply` the browser half publishes the registry via `ctx.provide("typography", registry)`; selection changes rewrite the injected `