supermemory / index.html
samihalawa's picture
add more feuatuires so to manage the ememoreis and retriveby coincidence and ggorup anf gorp the related ones etc. u knwo... lsit the 20 CCRUD and proceed imeplemntin ======================== CODE SNIPPETS ======================== TITLE: Setting Up and Running Development Environment (npm) DESCRIPTION: This snippet provides the commands to install project dependencies and start the local development server for a Node.js/JavaScript project using npm. 'npm install' fetches all required packages, and 'npm run dev' typically starts a development server or build process. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/backend/README.md#_snippet_0 LANGUAGE: Shell CODE: ``` npm install npm run dev ``` ---------------------------------------- TITLE: Installing Project Dependencies with Bun DESCRIPTION: This command installs all necessary project dependencies using Bun, a fast JavaScript runtime and package manager. It's the initial step required before running the application development servers. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/SELF-HOSTING-GUIDE.md#_snippet_5 LANGUAGE: bash CODE: ``` bun install ``` ---------------------------------------- TITLE: Starting Supermemory Development Servers with Bun DESCRIPTION: This command initiates the development servers for the Supermemory application using Bun. It allows developers to run and test the application locally during development. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/SELF-HOSTING-GUIDE.md#_snippet_6 LANGUAGE: bash CODE: ``` bun run dev ``` ---------------------------------------- TITLE: Starting Local Wrangler Server DESCRIPTION: After building the application, this command starts the local Wrangler server, allowing developers to test their Cloudflare Worker and Pages functions in a local environment that mimics Cloudflare's infrastructure. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/web/README.md#_snippet_2 LANGUAGE: Shell CODE: ``` npm run start ``` ---------------------------------------- TITLE: Building Application for Production Deployment (Cloudflare Pages) DESCRIPTION: This command prepares the Remix application for production by compiling and optimizing it, which is the first step before deploying to Cloudflare Pages. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/web/README.md#_snippet_4 LANGUAGE: Shell CODE: ``` npm run build ``` ---------------------------------------- TITLE: Running Development Server (Remix + Cloudflare) DESCRIPTION: This command initiates the local development server for a Remix application, providing live reloading and a local environment for testing and development. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/web/README.md#_snippet_0 LANGUAGE: Shell CODE: ``` npm run dev ``` ---------------------------------------- TITLE: Deploying Application to Cloudflare Pages DESCRIPTION: This command pushes the pre-built Remix application to Cloudflare Pages, making it publicly accessible and hosted on Cloudflare's global network. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/web/README.md#_snippet_5 LANGUAGE: Shell CODE: ``` npm run deploy ``` ---------------------------------------- TITLE: Supermemory API Base URL DESCRIPTION: Specifies the base URL for all Supermemory API requests. This is the root endpoint to which all specific API paths are appended. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/quickstart.mdx#_snippet_0 LANGUAGE: text CODE: ``` https://v2.api.supermemory.ai ``` ---------------------------------------- TITLE: Running Mintlify Local Development Server (Shell) DESCRIPTION: This command starts the local development server for your Mintlify documentation. It allows you to preview changes in real-time and must be executed from the root directory where your `mint.json` configuration file is located. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/README.md#_snippet_1 LANGUAGE: Shell CODE: ``` mintlify dev ``` ---------------------------------------- TITLE: Installing Mintlify CLI Globally (Shell) DESCRIPTION: This command uses npm to globally install the Mintlify Command Line Interface (CLI). The CLI is essential for previewing documentation changes locally and interacting with Mintlify features. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/README.md#_snippet_0 LANGUAGE: Shell CODE: ``` npm i -g mintlify ``` ---------------------------------------- TITLE: Building Application for Local Wrangler Testing DESCRIPTION: This command compiles the Remix application for production, a prerequisite for running it locally with Cloudflare's Wrangler CLI to simulate the Cloudflare Workers environment. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/web/README.md#_snippet_1 LANGUAGE: Shell CODE: ``` npm run build ``` ---------------------------------------- TITLE: Spinning up PostgreSQL Database with Docker Compose DESCRIPTION: This command uses Docker Compose to start a PostgreSQL database instance locally, including the pgvector extension, making it accessible at `localhost:5432` for the Supermemory application. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/SELF-HOSTING-GUIDE.md#_snippet_0 LANGUAGE: bash CODE: ``` docker-compose up -d ``` ---------------------------------------- TITLE: Cloning the Supermemory Repository and Installing Dependencies (Bash) DESCRIPTION: This snippet provides the commands to clone the Supermemory GitHub repository, navigate into the project directory, install Bun globally, and then install all project dependencies using Bun. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/self-hosting.mdx#_snippet_0 LANGUAGE: bash CODE: ``` git clone https://github.com/supermemoryai/supermemory.git cd supermemory npm i -g bun bun install ``` ---------------------------------------- TITLE: Starting Development Servers (Bun/Bash) DESCRIPTION: This command initiates the development servers for the Supermemory application, allowing local development and testing. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/self-hosting.mdx#_snippet_6 LANGUAGE: bash CODE: ``` bun run dev ``` ---------------------------------------- TITLE: Installing Application Dependencies (Bun/Bash) DESCRIPTION: This command installs all required project dependencies for the Supermemory application using the Bun package manager. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/self-hosting.mdx#_snippet_5 LANGUAGE: bash CODE: ``` bun install ``` ---------------------------------------- TITLE: Deploying Project (npm) DESCRIPTION: This snippet shows the command to trigger the deployment process for a Node.js/JavaScript project. 'npm run deploy' is a common script name used to build the project for production and push it to a deployment target. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/backend/README.md#_snippet_1 LANGUAGE: Shell CODE: ``` npm run deploy ``` ---------------------------------------- TITLE: Spinning Up Local Database with Docker Compose (Bash) DESCRIPTION: This command uses Docker Compose to start a local PostgreSQL database instance, including the pgvector extension, accessible at `localhost:5432`. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/self-hosting.mdx#_snippet_1 LANGUAGE: bash CODE: ``` docker-compose up -d ``` ---------------------------------------- TITLE: Searching Memories in Supermemory API (curl) DESCRIPTION: Shows how to search for existing memories in the Supermemory account using a `curl` POST request. It requires an API key for authentication and sends the search query (`q`) as a JSON payload. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/quickstart.mdx#_snippet_2 LANGUAGE: bash CODE: ``` curl -X POST https://v2.api.supermemory.ai/search \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"q": "This is the content of my first memory."}' ``` ---------------------------------------- TITLE: Adding New Memory to Supermemory API (curl) DESCRIPTION: Demonstrates how to add a new memory to the Supermemory account using a `curl` POST request. It requires an API key for authentication and sends the memory content as a JSON payload. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/quickstart.mdx#_snippet_1 LANGUAGE: bash CODE: ``` curl -X POST https://v2.api.supermemory.ai/add \ -H "x-api-key: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{"content": "This is the content of my first memory."}' ``` ---------------------------------------- TITLE: Generating Cloudflare Binding Types (TypeScript) DESCRIPTION: This command generates TypeScript type definitions for Cloudflare bindings specified in `wrangler.toml`, enhancing type safety and developer experience. It must be re-executed whenever `wrangler.toml` is modified. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/web/README.md#_snippet_3 LANGUAGE: Shell CODE: ``` npm run typegen ``` ---------------------------------------- TITLE: Applying Local Database Migrations with Bun DESCRIPTION: This command applies pending database migrations to the local PostgreSQL database using Bun, ensuring the database schema is up-to-date with the application's requirements. It's crucial for schema synchronization. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/SELF-HOSTING-GUIDE.md#_snippet_2 LANGUAGE: bash CODE: ``` bun run migrate:local ``` ---------------------------------------- TITLE: Configuring Web Application Environment Variables DESCRIPTION: This snippet outlines the environment variables necessary for the Supermemory web application. It includes configurations for WorkOS authentication, database connection, Cloudflare R2 storage, backend URL, OpenAI, Notion integration, Node environment, and Stripe payment keys. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/SELF-HOSTING-GUIDE.md#_snippet_4 LANGUAGE: env CODE: ``` WORKOS_CLIENT_ID=your_workos_client_id WORKOS_API_KEY=your_workos_api_key WORKOS_REDIRECT_URI="http://localhost:3000/callback" WORKOS_COOKIE_PASSWORD=your_cookie_password DATABASE_URL="postgresql://postgres:postgres@localhost:5432/supermemorydhravya" CLOUDFLARE_ACCOUNT_ID=your_cloudflare_account_id R2_ACCESS_KEY_ID=your_r2_access_key_id R2_SECRET_ACCESS_KEY=your_r2_secret_access_key BACKEND_URL=http://localhost:8787 OPENAI_API_KEY=your_openai_api_key NOTION_CLIENT_ID=your_notion_client_id NOTION_CLIENT_SECRET=your_notion_client_secret NODE_ENV=development STRIPE_CHECKOUT_KEY=your_stripe_checkout_key STRIPE_WEBHOOK_SECRET=your_stripe_webhook_secret ``` ---------------------------------------- TITLE: Configuring Backend Environment Variables DESCRIPTION: This snippet shows the essential environment variables required for the Supermemory backend application. These variables configure API keys for various services (WorkOS, Gemini, OpenAI, Braintrust, Resend, Turnstile), database connection, and content workflow settings. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/SELF-HOSTING-GUIDE.md#_snippet_3 LANGUAGE: env CODE: ``` WORKOS_API_KEY=your_workos_api_key WORKOS_CLIENT_ID=your_workos_client_id WORKOS_COOKIE_PASSWORD=your_cookie_password DATABASE_URL="postgresql://postgres:postgres@localhost:5432/supermemory" CONTENT_WORKFLOW=your_content_workflow GEMINI_API_KEY=your_gemini_api_key NODE_ENV=development OPEN_AI_API_KEY=your_openai_api_key BRAINTRUST_API_KEY=your_braintrust_api_key RESEND_API_KEY=your_resend_api_key TURNSTILE_SECRET_KEY=your_turnstile_secret_key ``` ---------------------------------------- TITLE: Generating Drizzle ORM Database Migration DESCRIPTION: This command generates a new database migration file using Bun, based on changes made to the Drizzle ORM schema. It's a prerequisite for applying schema updates to the database. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/SELF-HOSTING-GUIDE.md#_snippet_1 LANGUAGE: bash CODE: ``` bun run generate-migration ``` ---------------------------------------- TITLE: Example Metadata for Exact Search - JSON DESCRIPTION: Illustrates a JSON metadata object with string values, suitable for properties like 'classId' and 'year' when exact search matching is desired. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/api-reference/endpoints/memory-management/post-add.mdx#_snippet_0 LANGUAGE: json CODE: ``` { "classId": "21412", "year": "fifth" } ``` ---------------------------------------- TITLE: Example Metadata for Range Search - JSON DESCRIPTION: Demonstrates a JSON metadata object using a numeric value for 'price', enabling range-based searches for numerical or time-based properties. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/api-reference/endpoints/memory-management/post-add.mdx#_snippet_1 LANGUAGE: json CODE: ``` { "price": 1250 } ``` ---------------------------------------- TITLE: Initializing supermemory Client and Performing Operations (JavaScript) DESCRIPTION: This snippet demonstrates how to initialize the supermemory client using an API key, add content to a knowledge base from a URL with associated metadata, and then query the knowledge base for relevant information based on a natural language question. It showcases the basic workflow of content ingestion and semantic retrieval. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/README.md#_snippet_0 LANGUAGE: javascript CODE: ``` // Install: npm install supermemory import { supermemory } from 'supermemory'; const client = new supermemory({ apiKey: 'YOUR_API_KEY', }); // Add content to your knowledge base await client.memory.create({ content: "https://en.wikipedia.org/wiki/Artificial_intelligence", metadata: { source: "wikipedia", category: "AI" } }); // Query your knowledge base const results = await client.search.create({ q: "What are the ethical considerations in AI development?", limit: 5 }); ``` ---------------------------------------- TITLE: Generating and Applying Database Migrations (Bun/Bash) DESCRIPTION: These commands are used to generate new database migrations based on schema changes and then apply those migrations to the local PostgreSQL database. It's crucial to use `drizzle-orm` functions for database interactions. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/self-hosting.mdx#_snippet_2 LANGUAGE: bash CODE: ``` bun run generate-migration bun run migrate:local ``` ---------------------------------------- TITLE: Configuring Backend Environment Variables (.env) DESCRIPTION: This snippet shows the essential environment variables required for the Supermemory backend application, including API keys for various services like WorkOS, Gemini, OpenAI, Braintrust, Resend, Turnstile, and the local PostgreSQL database URL. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/self-hosting.mdx#_snippet_3 LANGUAGE: env CODE: ``` WORKOS_API_KEY=your_workos_api_key WORKOS_CLIENT_ID=your_workos_client_id WORKOS_COOKIE_PASSWORD=your_cookie_password DATABASE_URL="postgresql://postgres:postgres@localhost:5432/supermemorylocal" CONTENT_WORKFLOW=your_content_workflow GEMINI_API_KEY=your_gemini_api_key NODE_ENV=development OPEN_AI_API_KEY=your_openai_api_key BRAINTRUST_API_KEY=your_braintrust_api_key RESEND_API_KEY=your_resend_api_key TURNSTILE_SECRET_KEY=your_turnstile_secret_key ``` ---------------------------------------- TITLE: Configuring Web Application Environment Variables (.env) DESCRIPTION: This snippet lists the necessary environment variables for the Supermemory web application, covering WorkOS authentication, Cloudflare R2 storage, backend URL, OpenAI and Notion API keys, and Stripe integration details. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/self-hosting.mdx#_snippet_4 LANGUAGE: env CODE: ``` WORKOS_CLIENT_ID=your_workos_client_id WORKOS_API_KEY=your_workos_api_key WORKOS_REDIRECT_URI="http://localhost:3000/callback" WORKOS_COOKIE_PASSWORD=your_cookie_password DATABASE_URL="postgresql://postgres:postgres@localhost:5432/supermemorylocal" CLOUDFLARE_ACCOUNT_ID=your_cloudflare_account_id R2_ACCESS_KEY_ID=your_r2_access_key_id R2_SECRET_ACCESS_KEY=your_r2_secret_access_key BACKEND_URL=http://localhost:8787 OPENAI_API_KEY=your_openai_api_key NOTION_CLIENT_ID=your_notion_client_id NOTION_CLIENT_SECRET=your_notion_client_secret NODE_ENV=development STRIPE_CHECKOUT_KEY=your_stripe_checkout_key STRIPE_WEBHOOK_SECRET=your_stripe_webhook_secret ``` ---------------------------------------- TITLE: Performing a Filtered Search Request with Supermemory API - cURL Bash DESCRIPTION: This cURL command demonstrates how to make a search request to the Supermemory API, including a query string (`q`), a limit on results, and a complex `AND` filter. The filter specifies that results must match both "book": "maths" and "author": "r.d. sharma", showcasing how to apply specific metadata filters to search queries. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/essentials/metadata-filtering.mdx#_snippet_1 LANGUAGE: bash CODE: ``` curl --location 'https://v2.api.supermemory.ai/search' \ --header 'x-api-key: supermemory_RXPx' \ --header 'Content-Type: application/json' \ --data '{ "q": "How to use teamcity to set up a project?", "limit": 10, "filters": { "AND": [ { "key": "book", "value": "maths", "negate": false }, { "key": "author", "value": "r.d. sharma", "negate": false } ] } }' ``` ---------------------------------------- TITLE: Composing Advanced Filters for Supermemory API Search - JSON DESCRIPTION: This JSON snippet demonstrates how to construct complex filter conditions for Supermemory API search queries using `AND`, `OR`, and `numeric` operators. It shows filtering by timestamp, user group, and either team name or organization name, allowing for precise control over search results in multi-user environments. SOURCE: https://github.com/supermemoryai/supermemory/blob/main/apps/docs/essentials/metadata-filtering.mdx#_snippet_0 LANGUAGE: json CODE: ``` { "AND": [ { "filterType": "numeric", "key": "timestamp", "value": "1742745777", "negate": false, "numericOperator": ">" }, { "key": "group", "value": "jira_users", "negate": false }, { "OR": [ { "key": "team_name", "value": "engineering", "negate": false }, { "key": "org_name", "value": "supermemory", "negate": false } ] } ] } ``` - Initial Deployment
95d95a7 verified
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Memories</title>
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.js"></script>
<style>
.memory-card {
transition: all 0.3s ease;
border: 1px solid #e5e7eb;
}
.memory-card:hover {
transform: translateY(-2px);
box-shadow: 0 10px 25px rgba(0, 0, 0, 0.1);
}
.loading-shimmer {
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
background-size: 200% 100%;
animation: shimmer 1.5s infinite;
}
@keyframes shimmer {
0% { background-position: 200% 0; }
100% { background-position: -200% 0; }
}
</style>
</head>
<body class="bg-gradient-to-br from-slate-50 to-blue-50 min-h-screen">
<div class="max-w-6xl mx-auto px-4 py-8">
<!-- Header -->
<header class="text-center mb-12">
<h1 class="text-5xl font-bold text-gray-800 mb-4">
<i data-lucide="brain" class="inline-block mr-3 text-blue-600"></i>
My Memories
</h1>
<p class="text-gray-600 text-lg">Capture and organize your thoughts with AI-powered memory management</p>
</header>
<div class="grid lg:grid-cols-3 gap-8">
<!-- Add Memory Section -->
<div class="lg:col-span-1">
<div class="bg-white rounded-xl shadow-lg p-6">
<h2 class="text-2xl font-semibold text-gray-800 mb-4 flex items-center">
<i data-lucide="plus-circle" class="mr-2 text-green-500"></i>
Add New Memory
</h2>
<div class="space-y-4">
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Content</label>
<textarea
id="content"
rows="4"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all"
placeholder="Share your thoughts, ideas, or memories..."
></textarea>
<p class="text-xs text-gray-500 mt-1">Supports up to 5000 characters</p>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Tag</label>
<input
type="text"
id="memoryTag"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500"
placeholder="e.g., work, personal, idea"
>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 mb-2">Source</label>
<input
type="text"
id="memorySource"
class="w-full px-3 py-2 border border-gray-300 rounded-lg focus:ring-2 focus:ring-blue-500"
placeholder="e.g., book, article, thought"
>
</div>
<button
onclick="addMemory()"
class="w-full bg-blue-600 hover:bg-blue-700 text-white font-semibold py-3 px-4 rounded-lg transition-all duration-200 flex items-center justify-center"
>
<i data-lucide="save" class="mr-2"></i>
Add Memory
</button>
<div id="addStatus" class="text-sm"></div>
</div>
</div>
<!-- Advanced Controls -->
<div class="bg-white rounded-xl shadow-lg p-6 mt-6">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center">
<i data-lucide="sliders" class="mr-2 text-purple-500"></i>
Advanced
</h3>
<div class="space-y-3">
<button onclick="groupMemories()" class="w-full bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-2 px-4 rounded-lg">
Group Memories
</button>
<button onclick="exportMemories()" class="w-full bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded-lg">
Export Memories
</button>
<button onclick="importMemories()" class="w-full bg-orange-600 hover:bg-orange-700 text-white font-medium py-2 px-4 rounded-lg">
Import Memories
</button>
</div>
</div>
<!-- API Key Section -->
<div class="bg-white rounded-xl shadow-lg p-6 mt-6">
<h3 class="text-lg font-semibold text-gray-800 mb-3 flex items-center">
<i data-lucide="key" class="mr-2 text-purple-500"></i>
Configuration
</h3>
<button
onclick="updateAPIKey()"
class="w-full bg-gray-600 hover:bg-gray-700 text-white font-medium py-2 px-4 rounded-lg transition-colors"
>
Update API Key
</button>
</div>
</div>
<!-- Memories List Section -->
<div class="lg:col-span-2">
<div class="bg-white rounded-xl shadow-lg p-6">
<div class="flex justify-between items-center mb-6">
<h2 class="text-2xl font-semibold text-gray-800 flex items-center">
<i data-lucide="list" class="mr-2 text-indigo-500"></i>
My Memories
</h2>
<button
onclick="listMemories()"
class="bg-indigo-600 hover:bg-indigo-700 text-white font-medium py-2 px-4 rounded-lg transition-all duration-200 flex items-center"
>
<i data-lucide="refresh-cw" class="mr-2"></i>
Refresh
</button>
</div>
<!-- Search and Filter -->
<div class="mb-4 space-y-3">
<div class="flex gap-2">
<input
type="text"
id="searchQuery"
placeholder="Search memories..."
class="flex-1 px-3 py-2 border border-gray-300 rounded-lg"
onkeypress="if(event.key === 'Enter') searchMemories()"
>
<button onclick="searchMemories()" class="px-4 py-2 bg-blue-600 text-white rounded-lg">
<i data-lucide="search" class="h-4 w-4"></i>
</button>
</div>
<div class="flex gap-2 items-center">
<label class="text-sm text-gray-600">Group by:</label>
<select id="groupBySelect" class="px-3 py-1 border border-gray-300 rounded">
<option value="date">Date</option>
<option value="week">Week</option>
<option value="month">Month</option>
<option value="tag">Tag</option>
</select>
</div>
</div>
<div class="space-y-4">
<div id="memoriesList"></div>
</div>
<div id="listStatus" class="text-sm mt-4"></div>
</div>
</div>
</div>
</div>
<!-- Modal for API Key -->
<div id="apiKeyModal" class="fixed inset-0 bg-black bg-opacity-50 hidden flex items-center justify-center z-50">
<div class="bg-white rounded-xl p-6 max-w-md w-full mx-4">
<h3 class="text-xl font-semibold mb-4">Enter SuperMemory API Key</h3>
<input
type="password"
id="apiKeyInput"
class="w-full px-3 py-2 border border-gray-300 rounded-lg mb-4"
placeholder="Your API key..."
>
<div class="flex gap-2">
<button onclick="saveAPIKey()" class="flex-1 bg-blue-600 hover:bg-blue-700 text-white py-2 rounded">Save</button>
<button onclick="closeModal()" class="flex-1 bg-gray-300 hover:bg-gray-400 text-gray-800 py-2 rounded">Cancel</button>
</div>
</div>
</div>
<!-- Edit Memory Modal -->
<div id="editModal" class="fixed inset-0 bg-black bg-opacity-50 hidden flex items-center justify-center z-50">
<div class="bg-white rounded-xl p-6 max-w-2xl w-full mx-4">
<h3 class="text-xl font-semibold mb-4">Edit Memory</h3>
<textarea
id="editContent"
rows="6"
class="w-full px-3 py-2 border border-gray-300 rounded-lg mb-4"
></textarea>
<input type="hidden" id="editId">
<div class="flex gap-2">
<button onclick="saveEdit()" class="flex-1 bg-blue-600 hover:bg-blue-700 text-white py-2 rounded">Save</button>
<button onclick="closeEditModal()" class="flex-1 bg-gray-300 hover:bg-gray-400 text-gray-800 py-2 rounded">Cancel</button>
</div>
</div>
</div>
<script>
// Configuration
const CONFIG = {
API_BASE: 'https://v2.api.supermemory.ai',
CORS_PROXY: 'https://cors.trigox.workers.dev?url=',
get BASE_URL() {
return `${this.CORS_PROXY}${encodeURIComponent(this.API_BASE)}`;
}
};
// Global state
let currentMemories = [];
let currentFilters = {};
let currentPage = 1;
const ITEMS_PER_PAGE = 20;
// Initialize Lucide icons
lucide.createIcons();
// CRUD Operations Implementation
class MemoryManager {
constructor() {
this.apiKey = localStorage.getItem('sm_api_key');
}
async createMemory(content, metadata = {}) {
if (!this.apiKey) throw new Error('API key required');
const response = await fetch(`${CONFIG.CORS_PROXY}${encodeURIComponent(CONFIG.API_BASE)}/add`, {
method: 'POST',
headers: {
'x-api-key': this.apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({ content, metadata })
});
return response.json();
}
async readMemory(id) {
if (!this.apiKey) throw new Error('API key required');
const response = await fetch(`${CONFIG.CORS_PROXY}${encodeURIComponent(CONFIG.API_BASE)}/memories/${id}`, {
headers: { 'x-api-key': this.apiKey }
});
return response.json();
}
async updateMemory(id, content, metadata = {}) {
if (!this.apiKey) throw new Error('API key required');
const response = await fetch(`${CONFIG.CORS_PROXY}${encodeURIComponent(CONFIG.API_BASE)}/memories/${id}`, {
method: 'PUT',
headers: {
'x-api-key': this.apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({ content, metadata })
});
return response.json();
}
async deleteMemory(id) {
if (!this.apiKey) throw new Error('API key required');
const response = await fetch(`${CONFIG.CORS_PROXY}${encodeURIComponent(CONFIG.API_BASE)}/memories/${id}`, {
method: 'DELETE',
headers: { 'x-api-key': this.apiKey }
});
return response.json();
}
async listMemories(limit = 20, offset = 0) {
if (!this.apiKey) throw new Error('API key required');
const response = await fetch(`${CONFIG.CORS_PROXY}${encodeURIComponent(CONFIG.API_BASE)}/memories/list`, {
method: 'POST',
headers: {
'x-api-key': this.apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({ limit, offset })
});
const data = await response.json();
return data.memories || [];
}
async searchMemories(query, filters = {}, limit = 10) {
if (!this.apiKey) throw new Error('API key required');
const response = await fetch(`${CONFIG.CORS_PROXY}${encodeURIComponent(CONFIG.API_BASE)}/search`, {
method: 'POST',
headers: {
'x-api-key': this.apiKey,
'Content-Type': 'application/json'
},
body: JSON.stringify({ q: query, limit, filters })
});
const data = await response.json();
return data.results || [];
}
async groupMemories(groupBy = 'date') {
if (!currentMemories.length) return {};
const groups = {};
currentMemories.forEach(memory => {
let key;
switch(groupBy) {
case 'date':
key = new Date(memory.createdAt).toDateString();
break;
case 'week':
const weekStart = new Date(memory.createdAt);
weekStart.setDate(weekStart.getDate() - weekStart.getDay());
key = weekStart.toDateString();
break;
case 'month':
key = new Date(memory.createdAt).toLocaleDateString('en-US', { year: 'numeric', month: 'long' });
break;
case 'tag':
key = memory.metadata?.tag || 'untagged';
break;
default:
key = 'ungrouped';
}
if (!groups[key]) groups[key] = [];
groups[key].push(memory);
});
return groups;
}
async getRelatedMemories(memoryId) {
const memory = await this.readMemory(memoryId);
if (!memory?.content) return [];
const related = await this.searchMemories(memory.content, {}, 10);
return related.filter(m => m.id !== memoryId);
}
async bulkDelete(memoryIds) {
const results = await Promise.all(
memoryIds.map(id => this.deleteMemory(id).catch(e => ({ error: e.message, id })))
);
return results;
}
async exportMemories(format = 'json') {
const memories = await this.listMemories(1000);
switch(format) {
case 'json':
return JSON.stringify(memories, null, 2);
case 'csv':
const csv = memories.map(m =>
`"${m.id}","${m.content.replace(/"/g, '""')}","${m.createdAt}"`
).join('\n');
return 'id,content,createdAt\n' + csv;
default:
return memories;
}
}
async importMemories(memories) {
const results = await Promise.all(
memories.map(memory => this.createMemory(memory.content, memory.metadata))
);
return results;
}
async getStats() {
const memories = await this.listMemories(1000);
return {
total: memories.length,
oldest: memories[memories.length - 1],
newest: memories[0],
averageLength: memories.reduce((sum, m) => sum + (m.content?.length || 0), 0) / memories.length
};
}
}
const memoryManager = new MemoryManager();
// Main functions
async function addMemory() {
const content = document.getElementById('content').value;
const metadata = collectMetadata();
const statusDiv = document.getElementById('addStatus');
if (!content.trim()) {
showStatus(statusDiv, 'Please enter some content', 'error');
return;
}
try {
const button = event.target;
button.disabled = true;
button.innerHTML = '<i data-lucide="loader" class="mr-2 animate-spin"></i>Adding...';
await memoryManager.createMemory(content, metadata);
showStatus(statusDiv, 'Memory added successfully!', 'success');
document.getElementById('content').value = '';
listMemories();
} catch (error) {
console.error('Error adding memory:', error);
showStatus(statusDiv, `Error: ${error.message}`, 'error');
} finally {
const button = event.target;
button.disabled = false;
button.innerHTML = '<i data-lucide="save" class="mr-2"></i>Add Memory';
lucide.createIcons();
}
}
async function listMemories(page = 1) {
const listDiv = document.getElementById('memoriesList');
const apiKey = localStorage.getItem('sm_api_key');
if (!apiKey) {
updateAPIKey();
return;
}
showLoading(listDiv);
try {
memoryManager.apiKey = apiKey;
const offset = (page - 1) * ITEMS_PER_PAGE;
const memories = await memoryManager.listMemories(ITEMS_PER_PAGE, offset);
currentMemories = memories;
displayMemories(memories);
currentPage = page;
} catch (error) {
console.error('Error loading memories:', error);
listDiv.innerHTML = `<p class="text-red-500">Error: ${error.message}</p>`;
}
}
async function searchMemories() {
const query = document.getElementById('searchQuery').value;
const listDiv = document.getElementById('memoriesList');
if (!query.trim()) {
listMemories();
return;
}
showLoading(listDiv);
try {
const results = await memoryManager.searchMemories(query, currentFilters);
currentMemories = results;
displayMemories(results);
} catch (error) {
console.error('Error searching:', error);
listDiv.innerHTML = `<p class="text-red-500">Search error: ${error.message}</p>`;
}
}
async function groupMemories() {
const groupBy = document.getElementById('groupBySelect').value;
const groups = await memoryManager.groupMemories(groupBy);
displayGroupedMemories(groups);
}
async function deleteMemory(id) {
if (!confirm('Are you sure you want to delete this memory?')) return;
try {
await memoryManager.deleteMemory(id);
showStatus(document.getElementById('listStatus'), 'Memory deleted', 'success');
listMemories();
} catch (error) {
showStatus(document.getElementById('listStatus'), `Delete error: ${error.message}`, 'error');
}
}
async function editMemory(id) {
const memory = await memoryManager.readMemory(id);
if (!memory) return;
document.getElementById('editModal').classList.remove('hidden');
document.getElementById('editContent').value = memory.content || '';
document.getElementById('editId').value = id;
}
async function saveEdit() {
const id = document.getElementById('editId').value;
const content = document.getElementById('editContent').value;
try {
await memoryManager.updateMemory(id, content);
closeEditModal();
listMemories();
} catch (error) {
alert(`Edit error: ${error.message}`);
}
}
function closeEditModal() {
document.getElementById('editModal').classList.add('hidden');
}
function displayMemories(memories) {
const listDiv = document.getElementById('memoriesList');
if (memories.length === 0) {
listDiv.innerHTML = `
<div class="text-center py-8">
<i data-lucide="inbox" class="mx-auto h-12 w-12 text-gray-400 mb-3"></i>
<p class="text-gray-500">No memories found</p>
<p class="text-sm text-gray-400 mt-1">Try adjusting your search or filters</p>
</div>
`;
lucide.createIcons();
return;
}
listDiv.innerHTML = `
<div class="space-y-4">
${memories.map(memory => `
<div class="memory-card bg-white rounded-lg p-5">
<div class="flex justify-between items-start mb-3">
<div>
<span class="text-xs text-gray-500">${new Date(memory.createdAt).toLocaleString()}</span>
${memory.metadata?.tag ? `<span class="ml-2 px-2 py-1 bg-blue-100 text-blue-800 text-xs rounded">${memory.metadata.tag}</span>` : ''}
</div>
<div class="flex gap-2">
<button onclick="editMemory('${memory.id}')" class="text-blue-600 hover:text-blue-800">
<i data-lucide="edit-3" class="h-4 w-4"></i>
</button>
<button onclick="deleteMemory('${memory.id}')" class="text-red-600 hover:text-red-800">
<i data-lucide="trash-2" class="h-4 w-4"></i>
</button>
</div>
</div>
<p class="text-gray-800 leading-relaxed">${memory.content || 'No content'}</p>
${memory.metadata?.source ? `<p class="text-xs text-gray-500 mt-2">Source: ${memory.metadata.source}</p>` : ''}
</div>
`).join('')}
</div>
<div class="mt-6 flex justify-between items-center">
<button onclick="listMemories(${currentPage - 1})" ${currentPage <= 1 ? 'disabled' : ''}
class="px-4 py-2 bg-gray-200 rounded disabled:opacity-50">
Previous
</button>
<span class="text-gray-600">Page ${currentPage}</span>
<button onclick="listMemories(${currentPage + 1})"
class="px-4 py-2 bg-gray-200 rounded">
Next
</button>
</div>
`;
lucide.createIcons();
}
function displayGroupedMemories(groups) {
const listDiv = document.getElementById('memoriesList');
let html = '<div class="space-y-6">';
Object.entries(groups).forEach(([group, memories]) => {
html += `
<div class="border rounded-lg p-4">
<h4 class="font-semibold text-lg mb-3">${group} (${memories.length})</h4>
</div>
`;
});
html += '</div>';
listDiv.innerHTML = html;
}
function collectMetadata() {
const metadata = {};
const tag = document.getElementById('memoryTag').value;
const source = document.getElementById('memorySource').value;
if (tag) metadata.tag = tag;
if (source) metadata.source = source;
return metadata;
}
function showStatus(element, message, type) {
element.innerHTML = `<p class="${type === 'error' ? 'text-red-600' : 'text-green-600'}">${message}</p>`;
setTimeout(() => element.innerHTML = '', 3000);
}
function showLoading(element) {
element.innerHTML = `
<div class="space-y-3">
${Array(3).fill(0).map(() => `
<div class="memory-card bg-white rounded-lg p-5">
<div class="loading-shimmer h-4 w-1/3 rounded mb-3"></div>
<div class="loading-shimmer h-4 w-full rounded mb-2"></div>
<div class="loading-shimmer h-4 w-3/4 rounded"></div>
</div>
`).join('')}
</div>
`;
}
function updateAPIKey() {
document.getElementById('apiKeyModal').classList.remove('hidden');
document.getElementById('apiKeyInput').value = localStorage.getItem('sm_api_key') || '';
}
function saveAPIKey() {
const key = document.getElementById('apiKeyInput').value.trim();
if (key) {
localStorage.setItem('sm_api_key', key);
memoryManager.apiKey = key;
closeModal();
listMemories();
}
}
function closeModal() {
document.getElementById('apiKeyModal').classList.add('hidden');
}
async function exportMemories() {
try {
const data = await memoryManager.exportMemories('json');
const blob = new Blob([data], { type: 'application/json' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'memories.json';
a.click();
} catch (error) {
alert(`Export error: ${error.message}`);
}
}
async function importMemories() {
const input = document.createElement('input');
input.type = 'file';
input.accept = '.json';
input.onchange = async (e) => {
const file = e.target.files[0];
if (!file) return;
try {
const text = await file.text();
const memories = JSON.parse(text);
await memoryManager.importMemories(memories);
listMemories();
} catch (error) {
alert(`Import error: ${error.message}`);
}
};
input.click();
}
// Initialize
document.addEventListener('DOMContentLoaded', () => {
if (!localStorage.getItem('sm_api_key')) {
setTimeout(updateAPIKey, 500);
} else {
memoryManager.apiKey = localStorage.getItem('sm_api_key');
listMemories();
}
});
</script>
<p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://enzostvs-deepsite.hf.space/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://enzostvs-deepsite.hf.space" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://enzostvs-deepsite.hf.space?remix=samihalawa/supermemory" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body>
</html>