Conversation
Drops the pull_request trigger and removes develop from the push trigger. The 4-shard Playwright suite now runs only on merges to release branches (stage / main). Lightweight workflows (ci.yml, codeql.yml, docs.yml) keep their PR + push triggers so PR reviewers still see lint/build/typecheck/security results before merge. Policy doc: Workspace/knowledge/runbooks/CI_RELEASE_GATES.md. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…[slug] (+ Data Cache persistence) (#940) * perf(items): persist similar-items in Data Cache + parallel page loads The item-detail page (/[locale]/items/[slug]) renders a "Similar items" rail produced by fetchSimilarItems(), which loads every item's metadata and scores the whole catalogue. Its only cache was a per-process in-memory Map — empty on every serverless cold start and not shared across instances, so each fresh instance re-scanned the catalogue. - Add getCachedSimilarItems() wrapping fetchSimilarItems in unstable_cache (keyed by slug+locale+maxResults, pinned to the content revision, tagged content/items/item:<slug>) so the scored result is persisted in Next's Data Cache, shared across instances, and survives cold starts. Falls back to the direct call in dev / when slug missing. - page.tsx now loads the item and translations concurrently via Promise.all (they are independent), then computes similar items. No markup, ordering, or scoring change. Docs: spec-037 + log entry. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * perf(items): stream similar-items so it doesn't block first paint User reported blank/slow first paint on /[locale]/items/[slug] in both dev and prod. Root cause: the server component awaited the similar-items computation — a full-catalogue scan via fetchItems — before returning any HTML, even though that carousel sits at the very bottom of the page. So the hero, body content, and sidebar all waited on below-the-fold work. In dev (content cache disabled) the scan runs every request, which is why dev felt worst. - page.tsx no longer awaits similar items: it passes a `similarItemsPromise` down to the client tree and lets the carousel stream in. - item-detail.tsx renders the "Similar Products" rail inside its own <Suspense> boundary, unwrapping the promise with React 19 `use()` so only that subtree suspends (with a skeleton), not the whole page. An empty result still omits the section, matching the previous guard. Builds on the earlier getCachedSimilarItems (Data Cache persistence) and the item+translations Promise.all parallelization in this branch. Final rendered markup and item ordering are unchanged — only the carousel's timing changes. Docs: spec-037 + log entry updated. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * perf(stats): migrate ItemStatsSection to useQuery for shared cache Replaces local useEffect/useState data fetching with useQuery under the key ['item-activity', itemSlug, days] so the cache entry can be updated optimistically by vote, favorite, and comment mutations. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf(stats): optimistically update upvote count in Statistics card On vote/unvote onMutate, patch ['item-activity'] cache immediately so the Upvotes stat reflects the click with zero latency. Invalidates on onSuccess/onError to sync the authoritative server count. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf(stats): optimistically update favorites count in Statistics card On add/remove favorite onMutate, patch ['item-activity'] cache so the Favorites stat updates instantly. Invalidates on onSuccess/onError to reconcile with the server count. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf(stats): optimistically update comments count and avgRating in Statistics card On createComment/deleteComment onMutate, patch ['item-activity'] cache so the Comments stat changes instantly. Invalidates after onSuccess so avgRating also syncs once the server rating refetch completes. Same invalidation applied to updateComment and rating mutations. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf(items): prefetch comments server-side via HydrationBoundary Runs getCommentsByItemId in parallel with the CMS item fetch on the server, dehydrates the result, and embeds it in the HTML via HydrationBoundary. CommentsSection now renders from cache on first paint instead of waiting for a separate client-side API round-trip. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf(location): lazy-load Map SDK via next/dynamic Replaces the static Map import with a dynamic import (ssr: false) so the map provider bundle (Mapbox/Google Maps) is deferred until the browser is idle. A pulse skeleton fills the map slot while the chunk loads, keeping layout stable. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * perf(similar-products): lazy-load ItemsCarousel with next/dynamic The carousel is below the fold and not needed for first paint. Deferring its JS bundle keeps the main chunk smaller and lets the hero + content area hydrate faster. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: joel-kalema <joelkalema63@gmail.com>
* feat(auth): expose username field on current-user API response
Reads username from the client profile and includes it in the /api/current-user
response so the frontend can build profile links by username.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(settings): link identity card to profile page and wire i18n
- Wraps the UserIdentityCard in a Link pointing to /client/profile/{username}
- Replaces all hardcoded strings (section labels, status badge, name fallback)
with t() calls from the existing 'settings' namespace
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(i18n): add settings section translation keys for all 21 locales
Adds ACTIVE, SECTION_PROFILE, SECTION_APPEARANCE, and SECTION_CONTENT_AND_BILLING
to the 'settings' namespace in en.json and all 20 supported locale files
(ar, bg, de, es, fr, he, hi, id, it, ja, ko, nl, pl, pt, ru, th, tr, uk, vi, zh).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(auth): change username type from string|null to string|undefined
getProfilePath and other utilities expect username?: string (undefined, not null).
Using null caused a TS2345 type mismatch that broke the CI build.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(security): remove duplicate clientIP declaration in change-password route
clientIP was declared at the top of POST then shadowed by an identical
const inside the inner email-send try block, causing a lint/shadowing
error. Removed the redundant inner declaration.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(security): fix change-password hook swallowing real API errors
The try/catch in changePasswordApi caught the ChangePasswordError it
threw itself, then re-wrapped it using error.message (undefined on
ChangePasswordError), making every server error show "Network error
occurred". Also added cleanErrorMessage() to strip the "HTTP 4xx: "
prefix that serverClient prepends before the actual message.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(security): add GET /api/auth/security/settings route
useSecuritySettings hook called this endpoint but the route did not
exist, so SecurityOverview always rendered the error state. The new
handler returns twoFactorEnabled (clientProfiles), lastPasswordChange
(users.updatedAt), and activeSessionsCount (non-expired sessions).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(security): redesign security page to single-column SaaS layout
Replace 3-column grid with max-w-3xl single-column layout matching the
danger-zone pattern. Page header now uses the repo-standard icon badge
(rounded-lg ring-inset) and <header> tag. Security tips moved from a
sidebar card into a bottom <aside role="note"> banner. Spacing updated
to py-10 space-y-8.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(security): redesign ChangePasswordForm to match settings design system
Rebuild as a divide-y card matching the basic-info pattern. Inputs now
use the repo INPUT_CLASS (h-9, neutral-200 border, theme-primary focus
ring). Labels use LABEL_CLASS. Lock prefix icon removed; eye-toggle
kept minimal. Actions footer uses bg-neutral-50 dark:bg-white/2
rounded-b-xl. Success state is a slim emerald banner with an icon tile.
PasswordStrength uses CheckCircle2/Circle with emerald met color.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(security): redesign SecurityOverview with clean divide-y row list
Replace per-metric colored cards with a divide-y card and slim MetricRow
components. Status is shown via small pill badges (StatusBadge) using
emerald/amber/red ring-1 patterns from the repo design system. Score
ring tightened to w-10. Skeleton updated to match new row structure.
Error state uses the aside banner pattern. Refresh button uses hover-bg
instead of ghost variant.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(security): add active sessions, login history, connected accounts, and notification preferences
- Add 4 new API routes: /sessions, /login-activity, /connected-accounts, /notifications
with full CRUD (GET, DELETE/PATCH) and Zod validation
- Add [token]/route.ts for per-session revocation and [provider]/route.ts for OAuth disconnect
- Synthesise current JWT session from session.expires when DB sessions table is empty
- Fix login-activity query to match activityLogs.clientId for client users (sign-ins are
logged against clientProfile.id, not userId)
- Fix hasPassword detection to check accounts table (type='credentials') instead of
users.passwordHash, where client credentials are actually stored
- Add 4 UI cards: ActiveSessionsCard, LoginHistoryCard, ConnectedAccountsCard,
SecurityNotificationsCard — each with skeleton/error/empty states
- Rewrite use-security-settings.ts hooks to correctly extract inner body.data from
serverClient responses; add all new query hooks and mutations
- Wire the 4 cards into the client security settings page
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(security): center security page layout and replace load-more with pagination
- Add mx-auto to security page content column to match /client/settings centering
- Replace "Load more" button in LoginHistoryCard with < page numbers > pagination
- getPageNumbers helper collapses long ranges with ellipsis (max 7 slots)
- Active page gets filled pill; prev/next arrows disable at bounds
- Bar only renders when totalPages > 1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(security): move channel labels above toggles and add optimistic updates
- Move Bell/Mail channel labels from header legend to above each toggle
- Fix extra nested div in card header
- Add optimistic updates to useUpdateSecurityNotifications: toggle flips
instantly on click and rolls back on error via onMutate/onError
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(security): translate ChangePasswordForm with next-intl
- Wire useTranslations('settings.SECURITY_PAGE.CHANGE_PASSWORD_FORM')
into ChangePasswordForm; all visible strings now use t()
- Build Zod schema and password requirements array inside useMemo so
validation messages are translated at runtime
- Pass strengthLabels and requirements as props to PasswordStrength;
pass showLabel/hideLabel to PasswordField
- Add missing keys to all 21 locale files: SECTION_TITLE,
SECTION_DESCRIPTION, STRENGTH.*, REQUIREMENTS.*, SUCCESS_TITLE,
SUCCESS_DESCRIPTION (English fallback for non-English locales)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix the button color
* fix(security): translate ChangePasswordForm using only existing message keys
- Revert all 21 message file reformats from the previous commit; no new
keys added so the diff is now just the component
- Use useTranslations('settings.SECURITY_PAGE') to access both
CHANGE_PASSWORD.TITLE/DESCRIPTION (section header) and
CHANGE_PASSWORD_FORM.* (labels, placeholders, buttons, validation)
- Strength bar labels and password requirements kept hardcoded — no
equivalent keys exist in the catalogue yet
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix the button color
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…mplate into develop
* feat(profile): match followers page UX to following page Extract the FollowPersonCard from the following page into a shared _follow-person-card.tsx, then rewrite the followers page to use the same card grid, header, empty state, and numbered pagination so both lists feel like the same product. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * fix(profile): hide self-row action on followers page Codex P2 on PR #946: the shared FollowPersonCard always rendered a disabled "Following" pill on the viewer's own row, which read as "you follow yourself" on the /followers page (the original followers page omitted the action entirely for isViewer). Add a selfRowMode prop ('following-pill' | 'hide-action', default 'following-pill' to preserve /following behavior) and pass 'hide-action' from /followers so the viewer's own card has no action chip. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
#947) * fix(users): live search without page reload + community link in profile menu - Extract sticky toolbar to UsersToolbar client component; search form now uses router.push() with a 350ms debounce so results update on every keystroke without a hard page reload. - Add /client/users (Community) entry to ProfileButton dropdown menu for non-admin users, with translations wired through the translations useMemo. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * i18n: add usersDirectory dropdown translations to all 20 language files Add HERO_TITLE and HERO_SUBTITLE keys under usersDirectory to ar, bg, de, es, fr, he, hi, id, it, ja, ko, nl, pl, pt, ru, th, tr, uk, vi, zh so the Community entry in the ProfileButton dropdown renders in the user's locale. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(profile-menu): match logout button icon size to menu items, remove hover Zap icon - Icon container: w-8 h-8 rounded-xl mr-4 → w-6 h-6 rounded-md mr-3 - Icon: h-4 w-4 → h-3 w-3 (LogOut + Loader2) - Padding: px-4 py-3 → px-3 py-2 - Remove Zap icon that appeared after logout text on hover - Drop unused Zap import Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
Bumps [axios](https://github.com/axios/axios) from 1.15.2 to 1.16.0. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](axios/axios@v1.15.2...v1.16.0) --- updated-dependencies: - dependency-name: axios dependency-version: 1.16.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com>
Bumps [axios](https://github.com/axios/axios) from 1.15.2 to 1.16.0. - [Release notes](https://github.com/axios/axios/releases) - [Changelog](https://github.com/axios/axios/blob/v1.x/CHANGELOG.md) - [Commits](axios/axios@v1.15.2...v1.16.0) --- updated-dependencies: - dependency-name: axios dependency-version: 1.16.0 dependency-type: direct:production ... Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
docs(deployment): document Neon Vercel-Marketplace DB setup + preview-branch cost warning The Vercel deploy guide only mentioned DATABASE_URL as a manual env var. Add a "Database (Neon via the Vercel Marketplace)" section covering the recommended integration settings — env var prefix `DATABASE`, Production branch ON, and **Preview branch OFF** — with a warning that a per-preview DB branch is created for every pushed branch/PR and can balloon into hundreds of branches + a large bill. Logged in docs/log.md. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> @
* fix(auth): redirect to sign-in after account deletion
deleteAccount now returns success + a redirect path after signOut
instead of calling next/navigation's redirect(), which doesn't
propagate through useActionState. The delete-account modal performs
a full page reload to /auth/signin so middleware picks up the
cleared session cookie.
* style(settings): center danger zone page content
Add mx-auto to the max-w-3xl content column so it's centered on
wider viewports instead of sitting flush left.
* i18n(settings): translate danger zone keys for all locales
Replace the English-fallback settings.DANGER_ZONE_PAGE strings
(title, intro, delete-account card, confirmation modal, and errors)
with localized copy across all 20 non-English locales, preserving
the {email} placeholder and existing key structure.
* fix(settings): align danger zone inputs with theme colors and fix autofill tint
Use theme-primary focus colors for the delete-account confirmation inputs,
and move the browser autofill background override into globals.scss (the
stylesheet actually imported) so autofilled fields no longer show the
browser's default yellow/blue tint.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(notifications): include profile actionUrl on new-follower notifications
Lets clicking a "New follower" notification redirect to the follower's
profile instead of doing nothing.
* fix(notifications): derive profile link for legacy follow notifications
Falls back to /client/profile/{followerUsername} when an older
user_followed notification has no actionUrl stored in its data, so
clicking it still navigates (in both the dropdown and notifications page).
* fix(notifications): hide unread badge while dropdown is open and fix tooltip i18n
The bell's unread-count badge no longer shows once the notifications
dropdown is open, and the tooltip/aria label now uses next-intl's
ICU interpolation instead of a manual {n} string replace.
* fix(notifications): clarify byTab stats are has-unread signals, not counts
* fix(notifications): derive byTab unread signals and add system-unread aggregate
* fix(notifications): add hasNew translation for tab indicator
* fix(notifications): replace numeric tab badges with unread dot indicator
* fix(notifications): make row actions reachable on touch devices
* fix(notifications): add query-key and optimistic stats cache helpers
* fix(notifications): keep SSE-pushed items in correct tab caches and update stats instantly
* fix(notifications): drop read items from unread tab cache and update unread badge instantly
* i18n(notifications): add bell tooltip translation for ar
* i18n(notifications): add bell tooltip translation for bg
* i18n(notifications): add bell tooltip translation for de
* i18n(notifications): add bell tooltip translation for es
* i18n(notifications): add bell tooltip translation for fr
* i18n(notifications): add bell tooltip translation for he
* i18n(notifications): add bell tooltip translation for hi
* i18n(notifications): add bell tooltip translation for id
* i18n(notifications): add bell tooltip translation for it
* i18n(notifications): add bell tooltip translation for ja
* i18n(notifications): add bell tooltip translation for ko
* i18n(notifications): add bell tooltip translation for nl
* i18n(notifications): add bell tooltip translation for pl
* i18n(notifications): add bell tooltip translation for pt
* i18n(notifications): add bell tooltip translation for ru
* i18n(notifications): add bell tooltip translation for th
* i18n(notifications): add bell tooltip translation for tr
* i18n(notifications): add bell tooltip translation for uk
* i18n(notifications): add bell tooltip translation for vi
* i18n(notifications): add bell tooltip translation for zh
docs(deployment): Neon Vercel-Marketplace DB setup + preview-branch cost warning
… template (#954) The k8s deploy manifest template defined readinessProbe/livenessProbe on `/` with no timeoutSeconds, so both inherited Kubernetes' 1-second default. A server-rendered `/` on a small shared node routinely exceeds 1s, so the liveness probe failed its default 3 attempts and kubelet killed the container in a permanent restart loop (observed: 460+ restarts, exit 143, on the first k8s-deployed Work awesome-compliance-automation-website — never an OOM). Add an explicit startupProbe (~5 min budget for first response before liveness/readiness apply) and set timeoutSeconds: 5 + failureThreshold on readiness (3) and liveness (6). No app code or image change. Docs: spec 038, index row, log entry (repo Definition of Done). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
#957) k8s-deployed sites 500 at first render (`[auth] AUTH_SECRET must be set in production`) — the Deployment only carried NODE_ENV/PORT/HOSTNAME. Adds a deploy_k8s.yaml step that materializes a `${WORK_SLUG}-runtime-env` Secret from the AUTH_SECRET/COOKIE_SECRET/COOKIE_SECURE/DATABASE_URL secrets the platform pushes (+ NEXT_PUBLIC_APP_URL/COOKIE_DOMAIN from the ingress host), and deployment.yaml mounts it via `envFrom` (optional). No-op when absent. Platform half: ever-works#1306 (DeployService.ensureRuntimeEnv + WorkRuntimeEnvService). Docs: spec 040 + index + log (Definition of Done). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
* feat(item-detail): add SharePopover with Copy link, X and LinkedIn options
Replaces the single share button with a popover offering three actions:
copy the directory page URL, share on Twitter/X, and share on LinkedIn.
Uses existing COPY_LINK, SHARE_ON_X and SHARE_ON_LINKEDIN i18n keys.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(item-detail): add StickyMobileCTA fixed bottom bar for mobile
Slides up after 200px scroll on screens smaller than lg, keeping the
Visit Website CTA accessible without forcing users to scroll back to top.
Hidden on lg+ breakpoints to avoid overlap with the desktop sidebar.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(utils): add extractHeadings utility for server-side ToC generation
Parses h2/h3 headings from raw Markdown strings using regex, strips
inline formatting, and produces URL-safe IDs via the same pipeline used
by the rehypeAddHeadingIds plugin so anchor links resolve correctly.
Capped at 12 headings to keep the ToC usable.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(item-detail): add floating glass TableOfContents widget
Fixed right-edge widget with frosted-glass styling (backdrop-blur-2xl,
bg-white/70 dark:bg-black/50). Collapsed state shows a List icon and
per-heading progress dots. On hover the panel slides in from the right
with the full heading list and IntersectionObserver active highlighting.
Hidden on mobile to avoid overlap with StickyMobileCTA.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(item-detail): add rehypeAddHeadingIds plugin to ServerItemContent
Inline rehype plugin walks the HAST tree and sets id attributes on h2/h3
elements using the same slugification as extractHeadings, so ToC anchor
links resolve to the correct rendered heading elements.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(item-detail): wire up all UX improvements in ItemDetail
- Replace inline share button with SharePopover component
- Replace Published label key with LAST_UPDATED (matches updated_at value)
- Mount StickyMobileCTA below the page container
- Mount floating TableOfContents (lg+ only) outside the Container
- Thread headings prop through ItemDetail and ItemDetailContent
- Remove unused toast and Share2 imports
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(items/page): extract headings and pass to ItemDetailWrapper
Calls extractHeadings on the raw MDX content string server-side and
passes the result as the headings prop to ItemDetailWrapper, enabling
the floating TableOfContents to render without any client-side fetch.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* i18n(en): add LAST_UPDATED and TABLE_OF_CONTENTS keys to itemDetail namespace
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* i18n(locales): add LAST_UPDATED translation to all 20 locale files
Adds translated "Last updated" strings to the itemDetail namespace in
ar, bg, de, es, fr, he, hi, id, it, ja, ko, nl, pl, pt, ru, th, tr,
uk, vi and zh to match the en.json LAST_UPDATED key.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* i18n(ar): translate TABLE_OF_CONTENTS — في هذه الصفحة
* i18n(bg): translate TABLE_OF_CONTENTS — На тази страница
* i18n(de): translate TABLE_OF_CONTENTS — Auf dieser Seite
* i18n(es): translate TABLE_OF_CONTENTS — En esta página
* i18n(fr): translate TABLE_OF_CONTENTS — Sur cette page
* i18n(he): translate TABLE_OF_CONTENTS — בעמוד זה
* i18n(hi): translate TABLE_OF_CONTENTS — इस पृष्ठ पर
* i18n(id): translate TABLE_OF_CONTENTS — Di halaman ini
* i18n(it): translate TABLE_OF_CONTENTS — In questa pagina
* i18n(ja): translate TABLE_OF_CONTENTS — このページの内容
* i18n(ko): translate TABLE_OF_CONTENTS — 이 페이지에서
* i18n(nl): translate TABLE_OF_CONTENTS — Op deze pagina
* i18n(pl): translate TABLE_OF_CONTENTS — Na tej stronie
* i18n(pt): translate TABLE_OF_CONTENTS — Nesta página
* i18n(ru): translate TABLE_OF_CONTENTS — На этой странице
* i18n(th): translate TABLE_OF_CONTENTS — ในหน้านี้
* i18n(tr): translate TABLE_OF_CONTENTS — Bu sayfada
* i18n(uk): translate TABLE_OF_CONTENTS — На цій сторінці
* i18n(vi): translate TABLE_OF_CONTENTS — Trên trang này
* i18n(zh): translate TABLE_OF_CONTENTS — 本页内容
* fix(share-popover): resolve empty URL bug on SSR and fix share link format
Two bugs fixed:
1. currentUrl was computed at render time with typeof window check — on the
server this evaluates to '' so Twitter/LinkedIn href attributes were baked
with an empty URL before hydration. Now captured in useEffect (client-only).
2. Social share links were static <a href> elements constructed before mount.
Replaced with onClick handlers that call window.location.href at click time,
guaranteeing the freshest URL regardless of SPA navigation.
Twitter format changed to text="{name} — {url}" (single param, no duplication).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* revert(item-detail): restore original share button, remove share-popover
Share button code is restored exactly as it was on develop — inline button
copying meta.source_url || window.location.href with toast feedback.
Removes the share-popover.tsx component that was created in error without
first checking the existing ShareButton component already in the codebase.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* refactor(pricing): minimalist redesign matching 21st.dev aesthetic Restyles the /pricing page UI to a cleaner, more minimal look while keeping all existing behavior (billing toggle, Pay Now/Pay Later flow, payment provider selection, payment modal, sponsor section, trust grid, selected-plan continue CTA, i18n strings, analytics). - Header: large left-aligned monospace headline + concise subtitle (drops the gradient subheading and animated trust pills). - Billing toggle: switches to the existing BillingToggle preset, with a '-20%' yearly badge. - Plan cards: flat dark-first cards with a subtle border, inline 'Most Popular' chip on the highlighted plan, plain check/X feature list, and a full-width pill CTA (solid white for the highlighted plan in dark mode, ghost for the rest). - Removes heavy decoration: DecorativeBg overlay, radar-circle sponsor animation, multi-layer card glow, and the negative top offset. - Sponsor + trust blocks restyled as compact bordered cards. Functionality is unchanged: identical hook usage, checkout flow, modals, locale handling, and conditional rendering for review mode and non-payment-configured deployments. * refactor(pricing): revert headline to default sans-serif font Keep the original Geist Sans font on the /pricing page H1 instead of forcing Geist Mono. The monospace look was specific to the 21st.dev screenshot; the rest of the site keeps a sans-serif headline. * docs(pricing): add before/after screenshots of the pricing redesign Adds dark and light preview screenshots of the redesigned /pricing page under docs/assets/pricing-redesign/, referenced from the PR description for PR #949. * refactor(pricing): hoist Pay Now/Pay Later toggle into card header Restores the original placement of the payment-timing ToggleGroup (and its info button) to the top-right of the Standard/Premium plan cards, next to the title. In the prior commit it had moved below the price, which made it visually subordinate. The "Most Popular" chip now sits inline with the title rather than competing for the top-right slot. No behavior changes; the toggle still drives the same selectedFlow / onFlowChange / onOpenModal props. Updates the dark/light preview screenshots referenced from the PR description to match. * refactor(pricing): cleaner billing toggle (no doubled border) Replaces the shared BillingToggle preset (variant="modern") with a local inline pill toggle on the /pricing page. The shared preset stacked a border on both the container and the sliding indicator, which produced a chunky doubled outline. The inline version uses a single subtle pill background with a lighter active button — no container border, no sliding indicator, same behaviour. The "-20%" badge is now a flat emerald chip (10px text, tinted background) rendered inline inside the yearly button. Shared BillingToggle / ToggleGroup component is unchanged.
…ace (#955) The authenticated write-flow e2e specs timed out at ~30s in CI: - admin/collections.spec.ts › create a new collection - client/submit-and-manage.spec.ts › submit a new item - client/favorites-toggle.spec.ts › add/remove a favorite Causes & fixes (no prod behaviour change, no tests skipped): 1) Collection/Item git services pull() on init and push() after each write to the content remote. In CI the .content stub's origin is an unreachable placeholder (401) and isomorphic-git has no HTTP timeout, so the round-trips blocked the POST past the redirect/modal wait. Added isContentGitRemoteDisabled() (CI / CONTENT_GIT_OFFLINE) and guarded syncWithRemote + push in both services. Runtime (no CI) still pushes. Mirrors the read-path short-circuit in d883149. 2) getGitService() memoized with no in-flight lock → 2 CI workers could init isomorphic-git on the same .content/.git at once. Added an init promise lock to item.repository.ts and collection.repository.ts. 3) Favorites are DB-backed; an early click before useCurrentUser resolved opened the login modal whose backdrop then ate clicks. Hardened clickFavorite() to dismiss the modal and only count a click that flips the aria-label. Docs: spec 039 + index + log (repo Definition of Done). Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
This pull request is abnormally large and would use a significant amount of tokens to review. If you still wish to review it, comment "augment review" and we will review it. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cascade
develop->stage.Included PRs
Plus parallel overnight-batch tasks (pr951 esbuild, pr945 review).
DO NOT delete
developafter merge.