Files
dylanmazzei-website/build.mjs
T
Alejandro Veras d0357f1c52 Merge option 2 homepage and visual language into the site
Rebuild the homepage on option 2's sections and effects (3D DNA, spinning
cube, giant words, fireworks journey, neon type, chrome ribbon) with copy
kept verbatim from the content document. Each venture now has its own 3D
object, the portfolio dashboard sits beside the DNA, the journey uses the
original stats row and the playbook keeps our book. Inner pages adopt the
same navy, glass and gradient skin, with dark as the default theme.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-01 12:47:20 -04:00

46 lines
2.3 KiB
JavaScript

// Builds the static site into ./dist. No dependencies: `node build.mjs`.
import { mkdir, rm, writeFile, cp, readFile } from 'node:fs/promises';
import { createHash } from 'node:crypto';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { page, eyebrow, btn } from './src/layout.mjs';
const root = dirname(fileURLToPath(import.meta.url));
const out = join(root, 'dist');
const pages = ['home', 'about', 'portfolio', 'consulting', 'marketing', 'business-setup', 'contact', 'press'];
await rm(out, { recursive: true, force: true });
await mkdir(out, { recursive: true });
await cp(join(root, 'static'), out, { recursive: true });
// Fingerprint CSS/JS so a new deploy never reuses a stale cached copy.
const hashOf = async (f) => createHash('sha256').update(await readFile(join(root, 'static', f))).digest('hex').slice(0, 10);
const assetVersions = Object.fromEntries(await Promise.all(['styles.css', 'site.js', 'home.css', 'home.js', 'fonts.css'].map(async (f) => ['/assets/' + f, await hashOf('assets/' + f)])));
const fingerprint = (html) => Object.entries(assetVersions).reduce((h, [u, v]) => h.replaceAll(`"${u}"`, `"${u}?v=${v}"`), html);
const urls = [];
for (const name of pages) {
const def = (await import(`./src/pages/${name}.mjs`)).default;
const file = join(out, def.path, 'index.html');
await mkdir(dirname(file), { recursive: true });
await writeFile(file, fingerprint(page(def)));
urls.push(def.path);
console.log('built', def.path);
}
await writeFile(join(out, '404.html'), fingerprint(page({
path: '/404/',
title: 'Page Not Found | Dylan Mazzei',
description: 'This page could not be found.',
body: `<section class="page-hero"><div class="wrap-narrow stack center" style="align-items:center;text-align:center">${eyebrow('404')}<h1 class="h-display-lg">Page Not Found</h1><div class="btn-row">${btn('BACK TO HOME', '/')}</div></div></section>`,
})));
const today = new Date().toISOString().slice(0, 10);
await writeFile(join(out, 'sitemap.xml'), `<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
${urls.map((u) => ` <url><loc>https://dylanmazzei.com${u}</loc><lastmod>${today}</lastmod></url>`).join('\n')}
</urlset>
`);
await writeFile(join(out, 'robots.txt'), 'User-agent: *\nAllow: /\nSitemap: https://dylanmazzei.com/sitemap.xml\n');
console.log('done →', out);