aboutsummaryrefslogtreecommitdiffhomepage
path: root/astro.config.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'astro.config.mjs')
-rw-r--r--astro.config.mjs54
1 files changed, 54 insertions, 0 deletions
diff --git a/astro.config.mjs b/astro.config.mjs
index 6b37a1a..bc9c803 100644
--- a/astro.config.mjs
+++ b/astro.config.mjs
@@ -1,3 +1,6 @@
+import { existsSync } from "node:fs";
+import { join } from "node:path";
+import { fileURLToPath } from "node:url";
import { defineConfig } from "astro/config";
import starlight from "@astrojs/starlight";
import sitemap from "@astrojs/sitemap";
@@ -5,6 +8,42 @@ import remarkMermaid from "remark-mermaidjs";
import ogImagePlugin from "./src/plugins/og-image";
import updatesIntegration from "./src/plugins/updates";
+// Apache (production) resolves a directory URL to its index.html, so the site can
+// link to `/bluebey-studio/`. Vite's dev server serves `/bluebey-studio/index.html`
+// but 404s on the directory form, so the link appears broken in `astro dev`.
+// This serve-only middleware rewrites such a URL to the index file it points at,
+// leaving the production output untouched.
+function publicDirIndexPlugin() {
+ const publicDir = fileURLToPath(new URL("./public/", import.meta.url));
+ return {
+ name: "serve-public-dir-index",
+ apply: "serve",
+ configureServer(server) {
+ server.middlewares.use((req, res, next) => {
+ const [pathname, query] = (req.url ?? "").split("?", 2);
+ // The studio is plain static files whose names never change, so a cached
+ // copy hides edits during development (the browser keeps running the old
+ // JS after it has been rebuilt).
+ if (pathname.startsWith("/bluebey-studio/")) {
+ res.setHeader("Cache-Control", "no-store");
+ }
+ // Only directory requests (trailing slash) can need an index file.
+ if (!pathname.endsWith("/")) return next();
+ let indexFile;
+ try {
+ indexFile = join(publicDir, decodeURIComponent(pathname), "index.html");
+ } catch {
+ return next(); // malformed percent-encoding
+ }
+ // Make sure the path stayed inside public/ and the file really exists.
+ if (!indexFile.startsWith(publicDir) || !existsSync(indexFile)) return next();
+ req.url = `${pathname}index.html${query ? `?${query}` : ""}`;
+ next();
+ });
+ },
+ };
+}
+
export default defineConfig({
site: "https://yasutakeyohei.com",
base: "/",
@@ -12,6 +51,9 @@ export default defineConfig({
markdown: {
remarkPlugins: [remarkMermaid],
},
+ vite: {
+ plugins: [publicDirIndexPlugin()],
+ },
integrations: [
sitemap(),
updatesIntegration(),
@@ -256,6 +298,18 @@ export default defineConfig({
},
],
},
+ // The mascot studio is its own section on purpose: it is a personal
+ // hobby project, not one of the site's political-activity tools, and
+ // the ぶるべー character belongs to the city (see the page's opening note).
+ {
+ label: "つくってあそぶ",
+ items: [
+ {
+ label: "ぶるべー スタジオ",
+ link: "/bluebey/",
+ },
+ ],
+ },
{ label: "ご支援", link: "/support/" },
{ label: "コンタクト", link: "/contact/" },
{ label: "私の方針", link: "/policy/" },