Documentation Index
Fetch the complete documentation index at: https://mintlify.com/dreancaste/TriviaPP/llms.txt
Use this file to discover all available pages before exploring further.
TriviaPP is an Angular single-page application (SPA) wrapped by Ionic for its component library and by Capacitor for its native Android runtime. The app follows Angular’s injectable service pattern — all business logic, data fetching, and persistence is encapsulated in dedicated services, keeping page components thin and focused purely on presentation. Authentication is split across two systems: AWS Amplify (Cognito) handles identity and session tokens, while Firebase Firestore stores online leaderboard scores. Persistence is similarly split: localStorage handles all per-device data (profile, history, local ranking, stats), while Firestore handles the shared daily ranking visible to all players.
Service Layer
Each Angular service has a single, clearly defined responsibility. All services are provided at the root level (providedIn: 'root').
AuthService
Wraps the AWS Amplify Auth module and is the sole entry point for all identity operations in the app:
| Method | Amplify function | Description |
|---|
register(email, password) | signUp | Creates a new Cognito user |
confirmarRegistro(email, code) | confirmSignUp | Verifies the email confirmation code |
login(email, password) | signIn | Signs the user in and caches their email in memory |
logout() | signOut | Signs the user out and clears the cached email |
getCurrentUser() | getCurrentUser | Returns the currently authenticated Amplify user, or null |
obtenerTokenJWT() | fetchAuthSession | Returns the Cognito idToken JWT string for the current session |
TriviaService
Generates trivia questions for each game round by combining two sources:
- 60% lore questions — drawn from a curated bank of 19 static Star Wars lore questions (characters, events, factions). Questions already shown in the current session are tracked in
usedQuestionKeys to prevent repeats.
- 40% SWAPI questions — generated dynamically by calling
SwapiService. Three question types are possible: character homeworld (generatePeopleQuestion), planet climate (generatePlanetQuestion), and film director (generateFilmQuestion). Planet climate answers are passed through TranslationService to translate them from English to Spanish before display.
If all lore questions have been used in the current session, usedQuestionKeys resets automatically and the pool refills.
SwapiService
A lightweight HTTP wrapper around the Star Wars API (https://swapi.py4e.com/api). All methods return Promises via RxJS firstValueFrom.
| Method | Endpoint |
|---|
getPeople(page) | GET /people/?page={page} |
getPerson(id) | GET /people/{id}/ |
getPlanets(page) | GET /planets/?page={page} |
getPlanet(id) | GET /planets/{id}/ |
getFilms() | GET /films/ |
getFilm(id) | GET /films/{id}/ |
getByUrl(url) | GET {url} (follows SWAPI resource URLs, e.g. homeworld links) |
StorageService
Manages all localStorage-backed persistence. The service defines five storage keys:
| Key | Type | Contents |
|---|
sw_profile | Profile | Display name, avatar (base64), haptics preference |
sw_history | HistoryItem[] | All past game results, newest first |
sw_ranking | RankingItem[] | Local top-20 leaderboard, sorted by score descending |
sw_stats | object | Lifetime stats: gamesPlayed, correctAnswers, maxScore |
sw_ranking_reset_time | timestamp | Unix ms timestamp of the last local ranking reset |
The local ranking automatically resets every 24 hours. On each read or write to the ranking, checkAndResetRanking() compares the current time against sw_ranking_reset_time. If more than 24 hours have elapsed, sw_ranking is cleared and the reset timestamp is updated.
RankingService
Reads and writes the online daily leaderboard stored in Firebase Firestore. Each score entry is a document in the ranking collection with three fields: name, score, and date (ISO date string, e.g. "2025-01-15").
| Method | Description |
|---|
addScore(name, score) | Adds a new document to the ranking collection with today’s date |
getDailyRanking() | Queries the collection ordered by score descending, then filters client-side to return only today’s entries |
TranslationService
Calls the MyMemory Translation API (https://api.mymemory.translated.net) to translate English SWAPI text into Spanish (language pair en|es). The API has a query-length limit; TranslationService handles this automatically:
- Texts of 450 characters or fewer are sent in a single request.
- Texts longer than 450 characters are split into sentence-boundary-aware chunks via
splitForApi(), each chunk is translated in parallel with Promise.all, and the results are joined back together.
If a request fails or the API returns a QUERY LENGTH LIMIT EXCEEDED error, the original English text is returned as a fallback.
WikiContentService
Drives the in-app Star Wars wiki by combining static configuration (section definitions, navigation structure, and references to visual guide assets stored under src/app/data/) with dynamic translation. It delegates translation to TranslationService and uses a local cache (translationCache) to avoid re-requesting the same strings. It also builds Star Wars Visual Guide image URLs (https://starwars-visualguide.com/assets/img/{type}/{id}.jpg) and generates fallback curiosity facts from raw SWAPI entity fields when no curated facts are available for a given entity.
External Integrations
| Service | Purpose | URL / SDK |
|---|
| SWAPI | Live Star Wars character, planet, and film data | https://swapi.py4e.com/api |
| AWS Amplify / Cognito | User registration, email confirmation, login, session tokens | aws-amplify npm package |
| Firebase Firestore | Online daily leaderboard | firebase npm package |
| MyMemory Translation API | Translate SWAPI English answers to Spanish | https://api.mymemory.translated.net |
| Capacitor Camera | Capture and set the player’s profile photo | @capacitor/camera |
| Capacitor Haptics | Vibrate the device when the player selects a wrong answer | @capacitor/haptics |
Authentication Flow
TriviaPP uses a two-step registration flow powered by AWS Amplify and Amazon Cognito:
- Register — The player submits their email and password on the register page.
AuthService.register() calls Amplify signUp, which creates an unconfirmed Cognito user and sends a confirmation code to the player’s email.
- Confirm — The player enters the six-digit code on the confirmation screen.
AuthService.confirmarRegistro() calls Amplify confirmSignUp. On success, the account is activated.
- Login — The player signs in with their email and password.
AuthService.login() calls Amplify signIn. On success, Amplify stores a JWT session internally; AuthService also caches the email in memory for the current app session.
- Session check —
AuthGuard calls AuthService.getCurrentUser() (which wraps Amplify getCurrentUser) on every navigation to a protected route. If no authenticated user is found, the guard redirects to /login.
- Token access — Any service that needs to make an authenticated API call can retrieve the Cognito
idToken JWT string via AuthService.obtenerTokenJWT(), which wraps Amplify fetchAuthSession.
Data Persistence
TriviaPP uses two distinct persistence layers that serve different scopes:
| Data | Storage | Scope | Reset cadence |
|---|
| Player profile (name, avatar, haptics setting) | localStorage (sw_profile) | Device-local | Never (manual update only) |
| Game history | localStorage (sw_history) | Device-local | Never (accumulates indefinitely) |
| Local ranking (top 20) | localStorage (sw_ranking) | Device-local | Automatic every 24 hours |
| Lifetime stats | localStorage (sw_stats) | Device-local | Never (accumulates indefinitely) |
| Online daily ranking | Firebase Firestore (ranking collection) | Shared across all players | New entries each day; old entries remain but are filtered out client-side |
Routing
All routes are defined in src/app/app-routing.module.ts using Angular’s lazy-loaded module pattern. The root path ("") redirects to login.
| Route | Module | AuthGuard | Notes |
|---|
/login | LoginPageModule | ❌ No | Entry point for returning users |
/register | RegisterPageModule | ❌ No | New user registration and email confirmation |
/home | HomePageModule | ✅ Yes | Main menu after login |
/profile | ProfilePageModule | ✅ Yes | Display name, avatar, stats |
/trivia | TriviaPageModule | ✅ Yes | Active game session |
/ranking | RankingPageModule | ✅ Yes | Online and local leaderboard |
/history | HistoryPageModule | ✅ Yes | Past game results |
/wiki | WikiPageModule | ❌ No | Star Wars wiki (public) |
All routes use PreloadAllModules as the preloading strategy, so Angular begins downloading lazy module bundles in the background immediately after the initial page load.
The /wiki route is intentionally not protected by AuthGuard. Players and visitors can browse Star Wars wiki content without creating an account or logging in. This is the only content section accessible without authentication.