Files
langflow/docs/docusaurus.config.js
Antônio Alexandre Borges Lima bbe2ccdc91 docs: fix sidebar and TOC styles for Redocusaurus (#12748)
* docs: improve sidebar and TOC readability + scroll progress

- Fix left nav sidebar hugging the left edge (remove margin-left)
- Increase sidebar font sizes and lift muted colors for legibility
- TOC right-side: white inactive items, pink active, gray for passed sections
- Add clientModule (tocProgress.js) to track scroll progress in TOC
- Add Redocusaurus API page styles to match site theme

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* docs: fix sidebar/TOC height stability and active item reflow

- Force sidebarViewport to 100vh to prevent shrinking during scroll
- Replace font-weight on active TOC item with text-shadow to avoid reflow

* docs: left-anchor sidebar and increase fonts on large screens

* docs: constrain prev/next nav to match content max-width

* docs: fix sidebar jump on scroll by moving padding-top inside menu

* docs: fix sidebar-ad spacing with transparent padding on li

* docs: fix sidebarViewport height and MutationObserver leak

* docs: constrain doc content to 75vw and remove dead CSS comments

- Cap docMainContainer at 75vw
- Set pagination-nav to 100% width to match content column
- Remove commented-out .markdown and .ch-scrollycoding blocks

* docs: set docMainContainer max-width to 75% for better reading width

* docs: center main-wrapper on large screens and center docItemWrapper

* fix: revert lodash override to stable 4.17.21

lodash 4.18.0 is a broken release — template.js uses assignWith and
arrayEach without importing them, crashing npm start. Pin to 4.17.21
across all nested overrides.

* fix: prevent horizontal scroll on mobile docs pages

docsWrapper has flex:1 0 auto (flex-shrink:0), so it never shrinks below
the natural content width (~570px on iPhone). Cap it to 100vw and add
min-width:0 down the flex chain (docRoot, docMainContainer) so the
layout stays within viewport on narrow screens.

Also remove the overflow:visible override from ch-code-wrapper, which
was defeating the code block's own horizontal containment.

* feat: responsive navbar search and hide social icons on mobile

Shrink search bar as viewport narrows (160px at 1100px, 100px at 996px),
collapse to icon-only at 960px. Hide GitHub, X, and Discord icons below
996px where the hamburger menu takes over navigation.

* fix: images always respect container width above 996px

Use min(100%, 600px) so images are capped at 600px but never overflow
their container when the content area is narrower (e.g. sidebar open).

* fix: improve TOC progress scroll tracking and bottom-of-page detection

Adds scroll handler with RAF throttle, pauses/resumes MutationObserver
to avoid loops, and forces last TOC link active when scrolled to page bottom.

* fix: translate Portuguese comments to English in custom.css

* fix: sidebar viewport fills full screen height

* feat: sidebar section icon turns pink with ease transition when active

* fix: reduce TOC font size to 0.8rem

* fix: remove docMainContainer right padding and add 48px gap to content col

* fix: card header responsive alignment and title margin reset

* fix: darken card background and active sidebar item bg on light theme

* fix: revert TOC colors and add inline code border radius tweak

* fix: minimal scrollbar for sidebar and TOC — thumb only on hover

* fix: scrollbar fade-in/out transition at 0.25s ease

* feat: add rehype plugin for table column wrapping and centering

Inserts zero-width space after underscores in inline code cells so long
env-var names wrap at underscore boundaries. Also centers Format/Default
columns via a col-center class applied at build time.

* fix: use --ifm-heading-color for sidebar group labels in both themes

* refactor: split docs custom.css into themed partials

Breaks the 1,658-line monolithic custom.css into 8 focused files
(tokens, layout, navbar, sidebar, typography, components, code,
redocusaurus). custom.css is now a thin entry point with @imports.

* fix: align sidebar and navbar with shared --docs-gutter token

Introduces --docs-gutter: 1rem in tokens.css and applies it to both
navbar__inner horizontal padding and sidebar nav.menu padding-left,
keeping the Langflow logo and sidebar items visually aligned.

* fix: match sidebar ad background to page background color

Dark mode uses #111 (same as sidebar bg); light mode uses --ifm-background-color.

---------

Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-12 22:11:36 +00:00

550 lines
17 KiB
JavaScript

// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
const path = require("path");
const lightCodeTheme = require("prism-react-renderer/themes/github");
const darkCodeTheme = require("prism-react-renderer/themes/dracula");
const { remarkCodeHike } = require("@code-hike/mdx");
const rehypeWbrUnderscore = require("./src/plugins/rehypeWbrUnderscore");
const isProduction = process.env.NODE_ENV === "production";
/** @type {import('@docusaurus/types').Config} */
const config = {
title: "Langflow Documentation",
tagline:
"Langflow is a low-code app builder for RAG and multi-agent AI applications.",
favicon: "img/favicon.ico",
url: "https://docs.langflow.org",
baseUrl: process.env.BASE_URL ? process.env.BASE_URL : "/",
onBrokenLinks: "throw",
onBrokenAnchors: "warn",
organizationName: "langflow-ai",
projectName: "langflow",
trailingSlash: false,
staticDirectories: ["static"],
markdown: {
hooks: {
onBrokenMarkdownLinks: "warn",
},
},
i18n: {
defaultLocale: "en",
locales: ["en"],
},
headTags: [
{
tagName: "link",
attributes: {
rel: "stylesheet",
href: "https://fonts.googleapis.com/css2?family=Geist:wght@300;400;500;600;700&family=Geist+Mono:wght@400;500&family=Sora:wght@550;600&display=swap",
},
},
...(isProduction
? [
// Google Consent Mode - Set defaults before Google tags load
{
tagName: "script",
attributes: {},
innerHTML: `
window.dataLayer = window.dataLayer || [];
function gtag(){dataLayer.push(arguments);}
// Set default consent to denied
gtag('consent', 'default', {
'ad_storage': 'denied',
'ad_user_data': 'denied',
'ad_personalization': 'denied',
'analytics_storage': 'denied'
});
`,
},
// TrustArc Consent Update Listener
{
tagName: "script",
attributes: {},
innerHTML: `
(function() {
function updateGoogleConsent() {
if (typeof window.truste !== 'undefined' && window.truste.cma) {
var consent = window.truste.cma.callApi('getConsent', window.location.href) || {};
// Map TrustArc categories to Google consent types
// Category 0 = Required, 1 = Functional, 2 = Advertising, 3 = Analytics
var hasAdvertising = consent[2] === 1;
var hasAnalytics = consent[3] === 1;
gtag('consent', 'update', {
'ad_storage': hasAdvertising ? 'granted' : 'denied',
'ad_user_data': hasAdvertising ? 'granted' : 'denied',
'ad_personalization': hasAdvertising ? 'granted' : 'denied',
'analytics_storage': hasAnalytics ? 'granted' : 'denied'
});
}
}
// Listen for consent changes
if (window.addEventListener) {
window.addEventListener('cm_data_subject_consent_changed', updateGoogleConsent);
window.addEventListener('cm_consent_preferences_set', updateGoogleConsent);
}
// Initial check after TrustArc loads
if (document.readyState === 'complete') {
updateGoogleConsent();
} else {
window.addEventListener('load', updateGoogleConsent);
}
})();
`,
},
]
: []),
],
presets: [
[
"@docusaurus/preset-classic",
/** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
routeBasePath: "/", // Serve the docs at the site's root
sidebarPath: require.resolve("./sidebars.js"), // Use sidebars.js file
sidebarCollapsed: true,
// Versioning configuration
lastVersion: "1.9.0",
versions: {
current: {
label: "1.10.x (Next)",
path: "next",
},
"1.9.0": {
label: "1.9.x",
path: "",
},
"1.8.0": {
label: "1.8.x",
path: "1.8.0",
},
},
beforeDefaultRemarkPlugins: [
[
remarkCodeHike,
{
theme: "github-dark",
showCopyButton: true,
lineNumbers: true,
},
],
],
rehypePlugins: [rehypeWbrUnderscore],
},
sitemap: {
// https://docusaurus.io/docs/api/plugins/@docusaurus/plugin-sitemap
// https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap
lastmod: "datetime",
changefreq: null,
priority: null,
ignorePatterns: [],
},
gtag: {
trackingID: "G-SLQFLQ3KPT",
},
blog: false,
theme: {
customCss: [
require.resolve("@code-hike/mdx/styles.css"),
require.resolve("./css/custom.css"),
],
},
}),
],
[
"redocusaurus",
{
openapi: {
path: "openapi",
routeBasePath: "/api",
},
specs: [
{
id: "api",
spec: "openapi/openapi.json",
route: "/api",
},
{
id: "workflow",
spec: "openapi/langflow-workflows-openapi.json",
route: "/api/workflow",
},
],
theme: {
primaryColor: "#7528FC",
},
},
],
],
plugins: [
// Alias so MDX can import code from the Langflow repo with !!raw-loader!@langflow/src/...
function langflowCodeImportPlugin(context) {
return {
name: "langflow-code-import",
configureWebpack() {
return {
resolve: {
alias: {
"@langflow": path.resolve(context.siteDir, ".."),
},
},
};
},
};
},
["docusaurus-node-polyfills", { excludeAliases: ["console"] }],
"docusaurus-plugin-image-zoom",
["./src/plugins/segment", { segmentPublicWriteKey: process.env.SEGMENT_PUBLIC_WRITE_KEY, allowedInDev: true }],
[
"@docusaurus/plugin-client-redirects",
{
redirects: [
{
to: "/",
from: [
"/whats-new-a-new-chapter-langflow",
"/👋 Welcome-to-Langflow",
"/getting-started-welcome-to-langflow",
"/guides-new-to-llms",
"/about-langflow",
],
},
{
to: "/get-started-installation",
from: [
"/getting-started-installation",
"/getting-started-common-installation-issues",
],
},
{
to: "/get-started-quickstart",
from: "/getting-started-quickstart",
},
{
to: "/concepts-overview",
from: [
"/workspace-overview",
"/365085a8-a90a-43f9-a779-f8769ec7eca1",
"/My-Collection",
"/workspace",
"/settings-project-general-settings",
],
},
{
to: "/concepts-components",
from: [
"/components",
"/components-overview",
"/components-processing",
"/components-data",
"/components-files",
"/components-logic",
"/components-tools",
"/components-io",
"/components-helpers",
"/components-memories",
],
},
{
to: "/configuration-global-variables",
from: "/settings-global-variables",
},
{
to: "/concepts-playground",
from: [
"/workspace-playground",
"/workspace-logs",
"/guides-chat-memory",
],
},
{
to: "/data-types",
from: ["/guides-data-message", "/configuration-objects"],
},
{
to: "/concepts-flows",
from: [
"/travel-planning-agent",
"/starter-projects-travel-planning-agent",
"/tutorials-travel-planning-agent",
"/starter-projects-dynamic-agent/",
"/simple-agent",
"/math-agent",
"/starter-projects-simple-agent",
"/starter-projects-math-agent",
"/tutorials-math-agent",
"/sequential-agent",
"/starter-projects-sequential-agent",
"/tutorials-sequential-agent",
"/memory-chatbot",
"/starter-projects-memory-chatbot",
"/tutorials-memory-chatbot",
"/financial-report-parser",
"/document-qa",
"/starter-projects-document-qa",
"/tutorials-document-qa",
"/blog-writer",
"/starter-projects-blog-writer",
"/tutorials-blog-writer",
"/basic-prompting",
"/starter-projects-basic-prompting",
"/vector-store-rag",
"/starter-projects-vector-store-rag",
],
},
{
to: "/components-bundle-components",
from: [
"/components-rag",
"/components-vector-stores",
"/components-loaders",
],
},
{
to: "/api-keys-and-authentication",
from: [
"/configuration-api-keys",
"/configuration-authentication",
"/configuration-security-best-practices",
"/Configuration/configuration-security-best-practices",
],
},
{
to: "/environment-variables",
from: [
"/configuration-auto-saving",
"/Configuration/configuration-auto-saving",
"/configuration-backend-only",
"/Configuration/configuration-backend-only",
],
},
{
to: "/concepts-publish",
from: [
"/concepts-api",
"/workspace-api",
],
},
{
to: "/components-custom-components",
from: "/components/custom",
},
{
to: "/mcp-server",
from: "/integrations-mcp",
},
{
to: "/deployment-kubernetes-dev",
from: "/deployment-kubernetes",
},
{
to: "/contributing-github-issues",
from: "/contributing-github-discussions",
},
{
to: "/agents",
from: "/agents-tool-calling-agent-component",
},
{
to: "/concepts-publish",
from: "/embedded-chat-widget",
},
{
to: "/bundles-google",
from: [
"/integrations-setup-google-oauth-langflow",
"/integrations-google-big-query",
],
},
{
to: "/bundles-vertexai",
from: "/integrations-setup-google-cloud-vertex-ai-langflow",
},
{
to: "/develop-application",
from: "/develop-overview",
},
{
to: "/data-types",
from: "/concepts-objects",
},
{
to: "/bundles-apify",
from: "/integrations-apify",
},
{
to: "/bundles-assemblyai",
from: "/integrations-assemblyai",
},
{
to: "/bundles-cleanlab",
from: "/integrations-cleanlab",
},
{
to: "/bundles-composio",
from: "/integrations-composio",
},
{
to: "/bundles-docling",
from: "/integrations-docling",
},
{
to: "/bundles-notion",
from: [
"/integrations/notion/setup",
"/integrations/notion/notion-agent-meeting-notes",
"/integrations/notion/notion-agent-conversational",
],
},
{
to: "/bundles-nvidia",
from: [
"/integrations-nvidia-ingest-wsl2",
"/integrations-nvidia-ingest",
"/integrations-nvidia-g-assist",
"/integrations-nvidia-system-assist",
]
}
// add more redirects like this
// {
// to: '/docs/anotherpage',
// from: ['/docs/legacypage1', '/docs/legacypage2'],
// },
],
},
],
// ....
async function myPlugin(context, options) {
return {
name: "docusaurus-tailwindcss",
configurePostCss(postcssOptions) {
// Appends TailwindCSS and AutoPrefixer.
postcssOptions.plugins.push(require("tailwindcss"));
postcssOptions.plugins.push(require("autoprefixer"));
return postcssOptions;
},
};
},
],
clientModules: [require.resolve("./src/clientModules/tocProgress.js")],
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
navbar: {
hideOnScroll: false,
logo: {
alt: "Langflow",
src: "img/lf-docs-light.svg",
srcDark: "img/lf-docs-dark.svg",
},
items: [
{
type: 'docsVersionDropdown',
position: 'left',
},
// right
{
position: "right",
href: "https://github.com/langflow-ai/langflow",
className: "header-github-link",
target: "_blank",
rel: null,
"aria-label": "GitHub",
'data-event': 'UI Interaction',
'data-action': 'clicked',
'data-channel': 'docs',
'data-element-id': 'social-github',
'data-namespace': 'header',
'data-platform-title': 'Langflow'
},
{
position: "right",
href: "https://twitter.com/langflow_ai",
className: "header-twitter-link",
target: "_blank",
rel: null,
"aria-label": "Twitter",
'data-event': 'UI Interaction',
'data-action': 'clicked',
'data-channel': 'docs',
'data-element-id': 'social-twitter',
'data-namespace': 'header',
'data-platform-title': 'Langflow'
},
{
position: "right",
href: "https://discord.gg/EqksyE2EX9",
className: "header-discord-link",
target: "_blank",
rel: null,
"aria-label": "Discord",
'data-event': 'UI Interaction',
'data-action': 'clicked',
'data-channel': 'docs',
'data-element-id': 'social-discord',
'data-namespace': 'header',
'data-platform-title': 'Langflow'
},
],
},
colorMode: {
defaultMode: "light",
/* Allow users to chose light or dark mode. */
disableSwitch: false,
/* Respect user preferences, such as low light mode in the evening */
respectPrefersColorScheme: true,
},
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme,
},
zoom: {
selector: ".markdown :not(a) > img:not(.no-zoom)",
background: {
light: "rgba(240, 240, 240, 0.9)",
},
config: {},
},
docs: {
sidebar: {
hideable: false,
autoCollapseCategories: false,
},
},
footer: {
links: [
{
title: null,
items: [
{
html: `<div class="footer-links">
<span>© ${new Date().getFullYear()} Langflow</span>
<span id="preferenceCenterContainer"> ·&nbsp; <a href="#" onclick="if(typeof window !== 'undefined' && window.truste && window.truste.eu && window.truste.eu.clickListener) { window.truste.eu.clickListener(); } return false;" style="cursor: pointer;">Manage Privacy Choices</a></span>
</div>`,
},
],
},
],
},
algolia: {
appId: "UZK6BDPCVY",
// public key, safe to commit
apiKey: "adbd7686dceb1cd510d5ce20d04bf74c",
indexName: "langflow",
contextualSearch: true,
searchParameters: {},
searchPagePath: "search",
},
}),
};
module.exports = config;