diff --git a/bun.lockb b/bun.lockb
index 29a569c..6815fcd 100755
Binary files a/bun.lockb and b/bun.lockb differ
diff --git a/index.html b/index.html
index f7afd88..cb1b53f 100644
--- a/index.html
+++ b/index.html
@@ -6,6 +6,7 @@
+
Minesweeper
diff --git a/package.json b/package.json
index a64205a..3fe4ab9 100644
--- a/package.json
+++ b/package.json
@@ -41,6 +41,7 @@
"tailwind-merge": "^2.5.2",
"tailwindcss": "^4.0.0-alpha.24",
"use-sound": "^4.0.3",
+ "vite-imagetools": "^7.0.4",
"wouter": "^3.3.5",
"zod": "^3.23.8",
"zustand": "^4.5.5"
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 0000000..1f53798
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,2 @@
+User-agent: *
+Disallow: /
diff --git a/src/Shell.tsx b/src/Shell.tsx
index 1431f9a..587fd36 100644
--- a/src/Shell.tsx
+++ b/src/Shell.tsx
@@ -48,11 +48,11 @@ const Shell: React.FC = ({ children }) => {
transition={{ type: "tween" }}
>
-
- Minesweeper
-
+
Business
-
+
+ Minesweeper
+
@@ -82,6 +82,7 @@ const Shell: React.FC = ({ children }) => {
className="absolute left-4 bg-black border-white/10 border-y-1 border-r-1 rounded-l-none"
variant="ghost"
onClick={() => setIsOpen((isOpen) => !isOpen)}
+ aria-label="Menu"
>
diff --git a/src/components/Auth/LoginButton.tsx b/src/components/Auth/LoginButton.tsx
index 7acbee6..66b1c23 100644
--- a/src/components/Auth/LoginButton.tsx
+++ b/src/components/Auth/LoginButton.tsx
@@ -61,9 +61,9 @@ const LoginButton = () => {
.then(async (res) => {
setToken(res.token);
await wsClient.dispatch("user.loginWithToken", {
- token: JSON.parse(res.token),
+ token: res.token,
});
- queryClient.invalidateQueries();
+ await queryClient.resetQueries();
})
.catch((e) => {
setError(e);
diff --git a/src/components/Auth/RegisterButton.tsx b/src/components/Auth/RegisterButton.tsx
index 6936842..a0cc880 100644
--- a/src/components/Auth/RegisterButton.tsx
+++ b/src/components/Auth/RegisterButton.tsx
@@ -61,9 +61,9 @@ const RegisterButton = () => {
.then(async (res) => {
setToken(res.token);
await wsClient.dispatch("user.loginWithToken", {
- token: JSON.parse(res.token),
+ token: res.token,
});
- queryClient.invalidateQueries();
+ await queryClient.resetQueries();
})
.catch((e) => {
setError(e);
diff --git a/src/components/Header.tsx b/src/components/Header.tsx
index 805b955..e4fd70c 100644
--- a/src/components/Header.tsx
+++ b/src/components/Header.tsx
@@ -12,13 +12,17 @@ import LoginButton from "./Auth/LoginButton";
import { useWSMutation, useWSQuery } from "../hooks";
import RegisterButton from "./Auth/RegisterButton";
import { useQueryClient } from "@tanstack/react-query";
+import { useAtom } from "jotai";
+import { loginTokenAtom } from "../atoms";
const Header = () => {
const [, setLocation] = useLocation();
const { data: username } = useWSQuery("user.getSelf", null);
const queryClient = useQueryClient();
+ const [, setToken] = useAtom(loginTokenAtom);
const logout = useWSMutation("user.logout", () => {
- queryClient.invalidateQueries();
+ setToken(undefined);
+ queryClient.resetQueries();
});
return (
diff --git a/src/views/home/Home.tsx b/src/views/home/Home.tsx
index 97bdb6d..5d6072f 100644
--- a/src/views/home/Home.tsx
+++ b/src/views/home/Home.tsx
@@ -4,9 +4,9 @@ import { useWSQuery } from "../../hooks";
import { Tag } from "../../components/Tag";
import RegisterButton from "../../components/Auth/RegisterButton";
import { Button } from "../../components/Button";
-import defusing from "../../assets/illustrations/defusing.png";
-import lootbox1 from "../../assets/illustrations/lootbox1.png";
-import mine from "../../assets/illustrations/mine.png";
+import defusing from "../../assets/illustrations/defusing.png?aspect=4:3&w=100;200;300;400&format=webp&quality=100&as=metadata";
+import lootbox1 from "../../assets/illustrations/lootbox1.png?aspect=1:1&w=100;200;300;400&format=webp&quality=100&as=metadata";
+import mine from "../../assets/illustrations/mine.png?aspect=1:1&w=100;200;300;400&format=webp&quality=100&as=metadata";
import Section from "./Section";
import Hr from "../../components/Hr";
import { Link } from "wouter";
diff --git a/src/views/home/Section.tsx b/src/views/home/Section.tsx
index 8fa7eab..ad0cd5e 100644
--- a/src/views/home/Section.tsx
+++ b/src/views/home/Section.tsx
@@ -5,17 +5,30 @@ import {
useScroll,
useTransform,
} from "framer-motion";
-import { useRef } from "react";
+import { useEffect, useRef, useState } from "react";
import { cn } from "../../lib/utils";
interface SectionProps {
text: string;
- image: string;
+ image: OutputMetadata[];
left?: boolean;
}
const Section = ({ text, image, left }: SectionProps) => {
const ref = useRef(null);
+ const wrapperRef = useRef(null);
+ const [width, setWidth] = useState(0);
+ useEffect(() => {
+ const resizeObserver = new ResizeObserver(() => {
+ if (wrapperRef.current) {
+ setWidth(wrapperRef.current.clientWidth);
+ }
+ });
+ if (wrapperRef.current) {
+ resizeObserver.observe(wrapperRef.current);
+ }
+ return () => resizeObserver.disconnect();
+ }, []);
const { scrollYProgress } = useScroll({
target: ref,
});
@@ -44,18 +57,29 @@ const Section = ({ text, image, left }: SectionProps) => {
ease: "easeInOut",
}}
>
-
+ className="h-[80%] min-h-36"
+ >
+ `${i.src} ${i.width}w`).join(", ")}
+ sizes={`${width}px`}
+ loading="lazy"
+ className="h-[80%]"
+ />
+
);
diff --git a/src/vite-env.d.ts b/src/vite-env.d.ts
index 11f02fe..6a17aa3 100644
--- a/src/vite-env.d.ts
+++ b/src/vite-env.d.ts
@@ -1 +1,27 @@
///
+
+interface OutputMetadata {
+ src: string; // URL of the generated image
+ width: number; // Width of the image
+ height: number; // Height of the image
+ format: string; // Format of the generated image
+
+ // The following options are the same as sharps input options
+ space: string; // Name of colour space interpretation
+ channels: number; // Number of bands e.g. 3 for sRGB, 4 for CMYK
+ density: number; // Number of pixels per inch
+ depth: string; // Name of pixel depth format
+ hasAlpha: boolean; // presence of an alpha transparency channel
+ hasProfile: boolean; // presence of an embedded ICC profile
+ isProgressive: boolean; // indicating whether the image is interlaced using a progressive scan
+}
+
+declare module "*&as=metadata" {
+ const outputs: OutputMetadata[];
+ export default outputs;
+}
+
+declare module "*?as=metadata" {
+ const outputs: OutputMetadata[];
+ export default outputs;
+}
diff --git a/vite.config.ts b/vite.config.ts
index 50bf145..9163aca 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -1,8 +1,9 @@
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react-swc";
import tailwindcss from "@tailwindcss/vite";
+import { imagetools } from "vite-imagetools";
// https://vitejs.dev/config/
export default defineConfig({
- plugins: [react(), tailwindcss()],
+ plugins: [react(), tailwindcss(), imagetools()],
});