Index: pages/+Head.tsx
===================================================================
--- pages/+Head.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/+Head.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,7 @@
+// https://vike.dev/Head
+
+import logoUrl from "../assets/logo.svg";
+
+export function Head() {
+  return <link rel="icon" href={logoUrl} />;
+}
Index: pages/+Layout.telefunc.ts
===================================================================
--- pages/+Layout.telefunc.ts	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,127 +1,0 @@
-import * as drizzleQueries from "../database/drizzle/queries";
-import {ctx, getAuthState, parseSessionUserId, requireUser} from "../server/telefunc/ctx";
-import {Abort} from "telefunc";
-import type {Database} from "../database/drizzle/db";
-import {addNewBuild} from "../database/drizzle/queries";
-
-export async function onGetAuthState() {
-    const context = getAuthState();
-
-    return context;
-}
-
-export async function onGetAllComponents({ componentType, limit, sort, q }
-                                            : { componentType?: string; limit?: number; sort?: string, q?: string }) {
-    const c = ctx();
-
-    const components = await drizzleQueries.getAllComponents(c.db, limit, componentType, sort, q);
-
-    return components;
-}
-
-export async function onSuggestComponent({ link, description, componentType }
-                                               : { link: string; description: string; componentType: string }) {
-    const { c, userId } = requireUser()
-
-    const newSuggestionId = await drizzleQueries.addNewComponentSuggestion(c.db, userId, link, description, componentType);
-
-    if(!newSuggestionId) throw Abort();
-
-    return { success: true };
-}
-
-export async function onGetApprovedBuilds({ limit, sort, q }
-                                                 : { limit?: number; sort?: string; q?: string }) {
-    const context = ctx();
-
-    const approvedBuilds = await drizzleQueries.getApprovedBuilds(context.db, limit, sort, q);
-
-    return approvedBuilds;
-}
-
-export async function onGetComponentDetails({ componentId }
-                                            : { componentId: number }) {
-    const context = ctx();
-
-    if(!Number.isInteger(componentId) || componentId <= 0) throw Abort();
-
-    const componentDetails = await drizzleQueries.getComponentDetails(context.db, componentId);
-
-    if(!componentDetails) throw Abort();
-
-    return componentDetails;
-}
-
-export async function onGetBuildDetails({ buildId }
-                                           : { buildId: number }) {
-    const context = ctx();
-
-    if(!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    const userId = parseSessionUserId(context.session?.user?.id);
-    const buildDetails = await drizzleQueries.getBuildDetails(context.db, buildId, userId);
-
-    if(!buildDetails) throw Abort();
-
-    return buildDetails;
-}
-
-export async function onToggleFavorite({ buildId }
-                                          : { buildId: number }) {
-    const { c, userId } = requireUser()
-
-    if (!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    const isFavorite = await drizzleQueries.toggleFavoriteBuild(c.db, userId, buildId);
-
-    return isFavorite;
-}
-
-export async function onSetRating({ buildId, value }
-                                     : { buildId: number; value: number }) {
-    const { c, userId } = requireUser()
-
-    if (!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    if (!Number.isInteger(value) || value < 1 || value > 5) throw Abort();
-
-    const result = await drizzleQueries.setBuildRating(c.db, userId, buildId, value);
-
-    return { success: true };
-}
-
-export async function onSetReview({ buildId, content }
-                                     : { buildId: number; content: string }) {
-    const { c, userId } = requireUser()
-
-    if (!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    const result = await drizzleQueries.setBuildReview(c.db, userId, buildId, content);
-
-    return { success: true };
-}
-
-export async function onCloneBuild({ buildId }
-                                      : { buildId: number }) {
-    const { c, userId } = requireUser()
-
-    if (!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    const clonedBuildId = await drizzleQueries.cloneBuild(c.db, userId, buildId);
-
-    if (!clonedBuildId) throw Abort();
-
-    return clonedBuildId;
-}
-
-export async function onAddNewBuild({ name, description }
-                                          : { name: string; description: string }) {
-    const { c, userId } = requireUser()
-
-    const newBuildId = await drizzleQueries.addNewBuild(c.db, userId, name, description);
-
-    if (!newBuildId) throw Abort();
-
-    return newBuildId;
-}
-
Index: pages/+Layout.tsx
===================================================================
--- pages/+Layout.tsx	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ pages/+Layout.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -1,37 +1,74 @@
-import React from 'react';
-import Navbar from '../components/Navbar';
-import Footer from '../components/Footer';
-import Box from '@mui/material/Box';
-import { ThemeProvider, createTheme } from '@mui/material/styles';
-import CssBaseline from '@mui/material/CssBaseline';
+import "./Layout.css";
 
-const theme = createTheme({
-    palette: {
-        mode: 'dark',
-        primary: { main: '#ff8201' },
-        background: { default: '#121212', paper: '#1e1e1e' },
-    },
-});
+import logoUrl from "../assets/logo.svg";
+import { Link } from "../components/Link";
 
 export default function Layout({ children }: { children: React.ReactNode }) {
-    return (
-        <ThemeProvider theme={theme}>
-            <CssBaseline />
-            <Box
-                sx={{
-                    display: 'flex',
-                    flexDirection: 'column',
-                    minHeight: '100vh',
-                    bgcolor: 'background.default',
-                    color: 'text.primary',
-                }}
-            >
-                <Navbar />
-                <Box component="main" sx={{ flexGrow: 1, py: 3 }}>
-                    {children}
-                </Box>
-                <Footer />
-            </Box>
-        </ThemeProvider>
-    );
+  return (
+    <div
+      style={{
+        display: "flex",
+        maxWidth: 900,
+        margin: "auto",
+      }}
+    >
+      <Sidebar>
+        <Logo />
+        <Link href="/">Welcome</Link>
+        <Link href="/todo">Todo</Link>
+        <Link href="/star-wars">Data Fetching</Link>
+      </Sidebar>
+      <Content>{children}</Content>
+    </div>
+  );
 }
+
+function Sidebar({ children }: { children: React.ReactNode }) {
+  return (
+    <div
+      id="sidebar"
+      style={{
+        padding: 20,
+        flexShrink: 0,
+        display: "flex",
+        flexDirection: "column",
+        lineHeight: "1.8em",
+        borderRight: "2px solid #eee",
+      }}
+    >
+      {children}
+    </div>
+  );
+}
+
+function Content({ children }: { children: React.ReactNode }) {
+  return (
+    <div id="page-container">
+      <div
+        id="page-content"
+        style={{
+          padding: 20,
+          paddingBottom: 50,
+          minHeight: "100vh",
+        }}
+      >
+        {children}
+      </div>
+    </div>
+  );
+}
+
+function Logo() {
+  return (
+    <div
+      style={{
+        marginTop: 20,
+        marginBottom: 10,
+      }}
+    >
+      <a href="/">
+        <img src={logoUrl} height={64} width={64} alt="logo" />
+      </a>
+    </div>
+  );
+}
Index: pages/+config.ts
===================================================================
--- pages/+config.ts	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ pages/+config.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -1,3 +1,3 @@
-import type {Config} from "vike/types";
+import type { Config } from "vike/types";
 import vikePhoton from "vike-photon/config";
 import vikeReact from "vike-react/config";
@@ -7,13 +7,14 @@
 
 export default {
-    // https://vike.dev/head-tags
-    title: "PC Forge",
-    description: "PC Forge Site",
-    passToClient: ["user"],
-    extends: [vikeReact, vikePhoton],
+  // https://vike.dev/head-tags
+  title: "My Vike App",
+  description: "Demo showcasing Vike",
 
-    // https://vike.dev/vike-photon
-    photon: {
-        server: "../server/entry.ts",
-    },
+  passToClient: ["user"],
+  extends: [vikeReact, vikePhoton],
+
+  // https://vike.dev/vike-photon
+  photon: {
+    server: "../server/entry.ts",
+  },
 } satisfies Config;
Index: pages/Head.tsx
===================================================================
--- pages/Head.tsx	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,7 +1,0 @@
-// https://vike.dev/Head
-
-import logoUrl from "../assets/logo.svg";
-
-export function Head() {
-  return <link rel="icon" href={logoUrl} />;
-}
Index: pages/Layout.css
===================================================================
--- pages/Layout.css	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ pages/Layout.css	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -1,132 +1,29 @@
-html, body {
-    margin: 0;
-    padding: 0;
-    overflow-x: hidden;
-
+/* Links */
+a {
+  text-decoration: none;
+}
+#sidebar a {
+  padding: 2px 10px;
+  margin-left: -10px;
+}
+#sidebar a.is-active {
+  background-color: #eee;
 }
 
+/* Reset */
 body {
-    background: #262636;
+  margin: 0;
+  font-family: sans-serif;
+}
+* {
+  box-sizing: border-box;
 }
 
-#app-shell {
-    min-height: 100vh;
-    display: flex;
-    flex-direction: column;
+/* Page Transition Animation */
+#page-content {
+  opacity: 1;
+  transition: opacity 0.3s ease-in-out;
 }
-
-#page-content {
-    flex: 1;
-    padding: 32px 20px;
-    max-width: 1000px;
-    width: 100%;
-    margin: 0 auto;
+body.page-transition #page-content {
+  opacity: 0;
 }
-
-.navbar {
-    background: black;
-    color: white;
-}
-
-.navbar__logo{
-    height: 32px;
-    width: auto;
-    margin-right: 5px;
-}
-
-.navbar a {
-    color: white;
-    text-decoration: none;
-}
-
-.navbar__inner {
-    width: 100%;
-    margin: 0 auto;
-    padding: 5px 15px;
-    display: flex;
-    flex-direction: column;
-    gap: 10px;
-}
-
-.navbar__top {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    gap: 15px;
-    min-width: 0;
-}
-
-.navbar__bottom {
-    display: flex;
-    align-items: center;
-    justify-content: space-between;
-    gap: 16px;
-    min-width: 0;
-}
-
-.navbar__brand {
-    font-size: 25px;
-    font-weight: 700;
-}
-
-.navbar__auth {
-    display: flex;
-    align-items: center;
-    gap: 10px;
-    font-size: 18px;
-    opacity: 0.95;
-    margin-right: 30px;
-}
-
-.navbar__sep {
-    opacity: 0.5;
-}
-
-.navbar__links {
-    display: flex;
-    flex-wrap: wrap;
-    gap: 20px;
-    font-size: 18px;
-}
-
-.navbar__links a {
-    padding: 6px 8px;
-    border-radius: 8px;
-}
-
-.navbar__links a:hover,
-.navbar__auth a:hover {
-    background: rgba(255, 255, 255, 0.18);
-    color: #ff8201;
-}
-
-.navbar__search input {
-    width: 220px;
-    max-width: 45vw;
-    padding: 8px 10px;
-    border-radius: 10px;
-    border: 1px solid rgba(255, 255, 255, 0.15);
-    background: rgba(255, 255, 255, 0.06);
-    color: #eaeaea;
-    outline: none;
-    margin-right: 30px;
-    min-width: 0;
-
-}
-
-.navbar__search input::placeholder {
-    color: rgba(234, 234, 234, 0.6);
-}
-
-.footer {
-    border-top: 1px solid rgba(255, 255, 255, 0.08);
-    background: black;
-    color: gray;
-}
-
-.footer__inner {
-    width: 100%;
-    margin: 0 auto;
-    padding: 18px 20px;
-    font-size: 14px;
-}
Index: pages/auth/login/+Page.tsx
===================================================================
--- pages/auth/login/+Page.tsx	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,88 +1,0 @@
-import React, { useState } from "react";
-import { Container, Box, Typography, TextField, Button, Paper, Alert } from "@mui/material";
-
-export default function LoginPage() {
-    const [error, setError] = useState<string | null>(null);
-
-    const handleSubmit = async (event: React.FormEvent<HTMLFormElement>) => {
-        event.preventDefault();
-        setError(null);
-
-        const formData = new FormData(event.currentTarget);
-        const username = formData.get("username");
-        const password = formData.get("password");
-
-        const res = await fetch("/api/auth/callback/credentials", {
-            method: "POST",
-            headers: { "Content-Type": "application/json" },
-            body: JSON.stringify({
-                username,
-                password,
-                csrfToken: await getCsrfToken(),
-            }),
-        });
-
-        if (res.url.includes("error")) {
-            setError("Invalid username or password");
-        } else {
-            window.location.href = "/";
-        }
-    };
-
-    return (
-        <Container component="main" maxWidth="xs">
-            <Box sx={{ marginTop: 8, display: "flex", flexDirection: "column", alignItems: "center" }}>
-                <Paper elevation={3} sx={{ p: 4, width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center' }}>
-
-                    <Typography component="h1" variant="h5">
-                        Log in
-                    </Typography>
-
-                    {error && (
-                        <Alert severity="error" sx={{ mt: 2, width: '100%' }}>
-                            {error}
-                        </Alert>
-                    )}
-
-                    <Box component="form" onSubmit={handleSubmit} sx={{ mt: 1, width: '100%' }}>
-                        <TextField
-                            margin="normal"
-                            required
-                            fullWidth
-                            id="username"
-                            label="Username"
-                            name="username"
-                            autoComplete="username"
-                            autoFocus
-                        />
-                        <TextField
-                            margin="normal"
-                            required
-                            fullWidth
-                            name="password"
-                            label="Password"
-                            type="password"
-                            id="password"
-                            autoComplete="current-password"
-                        />
-
-                        <Button
-                            type="submit"
-                            fullWidth
-                            variant="contained"
-                            sx={{ mt: 3, mb: 2 }}
-                        >
-                            Sign In
-                        </Button>
-                    </Box>
-                </Paper>
-            </Box>
-        </Container>
-    );
-}
-
-async function getCsrfToken() {
-    const res = await fetch("/api/auth/csrf");
-    const data = await res.json();
-    return data.csrfToken;
-}
Index: pages/auth/register/+Page.tsx
===================================================================
--- pages/auth/register/+Page.tsx	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,88 +1,0 @@
-import React, {useState} from "react";
-import {Container, Box, Typography, TextField, Button, Paper, Alert, AlertColor} from "@mui/material";
-import {registerNewUser} from "./register.telefunc";
-
-export default function RegisterPage() {
-    const [username, setUsername] = useState("");
-    const [email, setEmail] = useState("");
-    const [password, setPassword] = useState("");
-    const [loading, setLoading] = useState(false);
-    const [message, setMessage] = useState<string | null>(null);
-    const [severity, setSeverity] = useState<AlertColor>("info");
-
-    async function onSubmit(e: React.FormEvent) {
-        e.preventDefault();
-        setLoading(true);
-        setMessage(null);
-
-        try {
-            const result = await registerNewUser({username, email, password});
-            if (result?.success) {
-                setSeverity("success");
-                setMessage("Registration successful! Redirecting...");
-                window.location.href = "/auth/login";
-            } else {
-                setSeverity("error");
-                setMessage("Registration failed.");
-            }
-        } catch (err) {
-            setSeverity("error");
-            setMessage("An error occurred. Please try again.");
-        } finally {
-            setLoading(false);
-        }
-    }
-
-    return (
-        <Container component="main" maxWidth="xs">
-            <Box sx={{marginTop: 8, display: "flex", flexDirection: "column", alignItems: "center", color: "white"}}>
-                <Paper elevation={3} sx={{p: 4, width: '100%'}}>
-                    <Typography component="h1" variant="h5" align="center">
-                        Register
-                    </Typography>
-
-                    <Box component="form" onSubmit={onSubmit} sx={{mt: 3}}>
-                        <TextField
-                            margin="normal"
-                            required
-                            fullWidth
-                            label="Username"
-                            value={username}
-                            onChange={(e) => setUsername(e.target.value)}
-                        />
-                        <TextField
-                            margin="normal"
-                            required
-                            fullWidth
-                            label="Email Address"
-                            type="email"
-                            value={email}
-                            onChange={(e) => setEmail(e.target.value)}
-                        />
-                        <TextField
-                            margin="normal"
-                            required
-                            fullWidth
-                            label="Password"
-                            type="password"
-                            value={password}
-                            onChange={(e) => setPassword(e.target.value)}
-                        />
-
-                        <Button
-                            type="submit"
-                            fullWidth
-                            variant="contained"
-                            disabled={loading}
-                            sx={{mt: 3, mb: 2, color: "white"}}
-                        >
-                            {loading ? "Registering..." : "Register"}
-                        </Button>
-
-                        {message && <Alert severity={severity}>{message}</Alert>}
-                    </Box>
-                </Paper>
-            </Box>
-        </Container>
-    );
-}
Index: pages/auth/register/register.telefunc.ts
===================================================================
--- pages/auth/register/register.telefunc.ts	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,22 +1,0 @@
-import * as drizzleQueries from "../../../database/drizzle/queries/users";
-import { ctx } from "../../../server/telefunc/ctx";
-import { Abort } from "telefunc";
-import bcrypt from "bcrypt";
-
-export async function registerNewUser({ username, email, password }
-                                      : { username: string; email: string; password: string }) {
-    const c = ctx();
-
-    if (c.session?.user?.id) throw Abort();
-
-    if(!username || !email || !password) throw Abort();
-
-    const passwordHash = await bcrypt.hash(password, 8);
-    const trimmedUsername = username.trim();
-    const trimmedEmail = email.trim();
-    const result = await drizzleQueries.createUser(c.db, trimmedUsername, trimmedEmail, passwordHash);
-
-    if(!result) throw Abort();
-
-    return { success: true };
-}
Index: pages/completed-builds/+Page.tsx
===================================================================
--- pages/completed-builds/+Page.tsx	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,192 +1,0 @@
-import React, { useEffect, useState } from 'react';
-import {
-    Container, Box, Typography, TextField, MenuItem, Select,
-    Slider, Button, Paper, InputAdornment, CircularProgress
-} from '@mui/material';
-import SearchIcon from '@mui/icons-material/Search';
-import FilterListIcon from '@mui/icons-material/FilterList';
-
-import BuildCard from '../../components/BuildCard';
-import BuildDetailsDialog from '../../components/BuildDetailsDialog';
-import { onGetApprovedBuilds, onGetAuthState } from '../+Layout.telefunc';
-
-export default function CompletedBuildsPage() {
-    const [builds, setBuilds] = useState<any[]>([]);
-    const [loading, setLoading] = useState(true);
-    const [userId, setUserId] = useState<number | null>(null);
-    const [selectedBuildId, setSelectedBuildId] = useState<number | null>(null);
-
-    const [sortBy, setSortBy] = useState('price_asc');
-    const [priceRange, setPriceRange] = useState<number[]>([0, 5000]);
-    const [searchQuery, setSearchQuery] = useState("");
-
-    const loadBuilds = async () => {
-        setLoading(true);
-        try {
-            const [userData, data] = await Promise.all([
-                onGetAuthState(),
-                onGetApprovedBuilds({q: searchQuery})
-            ]);
-            setUserId(userData.userId);
-
-            let sortedData = [...data];
-
-            switch (sortBy) {
-                case 'price_asc':
-                    sortedData.sort((a, b) => Number(a.total_price) - Number(b.total_price));
-                    break;
-                case 'price_desc':
-                    sortedData.sort((a, b) => Number(b.total_price) - Number(a.total_price));
-                    break;
-                case 'rating_desc':
-                    sortedData.sort((a, b) => (Number(b.avgRating) || 0) - (Number(a.avgRating) || 0));
-                    break;
-                case 'oldest':
-                    sortedData.sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
-                    break;
-                case 'newest':
-                default:
-                    sortedData.sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
-                    break;
-            }
-
-            sortedData = sortedData.filter(b => {
-                const price = Number(b.total_price);
-                return price >= priceRange[0] && price <= priceRange[1];
-            });
-
-            setBuilds(sortedData);
-        } catch (e) {
-            console.error("Failed to load builds", e);
-        } finally {
-            setLoading(false);
-        }
-    };
-
-    useEffect(() => {
-        void loadBuilds();
-    }, [sortBy, searchQuery]);
-
-    return (
-        <Container maxWidth={false} sx={{ mt: 4, mb: 10, px: { xs: 2, md: 4 } }}>
-            <Typography variant="h4" fontWeight="bold" gutterBottom>Completed Builds</Typography>
-            <Typography color="text.secondary" sx={{ mb: 4 }}>
-                Browse community configurations. Filter by price, components, or popularity.
-            </Typography>
-
-            <Box sx={{ display: 'flex', flexDirection: { xs: 'column', md: 'row' }, gap: 4 }}>
-
-                <Box sx={{
-                    width: { xs: '100%', md: '280px' },
-                    flexShrink: 0
-                }}>
-                    <Paper variant="outlined" sx={{ p: 3, position: 'sticky', top: 20 }}>
-                        <Box sx={{ display: 'flex', alignItems: 'center', mb: 2 }}>
-                            <FilterListIcon sx={{ mr: 1 }} />
-                            <Typography variant="h6" fontWeight="bold">Filters</Typography>
-                        </Box>
-
-                        <TextField
-                            fullWidth
-                            size="small"
-                            placeholder="Search builds..."
-                            value={searchQuery}
-                            onChange={(e) => setSearchQuery(e.target.value)}
-                            slotProps={{
-                                input: {
-                                    startAdornment: <InputAdornment position="start"><SearchIcon /></InputAdornment>,
-                                }
-                            }}
-                            sx={{ mb: 3 }}
-                        />
-
-                        <Typography gutterBottom fontWeight="bold">Price Range</Typography>
-                        <Box sx={{ px: 1, mb: 3 }}>
-                            <Slider
-                                value={priceRange}
-                                onChange={(_, newValue) => setPriceRange(newValue as number[])}
-                                valueLabelDisplay="auto"
-                                min={0}
-                                max={5000}
-                                step={100}
-                            />
-                            <Box sx={{ display: 'flex', justifyContent: 'space-between', mt: 1 }}>
-                                <Typography variant="caption">${priceRange[0]}</Typography>
-                                <Typography variant="caption">${priceRange[1]}+</Typography>
-                            </Box>
-                        </Box>
-
-                        <Button variant="contained" fullWidth onClick={loadBuilds}>
-                            Apply Filters
-                        </Button>
-                    </Paper>
-                </Box>
-
-                <Box sx={{ flexGrow: 1 }}>
-                    <Box sx={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', mb: 3 }}>
-                        <Typography fontWeight="bold">{builds.length} Builds Found</Typography>
-
-                        <Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
-                            <Typography variant="body2" color="text.secondary">Sort by:</Typography>
-                            <Select
-                                size="small"
-                                value={sortBy}
-                                onChange={(e) => setSortBy(e.target.value)}
-                                sx={{ minWidth: 150, bgcolor: 'background.paper' }}
-                            >
-                                <MenuItem value="newest">Newest First</MenuItem>
-                                <MenuItem value="oldest">Oldest First</MenuItem>
-                                <MenuItem value="price_desc">Price: High to Low</MenuItem>
-                                <MenuItem value="price_asc">Price: Low to High</MenuItem>
-                                <MenuItem value="rating_desc">Highest Rated</MenuItem>
-                            </Select>
-                        </Box>
-                    </Box>
-
-                    {loading ? (
-                        <Box sx={{ p: 5, textAlign: 'center' }}>
-                            <CircularProgress />
-                        </Box>
-                    ) : (
-                        <Box
-                            sx={{
-                                display: 'grid',
-                                gridTemplateColumns: {
-                                    xs: '1fr',
-                                    sm: 'repeat(2, 1fr)',
-                                    md: 'repeat(3, 1fr)',
-                                    lg: 'repeat(4, 1fr)',
-                                    xl: 'repeat(5, 1fr)'
-                                },
-                                gap: 3,
-                                width: '100%'
-                            }}
-                        >
-                            {builds.map((build) => (
-                                <BuildCard
-                                    key={build.id}
-                                    build={build}
-                                    onClick={() => setSelectedBuildId(build.id)}
-                                />
-                            ))}
-                            {builds.length === 0 && (
-                                <Box sx={{ gridColumn: '1 / -1', p: 5, textAlign: 'center', bgcolor: '#f5f5f5', borderRadius: 2 }}>
-                                    <Typography>No builds found matching your filters.</Typography>
-                                </Box>
-                            )}
-                        </Box>
-                    )}
-                </Box>
-            </Box>
-
-            {/* @ts-ignore */}
-            <BuildDetailsDialog
-                open={!!selectedBuildId}
-                buildId={selectedBuildId}
-                currentUser={userId}
-                onClose={() => setSelectedBuildId(null)}
-            />
-        </Container>
-    );
-
-}
Index: pages/dashboard/admin/+Page.tsx
===================================================================
--- pages/dashboard/admin/+Page.tsx	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,562 +1,0 @@
-import React, {useEffect, useState} from 'react';
-import {
-    Container, Paper, Typography, Box, Avatar, Divider, Button,
-    CircularProgress, Table, TableBody, TableCell, TableHead, TableRow,
-    Chip, IconButton, TextField, Dialog, DialogTitle, DialogContent, DialogActions
-} from '@mui/material';
-import AdminPanelSettingsIcon from '@mui/icons-material/AdminPanelSettings';
-import CheckCircleIcon from '@mui/icons-material/CheckCircle';
-import CancelIcon from '@mui/icons-material/Cancel';
-import BuildIcon from '@mui/icons-material/Build';
-import MemoryIcon from '@mui/icons-material/Memory';
-import AddIcon from '@mui/icons-material/Add';
-import DeleteIcon from '@mui/icons-material/Delete';
-
-import {
-    getAdminInfoAndData,
-    onSetBuildApprovalStatus,
-    onSetComponentSuggestionStatus
-} from './adminDashboard.telefunc';
-
-import BuildCard from '../../../components/BuildCard';
-import BuildDetailsDialog from '../../../components/BuildDetailsDialog';
-import {onDeleteBuild} from "../user/userDashboard.telefunc";
-import AddComponentDialog from "../../../components/AddComponentDialog";
-
-export default function AdminDashboard() {
-    const [data, setData] = useState<any>(null);
-    const [loading, setLoading] = useState(true);
-    const [selectedBuildId, setSelectedBuildId] = useState<number | null>(null);
-    const [deleteDialog, setDeleteDialog] = useState<{
-        open: boolean,
-        buildId: number | null,
-        buildName: string
-    }>({open: false, buildId: null, buildName: ''});
-    const [deleteLoading, setDeleteLoading] = useState(false);
-    const [addDialogOpen, setAddDialogOpen] = useState(false);
-
-    const [buildApprovalDialog, setBuildApprovalDialog] = useState<{
-        open: boolean,
-        buildId: number | null,
-        buildName: string
-    }>({open: false, buildId: null, buildName: ''});
-    const [approvalLoading, setApprovalLoading] = useState(false);
-
-    const [suggestionDialog, setSuggestionDialog] = useState<{
-        open: boolean,
-        id: number | null,
-        action: 'approved' | 'rejected'
-    }>({open: false, id: null, action: 'approved'});
-    const [adminComment, setAdminComment] = useState("");
-
-    const [createComponentDialog, setCreateComponentDialog] = useState<{
-        open: boolean;
-        suggestion: any | null;
-    }>({open: false, suggestion: null});
-
-    const loadData = () => {
-        setLoading(true);
-        getAdminInfoAndData()
-            .then(res => {
-                setData(res);
-                setLoading(false);
-            })
-            .catch(err => {
-                console.error(err);
-                alert("Failed to load admin data. Are you an admin?");
-                setLoading(false);
-            });
-    };
-
-    useEffect(() => {
-        loadData();
-    }, []);
-
-    const openBuildApproval = (buildId: number, buildName: string) => {
-        setBuildApprovalDialog({open: true, buildId, buildName});
-    };
-
-    const handleApproveBuild = async () => {
-        if (!buildApprovalDialog.buildId) return;
-        setApprovalLoading(true);
-        try {
-            await onSetBuildApprovalStatus({buildId: buildApprovalDialog.buildId, isApproved: true});
-            setBuildApprovalDialog({open: false, buildId: null, buildName: ''});
-            loadData();
-        } catch (e) {
-            alert("Approve failed");
-        } finally {
-            setApprovalLoading(false);
-        }
-    };
-
-    // const handleRejectBuild = async () => {
-    //     if (!buildApprovalDialog.buildId || !rejectReason.trim()) return;
-    //     setApprovalLoading(true);
-    //     try {
-    //         await onSetBuildApprovalStatus({
-    //             buildId: buildApprovalDialog.buildId,
-    //             isApproved: false,
-    //         });
-    //         setBuildApprovalDialog({open: false, buildId: null, buildName: ''});
-    //         loadData();
-    //     } catch (e) {
-    //         console.error("Reject error:", e); // 🔧 add this
-    //         alert("Reject failed");
-    //     } finally {
-    //         setApprovalLoading(false);
-    //     }
-    // };
-
-    const openSuggestionReview = (id: number, action: 'approved' | 'rejected') => {
-        setSuggestionDialog({open: true, id, action});
-        setAdminComment(action === 'approved' ? "" : "");
-    };
-
-    const submitSuggestionReview = async () => {
-        if (!suggestionDialog.id) return;
-        try {
-            await onSetComponentSuggestionStatus({
-                suggestionId: suggestionDialog.id,
-                status: suggestionDialog.action,
-                adminComment: adminComment
-            });
-            setSuggestionDialog({...suggestionDialog, open: false});
-            loadData();
-        } catch (e) {
-            alert("Failed to update suggestion");
-        }
-    };
-
-    const openDeleteDialog = (buildId: number, buildName: string) => {
-        setDeleteDialog({open: true, buildId, buildName});
-    };
-
-    const handleDelete = async () => {
-        if (!deleteDialog.buildId) return;
-        setDeleteLoading(true);
-        try {
-            await onDeleteBuild({buildId: deleteDialog.buildId});
-            setDeleteDialog({open: false, buildId: null, buildName: ''});
-            loadData();
-            setSelectedBuildId(null);
-        } catch (e) {
-            alert("Failed to delete build");
-        } finally {
-            setDeleteLoading(false);
-        }
-    };
-
-    if (loading) {
-        return (
-            <Container maxWidth="xl" sx={{
-                mt: 4,
-                mb: 10,
-                display: 'flex',
-                justifyContent: 'center',
-                alignItems: 'center',
-                minHeight: '50vh'
-            }}>
-                <CircularProgress/>
-            </Container>
-        );
-    }
-
-    if (!data) {
-        return (
-            <Container maxWidth="xl" sx={{mt: 4, mb: 10, textAlign: 'center', p: 5}}>
-                <Typography variant="h6" color="error">
-                    Access Denied - Admin privileges required
-                </Typography>
-            </Container>
-        );
-    }
-
-    return (
-        <Container maxWidth="xl" sx={{mt: 4, mb: 10}}>
-            <Box sx={{
-                display: 'grid',
-                gridTemplateColumns: {
-                    xs: '1fr',
-                    md: '300px 1fr'
-                },
-                gap: 4
-            }}>
-                <Box>
-                    <Paper elevation={3} sx={{
-                        p: 4,
-                        display: 'flex',
-                        flexDirection: 'column',
-                        alignItems: 'center',
-                        height: '100%',
-                        bgcolor: '#1e1e1e',
-                        color: 'white'
-                    }}>
-                        <Avatar sx={{width: 120, height: 120, mb: 2, bgcolor: 'error.main'}}>
-                            <AdminPanelSettingsIcon sx={{fontSize: 70}}/>
-                        </Avatar>
-                        <Typography variant="h5" fontWeight="bold">{data.admin?.username || 'Admin'}</Typography>
-                        <Typography variant="body2" sx={{opacity: 0.7, mb: 3}}>
-                            {data.admin?.email || 'admin@example.com'}
-                        </Typography>
-
-                        <Chip label="ADMINISTRATOR" color="error" variant="outlined" sx={{fontWeight: 'bold'}}/>
-                        <Divider sx={{width: '100%', my: 3, bgcolor: 'rgba(255,255,255,0.1)'}}/>
-
-                        <Box sx={{width: '100%', textAlign: 'center'}}>
-                            <Typography variant="h3" fontWeight="bold" color="primary.main">
-                                {data.pendingBuilds?.length || 0}
-                            </Typography>
-                            <Typography variant="caption">Pending Builds</Typography>
-                        </Box>
-
-                        <Box sx={{width: '100%', textAlign: 'center', mt: 3}}>
-                            <Button
-                                variant="contained"
-                                color="warning"
-                                size="large"
-                                fullWidth
-                                startIcon={<BuildIcon/>}
-                                onClick={() => setAddDialogOpen(true)}
-                                sx={{mb: 2}}
-                            >
-                                Add Component
-                            </Button>
-                        </Box>
-                    </Paper>
-                </Box>
-
-                <Box sx={{
-                    display: 'flex',
-                    flexDirection: 'column',
-                    gap: 4
-                }}>
-                    <Paper sx={{p: 3, borderLeft: '6px solid #9c27b0'}}>
-                        <Box sx={{display: 'flex', alignItems: 'center', mb: 2}}>
-                            <MemoryIcon color="secondary" sx={{mr: 1}}/>
-                            <Typography variant="h6" fontWeight="bold">
-                                Component Suggestions ({data.componentSuggestions?.length || 0})
-                            </Typography>
-                        </Box>
-
-                        {data.componentSuggestions?.length === 0 ? (
-                            <Typography color="text.secondary">No suggestions.</Typography>
-                        ) : (
-                            <Box sx={{width: '100%', overflowX: 'auto'}}>
-                                <Table size="small">
-                                    <TableHead>
-                                        <TableRow>
-                                            <TableCell>Link/Description</TableCell>
-                                            <TableCell>Type</TableCell>
-                                            <TableCell>User</TableCell>
-                                            <TableCell>Status</TableCell>
-                                            <TableCell align="right">Actions</TableCell>
-                                        </TableRow>
-                                    </TableHead>
-                                    <TableBody>
-                                        {data.componentSuggestions?.map((sug: any) => (
-                                            <TableRow key={sug.id}>
-                                                <TableCell sx={{minWidth: 200, maxWidth: 300}}>
-                                                    <a
-                                                        href={sug.link}
-                                                        target="_blank"
-                                                        rel="noopener noreferrer"
-                                                        title={sug.link}
-                                                        style={{textDecoration: 'none', color: 'inherit'}}
-                                                    >
-                                                        {sug.description || sug.link}
-                                                    </a>
-                                                </TableCell>
-                                                <TableCell sx={{minWidth: 80}}>
-                                                    {sug.componentType?.toUpperCase()}
-                                                </TableCell>
-                                                <TableCell sx={{minWidth: 100}}>
-                                                    {sug.user?.username || `${sug.userId}`}
-                                                </TableCell>
-                                                <TableCell sx={{minWidth: 100}}>
-                                                    <Chip
-                                                        label={sug.status || 'pending'}
-                                                        size="small"
-                                                        color={
-                                                            sug.status === 'approved' ? 'success' :
-                                                                sug.status === 'rejected' ? 'error' :
-                                                                    'default'
-                                                        }
-                                                    />
-                                                </TableCell>
-                                                <TableCell align="right" sx={{minWidth: 150}}>
-                                                    {sug.status === 'pending' ? (
-                                                        <>
-                                                            <IconButton
-                                                                size="small"
-                                                                color="success"
-                                                                onClick={() => openSuggestionReview(sug.id, 'approved')}
-                                                            >
-                                                                <CheckCircleIcon/>
-                                                            </IconButton>
-                                                            <IconButton
-                                                                size="small"
-                                                                color="error"
-                                                                onClick={() => openSuggestionReview(sug.id, 'rejected')}
-                                                            >
-                                                                <CancelIcon/>
-                                                            </IconButton>
-                                                        </>
-                                                    ) : sug.status === 'approved' ? (
-                                                        <Button
-                                                            size="small"
-                                                            variant="contained"
-                                                            color="warning"
-                                                            startIcon={<AddIcon/>}
-                                                            onClick={() => setCreateComponentDialog({
-                                                                open: true,
-                                                                suggestion: sug
-                                                            })}
-                                                        >
-                                                            Create
-                                                        </Button>
-                                                    ) : (
-                                                        <Typography variant="caption" color="text.secondary">
-                                                            {sug.adminComment || 'Rejected'}
-                                                        </Typography>
-                                                    )}
-                                                </TableCell>
-                                            </TableRow>
-                                        ))}
-                                    </TableBody>
-                                </Table>
-                            </Box>
-                        )}
-                    </Paper>
-
-                    <Paper sx={{p: 3, borderLeft: '6px solid #ed6c02', bgcolor: '#121212'}}>
-                        <Box sx={{display: 'flex', alignItems: 'center', mb: 2}}>
-                            <BuildIcon color="warning" sx={{mr: 1}}/>
-                            <Typography variant="h6" fontWeight="bold">
-                                Builds Waiting for Approval ({data.pendingBuilds?.length || 0})
-                            </Typography>
-                        </Box>
-
-                        {data.pendingBuilds?.length === 0 ? (
-                            <Typography color="text.secondary">No pending builds.</Typography>
-                        ) : (
-                            <Box sx={{
-                                display: 'grid',
-                                gridTemplateColumns: {
-                                    xs: '1fr',
-                                    sm: 'repeat(2, 1fr)',
-                                    lg: 'repeat(3, 1fr)',
-                                    xl: 'repeat(4, 1fr)'
-                                },
-                                gap: 2
-                            }}>
-                                {data.pendingBuilds.map((build: any) => (
-                                    <Box key={build.id} sx={{
-                                        display: 'flex',
-                                        flexDirection: 'column',
-                                        borderRadius: 2,
-                                        overflow: 'hidden',
-                                        bgcolor: 'background.paper'
-                                    }}>
-                                        <BuildCard
-                                            build={build}
-                                            onClick={() => setSelectedBuildId(build.id)}
-                                        />
-                                        <Button
-                                            variant="contained"
-                                            color="warning"
-                                            size="small"
-                                            fullWidth
-                                            startIcon={<BuildIcon/>}
-                                            onClick={(e) => {
-                                                e.stopPropagation();
-                                                openBuildApproval(build.id, build.name);
-                                            }}
-                                            sx={{borderRadius: 0}}
-                                        >
-                                            Review
-                                        </Button>
-                                    </Box>
-                                ))}
-
-                            </Box>
-                        )}
-                    </Paper>
-
-                    <Paper sx={{p: 3, borderLeft: '6px solid #2e7d32'}}>
-                        <Typography variant="h6" fontWeight="bold" gutterBottom>
-                            My Builds / Sandbox
-                        </Typography>
-                        {data.userBuilds?.length === 0 ? (
-                            <Typography color="text.secondary">No builds created by admin.</Typography>
-                        ) : (
-                            <Box sx={{
-                                display: 'grid',
-                                gridTemplateColumns: {
-                                    xs: '1fr',
-                                    sm: 'repeat(2, 1fr)',
-                                    lg: 'repeat(3, 1fr)',
-                                    xl: 'repeat(4, 1fr)'
-                                },
-                                gap: 2
-                            }}>
-                                {data.userBuilds.slice(0, 4).map((build: any) => (
-                                    <Box key={build.id}>
-                                        <BuildCard
-                                            build={build}
-                                            onClick={() => setSelectedBuildId(build.id)}
-                                        />
-                                        <Box sx={{mt: 1, display: 'flex', justifyContent: 'center'}}>
-                                            <Button
-                                                variant="outlined"
-                                                color="error"
-                                                size="small"
-                                                startIcon={<DeleteIcon/>}
-                                                onClick={(e) => {
-                                                    e.stopPropagation();
-                                                    openDeleteDialog(build.id, build.name);
-                                                }}
-                                                fullWidth
-                                            >
-                                                Delete
-                                            </Button>
-                                        </Box>
-                                    </Box>
-                                ))}
-                            </Box>
-                        )}
-                    </Paper>
-                </Box>
-            </Box>
-
-            <Dialog open={suggestionDialog.open}
-                    onClose={() => setSuggestionDialog({...suggestionDialog, open: false})}>
-                <DialogTitle>Review Component Suggestion</DialogTitle>
-                <DialogContent>
-                    <Typography gutterBottom>Status: <b>{suggestionDialog.action.toUpperCase()}</b></Typography>
-                    <TextField
-                        fullWidth
-                        label="Admin Comment"
-                        multiline
-                        rows={3}
-                        value={adminComment}
-                        onChange={(e) => setAdminComment(e.target.value)}
-                        sx={{mt: 2}}
-                    />
-                </DialogContent>
-                <DialogActions>
-                    <Button onClick={() => setSuggestionDialog({...suggestionDialog, open: false})}>Cancel</Button>
-                    <Button variant="contained" onClick={submitSuggestionReview}>Submit</Button>
-                </DialogActions>
-            </Dialog>
-
-            <Dialog
-                open={buildApprovalDialog.open}
-                onClose={() => setBuildApprovalDialog({open: false, buildId: null, buildName: ''})}
-            >
-                <DialogTitle>Review Build</DialogTitle>
-                <DialogContent>
-                    <Typography variant="h6" gutterBottom>{buildApprovalDialog.buildName}</Typography>
-                    <Typography color="text.secondary" sx={{mb: 2}}>
-                        Build ID: {buildApprovalDialog.buildId}
-                    </Typography>
-                    {/*<TextField*/}
-                    {/*    fullWidth*/}
-                    {/*    multiline*/}
-                    {/*    rows={2}*/}
-                    {/*    label="Reject reason (optional)"*/}
-                    {/*    value={rejectReason}*/}
-                    {/*    onChange={(e) => setRejectReason(e.target.value)}*/}
-                    {/*    placeholder="Why reject this build?"*/}
-                    {/*    sx={{mt: 1}}*/}
-                    {/*/>*/}
-                </DialogContent>
-                <DialogActions>
-                    <Button
-                        onClick={() => setBuildApprovalDialog({open: false, buildId: null, buildName: ''})}
-                        disabled={approvalLoading}
-                    >
-                        Cancel
-                    </Button>
-                    {/*<Button*/}
-                    {/*    onClick={handleRejectBuild}*/}
-                    {/*    variant="outlined"*/}
-                    {/*    color="error"*/}
-                    {/*    disabled={approvalLoading || !rejectReason.trim()}*/}
-                    {/*>*/}
-                    {/*    {approvalLoading ? <CircularProgress size={20}/> : 'Reject'}*/}
-                    {/*</Button>*/}
-                    <Button
-                        onClick={handleApproveBuild}
-                        variant="contained"
-                        color="success"
-                        disabled={approvalLoading}
-                    >
-                        {approvalLoading ? <CircularProgress size={20}/> : 'Approve'}
-                    </Button>
-                </DialogActions>
-            </Dialog>
-
-            <Dialog
-                open={deleteDialog.open}
-                onClose={() => setDeleteDialog({open: false, buildId: null, buildName: ''})}
-            >
-                <DialogTitle>Delete Build</DialogTitle>
-                <DialogContent>
-                    <Typography variant="h6" gutterBottom>{deleteDialog.buildName}</Typography>
-                    <Typography color="text.secondary">
-                        Are you sure you want to permanently delete this build? This action cannot be undone.
-                    </Typography>
-                </DialogContent>
-                <DialogActions>
-                    <Button
-                        onClick={() => setDeleteDialog({open: false, buildId: null, buildName: ''})}
-                        disabled={deleteLoading}
-                    >
-                        Cancel
-                    </Button>
-                    <Button
-                        onClick={handleDelete}
-                        variant="contained"
-                        color="error"
-                        disabled={deleteLoading}
-                        startIcon={deleteLoading ? <CircularProgress size={20}/> : <DeleteIcon/>}
-                    >
-                        {deleteLoading ? 'Deleting...' : 'Delete Build'}
-                    </Button>
-                </DialogActions>
-            </Dialog>
-
-            <BuildDetailsDialog
-                open={!!selectedBuildId}
-                buildId={selectedBuildId!}
-                currentUser={data.admin}
-                onClose={() => setSelectedBuildId(null)}
-                isDashboardView={true}
-            />
-
-            <AddComponentDialog
-                open={addDialogOpen}
-                onClose={() => setAddDialogOpen(false)}
-                onSuccess={() => {
-                    loadData();
-                    setAddDialogOpen(false);
-                }}
-            />
-
-            <AddComponentDialog
-                open={createComponentDialog.open}
-                onClose={() => setCreateComponentDialog({open: false, suggestion: null})}
-                onSuccess={() => {
-                    loadData();
-                    setCreateComponentDialog({open: false, suggestion: null});
-                }}
-                prefillData={createComponentDialog.suggestion ? {
-                    type: createComponentDialog.suggestion.componentType,
-                    suggestionLink: createComponentDialog.suggestion.link,
-                    suggestionDescription: createComponentDialog.suggestion.description
-                } : undefined}
-            />
-        </Container>
-    );
-}
Index: pages/dashboard/admin/adminDashboard.telefunc.ts
===================================================================
--- pages/dashboard/admin/adminDashboard.telefunc.ts	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,73 +1,0 @@
-import * as drizzleQueries from "../../../database/drizzle/queries";
-import {requireAdmin} from "../../../server/telefunc/ctx";
-import {Abort} from "telefunc";
-import { validateComponentSpecificData } from "../../../database/drizzle/util/componentFieldConfig";
-
-export async function getAdminInfoAndData() {
-    const { c, userId } = await requireAdmin();
-
-    const admin = await drizzleQueries.getUserProfile(c.db, userId);
-
-    if (!admin) throw new Error();
-
-    const pendingBuilds = await drizzleQueries.getPendingBuilds(c.db);
-    const userBuilds = await drizzleQueries.getUserBuilds(c.db, userId);
-    const componentSuggestions = await drizzleQueries.getComponentSuggestions(c.db);
-
-    return {
-        admin,
-        pendingBuilds,
-        userBuilds,
-        componentSuggestions
-    };
-}
-
-export async function onSetBuildApprovalStatus({ buildId, isApproved }
-                                                 : { buildId: number; isApproved: boolean }) {
-    const { c, userId } = await requireAdmin()
-
-    if (!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    const result = await drizzleQueries.setBuildApprovalStatus(c.db, buildId, isApproved);
-
-    if (!result) throw Abort();
-
-    return { success: true };
-}
-
-export async function onSetComponentSuggestionStatus({ suggestionId, status, adminComment }
-                                                : { suggestionId: number; status: string; adminComment: string }) {
-    const { c, userId } = await requireAdmin()
-
-
-    if(!Number.isInteger(suggestionId) || suggestionId <= 0) throw Abort();
-
-    const result = await drizzleQueries.setComponentSuggestionStatus(c.db, suggestionId, userId, status, adminComment);
-
-    if (!result) throw Abort();
-
-    return { success: true };
-}
-
-export async function onCreateNewComponent({ name, brand, price, imgUrl, type, specificData }
-                                            : { name: string; brand: string; price: number; imgUrl: string; type: string, specificData: any }) {
-
-    const { c, userId } = await requireAdmin()
-
-    if(!validateComponentSpecificData(type, specificData)) throw Abort();
-
-    const newComponentId = await drizzleQueries.addNewComponent(c.db, name, brand, price, imgUrl, type, specificData);
-
-    if(!newComponentId) throw Abort();
-
-    return { success: true };
-}
-
-export async function onGetDetailsForNewComponent({ type }
-                                                  : { type: string }) {
-    const { c, userId } = await requireAdmin()
-
-    const details = await drizzleQueries.getDetailsNewComponent(type);
-
-    return details;
-}
Index: pages/dashboard/user/+Page.tsx
===================================================================
--- pages/dashboard/user/+Page.tsx	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,364 +1,0 @@
-import React, {useEffect, useState} from 'react';
-import {
-    Container,
-    Paper,
-    Typography,
-    Box,
-    Avatar,
-    Divider,
-    Button,
-    CircularProgress,
-    IconButton,
-    Dialog,
-    DialogTitle,
-    DialogContent,
-    DialogActions
-} from '@mui/material';
-import CloseIcon from '@mui/icons-material/Close';
-import DeleteIcon from '@mui/icons-material/Delete';
-
-import PersonIcon from '@mui/icons-material/Person';
-import ComputerIcon from '@mui/icons-material/Computer';
-import FavoriteIcon from '@mui/icons-material/Favorite';
-
-import {getUserInfoAndData, onDeleteBuild} from "./userDashboard.telefunc";
-
-import BuildCard from "../../../components/BuildCard";
-import BuildDetailsDialog from "../../../components/BuildDetailsDialog";
-
-type DashboardData = {
-    user: { username: string; email?: string; [key: string]: any };
-    userBuilds: any[];
-    favoriteBuilds: any[];
-};
-
-export default function UserDashboard() {
-    const [data, setData] = useState<DashboardData | null>(null);
-    const [loading, setLoading] = useState(true);
-    const [error, setError] = useState<string | null>(null);
-    const [openMyBuildsDialog, setOpenMyBuildsDialog] = useState(false);
-    const [openFavoritesDialog, setOpenFavoritesDialog] = useState(false);
-    const [selectedBuildId, setSelectedBuildId] = useState<number | null>(null);
-    const [deleteDialog, setDeleteDialog] = useState<{ open: boolean, buildId: number | null, buildName: string }>({ open: false, buildId: null, buildName: '' });
-    const [deleteLoading, setDeleteLoading] = useState(false);
-
-    const loadData = () => {
-        getUserInfoAndData()
-            .then((result) => {
-                setData(result);
-                setLoading(false);
-            })
-            .catch((err) => {
-                console.error(err);
-                setError("Failed to load dashboard. Please log in.");
-                setLoading(false);
-            });
-    };
-
-    useEffect(() => {
-        loadData();
-    }, []);
-
-    const openDeleteDialog = (buildId: number, buildName: string) => {
-        setDeleteDialog({ open: true, buildId, buildName });
-    };
-
-    const handleDelete = async () => {
-        if (!deleteDialog.buildId) return;
-        setDeleteLoading(true);
-        try {
-            await onDeleteBuild({buildId: deleteDialog.buildId});
-            setDeleteDialog({ open: false, buildId: null, buildName: '' });
-            loadData();
-            setSelectedBuildId(null);
-        } catch (e) {
-            alert("Failed to delete build");
-        } finally {
-            setDeleteLoading(false);
-        }
-    };
-
-    if (loading) return <Box sx={{display: 'flex', justifyContent: 'center', mt: 10}}><CircularProgress/></Box>;
-    if (error || !data) return <Container sx={{mt: 5, textAlign: 'center'}}><Typography color="error" variant="h6">{error}</Typography><Button href="/auth/login" variant="contained">Login</Button></Container>;
-
-    return (
-        <Container maxWidth="xl" sx={{mb: 4, color: 'white'}}>
-            <Box sx={{
-                display: 'grid',
-                gridTemplateColumns: {
-                    xs: '1fr',
-                    md: '280px 1fr'
-                },
-                gap: 2
-            }}>
-                <Box>
-                    <Paper elevation={3} sx={{p: 3, display: 'flex', flexDirection: 'column', alignItems: 'center', height: '100%'}}>
-                        <Avatar sx={{width: 100, height: 100, mb: 2, bgcolor: 'primary.main'}}>
-                            <PersonIcon sx={{fontSize: 60}}/>
-                        </Avatar>
-                        <Typography variant="h5" fontWeight="bold" gutterBottom>{data.user.username}</Typography>
-                        <Typography variant="body2" color="text.secondary" gutterBottom>{data.user.email}</Typography>
-                        <Divider sx={{width: '100%', my: 2}}/>
-                    </Paper>
-                </Box>
-
-                <Box sx={{
-                    display: 'flex',
-                    flexDirection: 'column',
-                    gap: 3
-                }}>
-                    <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}>
-                        <Box sx={{
-                            display: 'flex',
-                            alignItems: 'center',
-                            justifyContent: 'space-between',
-                            mb: 2
-                        }}>
-                            <Box sx={{display: 'flex', alignItems: 'center'}}>
-                                <FavoriteIcon color="error" sx={{mr: 1}}/>
-                                <Typography variant="h6" fontWeight="bold">Favorited Builds</Typography>
-                            </Box>
-
-                            {data.favoriteBuilds.length > 6 && (
-                                <Button
-                                    variant="outlined"
-                                    size="small"
-                                    onClick={() => setOpenFavoritesDialog(true)}
-                                >
-                                    See All ({data.favoriteBuilds.length})
-                                </Button>
-                            )}
-                        </Box>
-                        <Divider sx={{mb: 2}}/>
-
-                        {data.favoriteBuilds.length === 0 ? (
-                            <Typography color="text.secondary" align="center" sx={{mt: 4}}>
-                                You haven't favorited any builds yet.
-                            </Typography>
-                        ) : (
-                            <Box sx={{
-                                display: 'grid',
-                                gridTemplateColumns: {
-                                    xs: '1fr',
-                                    sm: 'repeat(2, 1fr)',
-                                    md: 'repeat(3, 1fr)',
-                                    lg: 'repeat(4, 1fr)',
-                                    xl: 'repeat(6, 1fr)'
-                                },
-                                gap: 2
-                            }}>
-                                {data.favoriteBuilds.slice(0, 6).map((build: any) => (
-                                    <BuildCard
-                                        key={build.id}
-                                        build={build}
-                                        onClick={() => setSelectedBuildId(build.id)}
-                                    />
-                                ))}
-                            </Box>
-                        )}
-                    </Paper>
-
-                    <Paper elevation={3} sx={{p: 3, minHeight: '300px', bgcolor: '#1e1e1e'}}>
-                        <Box sx={{
-                            display: 'flex',
-                            alignItems: 'center',
-                            justifyContent: 'space-between',
-                            mb: 2
-                        }}>
-                            <Box sx={{display: 'flex', alignItems: 'center'}}>
-                                <ComputerIcon color="primary" sx={{mr: 1}}/>
-                                <Typography variant="h6" fontWeight="bold">My Builds</Typography>
-                            </Box>
-
-                            {data.userBuilds.length > 6 && (
-                                <Button
-                                    variant="outlined"
-                                    size="small"
-                                    onClick={() => setOpenMyBuildsDialog(true)}
-                                >
-                                    See All ({data.userBuilds.length})
-                                </Button>
-                            )}
-                        </Box>
-                        <Divider sx={{mb: 2}}/>
-
-                        {data.userBuilds.length === 0 ? (
-                            <Box sx={{textAlign: 'center', mt: 4}}>
-                                <Typography color="text.secondary" gutterBottom>
-                                    You haven't created any builds yet.
-                                </Typography>
-                                <Button variant="contained" href="/forge" sx={{color: 'white', fontWeight: 'bolder'}}>
-                                    Start Forging
-                                </Button>
-                            </Box>
-                        ) : (
-                            <Box sx={{
-                                display: 'grid',
-                                gridTemplateColumns: {
-                                    xs: '1fr',
-                                    sm: 'repeat(2, 1fr)',
-                                    md: 'repeat(3, 1fr)',
-                                    lg: 'repeat(4, 1fr)',
-                                    xl: 'repeat(6, 1fr)'
-                                },
-                                gap: 2
-                            }}>
-                                {data.userBuilds.slice(0, 6).map((build: any) => (
-                                    <Box key={build.id} sx={{ display: 'flex', flexDirection: 'column', pb: 2 }}>
-                                        <Box sx={{ flexGrow: 1 }}>
-                                            <BuildCard
-                                                build={build}
-                                                onClick={() => setSelectedBuildId(build.id)}
-                                            />
-                                        </Box>
-                                        <Button
-                                            variant="outlined"
-                                            color="error"
-                                            size="small"
-                                            startIcon={<DeleteIcon/>}
-                                            onClick={(e) => {
-                                                e.stopPropagation();
-                                                openDeleteDialog(build.id, build.name);
-                                            }}
-                                            sx={{ mt: 1, width: '100%' }}
-                                        >
-                                            Delete
-                                        </Button>
-                                    </Box>
-                                ))}
-                            </Box>
-                        )}
-                    </Paper>
-                </Box>
-            </Box>
-
-            <Dialog open={openMyBuildsDialog} onClose={() => setOpenMyBuildsDialog(false)} maxWidth="xl" fullWidth>
-                <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
-                    All My Builds
-                    <IconButton onClick={() => setOpenMyBuildsDialog(false)}>
-                        <CloseIcon/>
-                    </IconButton>
-                </DialogTitle>
-                <DialogContent dividers>
-                    <Box sx={{
-                        display: 'grid',
-                        gridTemplateColumns: {
-                            xs: '1fr',
-                            sm: 'repeat(2, 1fr)',
-                            md: 'repeat(3, 1fr)',
-                            lg: 'repeat(4, 1fr)',
-                            xl: 'repeat(5, 1fr)'
-                        },
-                        gap: 2,
-                        mt: 1,
-                    }}>
-                        {data.userBuilds.map((build: any) => (
-                            <Box key={build.id} sx={{ pb: 4 }}>
-                                <BuildCard
-                                    build={build}
-                                    onClick={() => {
-                                        setOpenMyBuildsDialog(false);
-                                        setSelectedBuildId(build.id);
-                                    }}
-                                />
-                                <Box sx={{mt: 1, display: 'flex', justifyContent: 'center'}}>
-                                    <Button
-                                        variant="outlined"
-                                        color="error"
-                                        size="small"
-                                        startIcon={<DeleteIcon/>}
-                                        onClick={(e) => {
-                                            e.stopPropagation();
-                                            openDeleteDialog(build.id, build.name);
-                                        }}
-                                        sx={{width: '100%'}}
-                                    >
-                                        Delete
-                                    </Button>
-                                </Box>
-                            </Box>
-                        ))}
-                    </Box>
-                </DialogContent>
-                <DialogActions>
-                    <Button onClick={() => setOpenMyBuildsDialog(false)}>Close</Button>
-                </DialogActions>
-            </Dialog>
-
-            <Dialog open={openFavoritesDialog} onClose={() => setOpenFavoritesDialog(false)} maxWidth="xl" fullWidth>
-                <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
-                    All Favorited Builds
-                    <IconButton onClick={() => setOpenFavoritesDialog(false)}>
-                        <CloseIcon/>
-                    </IconButton>
-                </DialogTitle>
-                <DialogContent dividers>
-                    <Box sx={{
-                        display: 'grid',
-                        gridTemplateColumns: {
-                            xs: '1fr',
-                            sm: 'repeat(2, 1fr)',
-                            md: 'repeat(3, 1fr)',
-                            lg: 'repeat(4, 1fr)',
-                            xl: 'repeat(5, 1fr)'
-                        },
-                        gap: 2,
-                        mt: 1
-                    }}>
-                        {data.favoriteBuilds.map((build: any) => (
-                            <BuildCard
-                                key={build.id}
-                                build={build}
-                                onClick={() => {
-                                    setOpenFavoritesDialog(false);
-                                    setSelectedBuildId(build.id);
-                                }}
-                            />
-                        ))}
-                    </Box>
-                </DialogContent>
-                <DialogActions>
-                    <Button onClick={() => setOpenFavoritesDialog(false)}>Close</Button>
-                </DialogActions>
-            </Dialog>
-
-            <Dialog open={deleteDialog.open} onClose={() => setDeleteDialog({ open: false, buildId: null, buildName: '' })}>
-                <DialogTitle>Delete Build</DialogTitle>
-                <DialogContent>
-                    <Typography variant="h6" gutterBottom>{deleteDialog.buildName}</Typography>
-                    <Typography color="text.secondary">
-                        Are you sure you want to permanently delete this build? This action cannot be undone.
-                    </Typography>
-                </DialogContent>
-                <DialogActions>
-                    <Button
-                        onClick={() => setDeleteDialog({ open: false, buildId: null, buildName: '' })}
-                        disabled={deleteLoading}
-                    >
-                        Cancel
-                    </Button>
-                    <Button
-                        onClick={handleDelete}
-                        variant="contained"
-                        color="error"
-                        disabled={deleteLoading}
-                        startIcon={deleteLoading ? <CircularProgress size={20} /> : <DeleteIcon />}
-                    >
-                        {deleteLoading ? 'Deleting...' : 'Delete Build'}
-                    </Button>
-                </DialogActions>
-            </Dialog>
-
-            <BuildDetailsDialog
-                open={!!selectedBuildId}
-                buildId={selectedBuildId}
-                currentUser={data?.user?.id ? Number(data.user.id) : undefined}
-                onClose={() => {
-                    setSelectedBuildId(null);
-                    loadData();
-                }}
-                isDashboardView={true}
-            />
-        </Container>
-    );
-}
Index: pages/dashboard/user/userDashboard.telefunc.ts
===================================================================
--- pages/dashboard/user/userDashboard.telefunc.ts	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,49 +1,0 @@
-import * as drizzleQueries from "../../../database/drizzle/queries";
-import {requireUser} from "../../../server/telefunc/ctx";
-import {Abort} from "telefunc";
-
-export async function getUserInfoAndData() {
-    const { c, userId } = requireUser()
-
-    const user = await drizzleQueries.getUserProfile(c.db, userId);
-
-    if (!user) throw new Error();
-
-    const userBuilds = await drizzleQueries.getUserBuilds(c.db, userId);
-    const favoriteBuilds = await drizzleQueries.getFavoriteBuilds(c.db, userId);
-
-    return {
-        user: {
-            ...user,
-            id: userId,
-        },
-        userBuilds,
-        favoriteBuilds
-    };
-}
-
-export async function onDeleteBuild({ buildId }
-                                  : { buildId: number }) {
-    const { c, userId } = requireUser()
-
-    if (!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    const result = await drizzleQueries.deleteBuild(c.db, userId, buildId);
-
-    if(!result) throw Abort();
-
-    return { success: true };
-}
-
-export async function onEditBuild({ buildId }
-                                  : { buildId: number }) {
-    const { c, userId } = requireUser()
-
-    if(!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    const buildToEditId = await drizzleQueries.editBuild(c.db, userId, buildId);
-
-    if(!buildToEditId) throw Abort();
-
-    return buildToEditId;
-}
Index: pages/forge/+Page.tsx
===================================================================
--- pages/forge/+Page.tsx	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,714 +1,0 @@
-import React, {useState, useEffect, useMemo} from 'react';
-import {
-    Container, Paper, Typography, Box, Table, TableBody, TableCell, TableContainer, TableHead, TableRow,
-    Button, IconButton, Avatar, TextField, Chip, CircularProgress,
-    Menu, MenuItem, ListItemIcon, Dialog, DialogTitle, DialogContent, DialogActions
-} from '@mui/material';
-
-import AddIcon from '@mui/icons-material/Add';
-import RemoveIcon from '@mui/icons-material/Remove';
-import DeleteIcon from '@mui/icons-material/Delete';
-import CloseIcon from "@mui/icons-material/Close";
-import AlbumIcon from "@mui/icons-material/Album";
-import CableIcon from "@mui/icons-material/Cable";
-import RouterIcon from "@mui/icons-material/Router";
-import MemoryIcon from "@mui/icons-material/Memory";
-
-import {
-    saveBuildState,
-    onAddComponentToBuild,
-    onRemoveComponentFromBuild,
-    onDeleteBuild,
-    onGetBuildState,
-    onGetBuildComponents
-} from './forge.telefunc';
-
-import ComponentDialog from '../../components/ComponentDialog';
-import ComponentDetailsDialog from '../../components/ComponentDetailsDialog';
-import {onAddNewBuild, onGetAuthState, onGetComponentDetails} from "../+Layout.telefunc";
-import {onEditBuild} from "../dashboard/user/userDashboard.telefunc";
-import {BuildSlot, INITIAL_SLOTS} from "./types/buildTypes";
-import {renderSpecs} from "./utils/RenderSpecs";
-import {
-    getMaxRamSlots,
-    calculateUsedRamSlots,
-    calculateUsedStorageSlots
-} from "./utils/componentCalculations";
-import {Snackbar, Alert} from '@mui/material';
-
-export default function ForgePage() {
-    const [slots, setSlots] = useState<BuildSlot[]>(INITIAL_SLOTS);
-    const [buildId, setBuildId] = useState<number | null>(null);
-    const [buildName, setBuildName] = useState("");
-    const [description, setDescription] = useState("");
-    const [totalPrice, setTotalPrice] = useState(0);
-    const [isSubmitting, setIsSubmitting] = useState(false);
-
-    const [browserOpen, setBrowserOpen] = useState(false);
-    const [activeSlotId, setActiveSlotId] = useState<string | null>(null);
-    const [detailsOpen, setDetailsOpen] = useState<any>(null);
-    const [anchorEl, setAnchorEl] = useState<null | HTMLElement>(null);
-    const [submitDialogOpen, setSubmitDialogOpen] = useState(false);
-    const [tempDescription, setTempDescription] = useState("");
-    const isSubmittedRef = React.useRef(false);
-
-    const [snackbar, setSnackbar] = useState<{
-        open: boolean;
-        message: string;
-        severity: 'error' | 'warning' | 'info' | 'success';
-    }>({
-        open: false,
-        message: '',
-        severity: 'info'
-    });
-
-    useEffect(() => {
-        const price = slots.reduce((sum, slot) => {
-            const quantity = slot.component?.quantity || 1;
-            return sum + (Number(slot.component?.price) || 0) * quantity;
-        }, 0);
-        setTotalPrice(price);
-    }, [slots]);
-
-    useEffect(() => {
-        if (buildId && buildName.trim()) {
-            const timeoutId = setTimeout(() => {
-                saveBuildState({buildId, name: buildName.trim(), description}).catch(() => {
-                });
-            }, 1000);
-
-            return () => clearTimeout(timeoutId);
-        }
-    }, [buildId, buildName, description]);
-
-    useEffect(() => {
-        if (!buildId) return;
-
-        const handleBeforeUnload = () => {
-            if (!isSubmittedRef.current) {
-                onDeleteBuild({buildId}).catch(() => {
-                });
-            }
-        };
-
-        window.addEventListener('beforeunload', handleBeforeUnload);
-
-        return () => {
-            window.removeEventListener('beforeunload', handleBeforeUnload);
-            if (!isSubmittedRef.current) {
-                onDeleteBuild({buildId}).catch(() => {
-                });
-            }
-        };
-    }, [buildId]);
-
-    useEffect(() => {
-        const urlParams = new URLSearchParams(window.location.search);
-        const urlBuildId = urlParams.get('buildId');
-
-        if (urlBuildId && Number.isInteger(Number(urlBuildId)) && Number(urlBuildId) > 0) {
-            const loadBuildId = Number(urlBuildId);
-
-            onGetBuildState({buildId: loadBuildId})
-                .then((buildState) => {
-                    if (buildState) {
-                        setBuildId(loadBuildId);
-                        setBuildName(buildState.build.name);
-                        setDescription(buildState.build.description || "");
-                    }
-                })
-                .catch(() => {
-                })
-                .finally(() => {
-                    onGetBuildComponents({buildId: loadBuildId})
-                        .then(async (components) => {
-                            if (components && components.length > 0) {
-                                const detailedComponents = await Promise.all(
-                                    components.map(async (c: any) => {
-                                        const full = await onGetComponentDetails({componentId: c.id}).catch(() => null);
-                                        return full ? {
-                                            ...c,
-                                            ...full,
-                                            details: full?.details,
-                                            quantity: c.quantity || 1
-                                        } : {...c, quantity: c.quantity || 1};
-                                    })
-                                );
-
-                                const componentMap = new Map();
-                                detailedComponents.forEach((c: any) => componentMap.set(c.type, c));
-
-                                setSlots(prevSlots => prevSlots.map(slot => {
-                                    const match = componentMap.get(slot.type);
-                                    return match ? {...slot, component: match} : slot;
-                                }));
-
-                                window.history.replaceState({}, document.title, "/forge");
-                            }
-                        })
-                        .catch(() => {
-                        });
-                });
-        }
-    }, []);
-
-    const handlePickPart = (slotId: string) => {
-        setActiveSlotId(slotId);
-        setTimeout(() => setBrowserOpen(true), 0);
-    };
-
-    // fix: changed text, new catch and removed setActiveSlotId(null), so the component name doesn't disappear.
-    const handleSelectComponent = async (component: any) => {
-        if (!activeSlotId) return;
-
-        try {
-            let id = buildId;
-            if (!id) {
-                let result;
-                try {
-                    result = await onAddNewBuild({
-                        name: buildName.trim() || "New Build",
-                        description: description || "Work in progress"
-                    });
-                } catch {
-                    setSnackbar({
-                        open: true,
-                        message: 'Please log in first!',
-                        severity: 'warning'
-                    });
-                    return;
-                }
-
-                id = typeof result === 'number' ? result : (result as any)?.buildId;
-                if (!id || !Number.isInteger(id) || id <= 0) {
-                    setSnackbar({
-                        open: true,
-                        message: 'Please log in first!',
-                        severity: 'warning'
-                    });
-                    return;
-                }
-                setBuildId(id);
-            }
-
-            const full = await onGetComponentDetails({componentId: component.id}).catch(() => null);
-            const merged = full ? {...component, ...full, details: full.details, quantity: 1} : {
-                ...component,
-                quantity: 1
-            };
-
-            setSlots(prev => prev.map(slot =>
-                slot.id === activeSlotId ? {...slot, component: merged} : slot
-            ));
-            setBrowserOpen(false);
-
-            await onAddComponentToBuild({buildId: id, componentId: component.id});
-        } catch (e) {
-            setSnackbar({
-                open: true,
-                message: 'Failed to add component to build. Please try again.',
-                severity: 'error'
-            });
-        } finally {
-            // setActiveSlotId(null);
-        }
-    };
-    const handleRemovePart = async (slotId: string) => {
-        const slot = slots.find(s => s.id === slotId);
-        if (!slot?.component || !buildId) return;
-
-        const quantity = slot.component.quantity || 1;
-
-        setSlots(prev => prev.map(s =>
-            s.id === slotId ? {...s, component: null} : s
-        ));
-
-        try {
-            for (let i = 0; i < quantity; i++) {
-                await onRemoveComponentFromBuild({
-                    buildId,
-                    componentId: slot.component.id
-                });
-            }
-        } catch (e) {
-            console.error("Failed to remove component from server", e);
-        }
-    };
-
-    const handleIncrementComponent = async (slotId: string) => {
-        const slot = slots.find(s => s.id === slotId);
-        if (!slot?.component || !buildId) return;
-
-        if (slot.type === 'memory') {
-            const maxSlots = getMaxRamSlots(slots);
-            const currentUsed = calculateUsedRamSlots(slots);
-            const modules = Number(slot.component.details?.modules || slot.component.modules || 1);
-
-            if (maxSlots && (currentUsed + modules > maxSlots)) {
-                setSnackbar({
-                    open: true,
-                    message: `Cannot add more RAM. Motherboard has only ${maxSlots} slots and ${currentUsed} are currently used.`,
-                    severity: 'error'
-                });
-                return;
-            }
-        }
-
-        if (slot.type === 'storage') {
-            const formFactor = slot.component.details?.formFactor || slot.component.formFactor;
-            const maxSlots = 4;
-            const currentUsed = calculateUsedStorageSlots(slots, formFactor);
-
-            if (maxSlots && (currentUsed + 1 > maxSlots)) {
-                setSnackbar({
-                    open: true,
-                    message: `Cannot add more ${formFactor} storage. Motherboard has only ${maxSlots} slots and ${currentUsed} are currently used.`,
-                    severity: 'error'
-                });
-                return;
-            }
-        }
-
-        try {
-            await onAddComponentToBuild({buildId, componentId: slot.component.id});
-
-            setSlots(prev => prev.map(s =>
-                s.id === slotId && s.component
-                    ? {...s, component: {...s.component, quantity: (s.component.quantity || 1) + 1}}
-                    : s
-            ));
-        } catch (e) {
-            setSnackbar({
-                open: true,
-                message: 'Failed to increment component. Please try again.',
-                severity: 'error'
-            });
-        }
-    };
-
-    const handleDecrementComponent = async (slotId: string) => {
-        const slot = slots.find(s => s.id === slotId);
-        if (!slot?.component || !buildId) return;
-
-        const currentQuantity = slot.component.quantity || 1;
-        if (currentQuantity <= 1) return;
-
-        try {
-            await onRemoveComponentFromBuild({buildId, componentId: slot.component.id});
-
-            setSlots(prev => prev.map(s =>
-                s.id === slotId && s.component
-                    ? {...s, component: {...s.component, quantity: (s.component.quantity || 1) - 1}}
-                    : s
-            ));
-        } catch (e) {
-            setSnackbar({
-                open: true,
-                message: 'Failed to decrement component. Please try again.',
-                severity: 'error'
-            });
-        }
-    };
-
-    const handleAddSlot = (type: string, label: string) => {
-        const count = slots.filter(s => s.type === type).length;
-        const newSlot: BuildSlot = {
-            id: `${type}_${count + 1}`,
-            type,
-            label: `${label} ${count > 0 ? count + 1 : ''}`,
-            component: null,
-            required: false
-        };
-        setSlots(prev => [...prev, newSlot]);
-        setAnchorEl(null);
-    };
-
-    const handleDeleteSlot = (slotId: string) => {
-        const slot = slots.find(s => s.id === slotId);
-        if (slot?.component) {
-            handleRemovePart(slotId).catch(() => {
-            });
-        }
-        setSlots(prev => prev.filter(s => s.id !== slotId));
-    };
-
-
-    const [isLoggedIn, setIsLoggedIn] = useState(false);
-    useEffect(() => {
-        onGetAuthState().then(userData => {
-            setIsLoggedIn(!!userData?.userId);
-        });
-    }, []);
-
-
-    const handleSubmit = () => {
-        if (!isLoggedIn) {
-            window.location.href = '/auth/login'
-            return;
-        }
-
-        if (!buildName.trim()) {
-            setSnackbar({
-                open: true,
-                message: 'Please give your build a name!',
-                severity: 'warning'
-            });
-            return;
-        }
-
-        if (!buildId) {
-            setSnackbar({
-                open: true,
-                message: 'Please add at least one component to your build before submitting!',
-                severity: 'warning'
-            });
-            return;
-        }
-
-        setTempDescription(description || "");
-        setSubmitDialogOpen(true);
-    };
-
-    const handleSubmitConfirm = async () => {
-        if (!buildId) return;
-
-        setIsSubmitting(true);
-        setSubmitDialogOpen(false);
-
-        try {
-            await saveBuildState({buildId, name: buildName.trim(), description: tempDescription});
-            const result = await onEditBuild({buildId});
-            if (!result) throw new Error("Failed to save build");
-
-            isSubmittedRef.current = true;
-            window.location.href = "/dashboard/user";
-        } catch (e) {
-            console.error(e);
-            setSnackbar({
-                open: true,
-                message: 'Failed to save build. Please try again.',
-                severity: 'error'
-            });
-            return;
-        } finally {
-            setIsSubmitting(false);
-        }
-    };
-
-    const activeSlotType = useMemo(() => {
-        if (!activeSlotId) return null;
-        return slots.find(s => s.id === activeSlotId)?.type || null;
-    }, [slots, activeSlotId]);
-
-    return (
-        <Container maxWidth="xl" sx={{mt: 0, mb: 10}}>
-            <Paper sx={{p: 4, mb: 0, bgcolor: '#ff8201', border: '1px solid #1e1e1e', color: 'white'}}>
-                <Typography variant="h4" align="center" fontWeight="bold">Forge Your Machine</Typography>
-                <Box sx={{display: 'flex', justifyContent: 'center', mt: 2}}>
-                    <TextField
-                        label="Build Name *"
-                        value={buildName}
-                        onChange={e => setBuildName(e.target.value)}
-                        sx={{bgcolor: '#1e1e1e', textAlign: 'center', borderRadius: 1, color: 'white', width: '200px'}}
-                    />
-                </Box>
-
-            </Paper>
-
-            <TableContainer component={Paper} elevation={3}>
-                <Table sx={{minWidth: 650}}>
-                    <TableHead sx={{bgcolor: '#1e1e1e'}}>
-                        <TableRow>
-                            <TableCell sx={{color: 'white', fontWeight: 'bold'}}>Component</TableCell>
-                            <TableCell sx={{color: 'white', fontWeight: 'bold'}}>Selection & Specs</TableCell>
-                            <TableCell sx={{color: 'white', fontWeight: 'bold'}}>Price</TableCell>
-                            <TableCell sx={{color: 'white', fontWeight: 'bold'}} align="right">Actions</TableCell>
-                        </TableRow>
-                    </TableHead>
-                    <TableBody>
-                        {slots.map((slot) => (
-                            <TableRow key={slot.id} hover>
-                                <TableCell width="15%" sx={{
-                                    fontWeight: 'bold',
-                                    bgcolor: '#1e1e1e',
-                                    color: 'white',
-                                    verticalAlign: 'top',
-                                    pt: 3,
-                                    borderRight: '1px solid #333'
-                                }}>
-                                    {slot.label}
-                                    {slot.required &&
-                                        <Chip label="Required" size="small" color="error" sx={{ml: 1, height: 20}}/>}
-                                </TableCell>
-
-                                <TableCell>
-                                    {slot.component ? (
-                                        <Box sx={{display: 'flex', gap: 2, alignItems: 'flex-start'}}>
-                                            <Avatar
-                                                variant="rounded"
-                                                src={slot.component.imgUrl || slot.component.img_url}
-                                                sx={{width: 60, height: 60, bgcolor: '#eee'}}
-                                            >
-                                                {slot.component.brand?.[0]}
-                                            </Avatar>
-                                            <Box>
-                                                <Typography
-                                                    variant="subtitle1"
-                                                    fontWeight="bold"
-                                                    sx={{cursor: 'pointer', color: 'primary.main'}}
-                                                    onClick={() => setDetailsOpen(slot.component)}
-                                                >
-                                                    {slot.component.name}
-                                                </Typography>
-                                                <Box sx={{display: 'flex', flexWrap: 'wrap', gap: 1, mt: 0.5}}>
-                                                    {renderSpecs(slot.component, slot.type)}
-                                                </Box>
-                                            </Box>
-                                        </Box>
-                                    ) : (
-                                        <Button
-                                            variant="outlined"
-                                            startIcon={<AddIcon/>}
-                                            onClick={() => handlePickPart(slot.id)}
-                                            sx={{textTransform: 'none', color: '#666', borderColor: '#ccc'}}
-                                        >
-                                            Choose {slot.label}
-                                        </Button>
-                                    )}
-                                </TableCell>
-
-                                <TableCell width="10%" sx={{verticalAlign: 'top', pt: 3}}>
-                                    {slot.component ? (
-                                        <>
-                                            ${(Number(slot.component.price) * (slot.component.quantity || 1)).toFixed(2)}
-                                            {(slot.component.quantity || 1) > 1 && (
-                                                <Typography variant="caption" display="block" color="text.secondary">
-                                                    ${Number(slot.component.price).toFixed(2)} each
-                                                </Typography>
-                                            )}
-                                        </>
-                                    ) : '-'}
-                                </TableCell>
-
-                                <TableCell align="right" width="15%" sx={{verticalAlign: 'top', pt: 2}}>
-                                    <Box sx={{
-                                        display: 'flex',
-                                        gap: 1,
-                                        justifyContent: 'flex-end',
-                                        alignItems: 'center'
-                                    }}>
-                                        {slot.component && (
-                                            <>
-                                                {(slot.type === 'memory' || slot.type === 'storage') && (
-                                                    <>
-                                                        <IconButton
-                                                            size="small"
-                                                            color="primary"
-                                                            onClick={() => handleDecrementComponent(slot.id)}
-                                                            disabled={(slot.component.quantity || 1) <= 1}
-                                                            sx={{
-                                                                bgcolor: 'action.hover',
-                                                                '&:disabled': {bgcolor: 'action.disabledBackground'}
-                                                            }}
-                                                        >
-                                                            <RemoveIcon/>
-                                                        </IconButton>
-
-                                                        <Typography
-                                                            variant="body2"
-                                                            sx={{
-                                                                minWidth: '20px',
-                                                                textAlign: 'center',
-                                                                fontWeight: 'bold'
-                                                            }}
-                                                        >
-                                                            {slot.component.quantity || 1}
-                                                        </Typography>
-
-                                                        <IconButton
-                                                            size="small"
-                                                            color="primary"
-                                                            onClick={() => handleIncrementComponent(slot.id)}
-                                                            sx={{bgcolor: 'action.hover'}}
-                                                        >
-                                                            <AddIcon/>
-                                                        </IconButton>
-                                                    </>
-                                                )}
-
-                                                <IconButton
-                                                    color="error"
-                                                    onClick={() => handleRemovePart(slot.id)}
-                                                >
-                                                    <DeleteIcon/>
-                                                </IconButton>
-                                            </>
-                                        )}
-
-                                        {!slot.required && (
-                                            <IconButton
-                                                color="warning"
-                                                onClick={() => handleDeleteSlot(slot.id)}
-                                            >
-                                                <CloseIcon/>
-                                            </IconButton>
-                                        )}
-                                    </Box>
-                                </TableCell>
-                            </TableRow>
-                        ))}
-                    </TableBody>
-                </Table>
-            </TableContainer>
-
-            <Box sx={{mt: 4, display: 'flex', justifyContent: 'center'}}>
-                <Button variant="outlined" startIcon={<AddIcon/>} onClick={(e) => setAnchorEl(e.currentTarget)}
-                        sx={{mr: 2}}>
-                    Add Optional Component
-                </Button>
-                <Menu
-                    anchorEl={anchorEl}
-                    open={Boolean(anchorEl)}
-                    onClose={() => setAnchorEl(null)}
-                    anchorReference="none"
-                    sx={{
-                        display: 'flex',
-                        alignItems: 'center',
-                        justifyContent: 'center',
-                    }}
-                    slotProps={{
-                        paper: {
-                            sx: {
-                                position: 'absolute',
-                                top: '46%',
-                                // left: '50%',
-                                // transform: 'translate(50%, +50%)',
-                            }
-                        }
-                    }}
-                >
-                    {/*Removed RAM & Storage from optional components*/}
-                    <Typography sx={{px: 2, py: 1, display: 'block', color: 'text.secondary'}}>
-                        Accessories
-                    </Typography>
-                    <MenuItem onClick={() => handleAddSlot('optical_drive', 'Optical Drive')}>
-                        <ListItemIcon><AlbumIcon/></ListItemIcon>
-                        Optical Drive
-                    </MenuItem>
-                    <MenuItem onClick={() => handleAddSlot('cables', 'Cable')}>
-                        <ListItemIcon><CableIcon/></ListItemIcon>
-                        Cables
-                    </MenuItem>
-
-                    <Typography sx={{px: 2, py: 1, display: 'block', color: 'text.secondary', mt: 1}}>
-                        Expansion Cards
-                    </Typography>
-                    <MenuItem onClick={() => handleAddSlot('memory_card', 'Storage Card')}>
-                        <ListItemIcon><MemoryIcon/></ListItemIcon>
-                        Storage Card
-                    </MenuItem>
-                    <MenuItem onClick={() => handleAddSlot('sound_card', 'Sound Card')}>
-                        <ListItemIcon><RouterIcon/></ListItemIcon>
-                        Sound Card
-                    </MenuItem>
-                    <MenuItem onClick={() => handleAddSlot('network_card', 'Network Card')}>
-                        <ListItemIcon><RouterIcon/></ListItemIcon>
-                        Network Card
-                    </MenuItem>
-                    <MenuItem onClick={() => handleAddSlot('network_adapter', 'WiFi Adapter')}>
-                        <ListItemIcon><RouterIcon/></ListItemIcon>
-                        WiFi Adapter
-                    </MenuItem>
-                </Menu>
-            </Box>
-
-            <Box sx={{mt: 4, p: 4, bgcolor: '#1e1e1e', textAlign: 'center', borderRadius: 2}}>
-                <Typography variant="h5" sx={{mb: 2, fontWeight: 'bold', color: 'white'}}>
-                    Total: ${totalPrice.toFixed(2)}
-                </Typography>
-                <Button
-                    variant="contained"
-                    color="primary"
-                    size="large"
-                    onClick={handleSubmit}
-                    disabled={isSubmitting}
-                >
-                    {isSubmitting ? <CircularProgress size={24}/> : 'Save Build'}
-                </Button>
-            </Box>
-
-            <ComponentDialog
-                open={browserOpen}
-                category={activeSlotType}
-                onClose={() => {
-                    setBrowserOpen(false);
-                    setActiveSlotId(null);
-                }}
-                mode="forge"
-                onSelect={handleSelectComponent}
-                currentBuildId={buildId}
-            />
-
-            <ComponentDetailsDialog
-                open={!!detailsOpen}
-                component={detailsOpen}
-                onClose={() => setDetailsOpen(null)}
-            />
-
-            <Dialog open={submitDialogOpen} onClose={() => setSubmitDialogOpen(false)} maxWidth="sm" fullWidth>
-                <DialogTitle sx={{bgcolor: '#ff8201', color: 'white', fontWeight: 'bold'}}>
-                    Build Description
-                </DialogTitle>
-                <DialogContent sx={{p: 3}}>
-                    <Typography variant="body1" sx={{mb: 2, color: 'text.secondary'}}>
-                        Add some notes about your build (optional):
-                    </Typography>
-                    <TextField
-                        fullWidth
-                        multiline
-                        rows={4}
-                        placeholder="e.g. Workstation monster, great for crunching numbers!"
-                        value={tempDescription}
-                        onChange={(e) => setTempDescription(e.target.value)}
-                        variant="outlined"
-                    />
-                </DialogContent>
-                <DialogActions sx={{p: 3, pt: 0}}>
-                    <Button onClick={() => setSubmitDialogOpen(false)}>
-                        Cancel
-                    </Button>
-                    <Button
-                        variant="contained"
-                        color="primary"
-                        onClick={handleSubmitConfirm}
-                        disabled={isSubmitting}
-                    >
-                        {isSubmitting ? (
-                            <>
-                                <CircularProgress size={20} sx={{mr: 1}}/>
-                                Submitting...
-                            </>
-                        ) : (
-                            'Submit Build'
-                        )}
-                    </Button>
-                </DialogActions>
-            </Dialog>
-            <Snackbar
-                open={snackbar.open}
-                autoHideDuration={4000}
-                onClose={() => setSnackbar(prev => ({...prev, open: false}))}
-                anchorOrigin={{vertical: 'bottom', horizontal: 'center'}}
-            >
-                <Alert
-                    onClose={() => setSnackbar(prev => ({...prev, open: false}))}
-                    severity={snackbar.severity}
-                    variant="filled"
-                    sx={{width: '100%'}}
-                >
-                    {snackbar.message}
-                </Alert>
-            </Snackbar>
-        </Container>
-    );
-}
Index: pages/forge/forge.telefunc.ts
===================================================================
--- pages/forge/forge.telefunc.ts	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,90 +1,0 @@
-import * as drizzleQueries from "../../database/drizzle/queries";
-import {ctx, getAuthState, requireUser} from "../../server/telefunc/ctx";
-import {Abort} from "telefunc";
-import type {Database} from "../../database/drizzle/db";
-import {removeComponentFromBuild} from "../../database/drizzle/queries";
-
-export async function onRemoveComponentFromBuild({ buildId, componentId }
-                                                 : { buildId: number, componentId: number }) {
-    const { c, userId } = requireUser()
-
-    const result = await drizzleQueries.removeComponentFromBuild(c.db, userId, buildId, componentId);
-
-    if(!result) throw Abort();
-
-    return { success: true };
-}
-
-export async function onAddComponentToBuild({ buildId, componentId }: { buildId: number, componentId: number }) {
-    const { c, userId } = requireUser()
-
-    if(!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-    if(!Number.isInteger(componentId) || componentId <= 0) throw Abort();
-
-    const result = await drizzleQueries.addComponentToBuild(c.db, userId, buildId, componentId);
-
-    if(!result) throw Abort();
-
-    return { success: true };
-}
-
-export async function onDeleteBuild({ buildId }: { buildId: number }) {
-    const { c, userId } = requireUser()
-
-    const result = await drizzleQueries.deleteBuild(c.db, userId, buildId);
-    if(!result) throw Abort();
-
-    return { success: true };
-}
-
-export async function onGetBuildComponents({ buildId }
-                                           : { buildId: number }) {
-    const { c, userId } = requireUser()
-
-    if(!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    const buildComponents = await drizzleQueries.getBuildComponents(c.db, buildId);
-
-    if(!buildComponents) throw Abort();
-
-    return buildComponents;
-}
-
-export async function onGetCompatibleComponents({ buildId, componentType, limit, sort }
-                                                : { buildId: number, componentType: string, limit?: number, sort?: string }) {
-    const { c, userId } = requireUser()
-
-    if(!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    const compatibleComponents = await drizzleQueries.getCompatibleComponents(c.db, buildId, componentType, limit, sort);
-
-    if(!compatibleComponents) throw Abort();
-
-    return compatibleComponents;
-}
-
-export async function onGetBuildState({ buildId }
-                                      :{ buildId: number }) {
-    const { c, userId } = requireUser()
-
-    if(!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    const buildState = await drizzleQueries.getBuildState(c.db, userId, buildId);
-
-    if(!buildState) throw Abort();
-
-    return buildState;
-}
-
-export async function saveBuildState({ buildId, name, description }
-                                     :{ buildId: number, name: string, description: string }) {
-    const { c, userId } = requireUser()
-
-    if(!Number.isInteger(buildId) || buildId <= 0) throw Abort();
-
-    const result = await drizzleQueries.saveBuildState(c.db, userId, buildId, name, description);
-
-    if(!result) throw Abort();
-
-    return { success: true };
-}
Index: pages/forge/types/buildTypes.ts
===================================================================
--- pages/forge/types/buildTypes.ts	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,18 +1,0 @@
-export type BuildSlot = {
-    id: string;
-    type: string;
-    label: string;
-    component: any | null;
-    required: boolean;
-};
-
-export const INITIAL_SLOTS: BuildSlot[] = [
-    {id: 'cpu', type: 'cpu', label: 'CPU', component: null, required: true},
-    {id: 'cooler', type: 'cooler', label: 'CPU Cooler', component: null, required: true},
-    {id: 'motherboard', type: 'motherboard', label: 'Motherboard', component: null, required: true},
-    {id: 'memory_1', type: 'memory', label: 'Memory', component: null, required: true},
-    {id: 'gpu', type: 'gpu', label: 'Video Card', component: null, required: true},
-    {id: 'storage_1', type: 'storage', label: 'Storage', component: null, required: true},
-    {id: 'powersupply', type: 'power_supply', label: 'Power Supply', component: null, required: true},
-    {id: 'case', type: 'case', label: 'Case', component: null, required: true},
-];
Index: pages/forge/utils/RenderSpecs.tsx
===================================================================
--- pages/forge/utils/RenderSpecs.tsx	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,97 +1,0 @@
-import {Chip, Typography} from '@mui/material';
-import React from "react";
-
-export function renderSpecs(c: any, type: string) {
-    if (!c) return null;
-    const data = {...c, ...(c.details || {})};
-    const chipStyle = {height: 24, fontSize: '0.75rem', bgcolor: 'rgba(0,0,0,0.05)'};
-    const specs: string[] = [];
-    const val = (k: string) => data[k] || data[k.toLowerCase()] || data[k.replace('_', '')];
-
-    switch (type) {
-
-        case 'cpu':
-            if (val('socket')) specs.push(`Socket: ${val('socket')}`);
-            if (val('cores')) specs.push(`${val('cores')} Cores / ${val('threads')} Threads`);
-            const base = data.baseclock || data.baseClock || data.base_clock;
-            const boost = data.boostclock || data.boostClock || data.boost_clock;
-            if (base) specs.push(`Base Clock Speed: ${base}GHz`);
-            if (boost) specs.push(`Boost Clock Speed: ${boost}GHz`);
-            break;
-        case 'gpu':
-            if (val('vram')) specs.push(`VRAM: ${val('vram')}GB`);
-            if (val('tdp')) specs.push(`Card TDP: ${val('tdp')}W`);
-            if (val('length')) specs.push(`Length: ${val('length')}mm`);
-            if (val('baseClock')) specs.push(`Base Clock Speed: ${val('baseClock')}GHz`);
-            if (val('boostClock')) specs.push(`Boost Clock Speed: ${val('boostClock')}GHz`);
-            break;
-        case 'motherboard':
-            if (val('socket')) specs.push(`Socket: ${val('socket')}`);
-            if (val('formFactor')) specs.push(`Form Factor: ${val('formFactor')}`);
-            if (val('ramType')) specs.push(`RAM Type: ${val('ramType')}`);
-            if (val('numRamSlots')) specs.push(`RAM Slots: ${val('numRamSlots')}`);
-            if (val('maxRamCapacity')) specs.push(`Max Ram Caacity: ${val('maxRamCapacity')}GB`);
-            break;
-        case 'memory':
-            if (val('capacity')) specs.push(`Size Per Stick: ${val('capacity')}GB`);
-            if (val('type')) specs.push(`RAM Type: ${val('type')}`);
-            if (val('speed')) specs.push(`RAM Speed: ${val('speed')} MHz`);
-            if (val('modules')) specs.push(`Modules: ${val('modules')}`);
-            break;
-        case 'storage':
-            if (val('capacity')) specs.push(`Capacity: ${val('capacity')}GB`);
-            if (val('type')) specs.push(`Type: ${val('type')}`);
-            break;
-        case 'power_supply':
-            if (val('wattage')) specs.push(`Wattage: ${val('wattage')}W`);
-            if (val('type')) specs.push(`Type: ${val('type')}`);
-            if (val('formFactor')) specs.push(`Form Factor: ${val('formFactor')}`);
-            break;
-        case 'case':
-            if (val('gpuMaxLength')) specs.push(`Max GPU Length: ${val('gpuMaxLength')}mm`);
-            if (val('coolerMaxHeight')) specs.push(`Max CPU Cooler Height: ${val('coolerMaxHeight')}mm`);
-            break;
-        case 'cooler':
-            if (val('type')) specs.push(`Cooler Type: ${val('type')} Cooler`);
-            if (val('height')) specs.push(`Height: ${val('height')}mm`);
-            if (val('maxTdpSupported')) specs.push(`Max TDP: ${val('maxTdpSupported')}W`);
-            break;
-        case 'network_card':
-            if (val('interface')) specs.push(`Interface: ${val('interface')}`);
-            if (val('numPorts')) specs.push(`Number of Ports: ${val('numPorts')}`);
-            if (val('speed')) specs.push(`Speed: ${val('speed')}Mbps`);
-            break;
-        case 'network_adapter':
-            if (val('interface')) specs.push(`Interface: ${val('interface')}`);
-            if (val('numAntennas')) specs.push(`Number of Antennas: ${val('numAntennas')}`);
-            if (val('wifiVersion')) specs.push(`Wi-Fi Version: ${val('wifiVersion')}`);
-            break;
-        case 'sound_card':
-            if (val('interface')) specs.push(`Interface: ${val('interface')}`);
-            if (val('chipset')) specs.push(`Chipset: ${val('chipset')}`);
-            if (val('channel')) specs.push(`Channels: ${val('channel')}`);
-            break;
-        case 'memory_card':
-            if (val('interface')) specs.push(`Interface: ${val('interface')}`);
-            if (val('numSlots')) specs.push(`Number of Slots: ${val('numSlots')}`);
-            break;
-        case 'optical_drive':
-            if (val('interface')) specs.push(`Interface: ${val('interface')}`);
-            if (val('type')) specs.push(`Type: ${val('type')}`);
-            if (val('formFactor')) specs.push(`Form Factor: ${val('formFactor')}`);
-            break;
-        case 'cables':
-            if (val('type')) specs.push(`Type of Cables: ${val('type')}`);
-            if (val('lengthCm')) specs.push(`Length: ${val('lengthCm')}cm`);
-            break;
-        default:
-            if (data.brand) specs.push(data.brand);
-    }
-
-    if (specs.length === 0) {
-        if (data.brand) return <Chip label={data.brand} sx={chipStyle}/>;
-        return <Typography variant="caption" color="text.secondary">...</Typography>;
-    }
-
-    return specs.map((label, i) => <Chip key={i} label={label} sx={chipStyle}/>);
-}
Index: pages/forge/utils/componentCalculations.ts
===================================================================
--- pages/forge/utils/componentCalculations.ts	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ 	(revision )
@@ -1,54 +1,0 @@
-// Helper Functions
-import {BuildSlot} from "../types/buildTypes";
-
-export function calculateUsedRamSlots(slots: BuildSlot[]): number {
-    return slots
-        .filter(s => s.type === 'memory' && s.component)
-        .reduce((sum, s) => {
-            const modules = Number(s.component?.details?.modules || s.component?.modules || 1);
-            const quantity = Number(s.component?.quantity || 1);
-            return sum + (modules * quantity);
-        }, 0);
-}
-
-export function getMaxRamSlots(slots: BuildSlot[]): number | null {
-    const mobo = slots.find(s => s.type === 'motherboard' && s.component);
-    if (!mobo?.component?.details?.numRamSlots) return null;
-    return Number(mobo.component.details.numRamSlots);
-}
-
-export function calculateUsedStorageSlots(slots: BuildSlot[], formFactor: string): number {
-    return slots
-        .filter(s => s.type === 'storage' && s.component)
-        .reduce((sum, s) => {
-            const componentFormFactor = s.component?.details?.formFactor || s.component?.details?.form_factor || s.component?.formFactor;
-            if (componentFormFactor?.trim().toLowerCase() === formFactor?.trim().toLowerCase()) {
-                return sum + Number(s.component?.quantity || 1);
-            }
-            return sum;
-        }, 0);
-}
-
-export function getMaxStorageSlots(slots: BuildSlot[], formFactor: string): number | null {
-    const pcCase = slots.find(s => s.type === 'case' && s.component);
-    if (!pcCase?.component?.details?.storageFormFactors) return null;
-
-    const storageFormFactors = pcCase.component.details.storageFormFactors;
-
-    if (!Array.isArray(storageFormFactors)) {
-        return null;
-    }
-
-    const storageFF = storageFormFactors.find((sf: any) => {
-        const sfFormFactor = sf.formFactor || sf.form_factor;
-        return sfFormFactor?.trim().toLowerCase() === formFactor?.trim().toLowerCase();
-    });
-
-    if (!storageFF) {
-        return null;
-    }
-
-    const numSlots = storageFF.numSlots || storageFF.num_slots;
-
-    return Number(numSlots) || null;
-}
Index: pages/index/+Page.tsx
===================================================================
--- pages/index/+Page.tsx	(revision ff3a6146e85f77e90dc322a0ad0c9d9eb048c629)
+++ pages/index/+Page.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -1,210 +1,16 @@
-import React, {useEffect, useState} from 'react';
-import {
-    Container, Box, Typography, Button, IconButton, Dialog, DialogTitle, DialogContent
-} from '@mui/material';
-import CloseIcon from '@mui/icons-material/Close';
-import AutoFixHighIcon from '@mui/icons-material/AutoFixHigh';
-import ListIcon from '@mui/icons-material/List';
+import { Counter } from "./Counter.js";
 
-import BuildDetailsDialog from '../../components/BuildDetailsDialog';
-import BuildCard from '../../components/BuildCard';
-
-import {onGetApprovedBuilds, onGetAuthState} from '../+Layout.telefunc';
-
-export default function HomePage() {
-    const [data, setData] = useState<any>(null);
-    const [allRanked, setAllRanked] = useState<any[]>([]);
-
-    const [selectedBuildId, setSelectedBuildId] = useState<number | null>(null);
-    const [openRankedPopup, setOpenRankedPopup] = useState(false);
-
-    useEffect(() => {
-        async function loadSite() {
-            try {
-                const [
-                    authData,
-                    highestRankedBuilds,
-                    communityBuilds,
-                    fullRankedList
-                ] = await Promise.all([
-                    onGetAuthState(),
-                    onGetApprovedBuilds({limit: 5, sort: 'rating_desc'}),
-                    onGetApprovedBuilds({limit: 12}),
-                    onGetApprovedBuilds({limit: 20, sort: 'rating_desc'})
-                ]);
-
-                setData({
-                    isLoggedIn: authData.isLoggedIn,
-                    userId: authData.userId,
-                    prebuilts: highestRankedBuilds,
-                    communityBuilds: communityBuilds
-                });
-                setAllRanked(fullRankedList);
-            } catch (error) {
-                console.error("Error loading homepage data:", error);
-            }
-        }
-
-        void loadSite();
-    }, []);
-
-    if (!data) return <Box sx={{p: 10, textAlign: 'center'}}>Loading Forge...</Box>;
-
-    return (
-        <Box>
-            <Box sx={{
-                position: 'relative', height: '500px',
-                display: 'flex', alignItems: 'center', justifyContent: 'center', color: 'white',
-                '&::before': {
-                    content: '""', position: 'absolute', top: 0, left: 0, width: '100%', height: '100%',
-                    backgroundColor: 'rgba(0,0,0,0.6)'
-                }
-            }}>
-                <Box sx={{position: 'relative', textAlign: 'center', zIndex: 1, p: 2}}>
-                    <Typography variant="h2" fontWeight="bold" gutterBottom>Forge Your Ultimate Machine</Typography>
-                    <Typography variant="h5" sx={{maxWidth: '800px', mx: 'auto', mb: 1}}>
-                        Build, share, discuss, and discover custom PC configurations.
-                    </Typography>
-                    <Button variant="contained" size="large" href="/forge" startIcon={<AutoFixHighIcon/>}
-                            sx={{fontSize: '1.2rem', px: 4, py: 1.5, mt: 2}}>
-                        Start Forging
-                    </Button>
-                </Box>
-            </Box>
-
-            <Container maxWidth="xl" sx={{mt: 6, mb: 10}}>
-                <Box sx={{
-                    mb: 2, borderLeft: '5px solid #ff8201', pl: 1,
-                    display: 'flex', justifyContent: 'space-between', alignItems: 'end'
-                }}>
-                    <Box>
-                        <Typography variant="h4" fontWeight="bold">Hall of Fame</Typography>
-                        <Typography variant="subtitle1" color="text.secondary">
-                            The highest rated configurations from across the community.
-                        </Typography>
-                    </Box>
-                    <Button variant="outlined" startIcon={<ListIcon/>} onClick={() => setOpenRankedPopup(true)}>
-                        Show All Top Ranked
-                    </Button>
-                </Box>
-                <Box
-                    sx={{
-                        display: 'grid',
-                        gridTemplateColumns: {
-                            xs: '1fr',
-                            sm: 'repeat(2, 1fr)',
-                            md: 'repeat(3, 1fr)',
-                            lg: 'repeat(4, 1fr)',
-                            xl: 'repeat(5, 1fr)',
-                        },
-                        gap: 3,
-                        width: '100%',
-                        mb: 8
-                    }}
-                >
-                    {data.prebuilts.map((build: any) => (
-                        <BuildCard
-                            key={build.id}
-                            build={build}
-                            onClick={() => setSelectedBuildId(build.id)}
-                        />
-                    ))}
-                </Box>
-
-                <Box sx={{
-                    mb: 2, mt: 2, borderLeft: '5px solid #ff8201', pl: 1,
-                }}>
-                    <Typography variant="h4" fontWeight="bold" color="text.primary">Community Forge</Typography>
-                    <Typography variant="subtitle1" color="text.secondary" sx={{mb: 2}}>Fresh builds from users around the world.</Typography>
-                </Box>
-                <Box
-                    sx={{
-                        display: 'grid',
-                        gridTemplateColumns: {
-                            xs: '1fr',
-                            sm: 'repeat(2, 1fr)',
-                            md: 'repeat(3, 1fr)',
-                            lg: 'repeat(4, 1fr)',
-                            xl: 'repeat(5, 1fr)',
-                        },
-                        gap: 3,
-                        width: '100%',
-                    }}
-                >
-                    {data.communityBuilds.map((build: any) => (
-                        <BuildCard
-                            key={build.id}
-                            build={build}
-                            onClick={() => setSelectedBuildId(build.id)}
-                        />
-                    ))}
-                </Box>
-
-                <Box sx={{display: 'flex', justifyContent: 'center', mt: 6}}>
-                    <Button variant="outlined" size="large" href="/completed-builds">View All Community Builds</Button>
-                </Box>
-            </Container>
-
-            <BuildDetailsDialog
-                open={!!selectedBuildId}
-                buildId={selectedBuildId}
-                currentUser={data.userId}
-                onClose={() => setSelectedBuildId(null)}
-            />
-
-            <Dialog open={openRankedPopup} onClose={() => setOpenRankedPopup(false)} maxWidth="xl" fullWidth scroll="paper">
-                <DialogTitle sx={{display: 'flex', justifyContent: 'space-between', alignItems: 'center'}}>
-                    Hall of Fame (Top Rated)
-                    <IconButton onClick={() => setOpenRankedPopup(false)}><CloseIcon/></IconButton>
-                </DialogTitle>
-                <DialogContent dividers sx={{p: 3}}>
-                    <Box
-                        sx={{
-                            display: 'grid',
-                            gridTemplateColumns: {
-                                xs: '1fr',
-                                sm: 'repeat(2, 1fr)',
-                                md: 'repeat(3, 1fr)',
-                                lg: 'repeat(4, 1fr)',
-                                xl: 'repeat(5, 1fr)',
-                            },
-                            gap: 3,
-                            width: '100%'
-                        }}
-                    >
-                        {allRanked.map((build: any, index: number) => (
-                            <Box key={`ranked-${build.id}`} sx={{position: 'relative', width: '100%'}}>
-                                <Box sx={{
-                                    position: 'absolute',
-                                    top: -10,
-                                    left: -10,
-                                    zIndex: 1,
-                                    width: 35,
-                                    height: 35,
-                                    borderRadius: '50%',
-                                    bgcolor: index < 3 ? '#ff8201' : 'grey.800',
-                                    color: 'white',
-                                    display: 'flex',
-                                    alignItems: 'center',
-                                    justifyContent: 'center',
-                                    fontWeight: 'bold',
-                                    border: '2px solid white',
-                                    boxShadow: 2,
-                                }}>
-                                    #{index + 1}
-                                </Box>
-                                <BuildCard
-                                    build={build}
-                                    onClick={() => {
-                                        setOpenRankedPopup(false);
-                                        setSelectedBuildId(build.id);
-                                    }}
-                                />
-                            </Box>
-                        ))}
-                    </Box>
-                </DialogContent>
-            </Dialog>
-        </Box>
-    );
+export default function Page() {
+  return (
+    <>
+      <h1>My Vike app</h1>
+      <p>This page is:</p>
+      <ul>
+        <li>Rendered to HTML.</li>
+        <li>
+          Interactive. <Counter />
+        </li>
+      </ul>
+    </>
+  );
 }
Index: pages/index/Counter.tsx
===================================================================
--- pages/index/Counter.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/index/Counter.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,11 @@
+import { useState } from "react";
+
+export function Counter() {
+  const [count, setCount] = useState(0);
+
+  return (
+    <button type="button" onClick={() => setCount((count) => count + 1)}>
+      Counter {count}
+    </button>
+  );
+}
Index: pages/star-wars/@id/+Page.tsx
===================================================================
--- pages/star-wars/@id/+Page.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/star-wars/@id/+Page.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,16 @@
+import { useData } from "vike-react/useData";
+import type { Data } from "./+data.js";
+
+export default function Page() {
+  const { movie } = useData<Data>();
+  return (
+    <>
+      <h1>{movie.title}</h1>
+      Release Date: {movie.release_date}
+      <br />
+      Director: {movie.director}
+      <br />
+      Producer: {movie.producer}
+    </>
+  );
+}
Index: pages/star-wars/@id/+data.ts
===================================================================
--- pages/star-wars/@id/+data.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/star-wars/@id/+data.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,31 @@
+// https://vike.dev/data
+
+import type { PageContextServer } from "vike/types";
+import { useConfig } from "vike-react/useConfig";
+import type { MovieDetails } from "../types.js";
+
+export type Data = Awaited<ReturnType<typeof data>>;
+
+export async function data(pageContext: PageContextServer) {
+  // https://vike.dev/useConfig
+  const config = useConfig();
+
+  const response = await fetch(`https://brillout.github.io/star-wars/api/films/${pageContext.routeParams.id}.json`);
+  let movie = (await response.json()) as MovieDetails;
+
+  config({
+    // Set <title>
+    title: movie.title,
+  });
+
+  // We remove data we don't need because the data is passed to
+  // the client; we should minimize what is sent over the network.
+  movie = minimize(movie);
+
+  return { movie };
+}
+
+function minimize(movie: MovieDetails): MovieDetails {
+  const { id, title, release_date, director, producer } = movie;
+  return { id, title, release_date, director, producer };
+}
Index: pages/star-wars/index/+Page.tsx
===================================================================
--- pages/star-wars/index/+Page.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/star-wars/index/+Page.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,21 @@
+import { useData } from "vike-react/useData";
+import type { Data } from "./+data.js";
+
+export default function Page() {
+  const { movies } = useData<Data>();
+  return (
+    <>
+      <h1>Star Wars Movies</h1>
+      <ol>
+        {movies.map(({ id, title, release_date }) => (
+          <li key={id}>
+            <a href={`/star-wars/${id}`}>{title}</a> ({release_date})
+          </li>
+        ))}
+      </ol>
+      <p>
+        Source: <a href="https://brillout.github.io/star-wars">brillout.github.io/star-wars</a>.
+      </p>
+    </>
+  );
+}
Index: pages/star-wars/index/+data.ts
===================================================================
--- pages/star-wars/index/+data.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/star-wars/index/+data.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,32 @@
+// https://vike.dev/data
+
+import { useConfig } from "vike-react/useConfig";
+import type { Movie, MovieDetails } from "../types.js";
+
+export type Data = Awaited<ReturnType<typeof data>>;
+
+export async function data() {
+  // https://vike.dev/useConfig
+  const config = useConfig();
+
+  const response = await fetch("https://brillout.github.io/star-wars/api/films.json");
+  const moviesData = (await response.json()) as MovieDetails[];
+
+  config({
+    // Set <title>
+    title: `${moviesData.length} Star Wars Movies`,
+  });
+
+  // We remove data we don't need because the data is passed to the client; we should
+  // minimize what is sent over the network.
+  const movies = minimize(moviesData);
+
+  return { movies };
+}
+
+function minimize(movies: MovieDetails[]): Movie[] {
+  return movies.map((movie) => {
+    const { title, release_date, id } = movie;
+    return { title, release_date, id };
+  });
+}
Index: pages/star-wars/types.ts
===================================================================
--- pages/star-wars/types.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/star-wars/types.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,10 @@
+export type Movie = {
+  id: string;
+  title: string;
+  release_date: string;
+};
+
+export type MovieDetails = Movie & {
+  director: string;
+  producer: string;
+};
Index: pages/todo/+Page.tsx
===================================================================
--- pages/todo/+Page.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/todo/+Page.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,10 @@
+import { TodoList } from "./TodoList.js";
+
+export default function Page() {
+  return (
+    <>
+      <h1>To-do List</h1>
+      <TodoList />
+    </>
+  );
+}
Index: pages/todo/+config.ts
===================================================================
--- pages/todo/+config.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/todo/+config.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,3 @@
+export const config = {
+  prerender: false,
+};
Index: pages/todo/+data.ts
===================================================================
--- pages/todo/+data.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/todo/+data.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,12 @@
+// https://vike.dev/data
+
+import * as drizzleQueries from "../../database/drizzle/queries/todos";
+import type { PageContextServer } from "vike/types";
+
+export type Data = Awaited<ReturnType<typeof data>>;
+
+export async function data(_pageContext: PageContextServer) {
+  const todoItemsInitial = await drizzleQueries.getAllTodos(_pageContext.db);
+
+  return { todoItemsInitial };
+}
Index: pages/todo/TodoList.telefunc.ts
===================================================================
--- pages/todo/TodoList.telefunc.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/todo/TodoList.telefunc.ts	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,9 @@
+// We use Telefunc (https://telefunc.com) for data mutations.
+
+import * as drizzleQueries from "../../database/drizzle/queries/todos";
+import { getContext } from "telefunc";
+
+export async function onNewTodo({ text }: { text: string }) {
+  const context = getContext();
+  await drizzleQueries.insertTodo(context.db, text);
+}
Index: pages/todo/TodoList.tsx
===================================================================
--- pages/todo/TodoList.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
+++ pages/todo/TodoList.tsx	(revision 8ee45534cd667e6cced2ed96968c95d8de3b1029)
@@ -0,0 +1,36 @@
+import type { Data } from "./+data";
+import { onNewTodo } from "./TodoList.telefunc";
+import { useState } from "react";
+import { useData } from "vike-react/useData";
+
+export function TodoList() {
+  const { todoItemsInitial } = useData<Data>();
+  const [todoItems, setTodoItems] = useState<{ text: string }[]>(todoItemsInitial);
+  const [newTodo, setNewTodo] = useState("");
+  return (
+    <>
+      <ul>
+        {todoItems.map((todoItem, index) => (
+          // biome-ignore lint: example
+          <li key={index}>{todoItem.text}</li>
+        ))}
+      </ul>
+      <div>
+        <form
+          onSubmit={async (ev) => {
+            ev.preventDefault();
+
+            const text = newTodo;
+            setTodoItems((prev) => [...prev, { text }]);
+            setNewTodo("");
+
+            await onNewTodo({ text });
+          }}
+        >
+          <input type="text" onChange={(ev) => setNewTodo(ev.target.value)} value={newTodo} />
+          <button type="submit">Add to-do</button>
+        </form>
+      </div>
+    </>
+  );
+}
