mirror of
https://github.com/photoprism/photoprism.git
synced 2026-01-23 02:24:24 +00:00
6.8 KiB
6.8 KiB
PhotoPrism — Frontend CODEMAP
Purpose
- Help agents and contributors navigate the Vue 3 + Vuetify 3 app quickly and make safe changes.
- Use Makefile targets and scripts in
frontend/package.jsonas sources of truth.
Quick Start
- Build once:
make -C frontend build - Watch for changes (inside dev container is fine):
make watch-jsfrom repo root, orcd frontend && npm run watch
- Unit tests (Vitest):
make vitest-watch/make vitest-coverageorcd frontend && npm run test
Directory Map (src)
src/app.vue— root component; UI shellsrc/app.js— app bootstrap: creates Vue app, installs Vuetify + plugins, configures router, mounts to#appsrc/app/routes.js— all route definitions (guards, titles, meta)src/app/session.js—$configand$sessionsingletons wired from server-providedwindow.__CONFIG__and storagesrc/common/*— framework-agnostic helpers:$api(Axios),$notify,$view,$event(PubSub), i18n (gettext), util, fullscreen, map utils, websocketsrc/component/*— Vue components;src/component/components.jsregisters global componentssrc/page/*— route views (Albums, Photos, Places, Settings, Admin, Discover, Help, Login, etc.)src/model/*— REST models; baseRestclass (model/rest.js) wraps Axios CRUD for collections and entitiessrc/options/*— UI/theme options, formats, auth optionssrc/css/*— styles loaded by Webpacksrc/locales/*— gettext catalogs; extraction/compile scripts inpackage.json
Runtime & Plugins
- Vue 3 + Vuetify 3 (
createVuetify) with MDI icons; themes fromsrc/options/themes.js - Router: Vue Router 4, history base at
$config.baseUri + "/library/" - I18n:
vue3-gettextviacommon/gettext.js; extraction withnpm run gettext-extract, compile withnpm run gettext-compile - HTML sanitization:
vue-3-sanitize+vue-sanitize-directive - Tooltips:
floating-vue - Video: HLS.js assigned to
window.Hls - PWA:
@lcdp/offline-plugin/runtimeinstalls whenbaseUri === "" - WebSocket:
src/common/websocket.jspublisheswebsocket.*events, used by$sessionfor client info
HTTP Client
- Axios instance:
src/common/api.js- Base URL:
window.__CONFIG__.apiUri(or/api/v1in tests) - Adds
X-Auth-Token,X-Client-Uri,X-Client-Version - Interceptors drive global progress notifications and token refresh via headers
X-Preview-Token/X-Download-Token
- Base URL:
Auth, Session, and Config
$session:src/common/session.js— storesX-Auth-Tokenandsession.idin storage; provides guards and default routes$config:src/common/config.js— reactive view of server config and user settings; sets theme, language, limits; exposesdeny()for feature flags- Route guards live in
src/app.js(routerbeforeEach/afterEach) and use$session+$config $view:src/common/view.js— manages focus/scroll helpers; usesaveWindowScrollPos()/restoreWindowScrollPos()when navigating so infinite-scroll pages land back where users left them; behaviour is covered bytests/vitest/common/view.test.js
Models (REST)
- Base class:
src/model/rest.jsprovidessearch,find,save,update,removefor concrete models (photo,album,label,subject, etc.) - Collection helpers:
src/model/collection.jsadds shared behaviors (for examplesetCover) used by collection-types such as albums and labels. - Pagination headers used:
X-Count,X-Limit,X-Offset
Routing Conventions
- Add pages under
src/page/<area>/...and import them insrc/app/routes.js - Set
meta.requiresAuth,meta.admin, andmeta.settingsas needed - Use
meta.titlefor translated titles;router.afterEachupdatesdocument.title
Theming & UI
- Themes:
src/options/themes.jsregistered in Vuetify; default comes from$config.values.settings.ui.theme - Global components: register in
src/component/components.jswhen they are broadly reused
Testing
- Vitest config:
frontend/vitest.config.js(Vue plugin, alias map tosrc/*),tests/vitest/**/* - Run:
cd frontend && npm run test(ormake test-jsfrom repo root) - Acceptance: TestCafe configs in
frontend/tests/acceptance; run against a live server
Build & Tooling
- Webpack is used for bundling; scripts in
frontend/package.json:npm run build(prod),npm run build-dev(dev),npm run watch- Lint/format:
npm run lint,npm run fmt - Security scan:
npm run security:scan(checks--ignore-scriptsand forbidsv-html)
- Make targets (from repo root):
make build-js,make watch-js,make test-js
Common How‑Tos
-
Add a page
- Create
src/page/<name>.vue(or nested directory) - Add route in
src/app/routes.jswithname,path,component, andmeta - Use
$apifor data,$notifyfor UX,$sessionfor guards updateQuery(props)helpers should return a boolean indicating whether a navigation was scheduled (recently standardised across pages); callers can bail early whenfalse
- Create
-
Add a REST model
- Create
src/model/<thing>.jsextendingRestand implementstatic getCollectionResource()+static getModelName() - Use in pages/components for CRUD
- Create
-
Call a backend endpoint
- Use
$api.get/post/put/deletefromsrc/common/api.js - For auth:
$session.setAuthToken(token)sets header; router guards redirect tologinwhen needed
- Use
-
Add translations
- Wrap strings with
$gettext(...)/$pgettext(...) - Extract:
npm run gettext-extract; compile:npm run gettext-compile
- Wrap strings with
-
Restore scroll state on back navigation
- Use
$view.saveRestoreState(key, { count, offset, scrollTop })when unloads happen and$view.consumeRestoreState(key)on popstate to preload prior batches (Albums, Labels already supply examples). - Compute
keyfrom route + filter params and cap eager loads withRest.restoreCap(Model.batchSize())(defaults to 10× the batch size). - Check
$view.wasBackwardNavigation()when deciding whether to reuse stored state;src/app.jswires the router guards that keep the history direction in sync so no globals likewindow.backwardsNavigationDetectedare needed.
- Use
Conventions & Safety
- Avoid
v-html; usev-sanitizeor$util.sanitizeHtml()(build enforces this) - Keep big components lazy if needed; split views logically under
src/page - Respect aliases in
vitest.config.jswhen importing (app,common,component,model,options,page)
Frequently Touched Files
- Bootstrap:
src/app.js,src/app.vue - Router:
src/app/routes.js - HTTP:
src/common/api.js - Session/Config:
src/common/session.js,src/common/config.js - Models:
src/model/rest.jsand concrete models (photo.js,album.js, ...) - Global components:
src/component/components.js
See Also
- Backend CODEMAP at repo root (
CODEMAP.md) for API and server internals - AGENTS.md for repo-wide rules and test tips