Back to News
Blog

Introducing Lampray: An Open Source Self-Hosted Blog Platform

2026-05-24 RollW 7 min

Every blog platform demands a compromise.

WordPress requires trusting thousands of third-party plugins with your security, and it locks you into MySQL. Migrating away is a non-trivial ordeal. Medium asks you to exchange your readers and content for its distribution network. Your blog resides on its domain, your SEO rankings belong to it, and your relationship with readers is mediated by its algorithms. Static site generators impose a developer workflow even for pure writing: fix a typo by editing a file, committing, pushing, waiting for CI, then deploying. A ten-second correction becomes a five-minute production operation.

None of these are bad tools, but none of them let you own your content fully without sacrificing ease of use.

Lampray takes a different approach.

The Core Problem

Existing blog platforms force a tradeoff between ownership, usability, and extensibility.

WordPress is extensible but couples you to MySQL and a plugin ecosystem with significant security overhead. Its editing experience has remained largely unchanged for years, and the admin interface has grown complex over decades of feature accumulation. Medium is usable but owns your audience and your content distribution. Your blog is a tenant on its platform, not a property you control. Static site generators give you full ownership at the cost of a developer-oriented workflow that assumes Git proficiency and CI/CD familiarity.

A platform that combines the simplicity of Medium, the extensibility of WordPress, and the freedom of a static site, without any of the corresponding tradeoffs, did not exist. That is the premise Lampray was built on.

The Architecture of Lampray

Lampray is a self-hosted blog system. You deploy it on your own server, your content lives in your own database, and you retain complete ownership over every aspect of the experience.

Database Independence

Most blog platforms are tightly coupled to a specific database. Lampray supports seven engines out of the box: SQLite, H2, MySQL, PostgreSQL, MariaDB, Oracle, and SQL Server.

You can begin with an in-memory SQLite database requiring zero configuration. No database server, no setup, no credentials. Just run the application and start writing. When you need more capacity, switch to a file-based SQLite for persistence, or transition to PostgreSQL for production workloads. The change requires modifying three lines in a configuration file:

[database]
type = "postgresql"
target = "localhost:5432"
name = "lampray"

No code changes. No migration scripts. No vendor-specific features to work around.

Behind the scenes, each database type has a dedicated URL builder that constructs the correct JDBC connection string and manages engine-specific parameters. Hibernate's dialect system handles query-level differences at runtime, and Liquibase manages schema evolution by detecting whether the deployment is a fresh install, an incremental upgrade, or a legacy migration.

The Editor

The editor is the central component of a writing platform. Lampray's editor is built on Tiptap, which wraps ProseMirror's document model, the same foundation used by many professional content tools.

ProseMirror's document model handles complex editing operations correctly: selections, transformations, undo history, and collaborative editing primitives. Contenteditable-based editors, by contrast, struggle with cursor stability, DOM synchronization, and cross-browser consistency.

The editor supports:

  • Rich text formatting with a context-aware bubble menu that appears on text selection
  • Tables with full row and column operations, including insertion, deletion, and cell merging
  • Code blocks with syntax highlighting powered by Lowlight
  • Image embedding with upload handled by the file storage service
  • Drag-and-drop block reordering via Tiptap's drag handle extension
  • Task lists for checklist-style content
  • Full-screen mode for distraction-free writing
  • Document outlines that track the article's structure automatically

The integration matters more than the individual features: the interface surfaces controls contextually, staying out of the way until needed.

Modular Backend Architecture

The backend is organized into independent modules that communicate through well-defined interfaces rather than direct dependencies:

ModuleResponsibility
lampray-webApplication entry point, server configuration, controllers
lampray-commonShared utilities and base abstractions
lampray-contentArticles, comments, content review
lampray-fileFile storage (local filesystem, AWS S3)
lampray-iamAuthentication and authorization
lampray-userUser management, staff roles
lampray-systemSystem settings, message resources
lampray-pushNotification delivery

Each module has its own API surface and persistence layer. The content-api module defines interfaces that article-service and comment-service implement independently. Replacing a module with a custom implementation, for example integrating an external CMS, requires implementing the interface and swapping the Spring bean.

This modularity also applies at build time: subsystems can be excluded from the build to reduce attack surface and memory footprint.

Content Moderation

Lampray includes a review pipeline with configurable sensitive-word filtering. The system can operate in fully automated mode, require manual approval, or be disabled entirely, controlled through the administration panel.

For team blogs or community publications, content can be submitted as draft, automatically scanned against a configurable word list, and queued for reviewer approval before publication. The review system tracks the entire lifecycle: submission, automated checks, human review, feedback, and final decision.

Security

Security is organized into several layers:

  1. Authentication — JWT-based with access and refresh token rotation. Tokens are signed with a configurable secret key supporting both file-based and in-memory storage.
  2. Authorization — Role-based access control with USER, ADMIN, STAFF, and REVIEWER roles. Routes and API endpoints are protected through Spring Security's method-level and URL-level security.
  3. Content safety — Sensitive-word filtering operates at registration (username, bio) and content creation (articles, comments).
  4. Firewall — An IP-based firewall system that blocks, rate-limits, or allows traffic based on configurable rules. It provides application-level protection such as blocking repeated failed login attempts from a single IP or rate-limiting comment submissions.

Deployment Flexibility

Lampray offers multiple deployment paths optimized for different use cases.

Development mode. Defaults to in-memory SQLite. Clone the repository and run ./gradlew bootRun. The first user to register is automatically granted administrative access. No setup step required.

Single-JAR deployment. Build the project and deploy the executable JAR with an embedded Tomcat server:

./gradlew assemble
java -jar lampray-web/build/libs/lampray.jar --config /path/to/lampray.toml

Docker deployment. A Containerfile and Gradle task are provided:

./gradlew buildImage
docker run -d -p 5100:5100 -v /path/to/conf:/app/lampray/conf --name lampray lampray:0.1.0

SSH console. An embedded SSH server (port 5101 by default) provides a restricted command-line interface limited to diagnostics, log viewing, and maintenance tasks. The SSH server runs Apache MINA sshd on a separate port, allowing selective exposure through your firewall.

Technology Stack

The backend is built with Spring Boot 3, using Kotlin and Java. Spring Boot provides mature multi-database support through Spring Data JPA, a comprehensive security framework via Spring Security, and a modular dependency injection model that aligns with the project's architecture. The database connection layer uses HikariCP for connection pooling with per-engine validation queries and configurable pool sizing.

The frontend is a Vue 3 single-page application written in TypeScript. State management uses Pinia with a single user store that handles authentication state, role management, and session persistence. Client-side navigation uses Vue Router with type-safe route definitions. Route names are defined as a const object and used throughout the application, eliminating string-based routing bugs. Internationalization uses vue-i18n with locale-persistent settings and translation files organized by locale.

The editor is powered by Tiptap with a ProseMirror foundation. Additional frontend dependencies include Axios for HTTP communication, Zod for runtime validation, and Nuxt UI for interface components.

Schema evolution is managed by Liquibase with a branching strategy: baseline schemas for new installations contain complete table definitions, while incremental changelogs handle upgrades without data loss. The migration system detects the deployment scenario automatically.

Roadmap

Lampray is currently at version 0.1.0-alpha. It is functional and stable for daily use, but significant work remains.

  • Storage improvements — Better file storage abstractions, S3-compatible object storage support, and backup tooling.
  • Editor improvements — Rich media embedding, slash commands, collaborative editing foundations.
  • Metrics and analytics — Built-in metrics monitoring and analysis for content performance and user engagement.
  • Security hardening — Rate limiting, brute-force protection enhancements, audit logging.
  • Full-text search — Integration with PostgreSQL's built-in full-text search or Elasticsearch for fast content discovery.
  • Dependency upgrades — Keeping the stack current with the latest framework and library versions.

Getting Started

Lampray is open source under the Apache License 2.0:

github.com/roll-w/lampray

Clone the repository, execute ./gradlew bootRun, and begin writing within a minute. Contributions, issue reports, and feature proposals are welcome.