Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
5859de5
chore: set up monorepo with workspaces, linting and CI
Sep 30, 2026
19cd994
docs: add deployment guide, systemd unit and Apache config
Sep 30, 2026
528ea5f
Merge branch 'feat/m5-deploy'
Sep 30, 2026
6fc9567
docs: define GraphQL API contract
Sep 30, 2026
e329ce1
test: add Playwright configuration
Sep 30, 2026
b0cfb74
chore: add one-shot VM setup script
Sep 30, 2026
7eec93b
feat(frontend): add search, filters, detail page, reviews and my list
Sep 30, 2026
aaf9657
Merge branch 'feat/frontend'
Sep 30, 2026
df85e3e
feat(backend): add schema, streaming IMDb import and GraphQL API
Sep 30, 2026
6ce063e
Merge branch 'feat/backend'
Sep 30, 2026
47504d9
fix(backend): rank popular titles higher in relevance sort
Sep 30, 2026
9f3ff47
Merge branch 'fix/relevance-popularity'
Sep 30, 2026
43052d2
fix(frontend): prevent layout shift from footer and scrollbar
Sep 30, 2026
50cb89d
test: add Playwright end-to-end and axe accessibility tests
Sep 30, 2026
24b4130
Merge branch 'fix/layout-shift'
Sep 30, 2026
7ab6ae9
Merge branch 'test/e2e'
Sep 30, 2026
fdd6d0a
docs: add status summary, Lighthouse results and complete plan
Sep 30, 2026
e2fe1e9
Merge branch 'docs/status'
Sep 30, 2026
bf3a7de
fix(deploy): fail setup when the API does not respond
Sep 30, 2026
3164ed7
Merge branch 'fix/setup-check'
Sep 30, 2026
5e6e16a
chore(deploy): add VM diagnostics script
Sep 30, 2026
ed3a51f
Merge branch 'chore/check-script'
Sep 30, 2026
06e7568
fix(frontend): generate user id without crypto.randomUUID on plain http
Sep 30, 2026
62c18aa
Merge branch 'fix/uuid-insecure-context'
Sep 30, 2026
cd372be
docs: record successful deployment to the VM
Sep 30, 2026
6bc294d
Merge branch 'docs/deployed'
Sep 30, 2026
37960db
fix(deploy): add security headers to Apache config
Sep 30, 2026
b874eee
Merge branch 'fix/security-headers'
Sep 30, 2026
ba1d689
feat: add TMDB artwork and cinematic UI (backend tests pending)
Sep 30, 2026
8cfbf8f
test(backend): fix width snapping expectation
Sep 30, 2026
d941cfb
Merge branch 'feat/artwork-and-cinematic-ui'
Sep 30, 2026
3cff0cd
Merge pull request #1 from Nicolaykopaas/claude/webutvikling-projekt-…
Sep 30, 2026
e21ecce
docs: add README
Sep 30, 2026
7eb1a13
Merge branch 'docs/readme'
Sep 30, 2026
ea86149
Merge pull request #2 from Nicolaykopaas/Main
Sep 30, 2026
ad993d0
Merge README into main
Sep 30, 2026
ef81f54
fix(deploy): force LF line endings and refuse to run outside the VM
Sep 30, 2026
ad798bb
Merge branch 'fix/script-line-endings'
Sep 30, 2026
98f55ca
Merge LF line ending fix into main
Sep 30, 2026
130e35d
chore(deploy): report TMDB key and artwork status in check script
Sep 30, 2026
dcdde41
Merge branch 'chore/check-tmdb'
Sep 30, 2026
fe0e304
Merge TMDB status check into main
Sep 30, 2026
b82697d
fix(deploy): validate TMDB key and prompt again after a bad paste
Sep 30, 2026
068d82f
Merge branch 'fix/tmdb-key-prompt'
Sep 30, 2026
b13e470
Merge TMDB key validation into main
Sep 30, 2026
20b25ed
chore(deploy): add one-command update script for the VM
Sep 30, 2026
a3113aa
Merge branch 'chore/update-script'
Sep 30, 2026
aeea708
Merge VM update script into main
Sep 30, 2026
6e56ade
fix: expose db:artwork script at the repo root
Sep 30, 2026
41477e6
Merge branch 'fix/root-artwork-script'
Sep 30, 2026
a483dd9
Merge root db:artwork script into main
Sep 30, 2026
e3c38e4
chore(deploy): pull latest code in update script
Sep 30, 2026
bf427b3
Merge branch 'chore/self-updating-script'
Sep 30, 2026
31fb030
Merge self-updating VM script into main
Sep 30, 2026
e1aa58d
docs: document one-line VM update
Sep 30, 2026
c24d103
Merge branch 'docs/one-line-deploy'
Sep 30, 2026
492e209
Merge one-line deploy docs into main
Sep 30, 2026
94548ea
docs: shorten README with roles and pipeline
Sep 30, 2026
e48e66b
Merge branch 'docs/short-readme'
Sep 30, 2026
e52d05b
Merge short README into main
Sep 30, 2026
9cb76b1
docs: plan M6 legal streaming from Internet Archive
Sep 30, 2026
724a8f2
Merge branch 'docs/plan-m6'
Sep 30, 2026
cfb7979
feat: stream public domain films from Internet Archive with accessibl…
Sep 30, 2026
bd4a353
Merge branch 'feat/archive-streaming'
Sep 30, 2026
d4e202f
Merge Internet Archive streaming into main
Sep 30, 2026
4783306
chore: import project from private repository
daniekm Oct 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .claude/DONE
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
MVP ferdig og verifisert 2026-09-30. Se docs/status.md.
13 changes: 13 additions & 0 deletions .claude/agents/backend-utvikler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
name: backend-utvikler
description: Implementerer database, importskript og GraphQL-API (Node + TypeScript + PostgreSQL). Bruk for alt under backend/.
model: sonnet
---

Du er backend-utvikler i IT2810-prosjektet. Følg CLAUDE.md.

- Jobb kun i `backend/` og delte konfigfiler du blir bedt om.
- All søk/filter/sortering i SQL, parameteriserte spørringer, cursor-paginering.
- Skriv eller oppdater tester for det du endrer (Vitest mot testdatabase).
- Kjør `npm run lint -w backend && npm run typecheck -w backend && npm test -w backend` før du svarer.
- Svar lederen kort: hva endret, hvilke filer, testresultat, evt. åpne problemer. Ikke commit – lederen gjør det.
15 changes: 15 additions & 0 deletions .claude/agents/frontend-utvikler.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
name: frontend-utvikler
description: Implementerer React/TypeScript/Vite-klienten med Apollo Client. Bruk for alt under frontend/.
model: sonnet
---

Du er frontend-utvikler i IT2810-prosjektet. Følg CLAUDE.md.

- Jobb kun i `frontend/`.
- Semantisk HTML, tastaturstøtte, synlig fokus, labels på alle input, `aria-live` der innhold endres.
- Ingen sortering/filtrering på klienten – alt via GraphQL-variabler.
- Hold bundlen liten; spør deg selv om hvert nytt bibliotek er nødvendig.
- Skriv komponenttester (Vitest + Testing Library) for det du lager.
- Kjør `npm run lint -w frontend && npm run typecheck -w frontend && npm test -w frontend` før du svarer.
- Svar lederen kort: hva endret, hvilke filer, testresultat, evt. åpne problemer. Ikke commit.
11 changes: 11 additions & 0 deletions .claude/agents/reviewer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
---
name: reviewer
description: Går gjennom en endring (diff) for korrekthet, sikkerhet, tilgjengelighet og etterlevelse av CLAUDE.md.
model: sonnet
---

Du er reviewer i IT2810-prosjektet. Følg CLAUDE.md.

- Les diffen lederen peker på. Se etter feil, SQL-injeksjon, manglende validering, klient-side sortering/filtrering, a11y-brudd og utestede kanttilfeller.
- Rangér funn: blokkerende / bør fikses / valgfritt. Oppgi fil og linje.
- Ikke endre kode selv. Svar kort. Ikke commit.
12 changes: 12 additions & 0 deletions .claude/agents/tester.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
name: tester
description: Kjører og utvider tester (Vitest, Testing Library, Playwright + axe). Bruk etter hver endring for å verifisere.
model: sonnet
---

Du er tester i IT2810-prosjektet. Følg CLAUDE.md.

- Kjør relevante tester for endringen og rapporter nøyaktig hva som feilet (kommando + utdrag av output).
- Legg til tester for utypisk bruk: tomt søk, ingen treff, spesialtegn, veldig lange strenger, nettverksfeil.
- Ikke endre produksjonskode; foreslå heller fiks til lederen.
- Svar lederen kort: hvilke tester, resultat, evt. funn. Ikke commit.
9 changes: 9 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
root = true

[*]
charset = utf-8
end_of_line = lf
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
28 changes: 28 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Kopier til .env og tilpass. .env skal aldri committes.

# Backend
PORT=3001
DATABASE_URL=postgres://postgres@localhost:5432/project2
# Egen database for tester – tømmes av testene.
TEST_DATABASE_URL=postgres://postgres@localhost:5432/project2_test
# Tillatt opprinnelse for CORS i utvikling (Vite dev-server).
CORS_ORIGIN=http://localhost:5173

# Import: mappe med title.basics.tsv.gz og title.ratings.tsv.gz
IMDB_DATA_DIR=./data
# Minste antall stemmer for at en tittel tas med
IMDB_MIN_VOTES=100

# Frontend (valgfri – standard er <base>/graphql)
VITE_GRAPHQL_URL=

# Bilder og handling fra TMDB (https://www.themoviedb.org/settings/api). Uten nøkkel vises
# plassholdere i stedet for plakater.
TMDB_API_KEY=
# Overstyres i utvikling/E2E for å bruke den lokale falske TMDB-serveren (npm run tmdb:mock -w backend):
# TMDB_API_URL=http://localhost:3999/3
# TMDB_IMAGE_URL=http://localhost:3999/t/p

# Lovlige gratisfilmer fra Internet Archive (npm run db:archive). Standard er den ekte tjenesten;
# pek mot den falske serveren (npm run archive:mock -w backend) i utvikling/E2E:
# ARCHIVE_URL=http://localhost:3998
5 changes: 5 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Skallskript må ha LF også når repoet klones på Windows (core.autocrlf), ellers feiler bash
# med «set: pipefail\r: invalid option name».
*.sh text eol=lf
*.service text eol=lf
*.conf text eol=lf
18 changes: 18 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
node_modules/
dist/
coverage/
*.log
.env
.env.*
!.env.example
data/*.tsv
data/*.tsv.gz
!data/.gitkeep
playwright-report/
test-results/
blob-report/
.vite/
*.tsbuildinfo
.DS_Store
.claude/DONE.local
data/e2e/
41 changes: 41 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# CI for IT2810 prosjekt 2: lint, typecheck og enhetstester på hver push/MR.
default:
image: node:22
cache:
key:
files:
- package-lock.json
paths:
- .npm/
before_script:
- npm ci --cache .npm --prefer-offline

stages:
- check
- test

variables:
HUSKY: '0'

lint:
stage: check
script:
- npm run lint

typecheck:
stage: check
script:
- npm run typecheck

unit-tests:
stage: test
services:
- name: postgres:16
alias: postgres
variables:
POSTGRES_DB: project2_test
POSTGRES_USER: postgres
POSTGRES_HOST_AUTH_METHOD: trust
TEST_DATABASE_URL: postgres://postgres@postgres:5432/project2_test
script:
- npm test
1 change: 1 addition & 0 deletions .husky/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
npx lint-staged
7 changes: 7 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
node_modules
dist
coverage
playwright-report
test-results
package-lock.json
data
6 changes: 6 additions & 0 deletions .prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"singleQuote": true,
"semi": true,
"trailingComma": "all",
"printWidth": 100
}
8 changes: 8 additions & 0 deletions BLOCKERS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# Blokkeringer som krever Nicolay

Punkter her kan ikke løses av agentene alene. Hvert punkt sier hva som trengs.

- ~~**IMDb-datasettet kunne ikke lastes ned i utviklingsmiljøet.**~~ Løst: importert på VM-en av Nicolay 2026-09-30. Sky-containeren agentene kjørte i har
en nettverkspolicy som blokkerer `datasets.imdbws.com` (HTTP 403 fra proxyen). Importskriptet er
skrevet for de ekte filene og testet mot et syntetisk datasett i samme format
(`npm run db:fixture -w backend`). Last ned de ekte filene selv og kjør importen, se `docs/oppsett.md`.
47 changes: 47 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# IT2810 Prosjekt 2 – regler for Claude Code

Du jobber autonomt. Nicolay ser ikke på skjermen før prosjektet er ferdig. Ikke still spørsmål, ta fornuftige valg og dokumenter dem i `docs/beslutninger.md`.

## Roller

- **Hovedsesjonen (Opus) er daglig leder.** Den planlegger, deler opp arbeid, delegerer til subagenter, verifiserer og krysser av i `PLAN.md`. Lederen skriver helst ikke produksjonskode selv.
- **Subagenter (Sonnet):** `backend-utvikler`, `frontend-utvikler`, `tester`, `reviewer`. Gi dem små, avgrensede oppgaver med tydelig ferdigkriterium. Kjør uavhengige oppgaver parallelt.

## Arbeidsløkke (hver runde)

1. Les `PLAN.md` og `BLOCKERS.md`.
2. Velg neste uavkryssede punkt (eller flere uavhengige).
3. Deleger → la `reviewer` gå gjennom endringen → la `tester` kjøre relevante tester.
4. Kjør selv `npm run lint && npm run typecheck && npm test` i berørte pakker. Rødt = ikke ferdig.
5. Commit, kryss av i `PLAN.md`, skriv én linje i `docs/ki-logg.md`.
6. Er alle MVP-kriterier oppfylt og verifisert: opprett filen `.claude/DONE`.

## Git

- Jobb alltid på grener fra `mvp`. Aldri commit eller push til `main`, aldri force-push.
- Én gren per oppgave (`feat/…`, `fix/…`, `test/…`), merge til `mvp` når review og tester er grønne.
- Små commits med Conventional Commits-meldinger på engelsk.
- Hvis `glab` er innlogget: opprett issue per PLAN-punkt og MR mot `mvp`, reviewer kommenterer i MR-en. Ellers: gjør det samme lokalt og loggfør i `docs/ki-logg.md`.

## Tekniske rammer (ikke avvik uten å skrive begrunnelse i beslutninger.md)

- Monorepo: `frontend/` (React + TS + Vite), `backend/` (Node + TS + GraphQL), npm workspaces.
- State: Apollo Client (cache + reactive vars). URL speiler søk/filter/sortering.
- Database: PostgreSQL, ingen Docker. `pg_trgm` + GIN-indekser. Migrasjoner og importskript i repo.
- Søk, filter og sortering skjer ALLTID i SQL på hele datasettet. Cursor-basert paginering.
- Søk debounces (300 ms). Ingen requests for tomme eller uendrede søk.
- Backend på port 3001. Frontend bygges med `base: '/project2/'`.
- Tilgjengelighet: WCAG 2.1 AA, semantisk HTML, tastatur overalt, synlig fokus, `aria-live` for antall treff.
- Bærekraft: lazy-loading, små bilder, ingen tunge biblioteker uten grunn, mørk modus, cache.
- Kommentarer skrives for eksterne lesere: forklar _hvorfor_, ikke _hva_.

## Tester

- Vitest + Testing Library for komponenter, Vitest for GraphQL-resolvere mot testdatabase, Playwright for E2E.
- Test både vanlig og utypisk bruk: tomt søk, ingen treff, spesialtegn, veldig lange strenger, nettverksfeil.

## Grenser

- Ingen `sudo`, ingen endringer utenfor repoet, ingen hemmeligheter i git (`.env` i `.gitignore`, `.env.example` i repo).
- README.md skrives av gruppa. Agentene legger bare fakta og installasjonssteg i `docs/`, som gruppa kan bygge README på.
- Står du fast på noe som krever Nicolay (passord, VM, VPN, tilganger): skriv det i `BLOCKERS.md` og gå videre.
72 changes: 72 additions & 0 deletions PLAN.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# PLAN – MVP

Målet er nådd når alle bokser under er krysset av og verifisert. Lederen krysser av, ikke utviklerne.

## Datasett (standardvalg)

IMDb non-commercial datasets (`title.basics.tsv.gz`, `title.ratings.tsv.gz`) fra https://datasets.imdbws.com – ingen API-nøkkel. Filtrer til filmer og serier med minst 100 stemmer (~100k+ rader). Bilder hoppes over i MVP (bærekraft), evt. placeholders.
Brukergenererte data: anmeldelser (1–5 stjerner + tekst) og "min liste".

## M0 – Oppsett

- [x] Monorepo med npm workspaces, TypeScript strict, ESLint, Prettier, Husky + lint-staged
- [x] Scripts i rot: `dev`, `build`, `lint`, `typecheck`, `test`, `test:e2e`, `db:migrate`, `db:seed`
- [x] `.env.example`, `.gitignore`, `docs/beslutninger.md`, `docs/ki-logg.md`, `BLOCKERS.md`
- [x] GitLab CI (`.gitlab-ci.yml`): lint, typecheck, unit-tester

## M1 – Database og import

- [x] Skjema + migrasjoner (titles, genres, reviews, lists), indekser inkl. `pg_trgm` GIN på tittel
- [x] Importskript som strømmer TSV (ikke les alt i minnet) og kan kjøres på nytt (idempotent)
- [x] `EXPLAIN ANALYZE` for søk før/etter indeks lagret i `docs/ytelse.md`

## M2 – GraphQL-API

- [x] `search(query, filters, sort, first, after)` med connection-type (edges, pageInfo, totalCount)
- [x] `title(id)` med detaljer og anmeldelser
- [x] `facets(query, filters)` → antall treff per sjanger / tiår / type
- [x] Mutations: `addReview`, `toggleList` (anonym bruker-id via cookie/localStorage-uuid)
- [x] Input-validering, feilhåndtering, maks `first`, query-dybde begrenset
- [x] API-tester for alle queries/mutations inkl. kanttilfeller

## M3 – Frontend

- [x] Søkefelt med debounce, case-insensitivt, tøm-knapp
- [x] Resultatliste med uendelig scroll + "Last flere"-knapp, skeleton-lasting
- [x] Filterpanel (sjanger, tiår, type, min. rating) med antall treff, aktive filtre som chips, nullstill
- [x] Sortering (relevans, rating, år, tittel) – alltid på server
- [x] Detaljside med anmeldelser og skjema for ny anmeldelse
- [x] "Min liste"-side
- [x] State i URL, tilbake-knapp bevarer scroll
- [x] Tomt/ingen treff/feil-tilstander med "prøv igjen"
- [x] Mørk modus (følger system), responsivt ned til 320 px

## M4 – Kvalitet

- [x] Komponenttester for søk, liste, filter, detaljside, anmeldelsesskjema
- [x] Playwright E2E: søk → filtrer → sorter → scroll → detalj → skriv anmeldelse → se den i lista
- [x] axe-sjekk i Playwright uten feil på alle sider
- [x] Lighthouse ≥ 90 på alle kategorier (resultat i `docs/ytelse.md`)
- [x] Alle tester, lint og typecheck grønne fra ren klon (`npm ci`)

## M5 – Deploy-klargjøring (kjøres ikke mot VM uten Nicolay)

- [x] `docs/deploy.md`: Postgres-oppsett, systemd-fil for backend, Apache-konfig for `/project2`, gzip/cache-headere
- [x] `deploy/`-mappe med systemd-unit og Apache-konfig ferdig utfylt for `it2810-17.idi.ntnu.no`

## M6 – Se lovlige filmer fra Internet Archive

Kun filmer som Internet Archive markerer som fri bruk (public domain eller Creative Commons). Vi
lenker til og strømmer fra archive.org og lagrer ingen video selv.

- [x] Backend: tabell `title_streams` (title_id, archive_id, fil, lisens, varighet) + migrering
- [x] Importskript `db:archive`: hent filmer fra Internet Archive-samlinger med fri lisens, koble til IMDb-titler via IMDb-ID i metadata (ellers tittel + år), velg en MP4-fil som nettlesere kan spille. Idempotent, testet mot falsk Archive-server
- [x] API: `Title.stream { url, license, archiveUrl }` og filter `availableOnly` (+ fasettantall)
- [x] Frontend: filter «Kun filmer du kan se», rad «Se gratis nå» på forsiden, merke på plakater
- [x] Videospiller på `/watch/:id`: spill/pause, spoling (tidslinje og ±10 s), volum og demping, fullskjerm, tastatur (mellomrom, piler, M, F), undertekster når de finnes, lisens og kilde under spilleren
- [x] Tester: import og kobling, API, spillerkontroller (komponent), E2E med liten testvideo, axe
- [x] Deploy: `setup-vm.sh` kjører `db:archive` etter importen

## Ferdig

- [x] Oppsummering i `docs/status.md`: hva er gjort, hva gjenstår, hva Nicolay må gjøre
Loading