Changelog

Product evolution timeline

### Summary Complete SDK release for both Python and TypeScript, enabling programmatic access to the Elephantasm LTAM framework. Both SDKs published to package registries with full test suites, examples, and documentation. --- ### Python SDK (`elephantasm-py`) **Installation**: `pip install elephantasm` **PyPI**: https://pypi.org/project/elephantasm/ **License**: Apache 2.0 **Core API**: - `inject(anima_id?, query?, preset?)` - Retrieve MemoryPack for LLM context - `extract(event_type, content, ...)` - Capture events for memory synthesis - `create_anima(name, description?, meta?)` - Create new agent entity **Features**: - Context manager support for explicit client lifecycle - Type-safe Pydantic models matching backend schemas - Exception hierarchy with status code mapping (401, 404, 422, 429, 5xx) - 28 tests passing --- ### TypeScript SDK (`@elephantasm/client`) **Installation**: `npm install @elephantasm/client` **npm**: https://www.npmjs.com/package/@elephantasm/client **License**: Apache 2.0 **Core API**: - `client.inject(options?)` - Get MemoryPack with helper methods - `client.extract(eventType, content, options?)` - Capture events - `client.createAnima(name, options?)` - Create new anima **MemoryPack Helpers**: - `pack.asPrompt()` - Format as LLM system prompt - `pack.sessionMemories`, `pack.knowledge`, `pack.identity` - Layer accessors **Features**: - OIDC trusted publishing (no token rotation) - 33 vitest tests passing - Examples: basic usage, Vercel AI SDK, multi-anima pattern --- ### SDK Documentation Page (`/sdk`) - Language toggle (Python/TypeScript) with dynamic content - Installation, quick start, configuration sections - Copy-to-clipboard code blocks - Terminal aesthetic matching site design --- ### RLS Security Hardening Enabled Row-Level Security for 4 remaining tables: - `identities` - Via anima ownership - `identity_audit_log` - Via identity chain - `io_configs` - Via anima ownership - `memory_packs` - Via anima ownership Fixed background task RLS context propagation for pack persistence.
### Summary Complete API key authentication system enabling programmatic SDK access alongside existing JWT auth. Users can create, manage, and revoke API keys via Settings > API. Also includes critical Dreamer service fixes. --- ### API Key System (6-Phase Implementation) **Database Layer**: - New `api_keys` table with bcrypt hashing (never plaintext) - Key format: `sk_live_<32-hex>` with display prefix - Usage tracking: `last_used_at`, `request_count` - Optional expiration support - RLS policy for multi-tenant isolation **Auth Middleware**: Dual authentication flow - both paths return `user_id` for RLS context: ``` Authorization: Bearer <token> | Starts with "sk_live_"? Yes -> API Key Validation No -> JWT/JWKS Validation | user_id -> RLS Context ``` **API Routes** (`/api/api-keys`): - POST `/` - Create key (returns full key once) - GET `/` - List keys (prefix only) - POST `/{id}/revoke` - Soft disable - DELETE `/{id}` - Hard delete **Frontend Settings UI** (`/settings/api`): - Key list with name, prefix, request count, last used - Create form with name/description - New key banner with copy button + warning - Revoke/delete with confirmation modals --- ### Dreamer Fixes **Background Task RLS Context**: - Manual dream triggers now properly set RLS context - Fixed error handler to use fresh RLS-aware session after rollback **Cancel Stuck Sessions**: - `POST /api/dreams/sessions/{id}/cancel` endpoint - Stale detection UI (>3 min running = amber warning) - Red cancel button for any RUNNING session
### Summary Dreamer Phase 5 frontend with Dream Journal UI. Temporal awareness for session gaps. Native Printify checkout with Stripe payments. Terms of Service and Privacy Policy pages. --- ### Dreamer UI (Phase 5) **Dreams Page** (`/dreams`): - Dream stats sidebar (total, completed, failed, last dream) - Status filter (All, Completed, Running, Failed) - Collapsible session cards with metrics - Action diffs with before/after snapshots - Manual "Trigger Dream" button **Components**: - `DreamSessionCard` - Expandable session with metrics - `DreamActionItem` - Action with diff view - `DreamStatusIndicator` - Dashboard integration --- ### Temporal Awareness Layer Bridges session gaps when user returns after absence: - Injects context like "Your last communication was 2 days ago about project deadline concerns." - Triggers when session_memories empty - Efficient LEFT JOIN query for last event detection --- ### Memory Pack Enhancements - **Pack Detail Modals**: Click any pack to view full details (3-tab: Overview, Context, Config) - **Identity Name Injection**: Anima name now included in identity prose - **Synthesis Sidebar**: Dedicated right panel on Memory page with always-expanded config --- ### Native Printify Checkout Full e-commerce flow replacing storefront redirect: - Cart system with localStorage persistence - 2-step checkout (shipping -> payment) - Stripe Elements integration with dark theme - Webhook handler for payment -> Printify fulfillment - Image lightbox with keyboard navigation --- ### Legal Pages - `/terms` - 21-section Terms of Service - `/privacy` - 14-section Privacy Policy - GDPR/CCPA user rights coverage - AI training opt-out clause - Third-party AI provider disclosures
### Summary Complete Dreamer memory curation system (Phases 1-4). Sandbox pack persistence with fire-and-forget background saves. Full Settings area with profile, usage, billing, team, and API sections. --- ### Dreamer Service (Phases 1-4) The Dreamer is Elephantasm's memory curation system - analogous to human sleep/dreaming. **Phase 1 - Database Foundation**: - `dream_sessions` table for cycle records - `dream_actions` table for audit trail - Enums: DreamTriggerType, DreamStatus, DreamActionType, DreamPhase - RLS policies via Anima ownership chain **Phase 2 - Core Workflow**: - `DreamerOperations` domain layer with full audit trail - Light Sleep (algorithmic): decay updates, state transitions, pgVector merge detection - Config snapshot stored per session for reproducibility **Phase 3 - Deep Sleep (LLM-Powered)**: - Identity-aware prompts for merge/review decisions - Operations: MERGE, SPLIT, UPDATE, ARCHIVE, DELETE - Embedding regeneration after mutations - Non-fatal error handling (individual failures don't abort) **Phase 4 - Integration**: - `DreamerScheduler` with 12-hour periodic dreams - REST API endpoints for manual trigger and session queries - Background execution via FastAPI BackgroundTasks --- ### Sandbox Pack Persistence Fire-and-forget persistence for injected memory packs: - `persist=true` query parameter on compile endpoint - Background thread saves pack while response returns immediately - 100 pack retention limit per anima with auto-cleanup - Payloads page STREAM tab now shows Sandbox packs --- ### Dual Ingest/Inject Toggles Replaced single Elephantasm toggle with independent controls: - **Ingest**: Capture MESSAGE_IN/MESSAGE_OUT events (cyan) - **Inject**: Compile & inject Memory Pack context (orange) 4 operational modes: Full LTAM, Logging, Read-only, Vanilla --- ### Settings Area (`/settings/*`) 5-section sidebar navigation: - **Profile**: Edit name, username, phone; email read-only - **Usage**: Real counts with progress bars + quotas - **Billing**: Plan cards (placeholder) - **Team**: Current user as Owner (placeholder) - **API**: SDK snippets, API keys table (placeholder -> now functional in 0.5.0)
### Summary New Identity page with RPG-style character builder UI. Critical Knowledge RLS fix. Complete Payloads backend infrastructure for I/O observability. --- ### Identity Page (`/identity`) RPG-style character builder inspired by Mass Effect, Disco Elysium, and D&D character sheets. **Interactive Components**: - `PersonalityGrid` - 4x4 MBTI selector with hover tooltips - `PrinciplesPanel` - RPG trait cards (Truth, Agency, Craft, Speed, Kindness...), reorderable, star for non-negotiables - `BeingPanel` - Essence + Nature text inputs - `PurposePanel` - Primary objective + secondary list - `PhilosophyPanel` - 2D epistemology compass + Ethics radios + Aesthetics chips - `ArcPanel` - Horizontal timeline with editable phase nodes - `RelationalPanel` - Owner/Creator + custom relationships **Template Picker**: Coding Assistant preset or Blank Canvas --- ### Knowledge Routes RLS Fix (Critical) Knowledge API routes were using `get_db` instead of `get_db_with_rls`, causing RLS policies to filter all rows and return empty results. **Impact**: Knowledge now displays correctly in `/knowledge` page and Sandbox FlowchartBox. --- ### Payloads Backend Infrastructure **IOConfig Table**: - Per-anima I/O configuration with JSONB columns - `read_settings`: Event capture config (types, timeouts, importance rules) - `write_settings`: Pack compilation config (presets, weights, limits) - 5 API endpoints for CRUD + reset **Memory Pack Persistence**: - Persisted packs for observability and provenance - Denormalized layer counts and token usage - Retention enforcement (default 100 packs) - 5 API endpoints for list, latest, stats, get, delete --- ### Sandbox Enhancements - FlowchartBox 4-tab system (Events, Storage, Packs, Flow) - Responsive event grid with `+X more` overflow indicator - Session/All view mode toggle - Provider selector as dropdown (GPT, Claude, Gemini Soon, Grok Soon)
### Summary Core component for assembling deterministic memory packs for LLM context injection. Implements 4-layer retrieval, 5-factor scoring algorithms, token budget enforcement, and two preset configurations. --- ### 4-Layer Retrieval System 1. **Identity Layer** - Static fetch (always included) 2. **Session Layer** - Time-windowed (last N hours), recency-scored 3. **Knowledge Layer** - Semantic search, confidence + similarity scoring 4. **Long-term Layer** - Semantic + full 5-factor scoring --- ### 5-Factor Scoring Algorithm | Factor | Default Weight | Rationale | |--------|----------------|----------| | importance | 0.25 | Inherent memory significance | | similarity | 0.25 | Query relevance (semantic) | | recency | 0.20 | Temporal freshness | | confidence | 0.15 | Accuracy certainty | | decay | 0.15 | Access-adjusted forgetting | **Scoring Functions**: - `compute_recency_score()` - Exponential decay with configurable half-life - `compute_decay_score()` - Forgetting curve with spaced repetition boost - `compute_combined_score()` - 5-factor weighted formula - `compute_knowledge_score()` - Simplified for stable knowledge --- ### Presets **Conversational** (~50ms): - Deterministic, recency-favored weights - 4-hour session window - 5 session / 3 knowledge / 3 long-term memories **Self-Determined** (+500-1000ms): - LLM-adaptive, agent chooses retrieval strategy per query - Higher token budgets and memory limits --- ### API Endpoints - `POST /api/packs/compile` - Full custom compilation - `POST /api/packs/compile/preview` - Lightweight preview - `POST /api/packs/compile/{preset_name}` - Preset-based compilation --- ### Token Budget Enforcement 25% session / 35% knowledge / 40% long-term distribution `MemoryPack.to_prompt_context()` outputs Markdown ready for LLM injection.
### Summary Memory Constellation visualization with prismatic aesthetics. Dedicated Knowledge and Memories pages. LangGraph workflow fixes for RLS bypass. LLM client resilience with automatic retry. --- ### Memory Constellation Visualization **Visual Metaphor**: "Prism of white light refracted into living memory" **Features**: - Bounded layout in concentric rings (age-based positioning) - Prismatic rainbow color distribution (0-280 hue HSL) - Three-layer nodes: outer glow + core sphere + inner sparkle - Smooth circular drift animation (4-6s cycles) - Hover preview with summary/importance/state - Click to open detail modal with full metadata - Synthesis flash animation for new memories **Semantic Encoding**: - Brightness -> importance - Position -> recency (concentric rings) - Size -> source event richness --- ### Knowledge Page (`/knowledge`) "Jedi Archives" digital library layout: - 5 collapsible sections by type (FACT, CONCEPT, METHOD, PRINCIPLE, EXPERIENCE) - Color-coded cards per type - Sidebar filters: Type, Source, Topic - Search bar with real-time filtering - Stats panel with per-type breakdown - Detail modal on click --- ### Memories Page (`/memories`) - Large-scale constellation (up to 24 nodes vs 5 in sandbox) - Advanced filter sidebar: state, time range, importance slider - Memory Stream list view alongside constellation - Responsive mobile controls --- ### LangGraph Workflow Fixes **Generic RLS Bypass**: `get_entity_user_id_bypass_rls()` helper for scheduler context **Public Schema Checkpoints**: Both Memory and Knowledge synthesis workflows operational --- ### LLM Client Resilience Automatic retry logic for transient API failures: - Rate limits, connection errors, timeouts, server overload (529/5xx) - Exponential backoff (1-10s), 3 max attempts via tenacity --- ### Logging Noise Reduction ~97% reduction in log noise: - Suppressed polling endpoints (events, memories, animas, CORS preflight) - httpx and apscheduler INFO logs suppressed
### Summary Complete end-to-end Knowledge Synthesis pipeline using LangGraph. Transforms synthesized Memories into structured Knowledge items (FACT, CONCEPT, METHOD, PRINCIPLE, EXPERIENCE) with full provenance tracking and automated triggers. --- ### Knowledge System (Database + API) **Knowledge Table**: - 5 types: FACT, CONCEPT, METHOD, PRINCIPLE, EXPERIENCE - 2 sources: INTERNAL (synthesized), EXTERNAL (manual) - `topic` and `tags` for organization - `confidence` score (0.0-1.0) - Soft delete with restore support **Knowledge Audit Log**: - Immutable provenance tracking - Actions: CREATE, UPDATE, DELETE, RESTORE - `source_id` links to source Memory **14 API Endpoints**: - CRUD operations - Filter by type, topic, source - Search by content/summary - Stats aggregation - History and provenance queries --- ### LangGraph Workflow **5-Node Pipeline**: 1. **Memory Fetch** - Load source memory with validation 2. **LLM Analysis** - Extract knowledge candidates via Claude/GPT 3. **Deduplication** - Check against existing knowledge 4. **Persistence** - Save new knowledge with audit log 5. **Completion** - Return synthesis results **LLM Prompt Engineering**: - Structured JSON output for consistent parsing - Type classification guidance - Confidence scoring instructions - Topic extraction --- ### Automated Triggers (Phase 7) Fire-and-forget hooks for zero-touch knowledge extraction: - Memory synthesis completion triggers knowledge synthesis - Background task execution (non-blocking) - Error isolation (failures logged, don't block memory workflow) --- ### Multi-Tenant Security **Row-Level Security (RLS)** on all Knowledge tables: - Policies via Anima -> User ownership chain - JWT-based user identification - Scheduler bypass helper for background jobs --- ### pgVector Semantic Search (Foundation) Added `embedding` column (vector 1536) to Memories and Knowledge tables: - OpenAI text-embedding-3-small model - IVFFlat indexes for fast cosine similarity - Auto-generation on synthesis - Semantic search endpoints for natural language queries
### Added **Frontend: Anima Page Nebula Cloud Animation + Edit Modal** (~2 hours) Dynamic particle-based nebula cloud visualization replacing static gradient sphere. **AnimaNebulaCore Component**: - Canvas-based 1000-particle nebula with pixelated aesthetic (`imageRendering: pixelated`) - 4 cycling color palettes (10s intervals): Default (warm grey/amber) -> Cool (blue/cyan) -> Warm (amber/orange) -> Emerald (green) - Smooth RGB interpolation (~2s transitions) via `lerpColor()` helper - Warm palette: 70% grey tones, 30% amber/cyan/emerald lightning traces - Subtle glow effects (shadowBlur: 4, opacity: 0.6) - Breathing animation via sinusoidal life cycles + gravitational drift - Increased size to 420px for better presence **Anima Page Layout Updates**: - Removed rigid box container (borderless floating cloud) - Repositioned cloud ~20% down page (`pt-16 lg:pt-24`) - Anima name moved below cloud as character title - Hover-to-edit: "EDIT" button appears on name hover - Responsive bottom alignment for Memories/Events sections **EditAnimaModal Component**: - New modal for editing anima name/description - Terminal aesthetic matching CreateAnimaModal - Calls `AnimasAPI.updateById()` with auto-refetch --- **Frontend: Sandbox Flowchart Visualization with Animated Event Flow** (~1.5 hours) Real-time data flow visualization showing message-to-event transformation with 90-degree particle animations. **FlowchartBox Component** (new): - Minimalist "Data Flow" panel replacing empty middle box - Events container with live event count - Session-scoped chronological event list (oldest -> newest) - Smooth stagger animations (30ms delay per event) - New event highlights: cyan/green border glow (1s fade) **AnimatedEventFlow Refactor**: - **90-degree curved path**: Horizontal -> vertical curve (Supabase FK-style) - SVG path: `M start L control-horizontal Q end-x control-y, end-x end-y` - Target changed from inspector panel to flowchart Events container - Dynamic end position via `document.getElementById('flowchart-events-container')` - **Particle redesign**: Large bubble -> small glowing orb (12px core) - Glowing particle trail with `pathLength` animation - Speed increased: 1500ms -> 800ms for snappier feel - Color-coded: Green (#22c55e) for user, Cyan (#06b6d4) for AI **Sandbox Page Integration**: - Session filtering: `events.filter(e => e.session_id === sessionId)` - Chronological sorting for flowchart display - Both MESSAGE_IN and MESSAGE_OUT events animate through ### Build Verification - Build successful (2.5s compile, 240 kB sandbox route) - No TypeScript errors - Linter passed (0 errors, 1 pre-existing warning) ---
### Added **LangGraph Memory Synthesis System: Complete End-to-End Automated Workflow** (~10 hours, Phases 0-6) Successfully implemented a production-ready, fully automated memory synthesis system that transforms raw events into structured memories using LLM-powered analysis, with scheduled automation, full provenance tracking, and checkpoint infrastructure. #### System Overview **What We Built:** - 5 workflow nodes orchestrating memory synthesis pipeline - Multi-provider LLM client (Anthropic Claude + OpenAI GPT with automatic retry) - Accumulation scoring algorithm (time + events + tokens) - Full provenance tracking (Memory <-> Event links with bulk operations) - Compiled StateGraph with conditional routing and async PostgreSQL checkpointer - Dedicated PostgreSQL schema (`langgraph`) for checkpoint isolation - Automated scheduler (APScheduler with FastAPI lifespan integration) - Parallel anima processing (10x faster via asyncio.gather) - REST API endpoints for manual triggers and monitoring - 22 passing tests across domain operations, services, and scheduler - Complete state schema (14 fields) with checkpoint support --- #### Key Components **Phase 0-1: Setup & Foundation** - Dependencies: `langgraph`, `langgraph-checkpoint-postgres`, `anthropic`, `openai`, `tenacity`, `apscheduler`, `structlog` - State schema: `MemorySynthesisState` TypedDict (14 fields, JSON-serializable) - Configuration: Environment-driven via Pydantic Settings **Phase 2: Domain Extensions** - `MemoryOperations.get_last_memory_time()` - Baseline timestamp - `EventOperations.count_since()`, `get_since()` - Temporal queries - Database context manager for workflow nodes **Phase 3: Multi-Provider LLM Client** - Abstract `BaseLLMClient` with shared prompt building - Concrete: `AnthropicClient`, `OpenAIClient` - Automatic retry (exponential backoff), robust JSON parsing **Phase 4: Workflow Nodes** 1. **Accumulation Score** - Calculates composite score from time/events/tokens 2. **Threshold Gate** - Routes based on synthesis threshold 3. **Event Collection** - Fetches chronological events 4. **Memory Synthesis** - LLM-powered analysis (async) 5. **Memory Persistence** - Atomic DB write with provenance **Phase 5: Graph Assembly & Checkpoints** - `StateGraph` with 5 nodes + conditional routing - Dedicated `langgraph` schema (separate from `public`) - Async PostgreSQL checkpointer (schema-aware) **Phase 6: Scheduler Integration** - 3-layer architecture: Orchestrator -> Base -> Workflow - APScheduler singleton with graceful shutdown - FastAPI lifespan integration - REST API: `/api/synthesis/trigger`, `/status`, `/start`, `/stop` - Parallel execution: `asyncio.gather()` (10x faster) --- #### Performance Characteristics **Node Execution Times:** - Accumulation Score: ~50ms - Threshold Gate: <1ms - Event Collection: ~100ms - Memory Synthesis: **2-5s** (LLM bottleneck) - Memory Persistence: ~50ms **Total Workflow Latency:** ~3-6 seconds (LLM-dominated) ---
### Added **Backend Production Deployment: Fly.io Single-Region Setup** (https://elephantasm.fly.dev) **Configuration:** - **Region:** Singapore (`sin`), 2 machines, auto-suspend mode (~200ms wake-up) - **Infrastructure:** Multi-stage Docker (87 MB), Python 3.12.6-slim, single worker per machine - **Health checks:** `/api/health` every 30s with DB connectivity verification - **Secrets:** 5 environment variables via `fly secrets set` (DATABASE_URL, MIGRATION_DATABASE_URL, Supabase keys) - **Cost:** ~$11-15/month (30-40% reduction vs Marlin multi-region) **Key Decisions:** - Single region v1 (simpler than Marlin's multi-region, no manual machine pinning) - Suspend mode (not stop) for fast wake-ups vs cold starts - Min 1 machine for zero cold starts - External Supabase PostgreSQL (no migration needed), pgBouncer pooling **Files Created:** - `backend/Dockerfile` (multi-stage build) - `backend/.dockerignore` (build optimization) - `backend/fly.toml` (deployment config) - `backend/app/api/routes/health.py` (enhanced health checks) ---
### Changed **Backend Architecture Refactor: Async-to-Sync Migration (Marlin Hybrid Pattern)** (~2 hours) Migrated entire backend from AsyncSQLAlchemy to sync SQLAlchemy, implementing hybrid async/sync pattern that eliminates prepared statement collisions with pgBouncer while maintaining HTTP concurrency. **Three Phases:** **Phase 1 - Database Layer:** - `create_async_engine` -> `create_engine` (sync) - `AsyncSession` -> `Session` with NullPool (delegates to pgBouncer) - `async def get_db()` -> `def get_db()` (generator pattern) **Phase 2 - Domain Operations:** - Converted 48 methods from `async def` -> `def` (4 files, ~2,020 lines) - Removed ~165 `await` keywords - No business logic changes (purely mechanical) **Phase 3 - API Routes:** - Updated 32 endpoints (removed ~80 `await` when calling domain operations) - **Kept routes as `async def`** for HTTP concurrency (critical!) **Hybrid Pattern:** ```python @router.post("/", response_model=SpiritRead) async def create_spirit( # <- Still async! data: SpiritCreate, db: Session = Depends(get_db) # <- Sync Session ): spirit = SpiritOperations.create(db, data) # <- No await! return SpiritRead.model_validate(spirit) ``` **Architecture Evolution:** ``` Before: Routes (async) -> await -> Domain (async) -> await -> AsyncSession After: Routes (async) -> Domain (sync via thread pool) -> Session ``` **Benefits:** - Fixes prepared statement collisions with pgBouncer - Removes async overhead from business logic - Simpler debugging (no coroutine frames) - Maintains HTTP concurrency ---
### Added **Spirit View Dashboard: RPG Character Screen Paradigm with Terminal Aesthetic** (`/platform`, 162 lines) **Three-Column RPG Layout:** - Left: Spirit Metrics (memory/event counts, importance, confidence) + Actions (New Memory, View Events, API Docs buttons) - Center: Spirit Core (circular sphere emoji 48x48->56x56, green/blue gradient glow, `> ACTIVE` status) - Right: Recent Memories + System Info (user, version, online status) **Authenticated Layout Redesign** (`layout.tsx`, 99 lines): - Galactic cityscape background (matches landing page) - Minimal terminal header: Wordmark + Spirit switcher (`> Spirit-01`) + email + sign out - Terminal-styled loading: Green spinner + `> LOADING...` - Space Mono font, black/gray/green palette **Design Pattern:** Terminal window component (2px border, glassmorphism, `[ TITLE ]` headers) used 5x across dashboard ### Changed - Landing page header: Wrapped wordmark in `flex-1` for three-column centering - Dashboard route: `(authenticated)/page.tsx` -> `(authenticated)/platform/page.tsx` (now `/platform`) ### Fixed **User Auth Trigger** (migration `4faf087cf25d`): - Problem: `handle_new_user()` trigger missing `is_deleted` field -> 500 errors on signup - Solution: Added `is_deleted=false` to INSERT statement ---
### Added **Frontend Authentication & Platform Restructure: Route Groups + Supabase SSR** (6 files, 618 lines) **Route Groups:** - `(public)/` - Landing page, accessible without auth - `(authenticated)/` - Platform dashboard, protected by middleware - Shared layouts with auth boundaries, URL structure unchanged (`/` vs `/platform`) **Supabase SSR Integration:** - `@supabase/ssr` with cookie-based sessions (browser + server clients) - Auth middleware with automatic token refresh, redirect logic (`/login?redirect={path}`) - `AuthContext` provider for global user state, `useAuth()` hook **Platform Dashboard** (`/platform` - authenticated route): - Empty state placeholder: "Welcome to Elephantasm Platform" - Protected route (redirects to `/login` if unauthenticated) **Environment:** `NEXT_PUBLIC_SUPABASE_URL`, `NEXT_PUBLIC_SUPABASE_ANON_KEY` ---

Showing latest 20 releases • View all on GitHub