Tweaks, fixes, etc
All checks were successful
ci/woodpecker/push/ci Pipeline was successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/push/deploy Pipeline was successful

This commit is contained in:
2026-02-13 18:12:52 -03:00
parent 9a84e9003a
commit 27808cfd0e
11 changed files with 277 additions and 281 deletions

View File

@@ -1,7 +1,7 @@
{ {
"semi": false, "semi": false,
"singleQuote": true, "singleQuote": true,
"tabWidth": 2, "tabWidth": 4,
"trailingComma": "none", "trailingComma": "none",
"overrides": [ "overrides": [
{ {

View File

@@ -81,7 +81,7 @@ Static landing site for **mifi.holdings** (and www). Plain HTML/CSS/JS source; a
- **Frontend**: Static HTML + CSS + JS in `src/`; production build minifies and inlines critical CSS. - **Frontend**: Static HTML + CSS + JS in `src/`; production build minifies and inlines critical CSS.
- **Server**: nginx (Alpine) in Docker. - **Server**: nginx (Alpine) in Docker.
- **Tooling**: **pnpm**; Prettier (format); ESLint (JS), Stylelint (CSS), yamllint (YAML); **terser**, **clean-css**, **critters** (build). - **Tooling**: **pnpm**; Prettier (format); ESLint (JS), Stylelint (CSS), yamllint (YAML); **terser**, **clean-css**, **beasties** (build).
- **Deployment**: Docker image (from `dist/`) → Gitea registry → Portainer stack redeploy. - **Deployment**: Docker image (from `dist/`) → Gitea registry → Portainer stack redeploy.
--- ---

View File

@@ -2,6 +2,7 @@ services:
mifi-holdings-landing: mifi-holdings-landing:
image: git.mifi.dev/mifi-holdings/landing:latest image: git.mifi.dev/mifi-holdings/landing:latest
container_name: mifi-holdings-landing container_name: mifi-holdings-landing
restart: unless-stopped
networks: networks:
- marina-net - marina-net
labels: labels:

View File

@@ -1,6 +1,6 @@
{ {
"type": "module",
"name": "mifi-holdings-landing", "name": "mifi-holdings-landing",
"type": "module",
"version": "1.0.0", "version": "1.0.0",
"packageManager": "pnpm@10.29.3", "packageManager": "pnpm@10.29.3",
"scripts": { "scripts": {
@@ -20,7 +20,7 @@
}, },
"devDependencies": { "devDependencies": {
"clean-css": "^5.3.3", "clean-css": "^5.3.3",
"critters": "^0.0.25", "beasties": "^0.4.1",
"eslint": "^10.0.0", "eslint": "^10.0.0",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"prettier": "^3.4.2", "prettier": "^3.4.2",

87
pnpm-lock.yaml generated
View File

@@ -8,12 +8,12 @@ importers:
.: .:
devDependencies: devDependencies:
beasties:
specifier: ^0.4.1
version: 0.4.1
clean-css: clean-css:
specifier: ^5.3.3 specifier: ^5.3.3
version: 5.3.3 version: 5.3.3
critters:
specifier: ^0.0.25
version: 0.0.25
eslint: eslint:
specifier: ^10.0.0 specifier: ^10.0.0
version: 10.0.0 version: 10.0.0
@@ -241,6 +241,10 @@ packages:
resolution: {integrity: sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==} resolution: {integrity: sha512-x0K50QvKQ97fdEz2kPehIerj+YTeptKF9hyYkKf6egnwmMWAkADiO0QCzSp0R5xN8FTZgYaBfSaue46Ej62nMg==}
engines: {node: 20 || >=22} engines: {node: 20 || >=22}
beasties@0.4.1:
resolution: {integrity: sha512-2Imdcw3LznDuxAbJM26RHniOLAzE6WgrK8OuvVXCQtNBS8rsnD9zsSEa3fHl4hHpUY7BYTlrpvtPVbvu9G6neg==}
engines: {node: '>=18.0.0'}
boolbase@1.0.0: boolbase@1.0.0:
resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==} resolution: {integrity: sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==}
@@ -262,10 +266,6 @@ packages:
resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==}
engines: {node: '>=6'} engines: {node: '>=6'}
chalk@4.1.2:
resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==}
engines: {node: '>=10'}
clean-css@5.3.3: clean-css@5.3.3:
resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==} resolution: {integrity: sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==}
engines: {node: '>= 10.0'} engines: {node: '>= 10.0'}
@@ -298,10 +298,6 @@ packages:
typescript: typescript:
optional: true optional: true
critters@0.0.25:
resolution: {integrity: sha512-ROF/tjJyyRdM8/6W0VqoN5Ql05xAGnkf5b7f3sTEl1bI5jTQQf8O918RD/V9tEb9pRY/TKcvJekDbJtniHyPtQ==}
deprecated: Ownership of Critters has moved to the Nuxt team, who will be maintaining the project going forward. If you'd like to keep using Critters, please switch to the actively-maintained fork at https://github.com/danielroe/beasties
cross-spawn@7.0.6: cross-spawn@7.0.6:
resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
@@ -310,15 +306,15 @@ packages:
resolution: {integrity: sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==} resolution: {integrity: sha512-8HFEBPKhOpJPEPu70wJJetjKta86Gw9+CCyCnB3sui2qQfOvRyqBy4IKLKKAwdMpWb2lHXWk9Wb4Z6AmaUT1Pg==}
engines: {node: '>=12'} engines: {node: '>=12'}
css-select@5.2.2: css-select@6.0.0:
resolution: {integrity: sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==} resolution: {integrity: sha512-rZZVSLle8v0+EY8QAkDWrKhpgt6SA5OtHsgBnsj6ZaLb5dmDVOWUDtQitd9ydxxvEjhewNudS6eTVU7uOyzvXw==}
css-tree@3.1.0: css-tree@3.1.0:
resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==} resolution: {integrity: sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==}
engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0} engines: {node: ^10 || ^12.20.0 || ^14.13.0 || >=15.0.0}
css-what@6.2.2: css-what@7.0.0:
resolution: {integrity: sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==} resolution: {integrity: sha512-wD5oz5xibMOPHzy13CyGmogB3phdvcDaB5t0W/Nr5Z2O/agcB8YwOz6e2Lsp10pNDzBoDO9nVa3RGs/2BttpHQ==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
cssesc@3.0.0: cssesc@3.0.0:
@@ -362,6 +358,10 @@ packages:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
entities@7.0.1:
resolution: {integrity: sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==}
engines: {node: '>=0.12'}
env-paths@2.2.1: env-paths@2.2.1:
resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -508,10 +508,6 @@ packages:
globjoin@0.1.4: globjoin@0.1.4:
resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==}
has-flag@4.0.0:
resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==}
engines: {node: '>=8'}
has-flag@5.0.1: has-flag@5.0.1:
resolution: {integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==} resolution: {integrity: sha512-CsNUt5x9LUdx6hnk/E2SZLsDyvfqANZSUq4+D3D8RzDJ2M+HDTIkF60ibS1vHaK55vzgiZw1bEPFG9yH7l33wA==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -527,8 +523,8 @@ packages:
resolution: {integrity: sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ==} resolution: {integrity: sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ==}
engines: {node: '>=20.10'} engines: {node: '>=20.10'}
htmlparser2@8.0.2: htmlparser2@10.1.0:
resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} resolution: {integrity: sha512-VTZkM9GWRAtEpveh7MSF6SjjrpNVNNVJfFup7xTY3UpFtm67foy9HDVXneLtFVt4pMz5kZtgNcvCniNFb1hlEQ==}
ignore@5.3.2: ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
@@ -856,10 +852,6 @@ packages:
resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==} resolution: {integrity: sha512-SS+jx45GF1QjgEXQx4NJZV9ImqmO2NPz5FNsIHrsDjh2YsHnawpan7SNQ1o8NuhrbHZy9AZhIoCUiCeaW/C80g==}
engines: {node: '>=18'} engines: {node: '>=18'}
supports-color@7.2.0:
resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==}
engines: {node: '>=8'}
supports-hyperlinks@4.4.0: supports-hyperlinks@4.4.0:
resolution: {integrity: sha512-UKbpT93hN5Nr9go5UY7bopIB9YQlMz9nm/ct4IXt/irb5YRkn9WaqrOBJGZ5Pwvsd5FQzSVeYlGdXoCAPQZrPg==} resolution: {integrity: sha512-UKbpT93hN5Nr9go5UY7bopIB9YQlMz9nm/ct4IXt/irb5YRkn9WaqrOBJGZ5Pwvsd5FQzSVeYlGdXoCAPQZrPg==}
engines: {node: '>=20'} engines: {node: '>=20'}
@@ -1115,6 +1107,18 @@ snapshots:
dependencies: dependencies:
jackspeak: 4.2.3 jackspeak: 4.2.3
beasties@0.4.1:
dependencies:
css-select: 6.0.0
css-what: 7.0.0
dom-serializer: 2.0.0
domhandler: 5.0.3
htmlparser2: 10.1.0
picocolors: 1.1.1
postcss: 8.5.6
postcss-media-query-parser: 0.2.3
postcss-safe-parser: 7.0.1(postcss@8.5.6)
boolbase@1.0.0: {} boolbase@1.0.0: {}
brace-expansion@5.0.2: brace-expansion@5.0.2:
@@ -1137,11 +1141,6 @@ snapshots:
callsites@3.1.0: {} callsites@3.1.0: {}
chalk@4.1.2:
dependencies:
ansi-styles: 4.3.0
supports-color: 7.2.0
clean-css@5.3.3: clean-css@5.3.3:
dependencies: dependencies:
source-map: 0.6.1 source-map: 0.6.1
@@ -1171,16 +1170,6 @@ snapshots:
js-yaml: 4.1.1 js-yaml: 4.1.1
parse-json: 5.2.0 parse-json: 5.2.0
critters@0.0.25:
dependencies:
chalk: 4.1.2
css-select: 5.2.2
dom-serializer: 2.0.0
domhandler: 5.0.3
htmlparser2: 8.0.2
postcss: 8.5.6
postcss-media-query-parser: 0.2.3
cross-spawn@7.0.6: cross-spawn@7.0.6:
dependencies: dependencies:
path-key: 3.1.1 path-key: 3.1.1
@@ -1189,10 +1178,10 @@ snapshots:
css-functions-list@3.3.3: {} css-functions-list@3.3.3: {}
css-select@5.2.2: css-select@6.0.0:
dependencies: dependencies:
boolbase: 1.0.0 boolbase: 1.0.0
css-what: 6.2.2 css-what: 7.0.0
domhandler: 5.0.3 domhandler: 5.0.3
domutils: 3.2.2 domutils: 3.2.2
nth-check: 2.1.1 nth-check: 2.1.1
@@ -1202,7 +1191,7 @@ snapshots:
mdn-data: 2.12.2 mdn-data: 2.12.2
source-map-js: 1.2.1 source-map-js: 1.2.1
css-what@6.2.2: {} css-what@7.0.0: {}
cssesc@3.0.0: {} cssesc@3.0.0: {}
@@ -1238,6 +1227,8 @@ snapshots:
entities@4.5.0: {} entities@4.5.0: {}
entities@7.0.1: {}
env-paths@2.2.1: {} env-paths@2.2.1: {}
error-ex@1.3.4: error-ex@1.3.4:
@@ -1410,8 +1401,6 @@ snapshots:
globjoin@0.1.4: {} globjoin@0.1.4: {}
has-flag@4.0.0: {}
has-flag@5.0.1: {} has-flag@5.0.1: {}
hashery@1.4.0: hashery@1.4.0:
@@ -1422,12 +1411,12 @@ snapshots:
html-tags@5.1.0: {} html-tags@5.1.0: {}
htmlparser2@8.0.2: htmlparser2@10.1.0:
dependencies: dependencies:
domelementtype: 2.3.0 domelementtype: 2.3.0
domhandler: 5.0.3 domhandler: 5.0.3
domutils: 3.2.2 domutils: 3.2.2
entities: 4.5.0 entities: 7.0.1
ignore@5.3.2: {} ignore@5.3.2: {}
@@ -1730,10 +1719,6 @@ snapshots:
supports-color@10.2.2: {} supports-color@10.2.2: {}
supports-color@7.2.0:
dependencies:
has-flag: 4.0.0
supports-hyperlinks@4.4.0: supports-hyperlinks@4.4.0:
dependencies: dependencies:
has-flag: 5.0.1 has-flag: 5.0.1

View File

@@ -1,5 +1,5 @@
/** /**
* Build script: copy src → dist, minify JS/CSS, inline critical CSS (Critters). * Build script: copy src → dist, minify JS/CSS, inline critical CSS (Beasties).
* Run with: pnpm build * Run with: pnpm build
*/ */
import { import {
@@ -12,7 +12,7 @@ import {
} from 'fs' } from 'fs'
import { join, dirname, extname } from 'path' import { join, dirname, extname } from 'path'
import { fileURLToPath } from 'url' import { fileURLToPath } from 'url'
import Critters from 'critters' import Beasties from 'beasties'
import { minify as minifyJs } from 'terser' import { minify as minifyJs } from 'terser'
import CleanCSS from 'clean-css' import CleanCSS from 'clean-css'
@@ -56,16 +56,18 @@ async function main() {
if (!result.errors.length) writeFileSync(f, result.styles) if (!result.errors.length) writeFileSync(f, result.styles)
} }
// 4. Inline critical CSS with Critters (no browser; works in CI) // 4. Inline critical CSS with Beasties for all HTML files (no browser; works in CI)
const critters = new Critters({ const htmlFiles = distFiles.filter((f) => extname(f) === '.html')
const beasties = new Beasties({
path: distDir, path: distDir,
preload: 'default', preload: 'default',
logLevel: 'warn' logLevel: 'warn'
}) })
const indexPath = join(distDir, 'index.html') for (const htmlFile of htmlFiles) {
const html = readFileSync(indexPath, 'utf8') const html = readFileSync(htmlFile, 'utf8')
const inlined = await critters.process(html) const inlined = await beasties.process(html)
writeFileSync(indexPath, inlined) writeFileSync(htmlFile, inlined)
}
console.log('Build complete: dist/') console.log('Build complete: dist/')
} }

View File

@@ -26,8 +26,16 @@
<link rel="stylesheet" href="assets/css/style.css" /> <link rel="stylesheet" href="assets/css/style.css" />
<link rel="icon" type="image/svg+xml" href="/assets/images/favicon.svg" /> <link
<link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico" /> rel="icon"
type="image/svg+xml"
href="/assets/images/favicon.svg"
/>
<link
rel="icon"
type="image/x-icon"
href="/assets/images/favicon.ico"
/>
<link <link
rel="apple-touch-icon" rel="apple-touch-icon"
sizes="180x180" sizes="180x180"
@@ -39,10 +47,10 @@
<div class="emoji">🛸</div> <div class="emoji">🛸</div>
<h1>Nothing to See Here</h1> <h1>Nothing to See Here</h1>
<p> <p>
You&apos;ve stumbled onto <b>mifi.holdings</b> — the legendary vault of You&apos;ve stumbled onto <b>mifi.holdings</b> — the legendary
digital oddities, curios, and coffee-fueled experiments belonging to a vault of digital oddities, curios, and coffee-fueled experiments
possibly-human, definitely-mysterious entity named belonging to a possibly-human, definitely-mysterious entity
<b>mifi</b>.<br /><br /> named <b>mifi</b>.<br /><br />
There&apos;s nothing here for you.<br /> There&apos;s nothing here for you.<br />
Go on. Shoo. Scram. Or just keep wondering. Go on. Shoo. Scram. Or just keep wondering.
</p> </p>