← FieldnoteTHE GUIDE · how it was built
Design showcase · build notes

A research tool that proves itself.

Fieldnote looks like a shipped dev-tool: a ⌘K palette that really searches, citations that pop a source card, a knowledge graph that lights up. It is a Next.js static export — no server, no database — that deploys to GitHub Pages as flat files. Here is how the illusion holds.

The idea

Scientists don’t lose their data — they lose the why. Which paper backed this claim? Which version of the protocol produced that figure? Fieldnote’s thesis is that a citation should be a first-class object, not a footnote: one canonical, resolvable DOI, deduplicated across the whole lab, attached directly to the sentence it supports. The site had to make that feel real in five seconds — so the hero is the product. You type; it searches; a source card shows the receipt. Everything else is proof the feeling holds up.

The stack

Because it is a project site at /fieldnote-research/, the config sets the base path and asset prefix so every URL resolves under that folder on Pages:

// next.config.mjs
const nextConfig = {
  output: 'export',
  basePath: '/fieldnote-research',
  assetPrefix: '/fieldnote-research/',
  trailingSlash: true,
  images: { unoptimized: true },
};

Signature technique #1 — a real ⌘K palette

The palette is not a screenshot. One PaletteBody component owns the query, the result set, and the active row; it renders both inline in the hero and inside a focus-trapped overlay dialog. The fuzzy matcher is a subsequence scorer that also returns the matched indices, so the UI can highlight exactly the letters you typed:

export function fuzzy(text, q) {
  let ti = 0, score = 0, prev = -2;
  const indices = [];
  for (const ch of q.toLowerCase()) {
    const found = text.toLowerCase().indexOf(ch, ti);
    if (found === -1) return null;      // not a subsequence
    score += found - prev - 1;                // penalise gaps
    if (isBoundary(text, found)) score -= 2;  // reward word starts
    indices.push(found); prev = found; ti = found + 1;
  }
  return { score, indices };
}

The keyboard contract is the whole point of a command palette, so it is exhaustive: a global /Ctrl-K listener toggles the overlay; the input is a role="combobox" that points aria-activedescendant at the selected role="option"; arrows / Home / End move it, Enter opens, Esc clears then closes. The dialog is aria-modal with a Tab focus-trap and restores focus to the trigger on close.

Reduced motion is respected everywhere: the overlay pop and ticker freeze, the graph stops pulsing, and reveals render in place — the palette still opens instantly.

Signature technique #2 — citations as objects

In the note mock, certain phrases are CitationChip components rather than plain text. The chip is a real button — hover or focus pops a card, click pins it for touch, Escape closes — and the card reads a shared SOURCES record, so the same DOI can be cited in many notes and counted once:

<span role="button" tabIndex={0} aria-expanded={pinned}
      aria-describedby={cardId}>
  {text}<sup>[{src.ref}]</sup>
  <span className="cite-card" id={cardId} role="tooltip">
    <b>{src.title}</b>
    <row>doi   {src.doi}</row>
    <row>venue {src.venue} · {src.year}</row>
  </span>
</span>

The backlinks rail beside the note lists the other notes that reference it — the human-readable edge of the same graph the #graph section draws as an SVG. Hover a node there and its neighbourhood lights up along the exact edges the search would traverse.

Details that matter

Ship it on GitHub Pages

Static export writes to out/. GitHub Pages serves this repo from /docs, so the build output is copied there with a .nojekyll marker (so Pages doesn't strip the _next folder):

# build → copy to docs → publish
npm run build
rm -rf docs && cp -r out docs && touch docs/.nojekyll

gh repo create bswxyz/fieldnote-research --public --source . --push
# Settings → Pages → main / docs
# live at https://bswxyz.github.io/fieldnote-research/

Because basePath and assetPrefix are set, every asset resolves under the project subpath, and trailingSlash keeps /guide/ working as a folder.


Fieldnote is a design-showcase concept. The notes, protocols, labs, and citations are fictional; search runs in memory with no real index, resolver, sync, or auth. See the repository README for the full demo-vs-real map.

← Back to Fieldnote