sveltekit-firebase-ssr
sveltekit-firebase-ssr copied to clipboard
SvelteKit + Firebase + SSR with user data
This is an example/boilerplate/starter of the SvelteKit sample app with Firebase authentication and SSR that has user data.
Features
- SSR is generated with user data
- Works with Firebase Emulator
- Svelte 5 runes
- Data is reactive
Live example
https://sveltekit-firebase-ssr.vercel.app/
Setup
Create a .env
file at the root of the folder with the following entries:
PUBLIC_FIREBASE_CLIENT_CONFIG=Your **client** Firebase config json, stringified
FIREBASE_SERVER_CONFIG=Your **server** Firebase config json, stringified
PUBLIC_USE_EMULATOR=true|false
PUBLIC_FIREBASE_EMULATOR_PROJECT=your-project-name
PUBLIC_FIREBASE_AUTH_EMULATOR_HOST=localhost
PUBLIC_FIREBASE_AUTH_EMULATOR_PORT=9099
PUBLIC_FIRESTORE_EMULATOR_HOST=localhost
PUBLIC_FIRESTORE_EMULATOR_PORT=8080
PUBLIC_FIREBASE_CLIENT_CONFIG
This value will be sent to the client in the user's session.
The (non-stringified) json has this shape:
{
"apiKey": "",
"authDomain": "",
"databaseURL": "",
"projectId": "",
"storageBucket": "",
"messagingSenderId": "",
"appId": "",
"measurementId": ""
}
To obtain the client config, log in to the Firebase console, click the ⚙️ (settings icon), then select Project Settings
and in the General
tab the config json will be under Your apps
.
FIREBASE_SERVER_CONFIG
This value is only used to retrieve data from Firebase on the server. See src/lib/server/firebase.ts
The (non-stringified) json has this shape:
{
"type": "",
"project_id": "",
"private_key_id": "",
"private_key": "",
"client_email": "",
"client_id": "",
"auth_uri": "",
"token_uri": "",
"auth_provider_x509_cert_url": "",
"client_x509_cert_url": ""
}
To obtain the admin server config, log in to the Firebase console, click the ⚙️ (settings icon), then select Project Settings
and then the Service accounts
tab. In the Firebase Admin SDK
click Generate new private key
.
These credentials contain a private key that should be kept secret (i.e. not shared or committed to Git)
Reading data
Because reading on the server requires firebase-admin
which uses a project's private key, DB operations are separated into the following:
-
/src/lib/server/firebase.ts
for the server. -
/src/lib/utils/firebase.ts
for the client. -
/src/routes/+page.server.ts
to get the components' initial data from both client and server.
Models
At risk of angering the FP gods I decided to go with classes for the document models.
/src/lib/models/doc.ts
is the base class for Firebase documents.
/src/lib/models/count.ts
holds the definition of the Count
item. The constructor adds the fields it wants to persist in the DB (in this case it's count
and uid
).
Firebase reactivity
The Counter
component shows how one can subscribe to Firebase changes. useDocument
gets the data from the server, creates a Document
and loads the object's data properties on Firebase's onSnapshot
.
You can open 2 browser windows and see how one changes with the other (as long as they're both logged in with the same user).
The Counter
component doesn't display on the home page if the user isn't logged in.
Loading user data.
+page.svelte
declares let { data } = $props();
which is populated by the return of the load
method in +page.server.ts
. +page.svelte
then checks if data.userCount
has something and passes the value to the component <Counter userCount={data.userCount} />
.
Update Firebase Cloud Firestore Rules
You will need to update your Firestore security rules to grant the necessary permissions for your SvelteKit app. You can do this in the Firebase console by following these steps:
- Go to the Firebase Console.
- Select your project.
- In the left-hand menu, click on "Firestore Database."
- Click on the "Rules" tab.
You'll now see the security rules for your Firestore database. You need to update these rules to allow read and/or write access for authenticated users, depending on your app requirements.
Here's an example of security rules that allow read and write access to all documents in the database for authenticated users:
rules_version = '2';
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}
These rules grant read and write permissions to any authenticated user. You may need to refine these rules further based on your app's specific requirements, such as allowing access only to specific collections or documents, or based on user roles.
After updating your security rules, click "Publish" to apply the changes.