Skip to content
0% · 14m

Building a Connected Engineering Blog with Next.js

By 14 min read views

An engineering blog becomes more useful when an article is not an isolated page. It should remain readable as ordinary prose, connect to the work around it, expose enough structure for search engines and machine readers, and require almost no publishing maintenance. This article documents the current system and deliberately exercises its major features.

The boundary is intentionally simple: Markdown owns the writing, Next.js owns the presentation, Git owns the history, and Vercel owns deployment. A small compiler connects those responsibilities without introducing a CMS or a second website stack.

The publishing architecture#

A note begins as local Markdown. Frontmatter supplies its stable title, summary, dates, aliases, publication status, and tags. The build validates that contract, resolves internal references, calculates indexes, and emits static or server-rendered HTML alongside machine-readable representations.

Publication is explicit. A file must be inside a public collection and declare publish: true; private vault material is never copied into the site. The repository also includes a publishing command that validates notes before they cross that boundary.

Frontmatter is a contract#

yaml
title: "Building a Connected Engineering Blog with Next.js"
description: "How the connected publishing system works."
publish: true
status: reference
created: "2026-07-17"
updated: "2026-07-17"
tags:
  - Next.js
  - software engineering
aliases:
  - Connected Engineering Notes

The three statuses describe editorial state without relying on a gardening metaphor:

StatusMeaningExpected use
BriefA concise observation or working ideaQuick technical findings
DevelopingA note that is still being expandedActive investigations
ReferenceA complete article intended for repeated useDurable explanations

The quality gate rejects missing titles, malformed dates, unsafe or duplicate routes, unresolved public wikilinks, missing images, invalid frontmatter, and secret-like values. TypeScript, ESLint, and the production build run before a change is published.

The publishing command is the boundary#

The private writing vault and website repository remain separate. The repository's publishing command reads only the selected public folder and only files with publish: true:

bash
npm run publish:notes -- \
  --source=/absolute/path/to/Vault/Public \
  --attachments=/absolute/path/to/Vault/Attachments \
  --build \
  --push

It validates titles, aliases, paths, and wikilinks; converts Obsidian image embeds; copies referenced attachments into hashed public asset names; removes files from the previous publishing manifest; validates the resulting public corpus; optionally runs the production build; and commits and pushes only the generated notes, assets, and publishing manifest. Replacing --build --push with --check performs a non-mutating eligibility check.

That's the documented path, but it isn't the only one in active use. Obsidian R2 Workflow describes how a growing share of notes, including this one, are written and edited directly in this repository instead of round-tripping through the vault, while still passing through the same validation and build gate before they go live.

Connections are part of the content model#

Markdown links and Obsidian-style wikilinks are resolved during compilation. For example, Ship of Theseus resolves through its title or alias to a normal, accessible HTML link. The target then receives a backlink automatically.

For every note vv, the compiler records outgoing edges. Reversing them produces backlinks:

B(v)={uV(u,v)E}B(v) = \{u \in V \mid (u, v) \in E\}

That shared index powers:

  • connected notes at the end of an article;
  • backlinks from notes that cite the current page;
  • related entries inferred from tags and graph proximity;
  • navigable internal-link previews;
  • the compact and full notes graphs.

PageRank identifies influential notes#

The notes index provides Top, Name, and Latest sorting. Top is not a manual editorial order: it follows PageRank over explicit internal links. For node vv, the iterative score is:

PR(v)=1dV+duB(v)PR(u)L(u)PR(v) = \frac{1-d}{|V|} + d \sum_{u \in B(v)} \frac{PR(u)}{L(u)}

where d=0.85d = 0.85 and L(u)L(u) is the number of outgoing links from uu. Dangling rank is redistributed across the graph, and iteration stops after convergence. The highest-ranked note begins at the center of the visualization; subsequent notes settle in progressively wider reference rings.

PageRank answers which notes are influential, while Girvan–Newman answers which notes form communities. The build calculates edge betweenness with Brandes' algorithm, removes the most central bridge, recomputes betweenness, and repeats until a useful number of connected components appears. Community membership controls node color.

The full notes graph combines those results with a physical simulation:

  • PageRank controls centrality and initial order;
  • Girvan–Newman communities control color;
  • circle area represents article word count;
  • explicit links behave like springs;
  • repulsion and collision keep nodes legible;
  • panning, zooming, dragging, and hover inspection remain interactive.

A compact framed graph is also embedded directly in /notes. Its initial render fits every node inside the frame and expands outward from the center. The accessible list beneath the canvas preserves every graph destination for keyboard users and non-visual readers.

Finding and browsing published work#

Discovery is deliberately available without making the graph the only way to navigate.

Search, sorting, and responsive pagination#

The Notes page searches titles, summaries, folders, and tags. All Posts searches both modern notes and legacy essays. The global Cmd/Ctrl +

K palette searches notes, essays, tags, and photos from one compact generated index; pressing / while not typing opens the same search. Photo results retain their thumbnails rather than being reduced to generic text rows.

Pagination follows viewport capacity:

CollectionMobileTabletDesktop
Notes468
All Posts61014

Filtering resets pagination to the first valid page, while URLs retain a shareable page number.

List and grid orientation#

Every primary content collection has an accessible List/Grid switch:

  • the Notes index;
  • individual folders and topic pages;
  • All Posts;
  • latest writing on the landing page;
  • Photos;
  • the folder browser itself.

List mode favors scanning metadata in sequence. Grid mode gives each result a self-contained card, similar to a compact research-note catalogue. The orientation buttons expose aria-pressed state and work without hiding content from assistive technology. Each page remembers its own choice, so changing Notes does not alter Photos, All Posts, the landing page, or a specific folder or tag page. Card grids use one column on mobile, two on medium screens, and three equal columns on wide screens while remaining inside the same site body width.

Folder browsing now belongs inside Notes instead of the landing dashboard. This keeps the home page focused on recent writing while /notes owns search, folders, topics, publication status, and graph exploration.

Photos participate in discovery#

Photos are first-class search documents rather than a disconnected gallery. Global search results include thumbnails and navigate directly to photo pages. The Photos page has its own search and List/Grid control: grid mode provides a visual gallery and dialog, while list mode includes the thumbnail, description, location, engagement counts, and a permanent detail link. Photo dialogs and detail pages expose views, one-time likes, private feedback, and native sharing with clipboard fallback. On touch devices, a deliberate press-and-hold gesture can share directly from the grid without first opening the dialog.

The first above-the-fold image loads eagerly for good Largest Contentful Paint; the remaining images remain lazy. The photo search/view toolbar takes over the top edge only after the normal site header has scrolled away.

Technical prose renders like technical prose#

The renderer supports GitHub-flavoured Markdown, mathematical notation, language-aware code, diagrams, tables, task lists, quotations, and deep heading structure. The output is semantic HTML rather than a client-only editor.

Mathematics with LaTeX#

Inline expressions such as O(nlogn)O(n \log n) stay within the sentence. Display expressions use KaTeX:

H(X)=xXp(x)log2p(x)H(X) = -\sum_{x \in \mathcal{X}} p(x)\log_2 p(x)

Code with theme-aware highlighting#

Fenced code retains its language and exposes a copy control:

ts
type PublicationStatus = "brief" | "developing" | "reference";


function canPublish(input: { publish: boolean; status: PublicationStatus }) {
  return input.publish && input.status !== "brief";
}

Light mode uses a paper-like surface and dark syntax. Dark mode uses an ambient surface with light, language-aware tokens. Both keep the code distinct without turning it into an unrelated black rectangle.

Tables, tasks, and quotations#

Tables use a complete cell grid at every viewport size, with overflow available when technical content is wider than the reading column.

  • validate public metadata;
  • resolve wikilinks and backlinks;
  • calculate PageRank and communities;
  • generate search, feeds, sitemap, and machine-readable text;
  • render diagrams, mathematics, and highlighted code;
  • provide list and grid discovery modes;
  • keep improving the writing itself.

The publishing system should disappear during writing and become strict only at the boundary where private thought turns into public information.

Reading without interface noise#

Every published note omits the global site header, regardless of its collection, so the page begins with the article itself. Collection indexes, graphs, photos, and supporting pages retain the normal navigation. A fixed top-right reading percentage, extracted table of contents that highlights the nearest section, and active-heading state provide orientation without crowding the reading column or placing a bar over the text. When the contents list is longer than its frame, it scrolls itself to keep the current section in view on desktop and whenever the mobile panel opens. A fixed close control returns directly to the complete Notes index from every collection. On mobile, the table of contents collapses into a small fixed icon beside the configurator and reading percentage; selecting a section navigates to it and dismisses the section menu. After a contents jump, the close control temporarily becomes a back arrow labelled with the previous section; returning there restores the usual close action.

A neighboring reading control stays collapsed until requested. It offers the site's default typeface plus five self-hosted reading fonts—Inter, Atkinson Hyperlegible, Source Serif 4, Lora, and Merriweather—text sizing from 90% to 120%, left, center, right, or justified alignment, narrow or wide reading widths, and bright or dark page tones. Choosing Site default removes the article-level font override; the other choices persist across articles while leaving code in its monospace typeface and keeping the document structure unchanged for browser reader modes. Wide reading mode uses the broader article column while retaining the desktop On this page sidebar by default. A reader can collapse that sidebar into a compact dialog button and pin it back onto the page from inside the dialog; the preference persists across articles.

Selecting a word or phrase in an article reveals a small Look up action. The definition panel resolves site-specific terms, WordNet entries, computer-science terms, and engineering idioms from local dictionaries, then presents every matching source together. The selected text stays on the server that already serves the site; lookup does not send reading activity to an external dictionary service.

Breadcrumbs remain available across notes, folders, topics, graphs, photos, and archive pages. On articles they describe Home → Notes → Folder → Article in both visible navigation and BreadcrumbList structured data.

Each note footer includes an email-feedback action addressed to the site owner. The generated message subject is Feedback: <note title>, and its body includes the canonical note URL so feedback retains its context outside the browser.

The semantic main, article, headline, author, dates, headings, and articleBody markers give browser reader modes a clean extraction target. The same article also has a direct raw Markdown representation, so immersive readers and machines do not need to reverse-engineer the interactive layout.

Internal references open a preview containing the target title, summary, folder, and publication status. The entire preview is navigable, not just its small title. Supported external references—such as Wikipedia's overview of hypertext— load a title, extract, description, and image, and likewise remain clickable.

Visual system and accessibility#

The default appearance for a new visitor is dark, with #1f1e1d as the main canvas. Supporting cards, popovers, borders, and muted text use a warm neutral palette rather than blue-grey black. Explicit Light, Dark, and System choices remain available and are respected on subsequent visits.

List and grid cards use the same restrained corner radius as the primary landing page buttons, keeping repeated content surfaces precise without making every panel feel like a floating container.

The typography is self-hosted, including the five optional reading fonts, and adds no external font request:

  • Inter for interface and default reading text;
  • Roboto Mono for dates, labels, metadata, and code-adjacent details;
  • KaTeX's mathematical fonts for formulas.

The layout uses visible focus states, semantic landmarks, skip navigation, accessible graph destinations, labelled control groups, reduced-motion rules, and responsive content widths. Interactive flourishes never replace the normal link or text representation.

The global header, page body, and footer share one content container and the same responsive gutters, keeping their left and right edges aligned across notes, indexes, graphs, photos, and supporting pages. On pages that retain the global header, it stays in normal document flow and scrolls away instead of occupying the viewport throughout the visit.

SEO and machine readability#

Good discovery begins with complete HTML. Each article receives a unique title and description, canonical URL, publication and modification dates, Open Graph and Twitter metadata, large image previews, and TechArticle structured data. The sitemap and Atom feed enumerate public content, while stable headings and internal links make the documents understandable without running the graph or search interfaces.

The Atom feed is advertised in page metadata for automatic discovery. A human-readable /subscribe page provides one-click Feedly and Inoreader links, the raw feed, a copyable feed URL, and setup instructions for any other reader.

Machine readers receive multiple coordinated entry points:

  • robots.txt explicitly permits major search and user-fetch agents;
  • llms.txt describes the author and canonical collections;
  • llms-full.txt provides the full public corpus with metadata and URLs;
  • /raw/[folder]/[slug] provides per-article Markdown;
  • every article advertises its Markdown alternate;
  • the footer exposes the AI index and subscription guide as normal links.

The crawler policy covers current agents from OpenAI, Anthropic, Perplexity, Google, Microsoft, Meta, and Apple, with a permissive fallback for other readers. This cannot force a model to browse or cite the site, but it removes avoidable technical barriers.

Design references and implementation choices#

Two independent sites helped clarify the product direction. Bibek Panthi's connected notes demonstrate the value of backlinks, a physical link graph, lightweight static pages, and a clear feed-subscription path. Hugo Cisneros's Notes show how a searchable notes index can remain calm, compact, and useful without becoming a dashboard.

This implementation borrows those interaction principles rather than either site's stack or visual identity. It keeps the existing Next.js application, uses the site's own content compiler and design tokens, treats the output as a professional engineering archive, and avoids metaphorical publication labels.

One source, several representations#

ConsumerRepresentation
ReaderSemantic HTML, reading controls, TOC, lookup, and feedback
Search engineCanonicals, JSON-LD, sitemap, metadata, and internal links
Feed readerAtom entries and a human-readable subscription guide
Site searchGenerated notes, essays, tags, and photo documents
Notes graphPageRank, communities, word counts, and explicit edges
AI crawlerHTML, per-article Markdown, llms.txt, and llms-full.txt

Correcting a title or adding a link updates the page, breadcrumb, search result, graph label, backlink index, feed metadata, sitemap, and machine-readable corpus from the same source.

Current public routes#

RoutePurpose
/notesSearch, folders, topics, statuses, and graph
/notes/graphFull interactive notes graph
/all-postsUnified modern and legacy archive
/photosSearchable list/grid photo collection
/photos/[id]Canonical photo detail and engagement page
/tags/[tag]Topic-specific note results
/raw/[folder]/[slug]Plain Markdown representation
/search-index.jsonGenerated global-search document index
/robots.txtSearch and AI crawler policy
/sitemap.xmlSearch discovery index
/atomFeed-reader representation
/subscribeHuman-readable feed subscription guide
/llms.txtMachine-oriented site guide
/llms-full.txtFull machine-readable public corpus

Legacy /knowledge URLs permanently redirect to /notes, preserving old links without keeping outdated public terminology.

What the reader should notice#

The system is broad, but the article remains the main object. Search is quick, the table of contents is quiet, previews appear only when requested, the graph starts fitted to its frame, and each interactive view has a normal link-based equivalent.

This page demonstrates the system in one ordinary Markdown file: validated metadata, aliases, publication status, headings and table of contents, LaTeX, Mermaid, highlighted code, tables, tasks, tags, a wikilink, backlinks, related notes, reading progress, mobile and desktop orientation, text lookup, adjustable reading presentation, close navigation, note-specific email feedback, internal and Wikipedia previews, structured data, responsive discovery, feed subscription, sitemap inclusion, reader-mode semantics, and machine-readable full text. That portability is the most important feature: the writing remains useful even outside the site that presents it.