# enscribe.dev: a personal site built as a typography experiment

> enscribe.dev is the personal blog and portfolio of a single developer, built with Astro and vanilla CSS, with a Knuth-Plass line breaker, baked-in small caps, quantised graphics and a reader mode, all wrapped in a custom proprietary licence. It suits people who want to see what a careful typographic web build looks like, and it is not a template you can copy.

**jktrn/enscribe.dev** — My personal website, built with Astro, CSS, and love.

- Repository: https://github.com/jktrn/enscribe.dev
- Website: https://enscribe.dev
- Stars: 612 · Forks: 55
- Language: TypeScript
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/jktrn-enscribe-dev

## A blog, and a personal site, and a typesetting laboratory

The project description is short: my personal website, built with Astro, CSS, and love. The README expands on it. enscribe.dev is a personal blog and portfolio, built with Astro and vanilla CSS on top of the author's personal blogging template, astro-erudite.

The stated design goal is worth repeating because it explains the feature list. The majority of technology behind the website was designed for the sole purpose of augmenting and enhancing the reader experience without detracting from the content itself.

That framing is unusual for a personal site, and it is the reason the repository is worth an engineer's attention. Most personal sites are a design gallery. This one reads as an engineering log, where the interesting problems are typesetting, glyph rendering and font measurement, and the blog posts are the output rather than the subject.

The site also carries what the author calls automatically collected data about himself. A GitHub calendar, WakaTime hours, Spotify and Discord statuses, and the posts are written in the same voice he speaks in. The repository topics reflect the blend: astro, blog, css, ctf-challenges, ctf-writeups, landing, personal-blog, personal-site, personal-website, portfolio, typescript, website and website-design.

The homepage is enscribe.dev, the default branch is main, the primary language is TypeScript, and the last push was on 2026-10-20, with the tagged releases v4.0.0 from 2026-07-24, v3.1.0 from 2025-06-04 and v3.0.0 from 2024-10-15.

## Knuth-Plass line breaking, shipped as a toggle

The first feature is the most technically interesting one, and the author flags his own doubt about it. The Knuth-Plass line-breaking algorithm is implemented using Pretext, and the algorithm hyphenates and justifies text optimally for beautiful typesetting. The README calls it a rare and experimental feature and says it has been made a toggle due to its fragileness.

The fragility is real and worth understanding rather than dismissing. Knuth-Plass is a global optimisation: it chooses the set of break points across the whole paragraph that minimises total badness, which is what produces even spacing in a way that greedy first-fit breaking cannot. The cost is that the algorithm needs the full paragraph and can fail to find a feasible set of breaks, and the failure modes are paragraph-level, so a single unbreakable long word can blow up the whole paragraph. That is a plausible reason to make it a toggle rather than the default.

The more interesting part is what the algorithm needs in order to work at all. It needs accurate glyph widths. That is the thread running through the next feature.

The typographic system is described as rich, with Utopia type scales, old-style numerals, smart punctuation, muted parentheticals, and automatic small caps for acronyms and abbreviations. The key sentence is the last one: the numerals and small caps are baked into the served font files rather than applied with font-variant, so canvas text measurement sees the same glyph widths the page renders, and the line-breaking algorithm depends on this.

That is a genuinely careful decision. font-variant is a rendering hint, and text measurement libraries generally do not account for small caps substitutions, so a paragraph measured with a normal-width font and rendered with small caps will have widths that do not match, and the line breaker will place breaks against the wrong metrics. Subsetting the font so the substituted glyphs are the real ones removes the discrepancy at the cost of shipping a larger font file.

## Graphics as vectors, rasters quantised to a fixed palette

The image pipeline has a rule, and the rule is stated as a rule. The majority of graphics and images on the site are designed in both light and dark mode. If a graphic can be represented entirely as a vector, it is embedded directly onto the page and uses the same color variables as the site. If a graphic has raster elements, its luminance is quantized onto the author's constrained color scale.

Vector-first is a light and dark mode strategy rather than a performance one. The point is that an inline SVG can reference the same CSS custom properties the rest of the page uses, so a graphic follows the theme automatically. A raster image cannot, so it needs two files or a filter, and the cheaper consistent answer is to reduce the raster to a small set of values that have light and dark equivalents.

Quantising luminance to a constrained scale is a recognisable technique and it explains the design constraint it imposes. Once the number of possible colours is fixed, you can guarantee that each colour in the scale has a counterpart in the other mode that carries the same meaning. The tradeoff is that gradients, soft shadows and photographic detail cannot survive, so a raster element in this system is already a flat graphic by the time it ships.

The repository backs the pipeline up. There is a scripts/ directory with an assets folder, and the package.json carries a media cluster of scripts: media:prepare, media:prepare:graphics, media:manifest, media:upload, media:verify and a media:sync that runs prepare, content render, manifest and upload in sequence. A separate content:render script handles the graphics side. So the images are not committed as finished artefacts; they are generated, verified and uploaded by scripts as part of the content pipeline.

The favicons get the same treatment, with a check script, and the README explains the payoff: external links receive source-specific favicon glyphs so their destinations are recognizable. The system name for this is an icon font, and the check script presumably exists so a link to a domain without a configured glyph is caught before it ships.

## Prose elements, reader mode, and a build that does a lot before Astro runs

The content layer lists the supported prose elements: theme-aware syntax-highlighted code, copyable commands, collapsible callouts, tabs, file trees, footnotes, MathML, and responsive tables. That is a set of components a technical blog needs, and the file tree and tabs in particular are the kind of thing that is painful to retrofit.

There is also a reader mode, described as hiding navigational elements, inline favicons, and underlined links to improve readability and reduce noise. This is a small feature with a large design cost, because it means the page has to be able to render in two configurations without the layout breaking. It is also the clearest instance of the stated principle: the point is to remove everything that is not the text.

The build scripts show how much work happens before the site is built. The dev script runs media preparation, font preparation and the linebreak build before astro dev. The build script is longer still:

```json
    "build": "bun run media:prepare && bun run fonts:prepare && bun run favicons:check && bun run linebreak:build && astro check && astro build --force && pagefind --site dist",
```

The order is the interesting part. Media and fonts are prepared first, then the favicon assets are checked, then the line-breaking package is built, then astro check runs the type check, then the site is built with --force, and finally pagefind indexes the dist output. The pagefind step means the search index is built at deploy time rather than being a third party service, which fits the theme of the site keeping its own data.

The line-breaking code is a workspace package of its own, at packages/linebreak, with separate build and check scripts, and the test script runs bun test against tests/lib and tests/linebreak/unit, with a separate test:site script for the site-level tests.

## Bun, Astro and Cloudflare

The toolchain choices are visible in the manifest. The project is private, is an ES module package, and declares bun@1.3.14 as its packageManager, with Node 22.12.0 or newer as the engine requirement. There is a bun.lock in the repository root and the workspaces are packages/* and tests/*, so the linebreak implementation and the site tests are separate workspaces inside the same repository.

Astro is the framework, and the site is built and previewed with astro dev, astro preview and astro build, with a plain astro script exposed for the rest. The content collections are the Astro convention, and the src/ directory with its components and layouts is where the site itself lives.

Deployment is Cloudflare. The repository root has a wrangler.jsonc, and two scripts cover it: preview:cloudflare runs a build and then wrangler dev, and deploy:cloudflare runs a build and then wrangler deploy. The difference between the two is one word in the wrangler invocation, which is the point of having them separate.

The scripts directory also holds a gallery editor, with gallery:edit running a server script and gallery:cards rendering cards, which suggests the image gallery is authored through a local tool rather than by editing files by hand.

Formatting is handled by Biome, with biome.json at the root and separate format and format:check scripts, and the same tool family is used in the other projects in this ecosystem, so it is a deliberate choice rather than an inherited default.

## The licence is the boundary, and the template is the open path

This is the part that decides who can use what, and the README is unusually direct about it. enscribe.dev is source-available, not open source. Unless stated otherwise, its site-specific code and visual design are proprietary and may not be copied, reused, or redistributed without permission. The README also says plainly that you are not allowed to copy this website's source code as your own.

For an MIT-licensed foundation, the README points to jktrn/astro-erudite. So the split is: the general-purpose template is open, and this particular site, its design and its site-specific code are not. If you want the same starting point, that is the repository to use, and that is a much better outcome than forking a proprietary site and discovering the problem later.

The content is under a separate licence. Original posts, images, and other published material are licensed under CC BY-NC-ND 4.0, which permits unchanged, attributed sharing for noncommercial purposes. ND is the restrictive term here, since it means you cannot adapt the writing, and NC means you cannot use it commercially. Reading a post and quoting it with attribution is fine. Republishing a post on a commercial site, or rewriting one into your own article, is not.

Two files govern this, LICENSE.md for the code and design terms and LICENSE.content.md for the content terms, and permission requests can be sent to the address given in the README. The licence field for the repository is recorded as a custom one that GitHub cannot classify, which is consistent with a proprietary code licence sitting next to a Creative Commons content licence.

This review does not give legal advice. The practical point is that the two licences cover different artefacts, and a reader who only looks at the code licence badge will get the wrong answer about what they may do with the writing.

## What to take from a project you cannot copy

The value of this repository is therefore pedagogical rather than reusable, and it is worth being precise about what that means.

You cannot take the design. The colour scale, the type system, the baked fonts and the layout are the proprietary part, and the visual identity of a personal site is the author's work in the most direct sense. A site that is someone else's personal portfolio, with their writing, their data and their name, is not a starting point for you even if the code were available.

What you can take is the reasoning. That the line breaker needs real glyph widths is a fact about measurement that applies to any justified text. That font-variant does not affect canvas measurement is a trap worth knowing about before you build a similar thing. That a constrained luminance palette is what makes light and dark mode consistent for raster graphics is a technique with a clear cost. That favicon glyphs per domain turn a link list into a scannable one is a design idea with an implementation pattern behind it.

The alternative worth comparing is simply using the open template. astro-erudite is described as the author's personal blogging template, and if you want the Astro plus vanilla CSS foundation with a MIT licence, that is the artifact designed for reuse. The difference in approach is that the template gives you the scaffolding and the features without the specific visual decisions, and you make the ones that are yours to make.

A second alternative is to ignore the typographic ambitions entirely. A personal blog does not need justified text, and a WordPress or Jekyll blog with a decent theme will serve most people. The case for enscribe.dev is that the author wanted the reading experience to be excellent, and then documented every decision that got there. For a reader who is not building a personal site, the posts about the decisions are worth more than the code.

## Conclusion

enscribe.dev is worth reading if you are building a personal or portfolio site and want to see what a typographically deliberate implementation looks like in practice, because the details are documented rather than hidden in a design system. It is the wrong thing to fork, since the site-specific code and visual design are proprietary and the author says explicitly that copying the source as your own is not allowed, and the MIT-licensed path is the author's separate template, astro-erudite. Before drawing any conclusion about your own build, read LICENSE.md and LICENSE.content.md separately, since the code and the writing are under different terms, and treat the published posts under CC BY-NC-ND 4.0 as shareable unchanged with attribution but not for commercial use.

## FAQ

### Can I copy the enscribe.dev source code?

No. The project states that enscribe.dev is source-available, not open source, and that its site-specific code and visual design are proprietary and may not be copied, reused or redistributed without permission. For an MIT-licensed foundation, the author points to jktrn/astro-erudite instead.

### What license applies to the enscribe.dev blog posts?

Original posts, images and other published material are under CC BY-NC-ND 4.0, which permits unchanged, attributed sharing for noncommercial purposes. The code and design terms are separate, in LICENSE.md, with the content terms in LICENSE.content.md.

### What does enscribe.dev use for line breaking and typesetting?

The site implements the Knuth-Plass line-breaking algorithm using Pretext, which hyphenates and justifies text optimally. The README describes it as a rare and experimental feature that has been made a toggle because of its fragileness.

### How is enscribe.dev built and deployed?

It is built with Astro and vanilla CSS on Bun, with media, fonts and the linebreak package prepared before astro build runs and pagefind indexing the dist output. Deployment goes through Cloudflare with wrangler, using the deploy:cloudflare script to build and then run wrangler deploy.

### Why are the numerals and small caps baked into the served fonts on enscribe.dev?

So that canvas text measurement sees the same glyph widths the page renders, which the line-breaking algorithm depends on. Applying small caps with font-variant instead would leave the measured widths different from the rendered ones and the breaks would be placed against the wrong metrics.

## Sources

- [Issues](https://github.com/jktrn/enscribe.dev/issues)
- [jktrn/enscribe.dev on GitHub](https://github.com/jktrn/enscribe.dev)
- [Project website](https://enscribe.dev)
- [README](https://github.com/jktrn/enscribe.dev/blob/main/README.md)
- [Releases](https://github.com/jktrn/enscribe.dev/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/jktrn-enscribe-dev
