#1830·linkwarden

Configurable max title length for AI-assisted title generation (fallback)

Author: mfbloomCreated Sep 8, 2026Updated Sep 8, 2026

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:

  1. empty, or
  2. equal to the URL (extraction failed / fell back to the URL), or
  3. 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.