aboutsummaryrefslogtreecommitdiff
path: root/apps/docs/memory-graph/examples.mdx
diff options
context:
space:
mode:
authorShoubhit Dash <[email protected]>2025-11-25 20:18:26 +0530
committerShoubhit Dash <[email protected]>2025-11-25 20:18:26 +0530
commit1e6954434b4690c62e7094b70c7c491a8371b268 (patch)
tree2eb87c8dc82a9b479b64ffdc200c72a0b066609a /apps/docs/memory-graph/examples.mdx
parentfeat (docs): web crawler connector (#593) (diff)
downloadsupermemory-graph-package-docs.tar.xz
supermemory-graph-package-docs.zip
add docs for memory graphgraph-package-docs
Diffstat (limited to 'apps/docs/memory-graph/examples.mdx')
-rw-r--r--apps/docs/memory-graph/examples.mdx566
1 files changed, 566 insertions, 0 deletions
diff --git a/apps/docs/memory-graph/examples.mdx b/apps/docs/memory-graph/examples.mdx
new file mode 100644
index 00000000..7fa9f578
--- /dev/null
+++ b/apps/docs/memory-graph/examples.mdx
@@ -0,0 +1,566 @@
+---
+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 (
+ <div style={{ width: '100%', height: '600px' }}>
+ <MemoryGraph documents={sampleDocuments} />
+ </div>
+ )
+}
+```
+
+{/* 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<DocumentWithMemories[]>([])
+ const [isLoading, setIsLoading] = useState(true)
+ const [error, setError] = useState<Error | null>(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 (
+ <main style={{ height: '100vh' }}>
+ <MemoryGraph
+ documents={documents}
+ isLoading={isLoading}
+ error={error}
+ variant="console"
+ />
+ </main>
+ )
+}
+```
+
+{/* 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<DocumentWithMemories[]>([])
+ const [page, setPage] = useState(1)
+ const [hasMore, setHasMore] = useState(true)
+ const [isLoading, setIsLoading] = useState(true)
+ const [isLoadingMore, setIsLoadingMore] = useState(false)
+ const [error, setError] = useState<Error | null>(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 (
+ <div style={{ width: '100%', height: '100vh' }}>
+ <MemoryGraph
+ documents={documents}
+ isLoading={isLoading}
+ isLoadingMore={isLoadingMore}
+ hasMore={hasMore}
+ totalLoaded={documents.length}
+ loadMoreDocuments={loadMore}
+ />
+ </div>
+ )
+}
+```
+
+<Tip>
+The graph automatically loads more documents when 80% of current documents are visible in the viewport. Set `autoLoadOnViewport={false}` for manual control.
+</Tip>
+
+{/* 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<DocumentWithMemories[]>([])
+ const [searchQuery, setSearchQuery] = useState('')
+ const [highlightedIds, setHighlightedIds] = useState<string[]>([])
+ 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 (
+ <div style={{ height: '100vh', display: 'flex', flexDirection: 'column' }}>
+ {/* Search bar */}
+ <div style={{
+ padding: '1rem',
+ display: 'flex',
+ gap: '0.5rem',
+ borderBottom: '1px solid #e5e7eb'
+ }}>
+ <input
+ type="text"
+ value={searchQuery}
+ onChange={(e) => setSearchQuery(e.target.value)}
+ onKeyDown={(e) => e.key === 'Enter' && handleSearch()}
+ placeholder="Search documents..."
+ style={{ flex: 1, padding: '0.5rem', borderRadius: '0.375rem' }}
+ />
+ <button onClick={handleSearch}>Search</button>
+ <button onClick={() => {
+ setHighlightedIds([])
+ setSearchQuery('')
+ }}>
+ Clear
+ </button>
+ <label>
+ <input
+ type="checkbox"
+ checked={showHighlights}
+ onChange={(e) => setShowHighlights(e.target.checked)}
+ />
+ Show highlights
+ </label>
+ </div>
+
+ {/* Graph */}
+ <div style={{ flex: 1 }}>
+ <MemoryGraph
+ documents={documents}
+ highlightDocumentIds={highlightedIds}
+ highlightsVisible={showHighlights}
+ variant="console"
+ />
+ </div>
+ </div>
+ )
+}
+```
+
+<Note>
+Highlighting supports both internal document IDs and custom IDs. The graph will automatically match either.
+</Note>
+
+{/* 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 (
+ <div style={{ width: '100%', height: '100vh' }}>
+ <MemoryGraph documents={documents}>
+ <div style={{
+ display: 'flex',
+ flexDirection: 'column',
+ alignItems: 'center',
+ justifyContent: 'center',
+ gap: '2rem',
+ padding: '2rem',
+ textAlign: 'center'
+ }}>
+ <div>
+ <svg
+ width="120"
+ height="120"
+ viewBox="0 0 24 24"
+ fill="none"
+ stroke="currentColor"
+ >
+ <circle cx="12" cy="12" r="10" />
+ <line x1="12" y1="8" x2="12" y2="12" />
+ <line x1="12" y1="16" x2="12.01" y2="16" />
+ </svg>
+ </div>
+
+ <div>
+ <h2 style={{ fontSize: '1.5rem', fontWeight: 600, marginBottom: '0.5rem' }}>
+ No memories yet
+ </h2>
+ <p style={{ color: '#6b7280', maxWidth: '400px' }}>
+ Start adding content to see your knowledge graph come to life.
+ Documents and their connections will appear here.
+ </p>
+ </div>
+
+ <div style={{ display: 'flex', gap: '1rem' }}>
+ <button
+ onClick={() => 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
+ </button>
+
+ <button
+ onClick={() => window.location.href = '/docs'}
+ style={{
+ padding: '0.75rem 1.5rem',
+ backgroundColor: 'transparent',
+ border: '1px solid #d1d5db',
+ borderRadius: '0.5rem',
+ cursor: 'pointer'
+ }}
+ >
+ Learn More
+ </button>
+ </div>
+ </div>
+ </MemoryGraph>
+ </div>
+ )
+}
+```
+
+## 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,
+})
+```
+
+<Warning>
+Always implement user isolation on the backend. Never trust client-side filtering for security.
+</Warning>
+
+## 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 (
+ <div style={{ height: '100vh' }}>
+ <MemoryGraph
+ documents={data?.documents || []}
+ isLoading={isLoading}
+ error={error}
+ />
+ </div>
+ )
+}
+```
+
+## Next Steps
+
+<CardGroup cols={2}>
+ <Card title="API Reference" icon="book" href="/memory-graph/api-reference">
+ Explore all props and types
+ </Card>
+
+ <Card title="Troubleshooting" icon="wrench" href="/memory-graph/troubleshooting">
+ Solve common issues
+ </Card>
+</CardGroup>