diff --git a/src/build.tsx b/src/build.tsx
index f67b2c6..a3b875f 100644
--- a/src/build.tsx
+++ b/src/build.tsx
@@ -1 +1,28 @@
-console.log("Hello via Bun!");
\ No newline at end of file
+import { Log } from "./utils";
+import { renderToString } from "react-dom/server";
+import fs from "fs";
+import Base from "./templates/Base";
+import Title from "./templates/Title";
+import Bento from "./templates/Bento";
+
+const environment: "prod" | "dev" =
+ (process.env.ENVIRONMENT as "prod" | "dev") || "prod";
+const log = new Log();
+
+if (environment == "dev") {
+ log.warn("Running in a dev mode!");
+}
+
+if (!fs.existsSync("out")) fs.mkdirSync("out");
+
+const html = renderToString(
+
+
+
+
+);
+fs.cpSync("src/static", "out/static", { recursive: true });
+if (environment == "dev") {
+ fs.cpSync("src/static_dev", "out/static/js", { recursive: true });
+}
+fs.writeFileSync("out/index.html", `${html}`);
diff --git a/src/input.css b/src/input.css
new file mode 100644
index 0000000..a781826
--- /dev/null
+++ b/src/input.css
@@ -0,0 +1,14 @@
+@import "tailwindcss";
+
+.ubuntu-mono-regular {
+ font-family: "Ubuntu Mono", serif;
+ font-weight: 400;
+ font-style: normal;
+}
+
+.sometype-mono-regular {
+ font-family: "Sometype Mono", serif;
+ font-optical-sizing: auto;
+ font-weight: 400;
+ font-style: normal;
+}
\ No newline at end of file
diff --git a/src/static/css/tailwind.css b/src/static/css/tailwind.css
new file mode 100644
index 0000000..29e16d1
--- /dev/null
+++ b/src/static/css/tailwind.css
@@ -0,0 +1,992 @@
+/*! tailwindcss v4.0.6 | MIT License | https://tailwindcss.com */
+@layer theme, base, components, utilities;
+@layer theme {
+ :root, :host {
+ --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji",
+ "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
+ --font-serif: ui-serif, Georgia, Cambria, "Times New Roman", Times, serif;
+ --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono",
+ "Courier New", monospace;
+ --color-red-50: oklch(0.971 0.013 17.38);
+ --color-red-100: oklch(0.936 0.032 17.717);
+ --color-red-200: oklch(0.885 0.062 18.334);
+ --color-red-300: oklch(0.808 0.114 19.571);
+ --color-red-400: oklch(0.704 0.191 22.216);
+ --color-red-500: oklch(0.637 0.237 25.331);
+ --color-red-600: oklch(0.577 0.245 27.325);
+ --color-red-700: oklch(0.505 0.213 27.518);
+ --color-red-800: oklch(0.444 0.177 26.899);
+ --color-red-900: oklch(0.396 0.141 25.723);
+ --color-red-950: oklch(0.258 0.092 26.042);
+ --color-orange-50: oklch(0.98 0.016 73.684);
+ --color-orange-100: oklch(0.954 0.038 75.164);
+ --color-orange-200: oklch(0.901 0.076 70.697);
+ --color-orange-300: oklch(0.837 0.128 66.29);
+ --color-orange-400: oklch(0.75 0.183 55.934);
+ --color-orange-500: oklch(0.705 0.213 47.604);
+ --color-orange-600: oklch(0.646 0.222 41.116);
+ --color-orange-700: oklch(0.553 0.195 38.402);
+ --color-orange-800: oklch(0.47 0.157 37.304);
+ --color-orange-900: oklch(0.408 0.123 38.172);
+ --color-orange-950: oklch(0.266 0.079 36.259);
+ --color-amber-50: oklch(0.987 0.022 95.277);
+ --color-amber-100: oklch(0.962 0.059 95.617);
+ --color-amber-200: oklch(0.924 0.12 95.746);
+ --color-amber-300: oklch(0.879 0.169 91.605);
+ --color-amber-400: oklch(0.828 0.189 84.429);
+ --color-amber-500: oklch(0.769 0.188 70.08);
+ --color-amber-600: oklch(0.666 0.179 58.318);
+ --color-amber-700: oklch(0.555 0.163 48.998);
+ --color-amber-800: oklch(0.473 0.137 46.201);
+ --color-amber-900: oklch(0.414 0.112 45.904);
+ --color-amber-950: oklch(0.279 0.077 45.635);
+ --color-yellow-50: oklch(0.987 0.026 102.212);
+ --color-yellow-100: oklch(0.973 0.071 103.193);
+ --color-yellow-200: oklch(0.945 0.129 101.54);
+ --color-yellow-300: oklch(0.905 0.182 98.111);
+ --color-yellow-400: oklch(0.852 0.199 91.936);
+ --color-yellow-500: oklch(0.795 0.184 86.047);
+ --color-yellow-600: oklch(0.681 0.162 75.834);
+ --color-yellow-700: oklch(0.554 0.135 66.442);
+ --color-yellow-800: oklch(0.476 0.114 61.907);
+ --color-yellow-900: oklch(0.421 0.095 57.708);
+ --color-yellow-950: oklch(0.286 0.066 53.813);
+ --color-lime-50: oklch(0.986 0.031 120.757);
+ --color-lime-100: oklch(0.967 0.067 122.328);
+ --color-lime-200: oklch(0.938 0.127 124.321);
+ --color-lime-300: oklch(0.897 0.196 126.665);
+ --color-lime-400: oklch(0.841 0.238 128.85);
+ --color-lime-500: oklch(0.768 0.233 130.85);
+ --color-lime-600: oklch(0.648 0.2 131.684);
+ --color-lime-700: oklch(0.532 0.157 131.589);
+ --color-lime-800: oklch(0.453 0.124 130.933);
+ --color-lime-900: oklch(0.405 0.101 131.063);
+ --color-lime-950: oklch(0.274 0.072 132.109);
+ --color-green-50: oklch(0.982 0.018 155.826);
+ --color-green-100: oklch(0.962 0.044 156.743);
+ --color-green-200: oklch(0.925 0.084 155.995);
+ --color-green-300: oklch(0.871 0.15 154.449);
+ --color-green-400: oklch(0.792 0.209 151.711);
+ --color-green-500: oklch(0.723 0.219 149.579);
+ --color-green-600: oklch(0.627 0.194 149.214);
+ --color-green-700: oklch(0.527 0.154 150.069);
+ --color-green-800: oklch(0.448 0.119 151.328);
+ --color-green-900: oklch(0.393 0.095 152.535);
+ --color-green-950: oklch(0.266 0.065 152.934);
+ --color-emerald-50: oklch(0.979 0.021 166.113);
+ --color-emerald-100: oklch(0.95 0.052 163.051);
+ --color-emerald-200: oklch(0.905 0.093 164.15);
+ --color-emerald-300: oklch(0.845 0.143 164.978);
+ --color-emerald-400: oklch(0.765 0.177 163.223);
+ --color-emerald-500: oklch(0.696 0.17 162.48);
+ --color-emerald-600: oklch(0.596 0.145 163.225);
+ --color-emerald-700: oklch(0.508 0.118 165.612);
+ --color-emerald-800: oklch(0.432 0.095 166.913);
+ --color-emerald-900: oklch(0.378 0.077 168.94);
+ --color-emerald-950: oklch(0.262 0.051 172.552);
+ --color-teal-50: oklch(0.984 0.014 180.72);
+ --color-teal-100: oklch(0.953 0.051 180.801);
+ --color-teal-200: oklch(0.91 0.096 180.426);
+ --color-teal-300: oklch(0.855 0.138 181.071);
+ --color-teal-400: oklch(0.777 0.152 181.912);
+ --color-teal-500: oklch(0.704 0.14 182.503);
+ --color-teal-600: oklch(0.6 0.118 184.704);
+ --color-teal-700: oklch(0.511 0.096 186.391);
+ --color-teal-800: oklch(0.437 0.078 188.216);
+ --color-teal-900: oklch(0.386 0.063 188.416);
+ --color-teal-950: oklch(0.277 0.046 192.524);
+ --color-cyan-50: oklch(0.984 0.019 200.873);
+ --color-cyan-100: oklch(0.956 0.045 203.388);
+ --color-cyan-200: oklch(0.917 0.08 205.041);
+ --color-cyan-300: oklch(0.865 0.127 207.078);
+ --color-cyan-400: oklch(0.789 0.154 211.53);
+ --color-cyan-500: oklch(0.715 0.143 215.221);
+ --color-cyan-600: oklch(0.609 0.126 221.723);
+ --color-cyan-700: oklch(0.52 0.105 223.128);
+ --color-cyan-800: oklch(0.45 0.085 224.283);
+ --color-cyan-900: oklch(0.398 0.07 227.392);
+ --color-cyan-950: oklch(0.302 0.056 229.695);
+ --color-sky-50: oklch(0.977 0.013 236.62);
+ --color-sky-100: oklch(0.951 0.026 236.824);
+ --color-sky-200: oklch(0.901 0.058 230.902);
+ --color-sky-300: oklch(0.828 0.111 230.318);
+ --color-sky-400: oklch(0.746 0.16 232.661);
+ --color-sky-500: oklch(0.685 0.169 237.323);
+ --color-sky-600: oklch(0.588 0.158 241.966);
+ --color-sky-700: oklch(0.5 0.134 242.749);
+ --color-sky-800: oklch(0.443 0.11 240.79);
+ --color-sky-900: oklch(0.391 0.09 240.876);
+ --color-sky-950: oklch(0.293 0.066 243.157);
+ --color-blue-50: oklch(0.97 0.014 254.604);
+ --color-blue-100: oklch(0.932 0.032 255.585);
+ --color-blue-200: oklch(0.882 0.059 254.128);
+ --color-blue-300: oklch(0.809 0.105 251.813);
+ --color-blue-400: oklch(0.707 0.165 254.624);
+ --color-blue-500: oklch(0.623 0.214 259.815);
+ --color-blue-600: oklch(0.546 0.245 262.881);
+ --color-blue-700: oklch(0.488 0.243 264.376);
+ --color-blue-800: oklch(0.424 0.199 265.638);
+ --color-blue-900: oklch(0.379 0.146 265.522);
+ --color-blue-950: oklch(0.282 0.091 267.935);
+ --color-indigo-50: oklch(0.962 0.018 272.314);
+ --color-indigo-100: oklch(0.93 0.034 272.788);
+ --color-indigo-200: oklch(0.87 0.065 274.039);
+ --color-indigo-300: oklch(0.785 0.115 274.713);
+ --color-indigo-400: oklch(0.673 0.182 276.935);
+ --color-indigo-500: oklch(0.585 0.233 277.117);
+ --color-indigo-600: oklch(0.511 0.262 276.966);
+ --color-indigo-700: oklch(0.457 0.24 277.023);
+ --color-indigo-800: oklch(0.398 0.195 277.366);
+ --color-indigo-900: oklch(0.359 0.144 278.697);
+ --color-indigo-950: oklch(0.257 0.09 281.288);
+ --color-violet-50: oklch(0.969 0.016 293.756);
+ --color-violet-100: oklch(0.943 0.029 294.588);
+ --color-violet-200: oklch(0.894 0.057 293.283);
+ --color-violet-300: oklch(0.811 0.111 293.571);
+ --color-violet-400: oklch(0.702 0.183 293.541);
+ --color-violet-500: oklch(0.606 0.25 292.717);
+ --color-violet-600: oklch(0.541 0.281 293.009);
+ --color-violet-700: oklch(0.491 0.27 292.581);
+ --color-violet-800: oklch(0.432 0.232 292.759);
+ --color-violet-900: oklch(0.38 0.189 293.745);
+ --color-violet-950: oklch(0.283 0.141 291.089);
+ --color-purple-50: oklch(0.977 0.014 308.299);
+ --color-purple-100: oklch(0.946 0.033 307.174);
+ --color-purple-200: oklch(0.902 0.063 306.703);
+ --color-purple-300: oklch(0.827 0.119 306.383);
+ --color-purple-400: oklch(0.714 0.203 305.504);
+ --color-purple-500: oklch(0.627 0.265 303.9);
+ --color-purple-600: oklch(0.558 0.288 302.321);
+ --color-purple-700: oklch(0.496 0.265 301.924);
+ --color-purple-800: oklch(0.438 0.218 303.724);
+ --color-purple-900: oklch(0.381 0.176 304.987);
+ --color-purple-950: oklch(0.291 0.149 302.717);
+ --color-fuchsia-50: oklch(0.977 0.017 320.058);
+ --color-fuchsia-100: oklch(0.952 0.037 318.852);
+ --color-fuchsia-200: oklch(0.903 0.076 319.62);
+ --color-fuchsia-300: oklch(0.833 0.145 321.434);
+ --color-fuchsia-400: oklch(0.74 0.238 322.16);
+ --color-fuchsia-500: oklch(0.667 0.295 322.15);
+ --color-fuchsia-600: oklch(0.591 0.293 322.896);
+ --color-fuchsia-700: oklch(0.518 0.253 323.949);
+ --color-fuchsia-800: oklch(0.452 0.211 324.591);
+ --color-fuchsia-900: oklch(0.401 0.17 325.612);
+ --color-fuchsia-950: oklch(0.293 0.136 325.661);
+ --color-pink-50: oklch(0.971 0.014 343.198);
+ --color-pink-100: oklch(0.948 0.028 342.258);
+ --color-pink-200: oklch(0.899 0.061 343.231);
+ --color-pink-300: oklch(0.823 0.12 346.018);
+ --color-pink-400: oklch(0.718 0.202 349.761);
+ --color-pink-500: oklch(0.656 0.241 354.308);
+ --color-pink-600: oklch(0.592 0.249 0.584);
+ --color-pink-700: oklch(0.525 0.223 3.958);
+ --color-pink-800: oklch(0.459 0.187 3.815);
+ --color-pink-900: oklch(0.408 0.153 2.432);
+ --color-pink-950: oklch(0.284 0.109 3.907);
+ --color-rose-50: oklch(0.969 0.015 12.422);
+ --color-rose-100: oklch(0.941 0.03 12.58);
+ --color-rose-200: oklch(0.892 0.058 10.001);
+ --color-rose-300: oklch(0.81 0.117 11.638);
+ --color-rose-400: oklch(0.712 0.194 13.428);
+ --color-rose-500: oklch(0.645 0.246 16.439);
+ --color-rose-600: oklch(0.586 0.253 17.585);
+ --color-rose-700: oklch(0.514 0.222 16.935);
+ --color-rose-800: oklch(0.455 0.188 13.697);
+ --color-rose-900: oklch(0.41 0.159 10.272);
+ --color-rose-950: oklch(0.271 0.105 12.094);
+ --color-slate-50: oklch(0.984 0.003 247.858);
+ --color-slate-100: oklch(0.968 0.007 247.896);
+ --color-slate-200: oklch(0.929 0.013 255.508);
+ --color-slate-300: oklch(0.869 0.022 252.894);
+ --color-slate-400: oklch(0.704 0.04 256.788);
+ --color-slate-500: oklch(0.554 0.046 257.417);
+ --color-slate-600: oklch(0.446 0.043 257.281);
+ --color-slate-700: oklch(0.372 0.044 257.287);
+ --color-slate-800: oklch(0.279 0.041 260.031);
+ --color-slate-900: oklch(0.208 0.042 265.755);
+ --color-slate-950: oklch(0.129 0.042 264.695);
+ --color-gray-50: oklch(0.985 0.002 247.839);
+ --color-gray-100: oklch(0.967 0.003 264.542);
+ --color-gray-200: oklch(0.928 0.006 264.531);
+ --color-gray-300: oklch(0.872 0.01 258.338);
+ --color-gray-400: oklch(0.707 0.022 261.325);
+ --color-gray-500: oklch(0.551 0.027 264.364);
+ --color-gray-600: oklch(0.446 0.03 256.802);
+ --color-gray-700: oklch(0.373 0.034 259.733);
+ --color-gray-800: oklch(0.278 0.033 256.848);
+ --color-gray-900: oklch(0.21 0.034 264.665);
+ --color-gray-950: oklch(0.13 0.028 261.692);
+ --color-zinc-50: oklch(0.985 0 0);
+ --color-zinc-100: oklch(0.967 0.001 286.375);
+ --color-zinc-200: oklch(0.92 0.004 286.32);
+ --color-zinc-300: oklch(0.871 0.006 286.286);
+ --color-zinc-400: oklch(0.705 0.015 286.067);
+ --color-zinc-500: oklch(0.552 0.016 285.938);
+ --color-zinc-600: oklch(0.442 0.017 285.786);
+ --color-zinc-700: oklch(0.37 0.013 285.805);
+ --color-zinc-800: oklch(0.274 0.006 286.033);
+ --color-zinc-900: oklch(0.21 0.006 285.885);
+ --color-zinc-950: oklch(0.141 0.005 285.823);
+ --color-neutral-50: oklch(0.985 0 0);
+ --color-neutral-100: oklch(0.97 0 0);
+ --color-neutral-200: oklch(0.922 0 0);
+ --color-neutral-300: oklch(0.87 0 0);
+ --color-neutral-400: oklch(0.708 0 0);
+ --color-neutral-500: oklch(0.556 0 0);
+ --color-neutral-600: oklch(0.439 0 0);
+ --color-neutral-700: oklch(0.371 0 0);
+ --color-neutral-800: oklch(0.269 0 0);
+ --color-neutral-900: oklch(0.205 0 0);
+ --color-neutral-950: oklch(0.145 0 0);
+ --color-stone-50: oklch(0.985 0.001 106.423);
+ --color-stone-100: oklch(0.97 0.001 106.424);
+ --color-stone-200: oklch(0.923 0.003 48.717);
+ --color-stone-300: oklch(0.869 0.005 56.366);
+ --color-stone-400: oklch(0.709 0.01 56.259);
+ --color-stone-500: oklch(0.553 0.013 58.071);
+ --color-stone-600: oklch(0.444 0.011 73.639);
+ --color-stone-700: oklch(0.374 0.01 67.558);
+ --color-stone-800: oklch(0.268 0.007 34.298);
+ --color-stone-900: oklch(0.216 0.006 56.043);
+ --color-stone-950: oklch(0.147 0.004 49.25);
+ --color-black: #000;
+ --color-white: #fff;
+ --spacing: 0.25rem;
+ --breakpoint-sm: 40rem;
+ --breakpoint-md: 48rem;
+ --breakpoint-lg: 64rem;
+ --breakpoint-xl: 80rem;
+ --breakpoint-2xl: 96rem;
+ --container-3xs: 16rem;
+ --container-2xs: 18rem;
+ --container-xs: 20rem;
+ --container-sm: 24rem;
+ --container-md: 28rem;
+ --container-lg: 32rem;
+ --container-xl: 36rem;
+ --container-2xl: 42rem;
+ --container-3xl: 48rem;
+ --container-4xl: 56rem;
+ --container-5xl: 64rem;
+ --container-6xl: 72rem;
+ --container-7xl: 80rem;
+ --text-xs: 0.75rem;
+ --text-xs--line-height: calc(1 / 0.75);
+ --text-sm: 0.875rem;
+ --text-sm--line-height: calc(1.25 / 0.875);
+ --text-base: 1rem;
+ --text-base--line-height: calc(1.5 / 1);
+ --text-lg: 1.125rem;
+ --text-lg--line-height: calc(1.75 / 1.125);
+ --text-xl: 1.25rem;
+ --text-xl--line-height: calc(1.75 / 1.25);
+ --text-2xl: 1.5rem;
+ --text-2xl--line-height: calc(2 / 1.5);
+ --text-3xl: 1.875rem;
+ --text-3xl--line-height: calc(2.25 / 1.875);
+ --text-4xl: 2.25rem;
+ --text-4xl--line-height: calc(2.5 / 2.25);
+ --text-5xl: 3rem;
+ --text-5xl--line-height: 1;
+ --text-6xl: 3.75rem;
+ --text-6xl--line-height: 1;
+ --text-7xl: 4.5rem;
+ --text-7xl--line-height: 1;
+ --text-8xl: 6rem;
+ --text-8xl--line-height: 1;
+ --text-9xl: 8rem;
+ --text-9xl--line-height: 1;
+ --font-weight-thin: 100;
+ --font-weight-extralight: 200;
+ --font-weight-light: 300;
+ --font-weight-normal: 400;
+ --font-weight-medium: 500;
+ --font-weight-semibold: 600;
+ --font-weight-bold: 700;
+ --font-weight-extrabold: 800;
+ --font-weight-black: 900;
+ --tracking-tighter: -0.05em;
+ --tracking-tight: -0.025em;
+ --tracking-normal: 0em;
+ --tracking-wide: 0.025em;
+ --tracking-wider: 0.05em;
+ --tracking-widest: 0.1em;
+ --leading-tight: 1.25;
+ --leading-snug: 1.375;
+ --leading-normal: 1.5;
+ --leading-relaxed: 1.625;
+ --leading-loose: 2;
+ --radius-xs: 0.125rem;
+ --radius-sm: 0.25rem;
+ --radius-md: 0.375rem;
+ --radius-lg: 0.5rem;
+ --radius-xl: 0.75rem;
+ --radius-2xl: 1rem;
+ --radius-3xl: 1.5rem;
+ --radius-4xl: 2rem;
+ --shadow-2xs: 0 1px rgb(0 0 0 / 0.05);
+ --shadow-xs: 0 1px 2px 0 rgb(0 0 0 / 0.05);
+ --shadow-sm: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1);
+ --shadow-md: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1);
+ --shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
+ --shadow-xl: 0 20px 25px -5px rgb(0 0 0 / 0.1), 0 8px 10px -6px rgb(0 0 0 / 0.1);
+ --shadow-2xl: 0 25px 50px -12px rgb(0 0 0 / 0.25);
+ --inset-shadow-2xs: inset 0 1px rgb(0 0 0 / 0.05);
+ --inset-shadow-xs: inset 0 1px 1px rgb(0 0 0 / 0.05);
+ --inset-shadow-sm: inset 0 2px 4px rgb(0 0 0 / 0.05);
+ --drop-shadow-xs: 0 1px 1px rgb(0 0 0 / 0.05);
+ --drop-shadow-sm: 0 1px 2px rgb(0 0 0 / 0.15);
+ --drop-shadow-md: 0 3px 3px rgb(0 0 0 / 0.12);
+ --drop-shadow-lg: 0 4px 4px rgb(0 0 0 / 0.15);
+ --drop-shadow-xl: 0 9px 7px rgb(0 0 0 / 0.1);
+ --drop-shadow-2xl: 0 25px 25px rgb(0 0 0 / 0.15);
+ --ease-in: cubic-bezier(0.4, 0, 1, 1);
+ --ease-out: cubic-bezier(0, 0, 0.2, 1);
+ --ease-in-out: cubic-bezier(0.4, 0, 0.2, 1);
+ --animate-spin: spin 1s linear infinite;
+ --animate-ping: ping 1s cubic-bezier(0, 0, 0.2, 1) infinite;
+ --animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
+ --animate-bounce: bounce 1s infinite;
+ --blur-xs: 4px;
+ --blur-sm: 8px;
+ --blur-md: 12px;
+ --blur-lg: 16px;
+ --blur-xl: 24px;
+ --blur-2xl: 40px;
+ --blur-3xl: 64px;
+ --perspective-dramatic: 100px;
+ --perspective-near: 300px;
+ --perspective-normal: 500px;
+ --perspective-midrange: 800px;
+ --perspective-distant: 1200px;
+ --aspect-video: 16 / 9;
+ --default-transition-duration: 150ms;
+ --default-transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
+ --default-font-family: var(--font-sans);
+ --default-font-feature-settings: var(--font-sans--font-feature-settings);
+ --default-font-variation-settings: var(
+ --font-sans--font-variation-settings
+ );
+ --default-mono-font-family: var(--font-mono);
+ --default-mono-font-feature-settings: var(
+ --font-mono--font-feature-settings
+ );
+ --default-mono-font-variation-settings: var(
+ --font-mono--font-variation-settings
+ );
+ }
+}
+@layer base {
+ *, ::after, ::before, ::backdrop, ::file-selector-button {
+ box-sizing: border-box;
+ margin: 0;
+ padding: 0;
+ border: 0 solid;
+ }
+ html, :host {
+ line-height: 1.5;
+ -webkit-text-size-adjust: 100%;
+ tab-size: 4;
+ font-family: var( --default-font-family, ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji" );
+ font-feature-settings: var(--default-font-feature-settings, normal);
+ font-variation-settings: var( --default-font-variation-settings, normal );
+ -webkit-tap-highlight-color: transparent;
+ }
+ body {
+ line-height: inherit;
+ }
+ hr {
+ height: 0;
+ color: inherit;
+ border-top-width: 1px;
+ }
+ abbr:where([title]) {
+ -webkit-text-decoration: underline dotted;
+ text-decoration: underline dotted;
+ }
+ h1, h2, h3, h4, h5, h6 {
+ font-size: inherit;
+ font-weight: inherit;
+ }
+ a {
+ color: inherit;
+ -webkit-text-decoration: inherit;
+ text-decoration: inherit;
+ }
+ b, strong {
+ font-weight: bolder;
+ }
+ code, kbd, samp, pre {
+ font-family: var( --default-mono-font-family, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace );
+ font-feature-settings: var( --default-mono-font-feature-settings, normal );
+ font-variation-settings: var( --default-mono-font-variation-settings, normal );
+ font-size: 1em;
+ }
+ small {
+ font-size: 80%;
+ }
+ sub, sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+ }
+ sub {
+ bottom: -0.25em;
+ }
+ sup {
+ top: -0.5em;
+ }
+ table {
+ text-indent: 0;
+ border-color: inherit;
+ border-collapse: collapse;
+ }
+ :-moz-focusring {
+ outline: auto;
+ }
+ progress {
+ vertical-align: baseline;
+ }
+ summary {
+ display: list-item;
+ }
+ ol, ul, menu {
+ list-style: none;
+ }
+ img, svg, video, canvas, audio, iframe, embed, object {
+ display: block;
+ vertical-align: middle;
+ }
+ img, video {
+ max-width: 100%;
+ height: auto;
+ }
+ button, input, select, optgroup, textarea, ::file-selector-button {
+ font: inherit;
+ font-feature-settings: inherit;
+ font-variation-settings: inherit;
+ letter-spacing: inherit;
+ color: inherit;
+ border-radius: 0;
+ background-color: transparent;
+ opacity: 1;
+ }
+ :where(select:is([multiple], [size])) optgroup {
+ font-weight: bolder;
+ }
+ :where(select:is([multiple], [size])) optgroup option {
+ padding-inline-start: 20px;
+ }
+ ::file-selector-button {
+ margin-inline-end: 4px;
+ }
+ ::placeholder {
+ opacity: 1;
+ color: color-mix(in oklab, currentColor 50%, transparent);
+ }
+ textarea {
+ resize: vertical;
+ }
+ ::-webkit-search-decoration {
+ -webkit-appearance: none;
+ }
+ ::-webkit-date-and-time-value {
+ min-height: 1lh;
+ text-align: inherit;
+ }
+ ::-webkit-datetime-edit {
+ display: inline-flex;
+ }
+ ::-webkit-datetime-edit-fields-wrapper {
+ padding: 0;
+ }
+ ::-webkit-datetime-edit, ::-webkit-datetime-edit-year-field, ::-webkit-datetime-edit-month-field, ::-webkit-datetime-edit-day-field, ::-webkit-datetime-edit-hour-field, ::-webkit-datetime-edit-minute-field, ::-webkit-datetime-edit-second-field, ::-webkit-datetime-edit-millisecond-field, ::-webkit-datetime-edit-meridiem-field {
+ padding-block: 0;
+ }
+ :-moz-ui-invalid {
+ box-shadow: none;
+ }
+ button, input:where([type="button"], [type="reset"], [type="submit"]), ::file-selector-button {
+ appearance: button;
+ }
+ ::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
+ height: auto;
+ }
+ [hidden]:where(:not([hidden="until-found"])) {
+ display: none !important;
+ }
+}
+@layer utilities {
+ .absolute {
+ position: absolute;
+ }
+ .relative {
+ position: relative;
+ }
+ .static {
+ position: static;
+ }
+ .inset-0 {
+ inset: calc(var(--spacing) * 0);
+ }
+ .-z-10 {
+ z-index: calc(10 * -1);
+ }
+ .col-\[1\] {
+ grid-column: 1;
+ }
+ .col-span-2 {
+ grid-column: span 2 / span 2;
+ }
+ .col-span-full {
+ grid-column: 1 / -1;
+ }
+ .col-start-2 {
+ grid-column-start: 2;
+ }
+ .row-\[1\] {
+ grid-row: 1;
+ }
+ .row-\[4\] {
+ grid-row: 4;
+ }
+ .row-span-2 {
+ grid-row: span 2 / span 2;
+ }
+ .row-span-3 {
+ grid-row: span 3 / span 3;
+ }
+ .row-start-1 {
+ grid-row-start: 1;
+ }
+ .row-start-2 {
+ grid-row-start: 2;
+ }
+ .container {
+ width: 100%;
+ @media (width >= 40rem) {
+ max-width: 40rem;
+ }
+ @media (width >= 48rem) {
+ max-width: 48rem;
+ }
+ @media (width >= 64rem) {
+ max-width: 64rem;
+ }
+ @media (width >= 80rem) {
+ max-width: 80rem;
+ }
+ @media (width >= 96rem) {
+ max-width: 96rem;
+ }
+ }
+ .mx-auto {
+ margin-inline: auto;
+ }
+ .ml-auto {
+ margin-left: auto;
+ }
+ .block {
+ display: block;
+ }
+ .flex {
+ display: flex;
+ }
+ .grid {
+ display: grid;
+ }
+ .aspect-square {
+ aspect-ratio: 1 / 1;
+ }
+ .aspect-video {
+ aspect-ratio: var(--aspect-video);
+ }
+ .h-8 {
+ height: calc(var(--spacing) * 8);
+ }
+ .h-12 {
+ height: calc(var(--spacing) * 12);
+ }
+ .h-\[114px\] {
+ height: 114px;
+ }
+ .h-full {
+ height: 100%;
+ }
+ .max-h-\[512px\] {
+ max-height: 512px;
+ }
+ .min-h-\[438px\] {
+ min-height: 438px;
+ }
+ .w-\[114px\] {
+ width: 114px;
+ }
+ .w-full {
+ width: 100%;
+ }
+ .max-w-\[60\%\] {
+ max-width: 60%;
+ }
+ .max-w-\[75\%\] {
+ max-width: 75%;
+ }
+ .max-w-\[590px\] {
+ max-width: 590px;
+ }
+ .max-w-\[1210px\] {
+ max-width: 1210px;
+ }
+ .flex-shrink-0 {
+ flex-shrink: 0;
+ }
+ .scale-140 {
+ --tw-scale-x: 140%;
+ --tw-scale-y: 140%;
+ --tw-scale-z: 140%;
+ scale: var(--tw-scale-x) var(--tw-scale-y);
+ }
+ .scale-150 {
+ --tw-scale-x: 150%;
+ --tw-scale-y: 150%;
+ --tw-scale-z: 150%;
+ scale: var(--tw-scale-x) var(--tw-scale-y);
+ }
+ .grid-cols-1 {
+ grid-template-columns: repeat(1, minmax(0, 1fr));
+ }
+ .grid-cols-\[repeat\(4\,minmax\(0\,280px\)\)\] {
+ grid-template-columns: repeat(4,minmax(0,280px));
+ }
+ .grid-rows-1 {
+ grid-template-rows: repeat(1, minmax(0, 1fr));
+ }
+ .grid-rows-\[repeat\(4\,minmax\(0\,136px\)\)\] {
+ grid-template-rows: repeat(4,minmax(0,136px));
+ }
+ .flex-col {
+ flex-direction: column;
+ }
+ .flex-col-reverse {
+ flex-direction: column-reverse;
+ }
+ .items-center {
+ align-items: center;
+ }
+ .items-end {
+ align-items: flex-end;
+ }
+ .justify-center {
+ justify-content: center;
+ }
+ .justify-end {
+ justify-content: flex-end;
+ }
+ .gap-1 {
+ gap: calc(var(--spacing) * 1);
+ }
+ .gap-2 {
+ gap: calc(var(--spacing) * 2);
+ }
+ .gap-4 {
+ gap: calc(var(--spacing) * 4);
+ }
+ .gap-8 {
+ gap: calc(var(--spacing) * 8);
+ }
+ .overflow-hidden {
+ overflow: hidden;
+ }
+ .overflow-x-hidden {
+ overflow-x: hidden;
+ }
+ .rounded-xl {
+ border-radius: var(--radius-xl);
+ }
+ .border {
+ border-style: var(--tw-border-style);
+ border-width: 1px;
+ }
+ .border-transparent {
+ border-color: transparent;
+ }
+ .bg-\[\#1A0F05\] {
+ background-color: #1A0F05;
+ }
+ .bg-\[\#3B0D25\] {
+ background-color: #3B0D25;
+ }
+ .bg-\[var\(--color\)\] {
+ background-color: var(--color);
+ }
+ .bg-gradient-to-r {
+ --tw-gradient-position: to right in oklab;
+ background-image: linear-gradient(var(--tw-gradient-stops));
+ }
+ .from-\[var\(--color\)\/0\] {
+ --tw-gradient-from: var(--color)/0;
+ --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
+ }
+ .to-\[var\(--color\)\] {
+ --tw-gradient-to: var(--color);
+ --tw-gradient-stops: var(--tw-gradient-via-stops, var(--tw-gradient-position), var(--tw-gradient-from) var(--tw-gradient-from-position), var(--tw-gradient-to) var(--tw-gradient-to-position));
+ }
+ .to-\[50\%\] {
+ --tw-gradient-to-position: 50%;
+ }
+ .to-\[75\%\] {
+ --tw-gradient-to-position: 75%;
+ }
+ .object-cover {
+ object-fit: cover;
+ }
+ .object-center {
+ object-position: center;
+ }
+ .p-2 {
+ padding: calc(var(--spacing) * 2);
+ }
+ .p-8 {
+ padding: calc(var(--spacing) * 8);
+ }
+ .px-8 {
+ padding-inline: calc(var(--spacing) * 8);
+ }
+ .py-8 {
+ padding-block: calc(var(--spacing) * 8);
+ }
+ .py-14 {
+ padding-block: calc(var(--spacing) * 14);
+ }
+ .text-right {
+ text-align: right;
+ }
+ .text-lg {
+ font-size: var(--text-lg);
+ line-height: var(--tw-leading, var(--text-lg--line-height));
+ }
+ .text-\[24px\] {
+ font-size: 24px;
+ }
+ .text-\[32px\] {
+ font-size: 32px;
+ }
+ .text-\[64px\] {
+ font-size: 64px;
+ }
+ .leading-none {
+ --tw-leading: 1;
+ line-height: 1;
+ }
+ .tracking-tighter {
+ --tw-tracking: var(--tracking-tighter);
+ letter-spacing: var(--tracking-tighter);
+ }
+ .text-\[\#FF851A\] {
+ color: #FF851A;
+ }
+ .text-black {
+ color: var(--color-black);
+ }
+ .text-white {
+ color: var(--color-white);
+ }
+ .transition-colors {
+ transition-property: color, background-color, border-color, outline-color, text-decoration-color, fill, stroke, --tw-gradient-from, --tw-gradient-via, --tw-gradient-to;
+ transition-timing-function: var(--tw-ease, var(--default-transition-timing-function));
+ transition-duration: var(--tw-duration, var(--default-transition-duration));
+ }
+ .hover\:border-\[\#FF851A\] {
+ &:hover {
+ @media (hover: hover) {
+ border-color: #FF851A;
+ }
+ }
+ }
+ .sm\:flex-shrink-1 {
+ @media (width >= 40rem) {
+ flex-shrink: 1;
+ }
+ }
+ .md\:scale-95 {
+ @media (width >= 48rem) {
+ --tw-scale-x: 95%;
+ --tw-scale-y: 95%;
+ --tw-scale-z: 95%;
+ scale: var(--tw-scale-x) var(--tw-scale-y);
+ }
+ }
+ .md\:scale-100 {
+ @media (width >= 48rem) {
+ --tw-scale-x: 100%;
+ --tw-scale-y: 100%;
+ --tw-scale-z: 100%;
+ scale: var(--tw-scale-x) var(--tw-scale-y);
+ }
+ }
+ .md\:py-0 {
+ @media (width >= 48rem) {
+ padding-block: calc(var(--spacing) * 0);
+ }
+ }
+ .md\:text-\[32px\] {
+ @media (width >= 48rem) {
+ font-size: 32px;
+ }
+ }
+ .md\:text-\[48px\] {
+ @media (width >= 48rem) {
+ font-size: 48px;
+ }
+ }
+ .md\:text-\[128px\] {
+ @media (width >= 48rem) {
+ font-size: 128px;
+ }
+ }
+ .md\:tracking-normal {
+ @media (width >= 48rem) {
+ --tw-tracking: var(--tracking-normal);
+ letter-spacing: var(--tracking-normal);
+ }
+ }
+ .lg\:scale-90 {
+ @media (width >= 64rem) {
+ --tw-scale-x: 90%;
+ --tw-scale-y: 90%;
+ --tw-scale-z: 90%;
+ scale: var(--tw-scale-x) var(--tw-scale-y);
+ }
+ }
+ .xl\:mt-2 {
+ @media (width >= 80rem) {
+ margin-top: calc(var(--spacing) * 2);
+ }
+ }
+ .xl\:max-h-none {
+ @media (width >= 80rem) {
+ max-height: none;
+ }
+ }
+ .xl\:scale-95 {
+ @media (width >= 80rem) {
+ --tw-scale-x: 95%;
+ --tw-scale-y: 95%;
+ --tw-scale-z: 95%;
+ scale: var(--tw-scale-x) var(--tw-scale-y);
+ }
+ }
+ .xl\:flex-row {
+ @media (width >= 80rem) {
+ flex-direction: row;
+ }
+ }
+}
+.ubuntu-mono-regular {
+ font-family: "Ubuntu Mono", serif;
+ font-weight: 400;
+ font-style: normal;
+}
+.sometype-mono-regular {
+ font-family: "Sometype Mono", serif;
+ font-optical-sizing: auto;
+ font-weight: 400;
+ font-style: normal;
+}
+@keyframes spin {
+ to {
+ transform: rotate(360deg);
+ }
+}
+@keyframes ping {
+ 75%, 100% {
+ transform: scale(2);
+ opacity: 0;
+ }
+}
+@keyframes pulse {
+ 50% {
+ opacity: 0.5;
+ }
+}
+@keyframes bounce {
+ 0%, 100% {
+ transform: translateY(-25%);
+ animation-timing-function: cubic-bezier(0.8, 0, 1, 1);
+ }
+ 50% {
+ transform: none;
+ animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
+ }
+}
+@property --tw-scale-x {
+ syntax: "*";
+ inherits: false;
+ initial-value: 1;
+}
+@property --tw-scale-y {
+ syntax: "*";
+ inherits: false;
+ initial-value: 1;
+}
+@property --tw-scale-z {
+ syntax: "*";
+ inherits: false;
+ initial-value: 1;
+}
+@property --tw-border-style {
+ syntax: "*";
+ inherits: false;
+ initial-value: solid;
+}
+@property --tw-gradient-position {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-gradient-from {
+ syntax: "";
+ inherits: false;
+ initial-value: #0000;
+}
+@property --tw-gradient-via {
+ syntax: "";
+ inherits: false;
+ initial-value: #0000;
+}
+@property --tw-gradient-to {
+ syntax: "";
+ inherits: false;
+ initial-value: #0000;
+}
+@property --tw-gradient-stops {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-gradient-via-stops {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-gradient-from-position {
+ syntax: "";
+ inherits: false;
+ initial-value: 0%;
+}
+@property --tw-gradient-via-position {
+ syntax: "";
+ inherits: false;
+ initial-value: 50%;
+}
+@property --tw-gradient-to-position {
+ syntax: "";
+ inherits: false;
+ initial-value: 100%;
+}
+@property --tw-leading {
+ syntax: "*";
+ inherits: false;
+}
+@property --tw-tracking {
+ syntax: "*";
+ inherits: false;
+}
diff --git a/src/static/images/card-blur.png b/src/static/images/card-blur.png
new file mode 100644
index 0000000..bfac785
Binary files /dev/null and b/src/static/images/card-blur.png differ
diff --git a/src/static/images/card.png b/src/static/images/card.png
new file mode 100644
index 0000000..0d557ea
Binary files /dev/null and b/src/static/images/card.png differ
diff --git a/src/static/images/cards/immich.png b/src/static/images/cards/immich.png
new file mode 100644
index 0000000..7d5cddf
Binary files /dev/null and b/src/static/images/cards/immich.png differ
diff --git a/src/static/images/cards/linkwarden.png b/src/static/images/cards/linkwarden.png
new file mode 100644
index 0000000..2cb3075
Binary files /dev/null and b/src/static/images/cards/linkwarden.png differ
diff --git a/src/static/images/cards/matrix.png b/src/static/images/cards/matrix.png
new file mode 100644
index 0000000..95aeadb
Binary files /dev/null and b/src/static/images/cards/matrix.png differ
diff --git a/src/static/images/cards/nextcloud.png b/src/static/images/cards/nextcloud.png
new file mode 100644
index 0000000..88a748c
Binary files /dev/null and b/src/static/images/cards/nextcloud.png differ
diff --git a/src/static/images/cards/vaultwarden.png b/src/static/images/cards/vaultwarden.png
new file mode 100644
index 0000000..cd86967
Binary files /dev/null and b/src/static/images/cards/vaultwarden.png differ
diff --git a/src/static/images/cards/xbb.png b/src/static/images/cards/xbb.png
new file mode 100644
index 0000000..601cb3f
Binary files /dev/null and b/src/static/images/cards/xbb.png differ
diff --git a/src/static/images/logos/immich.png b/src/static/images/logos/immich.png
new file mode 100644
index 0000000..2a33a68
Binary files /dev/null and b/src/static/images/logos/immich.png differ
diff --git a/src/static/images/logos/linkwarden.png b/src/static/images/logos/linkwarden.png
new file mode 100644
index 0000000..2790819
Binary files /dev/null and b/src/static/images/logos/linkwarden.png differ
diff --git a/src/static/images/logos/matrix.png b/src/static/images/logos/matrix.png
new file mode 100644
index 0000000..0fdb771
Binary files /dev/null and b/src/static/images/logos/matrix.png differ
diff --git a/src/static/images/logos/nextcloud.png b/src/static/images/logos/nextcloud.png
new file mode 100644
index 0000000..f3f043c
Binary files /dev/null and b/src/static/images/logos/nextcloud.png differ
diff --git a/src/static/images/logos/vaultwarden.png b/src/static/images/logos/vaultwarden.png
new file mode 100644
index 0000000..d44962b
Binary files /dev/null and b/src/static/images/logos/vaultwarden.png differ
diff --git a/src/static/images/logos/xbb.png b/src/static/images/logos/xbb.png
new file mode 100644
index 0000000..ac1ab21
Binary files /dev/null and b/src/static/images/logos/xbb.png differ
diff --git a/src/templates/Base.tsx b/src/templates/Base.tsx
new file mode 100644
index 0000000..9cc55f0
--- /dev/null
+++ b/src/templates/Base.tsx
@@ -0,0 +1,38 @@
+import React from "react";
+
+interface BaseProps {
+ children: React.ReactNode;
+ isDev?: boolean;
+}
+
+export default function Base({ children, isDev }: BaseProps) {
+ return (
+ <>
+
+
+
+
+ WAH.su
+ {isDev ? : ""}
+
+
+
+
+
+
+ {children}
+
+
+ >
+ );
+}
diff --git a/src/templates/Bento.tsx b/src/templates/Bento.tsx
new file mode 100644
index 0000000..af3436d
--- /dev/null
+++ b/src/templates/Bento.tsx
@@ -0,0 +1,67 @@
+import BentoCard from "./BentoCards/BentoCard";
+import Footer from "./Footer";
+
+export default function Bento() {
+ return (
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/templates/BentoCards/BentoCard.tsx b/src/templates/BentoCards/BentoCard.tsx
new file mode 100644
index 0000000..5192854
--- /dev/null
+++ b/src/templates/BentoCards/BentoCard.tsx
@@ -0,0 +1,31 @@
+import BentoCardSmall from "./Small";
+import BentoCardNormal from "./Normal";
+import BentoCardBig from "./Big";
+import BentoCardLarge from "./Large";
+
+export interface BentoCardProps {
+ type?: "small" | "normal" | "big" | "large";
+ color: string;
+ image?: string;
+ logo: string;
+ title: string;
+ description?: string;
+ className?: string;
+ link?: string;
+}
+
+export default function BentoCard(props: BentoCardProps) {
+ if (!props.type || props.type == "normal") {
+ return ;
+ }
+ if (props.type == "small") {
+ return ;
+ }
+ if (props.type == "big") {
+ return ;
+ }
+ if (props.type == "large") {
+ return ;
+ }
+ return NOTHING
;
+}
diff --git a/src/templates/BentoCards/Big.tsx b/src/templates/BentoCards/Big.tsx
new file mode 100644
index 0000000..9890f62
--- /dev/null
+++ b/src/templates/BentoCards/Big.tsx
@@ -0,0 +1,77 @@
+import type { BentoCardProps } from "./BentoCard";
+
+export default function BentoCardBig({
+ color,
+ image,
+ logo,
+ title,
+ description,
+ className,
+ link,
+}: BentoCardProps) {
+ if (link) {
+ return (
+
+ {image ? (
+ <>
+
+
+ >
+ ) : (
+ ""
+ )}
+
+
+
+
{title}
+
+
+
+ {description}
+
+
+ );
+ }
+ return (
+
+ {image ? (
+ <>
+
+
+ >
+ ) : (
+ ""
+ )}
+
+
+
+
{title}
+
+
+
+ {description}
+
+
+ );
+}
diff --git a/src/templates/BentoCards/Large.tsx b/src/templates/BentoCards/Large.tsx
new file mode 100644
index 0000000..6f09dca
--- /dev/null
+++ b/src/templates/BentoCards/Large.tsx
@@ -0,0 +1,77 @@
+import type { BentoCardProps } from "./BentoCard";
+
+export default function BentoCardLarge({
+ color,
+ image,
+ logo,
+ title,
+ description,
+ className,
+ link,
+}: BentoCardProps) {
+ if (link) {
+ return (
+
+ {image ? (
+ <>
+
+
+ >
+ ) : (
+ ""
+ )}
+
+
+
+
{title}
+
+
+
+ {description}
+
+
+ );
+ }
+ return (
+
+ {image ? (
+ <>
+
+
+ >
+ ) : (
+ ""
+ )}
+
+
+
+
{title}
+
+
+
+ {description}
+
+
+ );
+}
diff --git a/src/templates/BentoCards/Normal.tsx b/src/templates/BentoCards/Normal.tsx
new file mode 100644
index 0000000..150bea1
--- /dev/null
+++ b/src/templates/BentoCards/Normal.tsx
@@ -0,0 +1,77 @@
+import type { BentoCardProps } from "./BentoCard";
+
+export default function BentoCardNormal({
+ color,
+ image,
+ logo,
+ title,
+ description,
+ className,
+ link,
+}: BentoCardProps) {
+ if (link) {
+ return (
+
+ {image ? (
+ <>
+
+
+ >
+ ) : (
+ ""
+ )}
+
+
+
+
+
{title}
+
+
+
{description}
+
+
+ );
+ }
+ return (
+
+ {image ? (
+ <>
+
+
+ >
+ ) : (
+ ""
+ )}
+
+
+
+
+
{title}
+
+
+
{description}
+
+
+ );
+}
diff --git a/src/templates/BentoCards/Small.tsx b/src/templates/BentoCards/Small.tsx
new file mode 100644
index 0000000..39f5974
--- /dev/null
+++ b/src/templates/BentoCards/Small.tsx
@@ -0,0 +1,31 @@
+import type { BentoCardProps } from "./BentoCard";
+
+export default function BentoCardSmall({
+ color,
+ logo,
+ title,
+ className,
+ link
+}: BentoCardProps) {
+ if (link) {
+ return (
+
+
+ {title}
+
+ );
+ }
+ return (
+
+
+
{title}
+
+ );
+}
diff --git a/src/templates/Footer.tsx b/src/templates/Footer.tsx
new file mode 100644
index 0000000..4e4b69e
--- /dev/null
+++ b/src/templates/Footer.tsx
@@ -0,0 +1,11 @@
+interface FooterProps {
+ className?: string;
+}
+
+export default function Footer({ className }: FooterProps) {
+ return (
+
+ );
+}
diff --git a/src/templates/Title.tsx b/src/templates/Title.tsx
new file mode 100644
index 0000000..f62b201
--- /dev/null
+++ b/src/templates/Title.tsx
@@ -0,0 +1,19 @@
+export default function Title() {
+ return (
+
+
+
+ WAH.su(d0)
+
+
+ A tech non-company with a whole lot of wah—100% tech, 100%
+ non-company, 200% wah!
+
+
+
+
+
+
+
+ );
+}
diff --git a/src/watch.ts b/src/watch.ts
index ad925f0..57b15ee 100644
--- a/src/watch.ts
+++ b/src/watch.ts
@@ -10,7 +10,6 @@ import { WebSocketServer } from "ws";
let triggered = 0;
const delay = 1000;
-let SIGINTCount = 0;
let WSclients: any[] = [];
const log = new Log();
@@ -40,11 +39,12 @@ function onChange() {
}
function onExit() {
- fs.rmdirSync("out", { recursive: true });
+ fs.rmdirSync(path.join(__dirname, "../out"), { recursive: true });
+ log.info("Deleted 'out' folder");
process.exit(0);
}
-const watcher = chokidar.watch(["./src", "./stickerpacks", "./static"], {
+const watcher = chokidar.watch(["./src", "./static"], {
ignored: (filePath, stats) => filePath.endsWith("watch.ts"),
atomic: true,
awaitWriteFinish: true,
@@ -65,20 +65,8 @@ function startServerWithRebuild() {
});
process.on("SIGINT", () => {
- SIGINTCount += 1;
- if (WSclients.length > 0) {
- async function _closeWS() {
- WSclients.forEach(async (ws) => await ws.close());
- }
- _closeWS();
- }
- if (SIGINTCount == 1) {
- log.info("Gracefully shutdown and cleanup...");
- onExit();
- } else if (SIGINTCount >= 3) {
- log.info("Received 3+ SIGINT signals. Force exit...");
- process.exit(0);
- }
+ log.info("Gracefully shutdown and cleanup...");
+ onExit();
});
app.use(express.static(folder));
@@ -100,6 +88,9 @@ function startServerWithRebuild() {
onChange();
});
});
+ app.on("close", () => {
+ log.info("Server closed");
+ });
}
startServerWithRebuild();