AvenEditor is a mobile-first Markdown/code editor built with React, TypeScript, and Vite.
Current behavior supports two working modes:
- Local mode: files/folders are persisted in browser storage.
- Server mode: connect to a filesystem workspace via
working directory + access key.
|
|
- Hierarchical file/folder browser with search
- Create, rename, delete files and folders (local or server mode)
- CodeMirror editor with language-aware syntax
- Markdown preview (
remark-gfm+rehype-sanitize) - Code runner panel for
javascript,typescript,html,python - Command palette (
Ctrl+K/Cmd+K) - Zen mode
- Server workspace connect/reconnect/disconnect dialog
- On-demand server folder listing + lazy file loading
- Remote file cache reuse keyed by
contentHash - Optional write history snapshots (
.history) on server
markdown(.mdand unknown extensions)javascript(.js)typescript(.ts,.tsx)html(.html)css(.css)json(.json)python(.py)yaml(.yml,.yaml)image(.png,.jpg,.jpeg,.gif,.webp,.svg,.bmp,.ico,.avif) for previewbinary(e.g..pdf,.zip,.docx,.mp4) shown as unsupported in editor window
- Node.js
18+ - npm
npm installnpm run dev- Serves UI + API from one origin
- Default URL:
http://localhost:3000 - HMR for fullstack dev is controlled by
AVENEDITOR_DEV_HMR(defaultfalse)
npm run dev:client- Default URL:
http://localhost:3000(script sets--port=3000)
npm run dev:server- Default URL:
http://localhost:8787(unlessPORTis set) - If
dist/exists, this process also serves built frontend assets
npm run build
npm run servernpm run lint
npm testnpm test currently maps to the same TypeScript check as npm run lint.
Refer to .env.example for the full template. Key values:
AVENEDITOR_ACCESS_KEY(required): server auth key for session creationAVENEDITOR_WORKSPACE_ROOT(optional): restrict allowed workspaces to a root directoryAVENEDITOR_SESSION_TTL_SECONDS(optional, default604800)AVENEDITOR_MAX_TREE_ENTRIES(optional, default5000)AVENEDITOR_IGNORE_FILE(optional, default.avenignore): ignore file path/name (relative paths resolve from workspace root)AVENEDITOR_IGNORE_DIRS(optional, defaultnode_modules,.git,dist): comma-separated ignore entries (folders/files/globs), always merged with ignore file rulesAVENEDITOR_MAX_FILE_SIZE_BYTES(optional, default1048576)AVENEDITOR_ALLOW_ORIGIN(optional, default*)AVENEDITOR_HISTORY_ENABLED(optional, defaulttrue)AVENEDITOR_HISTORY_DIR(optional, default.history)AVENEDITOR_READ_ONLY(optional, defaulttrue)
Important: write operations are blocked by default because AVENEDITOR_READ_ONLY=true.
Set it to false when you want create/update/delete in server mode.
cp .env.example .envSet at least:
AVENEDITOR_ACCESS_KEYAVENEDITOR_WORKSPACE_HOST_PATH(host path mounted to container/workspace)
If you need write access from the editor:
AVENEDITOR_READ_ONLY=false
docker compose up -d --build- Open:
http://<server-ip>:<AVENEDITOR_HTTP_PORT> - In
Server Workspacedialog:API Base URL: same origin (or leave empty to use current origin)Working Directory:/workspaceAccess Key: value ofAVENEDITOR_ACCESS_KEY
- Access key is checked with constant-time comparison.
- A bearer token is used after session creation.
- Workspace traversal (
..) is blocked. - Session token is persisted across page refresh while still valid.
- Session validity is controlled by
AVENEDITOR_SESSION_TTL_SECONDS(server-side).
This project is still MVP-level security. For production hardening, add rate limiting, stronger auth/rotation, audit logs, and network controls.
See SECURITY.md for vulnerability reporting.
See CONTRIBUTING.md and CODE_OF_CONDUCT.md.
MIT, see LICENSE.
server/
apiApp.ts
dev.ts
ignore.ts
index.ts
src/
App.tsx
store.ts
serverApi.ts
components/
CodeRunner.tsx
CommandPalette.tsx
ConfirmDialog.tsx
Editor.tsx
FileList.tsx
Preview.tsx
RenameDialog.tsx
ServerConnectDialog.tsx
Toolbar.tsx

