Migrate the frontend to the Nextcloud UI framework (@nextcloud/vue) — staged epic
Context
The frontend is a legacy jQuery multi-page app: ~3,100 lines of hand-written jQuery across 9 webpack entry bundles (timer, clients, dashboard, projects, reports, tags, goals, timelines, timelines-admin), each hydrating a server-rendered PHP template and calling the existing controllers. Runtime dependencies are all jQuery-era plugins: jquery, jquery-migrate, jqueryui, select2, daterangepicker, moment, tabulator-tables, chart.js@2 (EOL), plus a vendored piklor.js color picker.
The PHP backend (lib/) is lean and healthy and should NOT be rewritten — there is already an AjaxController, so the backend is API-ready. This epic migrates only the frontend onto the Nextcloud UI framework (Vue + @nextcloud/vue + @nextcloud/* helpers), turning the app from "server-rendered pages + jQuery" into a Vue SPA calling the existing controllers as JSON endpoints.
Depends on: the repo-size-reduction issue (remove FontAwesome/KingTable) and the testing/CI issue (land CI first so each migration PR is checked).
Goals
- Remove nearly all runtime npm dependencies, replacing them with the shared, server-provided
@nextcloud/vue component library (weight amortised across the instance, not shipped per-app).
- Collapse the maintenance surface: no
jquery-migrate shims, no unmaintained vendored plugins, and automatic theming / dark mode / RTL / accessibility from the native components.
- Preserve existing behaviour and the existing controller endpoints (no backend rewrite).
Dependency → native replacement map
| Current |
Role |
Native replacement |
| jquery, jquery-migrate, jqueryui |
DOM, dialogs, buttons, widgets |
Vue + @nextcloud/vue: NcButton, NcModal/NcDialog, NcActions, NcAppNavigation, NcAppContent |
| select2 |
searchable dropdowns |
NcSelect |
| daterangepicker (+ moment) |
date-range picking |
NcDateTimePickerNative / NcDateTimePicker |
| moment (every view) |
date format/parse |
@nextcloud/moment (locale-aware) or dayjs; much can be native Intl |
| tabulator-tables |
data tables |
NcTable where it fits, otherwise a Vue table against the same endpoints |
| chart.js@2.9.4 (dashboard) |
donut/pie chart |
keep, but upgrade to chart.js v4; vue-chartjs wrapper |
| vendored piklor.js |
color picker |
NcColorPicker |
| PHP templates + jQuery wiring |
shell, nav, routing |
NcContent + NcAppNavigation + NcAppContent, @nextcloud/router, @nextcloud/axios, @nextcloud/l10n, @nextcloud/dialogs |
Staged plan (one PR per stage; app stays working throughout)
Stage 1 — Tooling & app shell
Stage 2 — Migrate views (one per PR, easiest first)
Each view becomes a Vue component calling the same controller endpoints via @nextcloud/axios. Suggested order:
Stage 3 — Retire shared plugins
As each plugin loses its last consumer, remove it:
Stage 4 — Remove legacy scaffolding
Acceptance criteria (epic complete)
Testing (live instance, per PR)
For every migrated view, verify against the previous behaviour:
Notes for the implementing agent
- Split this epic into one PR per checkbox-group (shell, then each view, then each plugin removal). Keep the app shippable after every PR.
- Do not touch
lib/ beyond adding endpoints if a view genuinely needs one; the goal is a frontend swap, not a backend rewrite.
- Reuse the existing controller routes and response shapes; where a legacy view relied on server-rendered HTML, add a small JSON endpoint rather than changing the data model.
Migrate the frontend to the Nextcloud UI framework (@nextcloud/vue) — staged epic
Context
The frontend is a legacy jQuery multi-page app: ~3,100 lines of hand-written jQuery across 9 webpack entry bundles (
timer,clients,dashboard,projects,reports,tags,goals,timelines,timelines-admin), each hydrating a server-rendered PHP template and calling the existing controllers. Runtime dependencies are all jQuery-era plugins:jquery,jquery-migrate,jqueryui,select2,daterangepicker,moment,tabulator-tables,chart.js@2(EOL), plus a vendoredpiklor.jscolor picker.The PHP backend (
lib/) is lean and healthy and should NOT be rewritten — there is already anAjaxController, so the backend is API-ready. This epic migrates only the frontend onto the Nextcloud UI framework (Vue +@nextcloud/vue+@nextcloud/*helpers), turning the app from "server-rendered pages + jQuery" into a Vue SPA calling the existing controllers as JSON endpoints.Goals
@nextcloud/vuecomponent library (weight amortised across the instance, not shipped per-app).jquery-migrateshims, no unmaintained vendored plugins, and automatic theming / dark mode / RTL / accessibility from the native components.Dependency → native replacement map
Staged plan (one PR per stage; app stays working throughout)
Stage 1 — Tooling & app shell
@nextcloud/vue,@nextcloud/webpack-vue-config,@nextcloud/axios,@nextcloud/router,@nextcloud/l10n,@nextcloud/dialogs; switch webpack to the Nextcloud Vue config.NcContent→NcAppNavigation(replacingtemplates/navigation/) +NcAppContent.@nextcloud/router/ vue-router) for the existing sections. Initially each route may still embed the legacy view; the shell is the deliverable here.Stage 2 — Migrate views (one per PR, easiest first)
Each view becomes a Vue component calling the same controller endpoints via
@nextcloud/axios. Suggested order:tags(simplest CRUD; introducesNcTable/list pattern + edit viaNcModal)clientsprojects(introducesNcColorPicker, replacingpiklor.js)goalstimer(main view; timer logic + manual-entry dialog →NcModal, entry inputs →NcTextField)dashboard(chart.js v4 +vue-chartjs; date range →NcDateTimePicker)reports,timelines,timelines-admin(the Tabulator-heavy grids — tackle last)Stage 3 — Retire shared plugins
As each plugin loses its last consumer, remove it:
select2→NcSelecteverywhere, then drop frompackage.jsondaterangepicker→NcDateTimePicker, then dropNcModal/NcDialog, then dropjqueryuijquery+jquery-migrateonce no view imports themchart.js2 → 4Stage 4 — Remove legacy scaffolding
templates/content/as the SPA owns routing (keep only the SPA host template).Acceptance criteria (epic complete)
jquery,jquery-migrate,jqueryui,select2,daterangepicker,piklor.jsin the shipped bundle.@nextcloud/vue, styled/themed natively (dark mode, RTL work automatically).lib/PHP endpoints unchanged (backend not rewritten).Testing (live instance, per PR)
For every migrated view, verify against the previous behaviour:
NcColorPicker)@nextcloud/l10nNotes for the implementing agent
lib/beyond adding endpoints if a view genuinely needs one; the goal is a frontend swap, not a backend rewrite.