Jak powstał Destinations (cz. 3): Firebase — baza i logowanie
13.10.2026 · 3 min czytania
W części 2 otypowałem destynacje. Ale skąd się w ogóle biorą? W pierwszej wersji siedziały w zwykłej tablicy w kodzie. Czas pokazać, gdzie zamieszkały naprawdę - i jak zamknąłem panel szkoleniowca na klucz.
Dane nie mogą mieszkać w kodzie#
Tablica destynacji w pliku była OK na start, ale ma wadę: żeby dodać albo usunąć kierunek, musiałbym edytować kod i wdrażać stronę od nowa. A przecież to szkoleniowiec ma zarządzać bazą - bez dotykania kodu. Potrzebowałem więc dwóch rzeczy: prawdziwej bazy danych oraz logowania, żeby panel zarządzania nie był otwarty dla wszystkich.
Firebase: baza i logowanie bez backendu#
Jak wspominałem w części 1, wybrałem Firebase — bo daje jedno i drugie bez stawiania własnego serwera: Firestore (baza) i Firebase Auth (logowanie).
Czytanie destynacji wygląda mniej więcej tak:
import { collection, getDocs } from "firebase/firestore";
import { db } from "./firebase";
import type { Destination } from "./types";
export async function getDestinations(): Promise<Destination[]> {
const snapshot = await getDocs(collection(db, "destinations"));
return snapshot.docs.map((doc) => doc.data() as Destination);
}
I tu widać, jak część 2 się spłaca: dane z bazy od razu wpadają w typ
Destination, więc reszta aplikacji wie, z czym ma do czynienia.
„Zaraz, klucz API w kodzie?!”#
Konfiguracja Firebase ląduje w kodzie frontendu — razem z apiKey:
const firebaseConfig = {
apiKey: "AIza...", // to jest PUBLICZNE — i tak ma być
authDomain: "destinations-xxxx.firebaseapp.com",
projectId: "destinations-xxxx",
};
Jeśli czytałeś moją serię o metarze, teraz pewnie zastanawiasz się, skąd ta rozbieżność. „Przecież uczyłeś, że token API chowa się na serwerze!”. I słusznie — ale to inny przypadek.
Skoro klucz nie chroni projektu, to co go chroni? Reguły bezpieczeństwa (Security Rules) po stronie Firebase:
match /destinations/{id} {
allow read: if true; // czytać może każdy (do generowania testów)
allow write: if request.auth != null; // pisać tylko zalogowany
}
Logowanie szkoleniowca#
Samo logowanie to zasługa Firebase Auth — konto na e-mail i hasło:
import { signInWithEmailAndPassword } from "firebase/auth";
import { auth } from "./firebase";
await signInWithEmailAndPassword(auth, email, password);
Informację o tym, kto jest zalogowany, trzymam w AuthContext — jednym miejscu,
z którego cała aplikacja może zapytać „czy ktoś jest zalogowany?”.
W części 4 domknę temat: skoro wiem już, kto jest zalogowany, pokażę, jak fizycznie zamknąć panel przed niezalogowanymi — czyli chronione trasy w React Router.