Git Product home page Git Product logo

sveltekit-firebase-ssr's Introduction

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.

Live example

https://sveltekit-firebase-ssr.vercel.app/

(counter and todos data subject to random deletion. Don't plan your day with it.)

Setup

Create a .env.development file at the root of the folder with the following entries:

VITE_FIREBASE_CLIENT_CONFIG="Your **client** Firebase config json, stringified"
VITE_FIREBASE_SERVER_CONFIG="Your **server** Firebase config json, stringified"

VITE_FIREBASE_CLIENT_CONFIG

This value will be sent to the client in the user's session. See src/hooks.ts

The (non-stringified) json has this shape:

{
    "apiKey": "",
    "authDomain": "",
    "databaseURL": "",
    "projectId": "",
    "storageBucket": "",
    "messagingSenderId": "",
    "appId": "",
    "measurementId": ""
}

VITE_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": ""
}

Authenticating the user

/src/routes/__layout.svelte uses the Auth component which shows a button to sign in and out. The signInWith and signOut functions are in /src/lib/utils/firebase.ts. Notice how the Firebase app is initialized with FIREBASE_CONFIG.

The script section of /src/routes/__layout.svelte invokes listenForAuthChanges() (/src/lib/utils/firebase.ts) if the app is running in the browser. It will update the session data with the logged in user and set a cookie with its token. The handle function in /src/hooks.ts reads the cookie and decodes the token for getSession to include minimal information about the user in the session object.

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/api/data.ts to get the components' initial data from both client and server.

Todos component

The load function in /src/routes/todos/index.svelte fetches the list of todos from /api/data. /src/routes/api/data.ts always runs on the server and it will decode the user's token from a cookie and use /src/lib/server/firebase.ts to retireve the documents using getDocuments. The result is passed to the component via props.

Models

At risk of angering the FP gods I decided to go with classes for the document models. /src/lib/models/Document.ts is the base class for Firebase documents. _collection is to be overridden with the path to the collection. _dbFields holds the fields that will make it to the database (not every field in the model needs to be stored). /src/lib/models/Todo.ts holds the definition of the Todo item. The constructor adds the fields it wants to persist in the DB (text and done). It also overrides _collection with the name of the Firebase collection ('todos').

Firebase reactivity

The Counter component shows how one can subscribe to Firebase changes. It gets the data from the server, creates a Document, and uses the .getStore() function which creates a readable store that A) loads the object's data properties on Firebase's onSnapshot, and B) it updates the store via the set method.

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.

Counter uses the helper method /src/lib/utils/firebase.ts -> getDocumentStore to react to changes in a single document (there's one counters document in Firebase for each user).

Todos uses the helper method /src/lib/utils/firebase.ts -> getCollectionStore to react to changes in all todos documents for the given user.

Protecting routes

There are two ways to protect a route, with hooks.ts and __layout.svelte.

In this example we have a publicPages constant with the list of pages which can be accessed without logging in. In hooks.ts handle we check for the token and if the user isn't logged in we send them to the home page. The same check is performed at the layout level.

sveltekit-firebase-ssr's People

Contributors

manueldeleon avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.