Skip to content

feat: 2026 redesign, SEO pages, UX fixes and cover art improvements#247

Merged
DestroyCom merged 4 commits into
masterfrom
feat/new-look
May 11, 2026
Merged

feat: 2026 redesign, SEO pages, UX fixes and cover art improvements#247
DestroyCom merged 4 commits into
masterfrom
feat/new-look

Conversation

@DestroyCom
Copy link
Copy Markdown
Owner

@DestroyCom DestroyCom commented May 11, 2026

UI / Design

  • Full 2026 hi-fi redesign: petrol-blue palette, Satoshi font, dark/light section alternation, smooth scroll
  • New SiteHeader with compact "← New search" variant on /fetch, white logo (brightness-0 invert filter), dark bg (stroy-800) for proper contrast
  • New SiteFooter with 4-column grid, legal links, stroy-900 dark background
  • Landing page rewrite: Hero, How it works, Formats, FAQ+Glossary sections with HowTo and FAQPage JSON-LD structured data
  • /fetch page: dedicated compact layout, wider result card (440px thumb, 1080px max), channel pill and duration badge on thumbnail
  • Redesigned GetterInput: label wrapper for click-to-focus, Paste button no longer gated behind clipboard-read permission query
  • Download progress: jumps to 100% when server responds, shows "Saving to your device…" phase, blob URL revoked after 1 s safety delay
  • Retry button shown on download error

SEO

  • New /how-to-download-youtube-videos guide page with Article + HowTo JSON-LD
  • Full legal section: terms, privacy, cookies, DMCA, contact (with sidebar nav)
  • Sitemap extended with new routes
  • WebApplication JSON-LD in root layout, FAQPage on landing

Library Ready / cover art

  • sharp installed as direct dependency; serverExternalPackages updated
  • Cover fetch timeout raised 5 s → 20 s (YouTube CDN can be slow)
  • Non-JPEG/PNG covers (WebP, AVIF…) converted to JPEG via sharp before embed
  • Provider cover (MusicBrainz CAA / iTunes) and YouTube thumbnail now passed separately so the thumbnail is a true fallback if the provider fetch fails

Summary by CodeRabbit

Release Notes

  • New Features

    • Added comprehensive legal pages (Terms, Privacy, Cookies, DMCA, Contact)
    • Added "How to download YouTube videos" guide with SEO optimization
    • Redesigned homepage with installation steps, format overview, and FAQ
    • Improved download interface with format selection tabs (MP4, MP3, Library Ready)
    • Enhanced audio downloads with improved cover art handling
  • Style

    • Updated visual design with petrol-blue color scheme and Satoshi font

Review Change Stack

UI / Design
- Full 2026 hi-fi redesign: petrol-blue palette, Satoshi font, dark/light
  section alternation, smooth scroll
- New SiteHeader with compact "← New search" variant on /fetch, white logo
  (brightness-0 invert filter), dark bg (stroy-800) for proper contrast
- New SiteFooter with 4-column grid, legal links, stroy-900 dark background
- Landing page rewrite: Hero, How it works, Formats, FAQ+Glossary sections
  with HowTo and FAQPage JSON-LD structured data
- /fetch page: dedicated compact layout, wider result card (440px thumb,
  1080px max), channel pill and duration badge on thumbnail
- Redesigned GetterInput: label wrapper for click-to-focus, Paste button
  no longer gated behind clipboard-read permission query
- Download progress: jumps to 100% when server responds, shows "Saving to
  your device…" phase, blob URL revoked after 1 s safety delay
- Retry button shown on download error

SEO
- New /how-to-download-youtube-videos guide page with Article + HowTo JSON-LD
- Full legal section: terms, privacy, cookies, DMCA, contact (with sidebar nav)
- Sitemap extended with new routes
- WebApplication JSON-LD in root layout, FAQPage on landing

Library Ready / cover art
- sharp installed as direct dependency; serverExternalPackages updated
- Cover fetch timeout raised 5 s → 20 s (YouTube CDN can be slow)
- Non-JPEG/PNG covers (WebP, AVIF…) converted to JPEG via sharp before embed
- Provider cover (MusicBrainz CAA / iTunes) and YouTube thumbnail now passed
  separately so the thumbnail is a true fallback if the provider fetch fails
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 11, 2026

Warning

Rate limit exceeded

@DestroyCom has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 32 minutes and 15 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 1b066b9a-94b7-49a3-8810-139474cb1a47

📥 Commits

Reviewing files that changed from the base of the PR and between 79db83d and fc1b59a.

⛔ Files ignored due to path filters (1)
  • assets/logo-white.svg is excluded by !**/*.svg
📒 Files selected for processing (20)
  • app/api/download/audio-library-ready/route.ts
  • app/layout.tsx
  • app/legal/terms/page.tsx
  • app/page.tsx
  • app/sitemap.ts
  • app/updates/[slug]/page.tsx
  • app/updates/page.tsx
  • components/custom/GetterInput.tsx
  • components/custom/SiteFooter.tsx
  • components/custom/SiteHeader.tsx
  • components/custom/VideoSelect.tsx
  • functions/fetchVideoinfos.ts
  • lib/embed-id3.ts
  • lib/lyrics/index.ts
  • lib/metadata/index.ts
  • lib/metadata/providers/deezer.ts
  • lib/metadata/providers/youtube-music.ts
  • lib/site-config.ts
  • lib/song-matching.ts
  • lib/updates.ts
📝 Walkthrough

Walkthrough

This PR implements a comprehensive site redesign introducing a new "StroyGetter petrol-blue" design system, centralizes configuration via siteConfig, refactors the layout into reusable SiteHeader and SiteFooter components, expands the home page with marketing sections and an FAQ accordion, adds a full legal section with five pages plus a how-to guide, redesigns the download flow to use format-tab selection (MP4/MP3/Library Ready), improves ID3 cover art with fallback logic and image re-encoding, and updates dependencies.

Changes

Design System, Layout Refactor, Content Expansion, and Download Flow Redesign

Layer / File(s) Summary
Configuration and Design System
lib/site-config.ts, app/globals.css
New siteConfig module exports environment-driven site URLs and contact emails. Global CSS switches from shadcn/ui tokens to a petrol-blue --color-stroy-* palette, adds Satoshi font via CSS variable, enables smooth scrolling, and changes body background to #102F42 with white text.
Layout Components and Root Template
components/custom/JsonLd.tsx, components/custom/SiteFooter.tsx, components/custom/SiteHeader.tsx, app/layout.tsx
JsonLd component renders schema.org JSON-LD via dangerouslySetInnerHTML. SiteHeader renders responsive header with brand logo, navigation links from NAV_LINKS, GitHub link from siteConfig, and mobile hamburger menu that swaps to "← New search" on /fetch routes. SiteFooter renders footer with logo, four link columns, and legal navigation using siteConfig URLs. RootLayout is refactored to render these components, apply Satoshi font via CSS variable, output JSON-LD for WebApplication schema, and inject GoogleAnalytics.
Robots and Sitemap Configuration
app/robots.ts, app/sitemap.ts
Both now derive the base URL from siteConfig.url instead of hardcoded domains. Sitemap expanded to include legal, how-to, and other new routes with explicit lastModified, changeFrequency, and priority values.
Legal Section Layout and Pages
app/legal/layout.tsx, app/legal/terms/page.tsx, app/legal/privacy/page.tsx, app/legal/cookies/page.tsx, app/legal/dmca/page.tsx, app/legal/contact/page.tsx
Added LegalLayout with sidebar navigation and disclaimer callout. Five new legal pages export metadata and render structured content: Terms (numbered sections), Privacy (collection/contact details), Cookies (analytics disclosure), DMCA (policy with email link), and Contact (GitHub + DMCA email links).
How-To Educational Page
app/how-to-download-youtube-videos/page.tsx
New page exports metadata and renders article with table of contents, three JSON-LD schemas (Article, HowTo, FAQPage), instructional sections with icons, troubleshooting list, and FAQ section generated from ARTICLE_FAQS array.
Home Page Marketing Expansion
app/page.tsx
Landing page refactored from minimal layout to multi-section marketing page. Adds structured HOW_STEPS, FORMATS, FAQS, and GLOSSARY constants. Renders hero with benefits bullets, GetterInput in Suspense with SkeletonInput, three-column "How it works" grid, format cards with feature badges, FAQ accordion from FAQS, glossary definitions, and GitHub CTA using siteConfig.githubUrl. Outputs HowTo and FAQPage JSON-LD schemas.
Accordion UI Component
components/ui/accordion.tsx
New Radix-based accordion component exports Accordion, AccordionItem, AccordionTrigger, and AccordionContent with styled layout, rotating chevron icon, and state-driven open/close animations.
Download Page Layout
app/fetch/page.tsx
Page now exports metadata with "Download video" title and robots: { index: false }. Simplified to non-async component rendering a section with two Suspense boundaries: GetterInput with SkeletonInput fallback and VideoSelect with VideoLoading fallback.
URL Input Component
components/custom/GetterInput.tsx
Refactored to initialize state from videoUrl search param. Removes clipboard permission querying; instead, handlePaste button uses navigator.clipboard.readText() asynchronously. submitUrl resolves input via searchQuery and navigates to /fetch?videoUrl=.... Updated UI from stacked layout to labeled search input row with Search icon, input, and "Paste" button, plus CTA button with ArrowRight.
Video Selection and Loading UI
components/custom/VideoSelect.tsx, components/custom/VideoEmpty.tsx, components/custom/VideoLoading.tsx, components/custom/SkeletonInput.tsx
VideoSelect refactored from quality dropdown to format-tab driven flow. Adds FORMAT_TABS and EDU_CARDS constants, state for fmt (mp4/mp3/library-ready) and selectedItag. Initializes selectedItag from first format's itag. Download handler selects endpoints by fmt, sets progress to 100% after fetch succeeds, and revokes blob URL after 1s delay. Renders format tabs, conditional MP4 quality dropdown, Library Ready callout, educational cards grid, and disclaimer. VideoEmpty updated with new text and styling. VideoLoading and SkeletonInput updated with refined spinner and form margin styling.
ID3 Tag Embedding with Cover Fallback
lib/embed-id3.ts
EmbedOptions now accepts optional ytThumbnail parameter. New internal fetchCoverBuffer(url) helper fetches images with 20s timeout, detects JPEG/PNG, and re-encodes non-JPEG/PNG to JPEG via sharp. embedId3Tags prioritizes metadata.coverUrl then falls back to ytThumbnail, using fetchCoverBuffer for normalization and setting tags.image with derived MIME type on success.
Download Route Endpoints
app/api/download/audio-library-ready/route.ts, app/api/download/audio/route.ts, app/api/download/video/route.ts
Audio-library-ready route changed to pass ytThumbnail separately to embedId3Tags instead of via songMeta.coverUrl. Audio and video routes reordered imports for consistency across download endpoints.
Dependencies and Build Configuration
package.json, next.config.ts
Added @radix-ui/react-accordion and sharp to dependencies. Added serverExternalPackages to Next.js config listing sharp, ffmpeg-static, prisma, and youtube-dl-exec.
Song Title Parsing Updates
lib/song-matching.ts
Updated regex patterns for artist-title separation and suffix stripping to handle additional bracket/parenthesis-wrapped suffixes and trailing content.

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant GetterInput
  participant VideoSelect
  participant FormatTabs
  participant DownloadAPI
  participant EmbedID3
  participant SharpReencoding
  participant BlobDownload
  User->>GetterInput: paste video URL
  GetterInput->>GetterInput: searchQuery(url)
  GetterInput->>VideoSelect: navigate with videoUrl param
  User->>FormatTabs: select format (mp4/mp3/library-ready)
  FormatTabs->>VideoSelect: update fmt state
  VideoSelect->>DownloadAPI: POST /api/download/{fmt}
  alt mp3 or library-ready
    DownloadAPI->>EmbedID3: embedId3Tags with ytThumbnail fallback
    EmbedID3->>SharpReencoding: fetchCoverBuffer normalizes image
    SharpReencoding->>EmbedID3: return JPEG buffer with MIME type
  end
  DownloadAPI->>BlobDownload: return formatted audio/video blob
  BlobDownload->>User: trigger download with format extension
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • DestroyCom/StroyGetter#246: Earlier PR that added audio-library-ready route and ID3 embedding; this PR refines the same codepaths by improving cover art fallback and adding ytThumbnail parameter support.

Poem

🐰 A rabbit hops through colors new,
Petrol-blue and Satoshi true,
Pages bloom with legal care,
Downloads dance through formats fair,
From fallback thumbs to schema bright,
The site now gleams with redesigned light!

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% 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 accurately summarizes the major changes: a comprehensive 2026 redesign with SEO pages, UX improvements, and cover art enhancements.
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 feat/new-look

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


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 and usage tips.

@socket-security
Copy link
Copy Markdown

socket-security Bot commented May 11, 2026

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​radix-ui/​react-accordion@​1.2.12991007191100

View full report

…s, error handling

- Add /updates changelog page with slug-based routes and sitemap entries
- Wire iTunes provider as intermediate cover art fallback in library-ready route
- Return plain lyrics from YouTube subtitles via syltToPlain helper
- Add try/catch in fetchVideoinfos with clean yt-dlp error extraction
- Add .catch() in VideoSelect to surface unexpected fetch failures
- Add coverFallbacks[] param to embedId3Tags for ordered cover resolution
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 12

🤖 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/layout.tsx`:
- Around line 68-88: webAppJsonLd is unnecessarily JSON.stringified then parsed
for JsonLd; change webAppJsonLd from a JSON string to a plain JS object (use the
same object literal currently inside JSON.stringify) and pass that object
directly to the JsonLd component (update any other spots that parse/stringify
the same value). Locate the webAppJsonLd definition and the JsonLd usage and
remove the stringification/JSON.parse round-trip so JsonLd receives the object
(keep siteConfig references as-is).

In `@app/legal/terms/page.tsx`:
- Around line 23-26: Update the Terms entry with n: "03" where title: "Privacy"
and its body string so it matches the Privacy page wording about analytics and
cookies; replace the current "No cookies, no third-party tracking" sentence with
a consistent statement that discloses Google Analytics 4 may set cookies (e.g.,
_ga) and that anonymous usage metrics are collected, or otherwise remove the
absolute "No cookies" claim to mirror the Privacy page’s disclosure—modify the
body field text for the object with n: "03" / title: "Privacy" accordingly.

In `@app/page.tsx`:
- Line 47: Remove the redundant explicit casts "as string | undefined" on the
badge property occurrences (the `badge` initializers in app/page.tsx referenced
in the diff) so TypeScript can infer the union type; locate the badge
declarations (the three places shown in the diff) and replace their initializers
with a simple undefined (or omit the type annotation) without the "as string |
undefined" cast.

In `@app/sitemap.ts`:
- Around line 15-38: Add a sitemap entry for the new /legal/contact route in the
sitemap array in app/sitemap.ts: mirror the existing pattern used for other
legal pages (use BASE template for the URL, set lastModified to new
Date("2026-05-07"), changeFrequency to "yearly" and an appropriate priority such
as 0.2 or 0.3) so crawlers can discover /legal/contact; locate the array of
objects (the sitemap entries around the existing objects for `/legal/terms`,
`/legal/privacy`, `/legal/cookies`, `/legal/dmca`) and insert the new object for
`/legal/contact`.

In `@components/custom/GetterInput.tsx`:
- Around line 21-30: In handlePaste, when navigator.clipboard.readText() throws,
don't silently focus the input; instead surface a brief user-visible
message—e.g., call a toast/error setter or update local state (use a provided
setError or create a short-lived message state) to show "Please paste manually
or grant clipboard permission" before focusing inputRef; keep the existing
fallback focus behavior and ensure the message clears after a few seconds or on
next input. Reference: handlePaste, navigator.clipboard.readText, inputRef,
setUrl, submitUrl.
- Line 26: Remove the artificial 100ms setTimeout call in GetterInput.tsx:
replace setTimeout(() => submitUrl(clipText), 100) by calling submitUrl directly
(await if inside an async handler) since clipText is already in scope;
alternatively use React.startTransition if you need to defer a
state-update-driven navigation. Update the handler that calls submitUrl (the
function wrapping setTimeout) to call submitUrl(clipText) directly and ensure
any async/await or transition semantics are applied there.

In `@components/custom/JsonLd.tsx`:
- Line 7: The JsonLd component currently injects raw JSON via
dangerouslySetInnerHTML using JSON.stringify(data), which can allow a
`</script>` to break out; fix it by sanitizing the JSON string before
injection—compute a safe string from JSON.stringify(data) and replace any '<'
characters (e.g., .replace(/</g, '\\u003c')) so script-breaking sequences are
neutralized, then pass that sanitized string to dangerouslySetInnerHTML; update
the JsonLd component to use this sanitized payload when referencing data and
dangerouslySetInnerHTML.

In `@components/custom/SiteHeader.tsx`:
- Line 39: The Logo image currently uses CSS filters ("brightness-0 invert")
which is fragile; replace that by either importing a dedicated white SVG (use
that asset instead of `logo`) or update the SVG file to use fill="currentColor"
and then remove the filter classes and set the Image/parent to use a text color
(e.g., add className="text-white" to the Image or its wrapper). Locate the Image
usage in SiteHeader (the <Image src={logo} ... /> line), remove the
"brightness-0 invert" classes, and update the import or SVG content accordingly
so the logo color is explicit and maintainable.

In `@components/custom/VideoSelect.tsx`:
- Around line 222-230: The mapping over formats in VideoSelect.tsx currently
returns null for entries missing qualityLabel or itag, causing empty dropdown
slots; replace the inline null-check by filtering the formats array first (e.g.,
use formats.filter(f => f.qualityLabel && f.itag) ) and then map the filtered
list to render <SelectItem> elements (keep using f.itag as the key and value and
f.qualityLabel as the label) inside SelectContent to ensure no null gaps in the
Select.
- Line 76: The code sets selectedItag from value.format[0].itag without
verifying format[0] exists; update the logic in VideoSelect.tsx (around the
setSelectedItag call) to first guard that value.format is an array and
value.format[0] and value.format[0].itag are defined (or use optional chaining
like value.format?.[0]?.itag) before calling setSelectedItag, and fall back to a
safe default (e.g., undefined or empty string) when no itag is available.

In `@lib/site-config.ts`:
- Line 10: The siteConfig.url can contain a trailing slash from
NEXT_PUBLIC_SITE_URL which breaks the no-trailing-slash contract; update how
siteConfig.url is constructed (the url property) to normalize the value by
stripping any trailing slashes from process.env.NEXT_PUBLIC_SITE_URL before
falling back to the hardcoded default (and ensure the default has no trailing
slash), e.g. trim trailing slashes with a replace or equivalent so
siteConfig.url never ends with '/'.

In `@lib/song-matching.ts`:
- Line 38: The current SEPARATOR_RE (const SEPARATOR_RE) allows mismatched
brackets because the fragment `[([].*[)\]]` accepts any opening with any
closing; update the regex to enforce matching bracket pairs by replacing that
fragment with a non-capturing alternation that matches either balanced
parentheses or balanced square brackets, e.g. use `(?:\([^)]*\)|\[[^\]]*\])` in
the SEPARATOR_RE definition so titles like "(text]" or "[text)" no longer match
incorrectly.
🪄 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: af0182c5-07c0-41a7-ad0f-bd51149c2600

📥 Commits

Reviewing files that changed from the base of the PR and between ed783c9 and 79db83d.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (30)
  • app/api/download/audio-library-ready/route.ts
  • app/api/download/audio/route.ts
  • app/api/download/video/route.ts
  • app/fetch/page.tsx
  • app/globals.css
  • app/how-to-download-youtube-videos/page.tsx
  • app/layout.tsx
  • app/legal/contact/page.tsx
  • app/legal/cookies/page.tsx
  • app/legal/dmca/page.tsx
  • app/legal/layout.tsx
  • app/legal/privacy/page.tsx
  • app/legal/terms/page.tsx
  • app/page.tsx
  • app/robots.ts
  • app/sitemap.ts
  • components/custom/GetterInput.tsx
  • components/custom/JsonLd.tsx
  • components/custom/SiteFooter.tsx
  • components/custom/SiteHeader.tsx
  • components/custom/SkeletonInput.tsx
  • components/custom/VideoEmpty.tsx
  • components/custom/VideoLoading.tsx
  • components/custom/VideoSelect.tsx
  • components/ui/accordion.tsx
  • lib/embed-id3.ts
  • lib/site-config.ts
  • lib/song-matching.ts
  • next.config.ts
  • package.json
📜 Review details
🧰 Additional context used
📓 Path-based instructions (6)
**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.{ts,tsx}: Use import { prisma } from '@/lib/prisma' for all Prisma client access in Next.js 16 with Prisma 7 — never instantiate new PrismaClient()
Never call prisma.$disconnect() on the singleton Prisma instance, as it breaks subsequent requests and cron runs
Use youtubei.js via lib/innertube.ts and getBasicInfo() for fetching metadata and format lists
Parse yt-dlp format information using lib/ytdlp-info.ts module

Files:

  • components/custom/SkeletonInput.tsx
  • next.config.ts
  • app/legal/privacy/page.tsx
  • components/custom/SiteFooter.tsx
  • components/custom/JsonLd.tsx
  • components/custom/VideoEmpty.tsx
  • app/robots.ts
  • app/legal/layout.tsx
  • app/api/download/video/route.ts
  • app/legal/contact/page.tsx
  • app/legal/cookies/page.tsx
  • app/legal/terms/page.tsx
  • app/fetch/page.tsx
  • components/custom/VideoLoading.tsx
  • lib/song-matching.ts
  • app/api/download/audio/route.ts
  • app/legal/dmca/page.tsx
  • components/custom/SiteHeader.tsx
  • app/how-to-download-youtube-videos/page.tsx
  • lib/site-config.ts
  • app/sitemap.ts
  • components/ui/accordion.tsx
  • app/api/download/audio-library-ready/route.ts
  • app/page.tsx
  • lib/embed-id3.ts
  • components/custom/GetterInput.tsx
  • app/layout.tsx
  • components/custom/VideoSelect.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use Biome for linting via pnpm lint command

Files:

  • components/custom/SkeletonInput.tsx
  • next.config.ts
  • app/legal/privacy/page.tsx
  • components/custom/SiteFooter.tsx
  • components/custom/JsonLd.tsx
  • components/custom/VideoEmpty.tsx
  • app/robots.ts
  • app/legal/layout.tsx
  • app/api/download/video/route.ts
  • app/legal/contact/page.tsx
  • app/legal/cookies/page.tsx
  • app/legal/terms/page.tsx
  • app/fetch/page.tsx
  • components/custom/VideoLoading.tsx
  • lib/song-matching.ts
  • app/api/download/audio/route.ts
  • app/legal/dmca/page.tsx
  • components/custom/SiteHeader.tsx
  • app/how-to-download-youtube-videos/page.tsx
  • lib/site-config.ts
  • app/sitemap.ts
  • components/ui/accordion.tsx
  • app/api/download/audio-library-ready/route.ts
  • app/page.tsx
  • lib/embed-id3.ts
  • components/custom/GetterInput.tsx
  • app/layout.tsx
  • components/custom/VideoSelect.tsx
**/{api,functions}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

Use youtube-dl-exec (yt-dlp binary) for actual stream downloading via selectYtDlpPath() function

Files:

  • app/api/download/video/route.ts
  • app/api/download/audio/route.ts
  • app/api/download/audio-library-ready/route.ts
**/{api,functions,lib}/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

**/{api,functions,lib}/**/*.{ts,tsx}: Store merged MP4s in temp/cached/ directory and index them in the File table by URL+quality for caching
Implement temp directory structure as ./temp/{source,cached} in development and /temp/stroygetter/{source,cached} in production, created automatically via initializeConf()

Files:

  • app/api/download/video/route.ts
  • lib/song-matching.ts
  • app/api/download/audio/route.ts
  • lib/site-config.ts
  • app/api/download/audio-library-ready/route.ts
  • lib/embed-id3.ts
app/api/**/*.{ts,tsx}

📄 CodeRabbit inference engine (CLAUDE.md)

app/api/**/*.{ts,tsx}: Stream audio quality directly via ffmpeg → PassThrough → Response without caching to disk
Fetch thumbnails to temp files for album art embedding, then delete after ffmpeg closes

Files:

  • app/api/download/video/route.ts
  • app/api/download/audio/route.ts
  • app/api/download/audio-library-ready/route.ts
package.json

📄 CodeRabbit inference engine (CLAUDE.md)

Ensure copy-binaries.js runs as a postbuild script to copy the yt-dlp binary into .next/standalone/ for production deployment

Files:

  • package.json
🪛 ast-grep (0.42.1)
components/custom/JsonLd.tsx

[warning] 6-6: Usage of dangerouslySetInnerHTML detected. This bypasses React's built-in XSS protection. Always sanitize HTML content using libraries like DOMPurify before injecting it into the DOM to prevent XSS attacks.
Context: dangerouslySetInnerHTML
Note: [CWE-79] Improper Neutralization of Input During Web Page Generation [REFERENCES]
- https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
- https://cwe.mitre.org/data/definitions/79.html

(react-unsafe-html-injection)

🪛 OpenGrep (1.20.0)
components/custom/JsonLd.tsx

[WARNING] 3-9: dangerouslySetInnerHTML with dynamic content can lead to XSS. Sanitize the input with a library like DOMPurify before rendering.

(coderabbit.xss.react-dangerously-set-innerhtml)

🔇 Additional comments (22)
lib/song-matching.ts (2)

53-78: LGTM! Robust fallback strategy for metadata extraction.

The three-tier fallback logic (yt-dlp metadata → parsed title → raw fallback) is well-designed and handles missing or malformed data gracefully. The function correctly prioritizes structured metadata when available and falls back to heuristic parsing only when needed.


46-46: 💤 Low value

Line 46's suffix-stripping serves keyword-specific filtering, but its necessity is unclear without test coverage.

The SEPARATOR_RE removes trailing brackets from the entire title, while line 46 removes keyword-specific bracketed content (e.g., "[Official Audio]") from the extracted title. These are different concerns. However, without tests demonstrating when line 46 actually removes content from real YouTube titles, it's unclear whether this is handling legitimate edge cases or defensive code. Consider adding tests with real YouTube title samples to verify this step is needed.

components/custom/SkeletonInput.tsx (1)

5-5: Layout tweak is clean and behavior-preserving.

package.json (1)

23-23: Dependency additions are consistent with the implementation and deployment setup.

Also applies to: 39-39

app/api/download/audio/route.ts (1)

7-7: Import reorder is safe and behavior-neutral.

app/api/download/video/route.ts (1)

8-8: Import ordering change is clean and non-breaking.

next.config.ts (1)

5-5: serverExternalPackages addition aligns with the new runtime dependencies.

components/ui/accordion.tsx (1)

1-54: Accordion composition is solid and idiomatic for Radix + React refs.

lib/embed-id3.ts (2)

20-48: LGTM! Well-designed fallback and conversion logic.

The 20-second timeout is appropriate given the redirect chains mentioned in the comment. The content-type detection handles multiple variations (includes/startsWith checks), and converting to JPEG at quality 92 balances file size with visual fidelity for album art. The null-return-on-error pattern enables clean fallback to the next cover candidate.


63-80: LGTM! Clean fallback implementation.

The provider cover (MusicBrainz/iTunes) → YouTube thumbnail fallback chain is correctly implemented with detailed logging and early-exit on success.

app/api/download/audio-library-ready/route.ts (1)

64-81: LGTM! Correctly separates provider cover from YouTube thumbnail fallback.

The change aligns with the updated embedId3Tags API in lib/embed-id3.ts, allowing the embed logic to try the provider cover first and fall back to the YouTube thumbnail only if needed.

components/custom/SiteHeader.tsx (1)

88-113: LGTM! Mobile menu implementation is clean.

The overlay uses absolute positioning with proper inset-x-0 top-full and z-50 to position below the header. The menu closes on navigation, and ARIA labels are present for accessibility.

app/globals.css (1)

9-20: LGTM! Clean design system implementation.

The new "StroyGetter petrol-blue" palette is well-structured with 11 shades, smooth-scroll improves UX, and the Satoshi font integration with proper antialiasing is correct. The shadcn/ui token mappings preserve component compatibility.

Also applies to: 52-62, 72-100

components/custom/VideoLoading.tsx (1)

5-7: LGTM! Styling updated to match new design system.

components/custom/VideoEmpty.tsx (1)

3-7: LGTM! Styling and message updated to match new design.

components/custom/VideoSelect.tsx (2)

81-89: LGTM! Smooth progress simulation using exponential decay.

The exponential formula 90 * (1 - Math.exp(-elapsed / 10000)) provides a natural-feeling progress curve that slows as it approaches 90%, then jumps to 100% when the server responds (line 108). The 1-second safety delay before revoking the object URL (line 118) is appropriate.


91-123: LGTM! Download flow correctly handles different formats.

The endpoint selection logic (lines 100-102) properly routes to the appropriate API based on format, and error handling with user feedback is well-implemented.

app/fetch/page.tsx (2)

7-10: LGTM — Clean metadata setup for non-indexed page.

The robots: { index: false } correctly prevents search engines from indexing the download results page, which is appropriate for a dynamic, user-specific interface.


12-28: LGTM — Proper async boundary pattern.

Converting the page component from async to synchronous while keeping async work isolated in Suspense boundaries is the correct approach. The fallback components provide appropriate loading states.

app/page.tsx (1)

110-134: LGTM — Proper structured data implementation.

The HowTo and FAQPage JSON-LD schemas are correctly structured according to schema.org specifications. The mapping from the static data arrays is clean and maintains semantic integrity.

app/how-to-download-youtube-videos/page.tsx (1)

60-117: LGTM — Well-structured schema.org markup.

The three JSON-LD blocks (Article, HowTo, FAQPage) provide comprehensive structured data for search engines. The schemas are properly nested and follow schema.org specifications.

app/layout.tsx (1)

90-102: LGTM — Clean root layout structure.

The layout properly sets up global font variables, structured data, site chrome (header/footer), and analytics. The placement of GoogleAnalytics after the closing </html> tag is correct for the @next/third-parties package.

Comment thread app/layout.tsx Outdated
Comment thread app/legal/terms/page.tsx
Comment thread app/page.tsx Outdated
Comment thread app/sitemap.ts
Comment thread components/custom/GetterInput.tsx
Comment thread components/custom/SiteHeader.tsx Outdated
Comment thread components/custom/VideoSelect.tsx Outdated
Comment thread components/custom/VideoSelect.tsx Outdated
Comment thread lib/site-config.ts Outdated
Comment thread lib/song-matching.ts Outdated
Adds two new cover art fallback providers (Deezer, YouTube Music) to
improve hit rate on well-known tracks where Cover Art Archive returns 404.

Cover chain is now: MusicBrainz CAA → iTunes → Deezer → YouTube Music → YouTube thumbnail.
- layout.tsx: webAppJsonLd is now a plain object (no stringify/parse)
- terms/page.tsx: disclose GA4 cookies instead of claiming "No cookies"
- page.tsx: remove redundant `as string | undefined` casts on badge
- sitemap.ts: add /legal/contact entry
- GetterInput: drop setTimeout, surface clipboard permission error
- SiteHeader: swap to logo-white.svg, drop brightness-0 invert filter
- VideoSelect: filter formats before map, guard itag with optional chaining
- site-config: strip trailing slash from NEXT_PUBLIC_SITE_URL
- song-matching: enforce matching brackets in SEPARATOR_RE
@DestroyCom DestroyCom merged commit bb346d0 into master May 11, 2026
4 checks passed
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