Skip to content

✨ feat: Add server-side support for APP_TITLE and APP_DESCRIPTION metadata#12385

Open
ucodia wants to merge 1 commit intodanny-avila:mainfrom
ucodia:feat-configurable-app-description
Open

✨ feat: Add server-side support for APP_TITLE and APP_DESCRIPTION metadata#12385
ucodia wants to merge 1 commit intodanny-avila:mainfrom
ucodia:feat-configurable-app-description

Conversation

@ucodia
Copy link
Copy Markdown
Contributor

@ucodia ucodia commented Mar 24, 2026

Summary

  • Adds a new APP_DESCRIPTION environment variable that allows operators to customize the HTML <meta name="description"> tag content at runtime, following the same pattern as the existing APP_TITLE env var.
  • Both APP_TITLE and APP_DESCRIPTION are now injected server-side into the HTML at startup, so crawlers and social-sharing previews see the correct values without JavaScript.
  • The PWA manifest.webmanifest is dynamically served with name, short_name, and description reflecting the configured values.
  • Shared default constants (defaultAppTitle, defaultAppDescription) ensure consistent fallback values across the codebase.
  • Client-side hooks are preserved for SPA navigation and dev mode.

Change Type

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

Testing

Test Configuration:

  1. Set APP_TITLE=My App and APP_DESCRIPTION=My custom description in .env
  2. Start the backend
  3. SEO/server-side: curl http://localhost:3080/ — confirm <title>My App</title> and <meta name="description" content="My custom description" appear in the raw HTML (no JS required)
  4. PWA manifest: curl http://localhost:3080/manifest.webmanifest — confirm "name": "My App", "short_name": "My App", and "description": "My custom description"
  5. Config API: visit http://localhost:3080/api/config — confirm "appTitle": "My App" and "appDescription": "My custom description" are present
  6. Client-side: Load the app in a browser, inspect the <title> and <meta name="description"> tags, confirm they match the configured values
  7. Defaults: Remove both env vars, restart — confirm the title defaults to "LibreChat" and the description defaults to "LibreChat - An open source chat application with support for multiple AI models"
  8. Unit tests: cd packages/api && npx jest appMetadata — 12 tests pass

Checklist

@danny-avila
Copy link
Copy Markdown
Owner

Here's an automated review I ran:

What's Good

The approach is straightforward, follows the existing APP_TITLE pattern, and touches all the right layers: backend payload, shared type definition, frontend hook, and .env.example.


Issues to Fix Before Merge

1. No real test coverage
The only test file change adds a cleanup line to an afterEach block inside a permanently-skipped describe block. Zero tests actually run. Neither the backend payload behavior nor the frontend DOM mutation is tested.

2. The SEO pitch doesn't hold up
Setting <meta name="description"> via JavaScript after a network request means crawlers (Google, Bing, social link previewers) will read the static index.html default, not the operator-configured value. If this is meant for branding/SEO, the implementation won't deliver. This needs to be documented clearly so operators aren't misled.

3. Inconsistent backend pattern
process.env.APP_DESCRIPTION || undefined is a confusing way to express "omit this key when unset." The rest of the file uses an explicit if block for optional env vars (see CUSTOM_FOOTER). Should match that pattern.


Minor/Polish

  • .env.example entry shows # APP_DESCRIPTION= with no example value or hint at what the default is
  • The ?? '' coercion in the useEffect is redundant given the !appDescription guard immediately after
  • The JSDoc comment narrates what the code does, which the project style guide explicitly discourages
  • The useEffect depends on the entire startupConfig object when it only reads one field from it

@ucodia
Copy link
Copy Markdown
Contributor Author

ucodia commented Mar 25, 2026

Thanks for the feedback @danny-avila

I did not indeed realize that a JS runtime update the DOM would defeat SEO in crawling/no JS scenarios. This actually reveals a more systematic issue with how LibreChat update the <title> tag as well. Doing a SEO check on my published stack revealed that meta title was still LibreChat.

This does need rework so I will think of a different strategy which may benefit all SEO and metadata related elements, including the app manifest.

… metadata

Apply title and description from environment variables at the server level
so that crawlers and SEO tools see the correct values without JavaScript.
Also serve a dynamically-patched `manifest.webmanifest` reflecting both
values for PWA contexts. Client-side hooks are preserved for SPA navigation
and dev mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@ucodia ucodia force-pushed the feat-configurable-app-description branch from 9c8773c to c4a0145 Compare March 26, 2026 01:02
@ucodia ucodia changed the title ⚗️ feat: Add support for APP_DESCRIPTION environment variable to set the application's meta description ✨ feat: Add server-side support for APP_TITLE and APP_DESCRIPTION metadata Mar 26, 2026
@ucodia ucodia changed the title ✨ feat: Add server-side support for APP_TITLE and APP_DESCRIPTION metadata ✨ feat: Add server-side support for APP_TITLE and APP_DESCRIPTION metadata Mar 26, 2026
@ucodia
Copy link
Copy Markdown
Contributor Author

ucodia commented Mar 26, 2026

@danny-avila updated accordingly so that it works for SEO as you highlighted and added relevant tests. In fact this was already not happening with the APP_TITLE value which was injected at runtime. Since the app title and description also exists in the web manifest I went ahead and also updated them. Admittedly this is a wider scope than my original PR intended!

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.

2 participants