Skip to content

Poiar/GameViewer

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

93 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

GameViewer

GameViewer is a personal video game collection tracker β€” a "Discogs for video games." Catalog your game library, track versions and DLCs, organize them into series and collections, and see your entire library at a glance.

πŸ€– This README is auto-generated by scripts/build-readme.ts. Run npx tsx scripts/build-readme.ts to regenerate.

Quick Start

git clone https://github.com/Poiar/GameViewer.git
cd GameViewer
npm install
# Backend setup
cd server && npm install && cd ..
# Create server/.env from server/.env.example (see Configuration below)
# Push DB schema:
cd server && npm run db:push && cd ..
# Import game data from Google Sheets:
cd server && npm run db:import-sheet && cd ..
# Start both servers (backend on :3001, frontend on :4200):
cd server && npm run dev & cd .. && npm start

Project Structure

GameViewer/
β”œβ”€β”€ src/app/                  # Angular 21 frontend
β”‚   β”œβ”€β”€ auth/                 # Login/register component
β”‚   β”œβ”€β”€ dashboard/            # Stats dashboard
β”‚   β”œβ”€β”€ game-ui/              # Game detail panel
β”‚   β”œβ”€β”€ inventory/            # Your collection view
β”‚   β”œβ”€β”€ model-viewer/         # 3D model viewer
β”‚   β”œβ”€β”€ profile/              # User profile
β”‚   β”œβ”€β”€ shared/               # Shared UI components (loading, errors, empty states)
β”‚   β”œβ”€β”€ types/                # TypeScript interfaces
β”‚   β”œβ”€β”€ services/             # HTTP service layer (11 services)
β”‚   └── interceptors/         # HTTP interceptors
β”œβ”€β”€ server/                   # Express + Drizzle backend
β”‚   └── src/
β”‚       β”œβ”€β”€ index.ts          # Express app entry point
β”‚       β”œβ”€β”€ config.ts         # Configuration
β”‚       β”œβ”€β”€ db/
β”‚       β”‚   β”œβ”€β”€ schema.ts     # Drizzle ORM schema (22 tables)
β”‚       β”‚   β”œβ”€β”€ index.ts      # DB connection
β”‚       β”‚   β”œβ”€β”€ seed.ts       # Demo data seeder
β”‚       β”‚   β”œβ”€β”€ import-sheet.ts  # Google Sheets importer
β”‚       β”‚   └── imports/      # CSV files from Google Sheets
β”‚       β”œβ”€β”€ routes/           # REST API routes (10 route files)
β”‚       └── middleware/       # Auth, validation, error handling
β”œβ”€β”€ scripts/
β”‚   └── build-readme.ts       # This README generator
β”œβ”€β”€ package.json              # Frontend dependencies + scripts
β”œβ”€β”€ angular.json              # Angular workspace config
└── proxy.conf.json           # API proxy config (β†’ :3001)

Architecture

Frontend β€” Angular v21

  • ^21.2.14 β€” standalone components, no routing (single-page app)
  • Strict TypeScript: strict, noImplicitOverride, noImplicitReturns, strict template checking
  • Styling: component-scoped CSS files
  • Playwright for E2E testing
  • Three.js for 3D model viewing (.obj file support)

Components

Selector Component
app-root app
app-auth auth
app-dashboard dashboard
app-game-ui game-ui
app-inventory inventory
app-model-viewer model-viewer
app-collections-page pages
app-dashboard-page pages
app-explore-page pages
app-games-page pages
app-inventory-page pages
app-series-page pages
app-versions-page pages
app-profile profile
app-empty-state shared
app-error-console shared
app-error-state shared
app-loading-spinner shared

Services

Service Purpose
auth.service.ts Authentication (login, register, token refresh)
collections.service.ts Collection/compilation management
dashboard.service.ts Dashboard statistics
dlc.service.ts DLC and DLC release management
error-console.service.spec.ts.service.ts
error-console.service.ts
favorites.service.ts Favorites/wishlist
games.service.ts Master game queries and CRUD
inventory.service.ts Owned instances (your collection)
lookup.service.ts Lookup tables (platforms, providers, genres, etc.)
releases.service.ts Release management
series.service.ts Series/franchise queries

Types

Core interfaces in src/app/types/:

File Key Interfaces
game.types.ts MasterGame, Release, ReleaseGroup, Dlc, Collection, Series, Genre, Platform, Provider, OwnedInstance, DashboardStats, UserProfile
api.types.ts ApiResponse<T>, PaginationMeta, ApiError

Backend β€” Express + Drizzle ORM

  • Express β€” REST API on port 3001
  • Drizzle ORM β€” PostgreSQL via Neon serverless (@neondatabase/serverless)
  • JWT auth β€” access tokens (15min) + refresh tokens (7 days, httpOnly cookie)
  • Security β€” Helmet, CORS, rate limiting (100 req/min), bcrypt (12 rounds)
  • Validation β€” Zod schemas on all mutating endpoints
  • Testing β€” Vitest (unit tests)

API Reference

All endpoints are prefixed with /api. Auth-required endpoints marked with πŸ”’.

Authentication & user profile

Method Path Auth
POST /api/auth/register
POST /api/auth/login
POST /api/auth/refresh
POST /api/auth/logout πŸ”’
GET /api/auth/me πŸ”’
PUT /api/auth/me πŸ”’
PUT /api/auth/me/password πŸ”’
POST /api/auth/dev-login

Compilations & box sets

Method Path Auth
GET /api/collections/
GET /api/collections/:id
POST /api/collections/ πŸ”’
PUT /api/collections/:id πŸ”’
DELETE /api/collections/:id πŸ”’
POST /api/collections/:id/releases/:releaseId πŸ”’
DELETE /api/collections/:id/releases/:releaseId πŸ”’
POST /api/collections/:id/dlc-releases/:dlcReleaseId πŸ”’
DELETE /api/collections/:id/dlc-releases/:dlcReleaseId πŸ”’

Stats & analytics

Method Path Auth
GET /api/dashboard/stats πŸ”’

DLC / expansions

Method Path Auth
GET /api/dlc/
GET /api/dlc/:id
POST /api/dlc/ πŸ”’
PUT /api/dlc/:id πŸ”’
DELETE /api/dlc/:id πŸ”’
POST /api/dlc/:dlcId/releases πŸ”’
POST /api/dlc/releases/:dlcReleaseId/compatibility πŸ”’
DELETE /api/dlc/releases/:dlcReleaseId/compatibility/:releaseId πŸ”’

Favorites & wishlist

Method Path Auth
GET /api/favorites/
POST /api/favorites/:gameId
DELETE /api/favorites/:gameId

Master games (canonical game entries)

Method Path Auth
GET /api/games/
GET /api/games/:slug
POST /api/games/ πŸ”’
PUT /api/games/:id πŸ”’
DELETE /api/games/:id πŸ”’
POST /api/games/:id/cover πŸ”’
POST /api/games/bulk-cover πŸ”’

Your owned collection

Method Path Auth
GET /api/inventory/
POST /api/inventory/
PUT /api/inventory/:id
DELETE /api/inventory/:id

Reference data (platforms, providers, genres, etc.)

Method Path Auth
GET /api/lookup/platforms
GET /api/lookup/providers
GET /api/lookup/genres
GET /api/lookup/edition-types
GET /api/lookup/media-formats

Release management

Method Path Auth
GET /api/releases/
GET /api/releases/:id
POST /api/releases/ πŸ”’
PUT /api/releases/:id πŸ”’
DELETE /api/releases/:id πŸ”’

Game series & franchises

Method Path Auth
GET /api/series/
GET /api/series/:slug
POST /api/series/ πŸ”’
PUT /api/series/:id πŸ”’
DELETE /api/series/:id πŸ”’

Database Schema

22 tables on PostgreSQL (Neon serverless). Managed with Drizzle ORM.

Lookup Tables

platforms β€” Gaming platforms (Win, PS5, Switch, etc.)

Column Type
id PK
name Platform name
slug URL-safe identifier

providers β€” Storefronts and distribution channels

Column Type
id PK
name Provider name
slug URL-safe identifier

genres β€” Game genres (RPG, FPS, Platformer, etc.)

Column Type
id PK
name Genre name
slug URL-safe identifier

edition_types β€” Edition classification (Original, Remaster, Remake, etc.)

Column Type
id PK
name Edition type name
slug URL-safe identifier

media_formats β€” Physical/digital media types

Column Type
id PK
name Format name
slug URL-safe identifier

Core Game Data

series β€” Game franchises and series groupings

Column Type
id PK
name Series name
slug URL-safe identifier
description Optional description
created_at Timestamp
updated_at Timestamp

master_games β€” Canonical game entries (like Discogs master releases)

Column Type
id PK
title Game title
slug URL-safe identifier
first_release_year Original release year
description Optional description
cover_image_url Cover art URL
series_id FK β†’ series
alternative_titles JSONB array of alternate names
created_at Timestamp
updated_at Timestamp

master_game_genres β€” Junction: games ↔ genres (many-to-many)

Column Type
game_id FK β†’ master_games
genre_id FK β†’ genres

release_groups β€” A specific edition/version grouping of a game

Column Type
id PK
master_game_id FK β†’ master_games
edition_type_id FK β†’ edition_types
edition_name Optional edition label
release_year Year of this edition
created_at Timestamp

releases β€” Concrete releases (platform + store + format combination)

Column Type
id PK
release_group_id FK β†’ release_groups
title Optional variant title
provider_id FK β†’ providers
media_format_id FK β†’ media_formats
intended_for JSONB: target platforms
playable_on JSONB: all compatible platforms
barcode Optional barcode
catalog_number Optional catalog number
publisher Optional publisher
region Optional region code
release_date Optional release date
controller_support Yes/No/Maybe/Not applicable
local_multiplayer Yes/No/Maybe/Not applicable
online_multiplayer Yes/No/Maybe/Not applicable
version_image_url Optional version-specific image
created_at Timestamp

DLC / Expansions

dlcs β€” Downloadable content / expansions

Column Type
id PK
title DLC title
first_release_year Release year
dlc_type Expansion / Season Pass / Bonus Content
master_game_id FK β†’ master_games
created_at Timestamp

dlc_releases β€” Concrete DLC releases (platform + store)

Column Type
id PK
dlc_id FK β†’ dlcs
provider_id FK β†’ providers
media_format_id FK β†’ media_formats
release_date Optional date
on_disc_for_console_only Boolean
created_at Timestamp

dlc_release_compatibility β€” Junction: which DLC releases work with which game releases

Column Type
dlc_release_id FK β†’ dlc_releases
release_id FK β†’ releases

Collections

collections β€” Box sets, compilations, bundles

Column Type
id PK
title Collection name
media_format_id FK β†’ media_formats
release_year Optional year
created_at Timestamp

collection_releases β€” Junction: collections ↔ releases

Column Type
collection_id FK β†’ collections
release_id FK β†’ releases

collection_dlc_releases β€” Junction: collections ↔ DLC releases

Column Type
collection_id FK β†’ collections
dlc_release_id FK β†’ dlc_releases

Users & Ownership

users β€” User accounts

Column Type
id PK
username Unique username
display_name Display name
email Unique email
password_hash Bcrypt hash
created_at Timestamp
updated_at Timestamp

refresh_tokens β€” JWT refresh token store

Column Type
id PK
user_id FK β†’ users
token_hash SHA-256 of refresh token
expires_at Expiration timestamp
created_at Timestamp

user_favorites β€” User favorited games

Column Type
user_id FK β†’ users
master_game_id FK β†’ master_games
created_at Timestamp

owned_instances β€” User's owned copies (the core collection)

Column Type
id PK
user_id FK β†’ users
release_id FK β†’ releases (nullable)
dlc_release_id FK β†’ dlc_releases (nullable)
condition Optional condition (Sealed, etc.)
location Where it's stored (Her, Kurv, bins 1-7, etc.)
notes Free-text notes (includes SheetID for traceability)
acquired_date Optional acquisition date
purchase_price Optional decimal price
created_at Timestamp
updated_at Timestamp

user_game_photos β€” User-uploaded photos and 3D scan models for owned games

Column Type
id PK
user_id FK β†’ users
owned_instance_id FK β†’ owned_instances
image_path Photo file path
scan_model_path Optional 3D scan model path
uploaded_at Timestamp

Commands

Frontend (npm run ...)

Command Description
ng ng
start Start Angular dev server (port 4200)
build Production build to dist/game-viewer/
watch Build in watch mode (development)
test Playwright E2E tests (UI mode)
test:headless Playwright E2E tests (headless)
test:unit npx vitest run
lint Lint TypeScript + HTML (ESLint + Prettier)
lint:fix Lint and auto-fix issues
format Format source files with Prettier
format:check Check formatting without fixing
typecheck TypeScript type checking (tsc --noEmit)
build-readme tsx scripts/build-readme.ts
check npm run lint && npm run format:check && npm run test:unit && npm run build-readme
prepare Install Husky git hooks

Backend (cd server && npm run ...)

Command Description
dev Start backend dev server (port 3001, hot reload)
build Compile backend TypeScript
start Start compiled backend
db:push Push Drizzle schema to database
db:generate Generate Drizzle migrations
db:seed Seed database with demo data
db:import-sheet Import game collection from Google Sheets CSV
test Run backend unit tests (Vitest)
test:watch Run backend tests in watch mode

Configuration

Frontend (proxy.conf.json)

{
  "/api": {
    "target": "http://localhost:3001",
    "secure": false,
    "logLevel": "debug"
  }
}

Backend (.env)

PORT=3001
DATABASE_URL=postgres://postgres:postgres@localhost:5432/gamedb
JWT_SECRET=change-this-to-a-random-secret
JWT_EXPIRES_IN=15m
CORS_ORIGIN=http://localhost:4200
COOKIE_SECRET=change-this-to-a-random-cookie-secret

Dependencies

Frontend

Package Version
@angular/animations ^21.2.14
@angular/common ^21.2.14
@angular/compiler ^21.2.14
@angular/core ^21.2.14
@angular/forms ^21.2.14
@angular/platform-browser ^21.2.14
@angular/platform-browser-dynamic ^21.2.14
@angular/router ^21.2.14
@types/three ^0.184.1
rxjs ~7.8.0
three ^0.184.0
tslib ^2.8.0
zone.js ~0.16.0

Backend

Package Version
@neondatabase/serverless ^0.10.4
bcryptjs ^2.4.3
compression ^1.7.5
cookie-parser ^1.4.7
cors ^2.8.5
dotenv ^16.4.7
drizzle-orm ^0.38.3
express ^4.21.2
express-rate-limit ^7.5.0
helmet ^8.0.0
jsonwebtoken ^9.0.2
uuid ^11.1.0
zod ^3.24.2

Testing

Frontend β€” Playwright E2E

Command Description
npm test Interactive UI mode
npm run test:headless Run all tests headlessly
npx playwright test --headed Run in visible browser
npx playwright test --debug Step-through debugger

Backend β€” Vitest

Command Description
cd server && npm test Run all unit tests
cd server && npm run test:watch Watch mode

Data Import

The project includes a Google Sheets importer that reads the game collection spreadsheet and populates the database.

cd server
# 1. Download your sheet tabs as CSV into server/src/db/imports/
# 2. Run the import:
npm run db:import-sheet

The importer handles:

  • Full games, DLC/expansions, arcade games, demos, shareware
  • Platform backward compatibility (e.g., PS5/PS4 β†’ plays on both)
  • Edition type inference (Original, Remaster, Demake, Enhanced)
  • Collection/compilation grouping
  • Ownership tracking with location and notes
  • Cross-reference to original sheet row IDs

Auto-generated README built 2026-06-16.

Run npm run build-readme to regenerate.

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

1 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors