--- title: 'Memory Graph' sidebarTitle: "Memory Graph" description: 'Interactive visualization for documents, memories and connections' icon: "network" --- Memory Graph is a React component that visualizes your Supermemory documents and memories as an interactive network. Documents appear as rectangular nodes, memories as hexagonal nodes, and connections between them show relationships and similarity. Check out the NPM page for more details ## Installation ```bash npm install @supermemory/memory-graph ``` **Requirements:** React 18.0.0 or higher ## Quick Start ```tsx 'use client'; // For Next.js App Router import { MemoryGraph } from '@supermemory/memory-graph'; import type { DocumentWithMemories } from '@supermemory/memory-graph'; import { useEffect, useState } from 'react'; export default function GraphPage() { const [documents, setDocuments] = useState([]); const [isLoading, setIsLoading] = useState(true); const [error, setError] = useState(null); useEffect(() => { fetch('/api/graph') .then(res => res.json()) .then(data => { setDocuments(data.documents); setIsLoading(false); }) .catch(err => { setError(err); setIsLoading(false); }); }, []); return (
); } ``` ## Backend API Route Create an API route to fetch documents from Supermemory: ```typescript Next.js App Router // app/api/graph/route.ts import { NextResponse } from 'next/server'; export async function GET() { 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', }), }); const data = await response.json(); return NextResponse.json(data); } ``` ```typescript Next.js Pages Router // pages/api/graph.ts import type { NextApiRequest, NextApiResponse } from 'next'; export default async function handler(req: NextApiRequest, res: NextApiResponse) { 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' }), }); const data = await response.json(); res.json(data); } ``` ```javascript Express app.get('/api/graph', async (req, res) => { 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' }), }); const data = await response.json(); res.json(data); }); ``` Never expose your Supermemory API key to the client. Always fetch data through your backend. --- ## Variants **Console Variant** - Full-featured dashboard view (0.8x zoom, space selector visible): ```tsx ``` **Consumer Variant** - Embedded widget view (0.5x zoom, space selector hidden): ```tsx ``` --- ## Examples ### With Pagination ```tsx 'use client'; import { MemoryGraph } from '@supermemory/memory-graph'; import { useCallback, useEffect, useState } from 'react'; export default function PaginatedGraph() { const [documents, setDocuments] = useState([]); const [page, setPage] = useState(1); const [hasMore, setHasMore] = useState(true); const [isLoading, setIsLoading] = useState(true); const [isLoadingMore, setIsLoadingMore] = useState(false); useEffect(() => { fetchPage(1, false); }, []); const fetchPage = async (pageNum, append) => { pageNum === 1 ? setIsLoading(true) : setIsLoadingMore(true); const res = await fetch(`/api/graph?page=${pageNum}&limit=100`); const data = await res.json(); append ? setDocuments(prev => [...prev, ...data.documents]) : setDocuments(data.documents); setHasMore(data.pagination.currentPage < data.pagination.totalPages); setIsLoading(false); setIsLoadingMore(false); }; const loadMore = useCallback(async () => { if (!isLoadingMore && hasMore) { const nextPage = page + 1; setPage(nextPage); await fetchPage(nextPage, true); } }, [page, hasMore, isLoadingMore]); return ( ); } ``` ### Highlighting Search Results ```tsx 0} /> ``` ### Controlled Space Selection ```tsx ``` ### Custom Empty State ```tsx

No memories yet

Add content to see your knowledge graph

``` --- ## Props Reference ### Core Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `documents` | `DocumentWithMemories[]` | required | Array of documents to display | | `isLoading` | `boolean` | `false` | Shows loading indicator | | `error` | `Error \| null` | `null` | Error to display | | `variant` | `"console" \| "consumer"` | `"console"` | Visual variant | | `children` | `ReactNode` | - | Custom empty state content | ### Pagination Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `isLoadingMore` | `boolean` | `false` | Shows indicator when loading more | | `hasMore` | `boolean` | `false` | Whether more documents available | | `totalLoaded` | `number` | - | Total documents currently loaded | | `loadMoreDocuments` | `() => Promise` | - | Callback to load more | | `autoLoadOnViewport` | `boolean` | `true` | Auto-load when 80% visible | ### Display Props | Prop | Type | Default | Description | |------|------|---------|-------------| | `showSpacesSelector` | `boolean` | variant-based | Show space filter dropdown | | `highlightDocumentIds` | `string[]` | `[]` | Document IDs to highlight | | `highlightsVisible` | `boolean` | `true` | Whether highlights shown | | `occludedRightPx` | `number` | `0` | Pixels occluded on right | ### Controlled State Props | Prop | Type | Description | |------|------|-------------| | `selectedSpace` | `string` | Currently selected space (use `"all"` for all) | | `onSpaceChange` | `(spaceId: string) => void` | Callback when space changes | | `memoryLimit` | `number` | Max memories per document when space selected | --- ## Data Types ### DocumentWithMemories ```typescript interface DocumentWithMemories { id: string; customId?: string | null; title?: string | null; content?: string | null; summary?: string | null; url?: string | null; source?: string | null; type?: string | null; status: 'pending' | 'processing' | 'done' | 'failed'; metadata?: Record | null; createdAt: string | Date; updatedAt: string | Date; memoryEntries: MemoryEntry[]; } ``` ### MemoryEntry ```typescript interface MemoryEntry { id: string; documentId: string; content: string | null; summary?: string | null; title?: string | null; type?: string | null; metadata?: Record | null; createdAt: string | Date; updatedAt: string | Date; spaceContainerTag?: string | null; relation?: 'updates' | 'extends' | 'derives' | null; isLatest?: boolean; spaceId?: string | null; } ``` --- ## Exports ### Components ```typescript import { MemoryGraph, GraphCanvas, Legend, LoadingIndicator, NodeDetailPanel, SpacesDropdown } from '@supermemory/memory-graph'; ``` ### Hooks ```typescript import { useGraphData, useGraphInteractions } from '@supermemory/memory-graph'; ``` ### Constants ```typescript import { colors, GRAPH_SETTINGS, LAYOUT_CONSTANTS } from '@supermemory/memory-graph'; ``` --- ## Performance The graph handles hundreds of nodes efficiently through: - Canvas-based rendering (not DOM elements) - Viewport culling (only draws visible nodes) - Level-of-detail optimization (simplifies when zoomed out) - Change-based rendering (only redraws when state changes) For very large datasets (1000+ documents), use pagination to load data in chunks. ## Browser Support Works in all modern browsers supporting Canvas 2D API, ES2020, and CSS custom properties. Tested on Chrome, Firefox, Safari, and Edge.