- Move bookmarks + episodes fetching to TanStack Query for caching and refetch control.
- Keep Preact + HTM + domstack build flow unchanged for pages that do not opt in.
- Avoid behavioral regressions in pagination, search params, and polling.
- Client bundles run via domstack + esbuild. domstack supports
esbuild.settingsoverrides. .jsx/.tsxdefaults to Preact; React-only libs need compat or build aliasing.- There is already a
useQueryhook for URL search params, which conflicts with TanStack’suseQueryname. - domstack docs call out
esbuild.settingsas the hook to customize build options (includingtarget,jsx, andjsxImportSource); unsettingjsx/jsxImportSourcereturns to default React transforms. - Preact docs recommend aliasing
react,react-dom,react/jsx-runtime, andreact-dom/test-utilsto the correspondingpreact/*compat modules. - TanStack Query React v5 docs require React 18+ and show
QueryClientProvideras the required top-level provider.
- Query package
- Option A (recommended):
@tanstack/react-query+preact/compataliasing. - Option B:
@tanstack/query-core+ custom Preact hook wrapper (more custom code).
- Option A (recommended):
- Provider location
- Each page mounts itself (no shared client root), so:
- Wrap each
client.jsentry withQueryClientProvider, or - Create a shared
renderWithQueryClienthelper and use it from every page entry.
- Wrap each
- Root layout is only used during string rendering, so it cannot host the provider.
- Each page mounts itself (no shared client root), so:
- Naming
- Keep existing
useQueryand alias TanStack import (useQuery as useTanstackQuery), or rename the routing hook.
- Keep existing
-
Build setup
- Add dependency on
@tanstack/react-query(andreact/react-domif peer deps require it). - Update
packages/web/client/esbuild.settings.jsto alias:react->preact/compatreact-dom->preact/compatreact/jsx-runtime->preact/jsx-runtimereact-dom/test-utils->preact/test-utils(optional)
- Implement aliasing via esbuild settings (using an alias plugin or domstack-supported mechanism), keeping domstack’s Preact JSX defaults unless React JSX transform is required.
- Confirm domstack’s esbuild override hook is applied to client bundles.
- Add dependency on
-
QueryClient setup
- Add
packages/web/client/lib/query-client.js:- Create a singleton
QueryClientwith default options (staleTime, retry, refetchOnWindowFocus).
- Create a singleton
- Add a tiny
QueryProviderwrapper component or helper render function used in each page entry, wrapping UI inQueryClientProvider. - Ensure
QueryClientis shared across page mounts if multiple client bundles can coexist on a page (avoid duplicate caches).
- Add
-
Bookmarks migration
- Replace
useBookmarkslocal state with TanStackuseQuery. - Query key should include:
state.user?.id(avoid cross-user cache)- URL search params (stringified in stable order)
state.sensitive,state.toread,state.starred
- Use the query
signalfor fetch aborts. - Keep pagination metadata (
before,after) in returned data (orselect). - Preserve the “top page” behavior that removes
before/afterfrom URL. - Use
keepPreviousDatato avoid list flicker when paginating.
- Replace
-
Episodes migration
- Extract a
useEpisodeshook (or updateepisodes/client.jsinline) to use TanStackuseQuery. - Include
bookmark_id+before/afterparams in the query key. - Replace
useResolvePollingusage with:refetchIntervalthat returnsfalsewhen no pending items, or- Keep
useResolvePollingbut callrefetchinstead of custom reload state.
- Extract a
-
Follow-up upgrades (optional)
- Migrate other fetch hooks (admin users, archives, search) to
useQuery. - Use
useMutationfor create/delete actions, theninvalidateQueries. - Centralize query key helpers for consistency.
- Migrate other fetch hooks (admin users, archives, search) to
- Name collisions with
useQuery(routing hook vs TanStack hook). - React 18 requirement in TanStack Query v5: confirm
preact/compatcovers required hooks (or use query-core). - Cache leakage if user identity is not part of the query key.
- Pagination params: ensure URL cleanup stays consistent with existing behavior.
- Peer deps: react-query may warn if
react/react-domaren’t installed even with aliasing.
- Build client bundles:
pnpm -C packages/web run build:domstack. - Navigate bookmarks/episodes with pagination and filters; verify no flicker.
- Confirm polling still resolves pending items.
- Verify back/forward nav updates query data correctly.