This commit is contained in:
2026-07-15 00:52:18 -04:00
parent 780bb5b65a
commit b19b5b1bd2
10 changed files with 893 additions and 41 deletions
+39 -12
View File
@@ -2,36 +2,63 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Pathway+Gothic+One&display=swap" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Pathway+Gothic+One&display=swap"
rel="stylesheet"
/>
<link href="https://mst.fntz.net/@alex" rel="me" />
<!-- opengraph tags -->
<meta property="og:image" content="https://storage.alexav.gg/content/picturev2.jpg" />
<meta
property="og:image"
content="https://storage.alexav.gg/content/picturev2.jpg"
/>
<meta property="og:title" content="alex" />
<meta property="og:description" content="hi, i'm alex! i'm obsessed with the last of us and i do a lot of code things. about it tbh" />
<meta
property="og:description"
content="hi, i'm alex! i'm obsessed with the last of us and i do a lot of code things. about it tbh"
/>
<meta property="og:url" content="https://alexav.gg" />
<meta property="og:site_name" content="alex" />
<!-- twitter tags -->
<meta name="twitter:title" content="alex" />
<meta name="twitter:description" content="hi, i'm alex! i'm obsessed with the last of us and i do a lot of code things. about it tbh" />
<meta
name="twitter:description"
content="hi, i'm alex! i'm obsessed with the last of us and i do a lot of code things. about it tbh"
/>
<meta name="twitter:url" content="https://alexav.gg" />
<meta name="twitter:image" content="https://storage.alexav.gg/content/picturev2.jpg" />
<meta
name="twitter:image"
content="https://storage.alexav.gg/content/picturev2.jpg"
/>
<meta name="twitter:card" content="summary" />
<!-- metadata -->
<meta name="title" content="alex" />
<meta name="description" content="hi, i'm alex! i'm obsessed with the last of us and i do a lot of code things. about it tbh" />
<meta name="keywords" content="alex frantz, frantz, alex, qa, javascript, html, react, python, java, alexavier frantz, alexavier, alexav, alexfrantz" />
<meta
name="description"
content="hi, i'm alex! i'm obsessed with the last of us and i do a lot of code things. about it tbh"
/>
<meta
name="keywords"
content="alex frantz, frantz, alex, qa, javascript, html, react, python, java, alexavier frantz, alexavier, alexav, alexfrantz"
/>
<title>alex</title>
<!--app-head-->
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<script defer data-domain="alexav.gg" src="https://metrics.alexav.gg/js/script.js"></script>
<div id="root"><!--app-html--></div>
<script type="module" src="/src/entry-client.tsx"></script>
<script
defer
data-domain="alexav.gg"
src="https://metrics.alexav.gg/js/script.js"
></script>
</body>
</html>
+14 -6
View File
@@ -4,25 +4,33 @@
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"dev:expose": "vite --host",
"build": "tsc -b && vite build",
"lint": "eslint .",
"preview": "vite preview"
"dev": "node server",
"build": "npm run build:client && npm run build:server",
"build:client": "vite build --outDir dist/client",
"build:server": "vite build --ssr src/entry-server.tsx --outDir dist/server",
"preview": "cross-env NODE_ENV=production node server",
"start": "cross-env NODE_ENV=production node server"
},
"dependencies": {
"@tailwindcss/vite": "4.1.4",
"compression": "^1.8.1",
"express": "^5.2.1",
"lucide-react": "0.488.0",
"react": "19.0.0",
"react-dom": "19.0.0",
"react-router-dom": "7.6.2",
"sirv": "^3.0.2",
"tailwindcss": "4.1.4"
},
"devDependencies": {
"@eslint/js": "9.22.0",
"@types/compression": "^1.8.1",
"@types/express": "^5.0.6",
"@types/node": "^26.1.1",
"@types/react": "19.0.10",
"@types/react-dom": "19.0.4",
"@vitejs/plugin-react": "4.3.4",
"cross-env": "^10.1.0",
"eslint": "9.22.0",
"eslint-plugin-react-hooks": "5.2.0",
"eslint-plugin-react-refresh": "0.4.19",
@@ -32,4 +40,4 @@
"typescript-eslint": "8.26.1",
"vite": "6.3.1"
}
}
}
+749 -8
View File
File diff suppressed because it is too large Load Diff
+2
View File
@@ -0,0 +1,2 @@
allowBuilds:
esbuild: false
+59
View File
@@ -0,0 +1,59 @@
import fs from "node:fs/promises";
import express from "express";
const isProduction = process.env.NODE_ENV === "production";
const port = process.env.PORT || 5173;
const base = process.env.BASE || "/";
const templateHtml = isProduction
? await fs.readFile("./dist/client/index.html", "utf-8")
: "";
const app = express();
let vite;
if (!isProduction) {
const { createServer } = await import("vite");
vite = await createServer({
server: { middlewareMode: true },
appType: "custom",
base,
});
app.use(vite.middlewares);
} else {
const compression = (await import("compression")).default;
const sirv = (await import("sirv")).default;
app.use(compression());
app.use(base, sirv("./dist/client", { extensions: [] }));
}
app.use("*all", async (req, res) => {
try {
const url = req.originalUrl.replace(base, "");
let template;
let render;
if (!isProduction) {
template = await fs.readFile("./index.html", "utf-8");
template = await vite.transformIndexHtml(url, template);
render = (await vite.ssrLoadModule("/src/entry-server.tsx")).render;
} else {
template = templateHtml;
render = (await import("./dist/server/entry-server.js")).render;
}
const rendered = await render(url);
const html = template
?.replace("<!--app-head-->", rendered.head ?? "")
.replace("<!--app-html-->", rendered.html ?? "");
res.status(200).set({ "Content-Type": "text/html" }).send(html);
} catch (e) {
vite?.ssrFixStacktrace(e);
console.log(e.stack);
res.status(500).end(e.stack);
}
});
app.listen(port, () => {
console.log(`Server started at http://localhost:${port}`);
});
+11
View File
@@ -0,0 +1,11 @@
import { hydrateRoot } from "react-dom/client";
import { BrowserRouter } from "react-router-dom";
import "./assets/main.css";
import App from "./pages/App.tsx";
hydrateRoot(
document.getElementById("root")!,
<BrowserRouter>
<App />
</BrowserRouter>,
);
+17
View File
@@ -0,0 +1,17 @@
import { renderToString } from "react-dom/server";
import * as RouterExports from "react-router-dom";
import App from "./pages/App";
// Vite's SSR runner resolves react-router-dom to its CommonJS build, so the
// named exports land on `.default`; fall back to the namespace when not.
const { StaticRouter } =
(RouterExports as { default?: typeof RouterExports }).default ?? RouterExports;
export function render(url: string) {
const html = renderToString(
<StaticRouter location={url}>
<App />
</StaticRouter>,
);
return { html };
}
-15
View File
@@ -1,15 +0,0 @@
import { createRoot } from "react-dom/client";
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import "./assets/main.css";
import App from "./pages/App.tsx";
const router = createBrowserRouter([
{
path: "/",
element: <App />,
},
]);
createRoot(document.getElementById("root")!).render(
<RouterProvider router={router} />
);
+1
View File
@@ -14,6 +14,7 @@
"moduleDetection": "force",
"noEmit": true,
"jsx": "react-jsx",
"types": ["node"],
/* Linting */
"strict": true,
+1
View File
@@ -12,6 +12,7 @@
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
"types": ["node"],
/* Linting */
"strict": true,