Project Overview & Astro + a Thin API Backend Setup
Premier League Predictor: Astro
Chapter 1 · Project Overview & Astro + a Thin API Backend Setup
This is the fourth course built in the Premier League Predictor set — after Premier League Predictor: FastAPI & PostgreSQL (the full relational reference implementation) and Premier League Predictor: Django & MySQL, both complete, with Premier League Predictor: FastAPI & Redis still outlined. This variant takes a genuinely different angle from all three: rather than standing up a separate backend framework and API service, it builds the entire app — pages and data layer alike — inside a single real Astro project, using Astro's own native server endpoints instead of a separate service. That makes this the most direct "how would this actually live on my real site" story of the whole set, since the site this predictor is meant to eventually join is itself already built in Astro.
What the App Actually Does
The same shared spec every course in this set builds toward — a personal, weekly Premier League prediction tracker, not a generic sports app:
- Track every fixture across a real 38-gameweek Premier League season, 20 teams, 10 fixtures per gameweek.
- Record four real prediction sources per fixture:
- the user's own prediction,
- the BBC's expert prediction (currently Chris Sutton),
- that week's guest predictor(s) — genuinely variable; some weeks have more than one guest, whose scores get averaged into a single "guest" figure for that week,
- and the BBC's own published AI-generated prediction, manually transcribed each week rather than scraped or generated by this app.
- Score two different things per prediction once a result is in — a correct score (the exact scoreline matched) and a correct result (the predicted win/draw/loss outcome matched, even if the scoreline itself was wrong).
- Maintain the real league table — points (3/1/0), goal difference, wins/draws/losses — alongside a second, parallel prediction league table ranking how each of the four real predictors is actually doing across the season.
- Handle promotion and relegation between seasons — the bottom three teams are auto-calculated and removed at season end; the three promoted teams are entered manually, since which teams come up from the Championship isn't something this app tracks on its own.
Fixture entry is deliberately fast to use, not a generic form. Ten fixtures a week, every single week, for 38 weeks — a dropdown-heavy "select home team, select away team" form for every one of them would be genuinely tedious. Chapter 4 builds a real click-to-pair interface instead: 20 clickable team buttons, paired directly into home/away boxes.
Why Astro for This One
Of the four variants in this set, this is the one built specifically to answer "could this genuinely just be a page on my real site" — and Astro's own real feature set makes that possible without reaching for a second framework at all:
- Astro's own server endpoints are the backend. A file under
src/pages/api/exporting aGETorPOSTfunction is a real, working API route — there's no separate Express server, no separate FastAPI process, nothing extra to deploy alongside the site itself. - A single SQLite file, not a database server. A personal hobby project run by one person doesn't need a standalone PostgreSQL or MySQL server sitting on standby —
better-sqlite3reads and writes one plain file on disk, which is exactly the amount of database this app actually needs. - Per-page rendering control, decided route by route. Astro can serve some pages statically and others on demand from the very same project, which turns out to matter a great deal for a data-driven app like this one — covered in real depth in Chapter 10.
astro1 (Astro) course already covers Astro's own component model, file-based routing, and static-first rendering philosophy in real depth, and website-rebuild-with-astro1 covers a full real Astro site rebuild. This course doesn't re-teach any of that — it assumes it, and moves straight into this predictor's own real schema, endpoints, and features.
Setting Up: Astro, Server Endpoints & SQLite
A local Node.js install is assumed from here on. Scaffold a fresh Astro project first:
Astro renders every page statically by default. Since this app needs real, on-demand server logic — API routes, an admin area that writes to the database — astro.config.mjs needs to switch the whole project over to server output first:
A minimal project structure, following this site's own established Astro project convention rather than inventing a new one:
A minimal health-check endpoint, confirming the setup works before any real route exists:
Visiting http://localhost:4321/api/health should return {"status":"ok"} — a real, live server response coming straight out of the Astro project itself, with no second process running anywhere.
output: 'server' makes every page in the project server-rendered on each request by default, not just the API routes — including pages that don't actually need it, like a mostly-static "About this tracker" page, if one ever gets added. That's the right tradeoff for this chapter, since almost every page this app needs really is dynamic. Chapter 10 comes back to this directly: Astro lets an individual page opt back into static prerendering with a single export const prerender = true line, and by then it'll be clear exactly which of this app's own pages can genuinely take advantage of that.
Where This Course Is Headed
A real SQLite schema for teams, seasons, gameweeks, and fixtures (Chapter 2); managing the 20 competing teams each season (Chapter 3); the fast click-to-pair fixture-entry UI (Chapter 4); recording all four prediction sources per fixture (Chapter 5); entering results and applying the confirmed 40/10 scoring (Chapter 6); the real league table (Chapter 7); the parallel prediction league table (Chapter 8); promotion and relegation between seasons (Chapter 9); Astro islands and exactly where client-side JavaScript actually earns its place in a static-first framework (Chapter 10); deployment (Chapter 11); and a capstone on mounting this predictor directly onto the real, live Astro site (Chapter 12).
Hands-On Exercises
Explain the real difference between a "correct score" and a "correct result" prediction, and describe one real scenario where a prediction earns the 10-point correct-result score but not the 40-point correct-score bonus.
📄 View solutionExplain why this app averages multiple guest predictors into a single "guest" figure for weeks with more than one guest, rather than tracking each guest as a permanently separate predictor across the season.
📄 View solutionSet up the Astro project and the /api/health route yourself, confirm it responds with a real server request, then explain — in your own words — the real difference between a page that's server-rendered on every request under output: 'server' and one that opts back into static prerendering with export const prerender = true.
Chapter 1 Quick Reference
- The shared app — a weekly Premier League prediction tracker: 4 real prediction sources per fixture (user, BBC expert, guest(s) averaged, BBC AI), scored 40 points for a correct score and 10 for a correct result, across a real 38-gameweek season
- Two league tables — the real Premier League table, plus a parallel prediction league table ranking predictor performance
- Promotion/relegation — bottom 3 auto-calculated and removed; the 3 promoted teams entered manually
- Why this variant — Astro's own native server endpoints as the entire backend, plus a single-file SQLite database — the most direct "bolt this onto my real site" story of the whole set
- Config —
output: 'server'with the@astrojs/nodeadapter, so every route is on-demand by default - Database — SQLite via
better-sqlite3, a single gitignored file, no separate database server to run - Assumed groundwork — Astro fundamentals, covered in this site's own dedicated
astro1andwebsite-rebuild-with-astro1courses - Next chapter: Data Modeling — teams, seasons, gameweeks & fixtures, as a lightweight SQLite-backed API