Skip to content

Commit c2b7648

Browse files
dani-polaniclaude
andcommitted
feat: extend API with per-line options, visual settings, pair controls; add agent skill
API now accepts: - lines as string or LineInput {text, font, sizePx, gapPx, rtl} for per-line typography and RTL support - settings object for global visual overrides: palette, lineStyle, lineThickness, lineOpacity, background, theme, showNumbers, colorTokensByLink - pairs array for per-adjacent-pair vertical gap and showConnectors control Also adds: - .agents/tools/word-aligner-api.md — skill prompt for AI agents (Claude, ChatGPT) - README API section with usage example and skill description - Updated /api docs page with full parameter tables and examples - Updated OpenAPI schema with LineInput, SettingsInput, PairInput components Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 3ad9520 commit c2b7648

6 files changed

Lines changed: 1067 additions & 157 deletions

File tree

.agents/tools/word-aligner-api.md

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,189 @@
1+
# Word Aligner — AI Agent Skill
2+
3+
You have access to the **Word Aligner** tool. Use it whenever the user asks to visualize word-by-word alignment between two or more texts (translations, glosses, morpheme breakdowns, parallel corpora, etc.).
4+
5+
## What it does
6+
7+
Word Aligner generates a shareable interactive diagram that shows which words in one text correspond to which words in another text. Words are connected by colored arcs; multiple words that form a group share the same color.
8+
9+
## When to use it
10+
11+
- User asks to translate a phrase and show which words correspond to which
12+
- User wants to align a translation with its source (any languages, including RTL)
13+
- User wants to show a linguistic gloss (morpheme-by-morpheme breakdown)
14+
- User asks to visualize parallel text or bitext alignment
15+
16+
## API
17+
18+
**Endpoint:** `POST https://aligner.tinygods.dev/api/align`
19+
**Content-Type:** `application/json`
20+
**Returns:** `{ "url": "https://aligner.tinygods.dev/?data=..." }`
21+
22+
Show the returned `url` to the user — it opens an interactive, shareable alignment diagram.
23+
24+
## Request format
25+
26+
```json
27+
{
28+
"lines": ["line 0 text", "line 1 text"],
29+
"alignments": [[lineA, wordA, lineB, wordB], ...],
30+
"settings": { ... },
31+
"pairs": [{ "upper": 0, "lower": 1, "gapPx": 120, "showConnectors": true }, ...]
32+
}
33+
```
34+
35+
### `lines` (required)
36+
37+
Array of 1–8 lines, top to bottom. Each entry is either:
38+
- A **plain string**: `"Hello world"`
39+
- A **LineInput object** with per-line options:
40+
41+
| Field | Type | Default | Description |
42+
|----------|---------------|---------|--------------------------------------------------------------|
43+
| `text` | string || Line text (required) |
44+
| `font` | string | Inter | Google Fonts family, e.g. `"Noto Serif"`, `"Noto Sans Arabic"` |
45+
| `sizePx` | integer 12–64 | 36 | Text size in px |
46+
| `gapPx` | integer 0–56 | 14 | Horizontal gap between word tokens in px |
47+
| `rtl` | boolean | false | Right-to-left layout (Hebrew, Arabic, Farsi, Urdu, etc.) |
48+
49+
### `alignments` (optional)
50+
51+
Array of `[lineA, wordA, lineB, wordB]` tuples:
52+
- Lines A and B must be **adjacent** (differ by exactly 1)
53+
- Indices are **0-based**
54+
- Multiple tuples sharing the same word get the **same color automatically**
55+
56+
### `settings` (optional)
57+
58+
| Field | Values | Default | Description |
59+
|-------------------|-------------------------------|----------|-----------------------------------------|
60+
| `palette` | `pastel` `vivid` `academic` | pastel | Color palette for connection lines |
61+
| `lineStyle` | `curved` `straight` | curved | Shape of connection lines |
62+
| `lineThickness` | number 1–8 | 3 | Stroke width |
63+
| `lineOpacity` | number 0.2–1 | 1 | Opacity of lines |
64+
| `background` | `light` `dark` | light | Preview background |
65+
| `theme` | `light` `dark` | light | UI theme (token chip color) |
66+
| `showNumbers` | boolean | false | Show line numbers |
67+
| `colorTokensByLink` | boolean | true | Tint word tokens in their connection color |
68+
69+
### `pairs` (optional)
70+
71+
Array of `{ upper, lower, gapPx?, showConnectors? }` — controls for specific adjacent line pairs:
72+
- `upper` / `lower`: 0-based line indices; `lower` must equal `upper + 1`
73+
- `gapPx` (12–156, default 120): vertical gap between the two lines
74+
- `showConnectors` (default true): set to `false` to hide connector lines for a pair (useful for gloss rows)
75+
76+
## Word index counting
77+
78+
Count words left to right starting from 0, splitting on whitespace. Characters `.`, `-`, `|` also split words.
79+
80+
For RTL lines, word 0 is the **logically first** word (rightmost on screen for Arabic/Hebrew).
81+
82+
**Example — "I have been going":**
83+
| Index | Word |
84+
|-------|------|
85+
| 0 | I |
86+
| 1 | have |
87+
| 2 | been |
88+
| 3 | going |
89+
90+
## Examples
91+
92+
### Simple two-language alignment
93+
94+
```json
95+
{
96+
"lines": ["Hello world", "Bonjour le monde"],
97+
"alignments": [
98+
[0, 0, 1, 0],
99+
[0, 1, 1, 2]
100+
]
101+
}
102+
```
103+
104+
"Hello" → "Bonjour", "world" → "monde" ("le" is word 1, "monde" is word 2).
105+
106+
### One-to-many (one source word maps to several target words)
107+
108+
```json
109+
{
110+
"lines": ["Я ходил", "I have been going"],
111+
"alignments": [
112+
[0, 0, 1, 0],
113+
[0, 1, 1, 1],
114+
[0, 1, 1, 2],
115+
[0, 1, 1, 3]
116+
]
117+
}
118+
```
119+
120+
"ходил" (Russian past imperfective) maps to three English words: "have been going". All three connections are the same color.
121+
122+
### RTL language (Hebrew)
123+
124+
```json
125+
{
126+
"lines": [
127+
{ "text": "שלום עולם", "rtl": true, "sizePx": 48, "font": "Noto Sans Hebrew" },
128+
{ "text": "Hello world", "sizePx": 40 }
129+
],
130+
"alignments": [
131+
[0, 0, 1, 0],
132+
[0, 1, 1, 1]
133+
]
134+
}
135+
```
136+
137+
Word 0 of the Hebrew line is "שלום" (logically first), word 1 is "עולם".
138+
139+
### Three lines with a gloss row
140+
141+
```json
142+
{
143+
"lines": [
144+
"Я ходил",
145+
"I have been going",
146+
"1SG.NOM PST.IPFV"
147+
],
148+
"alignments": [
149+
[0, 0, 1, 0],
150+
[0, 1, 1, 1],
151+
[0, 1, 1, 2],
152+
[0, 1, 1, 3]
153+
],
154+
"pairs": [
155+
{ "upper": 1, "lower": 2, "gapPx": 60, "showConnectors": false }
156+
]
157+
}
158+
```
159+
160+
Lines 0–1 are connected. Line 2 is a gloss with smaller vertical gap and no connector arcs.
161+
162+
### Custom visual style
163+
164+
```json
165+
{
166+
"lines": ["Hello world", "Bonjour le monde"],
167+
"alignments": [[0, 0, 1, 0], [0, 1, 1, 2]],
168+
"settings": {
169+
"palette": "vivid",
170+
"lineStyle": "straight",
171+
"background": "dark",
172+
"theme": "dark"
173+
}
174+
}
175+
```
176+
177+
## Workflow tip
178+
179+
When asked to "translate and align":
180+
1. Translate the phrase into the target language yourself.
181+
2. Determine which source words correspond to which target words.
182+
3. Call the API with the source + translation as `lines` and the correspondences as `alignments`.
183+
4. Return the `url` to the user with a brief explanation of the alignment.
184+
185+
If you are uncertain about word boundaries in a language, call the GET endpoint first to preview the tokenization:
186+
```
187+
GET https://aligner.tinygods.dev/api/align?lines=your+text+here
188+
```
189+
Open the URL and count the word boxes.

README.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,35 @@ Tune colors, tokenization, and fonts in settings, then export or share.
4949
- **Interlinear translation** places a gloss directly under each source word — compact, but it hides reordering. Aligner keeps both sentences on their own line and draws connectors, so reorderings, splits, and merges stay obvious.
5050
- **Parallel text** is side-by-side bilingual reading for long-form study. Aligner focuses on one sentence pair at a time with explicit connectors showing which tokens correspond.
5151

52+
## API
53+
54+
Word Aligner has a free HTTP API for generating alignment links programmatically.
55+
56+
```
57+
POST https://aligner.tinygods.dev/api/align
58+
Content-Type: application/json
59+
60+
{
61+
"lines": ["Hello world", "Bonjour le monde"],
62+
"alignments": [[0, 0, 1, 0], [0, 1, 1, 2]]
63+
}
64+
```
65+
66+
Returns `{ "url": "https://aligner.tinygods.dev/?data=..." }`.
67+
68+
Supports per-line options (font, size, RTL), global visual settings (palette, line style, background), pair-level gap control, and multi-line stacks with selective connectors.
69+
70+
- **API docs:** [aligner.tinygods.dev/api](https://aligner.tinygods.dev/api)
71+
- **OpenAPI schema:** [aligner.tinygods.dev/api/align/openapi.json](https://aligner.tinygods.dev/api/align/openapi.json)
72+
73+
### Using Word Aligner as an AI agent tool
74+
75+
The file [`.agents/tools/word-aligner-api.md`](.agents/tools/word-aligner-api.md) is a skill prompt that teaches AI assistants (Claude, ChatGPT, etc.) how to use the API. Add it as a custom instruction or system prompt to enable a flow like:
76+
77+
> "Translate 'я хочу спать' into English and show me the word alignment."
78+
79+
The agent translates, calls the API, and returns a shareable link.
80+
5281
## Learn more
5382

5483
- **App:** [aligner.tinygods.dev](https://aligner.tinygods.dev)

0 commit comments

Comments
 (0)