Ensures the UpgradeBlockProvider waits for both user and organization
data before computing the block reason, preventing premature paywall
flash. Temporary users are never blocked.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
useUser() throws when the store is null (before user data is fetched).
Switch to useMaybeUser() which safely returns null.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
On mobile, the sidebar was 192px wide (w-48) and could appear collapsed (icons-only)
depending on prior desktop state. This introduces effectivelyCollapsed to always force
expanded mode when the mobile overlay is open, and uses a narrower w-40 (160px) width
to reduce screen coverage on small devices like iPhone SE (375px).
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Add flex-wrap to the member action row (date + remove button) and the
header badge/language selector row so they wrap gracefully on narrow
screens without affecting desktop layout.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Cloudflare serves static assets before the worker runs, so the icon
redirect logic was never reached. Renamed the default icon files to
default-* prefix. The worker now handles all requests for the original
icon paths: redirects to org-specific icons when cookie is set, or to
the renamed defaults otherwise.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
iOS uses the apple-touch-icon link tag for the home screen icon, not
the manifest. The worker now intercepts requests for apple-touch-icon
and favicon PNGs, redirecting to the org-specific version from R2
when the x-org-id cookie is set.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Icons are stored in the web-assets R2 bucket which is already served
via assets.xtablo.com, same as user avatars. No need to proxy through
the API endpoint.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
The API runs on a separate domain from the frontend. Org icon URLs
in the manifest and settings page need the full API base URL.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Stack avatar and org logo sections vertically on mobile, wrap header badges/language selector, and make member list items stack on small screens.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Add horizontal padding to page containers so cards don't bleed to the
edges on small screens, reduce card inner padding on mobile, scale down
headings at mobile breakpoints, and change the first/last name grid from
a fixed two-column layout to responsive (single column on mobile).
Replace the fixed-width form class (w-95) with w-full on the login form.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Adds parseOrgIdFromCookie and buildManifest exports to the worker, intercepting /manifest.webmanifest to serve org-specific PWA icon URLs based on the x-org-id cookie. Removes legacy @ts-nocheck and biome-ignore-file comments.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Make project card grids responsive (single column on mobile, 2 cols on sm)
- Remove fixed w-56 card width so cards fill available space on mobile
- Convert modals to bottom-sheet style on mobile (items-end, rounded-t-2xl)
- Add max-h-[90vh] + overflow-y-auto to modals for small screens
- Increase touch targets to min 44px on action buttons and interactive elements
- Refactor DashboardTaskList rows from rigid grid to flexible layout
- Remove min-w-[600px] wrapper that forced horizontal scroll on task list
- Make tab navigation horizontally scrollable instead of wrapping on mobile
- Reduce left padding on etape child tasks for narrow screens
- Stack modal action buttons vertically on mobile (flex-col-reverse)
- Add responsive text sizing for headings and dates
- Fix share dialog invite input to stack on mobile
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Add backdrop overlay with tap-to-dismiss, enforce 44px touch targets on the
toggle button, auto-close on route change, clean up z-index layering, remove
duplicate translate logic, and respect safe-area insets for standalone PWA mode.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
- Add pnpm packageExtensions to declare zod as peer dep of @hookform/resolvers
(the package imports zod/v4/core but doesn't declare the peer dependency)
- Raise workbox maximumFileSizeToCacheInBytes to 5MB for large app bundle
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Add workbox-window as direct dependency and set injectRegister: false
to prevent conflict between vite-plugin-pwa and @cloudflare/vite-plugin.
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
UserStoreProvider was switching between three different return structures
(LoadingSpinner / children directly / Context.Provider wrapping children),
causing full fiber tree restructures in React 19 concurrent mode. When
batched with other state updates (e.g. UpgradeBlockContext loading),
React called insertBefore with a reference node already detached from
the DOM.
- Always render UserStoreContext.Provider so tree structure is stable;
spinner vs children toggle happens inside it
- Use useRef to hold a stable Zustand store (update via setState instead
of recreating on every render)
- Move inline <style> from App.tsx JSX into main.css to avoid React 19
style-tag edge cases with conditional sibling rendering
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Adds a BEFORE trigger and CHECK constraint on profiles to guarantee that
is_temporary cannot coexist with a paid plan (solo, team, or annual),
regardless of which code path performs the update.
Also back-fills any existing inconsistent rows.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>