diff --git a/.env.example b/.env.example
new file mode 100644
index 0000000..d0531cc
--- /dev/null
+++ b/.env.example
@@ -0,0 +1,56 @@
+# =============================================================================
+# Environment Configuration
+# =============================================================================
+# Copy this file to .env.local and fill in your actual values
+# Never commit .env.local to version control
+# =============================================================================
+
+# -----------------------------------------------------------------------------
+# SYSTEM & DEPLOYMENT
+# -----------------------------------------------------------------------------
+NIXPACKS_NODE_VERSION=22
+
+# -----------------------------------------------------------------------------
+# DATABASE
+# -----------------------------------------------------------------------------
+# PostgreSQL connection string
+DATABASE_URL="postgresql://user:password@localhost:5432/grounds"
+
+# -----------------------------------------------------------------------------
+# APPLICATION URLS
+# -----------------------------------------------------------------------------
+# Base URL of the application (client-accessible)
+NEXT_PUBLIC_SITE_URL="https://localhost:3000"
+
+# Auth callback URL
+NEXT_PUBLIC_APP_URL="https://localhost:3000"
+
+# -----------------------------------------------------------------------------
+# BETTER AUTH
+# -----------------------------------------------------------------------------
+# Better Auth configuration
+# URL must match your app URL (with protocol)
+BETTER_AUTH_URL="https://localhost:3000"
+
+# Secret key for signing tokens (generate with: openssl rand -base64 32)
+BETTER_AUTH_SECRET="your-secret-key-here"
+
+# -----------------------------------------------------------------------------
+# AUTHENTICATION
+# -----------------------------------------------------------------------------
+# Google OAuth credentials (required)
+GOOGLE_CLIENT_ID=""
+GOOGLE_CLIENT_SECRET=""
+
+# Discord OAuth credentials (required)
+DISCORD_CLIENT_ID=""
+DISCORD_CLIENT_SECRET=""
+
+# -----------------------------------------------------------------------------
+# STORAGE (S3 COMPATIBLE)
+# -----------------------------------------------------------------------------
+# S3-compatible credentials for file storage
+S3_ACCESS_KEY_ID=""
+S3_SECRET_ACCESS_KEY=""
+S3_BUCKET_NAME=""
+S3_PUBLIC_URL=""
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index 5ef6a52..7b8da95 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,6 +32,7 @@ yarn-error.log*
# env files (can opt-in for committing if needed)
.env*
+!.env.example
# vercel
.vercel
diff --git a/README.md b/README.md
index abe67ea..bd383f4 100644
--- a/README.md
+++ b/README.md
@@ -2,11 +2,11 @@
An open-source, community-driven database for Steam Deck (OLED & LCD) and Steam Machine compatibility, performance metrics, and settings.
-[//]: # "Add shields here if available: e.g., license, contributors, last commit"
+> **Note:** DeckyVault is currently under active development. The site is live at [deckyvault.xyz](https://deckyvault.xyz) but features are being built incrementally. Stay tuned!
## Why DeckyVault?
-Gaming on the Steam Deck is incredible, but finding reliable, detailed answers about whether a game will run well—or how to optimize it—can be frustrating. Existing resources are often fragmented, outdated, or lack the depth the community needs.
+Gaming on the Steam Deck is incredible, but finding reliable, detailed answers about whether a game will run well — or how to optimize it — can be frustrating. Existing resources are often fragmented, outdated, or lack the depth the community needs.
**DeckyVault** aims to solve this by being the definitive, community-first hub for Steam Deck performance data.
@@ -33,36 +33,49 @@ Gaming on the Steam Deck is incredible, but finding reliable, detailed answers a
## Tech Stack
-- **[Next.js](https://nextjs.org)** — React framework for production
-- **[React](https://react.dev)** — UI library
+- **[Next.js 16](https://nextjs.org)** — React framework (App Router)
+- **[React 19](https://react.dev)** — UI library
- **[TypeScript](https://www.typescriptlang.org)** — Type safety
-- **[Tailwind CSS](https://tailwindcss.com)** — Utility-first styling *(verify in your local setup)*
+- **[Tailwind CSS v4](https://tailwindcss.com)** — Utility-first styling
+- **[Elysia](https://elysiajs.com)** — Backend API framework
+- **[Drizzle ORM](https://orm.drizzle.team)** — Type-safe database queries
+- **[PostgreSQL](https://www.postgresql.org)** — Primary database
+- **[better-auth](https://better-auth.com)** — Authentication (Google & Discord OAuth)
+- **[Tiptap](https://tiptap.dev)** — Rich text editor
+- **[Motion](https://motion.dev)** — Animations
+- **[AWS S3](https://aws.amazon.com/s3/)** — File storage
+- **[Bun](https://bun.sh)** — Package manager & runtime
## Getting Started
-First, clone the repository and install dependencies:
+Clone the repository and install dependencies:
```bash
-npm install
-# or
-yarn install
-# or
-pnpm install
+bun install
```
-Then, run the development server:
+Copy the environment file and configure your values:
```bash
-npm run dev
-# or
-yarn dev
-# or
-pnpm dev
+cp .env.example .env.local
```
-Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+Run the development server:
-You can start editing the pages by modifying files in the `app/` directory. The page auto-updates as you edit the file.
+```bash
+bun run dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) to see the result.
+
+## Scripts
+
+| Command | Description |
+|---------|-------------|
+| `bun run dev` | Start development server (HTTPS) |
+| `bun run build` | Create production build |
+| `bun run start` | Start production server |
+| `bun run lint` | Run ESLint |
## Contributing
@@ -73,7 +86,7 @@ We welcome contributions of all kinds! Whether you want to:
- Improve the design
- Contribute code
-Feel free to open an [issue](../../issues) or submit a [pull request](../../pulls).
+Feel free to open an [issue](https://github.com/AdrianBonpin/deckyvault/issues) or submit a [pull request](https://github.com/AdrianBonpin/deckyvault/pulls).
If you're interested in helping develop or design the project, don't hesitate to reach out!
diff --git a/app/favicon.ico b/app/favicon.ico
deleted file mode 100644
index 718d6fe..0000000
Binary files a/app/favicon.ico and /dev/null differ
diff --git a/app/globals.css b/app/globals.css
index a2dc41e..2695c1e 100644
--- a/app/globals.css
+++ b/app/globals.css
@@ -1,26 +1,17 @@
@import "tailwindcss";
-:root {
- --background: #ffffff;
- --foreground: #171717;
-}
-
@theme inline {
- --color-background: var(--background);
- --color-foreground: var(--foreground);
- --font-sans: var(--font-geist-sans);
- --font-mono: var(--font-geist-mono);
-}
+ /* Colors */
+ --color-background: #100b14;
+ --color-foreground: #180161;
+ --color-primary: #eb3779;
+ --color-secondary: #571b8b;
+ --color-accent: #fb793c;
+ --color-text: #ebe4f1;
-@media (prefers-color-scheme: dark) {
- :root {
- --background: #0a0a0a;
- --foreground: #ededed;
- }
-}
+ /* Defaults */
+ --default-transition-duration: 0.3s;
-body {
- background: var(--background);
- color: var(--foreground);
- font-family: Arial, Helvetica, sans-serif;
+ /* Fonts */
+ --font-sans: var(--font-lexend);
}
diff --git a/app/icon.png b/app/icon.png
new file mode 100644
index 0000000..1fec42f
Binary files /dev/null and b/app/icon.png differ
diff --git a/app/layout.tsx b/app/layout.tsx
index 976eb90..5fbf250 100644
--- a/app/layout.tsx
+++ b/app/layout.tsx
@@ -1,33 +1,93 @@
-import type { Metadata } from "next";
-import { Geist, Geist_Mono } from "next/font/google";
-import "./globals.css";
+import type { Metadata } from "next"
+import { Lexend } from "next/font/google"
+import "./globals.css"
+import Script from "next/script"
-const geistSans = Geist({
- variable: "--font-geist-sans",
- subsets: ["latin"],
-});
-
-const geistMono = Geist_Mono({
- variable: "--font-geist-mono",
- subsets: ["latin"],
-});
+const font = Lexend({
+ variable: "--font-lexend",
+ subsets: ["latin"],
+})
export const metadata: Metadata = {
- title: "Create Next App",
- description: "Generated by create next app",
-};
+ metadataBase: new URL("https://deckyvault.xyz"),
+ title: {
+ default: "DeckyVault - Steam Deck Benchmarks & Settings",
+ template: "%s | DeckyVault",
+ },
+ description:
+ "A fast, modern browser for finding game benchmarks, settings, and guides for Steam Deck OLED, Steam Deck LCD, and Steam Machine.",
+ keywords: [
+ "Steam Deck",
+ "benchmarks",
+ "settings",
+ "performance",
+ "FPS",
+ "gaming",
+ "Steam Machine",
+ "Proton",
+ "FSR",
+ "compatibility",
+ ],
+ authors: [
+ { name: "Adrian Bonpin", url: "https://github.com/AdrianBonpin" },
+ ],
+ creator: "@adrianbonpin",
+ openGraph: {
+ type: "website",
+ locale: "en_US",
+ url: "https://deckyvault.xyz",
+ siteName: "DeckyVault",
+ title: "DeckyVault - Steam Deck Benchmarks & Settings",
+ description:
+ "A fast, modern browser for finding game benchmarks, settings, and guides for Steam Deck OLED, Steam Deck LCD, and Steam Machine.",
+ images: [
+ {
+ url: "/opengraph-image",
+ width: 1200,
+ height: 630,
+ alt: "DeckyVault - Steam Deck Benchmarks & Settings",
+ },
+ ],
+ },
+ twitter: {
+ card: "summary_large_image",
+ title: "DeckyVault - Steam Deck Benchmarks & Settings",
+ description:
+ "A fast, modern browser for finding game benchmarks, settings, and guides for Steam Deck OLED, Steam Deck LCD, and Steam Machine.",
+ creator: "@adrianbonpin",
+ images: ["/twitter-image"],
+ },
+ robots: {
+ index: true,
+ follow: true,
+ googleBot: {
+ index: true,
+ follow: true,
+ "max-video-preview": -1,
+ "max-image-preview": "large",
+ "max-snippet": -1,
+ },
+ },
+}
export default function RootLayout({
- children,
+ children,
}: Readonly<{
- children: React.ReactNode;
+ children: React.ReactNode
}>) {
- return (
-
-
{children}
-
- );
+ return (
+
+
+ {children}
+
+
+
+ )
}
diff --git a/app/manifest.ts b/app/manifest.ts
new file mode 100644
index 0000000..18510e5
--- /dev/null
+++ b/app/manifest.ts
@@ -0,0 +1,21 @@
+import type { MetadataRoute } from "next"
+
+export default function manifest(): MetadataRoute.Manifest {
+ return {
+ name: "DeckyVault - Steam Deck Benchmarks & Settings",
+ short_name: "DeckyVault",
+ description:
+ "A fast, modern browser for finding game benchmarks, settings, and guides for Steam Deck OLED, Steam Deck LCD, and Steam Machine.",
+ start_url: "/",
+ display: "standalone",
+ background_color: "#100b14",
+ theme_color: "#eb3779",
+ icons: [
+ {
+ src: "/icon.png",
+ sizes: "any",
+ type: "image/png",
+ },
+ ],
+ }
+}
diff --git a/app/opengraph-image.tsx b/app/opengraph-image.tsx
new file mode 100644
index 0000000..bd788f7
--- /dev/null
+++ b/app/opengraph-image.tsx
@@ -0,0 +1,65 @@
+import { ImageResponse } from "next/og"
+import { readFile } from "node:fs/promises"
+import { join } from "node:path"
+
+export const alt = "DeckyVault - Steam Deck Benchmarks & Settings"
+export const size = {
+ width: 1200,
+ height: 630,
+}
+export const contentType = "image/png"
+
+export default async function Image() {
+ const logoData = await readFile(
+ join(process.cwd(), "app/icon.png"),
+ "base64"
+ )
+ const logoSrc = `data:image/png;base64,${logoData}`
+
+ return new ImageResponse(
+ (
+
+

+
+ DeckyVault
+
+
+ Steam Deck Benchmarks & Settings
+
+
+ ),
+ {
+ ...size,
+ }
+ )
+}
diff --git a/app/page.tsx b/app/page.tsx
index 3f36f7c..b217d5b 100644
--- a/app/page.tsx
+++ b/app/page.tsx
@@ -1,65 +1,87 @@
-import Image from "next/image";
+"use client"
-export default function Home() {
- return (
-
-
-
-
-
- To get started, edit the page.tsx file.
-
-
- Looking for a starting point or more instructions? Head over to{" "}
-
- Templates
- {" "}
- or the{" "}
-
- Learning
- {" "}
- center.
-
-
-
-
-
- );
+
+ DeckyVault
+
+
+
+ A fast, modern browser for finding game
+
+
+
+ {words[currentWord]}
+
+
+
+
+ Stay tuned for the launch of DeckyVault
+
+
+ 2026 DeckyVault.
+
+ Github.
+
+
+
+ )
}
diff --git a/app/robots.ts b/app/robots.ts
new file mode 100644
index 0000000..cef8bb2
--- /dev/null
+++ b/app/robots.ts
@@ -0,0 +1,13 @@
+import type { MetadataRoute } from "next"
+
+export default function robots(): MetadataRoute.Robots {
+ return {
+ rules: {
+ userAgent: "*",
+ allow: "/",
+ },
+ sitemap: "https://deckyvault.xyz/sitemap.xml",
+ host: "https://deckyvault.xyz",
+ }
+}
+
diff --git a/app/sitemap.ts b/app/sitemap.ts
new file mode 100644
index 0000000..625e5a3
--- /dev/null
+++ b/app/sitemap.ts
@@ -0,0 +1,21 @@
+import type { MetadataRoute } from "next"
+
+const BASE_URL = "https://deckyvault.xyz"
+
+export default function sitemap(): MetadataRoute.Sitemap {
+ return [
+ {
+ url: BASE_URL,
+ lastModified: new Date(),
+ changeFrequency: "weekly",
+ priority: 1,
+ },
+ // Future dynamic routes can be added here:
+ // {
+ // url: `${BASE_URL}/games/${game.slug}`,
+ // lastModified: game.updatedAt,
+ // changeFrequency: "weekly",
+ // priority: 0.8,
+ // },
+ ]
+}
diff --git a/app/twitter-image.tsx b/app/twitter-image.tsx
new file mode 100644
index 0000000..bd788f7
--- /dev/null
+++ b/app/twitter-image.tsx
@@ -0,0 +1,65 @@
+import { ImageResponse } from "next/og"
+import { readFile } from "node:fs/promises"
+import { join } from "node:path"
+
+export const alt = "DeckyVault - Steam Deck Benchmarks & Settings"
+export const size = {
+ width: 1200,
+ height: 630,
+}
+export const contentType = "image/png"
+
+export default async function Image() {
+ const logoData = await readFile(
+ join(process.cwd(), "app/icon.png"),
+ "base64"
+ )
+ const logoSrc = `data:image/png;base64,${logoData}`
+
+ return new ImageResponse(
+ (
+
+

+
+ DeckyVault
+
+
+ Steam Deck Benchmarks & Settings
+
+
+ ),
+ {
+ ...size,
+ }
+ )
+}
diff --git a/bun.lock b/bun.lock
index 41bbd5e..ef90988 100644
--- a/bun.lock
+++ b/bun.lock
@@ -15,6 +15,7 @@
"dotenv": "^17.4.2",
"drizzle-orm": "^0.45.2",
"elysia": "^1.4.28",
+ "lucide-react": "^1.11.0",
"motion": "^12.38.0",
"next": "16.2.4",
"pg": "^8.20.0",
@@ -1042,6 +1043,8 @@
"lru-cache": ["lru-cache@5.1.1", "", { "dependencies": { "yallist": "^3.0.2" } }, "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w=="],
+ "lucide-react": ["lucide-react@1.11.0", "", { "peerDependencies": { "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" } }, "sha512-UOhjdztXCgdBReRcIhsvz2siIBogfv/lhJEIViCpLt924dO+GDms9T7DNoucI23s6kEPpe988m5N0D2ajnzb2g=="],
+
"magic-string": ["magic-string@0.30.21", "", { "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.5" } }, "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ=="],
"math-intrinsics": ["math-intrinsics@1.1.0", "", {}, "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g=="],
diff --git a/docs/superpowers/plans/2026-04-25-seo-and-readme.md b/docs/superpowers/plans/2026-04-25-seo-and-readme.md
new file mode 100644
index 0000000..c82e449
--- /dev/null
+++ b/docs/superpowers/plans/2026-04-25-seo-and-readme.md
@@ -0,0 +1,616 @@
+# SEO & README Implementation Plan
+
+> **For agentic workers:** REQUIRED: Use superpowers:subagent-driven-development (if subagents available) or superpowers:executing-plans to implement this plan. Steps use checkbox (`- [ ]`) syntax for tracking.
+
+**Goal:** Add comprehensive SEO infrastructure (metadata, OG images, sitemap, robots.txt, manifest) and update the README to reflect the current project state.
+
+**Architecture:** All SEO files live in `app/` as Next.js file conventions. The OG image is dynamically generated using `ImageResponse` from `next/og`, leveraging the existing `app/icon.png` logo. Sitemap and manifest use TypeScript file conventions for future dynamic data readiness. The site URL is `https://deckyvault.xyz`.
+
+**Tech Stack:** Next.js 16.2.4 App Router, `next/og` ImageResponse, TypeScript, Tailwind CSS v4
+
+---
+
+## File Structure
+
+### Files to Create
+| File | Purpose |
+|------|---------|
+| `app/layout.tsx` | Modify: add full metadata (title template, description, OpenGraph, Twitter, authors, keywords, metadataBase) |
+| `app/opengraph-image.tsx` | Create: dynamic OG banner image using ImageResponse with logo + brand colors |
+| `app/twitter-image.tsx` | Create: Twitter card image (can share OG image logic or be identical) |
+| `app/sitemap.ts` | Create: programmatic sitemap with static routes, ready for dynamic data |
+| `app/robots.ts` | Create: robots.txt allowing all crawlers, pointing to sitemap |
+| `app/manifest.ts` | Create: PWA web manifest with app name, theme colors, icons |
+| `app/icon.png` | Already exists — used as favicon and in OG image generation |
+| `README.md` | Modify: update tech stack, install commands, development status note |
+
+### Files Unchanged
+| File | Reason |
+|------|--------|
+| `app/page.tsx` | Landing page — no SEO changes needed (metadata is in layout) |
+| `app/globals.css` | Styles — no changes needed |
+| `next.config.ts` | No config changes needed for this scope |
+| `public/` | Stays empty — all assets handled via app directory conventions |
+
+---
+
+## Chunk 1: Root Layout Metadata & OG Image Generation
+
+### Task 1: Enhance Root Layout Metadata
+
+**Files:**
+- Modify: `app/layout.tsx`
+
+The current layout only sets `title`. We need to add full metadata for SEO and social sharing.
+
+- [ ] **Step 1: Update `app/layout.tsx` with comprehensive metadata**
+
+Replace the existing `metadata` export with a full configuration:
+
+```tsx
+import type { Metadata } from "next"
+import { Lexend } from "next/font/google"
+import "./globals.css"
+
+const font = Lexend({
+ variable: "--font-lexend",
+ subsets: ["latin"],
+})
+
+export const metadata: Metadata = {
+ metadataBase: new URL("https://deckyvault.xyz"),
+ title: {
+ default: "DeckyVault - Steam Deck Benchmarks & Settings",
+ template: "%s | DeckyVault",
+ },
+ description:
+ "A fast, modern browser for finding game benchmarks, settings, and guides for Steam Deck OLED, Steam Deck LCD, and Steam Machine.",
+ keywords: [
+ "Steam Deck",
+ "benchmarks",
+ "settings",
+ "performance",
+ "FPS",
+ "gaming",
+ "Steam Machine",
+ "Proton",
+ "FSR",
+ "compatibility",
+ ],
+ authors: [{ name: "Adrian Bonpin", url: "https://github.com/AdrianBonpin" }],
+ creator: "@adrianbonpin",
+ openGraph: {
+ type: "website",
+ locale: "en_US",
+ url: "https://deckyvault.xyz",
+ siteName: "DeckyVault",
+ title: "DeckyVault - Steam Deck Benchmarks & Settings",
+ description:
+ "A fast, modern browser for finding game benchmarks, settings, and guides for Steam Deck OLED, Steam Deck LCD, and Steam Machine.",
+ images: [
+ {
+ url: "/opengraph-image",
+ width: 1200,
+ height: 630,
+ alt: "DeckyVault - Steam Deck Benchmarks & Settings",
+ },
+ ],
+ },
+ twitter: {
+ card: "summary_large_image",
+ title: "DeckyVault - Steam Deck Benchmarks & Settings",
+ description:
+ "A fast, modern browser for finding game benchmarks, settings, and guides for Steam Deck OLED, Steam Deck LCD, and Steam Machine.",
+ creator: "@adrianbonpin",
+ images: ["/twitter-image"],
+ },
+ robots: {
+ index: true,
+ follow: true,
+ googleBot: {
+ index: true,
+ follow: true,
+ "max-video-preview": -1,
+ "max-image-preview": "large",
+ "max-snippet": -1,
+ },
+ },
+}
+
+export default function RootLayout({
+ children,
+}: Readonly<{
+ children: React.ReactNode
+}>) {
+ return (
+
+
+ {children}
+
+
+ )
+}
+```
+
+- [ ] **Step 2: Verify layout compiles**
+
+Run: `bun run build`
+Expected: Build succeeds with no TypeScript errors.
+
+---
+
+### Task 2: Create Dynamic OpenGraph Image
+
+**Files:**
+- Create: `app/opengraph-image.tsx`
+
+Uses `ImageResponse` from `next/og` to generate a branded OG banner at build time. Reads the existing `app/icon.png` as a base64 data URI and renders it with the DeckyVault name and tagline on the brand background color.
+
+- [ ] **Step 1: Create `app/opengraph-image.tsx`**
+
+```tsx
+import { ImageResponse } from "next/og"
+import { readFile } from "node:fs/promises"
+import { join } from "node:path"
+
+export const alt = "DeckyVault - Steam Deck Benchmarks & Settings"
+export const size = {
+ width: 1200,
+ height: 630,
+}
+export const contentType = "image/png"
+
+export default async function Image() {
+ const logoData = await readFile(
+ join(process.cwd(), "app/icon.png"),
+ "base64"
+ )
+ const logoSrc = `data:image/png;base64,${logoData}`
+
+ return new ImageResponse(
+ (
+
+

+
+ DeckyVault
+
+
+ Steam Deck Benchmarks & Settings
+
+
+ ),
+ {
+ ...size,
+ }
+ )
+}
+```
+
+- [ ] **Step 2: Verify OG image builds**
+
+Run: `bun run build`
+Expected: Build succeeds. `opengraph-image` route appears in build output.
+
+---
+
+### Task 3: Create Twitter Card Image
+
+**Files:**
+- Create: `app/twitter-image.tsx`
+
+Shares the same design as the OG image. Next.js supports separate `twitter-image` files. For now, we duplicate the OG image logic to allow independent customization later.
+
+- [ ] **Step 1: Create `app/twitter-image.tsx`**
+
+```tsx
+import { ImageResponse } from "next/og"
+import { readFile } from "node:fs/promises"
+import { join } from "node:path"
+
+export const alt = "DeckyVault - Steam Deck Benchmarks & Settings"
+export const size = {
+ width: 1200,
+ height: 630,
+}
+export const contentType = "image/png"
+
+export default async function Image() {
+ const logoData = await readFile(
+ join(process.cwd(), "app/icon.png"),
+ "base64"
+ )
+ const logoSrc = `data:image/png;base64,${logoData}`
+
+ return new ImageResponse(
+ (
+
+

+
+ DeckyVault
+
+
+ Steam Deck Benchmarks & Settings
+
+
+ ),
+ {
+ ...size,
+ }
+ )
+}
+```
+
+- [ ] **Step 2: Verify Twitter image builds**
+
+Run: `bun run build`
+Expected: Build succeeds. Both `opengraph-image` and `twitter-image` routes appear.
+
+---
+
+## Chunk 2: Sitemap, Robots.txt, and Manifest
+
+### Task 4: Create Dynamic Sitemap
+
+**Files:**
+- Create: `app/sitemap.ts`
+
+Programmatically generates `sitemap.xml`. Currently static (just the homepage), but structured so that dynamic game pages can be added later by querying the database.
+
+- [ ] **Step 1: Create `app/sitemap.ts`**
+
+```ts
+import type { MetadataRoute } from "next"
+
+const BASE_URL = "https://deckyvault.xyz"
+
+export default function sitemap(): MetadataRoute.Sitemap {
+ return [
+ {
+ url: BASE_URL,
+ lastModified: new Date(),
+ changeFrequency: "weekly",
+ priority: 1,
+ },
+ // Future dynamic routes can be added here:
+ // {
+ // url: `${BASE_URL}/games/${game.slug}`,
+ // lastModified: game.updatedAt,
+ // changeFrequency: "weekly",
+ // priority: 0.8,
+ // },
+ ]
+}
+```
+
+- [ ] **Step 2: Verify sitemap builds**
+
+Run: `bun run build`
+Expected: Build succeeds. `/sitemap.xml` route available.
+
+---
+
+### Task 5: Create Robots.txt
+
+**Files:**
+- Create: `app/robots.ts`
+
+Allows all crawlers, points to the sitemap, and sets the host.
+
+- [ ] **Step 1: Create `app/robots.ts`**
+
+```ts
+import type { MetadataRoute } from "next"
+
+export default function robots(): MetadataRoute.Robots {
+ return {
+ rules: {
+ userAgent: "*",
+ allow: "/",
+ },
+ sitemap: "https://deckyvault.xyz/sitemap.xml",
+ host: "https://deckyvault.xyz",
+ }
+}
+```
+
+- [ ] **Step 2: Verify robots.txt builds**
+
+Run: `bun run build`
+Expected: Build succeeds. `/robots.txt` route available.
+
+---
+
+### Task 6: Create Web App Manifest
+
+**Files:**
+- Create: `app/manifest.ts`
+
+Generates `manifest.webmanifest` for PWA support and better mobile experience. Uses the existing `app/icon.png` and the brand colors from `globals.css`.
+
+- [ ] **Step 1: Create `app/manifest.ts`**
+
+```ts
+import type { MetadataRoute } from "next"
+
+export default function manifest(): MetadataRoute.Manifest {
+ return {
+ name: "DeckyVault - Steam Deck Benchmarks & Settings",
+ short_name: "DeckyVault",
+ description:
+ "A fast, modern browser for finding game benchmarks, settings, and guides for Steam Deck OLED, Steam Deck LCD, and Steam Machine.",
+ start_url: "/",
+ display: "standalone",
+ background_color: "#100b14",
+ theme_color: "#eb3779",
+ icons: [
+ {
+ src: "/icon.png",
+ sizes: "any",
+ type: "image/png",
+ },
+ ],
+ }
+}
+```
+
+Note: `app/icon.png` is served at `/icon.png` by Next.js (the existing build output confirms this route exists).
+
+- [ ] **Step 2: Verify manifest builds**
+
+Run: `bun run build`
+Expected: Build succeeds. `/manifest.webmanifest` route available.
+
+---
+
+## Chunk 3: README Update
+
+### Task 7: Update README.md
+
+**Files:**
+- Modify: `README.md`
+
+The current README is outdated — references npm/yarn/pnpm instead of bun, doesn't mention Elysia, Drizzle, Tiptap, better-auth, S3 storage, or the actual full tech stack. Needs to reflect the current state and note that the site is under development.
+
+- [ ] **Step 1: Replace `README.md` content**
+
+```markdown
+# DeckyVault
+
+An open-source, community-driven database for Steam Deck (OLED & LCD) and Steam Machine compatibility, performance metrics, and settings.
+
+> **Note:** DeckyVault is currently under active development. The site is live at [deckyvault.xyz](https://deckyvault.xyz) but features are being built incrementally. Stay tuned!
+
+## Why DeckyVault?
+
+Gaming on the Steam Deck is incredible, but finding reliable, detailed answers about whether a game will run well — or how to optimize it — can be frustrating. Existing resources are often fragmented, outdated, or lack the depth the community needs.
+
+**DeckyVault** aims to solve this by being the definitive, community-first hub for Steam Deck performance data.
+
+## Features
+
+- **Community-First Contributions** — Built by the community, for the community. Anyone can contribute data and improvements.
+- **Streamlined Filters & Searching** — Quickly find the games you're looking for with powerful search and filtering.
+- **Rich Performance Metrics**
+ - Community average FPS (**low**, **avg**, **high**).
+ - Extended FPS metrics for technologies like **FSR** and **Frame Generation**.
+- **Beautifully Formatted Settings** — No more endless single-column lists. Every game features **sectioned setting tables** that mirror in-game menus.
+- **Historical FPS Graphs** — Track performance improvements over time across:
+ - Game Versions
+ - Proton / Native builds
+ - SteamOS Versions
+- **Multi-Device Support** — Dedicated metrics and optimized settings for **Steam Deck OLED**, **Steam Deck LCD**, and **Steam Machine**, all on a single page with quick toggles.
+- **Comprehensive Compatibility Tracking**
+ - Proton vs. Native status
+ - Online Play & Anti-Cheat status
+ - Straightforward "Playable" tags
+- **Loading & Storage Metrics** — Track initial launch times, game load times, world loading, and **SD Card** performance.
+- **Community & Steam Integration** — On-site comments plus existing reviews, artwork, and stats pulled directly from Steam.
+- **Open Source** — Fully transparent. Help us build the best resource for Deck gamers.
+
+## Tech Stack
+
+- **[Next.js 16](https://nextjs.org)** — React framework (App Router)
+- **[React 19](https://react.dev)** — UI library
+- **[TypeScript](https://www.typescriptlang.org)** — Type safety
+- **[Tailwind CSS v4](https://tailwindcss.com)** — Utility-first styling
+- **[Elysia](https://elysiajs.com)** — Backend API framework
+- **[Drizzle ORM](https://orm.drizzle.team)** — Type-safe database queries
+- **[PostgreSQL](https://www.postgresql.org)** — Primary database
+- **[better-auth](https://better-auth.com)** — Authentication (Google & Discord OAuth)
+- **[Tiptap](https://tiptap.dev)** — Rich text editor
+- **[Motion](https://motion.dev)** — Animations
+- **[AWS S3](https://aws.amazon.com/s3/)** — File storage
+- **[Bun](https://bun.sh)** — Package manager & runtime
+
+## Getting Started
+
+Clone the repository and install dependencies:
+
+```bash
+bun install
+```
+
+Copy the environment file and configure your values:
+
+```bash
+cp .env.example .env.local
+```
+
+Run the development server:
+
+```bash
+bun run dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) to see the result.
+
+## Scripts
+
+| Command | Description |
+|---------|-------------|
+| `bun run dev` | Start development server (HTTPS) |
+| `bun run build` | Create production build |
+| `bun run start` | Start production server |
+| `bun run lint` | Run ESLint |
+
+## Contributing
+
+We welcome contributions of all kinds! Whether you want to:
+
+- Suggest a new feature
+- Report a bug
+- Improve the design
+- Contribute code
+
+Feel free to open an [issue](https://github.com/AdrianBonpin/deckyvault/issues) or submit a [pull request](https://github.com/AdrianBonpin/deckyvault/pulls).
+
+If you're interested in helping develop or design the project, don't hesitate to reach out!
+
+## Roadmap
+
+This project is actively being developed. Here are some of the major items on our radar:
+
+- [ ] Core database and API for game entries
+- [ ] Advanced search and filter system
+- [ ] Community submission and moderation tools
+- [ ] FPS graphing and historical data visualization
+- [ ] Steam API integration for reviews, artwork, and stats
+- [ ] Support for additional handheld devices *(future consideration)*
+
+Stay tuned for updates!
+
+## License
+
+This project is open-source. *(Add your specific license here, e.g., MIT, GPL-3.0)*
+
+## Acknowledgements
+
+- Built with love for the Steam Deck community.
+- Check out the author's existing project for an idea of what to expect: **[https://grounds.ph](https://grounds.ph)**
+
+---
+
+*DeckyVault is an independent project and is not affiliated with Valve Corporation.*
+```
+
+- [ ] **Step 2: Verify no build impact**
+
+Run: `bun run build`
+Expected: Build succeeds (README changes don't affect build).
+
+---
+
+## Chunk 4: Verification & Lint/Build Cleanup
+
+### Task 8: Final Verification
+
+**Files:**
+- All files created/modified in Tasks 1-7
+
+- [ ] **Step 1: Run full lint**
+
+Run: `bun run lint`
+Expected: No errors or warnings.
+
+- [ ] **Step 2: Run full build**
+
+Run: `bun run build`
+Expected: Build succeeds. Verify the following routes are generated:
+- `/` — main page
+- `/icon.png` — favicon (already existed)
+- `/opengraph-image` — OG banner
+- `/twitter-image` — Twitter card
+- `/sitemap.xml` — sitemap
+- `/robots.txt` — robots
+- `/manifest.webmanifest` — PWA manifest
+
+- [ ] **Step 3: Fix any lint or build errors**
+
+If lint or build fails, fix the issues before claiming completion. Common issues to watch for:
+- TypeScript errors in OG image files (ensure `readFile` import works)
+- ESLint warnings on unused variables or missing dependencies
+- Build failures from incorrect `ImageResponse` JSX
+
+- [ ] **Step 4: Commit all changes**
+
+```bash
+git add app/layout.tsx app/opengraph-image.tsx app/twitter-image.tsx app/sitemap.ts app/robots.ts app/manifest.ts README.md
+git commit -m "feat: add comprehensive SEO (metadata, OG images, sitemap, robots, manifest) and update README"
+```
+
+---
+
+## Summary of Routes After Implementation
+
+| Route | Type | Source File |
+|-------|------|-------------|
+| `/` | Static page | `app/page.tsx` |
+| `/icon.png` | Favicon | `app/icon.png` |
+| `/opengraph-image` | OG banner (PNG) | `app/opengraph-image.tsx` |
+| `/twitter-image` | Twitter card (PNG) | `app/twitter-image.tsx` |
+| `/sitemap.xml` | Sitemap | `app/sitemap.ts` |
+| `/robots.txt` | Robots | `app/robots.ts` |
+| `/manifest.webmanifest` | PWA manifest | `app/manifest.ts` |
diff --git a/package.json b/package.json
index d90061f..e0a22f9 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"version": "2026.0.1",
"private": true,
"scripts": {
- "dev": "next dev",
+ "dev": "next dev --experimental-https",
"build": "next build",
"start": "next start",
"lint": "eslint"
@@ -19,6 +19,7 @@
"dotenv": "^17.4.2",
"drizzle-orm": "^0.45.2",
"elysia": "^1.4.28",
+ "lucide-react": "^1.11.0",
"motion": "^12.38.0",
"next": "16.2.4",
"pg": "^8.20.0",
diff --git a/public/file.svg b/public/file.svg
deleted file mode 100644
index 004145c..0000000
--- a/public/file.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/globe.svg b/public/globe.svg
deleted file mode 100644
index 567f17b..0000000
--- a/public/globe.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/next.svg b/public/next.svg
deleted file mode 100644
index 5174b28..0000000
--- a/public/next.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/vercel.svg b/public/vercel.svg
deleted file mode 100644
index 7705396..0000000
--- a/public/vercel.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/public/window.svg b/public/window.svg
deleted file mode 100644
index b2b2a44..0000000
--- a/public/window.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file