diff --git a/.vscode/settings.json b/.vscode/settings.json index 9d12604..250c8f5 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -58,6 +58,7 @@ "fssync", "gitlens", "hrefs", + "HTMX", "jpoissonnier", "julr", "jvitor", diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 8c5efde..580e936 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -1,28 +1,22 @@ { - "version": "2.0.0", - "tasks": [ - { - "label": "Run tests", - "type": "shell", - "command": "npm test --silent", - "problemMatcher": [ - "$tsc", - "$eslint-stylish" - ] - }, - { - "label": "Run tests", - "type": "shell", - "command": "npm test --silent", - "problemMatcher": [ - "$tsc", - "$eslint-stylish" - ] - }, - { - "label": "Typecheck", - "type": "shell", - "command": "npm run tsc --silent" - } - ] -} \ No newline at end of file + "version": "2.0.0", + "tasks": [ + { + "label": "Run tests", + "type": "shell", + "command": "npm test --silent", + "problemMatcher": ["$tsc", "$eslint-stylish"] + }, + { + "label": "Run tests", + "type": "shell", + "command": "npm test --silent", + "problemMatcher": ["$tsc", "$eslint-stylish"] + }, + { + "label": "Typecheck", + "type": "shell", + "command": "npm run tsc --silent" + } + ] +} diff --git a/README.md b/README.md index 1530a1a..d470f55 100644 --- a/README.md +++ b/README.md @@ -4,23 +4,89 @@ [![Netlify Status](https://api.netlify.com/api/v1/badges/4df86a71-2a3f-40f9-9bd5-b6dacd4f420c/deploy-status)](https://app.netlify.com/sites/piech-dev/deploys) -My personal page. Over time it turned into a complex project itself: it supports loading all projects' information directly from GitHub, renders GitHub's markdown, the whole page is pre-rendered and served with zero JS. It also includes dynamic tags for each project page, including individual og:image tags with sizes. All routes have appropriate JSON-LD objects with relevant information. +My personal page. Over time it turned into a complex project itself: -Lighthouse results +- Despite being written in React, the whole page is pre-rendered and served with zero JavaScript! +- It supports loading all projects' information directly from GitHub. +- GitHub's markdown from the projects' readmes is rendered within the page, including media. +- Includes dynamic \ tags for each project page, including individual og:image tags with sizes. +- All routes have appropriate JSON-LD objects with all relevant information, even if Google or other search engines currently don't support some of them. +- Thanks to the above and a bunch of other optimizations, all routes, including the heaviest /projects route, score a perfect 100/100/100/100 on [Google Lighthouse](https://pagespeed.web.dev/) mobile, which throttles to a slow 4G network connection. -## Dynamic project list pulled from GitHub-based +_Not a single word of this readme was written with AI. Letting you know just in case you don't enjoy reading AI-generated documentation._ -- The projects/ page is managed via minimal configuration, just based on repository names. Projects metadata and READMEs are fetched directly from GitHub at build time. +Projects page of piech.dev + +## GitHub-based personal projects browser + +- The projects/ page is managed via minimal configuration, just based on repository names which are then fetched during the pre-build step. Projects metadata and READMEs are fetched directly from GitHub at build time. - Markdown rendering transforms relative links to proper URLs and handles videos, so that you can see video previews of my projects without leaving my site. - GitHub repository topics automatically become \ keywords. - GitHub information, as well as images are dynamically pulled to each project's \ into appropriate og: tags, allowing for custom preview card of each project in social media and on messengers. -## React pre-rendering with zero JavaScript served to the user +## Pre-rendering React with zero JavaScript served to the user - The whole site, including all project routes, is pre-rendered with React Router in framework mode into HTML. -- The site ships without ANY client-side JavaScript despite being built in React. -- For performance reasons, the whole CSS is inlined into HTML, as there is so little of it and it significantly sped up page load times and it eliminates the awful Flash of Unstyled Content no matter the connection speed. +- The site ships without ANY client-side JavaScript despite being built in React. The build tools have been fighting me on this, so I'm traversing the build directory and deleting all JavaScript even if it wouldn't be linked to, "just to be safe" :) +- For performance reasons, all CSS is inlined into HTML, as there is so little of it (in the grand scheme of things and network payloads). It significantly sped up page load times and it eliminates the awful Flash of Unstyled Content no matter the user's connection speed. - Images are utilizing Netlify Image CDN to speed up their load times and to avoid serving oversized images. -- Thanks to the above and a ton of other optimizations, all routes, including the heaviest /projects route, score a perfect 100/100/100/100 on [Google Lighthouse](https://pagespeed.web.dev/) mobile, which throttles to a slow 4G network connection. Lighthouse results + +## Post-build scripts + +As of 2025, if you want to use React for generating static HTML sites and you don't rely on all-batteries-included frameworks/services, the ecosystem support is quite poor. React-router v7 with its framework mode and pre-rendering support changed the situation for the better. Still, it is assumed you will serve the .html static assets and then hydrate the page with JavaScript. If you want to have a true zero-JS output, you have do some of the wiring yourself. Moreover, most popular NPM packages for inlining CSS inline it into each html element's tags, which doesn't support media queries. + +This resulted in the project using the following post-build steps: + +1. Transforming image paths to use Netlify Image CDN, scans all .html files and looks for images matching the criteria (it doesn't touch the og:image assets, for instance). +2. Inlining all CSS. Finds all .html files, resolves the files and dumps all their content into a single \