apps/docs/integrations/memory-graph.mdx
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.
<Card title="@supermemory/memory-graph on npm" icon="npm" href="https://www.npmjs.com/package/@supermemory/memory-graph"> Check out the NPM page for more details </Card>npm install @supermemory/memory-graph
Requirements: React 18.0.0 or higher
'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<DocumentWithMemories[]>([]);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState<Error | null>(null);
useEffect(() => {
fetch('/api/graph')
.then(res => res.json())
.then(data => {
setDocuments(data.documents);
setIsLoading(false);
})
.catch(err => {
setError(err);
setIsLoading(false);
});
}, []);
return (
<div style={{ height: '100vh' }}>
<MemoryGraph
documents={documents}
isLoading={isLoading}
error={error}
variant="console"
/>
</div>
);
}
Create an API route to fetch documents from Supermemory:
<CodeGroup>// 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);
}
// 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);
}
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);
});
Console Variant - Full-featured dashboard view (0.8x zoom, space selector visible):
<MemoryGraph documents={documents} variant="console" />
Consumer Variant - Embedded widget view (0.5x zoom, space selector hidden):
<MemoryGraph documents={documents} variant="consumer" />
'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 (
<MemoryGraph
documents={documents}
isLoading={isLoading}
isLoadingMore={isLoadingMore}
hasMore={hasMore}
totalLoaded={documents.length}
loadMoreDocuments={loadMore}
/>
);
}
<MemoryGraph
documents={documents}
highlightDocumentIds={searchResults}
highlightsVisible={searchResults.length > 0}
/>
<MemoryGraph
documents={documents}
selectedSpace={selectedSpace}
onSpaceChange={setSelectedSpace}
showSpacesSelector={false}
/>
<MemoryGraph documents={documents} isLoading={isLoading}>
<div style={{ textAlign: 'center', padding: '2rem' }}>
<h2>No memories yet</h2>
<p>Add content to see your knowledge graph</p>
</div>
</MemoryGraph>
| 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 |
| 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<void> | - | Callback to load more |
autoLoadOnViewport | boolean | true | Auto-load when 80% visible |
| 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 |
| 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 |
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<string, string | number | boolean> | null;
createdAt: string | Date;
updatedAt: string | Date;
memoryEntries: MemoryEntry[];
}
interface MemoryEntry {
id: string;
documentId: string;
content: string | null;
summary?: string | null;
title?: string | null;
type?: string | null;
metadata?: Record<string, string | number | boolean> | null;
createdAt: string | Date;
updatedAt: string | Date;
spaceContainerTag?: string | null;
relation?: 'updates' | 'extends' | 'derives' | null;
isLatest?: boolean;
spaceId?: string | null;
}
import {
MemoryGraph,
GraphCanvas,
Legend,
LoadingIndicator,
NodeDetailPanel,
SpacesDropdown
} from '@supermemory/memory-graph';
import { useGraphData, useGraphInteractions } from '@supermemory/memory-graph';
import { colors, GRAPH_SETTINGS, LAYOUT_CONSTANTS } from '@supermemory/memory-graph';
The graph handles hundreds of nodes efficiently through:
For very large datasets (1000+ documents), use pagination to load data in chunks.
Works in all modern browsers supporting Canvas 2D API, ES2020, and CSS custom properties. Tested on Chrome, Firefox, Safari, and Edge.