# dsh-typography
**Typography plugin for DeepSeek Harness** — independent interface & code fonts · online presets · zero-conversion local font library
[](https://github.com/Gan332/dsh-typography/stargazers)
[](https://github.com/Gan332/dsh-typography/issues)
[](./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 `