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.
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
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)
^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)
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
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
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)
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
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
π
Method
Path
Auth
GET
/api/dashboard/stats
π
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
π
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
π
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
Method
Path
Auth
GET
/api/releases/
GET
/api/releases/:id
POST
/api/releases/
π
PUT
/api/releases/:id
π
DELETE
/api/releases/:id
π
Method
Path
Auth
GET
/api/series/
GET
/api/series/:slug
POST
/api/series/
π
PUT
/api/series/:id
π
DELETE
/api/series/:id
π
22 tables on PostgreSQL (Neon serverless). Managed with Drizzle ORM.
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
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
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 β 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 β 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
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
Frontend (proxy.conf.json)
{
"/api" : {
"target" : " http://localhost:3001" ,
"secure" : false ,
"logLevel" : " debug"
}
}
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
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
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
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
Command
Description
cd server && npm test
Run all unit tests
cd server && npm run test:watch
Watch mode
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.