Skip to content

Commit e767fdb

Browse files
committed
docs(readme): lead with the product, add a live demo link and sample
Rewrite the README around the name and tagline: a prominent live-demo link and license badge up top, a real sample of the exported diff image, benefit-framed features, and an honest note that inline token diffing suits localized edits over full rewrites.
1 parent 0285bbb commit e767fdb

2 files changed

Lines changed: 59 additions & 42 deletions

File tree

README.md

Lines changed: 59 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,60 +1,76 @@
11
# Diff Poster
22

3+
**▶ Live demo — [apps.charliekrug.com/diff-poster](https://apps.charliekrug.com/diff-poster/)**
4+
35
[![CI](https://github.com/ctkrug/diff-poster/actions/workflows/ci.yml/badge.svg)](https://github.com/ctkrug/diff-poster/actions/workflows/ci.yml)
6+
[![License: MIT](https://img.shields.io/badge/license-MIT-8a1c1c.svg)](LICENSE)
7+
8+
Turn a before/after code snippet into a single clean image of just the change.
9+
Paste the old code, paste the new code, get a token-level diff styled like a tidy
10+
editor window and sized for a tweet. No login, no export dialog, nothing uploaded.
411

5-
Paste a before/after code snippet, get back a single crisp image of just the diff —
6-
styled like a nice editor, sized for a tweet, no login, no export dialog.
12+
![A Diff Poster image: an async getUser function where db.find becomes db.findOne and user.name becomes user.fullName, with only the changed tokens highlighted](docs/media/sample-diff.png)
713

8-
## Why
14+
## Who it's for
915

10-
Sharing a code change on Twitter/Slack usually means a screenshot of a diff view that's
11-
either too cluttered (line numbers, gutter, full file chrome) or too crude (solid
12-
red/green line highlighting that hides exactly which tokens changed). Tools like
13-
Snappify solve a bigger problem — window chrome, themes, gradients, carousels — for
14-
people who need a lot of that. Most of the time you just want: paste old code, paste
15-
new code, get one clean image with token-level highlighting, done.
16+
Developers sharing a specific code change: a clever one-liner, a bug fix, a small
17+
refactor, dropped into a tweet, a PR description, or a Slack thread. Not slide decks or
18+
blog carousels; that is a bigger tool's job. This is the "quote-tweet a diff" case:
19+
fast, single-shot, disposable.
1620

17-
Diff Poster does the one thing: paste, render, download/copy. No account, no server
18-
round-trip, no saved projects.
21+
## Why token-level
1922

20-
## The wow moment
23+
Most diff screenshots paint a whole changed line red or green. Rewrite
24+
`return 'hi ' + name;` as ``return `hello, ${name}!`;`` and a line diff just says
25+
"this line changed" while hiding what actually changed. Diff Poster diffs at the token
26+
level (identifiers, operators, literals, strings), so only the swapped tokens are
27+
marked. The reader sees the exact substitution, which is the whole reason to share it.
2128

22-
Paste two versions of a function into the two panes and instantly get a properly
23-
highlighted diff image — token-level, not line-level — cropped and sized exactly for
24-
pasting into a tweet or a Slack message.
29+
Inline token diffing is at its best on localized edits. A wholesale rewrite (a
30+
for-loop turned into a `reduce`) interleaves a lot of removed and added tokens, the
31+
same way GitHub's word-diff does; the tool is tuned for the function-sized change, not
32+
the full-file rewrite.
2533

2634
## Features
2735

28-
- Token-level diff highlighting (not whole-line red/green blocks) via a real diffing
29-
algorithm over lexical tokens, so a renamed variable or a tweaked argument list reads
30-
clearly instead of the whole line going red.
31-
- Editor-style rendering: syntax highlighting, a monospace type stack, subtle line
32-
numbers, rounded window chrome — looks like a screenshot from a nice editor, not a
33-
raw `<pre>` block.
34-
- Output sized for social sharing (1200×675, tweet/Slack-friendly) by default, with
35-
the image rendered client-side onto a `<canvas>` and exported as PNG.
36-
- One-click "Copy image" (Clipboard API, with a clearly-disabled fallback where it's
37-
unsupported) and "Download PNG" — no export dialog, no intermediate screen.
38-
- No login, no backend, no stored data: everything happens in the browser.
36+
- **Token-level highlighting**, via a longest-common-subsequence diff over lexical
37+
tokens, so a renamed variable or a tweaked argument reads clearly instead of the
38+
whole line going red.
39+
- **Editor-style output**: syntax coloring for JavaScript and Python, a plain-text
40+
fallback, subtle line numbers, and rounded window chrome, so it reads as a
41+
screenshot from a nice editor, not a raw `<pre>` block.
42+
- **Sized for sharing** at 1200×675 (the 16:9 frame Twitter, Bluesky, and Slack use
43+
for previews), rendered onto a `<canvas>` at your screen's pixel density so the PNG
44+
stays crisp on retina displays.
45+
- **One-click copy or download**: copy the PNG straight to your clipboard, or save it,
46+
with no export dialog. Where the browser can't write images to the clipboard, Copy
47+
is clearly disabled and Download always works.
48+
- **Nothing leaves your browser**: tokenizing, diffing, and rendering all run
49+
client-side. No account, no backend, no stored snippets.
3950

4051
## Usage
4152

4253
1. Paste the original code into the **Before** pane, the changed code into **After**.
43-
2. Click **Generate image**.
44-
3. **Copy image** or **Download PNG** — both one click, no dialog.
54+
2. Pick the language (JavaScript, Python, or plain text) for syntax coloring.
55+
3. Click **Generate image**.
56+
4. **Copy image** or **Download PNG**, both one click, no dialog.
57+
58+
The download is named `diff-poster-YYYYMMDD-HHMMSS.png` so a folder of them sorts by
59+
time.
4560

46-
## Stack
61+
## How it works
4762

48-
Static, client-side JavaScript (no build-time server, no user accounts):
63+
A static, client-only Vite app with no framework, plain DOM APIs over a handful of
64+
pure modules:
4965

50-
- Vanilla JS + a small, focused diff library for token-level diffing.
51-
- `<canvas>` for rendering the final shareable image.
52-
- Vitest for unit tests (diff logic, tokenizer, layout math).
53-
- Ships as a static site — no server required at runtime.
66+
`tokenize` (text → tokens, with strings and comments atomic) → `diffTokens` (LCS over
67+
the two token streams) → `segmentsToRows` + `fitRows` (row splitting and sizing math)
68+
`classifyToken` (syntax category per token) → `renderDiffToCanvas` (window chrome,
69+
line numbers, syntax + diff coloring) → `canvasToBlob` (PNG for copy or download).
5470

55-
See [`docs/VISION.md`](docs/VISION.md) for the full design rationale,
71+
See [`docs/VISION.md`](docs/VISION.md) for the rationale,
5672
[`docs/ARCHITECTURE.md`](docs/ARCHITECTURE.md) for the module map, and
57-
[`docs/BACKLOG.md`](docs/BACKLOG.md) for the build plan.
73+
[`docs/DESIGN.md`](docs/DESIGN.md) for the paper-and-ink design direction.
5874

5975
## Development
6076

@@ -67,12 +83,13 @@ npm run lint # eslint
6783
npm run build # static production build (output: site/)
6884
```
6985

70-
## Status
71-
72-
The full v1 scope is built and tested: paste/diff/image, copy/download/share, a
73-
language selector, large-input guardrails, and a full keyboard/accessibility pass.
74-
See [`docs/BACKLOG.md`](docs/BACKLOG.md) for the story-by-story breakdown.
86+
Unit tests (jsdom) cover the diff, tokenizer, layout math, canvas rendering, and
87+
export; the Playwright suite covers the real-browser behavior jsdom can't: computed
88+
focus rings, `prefers-reduced-motion`, layout overflow, and font-blocked degradation.
89+
Both run in CI.
7590

7691
## License
7792

78-
MIT — see [`LICENSE`](LICENSE).
93+
MIT. See [`LICENSE`](LICENSE).
94+
95+
More of Charlie's projects → https://apps.charliekrug.com

docs/media/sample-diff.png

115 KB
Loading

0 commit comments

Comments
 (0)