Security First: Never expose your Supermemory API key in client-side code. Always use a backend proxy to authenticate requests.
Step 1: Create Backend Proxy
Create an API route in your backend that authenticates users and proxies requests to the Supermemory API.Copy
Ask AI
// app/api/supermemory-graph/route.ts
import { NextResponse } from 'next/server'
export async function GET(request: Request) {
// Add your authentication logic here
const user = await getAuthenticatedUser(request)
if (!user) {
return NextResponse.json(
{ error: 'Unauthorized' },
{ status: 401 }
)
}
try {
const response = await fetch(
'https://api.supermemory.ai/v3/documents/documents',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`,
},
body: JSON.stringify({
page: 1,
limit: 500,
sort: 'createdAt',
order: 'desc',
// Optional: Filter by user-specific container
containerTags: [user.id],
}),
}
)
if (!response.ok) {
throw new Error('Failed to fetch documents')
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Error fetching graph data:', error)
return NextResponse.json(
{ error: 'Failed to fetch data' },
{ status: 500 }
)
}
}
Use
containerTags to filter documents by user in multi-user applications. This ensures users only see their own data.Step 2: Create Frontend Component
Create a component that fetches data and renders the graph.GraphComponent.tsx
Copy
Ask AI
'use client' // Required for Next.js App Router
import { MemoryGraph } from '@supermemory/memory-graph'
import { useState, useEffect } from 'react'
import type { DocumentWithMemories } from '@supermemory/memory-graph'
export default function GraphComponent() {
const [documents, setDocuments] = useState<DocumentWithMemories[]>([])
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState<Error | null>(null)
useEffect(() => {
fetch('/api/supermemory-graph')
.then(async (res) => {
if (!res.ok) {
throw new Error('Failed to fetch documents')
}
return res.json()
})
.then((data) => {
setDocuments(data.documents)
setIsLoading(false)
})
.catch((err) => {
setError(err)
setIsLoading(false)
})
}, [])
return (
{/* CRITICAL: Container must have explicit width and height */}
<div style={{ width: '100%', height: '100vh' }}>
<MemoryGraph
documents={documents}
isLoading={isLoading}
error={error}
>
{/* Custom empty state when no documents exist */}
<div style={{
display: 'flex',
flexDirection: 'column',
alignItems: 'center',
justifyContent: 'center',
height: '100%',
gap: '1rem'
}}>
<h2>No memories yet</h2>
<p>Start adding content to see your knowledge graph</p>
</div>
</MemoryGraph>
</div>
)
}
Container Sizing: The graph component requires its parent container to have explicit width and height. Without this, the canvas will have 0 dimensions and won’t render.
Step 3: Add to Your Page
Use the component in your page:Copy
Ask AI
// app/graph/page.tsx
import GraphComponent from '@/components/GraphComponent'
export default function GraphPage() {
return (
<main style={{ height: '100vh' }}>
<GraphComponent />
</main>
)
}
Complete Example
Here’s a complete, production-ready example with proper error handling and loading states:Copy
Ask AI
'use client'
import { MemoryGraph } from '@supermemory/memory-graph'
import { useState, useEffect } from 'react'
import type { DocumentWithMemories } from '@supermemory/memory-graph'
export default function GraphDashboard() {
const [documents, setDocuments] = useState<DocumentWithMemories[]>([])
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState<Error | null>(null)
useEffect(() => {
const fetchData = async () => {
try {
const response = await fetch('/api/supermemory-graph')
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
const data = await response.json()
setDocuments(data.documents || [])
} catch (err) {
console.error('Failed to fetch graph data:', err)
setError(err instanceof Error ? err : new Error('Unknown error'))
} finally {
setIsLoading(false)
}
}
fetchData()
}, [])
return (
<div className="dashboard" style={{
width: '100%',
height: '100vh',
position: 'relative'
}}>
<MemoryGraph
documents={documents}
isLoading={isLoading}
error={error}
variant="console"
>
<div className="empty-state">
<h2>No memories yet</h2>
<p>Start adding content to visualize your knowledge graph</p>
<button onClick={() => window.location.href = '/add-memory'}>
Add Your First Memory
</button>
</div>
</MemoryGraph>
</div>
)
}