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.
@supermemory/memory-graph on npm Check out the NPM page for more details
Installation
npm install @supermemory/memory-graph
Requirements: React 18.0.0 or higher
Quick Start
'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 >
);
}
Backend API Route
Create an API route to fetch documents from Supermemory:
Next.js App Router
Next.js Pages Router
Express
// 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 );
}
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):
< MemoryGraph documents = { documents } variant = "console" />
Consumer Variant - Embedded widget view (0.5x zoom, space selector hidden):
< MemoryGraph documents = { documents } variant = "consumer" />
Examples
'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 }
/>
);
}
Highlighting Search Results
< MemoryGraph
documents = { documents }
highlightDocumentIds = { searchResults }
highlightsVisible = { searchResults . length > 0 }
/>
Controlled Space Selection
< MemoryGraph
documents = { documents }
selectedSpace = { selectedSpace }
onSpaceChange = { setSelectedSpace }
showSpacesSelector = { false }
/>
Custom Empty State
< 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 >
Props Reference
Core Props
Prop Type Default Description documentsDocumentWithMemories[]required Array of documents to display isLoadingbooleanfalseShows loading indicator errorError | nullnullError to display variant"console" | "consumer""console"Visual variant childrenReactNode- Custom empty state content
Prop Type Default Description isLoadingMorebooleanfalseShows indicator when loading more hasMorebooleanfalseWhether more documents available totalLoadednumber- Total documents currently loaded loadMoreDocuments() => Promise<void>- Callback to load more autoLoadOnViewportbooleantrueAuto-load when 80% visible
Display Props
Prop Type Default Description showSpacesSelectorbooleanvariant-based Show space filter dropdown highlightDocumentIdsstring[][]Document IDs to highlight highlightsVisiblebooleantrueWhether highlights shown occludedRightPxnumber0Pixels occluded on right
Controlled State Props
Prop Type Description selectedSpacestringCurrently selected space (use "all" for all) onSpaceChange(spaceId: string) => voidCallback when space changes memoryLimitnumberMax memories per document when space selected
Data Types
DocumentWithMemories
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 [];
}
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 ;
}
Exports
Components
import {
MemoryGraph ,
GraphCanvas ,
Legend ,
LoadingIndicator ,
NodeDetailPanel ,
SpacesDropdown
} from '@supermemory/memory-graph' ;
Hooks
import { useGraphData , useGraphInteractions } from '@supermemory/memory-graph' ;
Constants
import { colors , GRAPH_SETTINGS , LAYOUT_CONSTANTS } from '@supermemory/memory-graph' ;
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.