docs(portal): document the discovery portal, endpoints and mature filter

This commit is contained in:
2026-10-12 18:41:40 -07:00
parent ee6fb4e951
commit 24c895e1a0
11 changed files with 168 additions and 10 deletions
@@ -3,6 +3,10 @@
This document describes the layout components that form the structure of the
Flashpoint Web application.
Public pages use `PortalLayout` instead of `AppShell`; see
[Discovery Portal](../../10-features/12-discovery-portal.md). `AppShell` remains
for settings and admin pages.
## Component Hierarchy
```
+7
View File
@@ -32,6 +32,13 @@ Flashpoint Web frontend.
/activities → ActivitiesView (requires "activities.read")
```
## Layouts
Public routes (home, browse, game and player pages, favorites, playlists,
downloaded, dashboard) render in `PortalLayout`; settings and admin routes
render in `MainLayout` with the sidebar. See
[Discovery Portal](../10-features/12-discovery-portal.md).
## Route Protection
### ProtectedRoute Component
+5
View File
@@ -73,6 +73,11 @@ Default: 100 requests per 15 minutes. Headers: `X-RateLimit-Limit`,
- [GET /api/games/:id/launch](./games-api.md#get-launch-data)
- [GET /api/games/:id/related](./games-api.md#get-related-games)
### Discovery
- [GET /api/discovery/daily](./discovery-api.md#get-game-of-the-day)
- [GET /api/discovery/playlists](./discovery-api.md#get-playlist-shelves)
### Users
- [GET /api/users](./users-api.md#list-users)
+47
View File
@@ -0,0 +1,47 @@
# Discovery API
Homepage picks drawn from the Flashpoint curated playlists (`Data/Playlists`).
Only arcade playlists are used, and mature games are left out unless
`showExtreme=true` (see
[Mature Content](../10-features/12-discovery-portal.md#mature-content)).
## Get Game of the Day
`GET /api/discovery/daily?date=2026-10-12` - No auth required
Query params: `date` (YYYY-MM-DD, default: today in UTC), `showExtreme`
(default: false)
Picks the same game for everyone on a given date, from all curated playlists
combined. Games missing from the install are skipped.
```json
{
"date": "2026-10-12",
"game": { "id": "0a4ffe5c-...", "title": "The World's Hardest Game 4", ... },
"playlist": { "id": "f45d2eb2-...", "title": "Rage for the Ages" }
}
```
Error: `404 Not Found` if no curated games exist
## Get Playlist Shelves
`GET /api/discovery/playlists?count=3&perShelf=7&seed=42` - No auth required
Query params: `count` (default: 3), `perShelf` (games per playlist, default: 7),
`seed` (0-2147483647, default: 0), `showExtreme` (default: false)
Returns `count` curated playlists, each with a sample of its games. The same
seed always returns the same playlists and games.
```json
[
{
"id": "f45d2eb2-...",
"title": "Jingle Jollies",
"total": 30,
"games": [{ "id": "7de03fe2-...", "title": "Christmas Escape", ... }]
}
]
```
+11 -6
View File
@@ -10,10 +10,14 @@ Body (JSON): `search` (title/developer/publisher), `platform`, `series`,
`developers`, `publishers`, `playModes`, `languages`, `library`
(arcade|theatre), `downloaded` (boolean, optional - restrict to games whose
data is present on disk), `tags`, `yearFrom`, `yearTo`, `dateAddedSince` (ISO
datetime), `dateModifiedSince` (ISO datetime), `sortBy`
(title|releaseDate|dateAdded|dateModified|developer, default: title),
`sortOrder` (asc|desc, default: asc), `page` (default: 1), `limit` (default: 50,
max: 100), `showBroken` (default: false), `showExtreme` (default: false)
datetime), `dateModifiedSince` (ISO datetime), `releasedFrom`, `releasedTo`
(YYYY-MM-DD, inclusive; only matches day-precise release dates), `sortBy`
(title|releaseDate|dateAdded|dateModified|developer|random, default: title),
`seed` (0-2147483647, for `random`: the same seed gives the same order across
pages), `sortOrder` (asc|desc, default: asc), `page` (default: 1), `limit`
(default: 50, max: 100), `showBroken` (default: false), `showExtreme` (default:
false, include
[mature games](../10-features/12-discovery-portal.md#mature-content))
Returns paginated array with essential game fields (id, title, developer,
platformName, library, tags, orderTitle).
@@ -39,7 +43,8 @@ with name/code and count.
`GET /api/games/random?library=arcade` - No auth required
Query param: `library` (optional)
Query params: `library` (optional), `platforms` (comma-separated, optional),
`showExtreme` (default: false)
Returns single random game object.
@@ -137,7 +142,7 @@ canPlayInBrowser, and downloading status.
`GET /api/games/:id/related?limit=10` - No auth required
Query param: `limit` (default: 10, max: 50)
Query params: `limit` (default: 10, max: 50), `showExtreme` (default: false)
Returns array of related games based on developer/series/tags.
+2 -1
View File
@@ -67,7 +67,8 @@ Returns key-value pairs (stored as strings). Common keys:
- game_view_mode (grid|list)
- games_per_page (string, numeric)
- auto_play_next (true|false)
- show_extreme_content (true|false)
- show_mature (1|0) - show mature games; see
[Mature Content](../10-features/12-discovery-portal.md#mature-content)
## Update User Settings
+4
View File
@@ -3,6 +3,10 @@
Dynamic theme system with light/dark modes and 22 customizable color palettes.
Uses CSS variables for instant theme switching with Zustand state management.
Public pages are styled by portal color schemes instead, which override these
tokens while mounted; see
[Discovery Portal](../10-features/12-discovery-portal.md#color-schemes).
## Architecture
```
+10 -3
View File
@@ -37,14 +37,19 @@ grid and list view options.
- Platform, Series, Developer, Publisher
- Play Mode, Language, Tags
- Year Range (1970-2100)
- Release date range (day-precise dates, e.g. a Time Machine week)
- Library (arcade/theatre)
- Downloaded only
- Show/hide broken games and extreme content
- Show/hide broken games and
[mature content](./12-discovery-portal.md#mature-content)
**Sorting:**
- By: Title, Release Date, Date Added, Developer
- By: Shuffled (default), Title (default for searches), Release Date, Date
Added, Developer
- Order: Ascending (A-Z) or Descending (Z-A)
- The shuffle seed is kept in the URL so pages keep a stable order; Reshuffle
picks a new one
**Pagination:**
@@ -102,7 +107,9 @@ Get paginated list of games with filters.
- `playModes`, `languages`, `tags` - Comma-separated
- `library` - 'arcade' or 'theatre'
- `yearFrom`, `yearTo` - Release year range
- `sortBy` - 'title', 'releaseDate', 'dateAdded', 'developer'
- `releasedFrom`, `releasedTo` - Release date range (YYYY-MM-DD)
- `sortBy` - 'title', 'releaseDate', 'dateAdded', 'developer', 'random'
- `seed` - Shuffle seed for 'random'
- `sortOrder` - 'asc' or 'desc'
- `page` - Page number
- `limit` - Items per page
+1
View File
@@ -69,6 +69,7 @@ CREATE TABLE system_settings (
#### App Tab
- **Site Name** - Customize application name
- **Tagline** - Optional line shown under the site name in the portal header
- **Maintenance Mode** - Enable/disable maintenance mode
- **Default Theme** - Set default theme (light, dark, system)
- **Default Primary Color** - Set default color scheme
+75
View File
@@ -0,0 +1,75 @@
# Discovery Portal
## Overview
The public pages use an arcade portal layout styled after 2010-era Flash game
sites, with a homepage built for discovery instead of lists of recent changes.
Account and admin pages keep the application layout.
## Shell
`PortalLayout` (`frontend/src/components/portal/`) wraps the homepage, browse,
game, player, favorites, playlists, downloaded and dashboard routes:
- A framed fixed-width page (1180px, desktop first)
- A wordmark built from the **Site Name** setting, with the optional **Tagline**
setting underneath
- Search, and a user menu holding the library, account and admin links and the
mature content switch
- Genre categories linking to browse by tag: Action, Adventure, Puzzle, Shooter,
Platformer, Sports, Strategy, Driving, Escape the Room and Dress Up, plus
Animations
- Keyboard shortcuts: `/` focuses search, `R` opens a random game
## Color Schemes
Portal colors are token sets in `components/portal/schemes.ts`. Each scheme sets
`--p-*` properties for the portal's own styles (`portal.css`) and overrides the
shadcn tokens (`--background`, `--primary`, ...) so shared components match. The
tokens are applied to `<body>` while the portal is mounted, which takes
precedence over the app theme on `<html>` and also reaches dialogs and menus
rendered into the body.
One scheme ships, **Chilled** (slate background, sage boxes). Adding a scheme
means adding an entry to `PORTAL_SCHEMES`; no component changes are needed.
Display text uses Fredoka (OFL, bundled via `@fontsource-variable/fredoka`);
body text uses Verdana.
## Homepage
- **Game of the Day:** the same pick for everyone on a given day, from the
Flashpoint curated playlists, with a link to the previous day's pick
- **Time Machine:** games released in a given week, starting from a random day
between 2005 and 2014. Users can step by week, jump to a random day, or click
the date to pick any day. "See all" opens browse filtered to that week. Only
games with a day-precise release date are included.
- **Jump back in:** the signed-in user's recently played games
- **Playlist shelves:** three random curated playlists with a sample of their
games
See the [Discovery API](../06-api-reference/discovery-api.md).
## Default Ordering
Browse lists default to a shuffle instead of title order. The shuffle is seeded
and the seed is kept in the URL (`seed=`), so paging, back navigation and shared
links keep the same order; Reshuffle picks a new seed. Searches still default to
title order.
## Mature Content
Flashpoint's `extreme` game flag is not set in current metadata, so mature games
are identified the way the Flashpoint Launcher does: by the tag filter groups
marked `extreme` in `preferences.json` (falling back to
`.preferences.defaults.json`, then to the launcher's default groups:
Pornography, Fetishes, Violence, Bigotry and Pornography Extreme).
`MatureContentService` resolves those tags to game IDs once per database load.
Search, random, related games and discovery exclude them unless the request sets
`showExtreme=true`.
Users opt in with **Show mature games** in the user menu. The choice is stored
in the browser (`flashpoint-mature-content`), and for signed-in users also in
the account's `show_mature` setting, which is applied when they sign in on
another browser.
+2
View File
@@ -27,6 +27,8 @@ Web application.
date/time formatting and localization across the application
11. [Maintenance Mode](./11-maintenance-mode.md) - Temporarily restrict access
during system updates while allowing admin access
12. [Discovery Portal](./12-discovery-portal.md) - Arcade portal layout, color
schemes, discovery homepage and mature content filtering
## Quick Reference