Connecting backend with frontend - #28
Conversation
…into frontend-setup
…onditionally visible based on user role
Added project structure documentation for the frontend.
Added a cyberpunk theme to the home page
>> svelte 4 to svelte 5 migration >> reformatted code to be more structured >> Linked to google oauth at backend (wip)
Replaced SvelteKitAuth setup with getSession function for session management.
There was a problem hiding this comment.
Pull request overview
This PR introduces a new SvelteKit-based frontend scaffold and begins wiring it up to backend/session/auth flows to support game browsing, uploading, and admin moderation.
Changes:
- Added SvelteKit frontend project structure/configuration (Vite/SvelteKit/TypeScript).
- Implemented initial routes and UI for home, all-games, my-games, upload, game detail, and admin dashboard.
- Added early auth/session plumbing and admin API integration points (session checks + admin fetches).
Reviewed changes
Copilot reviewed 32 out of 45 changed files in this pull request and generated 18 comments.
Show a summary per file
| File | Description |
|---|---|
| package.json | Adds root-level npm dependencies (auth + node types). |
| package-lock.json | Root lockfile capturing installed dependency graph. |
| frontend/vite.config.ts | Vite config enabling SvelteKit plugin. |
| frontend/tsconfig.json | TS config extending SvelteKit generated config and adding $lib paths. |
| frontend/svelte.config.js | SvelteKit adapter + preprocess configuration. |
| frontend/static/favicon.svg | Adds default Svelte favicon asset. |
| frontend/src/routes/upload/+page.ts | Client-side access gating for upload page. |
| frontend/src/routes/upload/+page.svelte | Upload form UI + local submission store update logic. |
| frontend/src/routes/my-games/+page.svelte | “My games” UI driven by the submissions store. |
| frontend/src/routes/game/[id]/+page.ts | Loads game data by route param from local dataset. |
| frontend/src/routes/game/[id]/+page.svelte | Game iframe view + rating/superlike interactions. |
| frontend/src/routes/all-games/+page.svelte | All-games listing with filter/search/sort + store merge. |
| frontend/src/routes/admin/+page.ts | Client-side access gating for admin page (store-based). |
| frontend/src/routes/admin/+page.svelte | Admin dashboard UI calling backend admin endpoints. |
| frontend/src/routes/admin/+page.server.ts | Server-side admin session check + data fetching. |
| frontend/src/routes/+page.svelte | Home page UI with Google sign-in/out actions. |
| frontend/src/routes/+layout.svelte | Global layout wrapping pages with Header/Footer. |
| frontend/src/routes/+layout.server.ts | Layout server load returning session from locals.getSession(). |
| frontend/src/lib/stores/user.js | Mock user store for early auth/role usage. |
| frontend/src/lib/stores/submissions.ts | Writable store for submitted games + type definition. |
| frontend/src/lib/stores/ratings.ts | Writable store for ratings/superlikes by game id. |
| frontend/src/lib/index.ts | Placeholder library entry point. |
| frontend/src/lib/data/games.js | Temporary static games dataset for routing/demo. |
| frontend/src/lib/components/layout/Header.svelte | Header component using @auth/sveltekit/client sign-in/out. |
| frontend/src/lib/components/layout/Footer.svelte | Footer component. |
| frontend/src/lib/components/GameCard.svelte | Game card component for listing/navigating to game detail. |
| frontend/src/hooks.server.ts | Hooks entry re-exporting auth handle. |
| frontend/src/auth.ts | Helper to fetch session from backend API. |
| frontend/src/app.html | SvelteKit app HTML template. |
| frontend/src/app.d.ts | Declares locals.getSession() typing for SvelteKit. |
| frontend/src/app.css | Base global CSS. |
| frontend/package.json | Frontend package manifest (SvelteKit + auth deps). |
| frontend/README.md | Run instructions + default Svelte library template text. |
| frontend/LICENSE | MIT license text. |
| frontend/.npmrc | Enforces engine strict mode. |
| frontend/.gitignore | Frontend-specific ignores. |
Files not reviewed (1)
- frontend/package-lock.json: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| function superlike() { | ||
| if ($user.superlikesUsed >= $user.maxSuperlikes) return; | ||
|
|
||
| ratings.update(r => { | ||
| const current = r[gameId] ?? { totalRatings: 0, totalScore: 0, superlikes: 0 }; | ||
|
|
||
| return { | ||
| ...r, | ||
| [gameId]: { | ||
| ...current, | ||
| superlikes: current.superlikes + 1 | ||
| } | ||
| }; | ||
| }); | ||
|
|
||
| user.update(u => ({ | ||
| ...u, | ||
| superlikesUsed: u.superlikesUsed + 1 | ||
| })); | ||
| } |
There was a problem hiding this comment.
This component reads $user.superlikesUsed / $user.maxSuperlikes and updates superlikesUsed, but the user store defines different property names. As written, the limit check and increment will not work (and may produce NaN). Update the component to use the store’s actual field names (or update the store to match).
| // sign in with Google — redirects to Hono backend OAuth flow | ||
| function handleGoogleSignIn() { | ||
| window.location.href = 'http://localhost:9210/auth/google'; | ||
| } | ||
|
|
||
| // sign out — calls Hono logout endpoint then returns to home | ||
| async function handleSignOut() { | ||
| await fetch('http://localhost:9210/auth/logout', { | ||
| method: 'POST', | ||
| credentials: 'include', | ||
| }); | ||
| window.location.href = '/'; | ||
| } |
There was a problem hiding this comment.
Auth endpoints are hard-coded to http://localhost:9210 here. This will break in non-local environments and makes it easy to misconfigure deployments. Use a single configured base URL (env var) or relative paths/proxies so dev/prod can share the same code.
There was a problem hiding this comment.
Replace the hardcoded URL with an environment variable (like API_BASE_URL) to support different environments.
| export function load() { | ||
| const currentUser = get(user); | ||
|
|
||
| if (currentUser.role !== 'dev') { | ||
| throw redirect(302, '/'); | ||
| } |
There was a problem hiding this comment.
Access control for this page is enforced only in a client-side load() using a writable store. That can be bypassed and won’t protect server-rendered content. If /upload should be restricted, enforce it in +page.server.ts (using the real session) and keep the client-side store check only for UX.
| { | ||
| "dependencies": { | ||
| "@auth/core": "^0.41.1", | ||
| "@auth/sveltekit": "^1.11.1" | ||
| }, | ||
| "devDependencies": { | ||
| "@types/node": "^25.0.9" | ||
| } | ||
| } |
There was a problem hiding this comment.
There is now a second npm project at the repo root (package.json + package-lock.json) in addition to backend/ and frontend/. Without workspaces, this risks duplicate/accidental installs and peer-dependency auto-installs (your lockfile already contains many packages not listed in package.json). Consider removing the root npm files or converting to a proper workspace setup that manages frontend/backend explicitly.
| // go to a page, show login first if the user isn't signed in | ||
| function goTo(path: string, requiresAuth = false) { | ||
| goto(path); | ||
| } |
There was a problem hiding this comment.
goTo(path, requiresAuth) ignores requiresAuth and always navigates immediately. This contradicts the function comment and the call sites that pass true, and it bypasses the showLogin gating behavior. Either implement the auth gating here or remove the unused parameter and update call sites/comments.
| function handleFile(file: File) { | ||
| if (!file.type.startsWith('image/')) return; | ||
| thumbnail = file; | ||
| preview = URL.createObjectURL(file); | ||
| } |
There was a problem hiding this comment.
URL.createObjectURL(file) is used for preview but never revoked (including when the user picks a different file or navigates away). Revoke the previous preview URL before replacing it and in onDestroy to avoid leaking blob URLs.
| import { handle } from "./auth"; | ||
|
|
||
| export { handle }; No newline at end of file |
There was a problem hiding this comment.
hooks.server.ts re-exports handle from ./auth, but src/auth.ts only exports getSession (no handle). This will fail to compile at runtime/build. Export a handle hook from src/auth.ts (e.g., via @auth/sveltekit) or update the import to point at the correct module.
| export const load: LayoutServerLoad = async (event) => { | ||
| return { | ||
| session: await event.locals.getSession() | ||
| }; |
There was a problem hiding this comment.
event.locals.getSession() will throw unless locals.getSession is actually set in hooks.server.ts. With the current hook import/export mismatch, getSession is never defined, so this load will crash. Ensure the auth hook populates event.locals.getSession (or call the getSession(fetch) helper directly here).
| const API_URL = import.meta.env.VITE_API_URL ?? 'http://localhost:3000'; | ||
|
|
||
| export async function load({ fetch, redirect }) { | ||
| // Check if the current user is logged in and is an admin | ||
| const sessionRes = await fetch(`${API_URL}/auth/session`, { credentials: 'include' }); | ||
| const session = sessionRes.ok ? await sessionRes.json() : null; | ||
|
|
||
| // If not logged in or not an admin, send them back to the homepage | ||
| if (!session?.authenticated || session?.user?.userType !== 'admin') { | ||
| throw redirect(302, '/'); | ||
| } |
There was a problem hiding this comment.
In a +page.server.ts load, redirect is not provided on the event object (so this destructuring makes redirect undefined). Import redirect from @sveltejs/kit instead, and keep the load signature as ({ fetch, locals, ... }) => { ... }.
| export const user = writable({ | ||
| isSignedIn: true, | ||
| name: 'test', | ||
| role: 'dev', | ||
| usedSuperLikes: 0, | ||
| maxSuperLikes: 3 | ||
| }); |
There was a problem hiding this comment.
The shape of the mock user object here (e.g. usedSuperLikes/maxSuperLikes) does not match how it’s consumed elsewhere (the game page reads superlikesUsed/maxSuperlikes). This will result in undefined reads and broken superlike logic. Rename fields to be consistent across the store and all consumers.
Connecting backend with frontend
Summary
New branch to connect frontend with backend.
Type
Changes
mainandfrontend-trialbranches.Testing
Describe how you tested this:
Checklist
Conventional Commits