Skip to content

Commit

Permalink
With Firebase Client-Side example (#11053)
Browse files Browse the repository at this point in the history
* initialized example

* Import from "firebase/app"

to get only needed firebase modules

* credentials as env variables
Also, initialize app in a separate file. Much cleaner.

* Update examples/with-firebase-client-side/package.json

Co-Authored-By: Luis Alvarez D. <[email protected]>

* fixed environment variables and added .env.example

* added dotenv

* Updated readme

* Renamed example in the readme

* Renamed example files

* Updated title

Co-authored-by: Luis Alvarez D. <[email protected]>
  • Loading branch information
julianbenegas and Luis Alvarez D. authored Mar 20, 2020
1 parent 8724b3c commit f1944ca
Show file tree
Hide file tree
Showing 12 changed files with 400 additions and 0 deletions.
8 changes: 8 additions & 0 deletions examples/with-firebase/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# TODO. Fill in with Firebase Config
FIREBASE_API_KEY=
FIREBASE_AUTH_DOMAIN=
FIREBASE_DATABASE_URL=
FIREBASE_PROJECT_ID=
FIREBASE_STORAGE_BUCKET=
FIREBASE_MESSAGING_SENDER_ID=
FIREBASE_APP_ID=
25 changes: 25 additions & 0 deletions examples/with-firebase/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.

# dependencies
/node_modules
/.pnp
.pnp.js

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
.env

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
57 changes: 57 additions & 0 deletions examples/with-firebase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# With Firebase

This is a simple set up for Firebase for client side applications.

The firebase app is initialized in `firebase/clientApp.js`, to use you just have to import it anywhere in the app

The React Context API is used to provide user state.

## Deploy your own

Deploy the example using [ZEIT Now](https://zeit.co/now):

[![Deploy with ZEIT Now](https://zeit.co/button)](https://zeit.co/import/project?template=https://github.com/zeit/next.js/tree/canary/examples/with-firebase)

## How to use

### Using `create-next-app`

Execute [`create-next-app`](https://github.com/zeit/next.js/tree/canary/packages/create-next-app) with [npm](https://docs.npmjs.com/cli/init) or [Yarn](https://yarnpkg.com/lang/en/docs/cli/create/) to bootstrap the example:

```bash
npx create-next-app --example with-firebase with-firebase-app
# or
yarn create next-app --example with-firebase with-firebase-app
```

### Download manually

Download the example:

```bash
curl https://codeload.github.com/zeit/next.js/tar.gz/canary | tar -xz --strip=2 next.js-canary/examples/with-firebase
cd with-firebase
```

### Configuration

1. [Create a Firebase project](https://console.firebase.google.com/u/0/) and add a new app to it.
2. Create a `.env` file and copy the contents of `.env.example` into it:

```bash
cp .env.example .env
```

3. Set each variable on `.env` with your Firebase Configuration (found in "Project settings").

Install it and run:

```bash
npm install
npm run dev
# or
yarn
yarn dev
```

Deploy it to the cloud with [ZEIT Now](https://zeit.co/import?filter=next.js&utm_source=github&utm_medium=readme&utm_campaign=next-example) ([Documentation](https://nextjs.org/docs/deployment)).
40 changes: 40 additions & 0 deletions examples/with-firebase/context/userContext.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useState, useEffect, createContext, useContext } from 'react'
import firebase from '../firebase/clientApp'

export const UserContext = createContext()

export default ({ children }) => {
const [user, setUser] = useState(null)
const [loadingUser, setLoadingUser] = useState(true) // Helpful, to update the UI accordingly.

useEffect(() => {
// Listen authenticated user
const unsubscriber = firebase.auth().onAuthStateChanged(async user => {
try {
if (user) {
// User is signed in.
const { uid, displayName, email, photoURL } = user
// You could also look for the user doc in your Firestore (if you have one):
// const userDoc = await firebase.firestore().doc(`users/${uid}`).get()
setUser({ uid, displayName, email, photoURL })
} else setUser(null)
} catch (error) {
// Most probably a connection error. Handle appropiately.
} finally {
setLoadingUser(false)
}
})

// Unsubscribe auth listener on unmount
return () => unsubscriber()
}, [])

return (
<UserContext.Provider value={{ user, setUser, loadingUser }}>
{children}
</UserContext.Provider>
)
}

// Custom hook that shorhands the context!
export const useUser = () => useContext(UserContext)
24 changes: 24 additions & 0 deletions examples/with-firebase/firebase/clientApp.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import firebase from 'firebase/app'
import 'firebase/auth' // If you need it
import 'firebase/firestore' // If you need it
import 'firebase/storage' // If you need it
import 'firebase/analytics' // If you need it

const clientCredentials = {
apiKey: process.env.FIREBASE_API_KEY,
authDomain: process.env.FIREBASE_AUTH_DOMAIN,
databaseURL: process.env.FIREBASE_DATABASE_URL,
projectId: process.env.FIREBASE_PROJECT_ID,
storageBucket: process.env.FIREBASE_STORAGE_BUCKET,
messagingSenderId: process.env.FIREBASE_MESSAGING_SENDER_ID,
appId: process.env.FIREBASE_APP_ID,
}

// Check that `window` is in scope for the analytics module!
if (typeof window !== 'undefined' && !firebase.apps.length) {
firebase.initializeApp(clientCredentials)
// To enable analytics. https://firebase.google.com/docs/analytics/get-started
if ('measurementId' in clientCredentials) firebase.analytics()
}

export default firebase
14 changes: 14 additions & 0 deletions examples/with-firebase/next.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// On production, variables are set with `now secrets`. On development, they use the .env file
require('dotenv').config()

module.exports = {
env: {
FIREBASE_API_KEY: process.env.FIREBASE_API_KEY,
FIREBASE_AUTH_DOMAIN: process.env.FIREBASE_AUTH_DOMAIN,
FIREBASE_DATABASE_URL: process.env.FIREBASE_DATABASE_URL,
FIREBASE_PROJECT_ID: process.env.FIREBASE_PROJECT_ID,
FIREBASE_STORAGE_BUCKET: process.env.FIREBASE_STORAGE_BUCKET,
FIREBASE_MESSAGING_SENDER_ID: process.env.FIREBASE_MESSAGING_SENDER_ID,
FIREBASE_APP_ID: process.env.FIREBASE_APP_ID,
},
}
13 changes: 13 additions & 0 deletions examples/with-firebase/now.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"build": {
"env": {
"FIREBASE_API_KEY": "@firebase-api-key",
"FIREBASE_AUTH_DOMAIN": "@firebase-auth-domain",
"FIREBASE_DATABASE_URL": "@firebase-database-url",
"FIREBASE_PROJECT_ID": "@firebase-project-id",
"FIREBASE_STORAGE_BUCKET": "@firebase-storage-bucket",
"FIREBASE_MESSAGING_SENDER_ID": "@firebase-messaging-sender-id",
"FIREBASE_APP_ID": "@firebase-app-id"
}
}
}
18 changes: 18 additions & 0 deletions examples/with-firebase/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
{
"name": "with-firebase",
"version": "0.1.0",
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start"
},
"dependencies": {
"firebase": "7.11.0",
"next": "latest",
"react": "^16.13.0",
"react-dom": "^16.13.0"
},
"devDependencies": {
"dotenv": "8.2.0"
}
}
8 changes: 8 additions & 0 deletions examples/with-firebase/pages/_app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import UserProvider from '../context/userContext'

// Custom App to wrap it with context provider
export default ({ Component, pageProps }) => (
<UserProvider>
<Component {...pageProps} />
</UserProvider>
)
Loading

0 comments on commit f1944ca

Please sign in to comment.