Skip to content

Commit 42f86c2

Browse files
docs(solid-router): authenticated-routes-firebase (#5826)
* auth-firebase * docs(solid-router): authenticated-routes-firebase * add authenticated-routes to example overview * solid example * format * ci: apply automated fixes * call user function --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent 8f57746 commit 42f86c2

27 files changed

+960
-0
lines changed

docs/router/config.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -634,6 +634,10 @@
634634
"label": "Kitchen Sink + Solid Query (code-based)",
635635
"to": "framework/solid/examples/kitchen-sink-solid-query"
636636
},
637+
{
638+
"label": "Authenticated Routes",
639+
"to": "framework/solid/examples/authenticated-routes"
640+
},
637641
{
638642
"label": "View Transitions",
639643
"to": "framework/solid/examples/view-transitions"
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Firebase Configuration: Copy this file to `.env.local` and add your Firebase credentials
2+
# Obtain these values from your Firebase Console (see README.md for detailed setup instructions)
3+
VITE_PUBLIC_FIREBASE_API_KEY=
4+
VITE_PUBLIC_FIREBASE_AUTH_DOMAIN=
5+
VITE_PUBLIC_FIREBASE_PROJECT_ID=
6+
VITE_PUBLIC_FIREBASE_STORAGE_BUCKET=
7+
VITE_PUBLIC_FIREBASE_MESSAGING_SENDER_ID=
8+
VITE_PUBLIC_FIREBASE_APP_ID=
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
node_modules
2+
.DS_Store
3+
dist
4+
dist-ssr
5+
*.local
6+
.env.*
7+
!.env.example
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"files.watcherExclude": {
3+
"**/routeTree.gen.ts": true
4+
},
5+
"search.exclude": {
6+
"**/routeTree.gen.ts": true
7+
},
8+
"files.readonlyInclude": {
9+
"**/routeTree.gen.ts": true
10+
}
11+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Firebase Setup
2+
3+
1. Create a [Firebase project](https://console.firebase.google.com/)
4+
1. By default, firebase will configure an accepted domain for localhost...update if necessary!
5+
2. Enable Authentication in the Firebase console
6+
3. Add GitHub as an authentication provider:
7+
- Go to **Authentication** > **Sign-in method** > **GitHub**
8+
- Enable GitHub authentication
9+
- You'll need to set up OAuth in your GitHub account:
10+
- Go to [GitHub Developer Settings](https://github.com/settings/developers)
11+
- Create a new OAuth app
12+
- Set the homepage URL to your local or production URL
13+
- Set the callback URL to: `https://your-firebase-project-id.firebaseapp.com/__/auth/handler`
14+
- Copy the Client ID and Client Secret
15+
- Return to Firebase console and paste the GitHub Client ID and Client Secret
16+
- Save the changes
17+
18+
4. Create a web app in your Firebase project:
19+
- Go to **Project Overview** > **Add app** > **Web**
20+
- Register the app with a nickname
21+
- Copy the Firebase configuration object for later use
22+
23+
## Setup .env.local
24+
25+
Copy the .env.example provided and configure with your firebase credentials
26+
27+
````VITE_FIREBASE_API_KEY=
28+
VITE_FIREBASE_AUTH_DOMAIN=
29+
VITE_FIREBASE_PROJECT_ID=
30+
VITE_FIREBASE_STORAGE_BUCKET=
31+
VITE_FIREBASE_MESSAGING_SENDER_ID=
32+
VITE_FIREBASE_APP_ID=```
33+
34+
## Run the app
35+
36+
To run this example:
37+
38+
- `npm install` or `yarn`
39+
- `npm start` or `yarn start`
40+
````
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Vite App</title>
7+
</head>
8+
<body>
9+
<div id="app"></div>
10+
<script type="module" src="/src/main.tsx"></script>
11+
</body>
12+
</html>
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"name": "tanstack-router-solid-example-authenticated-routes-firebase",
3+
"private": true,
4+
"type": "module",
5+
"scripts": {
6+
"dev": "vite --port 3000",
7+
"build": "vite build && tsc --noEmit",
8+
"serve": "vite preview",
9+
"start": "vite"
10+
},
11+
"dependencies": {
12+
"@tailwindcss/postcss": "^4.1.15",
13+
"@tanstack/solid-router": "^1.135.2",
14+
"@tanstack/solid-router-devtools": "^1.135.2",
15+
"@tanstack/router-plugin": "^1.135.2",
16+
"firebase": "^11.4.0",
17+
"postcss": "^8.5.1",
18+
"solid-js": "^1.9.10",
19+
"redaxios": "^0.5.1",
20+
"simple-icons": "^14.9.0",
21+
"tailwindcss": "^4.1.15",
22+
"zod": "^3.24.2"
23+
},
24+
"devDependencies": {
25+
"vite-plugin-solid": "^2.11.10",
26+
"typescript": "^5.7.2",
27+
"vite": "^7.1.7"
28+
}
29+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export default {
2+
plugins: {
3+
'@tailwindcss/postcss': {},
4+
},
5+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import * as Solid from 'solid-js'
2+
3+
import { onAuthStateChanged, signInWithPopup, signOut } from 'firebase/auth'
4+
import { flushSync } from 'react-dom'
5+
import { auth } from './firebase/config'
6+
import type { AuthProvider, User } from 'firebase/auth'
7+
8+
export type AuthContextType = {
9+
isAuthenticated: () => boolean
10+
isInitialLoading: () => boolean
11+
login: (provider: AuthProvider) => Promise<void>
12+
logout: () => Promise<void>
13+
user: () => User | null
14+
}
15+
16+
const AuthContext = Solid.createContext<AuthContextType | null>(null)
17+
18+
export function AuthContextProvider(props: { children: Solid.JSX.Element }) {
19+
const [user, setUser] = Solid.createSignal<User | null>(auth.currentUser)
20+
const [isInitialLoading, setIsInitialLoading] = Solid.createSignal(true)
21+
const isAuthenticated = () => !!user()
22+
23+
Solid.createEffect(() => {
24+
const unsubscribe = onAuthStateChanged(auth, (user) => {
25+
flushSync(() => {
26+
setUser(user)
27+
setIsInitialLoading(false)
28+
})
29+
})
30+
return () => unsubscribe()
31+
})
32+
33+
const logout = async () => {
34+
console.log('Logging out...')
35+
await signOut(auth)
36+
setUser(null)
37+
setIsInitialLoading(false)
38+
}
39+
40+
const login = async (provider: AuthProvider) => {
41+
const result = await signInWithPopup(auth, provider)
42+
flushSync(() => {
43+
setUser(result.user)
44+
setIsInitialLoading(false)
45+
})
46+
}
47+
48+
return (
49+
<AuthContext.Provider
50+
value={{ isInitialLoading, isAuthenticated, user, login, logout }}
51+
>
52+
{props.children}
53+
</AuthContext.Provider>
54+
)
55+
}
56+
57+
export function useAuth() {
58+
const context = Solid.useContext(AuthContext)
59+
if (!context) {
60+
throw new Error('useAuth must be used within an AuthProvider')
61+
}
62+
return context
63+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Import the functions you need from the SDKs you need
2+
import { initializeApp } from 'firebase/app'
3+
import { getAuth } from 'firebase/auth'
4+
// TODO: Add SDKs for Firebase products that you want to use
5+
// https://firebase.google.com/docs/web/setup#available-libraries
6+
7+
// Your web app's Firebase configuration
8+
const firebaseConfig = {
9+
apiKey: import.meta.env.VITE_PUBLIC_FIREBASE_API_KEY,
10+
authDomain: import.meta.env.VITE_PUBLIC_FIREBASE_AUTH_DOMAIN,
11+
projectId: import.meta.env.VITE_PUBLIC_FIREBASE_PROJECT_ID,
12+
storageBucket: import.meta.env.VITE_PUBLIC_FIREBASE_STORAGE_BUCKET,
13+
messagingSenderId: import.meta.env.VITE_PUBLIC_FIREBASE_MESSAGING_SENDER_ID,
14+
appId: import.meta.env.VITE_PUBLIC_FIREBASE_APP_ID,
15+
}
16+
17+
// Initialize Firebase
18+
const app = initializeApp(firebaseConfig)
19+
export const auth = getAuth(app)

0 commit comments

Comments
 (0)