diff --git a/.github/workflows/pages.yml b/.github/workflows/pages.yml
index 96c606c..cd67ef3 100644
--- a/.github/workflows/pages.yml
+++ b/.github/workflows/pages.yml
@@ -44,14 +44,18 @@ jobs:
run: npm ci
- name: Build site
+ # Build into public/tsuki so the on-disk layout mirrors the URL structure
+ # (`/tsuki/foo` href → exampleSite/public/tsuki/foo file). This lets
+ # htmltest resolve internal links without needing URL-rewriting (which
+ # htmltest does not support).
working-directory: exampleSite
- run: hugo --gc --minify --baseURL "https://tiennm99.github.io/tsuki/"
+ run: hugo --gc --minify --destination public/tsuki --baseURL "https://tiennm99.github.io/tsuki/"
- name: Build Pagefind index
- run: npx pagefind --site exampleSite/public
+ run: npx pagefind --site exampleSite/public/tsuki
- name: Smoke tests (SEO + a11y + per-kind CSS budget + features regression guard)
- run: ./scripts/smoke-tests.sh exampleSite/public
+ run: ./scripts/smoke-tests.sh exampleSite/public/tsuki
- name: htmltest (broken internal links + HTML5 validation)
# Pinned to master SHA (2026-05-10) for supply-chain hygiene. Refresh periodically.
@@ -60,11 +64,12 @@ jobs:
config: .htmltest.yml
- name: Upload artifact
- # Only upload from the current Hugo version; the floor-version run is for compatibility check.
+ # Upload only the inner build (exampleSite/public/tsuki). Pages mounts the
+ # artifact root at /tsuki/, so the inner contents become the served site.
if: matrix.hugo == '0.154.0'
uses: actions/upload-pages-artifact@v5
with:
- path: exampleSite/public
+ path: exampleSite/public/tsuki
deploy:
needs: build
diff --git a/.gitignore b/.gitignore
index 32e1d11..ee641ae 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,4 @@ Thumbs.db
.vscode/
.idea/
*.swp
+tmp/
diff --git a/.htmltest.yml b/.htmltest.yml
index b1b325c..eb387c8 100644
--- a/.htmltest.yml
+++ b/.htmltest.yml
@@ -4,14 +4,10 @@ IgnoreDirectoryMissingTrailingSlash: true
IgnoreInternalEmptyHash: true
IgnoreEmptyHref: false
EnforceHTML5: true
-# Strip the /tsuki/ baseURL prefix so links resolve against exampleSite/public/.
-# htmltest's URLSwap is a regex substring match (not anchored), so the leading
-# "^" used previously silently failed against the minified `href=/tsuki/...`
-# outputs in built HTML — every link reported missing. Quoted plain-prefix form
-# matches whatever position /tsuki/ appears in the href, which for our build is
-# always at the start of relative URLs.
-URLSwap:
- "/tsuki/": /
+# CI builds with `hugo --destination public/tsuki` so the on-disk layout
+# mirrors the URL structure (`/tsuki/foo` → exampleSite/public/tsuki/foo).
+# htmltest has no URL-rewriting feature, so this is the cleanest way to make
+# internal-link resolution work without dual builds.
IgnoreURLs:
- "^https://giscus.app"
- "^https://github.com/"
diff --git a/layouts/404.html b/layouts/404.html
index 2d57e4a..373ba72 100644
--- a/layouts/404.html
+++ b/layouts/404.html
@@ -4,6 +4,6 @@
{{ end }}
diff --git a/layouts/_partials/header.html b/layouts/_partials/header.html
index 919d5a8..f55f1e0 100644
--- a/layouts/_partials/header.html
+++ b/layouts/_partials/header.html
@@ -1,5 +1,5 @@