Unvios is an AI-powered personal memory assistant built with Next.js 16. It stores, retrieves, and intelligently recalls user memories using LLM integration and vector embeddings, creating a personalized knowledge base that grows with you.
- AI Memory System: Store personal facts, preferences, and experiences with automatic semantic search
- Vector Embeddings: Optional pgvector integration for intelligent memory retrieval based on context
- LLM Chat Interface: Conversational AI that references your stored memories in responses
- Memory Management: Full CRUD operations with tagging, editing, and duplicate detection
- Activity Logging: Track user interactions and system events
- Cookie-based JWT authentication with email/password sign-up
- Stripe integration for subscription management
- Protected dashboard routes with role-based access
- Interactive onboarding tour for new users
- Real-time chat interface with memory annotations
- Dashboard with memory browser and analytics
- Marketing pages (features, pricing, about, blog, research)
- Framework: Next.js 16 (canary) with App Router
- Database: PostgreSQL with pgvector
- ORM: Drizzle
- LLM Integration: OpenAI-compatible API endpoints
- Embeddings: Configurable embedding service for vector search
- Payments: Stripe
- UI Library: shadcn/ui
- Styling: Tailwind CSS
- Node.js 18+ and pnpm
- PostgreSQL database with pgvector extension (or use
USE_LOCAL_MEMORIES=1for development) - Optional: OpenAI API key or compatible LLM endpoint
git clone https://github.com/olserra/unvios
cd unvios
pnpm installUse the included setup script to create your .env file:
pnpm db:setupOr manually create a .env file with the following variables:
# Database
POSTGRES_URL=postgresql://user:password@localhost:5432/unvios
# Auth (auto-generated in dev if not provided)
AUTH_SECRET=your-secret-key-here
# Base URL
BASE_URL=http://localhost:3000# LLM API (OpenAI or compatible endpoint)
LLM_API_URL=https://api.openai.com/v1
LLM_API_KEY=your-llm-api-key
# Embedding API (for vector search)
EMBEDDING_API_URL=https://api.openai.com/v1
EMBEDDING_API_KEY=your-embedding-api-key
# Stripe (for payments)
STRIPE_SECRET_KEY=your-stripe-secret-key
STRIPE_WEBHOOK_SECRET=your-webhook-secret
# Dev mode (skip DB, use local JSON file)
USE_LOCAL_MEMORIES=1Run migrations to create the database schema:
pnpm db:migrateSeed the database with a default user:
pnpm db:seedThis creates a test user:
- Email:
[email protected] - Password:
admin123
pnpm devOpen http://localhost:3000 to see the app.
pnpm dev- Start development server with Turbopackpnpm build- Build for productionpnpm start- Start production serverpnpm lint- Run ESLintpnpm db:setup- Initialize database and create.envpnpm db:migrate- Run Drizzle migrationspnpm db:seed- Seed database with test datapnpm db:reset-seed- Reset and re-seed databasepnpm test- Run Vitest unit testspnpm test:e2e- Run Playwright e2e tests
The memory system uses a special annotation format in LLM responses:
[MEMORY: User prefers dark mode | preferences, ui]
[MEMORY: Lives in San Francisco | location, personal]
The chat API (app/api/llm/chat/route.ts) automatically:
- Parses memory annotations from LLM responses
- Checks for duplicates using vector similarity
- Saves new memories with optional embeddings
- Retrieves relevant memories for context in future conversations
When embeddings are enabled:
- User message is embedded
- Nearest memories are retrieved using cosine distance (
<=>) - Memories are included in LLM prompt for context
- New memories are embedded and stored with vector column
Set USE_LOCAL_MEMORIES=1 to use lib/devMemories.ts instead of the database. Useful for:
- Quick prototyping without DB setup
- Testing memory logic in isolation
- Offline development
app/
├── (dashboard)/ # Protected dashboard pages
│ ├── chat/ # AI chat interface
│ └── dashboard/ # Memory browser, settings
├── (login)/ # Auth pages (sign-in, sign-up)
├── api/ # Next.js API routes
│ ├── llm/chat/ # LLM chat endpoint with memory integration
│ ├── memories/ # Memory CRUD + embeddings
│ ├── auth/ # Authentication endpoints
│ └── stripe/ # Payment webhooks
└── [marketing pages] # Public pages (about, pricing, etc.)
lib/
├── auth/ # Session management, JWT handling
├── db/ # Drizzle schema, queries, migrations
├── memoryParser.ts # Memory annotation parsing logic
└── devMemories.ts # Local development fallback store
components/
├── dashboard/ # Chat, memory panels, onboarding
└── ui/ # shadcn/ui primitives
scripts/
├── backfill-embeddings.ts # Generate embeddings for existing memories
├── dev-seed.ts # Seed development data
└── reset-and-seed.ts # Full reset workflow
pnpm testTests are in tests/ and use Vitest. Current coverage includes:
- Memory parser logic (
tests/memoryParser.test.ts) - Utility functions (
tests/utils.test.ts)
pnpm test:e2ePlaywright tests verify critical user flows end-to-end.
Set all required variables in your production environment:
POSTGRES_URL=your-production-db-url
AUTH_SECRET=$(openssl rand -base64 32)
BASE_URL=https://yourdomain.com
LLM_API_URL=your-llm-endpoint
LLM_API_KEY=your-llm-key
EMBEDDING_API_URL=your-embedding-endpoint
EMBEDDING_API_KEY=your-embedding-key
STRIPE_SECRET_KEY=your-stripe-secret-key
STRIPE_WEBHOOK_SECRET=your-webhook-secretEnsure your production database has the pgvector extension:
CREATE EXTENSION IF NOT EXISTS vector;Run migrations:
pnpm db:migrate- Create a production webhook in Stripe Dashboard
- Point it to
https://yourdomain.com/api/stripe/webhook - Select events:
checkout.session.completed,customer.subscription.updated, etc. - Copy the webhook secret to
STRIPE_WEBHOOK_SECRET
Deploy to Vercel or your preferred platform:
vercel --prodSee docs/adr/ for detailed Architecture Decision Records covering:
- CI/CD workflows and caching strategies
- Security audit and fixes
- Cookie consent implementation
- Onboarding tour implementation
- Test infrastructure
When making significant architectural changes, please create an ADR in docs/adr/ using the template at docs/adr/adr-template.md.
See SECURITY_FIXES_APPLIED.md for recent security improvements.
Report security issues to: [security contact info]
See LICENSE file for details.