A modern, secure, and scalable backend built with Elixir/Phoenix. Self-hostable with zero-knowledge encryption, powerful search, and a comprehensive REST API.
Built on battle-tested technologies optimized for reliability, performance, and developer experience.
Functional programming on the Erlang VM. Built for fault-tolerance with supervisor trees, hot code reloading, and millions of concurrent connections.
Enterprise-grade relational database with full-text search, JSONB storage, and vector embeddings for semantic search.
Robust background job processing backed by PostgreSQL. Handles sync operations, webhooks, cleanup tasks, and scheduled jobs.
Real-time, server-rendered UI without JavaScript complexity. WebSocket-based updates with automatic reconnection and offline handling.
Secure authentication with Guardian JWT, bcrypt password hashing, and API key management with scoped permissions.
In-memory caching with Erlang Term Storage. Microsecond lookups for frequently accessed data like user preferences and tag hierarchies.
A flexible schema designed for diverse content types, full history tracking, and efficient querying.
Primary content storage. UUID primary key, user ownership, soft deletes, timestamps, and sync metadata.
Multiple views of an entry (markdown, HTML, plain text, XAMLR). Supports per-format rendering and caching.
Full history of representation changes. Enables undo, diff viewing, and conflict resolution.
Binary attachments (images, files). Supports S3-compatible storage, thumbnails, and content-addressable hashing.
Hierarchical taxonomy with parent-child relationships. Supports tag aliases, colors, and icons.
Bidirectional relationships between entries. Typed links (reference, parent, related) with optional metadata.
# Entry Schema (Ecto)
schema "entries" do
field :uuid, Ecto.UUID
field :entry_type, :string # note, task, event...
field :title, :string
field :metadata, :map # JSONB for type-specific data
field :is_encrypted, :boolean
field :deleted_at, :utc_datetime
field :lock_version, :integer # optimistic locking
belongs_to :user, User
has_many :representations, Representation
has_many :assets, Asset
many_to_many :tags, Tag, join_through: "entries_tags"
timestamps(type: :utc_datetime)
end
# Representation with versions
schema "representations" do
field :format, :string # markdown, html, xamlr
field :content, :text
field :content_hash, :string
field :embedding, Pgvector.Ecto.Vector
belongs_to :entry, Entry
has_many :versions, RepresentationVersion
end
Extensible content types with type-specific metadata schemas. Add custom types without schema migrations.
General-purpose text content. Supports markdown, rich text, and XAMLR format.
metadata: {pinned, word_count}
Personal memories with date, location, and associated people.
metadata: {date, location, people[]}
Actionable items with status, priority, due dates, and recurrence.
metadata: {status, priority, due_at}
Calendar events with start/end times, location, and attendees.
metadata: {start_at, end_at, rrule}
Image entries with EXIF data, thumbnails, and AI-generated descriptions.
metadata: {exif, dimensions, alt}
Web bookmarks with automatic metadata extraction and archiving.
metadata: {url, favicon, archived}
Long-form documents with table of contents and section navigation.
metadata: {toc[], word_count}
Register custom types with JSON schema validation for metadata.
Entries.register_type/2
Your data is encrypted before it leaves your device. Even we can't read it.
Military-grade authenticated encryption. Each entry uses a unique initialization vector (IV) with authentication tags to prevent tampering.
# Encryption flow
key = PBKDF2.derive(password, salt, iterations: 600_000)
{ciphertext, tag} = AES.encrypt_gcm(plaintext, key, iv)
# Stored: Base64(iv || ciphertext || tag)
Password-based key derivation with 600,000 iterations (OWASP 2024 recommendation). Unique salt per user prevents rainbow table attacks.
Encryption keys derived and used only on client devices.
Re-encrypt data with new keys without server involvement.
Cryptographic erasure by destroying encryption keys.
Comprehensive API with OpenAPI 3.0 spec. Build integrations, automate workflows, and extend Onelist.
/api/v1/entries
List with pagination & filters
/api/v1/entries
Create entry
/api/v1/entries/:id
Update with lock_version
/api/v1/search
Full-text + semantic search
/api/v1/sync
Batch sync with conflicts
API Key with scoped permissions:
POST /api/v1/api_keys
{
"name": "Mobile App",
"scopes": ["entries:read", "entries:write", "tags:read"],
"expires_at": "2025-12-31T23:59:59Z"
}
# Response
{
"key": "ol_live_abc123...", # shown once
"key_preview": "ol_live_abc...xyz"
}
Combine PostgreSQL full-text search with pgvector semantic search for powerful, relevant results.
PostgreSQL's tsvector with GIN indexes. Supports stemming, phrase matching, and boolean operators.
# Query syntax
"meeting notes" # phrase match
meeting & notes # AND
meeting | notes # OR
meeting !urgent # NOT
meet:* # prefix match
Vector embeddings for meaning-based search. Find related content even without exact keyword matches.
# Search: "how to stay productive"
# Finds entries about:
- "Focus techniques for deep work"
- "My morning routine checklist"
- "Avoiding distractions"
Reciprocal Rank Fusion combines FTS and vector results for optimal relevance:
score = 1/(k + fts_rank) + 1/(k + vector_rank)
Offline-first architecture with automatic conflict resolution and complete version history.
Every entry has a lock_version. Updates must include the current version to prevent overwrites.
Configurable strategies: last-write-wins, manual merge, or automatic three-way merge for text.
Every change stored in representation_versions. View diffs, restore any version, or branch.
POST /api/v1/sync
{
"client_id": "device-abc",
"last_sync": "2024-01-15T10:30:00Z",
"changes": [
{"uuid": "...", "lock_version": 3, "content": "...", "updated_at": "..."}
]
}
# Response with server changes + conflicts
{
"server_changes": [...],
"conflicts": [{"uuid": "...", "client_version": {...}, "server_version": {...}}],
"sync_token": "2024-01-15T10:35:00Z"
}
Run Onelist on your own infrastructure. Full control over your data with enterprise-ready deployment options.
Single-command deployment with Docker Compose. Includes PostgreSQL, Redis, and automatic backups.
docker run -d \
-p 4000:4000 \
-e DATABASE_URL=... \
ghcr.io/onelist/core:latest
Production-ready manifests with HPA, PDB, and network policies. Supports any k8s distribution.
kubectl apply -f \
https://onelist.com/k8s/
Configurable Helm chart with values for HA, persistence, ingress, and monitoring.
helm install onelist \
oci://ghcr.io/onelist/helm \
--values custom.yaml
DATABASE_URL - PostgreSQL connectionSECRET_KEY_BASE - 64+ char secretPHX_HOST - Public hostnameS3_BUCKET - Asset storageSMTP_* - Email configurationOPENAI_API_KEY - EmbeddingsDeploy Onelist Core in minutes. Your data, your servers, your rules.