Configurable max title length for AI-assisted title generation (fallback)
Is your feature request related to a problem? Please describe.
When a link is added, its title comes from a plain <title> scrape in fetchTitleAndHeaders (apps/web/lib/api/controllers/links/postLink.ts). This produces poor results in three common cases:
- The page has no
<title>, so the title falls back to the raw URL. - The scrape fails / times out, so the title is empty or the raw URL.
- The
<title>is extremely long (SEO-stuffed pages, "Article title | Section | Very Long Site Name — Tagline"), so the link list is cluttered with 150+ character titles.
Linkwarden already has an AI subsystem (auto-tagging in apps/worker/lib/autoTagLink.ts) with a configured provider, but it is only used for tags. There is no way to get a clean, concise title, and no user-facing control over title length — the only AI-related knobs beyond tagging are deployment env variables.
Describe the solution you'd like
An opt-in, per-user AI title-generation fallback that runs in the worker after preservation (same pattern as autoTagPreservedLinks), triggered only when the extracted title is unsatisfactory:
- empty, or
- equal to the URL (extraction failed / fell back to the URL), or
- longer than a user-specified maximum length.
Exposed in Settings → Preferences → AI Settings (already gated by config.AI_ENABLED):
- a checkbox to enable AI title generation, and
- a "maximum title length" number input used as the trigger threshold.
Titles the user typed by hand are never overwritten. The max-length value is only a trigger threshold (titles are not truncated when AI is off); AI output is capped to that length as a safety net. A per-link done-flag prevents repeated retries of failing links.
Describe alternatives you've considered
- Env variable instead of UI setting — rejected; title-length preference is a user/library taste decision, not a deployment secret, unlike provider/model config.
- Hard-truncating long titles with an ellipsis, no AI — loses information and produces awkward cut-offs; could be offered as a separate non-AI option later.
- Running generation synchronously at link creation — blocks the add-link request on an AI call and only has raw HTML available (no readability content); the async worker path is consistent with existing AI tagging.
- Parsing OpenGraph /
og:title/ meta title before falling back to AI — a reasonable cheap improvement and complementary, but doesn't address the "too long" or "no useful metadata" cases.
Additional context
Implementation would mirror the existing auto-tagging flow: new User fields (aiGenerateTitles, aiTitleMaxLength), a Link.aiTitled done-flag, a shared getAIModel() helper extracted from autoTagLink.ts, a new prompt, a new worker loop, and a new "titles" batch mode in getLinkBatchFairly that is independent of whether AI tagging is enabled.
I have a working design and am happy to open a PR.
Source: linkwarden/linkwarden