diff options
| author | nexxeln <[email protected]> | 2025-12-04 18:56:40 +0000 |
|---|---|---|
| committer | nexxeln <[email protected]> | 2025-12-04 18:56:40 +0000 |
| commit | 1b9b3012e37284d67d9061c6a13dd53cfeb7463f (patch) | |
| tree | 79ad24f1ccadf666c9c4d9a2d3947a90eb6cecec /apps | |
| parent | use latest graph and remove old graph (#604) (diff) | |
| download | supermemory-graph-docs.tar.xz supermemory-graph-docs.zip | |
add docs for graph package (#603)graph-docs
Diffstat (limited to 'apps')
| -rw-r--r-- | apps/docs/docs.json | 12 | ||||
| -rw-r--r-- | apps/docs/memory-graph/api-reference.mdx | 334 | ||||
| -rw-r--r-- | apps/docs/memory-graph/examples.mdx | 407 | ||||
| -rw-r--r-- | apps/docs/memory-graph/installation.mdx | 28 | ||||
| -rw-r--r-- | apps/docs/memory-graph/npm.mdx | 5 | ||||
| -rw-r--r-- | apps/docs/memory-graph/overview.mdx | 38 | ||||
| -rw-r--r-- | apps/docs/memory-graph/quickstart.mdx | 207 |
7 files changed, 1031 insertions, 0 deletions
diff --git a/apps/docs/docs.json b/apps/docs/docs.json index dab7caeb..347d6df5 100644 --- a/apps/docs/docs.json +++ b/apps/docs/docs.json @@ -213,6 +213,18 @@ "ai-sdk/infinite-chat", "ai-sdk/npm" ] + }, + { + "group": "Memory Graph", + "icon": "network", + "pages": [ + "memory-graph/overview", + "memory-graph/installation", + "memory-graph/quickstart", + "memory-graph/api-reference", + "memory-graph/examples", + "memory-graph/npm" + ] } ] } diff --git a/apps/docs/memory-graph/api-reference.mdx b/apps/docs/memory-graph/api-reference.mdx new file mode 100644 index 00000000..92641a74 --- /dev/null +++ b/apps/docs/memory-graph/api-reference.mdx @@ -0,0 +1,334 @@ +--- +title: 'API Reference' +description: 'Complete reference for Memory Graph props and types' +--- + +## Component Props + +### MemoryGraph + +The main graph component. + +#### Core Props + +<ParamField path="documents" type="DocumentWithMemories[]" required> + Array of documents to display in the graph. Each document must include its memory entries. +</ParamField> + +<ParamField path="isLoading" type="boolean" default="false"> + Shows a loading indicator when true. +</ParamField> + +<ParamField path="error" type="Error | null" default="null"> + Error object to display. Shows an error message overlay when set. +</ParamField> + +<ParamField path="variant" type='"console" | "consumer"' default='"console"'> + Visual variant: + - `console`: Full-featured dashboard view (0.8x zoom, space selector visible) + - `consumer`: Embedded widget view (0.5x zoom, space selector hidden) +</ParamField> + +<ParamField path="children" type="ReactNode"> + Content to render when no documents exist. Useful for empty states. +</ParamField> + +#### Pagination Props + +<ParamField path="isLoadingMore" type="boolean" default="false"> + Shows a subtle indicator when loading additional documents. +</ParamField> + +<ParamField path="hasMore" type="boolean" default="false"> + Whether more documents are available to load. +</ParamField> + +<ParamField path="totalLoaded" type="number"> + Total number of documents currently loaded. Shown in loading indicator. +</ParamField> + +<ParamField path="loadMoreDocuments" type="() => Promise<void>"> + Callback to load more documents. Called automatically when viewport shows most documents. +</ParamField> + +<ParamField path="autoLoadOnViewport" type="boolean" default="true"> + Automatically load more documents when 80% are visible in viewport. +</ParamField> + +#### Display Props + +<ParamField path="showSpacesSelector" type="boolean"> + Show or hide the space filter dropdown. Defaults to `true` for console variant, `false` for consumer. +</ParamField> + +<ParamField path="highlightDocumentIds" type="string[]" default="[]"> + Array of document IDs to highlight with a pulsing outline. Accepts both `customId` and internal `id`. +</ParamField> + +<ParamField path="highlightsVisible" type="boolean" default="true"> + Controls whether highlights are shown. Useful for toggling highlights without changing the array. +</ParamField> + +<ParamField path="occludedRightPx" type="number" default="0"> + Pixels occluded on the right side (e.g., by a sidebar). Graph auto-fits accounting for this space. +</ParamField> + +<ParamField path="legendId" type="string"> + Custom ID for the legend component. Useful for testing or styling. +</ParamField> + +#### Controlled State Props + +<ParamField path="selectedSpace" type="string"> + Currently selected space. When provided, makes space selection controlled. Use `"all"` for all spaces. +</ParamField> + +<ParamField path="onSpaceChange" type="(spaceId: string) => void"> + Callback when space selection changes. Required when using `selectedSpace`. +</ParamField> + +<ParamField path="memoryLimit" type="number"> + Maximum memories to show per document when a specific space is selected. Only applies when `selectedSpace !== "all"`. +</ParamField> + +<ParamField path="isExperimental" type="boolean" default="false"> + Enable experimental features. Currently unused but reserved for future features. +</ParamField> + +## Data Types + +### DocumentWithMemories + +```typescript +interface DocumentWithMemories { + id: string; + customId?: string | null; + contentHash: string | null; + orgId: string; + userId: string; + connectionId?: 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; + processingMetadata?: Record<string, unknown> | null; + raw?: string | null; + tokenCount?: number | null; + wordCount?: number | null; + chunkCount?: number | null; + averageChunkSize?: number | null; + summaryEmbedding?: number[] | null; + summaryEmbeddingModel?: string | null; + createdAt: string | Date; + updatedAt: string | Date; + memoryEntries: MemoryEntry[]; +} +``` + +### MemoryEntry + +```typescript +interface MemoryEntry { + id: string; + customId?: string | null; + documentId: string; + content: string | null; + summary?: string | null; + title?: string | null; + url?: string | null; + type?: string | null; + metadata?: Record<string, string | number | boolean> | null; + embedding?: number[] | null; + embeddingModel?: string | null; + tokenCount?: number | null; + createdAt: string | Date; + updatedAt: string | Date; + + // Fields from join relationship + sourceAddedAt?: Date | null; + sourceRelevanceScore?: number | null; + sourceMetadata?: Record<string, unknown> | null; + spaceContainerTag?: string | null; + + // Version chain fields + updatesMemoryId?: string | null; + nextVersionId?: string | null; + relation?: 'updates' | 'extends' | 'derives' | null; + + // Memory status fields + isForgotten?: boolean; + forgetAfter?: Date | string | null; + isLatest?: boolean; + + // Space/container fields + spaceId?: string | null; + + // Legacy fields (for backwards compatibility) + memory?: string | null; + memoryRelations?: Array<{ + relationType: 'updates' | 'extends' | 'derives'; + targetMemoryId: string; + }> | null; + parentMemoryId?: string | null; +} +``` + +### GraphNode + +Internal type for rendered nodes: + +```typescript +interface GraphNode { + id: string; + type: 'document' | 'memory'; + x: number; + y: number; + data: DocumentWithMemories | MemoryEntry; + size: number; + color: string; + isHovered: boolean; + isDragging: boolean; +} +``` + +### GraphEdge + +Internal type for connections: + +```typescript +interface GraphEdge { + id: string; + source: string; + target: string; + similarity: number; + edgeType: 'doc-memory' | 'doc-doc' | 'version'; + relationType?: 'updates' | 'extends' | 'derives'; + color: string; + visualProps: { + opacity: number; + thickness: number; + glow: number; + pulseDuration: number; + }; +} +``` + +## Exported Components + +Besides `MemoryGraph`, the package exports individual components for advanced use cases: + +### GraphCanvas + +Low-level canvas renderer. Not recommended for direct use. + +```typescript +import { GraphCanvas } from '@supermemory/memory-graph'; +``` + +### Legend + +Graph legend showing node types and counts. + +```typescript +import { Legend } from '@supermemory/memory-graph'; +``` + +### LoadingIndicator + +Loading state indicator with progress counter. + +```typescript +import { LoadingIndicator } from '@supermemory/memory-graph'; +``` + +### NodeDetailPanel + +Side panel showing node details when clicked. + +```typescript +import { NodeDetailPanel } from '@supermemory/memory-graph'; +``` + +### SpacesDropdown + +Space filter dropdown. + +```typescript +import { SpacesDropdown } from '@supermemory/memory-graph'; +``` + +## Exported Hooks + +### useGraphData + +Processes documents into graph nodes and edges. + +```typescript +import { useGraphData } from '@supermemory/memory-graph'; + +const { nodes, edges } = useGraphData( + data, + selectedSpace, + nodePositions, + draggingNodeId, + memoryLimit +); +``` + +### useGraphInteractions + +Handles pan, zoom, and node interactions. + +```typescript +import { useGraphInteractions } from '@supermemory/memory-graph'; + +const { + panX, + panY, + zoom, + selectedNode, + handlePanStart, + handleWheel, + // ... more interaction handlers +} = useGraphInteractions('console'); +``` + +## Constants + +### colors + +Color palette used throughout the graph: + +```typescript +import { colors } from '@supermemory/memory-graph'; + +colors.document.primary; // Document fill color +colors.memory.primary; // Memory fill color +colors.connection.strong; // Strong edge color +``` + +### GRAPH_SETTINGS + +Initial zoom and pan settings for variants: + +```typescript +import { GRAPH_SETTINGS } from '@supermemory/memory-graph'; + +GRAPH_SETTINGS.console.initialZoom; // 0.8 +GRAPH_SETTINGS.consumer.initialZoom; // 0.5 +``` + +### LAYOUT_CONSTANTS + +Spatial layout configuration: + +```typescript +import { LAYOUT_CONSTANTS } from '@supermemory/memory-graph'; + +LAYOUT_CONSTANTS.clusterRadius; // Memory orbit radius +LAYOUT_CONSTANTS.documentSpacing; // Distance between documents +``` diff --git a/apps/docs/memory-graph/examples.mdx b/apps/docs/memory-graph/examples.mdx new file mode 100644 index 00000000..14d615d5 --- /dev/null +++ b/apps/docs/memory-graph/examples.mdx @@ -0,0 +1,407 @@ +--- +title: 'Examples' +description: 'Common use cases and implementation patterns' +--- + +## With Pagination + +Load documents in chunks for better performance with large datasets. + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import type { DocumentWithMemories } from '@supermemory/memory-graph'; +import { useCallback, useEffect, useState } from 'react'; + +export default function PaginatedGraph() { + 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); + + // Initial load + useEffect(() => { + fetchPage(1, false); + }, []); + + const fetchPage = async (pageNum: number, append: boolean) => { + if (pageNum === 1) { + setIsLoading(true); + } else { + setIsLoadingMore(true); + } + + const res = await fetch(`/api/graph?page=${pageNum}&limit=100`); + const data = await res.json(); + + if (append) { + setDocuments(prev => [...prev, ...data.documents]); + } else { + 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 ( + <div style={{ height: '100vh' }}> + <MemoryGraph + documents={documents} + isLoading={isLoading} + isLoadingMore={isLoadingMore} + hasMore={hasMore} + totalLoaded={documents.length} + loadMoreDocuments={loadMore} + /> + </div> + ); +} +``` + +## Highlighting Search Results + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import { useState } from 'react'; + +export default function SearchableGraph() { + const [documents, setDocuments] = useState([]); + const [searchResults, setSearchResults] = useState<string[]>([]); + const [searchQuery, setSearchQuery] = useState(''); + + const handleSearch = async (query: string) => { + setSearchQuery(query); + + if (!query) { + setSearchResults([]); + return; + } + + const res = await fetch(`/api/search?q=${encodeURIComponent(query)}`); + const data = await res.json(); + + // Extract document IDs from search results + const docIds = data.results.map(r => r.documentId); + setSearchResults(docIds); + }; + + return ( + <div style={{ height: '100vh' }}> + <div style={{ position: 'absolute', top: 16, left: 16, zIndex: 10 }}> + <input + type="text" + placeholder="Search memories..." + value={searchQuery} + onChange={(e) => handleSearch(e.target.value)} + style={{ + padding: '8px 12px', + borderRadius: 8, + border: '1px solid #333', + background: '#1a1a1a', + color: 'white', + }} + /> + </div> + + <MemoryGraph + documents={documents} + highlightDocumentIds={searchResults} + highlightsVisible={searchResults.length > 0} + /> + </div> + ); +} +``` + +## Controlled Space Selection + +Control space filtering from outside the component. + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import { useState } from 'react'; + +export default function ControlledSpaceGraph() { + const [documents, setDocuments] = useState([]); + const [selectedSpace, setSelectedSpace] = useState('all'); + + // Extract available spaces from documents + const spaces = Array.from( + new Set( + documents.flatMap(doc => + doc.memoryEntries.map(m => m.spaceId || 'default') + ) + ) + ); + + return ( + <div style={{ height: '100vh' }}> + <div style={{ + position: 'absolute', + top: 16, + right: 16, + zIndex: 10, + background: '#1a1a1a', + padding: 16, + borderRadius: 8, + border: '1px solid #333', + }}> + <h3 style={{ margin: '0 0 12px 0', color: 'white' }}>Filters</h3> + + <select + value={selectedSpace} + onChange={(e) => setSelectedSpace(e.target.value)} + style={{ + padding: '8px 12px', + borderRadius: 6, + background: '#2a2a2a', + color: 'white', + border: '1px solid #444', + width: '100%', + }} + > + <option value="all">All Spaces</option> + {spaces.map(space => ( + <option key={space} value={space}>{space}</option> + ))} + </select> + + <button + onClick={() => setSelectedSpace('all')} + style={{ + marginTop: 12, + padding: '6px 12px', + borderRadius: 6, + background: '#333', + color: 'white', + border: 'none', + width: '100%', + cursor: 'pointer', + }} + > + Reset + </button> + </div> + + <MemoryGraph + documents={documents} + selectedSpace={selectedSpace} + onSpaceChange={setSelectedSpace} + showSpacesSelector={false} + /> + </div> + ); +} +``` + +## Embedded Widget + +Use the consumer variant for embedded views with custom styling. + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; + +export default function EmbeddedGraph({ documents }) { + return ( + <div + style={{ + height: 400, + borderRadius: 12, + overflow: 'hidden', + border: '1px solid #2a2a2a', + }} + > + <MemoryGraph + documents={documents} + variant="consumer" + showSpacesSelector={false} + > + <div style={{ + textAlign: 'center', + padding: '2rem', + color: '#888', + }}> + <p>No memories to display</p> + </div> + </MemoryGraph> + </div> + ); +} +``` + +## With Loading States + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import { useEffect, useState } from 'react'; + +export default function LoadingGraph() { + const [documents, setDocuments] = useState([]); + const [isLoading, setIsLoading] = useState(true); + const [error, setError] = useState<Error | null>(null); + + useEffect(() => { + fetch('/api/graph') + .then(res => { + if (!res.ok) throw new Error('Failed to load graph'); + return 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} + > + <div style={{ + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + height: '100%', + color: '#888', + }}> + <div> + <h2>Welcome to your Memory Graph</h2> + <p>Add some content to get started</p> + <button + style={{ + marginTop: 16, + padding: '8px 16px', + borderRadius: 6, + background: '#2563eb', + color: 'white', + border: 'none', + cursor: 'pointer', + }} + onClick={() => window.location.href = '/add-memory'} + > + Add First Memory + </button> + </div> + </div> + </MemoryGraph> + </div> + ); +} +``` + +## React Server Component + +```tsx +// Next.js App Router with Server Component +import { MemoryGraphClient } from './memory-graph-client'; + +async function getGraphData() { + const res = await fetch('https://api.supermemory.ai/v3/documents/documents', { + method: 'POST', + headers: { + 'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`, + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + page: 1, + limit: 500, + sort: 'createdAt', + order: 'desc', + }), + cache: 'no-store', // or use revalidation + }); + + return res.json(); +} + +export default async function GraphPage() { + const data = await getGraphData(); + + return <MemoryGraphClient initialDocuments={data.documents} />; +} +``` + +```tsx +// memory-graph-client.tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import type { DocumentWithMemories } from '@supermemory/memory-graph'; + +interface Props { + initialDocuments: DocumentWithMemories[]; +} + +export function MemoryGraphClient({ initialDocuments }: Props) { + return ( + <div style={{ height: '100vh' }}> + <MemoryGraph + documents={initialDocuments} + isLoading={false} + /> + </div> + ); +} +``` + +## Mobile-Responsive Layout + +```tsx +'use client'; + +import { MemoryGraph } from '@supermemory/memory-graph'; +import { useState, useEffect } from 'react'; + +export default function ResponsiveGraph({ documents }) { + const [isMobile, setIsMobile] = useState(false); + + useEffect(() => { + const checkMobile = () => { + setIsMobile(window.innerWidth < 768); + }; + + checkMobile(); + window.addEventListener('resize', checkMobile); + return () => window.removeEventListener('resize', checkMobile); + }, []); + + return ( + <div style={{ + height: isMobile ? '60vh' : '100vh', + width: '100%', + }}> + <MemoryGraph + documents={documents} + variant={isMobile ? 'consumer' : 'console'} + showSpacesSelector={!isMobile} + /> + </div> + ); +} +``` diff --git a/apps/docs/memory-graph/installation.mdx b/apps/docs/memory-graph/installation.mdx new file mode 100644 index 00000000..0051825f --- /dev/null +++ b/apps/docs/memory-graph/installation.mdx @@ -0,0 +1,28 @@ +--- +title: 'Installation' +description: 'Install and set up the Memory Graph component' +--- + +## Installation + +Install the package using your preferred package manager: + +```bash npm +npm install @supermemory/memory-graph +``` + +## Requirements + +- **React**: 18.0.0 or higher +- **react-dom**: 18.0.0 or higher + +## Next Steps + +<CardGroup cols={2}> + <Card title="Quick Start" icon="rocket" href="/memory-graph/quickstart"> + Get the graph running with real data + </Card> + <Card title="API Reference" icon="code" href="/memory-graph/api-reference"> + Explore all available props and types + </Card> +</CardGroup> diff --git a/apps/docs/memory-graph/npm.mdx b/apps/docs/memory-graph/npm.mdx new file mode 100644 index 00000000..73185178 --- /dev/null +++ b/apps/docs/memory-graph/npm.mdx @@ -0,0 +1,5 @@ +--- +title: "NPM link" +url: "https://www.npmjs.com/package/@supermemory/memory-graph" +icon: npm +--- diff --git a/apps/docs/memory-graph/overview.mdx b/apps/docs/memory-graph/overview.mdx new file mode 100644 index 00000000..c3260d21 --- /dev/null +++ b/apps/docs/memory-graph/overview.mdx @@ -0,0 +1,38 @@ +--- +title: 'Overview' +description: 'Interactive visualization for documents, memories and connections' +--- + +## What is Memory Graph? + +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. + +The graph renders using Canvas 2D, providing smooth interactions with hundreds of nodes through pan, zoom, and drag operations. + +## When to Use It + +Use Memory Graph when you need to: + +- **Visualize knowledge graphs** - Show how documents and memories connect +- **Navigate memory spaces** - Filter and browse by workspace or tag +- **Create memory browsers** - Give users a visual overview of their stored content + +## 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 rendering when zoomed out) +- Change-based rendering (only redraws when state changes) +- Throttled viewport calculations + +For very large datasets (1000+ documents), use pagination to load data in chunks. + +## Browser Support + +Works in all modern browsers that support: +- Canvas 2D API +- ES2020 JavaScript +- CSS custom properties + +Tested on Chrome, Firefox, Safari, and Edge (latest versions). diff --git a/apps/docs/memory-graph/quickstart.mdx b/apps/docs/memory-graph/quickstart.mdx new file mode 100644 index 00000000..d05a0925 --- /dev/null +++ b/apps/docs/memory-graph/quickstart.mdx @@ -0,0 +1,207 @@ +--- +title: 'Quick Start' +description: 'Get Memory Graph running in 2 minutes' +--- + +## Basic Setup + +Here's a minimal example to get the graph running: + +```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<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: + +<CodeGroup> + +```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 +// routes/graph.js +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); +}); +``` + +</CodeGroup> + +<Warning> + Never expose your Supermemory API key to the client. Always fetch data through your backend. +</Warning> + +## Environment Variables + +Add your API key to `.env.local`: + +```bash +SUPERMEMORY_API_KEY=your_api_key_here +``` + +Get your API key from the [Supermemory dashboard](https://console.supermemory.ai). + +## Common Customizations + +### Embedded Mode + +For a widget-style view, use the consumer variant: + +```tsx +<MemoryGraph + documents={documents} + isLoading={isLoading} + variant="consumer" +/> +``` + +### CSS Import + +The component includes bundled styles. You don't need to import CSS separately. Styles are automatically injected when the component mounts. + +If you want explicit control, you can import the stylesheet: + +```typescript +import '@supermemory/memory-graph/styles.css'; +``` + +<Note> + The automatic CSS injection works for most setups. Only use the explicit import if you need custom control over style loading order. +</Note> + + +### Custom Empty State + +Show custom content when no documents exist: + +```tsx +<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> +``` + +### Hide Space Selector + +```tsx +<MemoryGraph + documents={documents} + isLoading={isLoading} + showSpacesSelector={false} +/> +``` + +## Next Steps + +<CardGroup cols={2}> + <Card title="Examples" icon="code" href="/memory-graph/examples"> + See more usage examples + </Card> + <Card title="API Reference" icon="book" href="/memory-graph/api-reference"> + Full API documentation + </Card> +</CardGroup> |