Loading…

Joe Steinbring

Personal website and digital gardenjws.dev

A statically generated personal site in four languages: professional experience, résumé, travel history, projects, and public activity, with its own JSON API and self-hosted behind NGINX.

In active development
The jws.dev homepage: a portrait beside an introduction, with a marquee of technology icons.
The jws.dev homepage, captured from the current build.

At a glanceProject statistics

Pages prerendered
1260
Languages
4
Technologies documented
100
API collections
11

Purpose and directionThe goal

jws.dev brings my professional history, projects, travel, and public activity together under one domain I own and host myself. It is deliberately built to be evidence rather than assertion: every page is prerendered and served by NGINX as static files, so Node.js is used only by the build system and never at request time. The whole site is published in four languages, the same content is available through a versioned JSON API so a native app can be built against it, and an automated audit suite has to pass before a build ships.

Connected to My ExperienceTechnologies used

Select a technology to read more about my experience with it and how I use it.

Explore the technology stack

AstroStatic routing, generated content pages, metadata, optimized image delivery, and production output served by NGINX.Vue.jsFocused interactive islands for navigation, maps, filters, feeds, and interface controls.Node.jsBuild-time content generators, consistency audits, data processing, and résumé output; Node.js is not required by the production web server.Web ComponentsStandards-based reusable components that work cleanly alongside Astro and Vue.Web AwesomeLocally installed cards, page layout, observers, controls, and other interface primitives.Font AwesomeLocally served semantic icons for navigation, actions, technology references, and metadata.LeafletInteractive travel maps enhanced with local static fallbacks for offline resilience.Semantic HTMLMeaningful page structure for accessibility, search visibility, and durable no-script content.AccessibilityKeyboard support, reduced-motion behavior, descriptive media, landmarks, and clear status messages.API DevelopmentA versioned JSON API that mirrors the site content, with a manifest of content hashes so a client can tell what changed before downloading anything.Search Engine OptimizationPer-locale canonicals, reciprocal hreflang across four languages, a generated sitemap, and structured metadata on every route.Hosting & InfrastructureSelf-hosted on my own server and served as static files behind NGINX, with no third-party analytics or tracking.GitVersion control for the site’s source, generated assets, and incremental content development.

Built for a second front endThe JSON API

The same content that renders these pages is published as a versioned JSON API, so a native app could be built against it without scraping the site. Version 1exposes 11 collections across 4 languages from 12 endpoints.

A client only needs one URL. The manifest lists every collection with a hash of its contents, so an app can compare hashes and tell what changed since its last sync before downloading anything.

Read the manifest

Measured, not assertedPerformance and accessibility

These numbers are generated during the build by measuring the output, so they describe the version of the site you are reading rather than a good day in a testing tool.

Pages prerendered
1,260Every route is static HTML; nothing is rendered on request.
JavaScript shipped
1,138 KBAcross the whole site. Interactive islands load only where a page needs them.
CSS shipped
362 KBBundled and shared across every page.
Median page
29 KBLargest is 113 KB.

Accessibility across all 1,260 pages

  • Declare a document languageevery page
  • Have exactly one top-level headingevery page
  • Expose a main landmarkevery page
  • Describe every imageevery page
  • Avoid positive tab indexesevery page

These are checks a build can make honestly. Colour contrast and focus order are verified by hand, because they need a real browser and a real keyboard to judge.