Skip to content

fix(bookmarks): keep explicit title over scraped title - #426

Merged
R-Sandor merged 2 commits into
FindFirst-Development:mainfrom
Abhishek84313:fix#404
Aug 16, 2026
Merged

fix(bookmarks): keep explicit title over scraped title#426
R-Sandor merged 2 commits into
FindFirst-Development:mainfrom
Abhishek84313:fix#404

Conversation

@Abhishek84313

Copy link
Copy Markdown
Contributor

An explicit title on POST /api/bookmark was thrown away whenever the url turned out to be
scrapable, so a scrapable bookmark could never be given a custom title.

addBookmark now resolves the title in order of precedence: the title the user gave us, then the
scraped page title, then the host of the url. Clients default the title field to the url itself
(NewBookmarkCard.tsx sends title || url), so a title equal to the url is treated as unset and
the scraped title wins.

The scrape and the title resolution are split into scrape(), resolveTitle() and
hasExplicitTitle(). The page is still fetched, indexed in Typesense and screenshotted when the
title is explicit, only the title is left alone.

Issue number: resolves #404


Checklist

  • Code Formatter (run prettier/spotlessApply)
  • Code has unit tests? (If no explain in other_information)
  • Builds on localhost
  • Builds/Runs in docker compose

What is the current behavior?

BookmarkService.addBookmark overwrites the requested title with the scraped <title> whenever the
url is scrapable. The title from the request is only used as a fallback when the page has no title
or the url is not scraped at all, so there is no way to save a scrapable bookmark under a name of
your own choosing.

What is the new behavior?

  • A title on the add request is kept as the bookmark's title even when the url is scraped.
  • A title equal to the url counts as no title, because clients default the field to the url; those
    requests still get the scraped title.
  • With no usable title from either the request or the page, the host of the url is used, as before.
  • Scraping is unchanged in every other respect: the page is still fetched, indexed in Typesense and
    screenshotted.

Does this introduce a breaking change?

  • Yes
  • No

The request and response shapes are unchanged. A client that sent a title and relied on the scrape
replacing it will now keep its own title, which is the bug being fixed. Stored bookmarks are
untouched.

Other information

  • New unit tests in BookmarkServiceTest cover a scrapable request with no title (null, empty,
    blank and the url), with an explicit title, with a page that has no title of its own, and a failed
    scrape falling back to the host. Jsoup.connect is stubbed with mockStatic, so no network is
    needed.
  • The updateBookmark test in BookmarkControllerTest asserted the old behaviour (the scraped
    LogRocket title replacing the posted "Dark mode guide"); it now expects the posted title to be
    kept.
  • Two latent bugs went out with the refactor: an NPE when a null title met a failed scrape, and a
    debug log that dereferenced retDoc.connection().response(), which is null for any document not
    produced by a live connection.
  • spotlessCheck is clean for the three files in this PR. It still reports pre-existing violations
    in FindFirstApplication.java, SecSecurityConfig.java and UserController.java, which this PR
    deliberately leaves alone.
  • Verified locally with gradlew test --tests "*BookmarkServiceTest" (10 tests, all passing) and
    gradlew assemble. The Testcontainers integration tests and docker compose were not run here, no
    Docker on this machine.

An explicit title on POST /api/bookmark was thrown away whenever the
url turned out to be scrapable, so a scrapable bookmark could never be
given a custom title.

addBookmark now resolves the title in order of precedence: the title the
user gave us, then the scraped page title, then the host of the url.
Clients default the title field to the url itself, so a title equal to
the url is treated as unset and the scraped title wins.

The scrape and the title resolution are split into scrape(),
resolveTitle() and hasExplicitTitle(). The page is still fetched,
indexed in Typesense and screenshotted when the title is explicit, only
the title is left alone. This also removes an NPE when a null title met
a failed scrape, and a debug log that dereferenced
retDoc.connection().response().

Tests cover a scrapable request with no title (null, empty, blank and
url), with an explicit title, with a page that has no title of its own,
and a failed scrape falling back to the host. The updateBookmark
controller test asserted the old behaviour and now expects the posted
title to be kept.
@R-Sandor
R-Sandor merged commit 5645830 into FindFirst-Development:main Aug 16, 2026
1 of 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.

[Server] Explicit title should take precedence over scraped title

2 participants