This document provides a high-level introduction to the Memos project, explaining its purpose, architecture, technology stack, and deployment model. It serves as an entry point for understanding the codebase structure and design decisions.
For detailed information about specific subsystems, see:
Memos is a self-hosted note-taking and knowledge management service built as a single-binary application. The system combines a Go backend with a React frontend, distributed as a unified executable with embedded static assets. The application is designed for personal and team use with emphasis on data portability, minimal resource usage, and privacy.
The codebase is organized as a monorepo containing both frontend (web/) and backend (server/, store/, plugin/) components, with protocol buffer definitions (proto/) defining the API contract between them.
Sources: README.md1-111 server/server.go1-183
The application compiles to a single executable that embeds all frontend assets. The Server struct in server/server.go27-35 manages both HTTP serving and background tasks. The frontend service at server/router/frontend/ embeds the compiled React application into the binary at build time using Go's embed directives.
The Store interface abstracts database operations, supporting three backends without code changes:
modernc.org/sqlite)github.com/go-sql-driver/mysql)github.com/lib/pq)The store implementations are in store/ with driver-specific SQL generation handled per database.
All business logic APIs are defined as gRPC services in protocol buffer files at proto/api/v1/ The system uses grpc-gateway to automatically generate HTTP/JSON endpoints from these definitions, providing both native gRPC and REST APIs from a single service implementation.
Sources: go.mod1-135 server/server.go27-83 README.md39-51
The following table lists core dependencies and their purposes:
| Component | Technology | Purpose |
|---|---|---|
| Backend Language | Go 1.25+ | Server implementation |
| HTTP Framework | Echo v5 | HTTP routing and middleware |
| API Protocol | gRPC + Protocol Buffers | Type-safe API definitions |
| HTTP/JSON Gateway | grpc-gateway v2 | REST API generation |
| Database Drivers | SQLite, MySQL, PostgreSQL | Data persistence |
| Frontend Framework | React 18.3 | UI implementation |
| Build Tool | Vite 7 | Frontend bundling |
| API Client | @connectrpc/connect | Type-safe frontend API client |
| State Management | React Query 5 | Server state caching |
| Styling | Tailwind CSS 4 | Utility-first CSS |
| i18n | i18next 25 | Internationalization |
Sources: go.mod1-135 web/package.json1-99
Architecture Overview
The system follows a layered architecture with clear separation between HTTP handling, business logic, and data access:
Entry Point: The main.go file initializes the Server struct with a Profile (configuration) and Store (database abstraction).
HTTP Layer: The Echo HTTP server handles all incoming requests. Routes are registered in a specific order at server/server.go58-80:
/healthz - Health check endpoint/o/r/* - File server routes (must be before gRPC gateway for Safari compatibility)/explore/rss.xml - RSS feed/api/v1/* - gRPC Gateway for all business logic APIsAPI Layer: The grpc-gateway translates HTTP/JSON requests to gRPC calls and back. All services implement protocol buffer definitions from proto/api/v1/
Business Logic: Service implementations at server/service/ handle memo operations, user management, resource handling, etc. These services use:
Store interface for database operationsMarkdownService for content processing (using goldmark)Webhook plugin for event notificationsData Layer: The Store interface at store/store.go provides database-agnostic operations. Driver implementations at store/db/ generate database-specific SQL.
Background Tasks: The server starts goroutines for asynchronous operations via server/server.go139-159 Currently includes S3 presign URL generation.
Sources: server/server.go1-183 go.mod1-135 Diagram 1, Diagram 2
Initialization Flow
The application initializes in the following sequence:
Configuration Loading: The Profile struct is populated from environment variables, command-line flags, or a .env file via github.com/spf13/viper and github.com/joho/godotenv
Store Initialization: The Store is created at store/store.go based on the database driver specified in the profile. Database migrations run automatically via store/migration/
Server Creation: The NewServer function at server/server.go37-83 performs these steps:
Echo instance with recovery middleware/healthz endpoint/api/v1/* routesServer Start: The Start method at server/server.go85-109:
Background Runners: Launched via server/server.go139-159 these run in separate goroutines with independent cancellation contexts for clean shutdown.
Sources: server/server.go37-159 store/store.go Diagram 4
The application supports multiple deployment strategies:
The primary distribution method is Docker images published to:
neosmemo/memos:stable and neosmemo/memos:canaryghcr.io/usememos/memosImages are built for multiple architectures (amd64, arm64, arm/v7) using GitHub Actions workflows at .github/workflows/ The Dockerfile at Dockerfile creates a minimal image from the compiled binary.
Pre-compiled binaries for Linux, macOS, and Windows are built via CI and attached to GitHub releases. The single binary includes all frontend assets and requires no external dependencies beyond the database.
The Store interface supports three connection modes configured via environment variables:
| Mode | Environment Variable | Example |
|---|---|---|
| SQLite | MEMOS_DSN | file:/var/opt/memos/memos_prod.db |
| MySQL | MEMOS_DSN | user:pass@tcp(localhost:3306)/memos |
| PostgreSQL | MEMOS_DSN | postgresql://user:pass@localhost:5432/memos |
SQLite is the default and requires no external database server. MySQL and PostgreSQL require a running database instance.
Sources: README.md52-78 .github/workflows/ Diagram 6
All APIs are defined in protocol buffer files at proto/api/v1/ and implemented as gRPC services. The system provides two access methods:
Direct gRPC access uses connectrpc.com/connect for type-safe communication. Service definitions include:
MemoService - CRUD operations, comments, reactionsUserService - Authentication, profile managementResourceService - File uploads and attachmentsWorkspaceSettingService - Instance configurationIdentityProviderService - SSO/OAuth providersWebhookService - Event webhooksThe grpc-gateway automatically generates RESTful endpoints at /api/v1/* by translating HTTP requests to gRPC calls. This is configured via protocol buffer annotations in the service definitions.
Example mapping:
POST /api/v1/memos → MemoService.CreateMemo()GET /api/v1/memos/{id} → MemoService.GetMemo()PATCH /api/v1/memos/{id} → MemoService.UpdateMemo()Authentication is handled via JWT tokens in the Authorization header, validated at server/middleware/
Sources: proto/api/v1/ server/service/ go.mod6-17 Diagram 2
The core data entities are:
All entities are defined as protocol buffer messages in proto/store/ and mapped to database tables via the Store interface.
For detailed entity relationships and storage patterns, see Data Models and Storage.
Sources: proto/store/ store/
The React frontend at web/ is built with:
The application entry point is web/src/main.tsx which establishes the context provider hierarchy and initializes the router. The build output is embedded into the Go binary at compile time via server/router/frontend/
For detailed frontend architecture, see Frontend.
Sources: web/package.json1-99 web/src/main.tsx Diagram 3
To run Memos locally:
Access at http://localhost:5230. The first user created becomes the admin.
Requires Go 1.25+ and Node.js 18+:
Configuration is via environment variables or .env file. See Setting Up Development Environment for detailed instructions.
Sources: README.md52-78 Dockerfile
Refresh this wiki