---
title: "Examples"
description: "Real-world implementation patterns and use cases"
sidebarTitle: "Examples"
---
Explore production-ready examples for common use cases and integration patterns.
## Basic Example
Simple implementation with static data - perfect for testing and learning:
```tsx BasicGraph.tsx
'use client'
import { MemoryGraph } from '@supermemory/memory-graph'
import type { DocumentWithMemories } from '@supermemory/memory-graph'
// Sample data for testing
const sampleDocuments: DocumentWithMemories[] = [
{
id: "doc-1",
title: "Project Roadmap",
content: "Q1 goals and milestones",
summary: "Planning for Q1 2024",
memoryEntries: [
{
id: "mem-1",
documentId: "doc-1",
content: "Launch new feature by end of Q1",
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
}
],
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
}
]
export default function BasicGraph() {
return (
)
}
```
{/* TODO: Add basic example screenshot */}
## Next.js Integration
### With App Router
Complete example with backend proxy, authentication, and error handling:
```typescript app/api/graph-data/route.ts
import { NextResponse } from 'next/server'
import { auth } from '@/lib/auth'
export async function GET() {
// Authenticate user
const session = await auth()
if (!session?.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,
containerTags: [session.user.id], // User isolation
sort: 'createdAt',
order: 'desc',
}),
}
)
if (!response.ok) {
throw new Error(`Supermemory API error: ${response.statusText}`)
}
const data = await response.json()
return NextResponse.json(data)
} catch (error) {
console.error('Graph data fetch error:', error)
return NextResponse.json(
{ error: 'Failed to fetch graph data' },
{ status: 500 }
)
}
}
```
```tsx app/graph/page.tsx
'use client'
import { MemoryGraph } from '@supermemory/memory-graph'
import { useState, useEffect } from 'react'
import type { DocumentWithMemories } from '@supermemory/memory-graph'
export default function GraphPage() {
const [documents, setDocuments] = useState([])
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState(null)
useEffect(() => {
fetch('/api/graph-data')
.then(async (res) => {
if (!res.ok) throw new Error(await res.text())
return res.json()
})
.then((data) => {
setDocuments(data.documents)
setIsLoading(false)
})
.catch((err) => {
setError(err)
setIsLoading(false)
})
}, [])
return (
)
}
```
{/* TODO: Add Next.js example screenshot */}
## With Pagination
Implement infinite scroll for large datasets:
```tsx GraphWithPagination.tsx
'use client'
import { MemoryGraph } from '@supermemory/memory-graph'
import { useState, useCallback } from 'react'
import type { DocumentWithMemories } from '@supermemory/memory-graph'
export default function GraphWithPagination() {
const [documents, setDocuments] = useState([])
const [page, setPage] = useState(1)
const [hasMore, setHasMore] = useState(true)
const [isLoading, setIsLoading] = useState(true)
const [isLoadingMore, setIsLoadingMore] = useState(false)
const [error, setError] = useState(null)
// Initial load
useState(() => {
fetchPage(1)
}, [])
const fetchPage = async (pageNum: number) => {
try {
if (pageNum === 1) {
setIsLoading(true)
} else {
setIsLoadingMore(true)
}
const response = await fetch(
`/api/graph-data?page=${pageNum}&limit=100`
)
if (!response.ok) {
throw new Error('Failed to fetch documents')
}
const data = await response.json()
setDocuments(prev =>
pageNum === 1 ? data.documents : [...prev, ...data.documents]
)
setHasMore(
data.pagination.currentPage < data.pagination.totalPages
)
setPage(pageNum)
} catch (err) {
setError(err instanceof Error ? err : new Error('Unknown error'))
} finally {
setIsLoading(false)
setIsLoadingMore(false)
}
}
const loadMore = useCallback(async () => {
if (!isLoadingMore && hasMore) {
await fetchPage(page + 1)
}
}, [page, isLoadingMore, hasMore])
return (
)
}
```
The graph automatically loads more documents when 80% of current documents are visible in the viewport. Set `autoLoadOnViewport={false}` for manual control.
{/* TODO: Add pagination example screenshot */}
## Search Integration with Highlighting
Highlight search results in the graph:
```tsx SearchableGraph.tsx
'use client'
import { MemoryGraph } from '@supermemory/memory-graph'
import { useState, useEffect } from 'react'
import type { DocumentWithMemories } from '@supermemory/memory-graph'
export default function SearchableGraph() {
const [documents, setDocuments] = useState([])
const [searchQuery, setSearchQuery] = useState('')
const [highlightedIds, setHighlightedIds] = useState([])
const [showHighlights, setShowHighlights] = useState(true)
// Fetch all documents
useEffect(() => {
fetch('/api/graph-data')
.then(res => res.json())
.then(data => setDocuments(data.documents))
}, [])
// Search and highlight
const handleSearch = async () => {
if (!searchQuery.trim()) {
setHighlightedIds([])
return
}
try {
const response = await fetch('/api/search', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ query: searchQuery })
})
const results = await response.json()
// Extract document IDs from search results
const docIds = results.documents.map((doc: any) => doc.id)
setHighlightedIds(docIds)
setShowHighlights(true)
} catch (error) {
console.error('Search error:', error)
}
}
return (
)
}
```
Highlighting supports both internal document IDs and custom IDs. The graph will automatically match either.
{/* TODO: Add search highlighting screenshot */}
## Custom Empty State
Provide a custom UI when no documents exist:
```tsx GraphWithEmpty.tsx
'use client'
import { MemoryGraph } from '@supermemory/memory-graph'
import { useState, useEffect } from 'react'
export default function GraphWithEmpty() {
const [documents, setDocuments] = useState([])
return (
No memories yet
Start adding content to see your knowledge graph come to life.
Documents and their connections will appear here.
window.location.href = '/add-memory'}
style={{
padding: '0.75rem 1.5rem',
backgroundColor: '#3b82f6',
color: 'white',
borderRadius: '0.5rem',
border: 'none',
cursor: 'pointer'
}}
>
Add Your First Memory
window.location.href = '/docs'}
style={{
padding: '0.75rem 1.5rem',
backgroundColor: 'transparent',
border: '1px solid #d1d5db',
borderRadius: '0.5rem',
cursor: 'pointer'
}}
>
Learn More
)
}
```
## Backend Patterns
### Express.js
```typescript server.ts
import express from 'express'
const app = express()
app.get('/api/graph-data', async (req, res) => {
// Authenticate user
const user = await authenticateRequest(req)
if (!user) {
return res.status(401).json({ error: 'Unauthorized' })
}
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,
containerTags: [user.id],
}),
}
)
const data = await response.json()
res.json(data)
} catch (error) {
console.error('Error:', error)
res.status(500).json({ error: 'Failed to fetch data' })
}
})
app.listen(3000)
```
### Cloudflare Workers
```typescript worker.ts
export default {
async fetch(request: Request, env: Env) {
// Authenticate
const user = await authenticateRequest(request, env)
if (!user) {
return new Response('Unauthorized', { status: 401 })
}
try {
const response = await fetch(
'https://api.supermemory.ai/v3/documents/documents',
{
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${env.SUPERMEMORY_API_KEY}`,
},
body: JSON.stringify({
page: 1,
limit: 500,
containerTags: [user.id],
}),
}
)
return new Response(await response.text(), {
headers: { 'Content-Type': 'application/json' }
})
} catch (error) {
return new Response('Internal Server Error', { status: 500 })
}
}
}
```
### User Isolation with Container Tags
For multi-user applications, always filter documents by user:
```typescript
// Backend: Filter by user ID
body: JSON.stringify({
containerTags: [user.id], // Only fetch this user's documents
page: 1,
limit: 500,
})
```
Always implement user isolation on the backend. Never trust client-side filtering for security.
## React Query Integration
For better data management and caching:
```tsx GraphWithReactQuery.tsx
'use client'
import { MemoryGraph } from '@supermemory/memory-graph'
import { useQuery } from '@tanstack/react-query'
export default function GraphWithReactQuery() {
const { data, isLoading, error } = useQuery({
queryKey: ['graph-data'],
queryFn: async () => {
const response = await fetch('/api/graph-data')
if (!response.ok) {
throw new Error('Failed to fetch graph data')
}
return response.json()
},
staleTime: 5 * 60 * 1000, // 5 minutes
refetchOnWindowFocus: false,
})
return (
)
}
```
## Next Steps
Explore all props and types
Solve common issues