From 1b9b3012e37284d67d9061c6a13dd53cfeb7463f Mon Sep 17 00:00:00 2001 From: nexxeln <95541290+nexxeln@users.noreply.github.com> Date: Thu, 4 Dec 2025 18:56:40 +0000 Subject: add docs for graph package (#603) --- apps/docs/docs.json | 12 + apps/docs/memory-graph/api-reference.mdx | 334 +++++++++++++++++++++++++ apps/docs/memory-graph/examples.mdx | 407 +++++++++++++++++++++++++++++++ apps/docs/memory-graph/installation.mdx | 28 +++ apps/docs/memory-graph/npm.mdx | 5 + apps/docs/memory-graph/overview.mdx | 38 +++ apps/docs/memory-graph/quickstart.mdx | 207 ++++++++++++++++ packages/memory-graph/README.md | 372 ++++------------------------ 8 files changed, 1075 insertions(+), 328 deletions(-) create mode 100644 apps/docs/memory-graph/api-reference.mdx create mode 100644 apps/docs/memory-graph/examples.mdx create mode 100644 apps/docs/memory-graph/installation.mdx create mode 100644 apps/docs/memory-graph/npm.mdx create mode 100644 apps/docs/memory-graph/overview.mdx create mode 100644 apps/docs/memory-graph/quickstart.mdx 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 + + + Array of documents to display in the graph. Each document must include its memory entries. + + + + Shows a loading indicator when true. + + + + Error object to display. Shows an error message overlay when set. + + + + Visual variant: + - `console`: Full-featured dashboard view (0.8x zoom, space selector visible) + - `consumer`: Embedded widget view (0.5x zoom, space selector hidden) + + + + Content to render when no documents exist. Useful for empty states. + + +#### Pagination Props + + + Shows a subtle indicator when loading additional documents. + + + + Whether more documents are available to load. + + + + Total number of documents currently loaded. Shown in loading indicator. + + + + Callback to load more documents. Called automatically when viewport shows most documents. + + + + Automatically load more documents when 80% are visible in viewport. + + +#### Display Props + + + Show or hide the space filter dropdown. Defaults to `true` for console variant, `false` for consumer. + + + + Array of document IDs to highlight with a pulsing outline. Accepts both `customId` and internal `id`. + + + + Controls whether highlights are shown. Useful for toggling highlights without changing the array. + + + + Pixels occluded on the right side (e.g., by a sidebar). Graph auto-fits accounting for this space. + + + + Custom ID for the legend component. Useful for testing or styling. + + +#### Controlled State Props + + + Currently selected space. When provided, makes space selection controlled. Use `"all"` for all spaces. + + + + Callback when space selection changes. Required when using `selectedSpace`. + + + + Maximum memories to show per document when a specific space is selected. Only applies when `selectedSpace !== "all"`. + + + + Enable experimental features. Currently unused but reserved for future features. + + +## 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 | null; + processingMetadata?: Record | 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 | 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 | 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([]); + 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 ( +
+ +
+ ); +} +``` + +## 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([]); + 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 ( +
+
+ handleSearch(e.target.value)} + style={{ + padding: '8px 12px', + borderRadius: 8, + border: '1px solid #333', + background: '#1a1a1a', + color: 'white', + }} + /> +
+ + 0} + /> +
+ ); +} +``` + +## 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 ( +
+
+

Filters

+ + + + +
+ + +
+ ); +} +``` + +## 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 ( +
+ +
+

No memories to display

+
+
+
+ ); +} +``` + +## 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(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 ( +
+ +
+
+

Welcome to your Memory Graph

+

Add some content to get started

+ +
+
+
+
+ ); +} +``` + +## 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 ; +} +``` + +```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 ( +
+ +
+ ); +} +``` + +## 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 ( +
+ +
+ ); +} +``` 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 + + + + Get the graph running with real data + + + Explore all available props and types + + 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([]); + 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 +// 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); +}); +``` + + + + + Never expose your Supermemory API key to the client. Always fetch data through your backend. + + +## 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 + +``` + +### 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'; +``` + + + The automatic CSS injection works for most setups. Only use the explicit import if you need custom control over style loading order. + + + +### Custom Empty State + +Show custom content when no documents exist: + +```tsx + +
+

No memories yet

+

Add content to see your knowledge graph

+
+
+``` + +### Hide Space Selector + +```tsx + +``` + +## Next Steps + + + + See more usage examples + + + Full API documentation + + diff --git a/packages/memory-graph/README.md b/packages/memory-graph/README.md index eae06940..83710f5a 100644 --- a/packages/memory-graph/README.md +++ b/packages/memory-graph/README.md @@ -1,378 +1,94 @@ # @supermemory/memory-graph -> Interactive graph visualization component for Supermemory - visualize and explore your memory connections +Interactive graph visualization for documents and their memory connections. [![npm version](https://img.shields.io/npm/v/@supermemory/memory-graph.svg)](https://www.npmjs.com/package/@supermemory/memory-graph) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) -## Features - -- **WebGL-powered rendering** - Smooth performance with hundreds of nodes -- **Interactive exploration** - Pan, zoom, drag nodes, and explore connections -- **Semantic connections** - Visualizes relationships based on content similarity -- **Space filtering with search** - Dynamically search and filter by spaces/tags -- **Memory limit control** - Limit memories per document (50-3000) for performance -- **Controlled/uncontrolled modes** - Flexible state management for integration -- **Responsive design** - Works seamlessly on mobile and desktop -- **Zero configuration** - Works out of the box with automatic CSS injection -- **Lightweight** - Tree-shakeable and optimized bundle -- **TypeScript** - Full TypeScript support with exported types - ## Installation ```bash npm install @supermemory/memory-graph # or -yarn add @supermemory/memory-graph +bun add @supermemory/memory-graph # or pnpm add @supermemory/memory-graph -# or -bun add @supermemory/memory-graph ``` ## Quick Start -The component accepts document data directly - you fetch the data from your backend, which proxies requests to the Supermemory API with proper authentication. - ```tsx -import { MemoryGraph } from '@supermemory/memory-graph' -import type { DocumentWithMemories } from '@supermemory/memory-graph' +import { MemoryGraph } from '@supermemory/memory-graph'; +import type { DocumentWithMemories } from '@supermemory/memory-graph'; function App() { - const [documents, setDocuments] = useState([]) - const [isLoading, setIsLoading] = useState(true) - const [error, setError] = useState(null) + const [documents, setDocuments] = useState([]); + const [isLoading, setIsLoading] = useState(true); useEffect(() => { - // Fetch from YOUR backend (which proxies to Supermemory API) - fetch('/api/supermemory-graph') + fetch('/api/graph') .then(res => res.json()) .then(data => { - setDocuments(data.documents) - setIsLoading(false) - }) - .catch(err => { - setError(err) - setIsLoading(false) - }) - }, []) + setDocuments(data.documents); + setIsLoading(false); + }); + }, []); return ( - - ) -} -``` - -## Backend Proxy Example - -Create an API route in your backend that authenticates and proxies requests to Supermemory: - -### Next.js API Route - -```typescript -// app/api/supermemory-graph/route.ts -import { NextResponse } from 'next/server' - -export async function GET(request: Request) { - // Add your own auth check here - const user = await getAuthenticatedUser(request) - if (!user) { - return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) - } - - 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) -} -``` - -## API Reference - -### Props - -| Prop | Type | Default | Description | -|------|------|---------|-------------| -| `documents` | `DocumentWithMemories[]` | **required** | Array of documents to display | -| `isLoading` | `boolean` | `false` | Whether data is currently loading | -| `error` | `Error \| null` | `null` | Error that occurred during fetching | -| `variant` | `"console" \| "consumer"` | `"console"` | Visual variant | -| `showSpacesSelector` | `boolean` | Based on variant | Show/hide the spaces filter | -| `children` | `ReactNode` | - | Content to show when no documents | -| `highlightDocumentIds` | `string[]` | `[]` | Document IDs to highlight | -| `highlightsVisible` | `boolean` | `true` | Whether highlights are visible | - -### Space & Memory Control Props (Optional) - -| Prop | Type | Default | Description | -|------|------|---------|-------------| -| `selectedSpace` | `string` | `"all"` | Currently selected space (controlled) | -| `onSpaceChange` | `(spaceId: string) => void` | - | Callback when space changes | -| `onSearchSpaces` | `(query: string) => Promise` | - | Async space search function | -| `memoryLimit` | `number` | `500` | Max memories per document when space selected | -| `onMemoryLimitChange` | `(limit: number) => void` | - | Callback when limit changes | -| `isExperimental` | `boolean` | `false` | Enable experimental features | - -### Pagination Props (Optional) - -For large datasets, you can implement pagination: - -| Prop | Type | Default | Description | -|------|------|---------|-------------| -| `isLoadingMore` | `boolean` | `false` | Whether loading more data | -| `hasMore` | `boolean` | `false` | Whether more data is available | -| `totalLoaded` | `number` | `documents.length` | Total documents loaded | -| `loadMoreDocuments` | `() => Promise` | - | Callback to load more | - -### Types - -```typescript -import type { - DocumentWithMemories, - MemoryEntry, - DocumentsResponse, - MemoryGraphProps, - MemoryLimit, - MemoryCountSelectorProps, - GraphNode, - GraphEdge, - MemoryRelation -} from '@supermemory/memory-graph' - -// Memory limit can be one of these values -type MemoryLimit = 50 | 100 | 250 | 500 | 1000 | 2000 | 3000 -``` - -## Advanced Usage - -### With Pagination - -```tsx -import { MemoryGraph } from '@supermemory/memory-graph' - -function GraphWithPagination() { - const [documents, setDocuments] = useState([]) - const [page, setPage] = useState(1) - const [hasMore, setHasMore] = useState(true) - const [isLoadingMore, setIsLoadingMore] = useState(false) - - const loadMore = async () => { - setIsLoadingMore(true) - const res = await fetch(`/api/supermemory-graph?page=${page + 1}`) - const data = await res.json() - setDocuments(prev => [...prev, ...data.documents]) - setHasMore(data.pagination.currentPage < data.pagination.totalPages) - setPage(p => p + 1) - setIsLoadingMore(false) - } - - return ( - - ) -} -``` - -### Custom Empty State - -```tsx - -
-

No memories yet

-

Start adding content to see your knowledge graph

-
-
-``` - -### Controlled Space Selection & Memory Limiting - -Control the selected space and memory limit externally for integration with your app's state management: - -```tsx -import { MemoryGraph } from '@supermemory/memory-graph' - -function ControlledGraph() { - const [selectedSpace, setSelectedSpace] = useState("all") - const [memoryLimit, setMemoryLimit] = useState(500) - const [searchResults, setSearchResults] = useState([]) - - // Handle space search via your API - const handleSpaceSearch = async (query: string) => { - const response = await fetch(`/api/spaces/search?q=${query}`) - const spaces = await response.json() - setSearchResults(spaces) - return spaces - } - - return ( -
- {/* Display current state */} -
-

Selected Space: {selectedSpace}

-

Memory Limit: {memoryLimit}

- -
- - {/* Controlled graph */} +
- ) -} -``` - -### Uncontrolled Mode (Automatic) - -If you don't provide `selectedSpace` or `memoryLimit` props, the component manages its own state: - -```tsx - -``` - -### Space Search Integration - -Implement server-side space search for dynamic filtering: - -```tsx -// Frontend -const handleSpaceSearch = async (query: string): Promise => { - const response = await fetch('/api/spaces/search', { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ query }) - }) - return response.json() -} - - - -// Backend (Next.js example) -// app/api/spaces/search/route.ts -export async function POST(request: Request) { - const { query } = await request.json() - - const response = await fetch('https://api.supermemory.ai/v3/search/spaces', { - method: 'GET', - headers: { - 'Authorization': `Bearer ${process.env.SUPERMEMORY_API_KEY}`, - }, - params: { q: query } - }) - - return response.json() + ); } ``` -### Variants - -The `variant` prop controls the visual layout and initial viewport settings: - -| Variant | Initial Zoom | Spaces Selector | Legend Position | Use Case | -|---------|-------------|-----------------|-----------------|----------| -| `console` | 0.8 | Shown | Bottom-right | Full-page dashboard views | -| `consumer` | 0.5 | Hidden | Top-right | Embedded/widget views | +## Features -```tsx -// Full dashboard view - +- **Interactive canvas visualization** - Pan, zoom, and drag nodes using Canvas 2D rendering +- **Document and memory nodes** - Documents as rectangles, memories as hexagons +- **Relationship visualization** - Edges show document similarity and memory version chains +- **Space filtering** - Filter by workspace or view all memories +- **Two variants** - Full-featured console mode or embedded consumer mode +- **Pagination support** - Load more documents on demand +- **TypeScript support** - Full type definitions included -// Embedded widget - -``` +## Essential Props -## Interactive Controls +| Prop | Type | Description | +|------|------|-------------| +| `documents` | `DocumentWithMemories[]` | Array of documents with their memory entries | +| `isLoading` | `boolean` | Show loading state | +| `variant` | `"console" \| "consumer"` | Display mode (default: "console") | +| `error` | `Error \| null` | Error to display | +| `loadMoreDocuments` | `() => Promise` | Function to load more data | +| `highlightDocumentIds` | `string[]` | IDs of documents to highlight | -- **Pan**: Click and drag the background -- **Zoom**: Mouse wheel or pinch on mobile -- **Select Node**: Click on any document or memory -- **Drag Nodes**: Click and drag individual nodes -- **Fit to View**: Auto-fit button to center all content -- **Space Filter**: Click the space selector to filter by space -- **Space Search**: Type in the search box and press Enter to find spaces -- **Memory Limit**: Select a limit (50-3K) when filtering by space +## Documentation -## Browser Support +Full documentation available at [docs.supermemory.ai](https://docs.supermemory.ai): -- Chrome/Edge (latest) -- Firefox (latest) -- Safari (latest) -- Mobile browsers with WebGL support +- [Overview](https://docs.supermemory.ai/memory-graph/overview) - What it is and when to use it +- [Installation](https://docs.supermemory.ai/memory-graph/installation) - Setup and requirements +- [Quick Start](https://docs.supermemory.ai/memory-graph/quickstart) - Get running in 2 minutes +- [API Reference](https://docs.supermemory.ai/memory-graph/api-reference) - Complete API documentation +- [Examples](https://docs.supermemory.ai/memory-graph/examples) - Common use cases +- [Troubleshooting](https://docs.supermemory.ai/memory-graph/troubleshooting) - Common issues ## Requirements - React 18+ -- Modern browser with WebGL support - -## Development - -```bash -# Install dependencies -bun install - -# Build the package -bun run build - -# Watch mode for development -bun run dev - -# Type checking -bun run check-types -``` +- Modern browser ## License MIT -## Support +## Links -- Issues: [GitHub Issues](https://github.com/supermemoryai/supermemory/issues) +- [GitHub](https://github.com/supermemoryai/supermemory/tree/main/packages/memory-graph) +- [Issues](https://github.com/supermemoryai/supermemory/issues) +- [Supermemory](https://supermemory.ai) -- cgit v1.2.3