paneo is a keyboard-first, two-pane file manager inspired by Total Commander and Midnight Commander. It runs as a Nuxt 4 app and is intended to be deployed in Docker, with filesystem access restricted to configured roots.
- Nuxt 4
- Nuxt UI
- Nitro server routes for filesystem operations
- @nuxtjs/i18n (locale JSON files)
- Frontend and backend are in the same Nuxt project.
- Backend exposes
/api/fs/*endpoints. - Filesystem operations are allowed only inside configured roots.
- Roots are configured via
NUXT_FILE_MANAGER_ROOTS. - Optional auth is enabled only when
NUXT_PANEO_AUTH_PASSWORDis set.
Environment variable format:
NUXT_FILE_MANAGER_ROOTS="alias1=/path1;alias2=/path2;/path3"
Parsing rules:
;or newline separator- optional alias (
alias=path) - if alias is omitted, basename/path is used as display name
- Favorites are stored server-side in
/app/.paneo/favorites.json(internal constant path). - For Docker persistence, mount a host volume to
/app/.paneo(configure viaPANEO_DATA_DIRin Compose).
app/pages/index.vue- file manager workspace page
app/pages/auth.vue- auth page (SSR redirect target)
app/components/file-manager/FileManagerWorkspace.vue- workspace orchestration (panels, hotkeys, modal wiring)
app/components/file-manager/*- panel/action/startup/modal UI components
app/composables/useFileManagerApi.ts- frontend API client (
/api/fs/*)
- frontend API client (
app/composables/useFileManagerPanels.ts- panel state, navigation, selection, history
app/composables/useFileManagerActions.ts- file actions, copy/upload tasks, action gating
app/composables/useFileManagerFavorites.ts- favorites state, modal actions, toggle/open logic
app/composables/usePaneoAuth.ts- auth actions (login/logout)
app/composables/useFileManagerHotkeys.ts- global keyboard shortcuts
server/utils/file-manager.ts- secure filesystem logic (path normalization, root enforcement, operations)
server/utils/favorites-store.ts- favorites persistence (read/write/cleanup)
server/utils/startup-status.ts- startup validation (env/access/warnings)
server/utils/auth-session.ts- auth session signing/verification helpers
server/middleware/auth-redirect.ts- SSR route guard (
/<->/auth)
- SSR route guard (
server/middleware/auth-api.ts- API auth guard (
/api/*)
- API auth guard (
server/api/fs/*.ts- HTTP handlers
server/api/system/startup.get.ts- startup status endpoint
i18n/locales/*.json- localization resources
- Panels are independent
- each panel keeps its own root, current path, selection, marked entries, and list state.
- Navigation safety
- operations are restricted to configured roots.
- path traversal is blocked.
- navigation into inaccessible directories is prevented/rolled back and surfaced via toast.
- Root level behavior
- when no root is selected, panel shows source list.
- most file actions are disabled in source-list context.
- Selection behavior
- first item is selected after load.
- going up selects the previous folder where applicable.
- list auto-scroll follows keyboard selection.
- Favorites
- only folders can be favorited.
- star icon in row toggles favorite.
- favorites modal can open/remove entries.
- favorites are validated on server; missing/inaccessible entries are dropped.
- Auth
- if
NUXT_PANEO_AUTH_PASSWORDis empty, app opens directly. - if it is set, unauthenticated users are SSR-redirected to
/auth. - after successful login user is redirected back to
/. - logout is available from Settings modal.
- Module:
@nuxtjs/i18n - Locale files:
i18n/locales/ru.jsoni18n/locales/en.jsoni18n/locales/zh-Hant.jsoni18n/locales/de.jsoni18n/locales/es.json
- Selected language is persisted in cookie key
paneo.locale.
Tab: switch active panelArrowUp/ArrowDown: move selectionPageUp/PageDown: page-wise selection moveEnter: open selected root/folder/..Insert/T: mark/unmark and move downF: toggle favorite for current selected folderF1: settingsF2: favorites modalF3: viewF4: edit (text files)F5: copy/move workflowF6: renameF7: createF8: deleteF9: uploadF10: download
GET /api/fs/rootsGET /api/fs/list?rootId=...&path=...GET /api/fs/read?rootId=...&path=...GET /api/fs/raw?rootId=...&path=...GET /api/fs/meta?rootId=...&path=...GET /api/fs/download?rootId=...&path=...POST /api/fs/writePOST /api/fs/mkdirPOST /api/fs/create-filePOST /api/fs/deletePOST /api/fs/copyPOST /api/fs/copy-startGET /api/fs/copy-statusPOST /api/fs/copy-cancelPOST /api/fs/movePOST /api/fs/uploadPOST /api/fs/upload-cancelPOST /api/fs/import-localGET /api/fs/favoritesPOST /api/fs/favorites-addPOST /api/fs/favorites-remove
- Keep UI on Nuxt UI components.
- Do not bypass server-side root/path validation.
- Preserve keyboard workflow and panel independence.
- Add translations to all locale files when introducing UI text.
- Keep destructive actions behind confirmation UX.
- Prefer composables for behavior; avoid overloading
index.vue.
pnpm install
pnpm dev
pnpm typecheck
pnpm lintIf i18n/module config changes do not appear, restart dev server and clear .nuxt.