Loading...
Loading...
Build a Next.js app that authenticates users, launches the Connector, and fetches financial data. Learn session token management and avoid rate limit errors.
Time: ~15 minutes Framework: Next.js (concepts apply to any framework)
A Next.js app that:
Session tokens authenticate users for the Connector and GraphQL API:
We'll use QuilttAuthProvider from @quiltt/react to handle token management automatically.
pnpm, yarn, or npm)This tutorial uses pnpm but commands work with any package manager.
Create a Next.js project and install dependencies:
pnpm create next-app quiltt-auth-tutorial --typescript --tailwind --app
cd quiltt-auth-tutorial
pnpm add @quiltt/react
Add your credentials from the Dashboard:
# .env.local
QUILTT_API_KEY_SECRET=your_api_key_secret_here
NEXT_PUBLIC_QUILTT_CONNECTOR_ID=your_connector_id_here
Never commit QUILTT_API_KEY_SECRET to Git. It's for server-side use only.
Start the dev server:
pnpm dev
Create a server-side endpoint to issue tokens (this protects your API key from client-side exposure):
// app/api/quiltt-session/route.ts
import { NextResponse } from 'next/server'
export async function POST(req) {
const requestBody = await req.json()
const data = await fetch('https://auth.quiltt.io/v1/users/sessions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.QUILTT_API_KEY_SECRET}`,
'Content-Type': 'application/json'
},
body: JSON.stringify(requestBody)
})
const session = await data.json()
return NextResponse.json(session)
}
Fetch tokens and pass to QuilttAuthProvider. This handles session management, Connector auth, and GraphQL client setup.
// app/providers.tsx
'use client'
import { useState, useEffect } from 'react'
import { QuilttAuthProvider } from "@quiltt/react"
export function Providers({ quilttProfileId, children }) {
const [token, setToken] = useState()
const [loading, setLoading] = useState(true)
useEffect(() => {
async function loadSession() {
// Check for cached token first
const cached = localStorage.getItem(`quiltt_session_${quilttProfileId}`)
if (cached) {
const { token, expiresAt } = JSON.parse(cached)
// Use cached token if still valid
if (new Date(expiresAt) > new Date()) {
setToken(token)
setLoading(false)
return
}
}
// Fetch new token if no valid cached token
const response = await fetch('/api/quiltt-session', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ userId: quilttProfileId })
})
const session = await response.json()
// Cache the token with expiration
localStorage.setItem(`quiltt_session_${quilttProfileId}`, JSON.stringify({
token: session.token,
expiresAt: session.expiresAt
}))
setToken(session.token)
setLoading(false)
}
loadSession()
}, [quilttProfileId])
if (loading) return <div>Loading...</div>
return (
<QuilttAuthProvider token={token}>
{children}
</QuilttAuthProvider>
)
}
Critical: This code checks localStorage before issuing new tokens. Without caching, every page refresh issues a new token, quickly hitting the 10/hour rate limit.
Only need the Connector (not GraphQL)? Use QuilttProvider instead of QuilttAuthProvider.
Wire up the Providers component:
// app/layout.tsx
import { Providers } from './providers'
export default function RootLayout({ children }) {
// Fetch this for the currently-logged user from your database or Auth provider
const quilttProfileId = "p_12yz8qVmHucM2yqv09KfPv"
return (
<html lang="en">
<body>
<Providers quilttProfileId={quilttProfileId}>
{children}
</Providers>
</body>
</html>
)
}
Add a button that launches the Connector (automatically authenticated):
// app/page.tsx
'use client'
import { QuilttButton } from '@quiltt/react'
const CONNECTOR_ID = process.env.NEXT_PUBLIC_QUILTT_CONNECTOR_ID
export default function Home() {
return (
<div className="grid items-center justify-items-center min-h-screen">
<main className="flex flex-col items-center">
<QuilttButton connectorId={CONNECTOR_ID} className="border p-2">
Launch Connector!
</QuilttButton>
</main>
</div>
)
}
Visit http://localhost:3000 and click "Launch Connector":
Use useQuilttClient for GraphQL queries:
// app/components/Welcome.tsx
'use client'
import { useQuilttClient, useQuery, gql } from '@quiltt/react'
const PROFILE_QUERY = gql`
query GetProfile {
profile {
id
email
}
}
`
export default function Welcome() {
const client = useQuilttClient()
const { data, loading } = useQuery(PROFILE_QUERY, { client })
if (loading) return <div>Loading...</div>
return (
<h1 className="text-4xl font-bold text-center py-4">
Welcome, {data?.profile?.email || data?.profile?.id}
</h1>
)
}
Add the Welcome component to your page:
// app/page.tsx
'use client'
import { QuilttButton } from '@quiltt/react'
import Welcome from './components/Welcome'
const CONNECTOR_ID = process.env.NEXT_PUBLIC_QUILTT_CONNECTOR_ID
export default function Home() {
return (
<div className="grid items-center justify-items-center min-h-screen">
<main className="flex flex-col items-center sm:items-start">
<Welcome />
<QuilttButton connectorId={CONNECTOR_ID} className="border p-2">
Launch Connector!
</QuilttButton>
</main>
</div>
)
}
Refresh the page to see the greeting:
Continue Learning:
Reference Documentation: