What we wanted to decide
The existing GitHub Pages website works well as a public educational journal. The new question is not whether to discard it, but how to extend it when the product needs authenticated learners, team content management, administrative analytics, protected documents, and stored progress.
The goal of this lesson is to define a migration path that preserves the successful public experience while introducing private application capabilities safely and gradually.
Engineering lesson: architecture should change because requirements changed—not because a larger technology stack looks more impressive.
The architecture decision
We will keep the current public frontend available while introducing a separate application layer. Public pages remain easy to access and inexpensive to host. Protected actions move behind authentication and a backend API. Personal and operational data stay outside the public repository.
Keep
The public learning journal, custom domain, lesson pages, PDFs intended for public release, and the clear frontend experience.
Add
Authentication, role-based authorization, API logic, structured data, private storage, monitoring, and automated deployment.
Static website versus web application
| Static website | Web application |
|---|---|
| Publishes the same files to every visitor. | Returns content and actions according to identity and permissions. |
| Contains no trusted server-side business logic. | Uses an API to validate requests and apply business rules. |
| Public files can be downloaded directly. | Private files require controlled, temporary access. |
| Works well for public information and lessons. | Supports accounts, progress, content management, and protected workflows. |
The selected architecture
Firebase Hosting serves the public interface. Auth0 manages login through Universal Login. The browser requests an access token and sends it to a FastAPI backend running on Google Cloud Run. The API verifies the token and role before reading Firestore or granting temporary access to a private Cloud Storage object.
Public interfaceAuth0
Login and tokenCloud Run
FastAPIFirestore
Application dataCloud Storage
Private files
Responsibilities of each service
Firebase Hosting
Delivers the frontend securely through a global content network and supports deployment from GitHub.
Auth0
Handles identity, login, logout, password recovery, and token creation outside our frontend code.
Cloud Run and FastAPI
Validate requests, enforce rules, connect services, and expose the application API.
Firestore and Cloud Storage
Store structured application data and private files under controlled backend access.
Start with one useful page per role
The long-term product may support several workflows, but the first application release should prove one valuable page for each role.
| Role | First page | Purpose |
|---|---|---|
| Learner | /learn/dashboard | Continue lessons and see personal progress. |
| Team | /team/content | Draft and manage lesson content. |
| Administrator | /admin/analytics | View aggregated operational analytics and system status. |
Authentication asks: who is this user? Authorization asks: is this user allowed to perform this action? A login alone does not protect a resource.
What makes the design secure
- Universal Login handles passwords outside the frontend.
- The backend verifies authentication and authorization on every protected request.
- Google service accounts receive only the permissions required by the API.
- Secrets remain in Secret Manager and never enter the public repositories.
- Private files remain in protected storage rather than GitHub Pages.
- Input is validated before data is stored or processed.
- Administrative actions create useful audit records.
- Logs and analytics avoid unnecessary sensitive personal data.
Repository boundaries
The repository structure should reflect the security boundary:
- Become-SWE: public learning material, tutorials, decisions, challenges, mistakes, and what was learned.
- swe-tickerbell: the public production frontend—HTML, CSS, JavaScript, public images, and deployment configuration.
- Private backend repository: FastAPI code, infrastructure configuration, database migrations, authorization rules, and private operational documentation.
Passwords, API secrets, customer data, private documents, and internal company information must not be committed to either public repository.
The practical build order
- Review the public page and role-page prototypes.
- Configure Auth0 and prove login and logout.
- Deploy the frontend through Firebase Hosting and GitHub Actions.
- Create a private backend repository and a FastAPI health endpoint.
- Protect one profile endpoint with an Auth0 access token.
- Store one learner profile in Firestore.
- Add one role check and verify unauthorized access is rejected.
- Deliver one private file through a controlled backend request.
- Add structured logs, error monitoring, and basic cost alerts.
- Expand only after the complete thin vertical slice works.
Practical exercise
For each planned page, write down the data it requires. Mark every item as public, personal, team-only, or administrator-only. Then identify which API endpoint must authorize access and which service should store the information.
Completion criteria
- You can explain authentication versus authorization.
- You can name the responsibility of every selected service.
- You understand why protected data cannot live in the public frontend repository.
- You can describe the request path from login to Firestore.
- You can identify the smallest end-to-end application slice to build first.