Editoro is a local-first markdown workspace inspired by Obsidian, built with Nuxt 4 and Nuxt UI 4.
It stores project files directly on disk in the `data/` directory and provides a two-panel experience:
file tree on the left, editor/browser on the right.
- Full-height split workspace (resizable sidebar with persisted width).
- File tree with create/rename/delete, drag-and-drop move, hidden files toggle.
- Markdown editor for
.md/.markdownfiles. - Image preview for image files.
- Folder browser view for directories.
- Rich markdown editor with slash menu, toolbar, link popover, image upload.
- Raw markdown mode toggle.
- Auto-save with status indicator.
- Pinned items (files/folders/images) persisted in cookies.
- Route sync via
?file=...with restore on refresh. - i18n support (
endefault,ru) and color mode preferences.
Run a prebuilt image from GHCR:
PUID="$(id -u 2>/dev/null || echo 1000)"
PGID="$(id -g 2>/dev/null || echo 1000)"
docker run --name editoro \
--user "${PUID}:${PGID}" \
-p 3000:3000 \
-v $(pwd)/data:/app/data \
ghcr.io/codewec/editoro:latestThen open http://localhost:3000.
Run with Docker Compose:
Minimal docker-compose.yml (no .env):
services:
editoro:
image: ghcr.io/codewec/editoro:latest
container_name: editoro
restart: unless-stopped
user: "${PUID:-1000}:${PGID:-1000}"
ports:
- "3000:3000"
volumes:
- ./data:/app/datamkdir -p data
export PUID="$(id -u 2>/dev/null || echo 1000)"
export PGID="$(id -g 2>/dev/null || echo 1000)"
docker compose pull
docker compose up -d
docker compose logs -fAlways set user in compose config. Without it, new files and folders in ./data will be created by root.
If needed, align host directory permissions before startup:
mkdir -p data
sudo chown -R "$(id -u 2>/dev/null || echo 1000):$(id -g 2>/dev/null || echo 1000)" dataLXD quick start (example):
lxc profile create editoro
lxc profile edit editoro < deploy/lxc/lxd-editoro.yaml
lxc launch images:ubuntu/24.04 editoro --profile default --profile editoro- Nuxt 4
- Nuxt UI 4
- Pinia
- @nuxtjs/i18n
- Tailwind CSS 4
- TypeScript + ESLint
- All user content is stored under
data/. - Markdown media is stored in sibling
.mediadirectories. - Server-side filesystem logic is centralized in
server/utils/data-storage.ts.
pnpm install
pnpm devpnpm lint
pnpm typecheckpnpm build
pnpm preview- Generate/update changelog from commits:
pnpm changelog- Prepare release changelog:
pnpm changelog:release- Push to
mainbuilds and publishes Docker image toghcr.iowith tagdev. - Push git tag (for example
v1.2.0) builds and publishes Docker image with tagslatestand<git-tag>.
Dockerfile- production image for Nuxt server output.docker-compose.yml- local container orchestration.deploy/lxc/lxd-editoro.yaml- LXD profile/cloud-init example.deploy/lxc/lxc.conf- classic LXC config example.