Skip to content

Fix proxied video poster loading for blocked booru CDNs - #146

Open
AlejandroAkbal wants to merge 7 commits into
mainfrom
cursor/88b92129
Open

Fix proxied video poster loading for blocked booru CDNs#146
AlejandroAkbal wants to merge 7 commits into
mainfrom
cursor/88b92129

Conversation

@AlejandroAkbal

@AlejandroAkbal AlejandroAkbal commented Jun 23, 2026

Copy link
Copy Markdown
Member

Summary

  • Route video preview thumbnails (preview_file) through imgproxy for Premium users and SSR LCP posts, matching the existing static-image proxy rules.
  • Add a hidden poster preload image so Premium users fall back to the CORS proxy when imgproxy still fails; <video poster> alone does not reliably emit load errors.
  • Add offline video mock data and tests for the imgproxy poster path.

Out of scope (follow-up)

  • PocketBase authStore.onChangeuseState sync (needed for reliable Premium fallback browser tests, but unrelated to the core imgproxy fix).

Test plan

  • pnpm vitest run test/assets/get-imgproxy-url.test.ts test/pages/posts-video-proxy.test.ts
  • Manually verify a video post from a blocked booru shows its poster for Premium and SSR first posts
  • Confirm Premium video-src CORS fallback on playback failure (manual; auth timing not covered by browser tests in this PR)

Summary by CodeRabbit

  • New Features

    • Enhanced video preview loading with intelligent proxy-based poster resolution for more reliable rendering in server-rendered and LCP scenarios.
  • Bug Fixes

    • Improved retry behavior for video and animated GIF poster/media loading when direct fetch fails, including separate handling for CORS-proxy and poster vs playback errors.
    • Aligned poster preloading and the actual video element to reduce source mismatches.
  • Tests

    • Added automated coverage for proxied poster URLs and an offline video page SSR scenario using mock data and page routing.

Route video preview thumbnails through imgproxy under the same rules as feed images, add a premium CORS-proxy fallback when posters still fail, and keep PocketBase auth state in sync so premium retries run reliably.
@coderabbitai

coderabbitai Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 03b4f5ba-c3f7-4f8a-a08e-b9a469ca45e1

📥 Commits

Reviewing files that changed from the base of the PR and between 461e56d and 6a67c19.

📒 Files selected for processing (1)
  • app/components/pages/posts/post/PostMedia.vue
📜 Recent review details
🧰 Additional context used
📓 Path-based instructions (6)
app/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

app/**/*.{vue,ts,tsx}: Use Nuxt 4 with Vue 3 and TypeScript for the frontend application
Use useLazyToast() to lazy-load vue-sonner; wait for ClientToaster to mount before calling toast.* using a proper async wait instead of plain nextTick()
Build reordered array synchronously instead of reading VueUse moveArrayElement() result before nextTick for state immediately persisted

Files:

  • app/components/pages/posts/post/PostMedia.vue
**/*.{vue,ts,tsx,js,jsx,json,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier for formatting with 120-char print width, no semicolons, single quotes, trailing commas removed, and single attribute per line in Vue templates

Files:

  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Use Nuxt flat ESLint via @nuxt/eslint for linting

Files:

  • app/components/pages/posts/post/PostMedia.vue
app/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

app/components/**/*.vue: Register Vue components without path prefix using pathPrefix: false in nuxt.config.ts; import them as not <Input/DomainSelector>
Auto-import components from app/components/ flat structure without folder prefix
Use custom imgproxy provider for images; generate images at 1x density only in webp format to reduce bandwidth
Use @nuxt/image v2 preload API (preload: { fetchPriority: 'high' }) for image preload priority instead of patching rendered HTML in Nitro
Use Nuxt Lazy* components, dynamic imports, or similarly deferred boundaries for components and composables only needed after user interaction (menu, sheet, dialog)

Files:

  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Define locales in config/i18n.ts as the single source of truth; do not hardcode locale lists in application code
Use PocketBase batch writes for multi-record replacement/reorder operations instead of one HTTP write per changed row

Files:

  • app/components/pages/posts/post/PostMedia.vue
app/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

app/**/*.vue: Use project.urls.production for canonical URLs to point to production (https://r34.app/...) even when served from clone domains
Keep breadcrumb Schema.org source item URLs local/locale-relative; do not convert to project.urls.production since nuxt-schema-org resolves against site.url
When triggering a premium prompt from a nested dialog/bottom sheet, let the sheet owner close local UI, open the prompt, and restore UI after prompt closes
Premium auth transitions are reload-backed in dashboard/sign-in flow; rely on page reload to clear memory state instead of tracking PocketBase user ids in useState

Files:

  • app/components/pages/posts/post/PostMedia.vue
🔇 Additional comments (1)
app/components/pages/posts/post/PostMedia.vue (1)

4-4: LGTM!

Also applies to: 39-80, 91-99, 226-226, 254-254, 396-447, 469-490, 659-659, 686-686, 704-704, 727-727, 792-797, 810-811


📝 Walkthrough

Walkthrough

Adds a getImgproxyUrl helper, updates PostMedia.vue to proxy video poster and media URLs with retry handling, and adds offline-video mock data plus tests for the poster proxy flow.

Changes

Video poster proxy via imgproxy

Layer / File(s) Summary
getImgproxyUrl helper and unit test
app/assets/js/nuxt-image/get-imgproxy-url.ts, test/assets/get-imgproxy-url.test.ts
Exports getImgproxyUrl(src) from imgproxyProvider().getImage using project.imgproxy config, and verifies the returned URL decodes to the expected nginx-proxy fetch target.
PostMedia.vue poster and playback proxy refactor
app/components/pages/posts/post/PostMedia.vue
Imports getImgproxyUrl, introduces mediaUrl, gifPosterUrl, poster proxy state, and videoPosterUrl, updates preload and template bindings to use the new URLs, and rewrites media error handling and reload behavior for video, poster, and GIF targets.
Offline-video mock data and test coverage
test/pages/posts.mock-data.ts, test/server-mocks/plugin.ts, test/pages/posts-video-proxy.test.ts
Adds an offline_video_test mock posts response, routes that tag in the server mock plugin, and adds a page test that decodes imgproxy poster URLs and checks the video poster value on the offline video page.

Possibly related PRs

  • Rule-34/App#131: Added media proxy routing support that getImgproxyUrl() now uses through project.imgproxy.mediaProxyUrls.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: fixing proxied video poster loading for blocked booru CDNs.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch cursor/88b92129
⚔️ Resolve merge conflicts
  • Resolve merge conflict in branch cursor/88b92129
✨ Simplify code
  • Create PR with simplified code
  • Commit simplified code in branch cursor/88b92129

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/components/pages/posts/post/PostMedia.vue`:
- Around line 465-473: The onVideoPlaybackError function has early return
conditions that exit without setting hasError.value to true, causing broken
video playback to display with no error UI. When the early return conditions are
triggered (for non-premium users, when hasError is already true, when the event
target is invalid, or when a proxy retry has already been attempted), the
function returns silently without indicating an error state. Set hasError.value
= true before each early return statement in the onVideoPlaybackError function
to ensure that failed video playback properly triggers the error UI fallback for
users who cannot retry with a proxy or are not premium members.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1dfcf435-a45c-441f-8a9f-d5e346b42820

📥 Commits

Reviewing files that changed from the base of the PR and between 8dc1ac4 and 8756b26.

📒 Files selected for processing (10)
  • app/assets/js/nuxt-image/get-imgproxy-url.ts
  • app/components/pages/posts/post/PostMedia.vue
  • app/composables/usePocketbase.ts
  • app/composables/useUserData.ts
  • app/plugins/030.pocketbase.ts
  • test/assets/get-imgproxy-url.test.ts
  • test/pages/posts-video-proxy.test.ts
  • test/pages/posts.mock-data.ts
  • test/pages/posts.test.ts
  • test/server-mocks/plugin.ts
💤 Files with no reviewable changes (1)
  • app/composables/usePocketbase.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (14)
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Use Nuxt 4 with Vue 3 and TypeScript as the primary framework

Files:

  • app/composables/useUserData.ts
  • test/assets/get-imgproxy-url.test.ts
  • test/pages/posts-video-proxy.test.ts
  • test/server-mocks/plugin.ts
  • test/pages/posts.test.ts
  • app/assets/js/nuxt-image/get-imgproxy-url.ts
  • test/pages/posts.mock-data.ts
  • app/plugins/030.pocketbase.ts
  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,js,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,vue}: Use Prettier formatting with 120-char print width, no semicolons, single quotes, trailing commas removed, and single attribute per line in Vue templates
Use Nuxt flat ESLint (@nuxt/eslint) for linting

Files:

  • app/composables/useUserData.ts
  • test/assets/get-imgproxy-url.test.ts
  • test/pages/posts-video-proxy.test.ts
  • test/server-mocks/plugin.ts
  • test/pages/posts.test.ts
  • app/assets/js/nuxt-image/get-imgproxy-url.ts
  • test/pages/posts.mock-data.ts
  • app/plugins/030.pocketbase.ts
  • app/components/pages/posts/post/PostMedia.vue
{app/composables/**/*.ts,app/components/**/*.vue}

📄 CodeRabbit inference engine (AGENTS.md)

{app/composables/**/*.ts,app/components/**/*.vue}: Use useLazyToast() to lazy-load vue-sonner and render ClientToaster; wait for ClientToaster to mount before calling toast.* (use plain nextTick() after lazy loading)
Use PocketBase batch writes for multi-record replacement/reorder operations; reordering positioned records should not emit one HTTP write per changed row
VueUse moveArrayElement() applies move on nextTick; for immediately persisted state, build reordered array synchronously instead of reading before VueUse applies move

Files:

  • app/composables/useUserData.ts
  • app/components/pages/posts/post/PostMedia.vue
{app/components/**/*.vue,app/composables/**/*.ts}

📄 CodeRabbit inference engine (AGENTS.md)

{app/components/**/*.vue,app/composables/**/*.ts}: Preserve interaction-gated loading for post UI features using Nuxt Lazy* components, dynamic imports, or deferred boundaries instead of entering first-load route chunk
PocketBase realtime subscriptions echo local writes; when debugging sync performance, inspect real network traces and separate write requests from realtime-triggered refreshes

Files:

  • app/composables/useUserData.ts
  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,js}

📄 CodeRabbit inference engine (AGENTS.md)

For URL validation/parsing, prefer URL.canParse() or URL.parse() over constructor try/catch; use URL.parse() when parsed object is needed

Files:

  • app/composables/useUserData.ts
  • test/assets/get-imgproxy-url.test.ts
  • test/pages/posts-video-proxy.test.ts
  • test/server-mocks/plugin.ts
  • test/pages/posts.test.ts
  • app/assets/js/nuxt-image/get-imgproxy-url.ts
  • test/pages/posts.mock-data.ts
  • app/plugins/030.pocketbase.ts
{app/components/**/*.vue,app/composables/**/*.ts,app/pages/**/premium/**/*.vue}

📄 CodeRabbit inference engine (AGENTS.md)

Empty cloud state means no user-authored cloud override; do not seed PocketBase from local defaults during initial load, only write premium cloud records after explicit user edits

Files:

  • app/composables/useUserData.ts
  • app/components/pages/posts/post/PostMedia.vue
test/**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

test/**/*.{ts,tsx}: Use Vitest + @nuxt/test-utils with Playwright browser mode for testing
Tests use @nuxt/test-utils with Playwright inside describe blocks calling await setup({ browser: true })
Import debugBrowserOptions from test/helper.ts for headful playback with slowMo in debug mode
Plain Vitest suites importing app modules directly do not get Nuxt runtime alias resolution; keep repository/pure modules importable through relative paths or import directly from app path
@nuxt/test-utils $fetch has no .raw method; use fetch from @nuxt/test-utils with { redirect: 'manual' } for redirect status and Location headers
Locale-related tests should import localeCodes, prefixedLocaleCodes, and removedLocaleCodes from config/i18n instead of hardcoding locale lists

Files:

  • test/assets/get-imgproxy-url.test.ts
  • test/pages/posts-video-proxy.test.ts
  • test/server-mocks/plugin.ts
  • test/pages/posts.test.ts
  • test/pages/posts.mock-data.ts
{nuxt.config.ts,test/server-mocks/plugin.ts}

📄 CodeRabbit inference engine (AGENTS.md)

Mock server-side API calls via test-only Nitro plugin at test/server-mocks/plugin.ts, injected through nuxt.config.ts → $test.nitro.plugins

Files:

  • test/server-mocks/plugin.ts
app/plugins/**/*.ts

📄 CodeRabbit inference engine (AGENTS.md)

Keep global TanStack Vue Query plugin unless a larger measured payoff appears

Files:

  • app/plugins/030.pocketbase.ts
app/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

app/components/**/*.vue: Register components without path prefix using pathPrefix: false in nuxt.config.ts; import as not <Input/DomainSelector>
Keep @formkit/auto-animate route-scoped unless used broadly; local vAutoAnimate imports on premium CSR pages saved about 3 KB gzip

Files:

  • app/components/pages/posts/post/PostMedia.vue
{app/pages/**/*.vue,app/components/**/*.vue}

📄 CodeRabbit inference engine (AGENTS.md)

{app/pages/**/*.vue,app/components/**/*.vue}: Keep schema.org breadcrumb source item URLs as local/locale-relative; do not convert to project.urls.production because nuxt-schema-org resolves JSON-LD against site.url
Use flat bracket keys (filter[sort], filter[rating], etc.) for query filters with Vue Router's default query handling; do not re-add qs unless URL contract changes

Files:

  • app/components/pages/posts/post/PostMedia.vue
{nuxt.config.ts,app/components/**/*.vue,app/pages/**/*.vue}

📄 CodeRabbit inference engine (AGENTS.md)

Use @nuxt/image v2 module API with preload: { fetchPriority: 'high' } for image preload priority instead of patching rendered HTML in Nitro

Files:

  • app/components/pages/posts/post/PostMedia.vue
{server/api/**/*.ts,app/components/**/*.vue}

📄 CodeRabbit inference engine (AGENTS.md)

Route Gelbooru media through Cloudflare Worker media proxies before imgproxy with clean upstream headers (no CF-, X-Forwarded-, cookies, auth)

Files:

  • app/components/pages/posts/post/PostMedia.vue
{app/components/**/*.vue,app/pages/**/*.vue}

📄 CodeRabbit inference engine (AGENTS.md)

When a premium prompt is triggered from inside a bottom sheet/dialog, let the sheet/dialog owner close local UI, open the premium prompt, and restore UI after prompt closes

Files:

  • app/components/pages/posts/post/PostMedia.vue
🧠 Learnings (1)
📚 Learning: 2026-06-22T07:50:54.935Z
Learnt from: AlejandroAkbal
Repo: Rule-34/App PR: 144
File: test/server/fix-canonical-queries.test.ts:174-178
Timestamp: 2026-06-22T07:50:54.935Z
Learning: In this Nuxt 3/4 project using `nuxt-schema-org` (v6.2.1), breadcrumb `source`/`itemListElement` URL values may be provided via `localePath()` (locale-relative in source code), but `nuxt-schema-org` renders JSON-LD with production-absolute URLs using `site.url` during schema rendering. When asserting JSON-LD breadcrumb `itemListElement` URLs in tests, expect production-absolute URLs (e.g., prefix with `project.urls.production.origin`), not the locale-relative `localePath()` forms. Do not flag production-absolute URL strings in JSON-LD breadcrumb tests as incorrect.

Applied to files:

  • test/assets/get-imgproxy-url.test.ts
  • test/pages/posts-video-proxy.test.ts
  • test/pages/posts.test.ts
🔇 Additional comments (10)
test/pages/posts.mock-data.ts (1)

3837-3879: LGTM!

test/server-mocks/plugin.ts (1)

10-10: LGTM!

Also applies to: 76-79

test/pages/posts.test.ts (2)

3-7: LGTM!


199-200: LGTM!

test/pages/posts-video-proxy.test.ts (1)

1-110: 📐 Maintainability & Code Quality

Well-structured E2E tests for video poster proxying.

The test coverage is comprehensive:

  1. Premium user fallback to CORS proxy on imgproxy failure
  2. SSR imgproxy poster routing for blocked CDNs

The test helpers (decodeImgproxySourceUrl, expectPosterSrcToReference, getPostVideoPoster) follow the patterns established in posts.test.ts and provide clear, reusable logic.

app/plugins/030.pocketbase.ts (1)

53-77: LGTM!

app/composables/useUserData.ts (1)

6-16: LGTM!

app/assets/js/nuxt-image/get-imgproxy-url.ts (1)

1-12: LGTM!

test/assets/get-imgproxy-url.test.ts (1)

1-30: LGTM!

app/components/pages/posts/post/PostMedia.vue (1)

4-67: LGTM!

Also applies to: 456-463, 483-483, 787-796

Comment thread app/components/pages/posts/post/PostMedia.vue Outdated
Revert PocketBase auth sync and premium browser tests that depended on it; keep imgproxy poster coverage.
Restore the non-premium and post-retry failure path that was lost when video errors moved to onVideoPlaybackError.
@AlejandroAkbal

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Derive poster URLs from a computed instead of a watcher, fold video proxy retries back into onMediaError, and keep GIF poster state separate from video posters.
Distinguish imgproxy poster routing from CORS-proxy retries, and separate GIF poster state from video poster URLs.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/components/pages/posts/post/PostMedia.vue`:
- Around line 426-437: The poster probe path in PostMedia.vue is incorrectly
letting hidden poster image failures set error state and show the error UI for
an otherwise playable video. Update the load/error handling around the poster
proxy logic in the video poster branch and the shared error path near the video
media handlers so poster-only failures are ignored or retried without assigning
error.value. Use the existing symbols isVideo.value, isPremium.value,
triedToLoadPosterWithProxy.value, videoPosterProxyOverride.value, and
props.mediaPosterSrc to keep the fix scoped to poster probing.
- Around line 56-57: The SSR imgproxy condition in PostMedia should only apply
to the actual LCP poster instead of every SSR video in the first eight slots.
Update the logic around the poster selection in PostMedia.vue so it uses the
existing isLikelyLcpMedia check (postIndex === 0) rather than the broader
wasCurrentPageSSR && props.postIndex < 8 fallback, and keep the premium path
unchanged.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a27714fb-bfeb-4831-a5ab-054ffb89c7e3

📥 Commits

Reviewing files that changed from the base of the PR and between 8756b26 and 461e56d.

📒 Files selected for processing (2)
  • app/components/pages/posts/post/PostMedia.vue
  • test/pages/posts-video-proxy.test.ts
💤 Files with no reviewable changes (1)
  • test/pages/posts-video-proxy.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
app/**/*.{vue,ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

app/**/*.{vue,ts,tsx}: Use Nuxt 4 with Vue 3 and TypeScript for the frontend application
Use useLazyToast() to lazy-load vue-sonner; wait for ClientToaster to mount before calling toast.* using a proper async wait instead of plain nextTick()
Build reordered array synchronously instead of reading VueUse moveArrayElement() result before nextTick for state immediately persisted

Files:

  • app/components/pages/posts/post/PostMedia.vue
**/*.{vue,ts,tsx,js,jsx,json,css,scss}

📄 CodeRabbit inference engine (AGENTS.md)

Use Prettier for formatting with 120-char print width, no semicolons, single quotes, trailing commas removed, and single attribute per line in Vue templates

Files:

  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,js,jsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

Use Nuxt flat ESLint via @nuxt/eslint for linting

Files:

  • app/components/pages/posts/post/PostMedia.vue
app/components/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

app/components/**/*.vue: Register Vue components without path prefix using pathPrefix: false in nuxt.config.ts; import them as not <Input/DomainSelector>
Auto-import components from app/components/ flat structure without folder prefix
Use custom imgproxy provider for images; generate images at 1x density only in webp format to reduce bandwidth
Use @nuxt/image v2 preload API (preload: { fetchPriority: 'high' }) for image preload priority instead of patching rendered HTML in Nitro
Use Nuxt Lazy* components, dynamic imports, or similarly deferred boundaries for components and composables only needed after user interaction (menu, sheet, dialog)

Files:

  • app/components/pages/posts/post/PostMedia.vue
**/*.{ts,tsx,vue}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,vue}: Define locales in config/i18n.ts as the single source of truth; do not hardcode locale lists in application code
Use PocketBase batch writes for multi-record replacement/reorder operations instead of one HTTP write per changed row

Files:

  • app/components/pages/posts/post/PostMedia.vue
app/**/*.vue

📄 CodeRabbit inference engine (AGENTS.md)

app/**/*.vue: Use project.urls.production for canonical URLs to point to production (https://r34.app/...) even when served from clone domains
Keep breadcrumb Schema.org source item URLs local/locale-relative; do not convert to project.urls.production since nuxt-schema-org resolves against site.url
When triggering a premium prompt from a nested dialog/bottom sheet, let the sheet owner close local UI, open the prompt, and restore UI after prompt closes
Premium auth transitions are reload-backed in dashboard/sign-in flow; rely on page reload to clear memory state instead of tracking PocketBase user ids in useState

Files:

  • app/components/pages/posts/post/PostMedia.vue
🔇 Additional comments (1)
app/components/pages/posts/post/PostMedia.vue (1)

4-4: LGTM!

Also applies to: 39-43, 85-98, 480-485, 805-805, 814-814

Comment thread app/components/pages/posts/post/PostMedia.vue Outdated
Comment thread app/components/pages/posts/post/PostMedia.vue Outdated
Keep onMediaError as a thin dispatcher while grouping video and GIF retry logic into dedicated functions.
Limit SSR imgproxy to the LCP poster only and treat hidden poster probe failures as non-fatal so playable videos keep their UI.
@AlejandroAkbal

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@AlejandroAkbal

Copy link
Copy Markdown
Member Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant