From 81b178a22c1bdefc4de10e4b9b03eb0d33eb6a80 Mon Sep 17 00:00:00 2001 From: Jonathan Norris Date: Mon, 12 Oct 2026 21:23:53 -0400 Subject: [PATCH 1/2] docs: generate llms.txt and Markdown versions of each page --- .yarnrc.yml | 8 +- .../import-from-anywhere.md | 1 + .../security/compromised-keys.md | 2 +- docs/cli-guides/environments.md | 1 + docs/cli-guides/features.md | 1 + docs/cli-guides/keys.md | 1 + docs/cli-guides/projects.md | 1 + docs/cli-guides/self-targeting.md | 1 + docs/cli-guides/targeting.md | 1 + docs/cli-guides/variables.md | 1 + docs/cli-guides/variations.md | 1 + docs/essentials/architecture.md | 1 + docs/essentials/feature-hierarchy.md | 1 + docs/index.mdx | 2 +- docs/integrations/google-analytics-4.md | 1 + docs/integrations/index.mdx | 5 +- docs/integrations/jira/jira-setup.md | 1 + docs/integrations/jira/jira.md | 1 + docs/integrations/vercel-edge-config.md | 2 +- .../creating-and-managing-metrics.md | 1 + .../feature-experimentation.md | 1 + .../how-metrics-are-calculated.md | 1 + .../tutorial-funnel-experiment.md | 1 + docs/platform/extras/custom-domains.md | 1 + .../stale-feature-notifications.md | 1 + .../targeting/random-variations.md | 1 + .../feature-flags/targeting/rollouts.md | 1 + .../targeting/targeting-overview.md | 1 + .../variable-defaults.md | 1 + .../feature-obfuscation.md | 1 + docs/sdk/client-side-sdks/android/android.md | 1 + docs/sdk/client-side-sdks/flutter/flutter.md | 1 + docs/sdk/client-side-sdks/ios/ios.md | 1 + .../javascript/javascript-typescript.md | 4 +- .../nextjs/nextjs-typescript.md | 4 +- .../react/react-typescript.md | 4 +- docs/sdk/client-side-sdks/react/react.md | 1 + docs/sdk/lifecycle.md | 1 + docs/sdk/sdk-proxy/index.md | 1 + docs/sdk/sdk-proxy/installation.md | 1 + docs/sdk/sdk-proxy/usage.md | 1 + docs/sdk/server-side-sdks/dotnet/dotnet.md | 1 + docs/sdk/server-side-sdks/go/go.md | 1 + docs/sdk/server-side-sdks/java/java.md | 1 + .../nestjs/nestjs-typescript.md | 4 +- .../server-side-sdks/node/node-typescript.md | 4 +- docs/sdk/server-side-sdks/php/php.md | 1 + .../python/python-gettingstarted.md | 1 + docs/sdk/server-side-sdks/ruby/ruby.md | 1 + docusaurus.config.js | 261 +++++++++++++-- package.json | 1 + plugins/llms-txt.js | 116 +++++++ plugins/rehype-llms-cleanup.js | 252 +++++++++++++++ yarn.lock | 303 +++++++++++++++++- 54 files changed, 965 insertions(+), 46 deletions(-) create mode 100644 plugins/llms-txt.js create mode 100644 plugins/rehype-llms-cleanup.js diff --git a/.yarnrc.yml b/.yarnrc.yml index 8deeb1ee..78b20d9d 100644 --- a/.yarnrc.yml +++ b/.yarnrc.yml @@ -2,4 +2,10 @@ compressionLevel: mixed enableGlobalCache: false -nodeLinker: pnpm \ No newline at end of file +nodeLinker: pnpm + +# The plugin imports @docusaurus/logger without declaring it +packageExtensions: + "@signalwire/docusaurus-plugin-llms-txt@*": + dependencies: + "@docusaurus/logger": ^3.0.0 diff --git a/docs/best-practices/edgedb-and-edge-flags/import-from-anywhere.md b/docs/best-practices/edgedb-and-edge-flags/import-from-anywhere.md index 166b33b3..a2682aea 100644 --- a/docs/best-practices/edgedb-and-edge-flags/import-from-anywhere.md +++ b/docs/best-practices/edgedb-and-edge-flags/import-from-anywhere.md @@ -1,5 +1,6 @@ --- title: Super Segments Integrations via Zapier +description: Import user data from external sources like Salesforce into EdgeDB with Zapier sidebar_position: 3 --- diff --git a/docs/best-practices/security/compromised-keys.md b/docs/best-practices/security/compromised-keys.md index f6afcb46..c678dca0 100644 --- a/docs/best-practices/security/compromised-keys.md +++ b/docs/best-practices/security/compromised-keys.md @@ -2,7 +2,7 @@ title: Compromised SDK Keys sidebar_label: Compromised SDK Keys sidebar_position: 2 -description: How to address compromised SDK keys in your environmentden +description: How to address compromised SDK keys in your environment --- # **Compromised SDK Keys** diff --git a/docs/cli-guides/environments.md b/docs/cli-guides/environments.md index a21c1e14..755b6c90 100644 --- a/docs/cli-guides/environments.md +++ b/docs/cli-guides/environments.md @@ -1,5 +1,6 @@ --- title: Environments +description: Create, view, and update Environments with the DevCycle CLI sidebar_position: 2 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/features.md b/docs/cli-guides/features.md index 8b92d032..7d024610 100644 --- a/docs/cli-guides/features.md +++ b/docs/cli-guides/features.md @@ -1,5 +1,6 @@ --- title: Features +description: Create, view, update, and delete Features with the DevCycle CLI sidebar_position: 4 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/keys.md b/docs/cli-guides/keys.md index 242d50f9..b5298942 100644 --- a/docs/cli-guides/keys.md +++ b/docs/cli-guides/keys.md @@ -1,5 +1,6 @@ --- title: SDK Keys +description: Retrieve SDK keys for your Environments with the DevCycle CLI sidebar_position: 3 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/projects.md b/docs/cli-guides/projects.md index 35e8eb62..1fe15de1 100644 --- a/docs/cli-guides/projects.md +++ b/docs/cli-guides/projects.md @@ -1,5 +1,6 @@ --- title: Projects +description: Create and view Projects with the DevCycle CLI sidebar_position: 1 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/self-targeting.md b/docs/cli-guides/self-targeting.md index 8a17e3f7..17150908 100644 --- a/docs/cli-guides/self-targeting.md +++ b/docs/cli-guides/self-targeting.md @@ -1,5 +1,6 @@ --- title: Self-Targeting +description: Manage your DevCycle Identity and Self-Targeting Overrides with the DevCycle CLI sidebar_position: 8 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/targeting.md b/docs/cli-guides/targeting.md index 0104354a..dd3b2820 100644 --- a/docs/cli-guides/targeting.md +++ b/docs/cli-guides/targeting.md @@ -1,5 +1,6 @@ --- title: Targeting Rules +description: View, update, enable, and disable Targeting Rules with the DevCycle CLI sidebar_position: 7 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/variables.md b/docs/cli-guides/variables.md index 0638a39c..d2767955 100644 --- a/docs/cli-guides/variables.md +++ b/docs/cli-guides/variables.md @@ -1,5 +1,6 @@ --- title: Variables +description: Create, view, and update Variables with the DevCycle CLI sidebar_position: 5 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/variations.md b/docs/cli-guides/variations.md index d9e9f738..87cce698 100644 --- a/docs/cli-guides/variations.md +++ b/docs/cli-guides/variations.md @@ -1,5 +1,6 @@ --- title: Variations +description: Create, view, and update Variations with the DevCycle CLI sidebar_position: 6 displayed_sidebar: cli_mcp --- diff --git a/docs/essentials/architecture.md b/docs/essentials/architecture.md index 93db12eb..533bd8c9 100644 --- a/docs/essentials/architecture.md +++ b/docs/essentials/architecture.md @@ -1,5 +1,6 @@ --- title: System Architecture +description: The design goals behind DevCycle and how its APIs, edge workers, and Client, Mobile, and Server SDKs deliver and evaluate Feature configurations sidebar_position: 3 --- diff --git a/docs/essentials/feature-hierarchy.md b/docs/essentials/feature-hierarchy.md index a4492f8f..ef566a3a 100644 --- a/docs/essentials/feature-hierarchy.md +++ b/docs/essentials/feature-hierarchy.md @@ -1,5 +1,6 @@ --- title: Feature Hierarchy +description: How Features, Variables, Variations, and Targeting Rules relate to each other in DevCycle sidebar_position: 4 --- In a traditional Feature Flagging platform, there is only one type of entity to worry about: a `Feature Flag`! In these diff --git a/docs/index.mdx b/docs/index.mdx index a46da64e..cd4ddde6 100644 --- a/docs/index.mdx +++ b/docs/index.mdx @@ -65,6 +65,6 @@ DevCycle is a feature flag platform built for teams of any size, helping you eas
- Your image description +
diff --git a/docs/integrations/google-analytics-4.md b/docs/integrations/google-analytics-4.md index 19c9c8ca..1e49d478 100644 --- a/docs/integrations/google-analytics-4.md +++ b/docs/integrations/google-analytics-4.md @@ -1,5 +1,6 @@ --- title: "Sending DevCycle Data as a Custom Event to Google Analytics 4 (GTM Specific)" +description: Send DevCycle Feature and Variation data to Google Analytics 4 with Google Tag Manager sidebar_position: 1 --- diff --git a/docs/integrations/index.mdx b/docs/integrations/index.mdx index c24122bc..363a5837 100644 --- a/docs/integrations/index.mdx +++ b/docs/integrations/index.mdx @@ -1,5 +1,6 @@ --- title: Integrations +description: First-party tools built on the DevCycle APIs, and third-party integrations that connect DevCycle to your other tools sidebar_class_name: hidden --- @@ -19,9 +20,7 @@ DevCycle APIs, as well as third party integrations to connect DevCycle to the to

If you would like to contribute to an existing integration or tool, all of DevCycle's tools and integrations are{' '} - - open source on the DevCycle Github repository. - + open source on GitHub.

Further, if you'd like to create a new tool or integration, a great diff --git a/docs/integrations/jira/jira-setup.md b/docs/integrations/jira/jira-setup.md index 1ca2b512..ac3d4e5e 100644 --- a/docs/integrations/jira/jira-setup.md +++ b/docs/integrations/jira/jira-setup.md @@ -1,5 +1,6 @@ --- title: 'DevCycle Jira Integration Setup' +description: Install the DevCycle app for Jira and connect it to your DevCycle Organization or Project sidebar_position: 1 --- diff --git a/docs/integrations/jira/jira.md b/docs/integrations/jira/jira.md index e72d42dc..d242df4e 100644 --- a/docs/integrations/jira/jira.md +++ b/docs/integrations/jira/jira.md @@ -1,5 +1,6 @@ --- title: DevCycle Feature Flag Management for Jira +description: Connect DevCycle Features to Jira issues with the DevCycle app for Jira --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/integrations/vercel-edge-config.md b/docs/integrations/vercel-edge-config.md index b2e23682..57872ce5 100644 --- a/docs/integrations/vercel-edge-config.md +++ b/docs/integrations/vercel-edge-config.md @@ -55,7 +55,7 @@ If you do not have the Vercel CLI set up for this project, [follow their steps]( ### Setup SDK -If you haven't already installed the DevCycle [Node.js](https://docs.devcycle.com/sdk/server-side-sdks/node/) or [Next.js](https://docs.devcycle.com/sdk/server-side-sdks/nestjs/) SDK you can follow the installation and usage guides for those SDKs in our [documentation here](https://docs.devcycle.com/sdk/). You can also find helpful setup information like where to find DevCycle SDK keys in our [Quickstart Tutorial](https://docs.devcycle.com/introduction/quickstart). +If you haven't already installed the DevCycle [Node.js](https://docs.devcycle.com/sdk/server-side-sdks/node/) or [Next.js](https://docs.devcycle.com/sdk/client-side-sdks/nextjs/) SDK you can follow the installation and usage guides for those SDKs in our [documentation here](https://docs.devcycle.com/sdk/). You can also find helpful setup information like where to find DevCycle SDK keys in our [Quickstart Tutorial](https://docs.devcycle.com/quickstart). In order to use the integration in a DevCycle SDK, you must install the `@devcycle/vercel-edge-config` package and provide it during SDK initialization. Using that package requires the `@vercel/global-config` package to be installed as well: diff --git a/docs/platform/experimentation/creating-and-managing-metrics.md b/docs/platform/experimentation/creating-and-managing-metrics.md index 58d34562..0fb227d2 100644 --- a/docs/platform/experimentation/creating-and-managing-metrics.md +++ b/docs/platform/experimentation/creating-and-managing-metrics.md @@ -1,5 +1,6 @@ --- title: Creating and Managing Metrics +description: Create, define, and manage Metrics in a Project, and attach them to Features to measure their impact sidebar_position: 2 --- diff --git a/docs/platform/experimentation/feature-experimentation.md b/docs/platform/experimentation/feature-experimentation.md index e3795ae3..36abe238 100644 --- a/docs/platform/experimentation/feature-experimentation.md +++ b/docs/platform/experimentation/feature-experimentation.md @@ -1,5 +1,6 @@ --- title: Feature Experimentation +description: Why and how to run and analyze Experiments on your Features in DevCycle sidebar_position: 1 --- diff --git a/docs/platform/experimentation/how-metrics-are-calculated.md b/docs/platform/experimentation/how-metrics-are-calculated.md index 647c870c..d48a9a15 100644 --- a/docs/platform/experimentation/how-metrics-are-calculated.md +++ b/docs/platform/experimentation/how-metrics-are-calculated.md @@ -1,5 +1,6 @@ --- title: How Metrics are Calculated +description: How DevCycle calculates Metric results and statistical significance for binary conversion and value optimization Metrics sidebar_position: 3 --- diff --git a/docs/platform/experimentation/tutorial-funnel-experiment.md b/docs/platform/experimentation/tutorial-funnel-experiment.md index 1426eb04..21800e04 100644 --- a/docs/platform/experimentation/tutorial-funnel-experiment.md +++ b/docs/platform/experimentation/tutorial-funnel-experiment.md @@ -1,5 +1,6 @@ --- title: "Tutorial: Funnel Experiment" +description: Set up and analyze a funnel experiment across a multi-step sign-up flow sidebar_position: 5 --- diff --git a/docs/platform/extras/custom-domains.md b/docs/platform/extras/custom-domains.md index e6730a2b..9732f515 100644 --- a/docs/platform/extras/custom-domains.md +++ b/docs/platform/extras/custom-domains.md @@ -1,5 +1,6 @@ --- title: Custom Domains +description: Send DevCycle SDK requests and cookies through your own domain so ad blockers and browser privacy features don't block them sidebar_position: 1 --- diff --git a/docs/platform/feature-flags/stale-feature-notifications.md b/docs/platform/feature-flags/stale-feature-notifications.md index eb5996cd..1da7b7a5 100644 --- a/docs/platform/feature-flags/stale-feature-notifications.md +++ b/docs/platform/feature-flags/stale-feature-notifications.md @@ -1,5 +1,6 @@ --- title: Stale Feature Notifications +description: How DevCycle detects potentially stale Features, and how to act on, snooze, or disable stale Feature notifications sidebar_position: 5 --- diff --git a/docs/platform/feature-flags/targeting/random-variations.md b/docs/platform/feature-flags/targeting/random-variations.md index 758f38a6..16f2f747 100644 --- a/docs/platform/feature-flags/targeting/random-variations.md +++ b/docs/platform/feature-flags/targeting/random-variations.md @@ -1,5 +1,6 @@ --- title: Random Variations +description: Serve a random distribution of Variations to users who match a Targeting Rule sidebar_position: 4 --- diff --git a/docs/platform/feature-flags/targeting/rollouts.md b/docs/platform/feature-flags/targeting/rollouts.md index 4b336ffc..ae87f58c 100644 --- a/docs/platform/feature-flags/targeting/rollouts.md +++ b/docs/platform/feature-flags/targeting/rollouts.md @@ -1,5 +1,6 @@ --- title: Scheduling & Rollouts +description: Schedule Feature releases and configure gradual and multi-step rollouts sidebar_position: 5 --- diff --git a/docs/platform/feature-flags/targeting/targeting-overview.md b/docs/platform/feature-flags/targeting/targeting-overview.md index ba4417f2..0da9d767 100644 --- a/docs/platform/feature-flags/targeting/targeting-overview.md +++ b/docs/platform/feature-flags/targeting/targeting-overview.md @@ -1,5 +1,6 @@ --- title: Targeting Overview +description: Use Targeting Rules to grant Features to specific user groups, roll out Features incrementally, and test different Feature configurations sidebar_position: 1 --- diff --git a/docs/platform/feature-flags/variables-and-variations/variable-defaults.md b/docs/platform/feature-flags/variables-and-variations/variable-defaults.md index 7244db5c..21589117 100644 --- a/docs/platform/feature-flags/variables-and-variations/variable-defaults.md +++ b/docs/platform/feature-flags/variables-and-variations/variable-defaults.md @@ -1,5 +1,6 @@ --- title: Variable Defaults +description: When DevCycle SDKs fall back to the default value you provide in code for a Variable sidebar_position: 3 --- diff --git a/docs/platform/security-and-guardrails/feature-obfuscation.md b/docs/platform/security-and-guardrails/feature-obfuscation.md index e6e72c27..ec1fa2a3 100644 --- a/docs/platform/security-and-guardrails/feature-obfuscation.md +++ b/docs/platform/security-and-guardrails/feature-obfuscation.md @@ -1,5 +1,6 @@ --- title: Feature Obfuscation +description: Obfuscate Variable keys in web SDKs so unreleased Feature names can't be found in the code shipped to users sidebar_position: 4 --- diff --git a/docs/sdk/client-side-sdks/android/android.md b/docs/sdk/client-side-sdks/android/android.md index ed959ea2..2f2deb9b 100644 --- a/docs/sdk/client-side-sdks/android/android.md +++ b/docs/sdk/client-side-sdks/android/android.md @@ -1,5 +1,6 @@ --- title: Android SDK +description: The DevCycle Android Client SDK, which uses the Client SDK APIs and globally distributed edge workers for segmentation and bucketing sidebar_position: 4 --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/client-side-sdks/flutter/flutter.md b/docs/sdk/client-side-sdks/flutter/flutter.md index f71a5920..e9f99d77 100644 --- a/docs/sdk/client-side-sdks/flutter/flutter.md +++ b/docs/sdk/client-side-sdks/flutter/flutter.md @@ -1,5 +1,6 @@ --- title: Flutter SDK +description: The DevCycle Flutter Client SDK, which uses the Client SDK APIs and globally distributed edge workers for segmentation and bucketing --- import CustomDocCardList from '@site/src/components/CustomDocCardList' import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; diff --git a/docs/sdk/client-side-sdks/ios/ios.md b/docs/sdk/client-side-sdks/ios/ios.md index d14e344c..e1298776 100644 --- a/docs/sdk/client-side-sdks/ios/ios.md +++ b/docs/sdk/client-side-sdks/ios/ios.md @@ -1,5 +1,6 @@ --- title: iOS SDK +description: The DevCycle Swift Client SDK for iOS, macOS, tvOS, and watchOS applications --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/client-side-sdks/javascript/javascript-typescript.md b/docs/sdk/client-side-sdks/javascript/javascript-typescript.md index f953eeb4..8749a9d1 100644 --- a/docs/sdk/client-side-sdks/javascript/javascript-typescript.md +++ b/docs/sdk/client-side-sdks/javascript/javascript-typescript.md @@ -14,7 +14,7 @@ sidebar_custom_props: { icon: cib:typescript } The DevCycle JS SDK is written in Typescript and includes a full Typescript interface. It is also possible to enhance the type safety of the SDK by using the -[Devcycle CLI](https://docs.devcycle.com/tools-and-integrations/cli) to generate a type definition +[Devcycle CLI](https://docs.devcycle.com/cli) to generate a type definition based on the complete set of variables defined in your project. Using this method, you can ensure that your code cannot access a variable key that is not defined in DevCycle, or treat a variable as a different type. @@ -80,7 +80,7 @@ dvc generate types See the [documentation](https://github.com/DevCycleHQ/cli/blob/main/docs/generate.md#dvc-generate-types) for this command -Ensure that the CLI is properly setup and authenticated to your project before running this command. See the [CLI docs](https://docs.devcycle.com/tools-and-integrations/cli) +Ensure that the CLI is properly setup and authenticated to your project before running this command. See the [CLI docs](https://docs.devcycle.com/cli) for further instructions on setting up the CLI. This command will generate a file called `dvcVariableTypes.ts` in the configured output directory. diff --git a/docs/sdk/client-side-sdks/nextjs/nextjs-typescript.md b/docs/sdk/client-side-sdks/nextjs/nextjs-typescript.md index 95b53ecf..89ec6264 100644 --- a/docs/sdk/client-side-sdks/nextjs/nextjs-typescript.md +++ b/docs/sdk/client-side-sdks/nextjs/nextjs-typescript.md @@ -14,7 +14,7 @@ sidebar_custom_props: {icon: cib:typescript} The DevCycle Next.js SDK is written in Typescript and includes a full Typescript interface. It is also possible to enhance the type safety of the SDK by using the -[Devcycle CLI](https://docs.devcycle.com/tools-and-integrations/cli) to generate a type definition +[Devcycle CLI](https://docs.devcycle.com/cli) to generate a type definition based on the complete set of variables defined in your project. Using this method, you can ensure that your code cannot access a variable key that is not defined in DevCycle, or treat a variable as a different type. @@ -73,7 +73,7 @@ dvc generate types See the [documentation](https://github.com/DevCycleHQ/cli/blob/main/docs/generate.md#dvc-generate-types) for this command -Ensure that the CLI is properly setup and authenticated to your project before running this command. See the [CLI docs](https://docs.devcycle.com/tools-and-integrations/cli) +Ensure that the CLI is properly setup and authenticated to your project before running this command. See the [CLI docs](https://docs.devcycle.com/cli) for further instructions on setting up the CLI. This command will generate a file called `dvcVariableTypes.ts` in the configured output directory. The generated output will contain the `declare module` statement to automatically augment the SDK's types. diff --git a/docs/sdk/client-side-sdks/react/react-typescript.md b/docs/sdk/client-side-sdks/react/react-typescript.md index 1bdacfe1..78c85030 100644 --- a/docs/sdk/client-side-sdks/react/react-typescript.md +++ b/docs/sdk/client-side-sdks/react/react-typescript.md @@ -14,7 +14,7 @@ sidebar_custom_props: {icon: cib:typescript} The DevCycle React SDK is written in Typescript and includes a full Typescript interface. It is also possible to enhance the type safety of the SDK by using the -[Devcycle CLI](https://docs.devcycle.com/tools-and-integrations/cli) to generate a type definition +[Devcycle CLI](https://docs.devcycle.com/cli) to generate a type definition based on the complete set of variables defined in your project. Using this method, you can ensure that your code cannot access a variable key that is not defined in DevCycle, or treat a variable as a different type. @@ -68,7 +68,7 @@ dvc generate types See the [documentation](https://github.com/DevCycleHQ/cli/blob/main/docs/generate.md#dvc-generate-types) for this command -Ensure that the CLI is properly setup and authenticated to your project before running this command. See the [CLI docs](https://docs.devcycle.com/tools-and-integrations/cli) +Ensure that the CLI is properly setup and authenticated to your project before running this command. See the [CLI docs](https://docs.devcycle.com/cli) for further instructions on setting up the CLI. This command will generate a file called `dvcVariableTypes.ts` in the configured output directory. The generated output will contain the `declare module` statement to automatically augment the SDK's types. diff --git a/docs/sdk/client-side-sdks/react/react.md b/docs/sdk/client-side-sdks/react/react.md index d5f38656..ab4eeb0e 100644 --- a/docs/sdk/client-side-sdks/react/react.md +++ b/docs/sdk/client-side-sdks/react/react.md @@ -1,5 +1,6 @@ --- title: React SDK +description: The DevCycle React SDK for React web applications, also used by the React Native SDK --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/lifecycle.md b/docs/sdk/lifecycle.md index 2ddf1b57..b7f5e794 100644 --- a/docs/sdk/lifecycle.md +++ b/docs/sdk/lifecycle.md @@ -1,5 +1,6 @@ --- title: SDK Release Lifecycle +description: How long each DevCycle SDK major version is supported, and which fixes are backported to previous versions --- # SDK Release Lifecycle diff --git a/docs/sdk/sdk-proxy/index.md b/docs/sdk/sdk-proxy/index.md index bc0b974e..221019fe 100644 --- a/docs/sdk/sdk-proxy/index.md +++ b/docs/sdk/sdk-proxy/index.md @@ -1,5 +1,6 @@ --- title: Overview +description: A self-hosted proxy between DevCycle SDKs and the DevCycle APIs, for restricted networks or to share one external connection across many SDK instances --- diff --git a/docs/sdk/sdk-proxy/installation.md b/docs/sdk/sdk-proxy/installation.md index b165d763..fe45a0fe 100644 --- a/docs/sdk/sdk-proxy/installation.md +++ b/docs/sdk/sdk-proxy/installation.md @@ -1,5 +1,6 @@ --- title: Installation +description: Install the DevCycle SDK Proxy from source, as a Docker image, or as an OS packaged binary --- # Installation diff --git a/docs/sdk/sdk-proxy/usage.md b/docs/sdk/sdk-proxy/usage.md index b7db6a85..8c10ce20 100644 --- a/docs/sdk/sdk-proxy/usage.md +++ b/docs/sdk/sdk-proxy/usage.md @@ -1,5 +1,6 @@ --- title: Usage +description: Run the SDK Proxy and configure server SDKs to connect to it --- ## Running the SDK Proxy diff --git a/docs/sdk/server-side-sdks/dotnet/dotnet.md b/docs/sdk/server-side-sdks/dotnet/dotnet.md index 412e40af..0d5a0155 100644 --- a/docs/sdk/server-side-sdks/dotnet/dotnet.md +++ b/docs/sdk/server-side-sdks/dotnet/dotnet.md @@ -1,5 +1,6 @@ --- title: .NET SDK +description: The DevCycle .NET / C# SDK for Cloud Bucketing and Local Bucketing --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/server-side-sdks/go/go.md b/docs/sdk/server-side-sdks/go/go.md index bd3802be..ac5c2905 100644 --- a/docs/sdk/server-side-sdks/go/go.md +++ b/docs/sdk/server-side-sdks/go/go.md @@ -1,5 +1,6 @@ --- title: Go SDK +description: The DevCycle Go Server SDK, supporting Local Bucketing and Cloud Bucketing modes --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/server-side-sdks/java/java.md b/docs/sdk/server-side-sdks/java/java.md index b286a791..558f3f22 100644 --- a/docs/sdk/server-side-sdks/java/java.md +++ b/docs/sdk/server-side-sdks/java/java.md @@ -1,5 +1,6 @@ --- title: Java SDK +description: The DevCycle Java Server SDK, supporting Local Bucketing and Cloud Bucketing modes --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/server-side-sdks/nestjs/nestjs-typescript.md b/docs/sdk/server-side-sdks/nestjs/nestjs-typescript.md index 55822ddc..416adc89 100644 --- a/docs/sdk/server-side-sdks/nestjs/nestjs-typescript.md +++ b/docs/sdk/server-side-sdks/nestjs/nestjs-typescript.md @@ -14,7 +14,7 @@ sidebar_custom_props: {icon: cib:typescript} The DevCycle NestJS SDK is written in Typescript and includes a full Typescript interface. It is also possible to enhance the type safety of the SDK by using the -[Devcycle CLI](https://docs.devcycle.com/tools-and-integrations/cli) to generate a type definition +[Devcycle CLI](https://docs.devcycle.com/cli) to generate a type definition based on the complete set of variables defined in your project. Using this method, you can ensure that your code cannot access a variable key that is not defined in DevCycle, or treat a variable as a different type. @@ -70,7 +70,7 @@ dvc generate types See the [documentation](https://github.com/DevCycleHQ/cli/blob/main/docs/generate.md#dvc-generate-types) for this command -Ensure that the CLI is properly setup and authenticated to your project before running this command. See the [CLI docs](https://docs.devcycle.com/tools-and-integrations/cli) +Ensure that the CLI is properly setup and authenticated to your project before running this command. See the [CLI docs](https://docs.devcycle.com/cli) for further instructions on setting up the CLI. This command will generate a file called `dvcVariableTypes.ts` in the configured output directory. diff --git a/docs/sdk/server-side-sdks/node/node-typescript.md b/docs/sdk/server-side-sdks/node/node-typescript.md index 27d95f9a..cbb2ae3b 100644 --- a/docs/sdk/server-side-sdks/node/node-typescript.md +++ b/docs/sdk/server-side-sdks/node/node-typescript.md @@ -14,7 +14,7 @@ sidebar_custom_props: {icon: cib:typescript} The DevCycle Node.js SDK is written in Typescript and includes a full Typescript interface. It is also possible to enhance the type safety of the SDK by using the -[Devcycle CLI](https://docs.devcycle.com/tools-and-integrations/cli) to generate a type definition +[Devcycle CLI](https://docs.devcycle.com/cli) to generate a type definition based on the complete set of variables defined in your project. Using this method, you can ensure that your code cannot access a variable key that is not defined in DevCycle, or treat a variable as a different type. @@ -80,7 +80,7 @@ dvc generate types See the [documentation](https://github.com/DevCycleHQ/cli/blob/main/docs/generate.md#dvc-generate-types) for this command -Ensure that the CLI is properly setup and authenticated to your project before running this command. See the [CLI docs](https://docs.devcycle.com/tools-and-integrations/cli) +Ensure that the CLI is properly setup and authenticated to your project before running this command. See the [CLI docs](https://docs.devcycle.com/cli) for further instructions on setting up the CLI. This command will generate a file called `dvcVariableTypes.ts` in the configured output directory. diff --git a/docs/sdk/server-side-sdks/php/php.md b/docs/sdk/server-side-sdks/php/php.md index a88cb766..295dbcc4 100644 --- a/docs/sdk/server-side-sdks/php/php.md +++ b/docs/sdk/server-side-sdks/php/php.md @@ -1,5 +1,6 @@ --- title: PHP SDK +description: The DevCycle PHP Server SDK, which uses Cloud Bucketing, with local bucketing available through the SDK Proxy --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/server-side-sdks/python/python-gettingstarted.md b/docs/sdk/server-side-sdks/python/python-gettingstarted.md index afc354da..52e26894 100644 --- a/docs/sdk/server-side-sdks/python/python-gettingstarted.md +++ b/docs/sdk/server-side-sdks/python/python-gettingstarted.md @@ -12,6 +12,7 @@ sidebar_custom_props: { icon: material-symbols:rocket } ## Initializing Local Bucketing SDK Code sample for importing and setting up the DevCycleLocalClient. + [//]: # 'wizard-initialize-start' ```python diff --git a/docs/sdk/server-side-sdks/ruby/ruby.md b/docs/sdk/server-side-sdks/ruby/ruby.md index 833f7d5a..e027529a 100644 --- a/docs/sdk/server-side-sdks/ruby/ruby.md +++ b/docs/sdk/server-side-sdks/ruby/ruby.md @@ -1,5 +1,6 @@ --- title: Ruby SDK +description: The DevCycle Ruby Server SDK, supporting Local Bucketing and Cloud Bucketing modes --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docusaurus.config.js b/docusaurus.config.js index 16eccc18..c24fd508 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -1,5 +1,9 @@ require('dotenv').config() const path = require('path') +const { + rehypeLlmsCleanup, + rehypeLlmsFixIndexLinks, +} = require('./plugins/rehype-llms-cleanup') import remarkEmbedder from '@remark-embedder/core' const YouTubeTransformer = { name: 'YouTubeTransformer', @@ -55,6 +59,107 @@ const VSCODE_EXTENSION_VERSION = 'v1.4.10' // auto updated by extension release const AI_PROMPTS_VERSION = 'main' // AI prompts repository branch +const SITE_URL = process.env.CF_PAGES + ? 'https://docs.devcycle.com' + : 'http://localhost:3000' + +/** + * Section names for llms.txt. Routes not listed here are grouped by their + * top-level path segment. + */ +const LLMS_SDK_NAMES = { + 'client-side-sdks': { + android: 'Android', + angular: 'Angular', + flutter: 'Flutter', + ios: 'iOS', + javascript: 'JavaScript', + nextjs: 'Next.js', + react: 'React', + 'react-native': 'React Native', + roku: 'Roku', + }, + 'server-side-sdks': { + dotnet: '.NET', + go: 'Go', + java: 'Java', + nestjs: 'NestJS', + node: 'Node.js', + php: 'PHP', + python: 'Python', + ruby: 'Ruby', + }, +} + +const LLMS_EXCLUDE_ROUTES = [ + '/search', + '/management-api/**', + '/bucketing-api/**', + // Example app pages only link out to GitHub repos and sandboxes + '/sdk/**/*-example', + // Generated `dvc --help` output; cli-guides covers the same commands + '/cli/docs/**', + // Build and deploy notes for the hosted MCP worker itself + '/cli/mcp-worker{,/}', + // Video-only page + '/platform/experimentation/tutorial-experiment-setup', +] + +const LLMS_ROUTE_RULES = [ + { route: '/quickstart', categoryName: 'Quickstart' }, + { route: '/essentials/**', categoryName: 'Essentials' }, + { route: '/platform/**', categoryName: 'Platform', depth: 2 }, + ...Object.entries({ + 'account-management': 'Account Management', + experimentation: 'Experimentation', + extras: 'Extras', + 'feature-flags': 'Feature Flags', + 'security-and-guardrails': 'Security and Guardrails', + 'testing-and-qa': 'Testing and QA', + }).map(([dir, categoryName]) => ({ + route: `/platform/${dir}/**`, + categoryName, + depth: 2, + })), + { route: '/sdk/**', categoryName: 'SDKs' }, + { route: '/sdk/sdk-proxy/**', categoryName: 'SDK Proxy', depth: 2 }, + { + route: '/sdk/client-side-sdks/**', + categoryName: 'Client-Side SDKs', + depth: 3, + }, + { + route: '/sdk/server-side-sdks/**', + categoryName: 'Server-Side SDKs', + depth: 3, + }, + ...Object.entries(LLMS_SDK_NAMES).flatMap(([group, sdks]) => + Object.entries(sdks).map(([dir, categoryName]) => ({ + route: `/sdk/${group}/${dir}/**`, + categoryName, + depth: 3, + })), + ), + { route: '/integrations/**', categoryName: 'Integrations' }, + { route: '/cli-mcp/**', categoryName: 'MCP Server' }, + { route: '/cli-guides/**', categoryName: 'CLI Guides' }, + { route: '/cli/**', categoryName: 'CLI' }, + { route: '/best-practices/**', categoryName: 'Best Practices' }, + { route: '/examples', categoryName: 'Examples' }, +] + +/** + * Prepend frontmatter to remote content. Without a description, Docusaurus + * uses the first line of the page, which is often a heading or badge. + */ +const withFrontMatter = (fields, content) => + '---\n' + + Object.entries(fields) + .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) + .join('\n') + + '\n---\n' + + content + const removeDocsSections = (content, sectionNames, headerIdentifier = '##') => { let result = content for (const sectionName of sectionNames) { @@ -99,6 +204,64 @@ const config = { } }, path.resolve(__dirname, 'plugins', 'custom-gtm'), + [ + path.resolve(__dirname, 'plugins', 'llms-txt.js'), + { + siteTitle: 'DevCycle Docs', + siteDescription: + 'DevCycle is a feature flag management and experimentation platform with SDKs for every major language, native OpenFeature providers, a CLI, and an MCP server for AI coding tools.', + depth: 1, + includeOrder: [ + '/', + '/quickstart', + '/essentials/**', + '/platform/**', + '/sdk/**', + '/integrations/**', + '/cli-mcp/**', + '/cli-guides/**', + '/cli/**', + '/best-practices/**', + '/examples', + ], + optionalLinks: [ + { + title: 'Management API OpenAPI spec', + url: 'https://api.devcycle.com/openapi.json', + description: + 'Manage projects, features, variables, environments, and targeting', + }, + { + title: 'Bucketing API OpenAPI spec', + url: 'https://bucketing-api.devcycle.com/openapi.yaml', + description: + 'Evaluate variables and track events for a user, used by Cloud Bucketing SDKs', + }, + { + title: 'DevCycle on GitHub', + url: 'https://github.com/DevCycleHQ', + }, + ], + content: { + enableLlmsFullTxt: true, + relativePaths: false, + excludeRoutes: LLMS_EXCLUDE_ROUTES, + beforeDefaultRehypePlugins: [ + [rehypeLlmsCleanup, { siteUrl: SITE_URL }], + ], + rehypePlugins: [ + [ + rehypeLlmsFixIndexLinks, + { + siteUrls: [SITE_URL, 'https://docs.devcycle.com'], + excludeRoutes: LLMS_EXCLUDE_ROUTES, + }, + ], + ], + routeRules: LLMS_ROUTE_RULES, + }, + }, + ], [ 'docusaurus-plugin-remote-content', { @@ -134,9 +297,37 @@ const config = { performCleanup: true, modifyContent: (filename, content) => { if (filename.includes('README')) { + // reduce headers to use with table of contents, skipping code blocks + let inFence = false + const reduced = content + .split('\n') + .map((line) => { + if (/^\s*(```|~~~)/.test(line)) inFence = !inFence + return inFence ? line : line.replace(/^(#{1,5})\s/, '#$1 ') + }) + .join('\n') + return { + content: filename.includes('mcp-worker') + ? withFrontMatter( + { + title: 'DevCycle MCP Cloudflare Worker', + description: + 'The hosted DevCycle MCP server, running as a Cloudflare Worker with OAuth authentication', + }, + reduced, + ) + : reduced, + } + } + if (filename.endsWith('mcp.md')) { return { - // reduce headers to use with table of contents - content: content.replace(/#\s/g, '## '), + content: withFrontMatter( + { + description: + 'Tools, authentication, and configuration for the local and hosted DevCycle MCP servers', + }, + content, + ), } } return undefined @@ -158,12 +349,18 @@ const config = { '# DevCycle VSCode Extension \n##', ) return { - content: removeDocsSections(noTitle, [ - 'About DevCycle', - 'Documentation', - 'Sign Up for DevCycle', - 'Contributing', - ]), + content: withFrontMatter( + { + description: + 'Manage and track DevCycle feature flags from Visual Studio Code', + }, + removeDocsSections(noTitle, [ + 'About DevCycle', + 'Documentation', + 'Sign Up for DevCycle', + 'Contributing', + ]), + ), } } return undefined @@ -180,10 +377,15 @@ const config = { documents: ['README.md'], performCleanup: true, modifyContent: (filename, content) => ({ - content: + content: withFrontMatter( + { + description: + 'Show DevCycle Variable code usages in the dashboard with a GitHub Action', + }, '# GitHub: Feature Flag Code Usages \n' + - 'Get the integration on the [GitHub Marketplace](https://github.com/marketplace/actions/devcycle-feature-flag-code-usages)\n' + - content, + 'Get the integration on the [GitHub Marketplace](https://github.com/marketplace/actions/devcycle-feature-flag-code-usages)\n' + + content, + ), }), }, ], @@ -197,10 +399,15 @@ const config = { documents: ['README.md'], performCleanup: true, modifyContent: (filename, content) => ({ - content: + content: withFrontMatter( + { + description: + 'Comment on pull requests with the DevCycle Features added or removed in each change, using a GitHub Action', + }, '# GitHub: Feature Flag Change Insights on Pull Request \n' + - 'Get the integration on the [GitHub Marketplace](https://github.com/marketplace/actions/devcycle-feature-flag-insights-for-pull-requests)\n' + - content, + 'Get the integration on the [GitHub Marketplace](https://github.com/marketplace/actions/devcycle-feature-flag-insights-for-pull-requests)\n' + + content, + ), }), }, ], @@ -214,10 +421,15 @@ const config = { documents: ['README.md'], performCleanup: true, modifyContent: (filename, content) => ({ - content: + content: withFrontMatter( + { + description: + 'Show DevCycle Variable code usages in the dashboard with a GitLab CI/CD pipeline', + }, '# GitLab: Feature Flag Code Usages \n' + - 'Get the integration here: https://gitlab.com/devcycle/devcycle-usages-ci-cd\n' + - content, + 'Get the integration here: https://gitlab.com/devcycle/devcycle-usages-ci-cd\n' + + content, + ), }), }, ], @@ -231,10 +443,15 @@ const config = { documents: ['README.md'], performCleanup: true, modifyContent: (filename, content) => ({ - content: + content: withFrontMatter( + { + description: + 'Comment on merge requests with the DevCycle Features added or removed in each change, using a GitLab CI/CD pipeline', + }, '# GitLab: Feature Flag Change Insights on Merge Request\n' + - 'Get the integration here: https://gitlab.com/devcycle/devcycle-pr-insights-ci-cd\n' + - content, + 'Get the integration here: https://gitlab.com/devcycle/devcycle-pr-insights-ci-cd\n' + + content, + ), }), }, ], @@ -343,9 +560,7 @@ const config = { }, DEVCYCLE_CLIENT_SDK_KEY: process.env.DEVCYCLE_CLIENT_SDK_KEY, }, - url: process.env.CF_PAGES - ? 'https://docs.devcycle.com' - : 'http://localhost:3000', + url: SITE_URL, baseUrl: '/', favicon: 'devcycle_favicon.svg', scripts: [ diff --git a/package.json b/package.json index 54b5e278..520706c2 100644 --- a/package.json +++ b/package.json @@ -53,6 +53,7 @@ "@docusaurus/tsconfig": "^3.9.2", "@docusaurus/types": "^3.9.2", "@iconify-icon/react": "^1.0.8", + "@signalwire/docusaurus-plugin-llms-txt": "^1.2.2", "@types/react": "^18.3.20", "typescript": "~5.8.2" }, diff --git a/plugins/llms-txt.js b/plugins/llms-txt.js new file mode 100644 index 00000000..bfe552c7 --- /dev/null +++ b/plugins/llms-txt.js @@ -0,0 +1,116 @@ +/** + * Wraps @signalwire/docusaurus-plugin-llms-txt and tidies the generated + * llms.txt index after it is written: + * - drops the category description the plugin prints under a section heading + * when the same description is repeated on the index page link right below + * - collapses the extra blank lines left by sections without an index page + * - adds the missing blank line after the `## Optional` heading + * + * llms-full.txt starts with a copy of llms.txt, so that prefix is replaced too. + * + * It also removes backslash escapes the Markdown serializer adds where they are + * not needed (`user\_id`, `?a=1\&b=2`) from the generated pages, since LLMs + * copy identifiers and URLs verbatim. Code blocks and inline code are untouched. + */ +const fs = require('fs/promises') +const path = require('path') +const { loadFreshModule } = require('@docusaurus/utils') + +function tidyIndex(content) { + const lines = content.split('\n') + const out = [] + for (let i = 0; i < lines.length; i++) { + const line = lines[i] + const next = lines[i + 2] + if ( + /^#{2,} /.test(lines[i - 2] ?? '') && + line && + !line.startsWith('- ') && + next?.startsWith('- [') && + next.endsWith(`: ${line}`) + ) { + i++ // also skip the blank line after the description + continue + } + out.push(line) + } + return out + .join('\n') + .replace(/\n{3,}/g, '\n\n') + .replace(/^## Optional\n(?=-)/m, '## Optional\n\n') +} + +function unescapeProse(markdown) { + let fence = null + return markdown + .split('\n') + .map((line) => { + const marker = /^\s*(`{3,}|~{3,})/.exec(line)?.[1] + if (marker) { + if (!fence) fence = marker + else if (marker[0] === fence[0] && marker.length >= fence.length) + fence = null + return line + } + if (fence) return line + return line + .split(/(`+[^`]*`+)/) + .map((part, i) => + i % 2 + ? part + : part + .replace(/(?<=[A-Za-z0-9])\\_(?=[A-Za-z0-9])/g, '_') + .replace(/\\&(?![A-Za-z0-9#]+;)/g, '&'), + ) + .join('') + }) + .join('\n') +} + +// Generated pages sit next to the HTML page they were made from, unlike +// Markdown files copied from static/ +async function generatedPages(outDir) { + const files = await fs.readdir(outDir, { recursive: true }) + const all = new Set(files) + return files.filter( + (f) => + f.endsWith('.md') && + (all.has(f.replace(/\.md$/, '.html')) || + all.has(path.join(f.replace(/\.md$/, ''), 'index.html'))), + ) +} + +async function rewrite(file, fn) { + const content = await fs.readFile(file, 'utf8').catch(() => null) + if (content !== null) await fs.writeFile(file, fn(content)) +} + +module.exports = async function llmsTxtPlugin(context, options) { + // Load the plugin the way Docusaurus does, since its ESM build uses + // extensionless imports that Node's native loader rejects + const { default: plugin } = await loadFreshModule( + require.resolve('@signalwire/docusaurus-plugin-llms-txt'), + ) + const instance = plugin(context, options) + return { + ...instance, + async postBuild(props) { + await instance.postBuild(props) + const { outDir } = props + for (const page of await generatedPages(outDir)) { + await rewrite(path.join(outDir, page), unescapeProse) + } + const llmsPath = path.join(outDir, 'llms.txt') + const original = await fs.readFile(llmsPath, 'utf8') + const tidied = tidyIndex(original) + await fs.writeFile(llmsPath, tidied) + await rewrite(path.join(outDir, 'llms-full.txt'), (full) => + unescapeProse( + full.startsWith(original) + ? tidied + full.slice(original.length) + : full, + ), + ) + }, + } +} diff --git a/plugins/rehype-llms-cleanup.js b/plugins/rehype-llms-cleanup.js new file mode 100644 index 00000000..b69535c7 --- /dev/null +++ b/plugins/rehype-llms-cleanup.js @@ -0,0 +1,252 @@ +/** + * Rehype plugins that normalize Docusaurus-rendered HTML before + * @signalwire/docusaurus-plugin-llms-txt converts it to Markdown. + * + * rehypeLlmsCleanup (runs before the built-in link rewriting): + * - drops heading permalinks, buttons, comments, and the AI prompt copy row + * - replaces YouTube embeds with a plain link + * - restores code block languages and line breaks from Prism output + * - labels each tab panel instead of emitting a detached list of tab names + * - turns admonitions into blockquotes with a bold label + * - turns doc card grids into a bullet list instead of a run of headings + * - turns

summaries into a bold line + * - drops decorative images (empty alt) and inlined base64 images, decodes + * alt text, and makes image URLs absolute + * - turns
outside tables into a line break and moves spaces out of bold + * and italic elements + * + * rehypeLlmsFixIndexLinks (runs after the built-in link rewriting and the + * HTML-to-Markdown conversion, so it walks Markdown link nodes): + * - fixes links to trailing-slash routes, which the plugin emits as `/path/.md` + * - points absolute links to doc pages (e.g. https://docs.devcycle.com/cli), + * which the plugin leaves alone, at their `.md` versions + * - points links to excluded routes back at the HTML page, since they have no + * `.md` version + */ + +const { createMatcher } = require('@docusaurus/utils') + +const classList = (node) => { + const cls = node.type === 'element' ? node.properties?.className : undefined + if (Array.isArray(cls)) return cls.map(String) + return typeof cls === 'string' ? cls.split(' ') : [] +} + +const hasClass = (node, name) => classList(node).includes(name) + +const hasClassPrefix = (node, prefix) => + classList(node).some((c) => c.startsWith(prefix)) + +const textOf = (node) => + node.type === 'text' + ? node.value + : node.children + ? node.children.map(textOf).join('') + : '' + +const findAll = (node, pred, out = []) => { + if (node.type === 'element' && pred(node)) out.push(node) + else if (node.children) node.children.forEach((c) => findAll(c, pred, out)) + return out +} + +const find = (node, pred) => findAll(node, pred)[0] + +const el = (tagName, children, properties = {}) => ({ + type: 'element', + tagName, + properties, + children, +}) + +const txt = (value) => ({ type: 'text', value }) + +const youtubeId = (src) => + /youtube(?:-nocookie)?\.com\/embed\/([^?&#/]+)/.exec(src)?.[1] + +const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1) + +// Docusaurus escapes image alt text twice, leaving entities like `'` +const decodeEntities = (s) => + s + .replace(/&#(\d+);/g, (_, n) => String.fromCodePoint(Number(n))) + .replace(/&#x([0-9a-f]+);/gi, (_, n) => + String.fromCodePoint(parseInt(n, 16)), + ) + .replace(/"/g, '"') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/&/g, '&') + +const INLINE_EMPHASIS = new Set(['b', 'strong', 'em', 'i']) + +// Move leading/trailing spaces out of ` text `, which would otherwise +// be serialized as `**text **` +function hoistWhitespace(element) { + const first = element.children[0] + const last = element.children[element.children.length - 1] + const lead = first?.type === 'text' ? /^\s+/.exec(first.value)?.[0] : null + const trail = last?.type === 'text' ? /\s+$/.exec(last.value)?.[0] : null + if (lead) first.value = first.value.slice(lead.length) + if (trail && last.value) last.value = last.value.slice(0, -trail.length) + return [lead && txt(' '), element, trail && txt(' ')].filter(Boolean) +} + +function transform(node, options, inTable = false) { + const out = [] + for (const child of node.children) { + if (child.type === 'comment') continue + if (child.type !== 'element') { + out.push(child) + continue + } + if ( + hasClass(child, 'hash-link') || + hasClass(child, 'aiPromptRow') || + child.tagName === 'button' + ) { + continue + } + + if (child.tagName === 'iframe') { + const id = youtubeId(String(child.properties?.src ?? '')) + if (id) { + const href = `https://www.youtube.com/watch?v=${id}` + out.push(el('p', [txt('Video: '), el('a', [txt(href)], { href })])) + } + continue + } + + if (child.tagName === 'pre') { + const lang = classList(child).find((c) => c.startsWith('language-')) + const lines = findAll(child, (n) => hasClass(n, 'token-line')).map(textOf) + const code = lines.length ? lines.join('\n') : textOf(child) + out.push( + el('pre', [el('code', [txt(code)], lang ? { className: [lang] } : {})]), + ) + continue + } + + if (hasClass(child, 'tabs-container')) { + const labels = findAll(child, (n) => n.properties?.role === 'tab').map( + textOf, + ) + const panels = findAll(child, (n) => n.properties?.role === 'tabpanel') + panels.forEach((panel, i) => { + out.push(el('p', [el('strong', [txt(labels[i] ?? `Tab ${i + 1}`)])])) + out.push(...transform(panel, options, inTable).children) + }) + continue + } + + if (hasClass(child, 'theme-admonition')) { + const heading = find(child, (n) => hasClassPrefix(n, 'admonitionHeading')) + const content = find(child, (n) => hasClassPrefix(n, 'admonitionContent')) + const title = capitalize(heading ? textOf(heading).trim() : 'Note') + const label = /[.:?!]$/.test(title) ? title : `${title}:` + const body = content ? transform(content, options, inTable).children : [] + const first = body.find((n) => n.type === 'element') + if (first?.tagName === 'p') { + first.children.unshift(el('strong', [txt(label)]), txt(' ')) + } else { + body.unshift(el('p', [el('strong', [txt(label)])])) + } + out.push(el('blockquote', body)) + continue + } + + const cards = + child.tagName === 'section' + ? findAll(child, (n) => n.tagName === 'a' && hasClass(n, 'card')) + : [] + if (cards.length) { + const items = cards.map((card) => { + const title = textOf(find(card, (n) => n.tagName === 'h2') ?? card) + const desc = textOf(find(card, (n) => n.tagName === 'p') ?? txt('')) + const link = el('a', [txt(title.trim())], { + href: card.properties.href, + }) + return el('li', desc.trim() ? [link, txt(`: ${desc.trim()}`)] : [link]) + }) + out.push(el('ul', items)) + continue + } + + // The plugin keeps
as inline HTML so table cells stay on one line; + // elsewhere a plain line break reads better + if (child.tagName === 'br' && !inTable) { + out.push(txt('\n')) + continue + } + + if (INLINE_EMPHASIS.has(child.tagName)) { + out.push(...hoistWhitespace(transform(child, options, inTable))) + continue + } + + // Collapsibles: keep the summary as a bold line, then the content + if (child.tagName === 'summary') { + const label = textOf(child).replace(/\s+/g, ' ').trim() + if (label) out.push(el('p', [el('strong', [txt(label)])])) + continue + } + + if (child.tagName === 'img') { + if (child.properties?.alt === '') continue + // Small images are inlined by the bundler as base64 data URIs + if (String(child.properties?.src ?? '').startsWith('data:')) continue + if (typeof child.properties?.alt === 'string') { + child.properties.alt = decodeEntities(child.properties.alt) + } + const src = String(child.properties?.src ?? '') + if (src.startsWith('/') && !src.startsWith('//')) { + child.properties.src = options.siteUrl + src + } + } + + out.push( + transform( + child, + options, + inTable || child.tagName === 'td' || child.tagName === 'th', + ), + ) + } + node.children = out + return node +} + +function rehypeLlmsCleanup(options = {}) { + const siteUrl = (options.siteUrl ?? '').replace(/\/$/, '') + return (tree) => { + transform(tree, { siteUrl }) + } +} + +function rehypeLlmsFixIndexLinks(options = {}) { + const origins = (options.siteUrls ?? []).map((u) => u.replace(/\/$/, '')) + const isExcluded = createMatcher(options.excludeRoutes ?? []) + const toMarkdown = (url) => { + const origin = origins.find((o) => url.startsWith(`${o}/`)) + if (!origin) return url + const [, pathname, suffix] = /^([^?#]*)(.*)$/.exec(url.slice(origin.length)) + if (pathname === '/') return url + // Excluded pages have no .md version, so link to the HTML page + if (pathname.endsWith('.md')) { + const route = pathname.slice(0, -'.md'.length) + return isExcluded(route) ? `${origin}${route}${suffix}` : url + } + if (/\.[a-z0-9]+$/i.test(pathname)) return url + const route = pathname.replace(/\/$/, '') + return isExcluded(route) ? url : `${origin}${route}.md${suffix}` + } + const fix = (node) => { + if (node.type === 'link' || node.type === 'definition') { + node.url = toMarkdown(node.url.replace(/\/\.md(?=$|[?#])/, '.md')) + } + node.children?.forEach(fix) + } + return fix +} + +module.exports = { rehypeLlmsCleanup, rehypeLlmsFixIndexLinks } diff --git a/yarn.lock b/yarn.lock index 93605a7c..bd72a1cb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2823,6 +2823,16 @@ __metadata: languageName: node linkType: hard +"@docusaurus/logger@npm:^3.0.0": + version: 3.10.2 + resolution: "@docusaurus/logger@npm:3.10.2" + dependencies: + chalk: "npm:^4.1.2" + tslib: "npm:^2.6.0" + checksum: 10/cb95fb35d6af203a2f1f98a52819c0a02ebbbd0ceba50ed7def39c233fdf1d3db5783a9d75c77084334bf1790536be10239cfb4f1e025d5013986e3ce660dd50 + languageName: node + linkType: hard + "@docusaurus/mdx-loader@npm:3.9.2": version: 3.9.2 resolution: "@docusaurus/mdx-loader@npm:3.9.2" @@ -4064,6 +4074,28 @@ __metadata: languageName: node linkType: hard +"@signalwire/docusaurus-plugin-llms-txt@npm:^1.2.2": + version: 1.2.2 + resolution: "@signalwire/docusaurus-plugin-llms-txt@npm:1.2.2" + dependencies: + fs-extra: "npm:^11.0.0" + hast-util-select: "npm:^6.0.4" + hast-util-to-html: "npm:^9.0.5" + hast-util-to-string: "npm:^3.0.1" + p-map: "npm:^7.0.2" + rehype-parse: "npm:^9" + rehype-remark: "npm:^10" + remark-gfm: "npm:^4" + remark-stringify: "npm:^11" + string-width: "npm:^5.0.0" + unified: "npm:^11" + unist-util-visit: "npm:^5" + peerDependencies: + "@docusaurus/core": ^3.0.0 + checksum: 10/66ac57275178c86fcb060e107df4a30f6989be9d162e5c1f77e104c1ae99598a8b0564a45c5b795a601f3a341731eed3293804b9ee2fe628fe0485c05a3a5d3d + languageName: node + linkType: hard + "@sinclair/typebox@npm:^0.27.8": version: 0.27.8 resolution: "@sinclair/typebox@npm:0.27.8" @@ -5369,6 +5401,13 @@ __metadata: languageName: node linkType: hard +"bcp-47-match@npm:^2.0.0": + version: 2.0.3 + resolution: "bcp-47-match@npm:2.0.3" + checksum: 10/fb47d31946268865c45df4c5d447964656ea357871bbd6969dc4ea2fb6b581fda385174ed43bc1dc1a7ed75c1a93a51fef18eec0fbd24352725dfceb2246cf2e + languageName: node + linkType: hard + "big.js@npm:^5.2.2": version: 5.2.2 resolution: "big.js@npm:5.2.2" @@ -6364,6 +6403,13 @@ __metadata: languageName: node linkType: hard +"css-selector-parser@npm:^3.0.0": + version: 3.3.0 + resolution: "css-selector-parser@npm:3.3.0" + checksum: 10/492d662310e46353b321a4c3dd72f4046d7a0d73f4caf66b299b70d9973a61cf2a1ae35f73e1be6d608d24e48fd99f928f7c403d915863d157c85f1cfb152c1c + languageName: node + linkType: hard + "css-to-react-native@npm:3.2.0": version: 3.2.0 resolution: "css-to-react-native@npm:3.2.0" @@ -6711,6 +6757,7 @@ __metadata: "@iconify-icon/react": "npm:^1.0.8" "@mdx-js/react": "npm:^3.1.0" "@remark-embedder/core": "npm:^3.0.3" + "@signalwire/docusaurus-plugin-llms-txt": "npm:^1.2.2" "@tailwindcss/aspect-ratio": "npm:^0.4.2" "@types/react": "npm:^18.3.20" call-me-maybe: "npm:^1.0.2" @@ -6762,6 +6809,15 @@ __metadata: languageName: node linkType: hard +"direction@npm:^2.0.0": + version: 2.0.1 + resolution: "direction@npm:2.0.1" + bin: + direction: cli.js + checksum: 10/59a423f2f4ca6bbcdd38fb002ae7c06b6af785392162417e6f30a7ca0b406dfa066971d9963ae796e59090b4b4a0d342b1769d19af50985597abf976c1190355 + languageName: node + linkType: hard + "dlv@npm:^1.1.3": version: 1.1.3 resolution: "dlv@npm:1.1.3" @@ -7712,6 +7768,17 @@ __metadata: languageName: node linkType: hard +"fs-extra@npm:^11.0.0": + version: 11.4.1 + resolution: "fs-extra@npm:11.4.1" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^6.0.1" + universalify: "npm:^2.0.0" + checksum: 10/8805c7413442ed9e94fb25eeafd28d705e2a732deba3eeb7b43cf687ce60c94e8a298b882de38249034ca84db7d21a0e4a237a041e8141f8f24f0d5ac2c6056a + languageName: node + linkType: hard + "fs-extra@npm:^11.1.1, fs-extra@npm:^11.2.0": version: 11.3.1 resolution: "fs-extra@npm:11.3.1" @@ -8032,6 +8099,30 @@ __metadata: languageName: node linkType: hard +"hast-util-embedded@npm:^3.0.0": + version: 3.0.0 + resolution: "hast-util-embedded@npm:3.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + hast-util-is-element: "npm:^3.0.0" + checksum: 10/ccb26926144dd72f9eec2307ceb45ff991c382c0cd20c517519a6a30e46b4e8c683bf6e2906cb0288ead880ca8fdfeaa1610de68ef8c0d12340d101352ba8a1a + languageName: node + linkType: hard + +"hast-util-from-html@npm:^2.0.0": + version: 2.0.3 + resolution: "hast-util-from-html@npm:2.0.3" + dependencies: + "@types/hast": "npm:^3.0.0" + devlop: "npm:^1.1.0" + hast-util-from-parse5: "npm:^8.0.0" + parse5: "npm:^7.0.0" + vfile: "npm:^6.0.0" + vfile-message: "npm:^4.0.0" + checksum: 10/cdd8ceae114d7ff6d4a81d9d7314c53299acfaca3d959a5894e80eb013c0850af613e2688f1682945c2793e0d9e1acb105560295fd8f141ab7b75f4b2e49cb2c + languageName: node + linkType: hard + "hast-util-from-parse5@npm:^8.0.0, hast-util-from-parse5@npm:^8.0.1": version: 8.0.3 resolution: "hast-util-from-parse5@npm:8.0.3" @@ -8048,6 +8139,46 @@ __metadata: languageName: node linkType: hard +"hast-util-has-property@npm:^3.0.0": + version: 3.0.0 + resolution: "hast-util-has-property@npm:3.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + checksum: 10/f82b6d65cbaa90f63edab97d7ad771182f515fb9e08e461e0443954d51c1b568814b56d128a73f37326f6005ab0b35c01624d46259a4d0b850e55849f1ff3035 + languageName: node + linkType: hard + +"hast-util-is-body-ok-link@npm:^3.0.0": + version: 3.0.1 + resolution: "hast-util-is-body-ok-link@npm:3.0.1" + dependencies: + "@types/hast": "npm:^3.0.0" + checksum: 10/ec265d0262f130d2e9b688024175aedb27c9e1402d175ed8834e79cb465934d99adf911cd5a9644ec3f3ce55c40fa2a314ee48c8dd928b85f6c5df83b3990d48 + languageName: node + linkType: hard + +"hast-util-is-element@npm:^3.0.0": + version: 3.0.0 + resolution: "hast-util-is-element@npm:3.0.0" + dependencies: + "@types/hast": "npm:^3.0.0" + checksum: 10/b4e6d84c763ffdc44198ba0c4a5a7430794a7b2c1eec699d37776ea9832eef79f129726c175982103eb3b21f531a6bfd2fa43ce26e1ed6d8f6a87c102ba212c8 + languageName: node + linkType: hard + +"hast-util-minify-whitespace@npm:^1.0.0": + version: 1.0.1 + resolution: "hast-util-minify-whitespace@npm:1.0.1" + dependencies: + "@types/hast": "npm:^3.0.0" + hast-util-embedded: "npm:^3.0.0" + hast-util-is-element: "npm:^3.0.0" + hast-util-whitespace: "npm:^3.0.0" + unist-util-is: "npm:^6.0.0" + checksum: 10/e43d3b1cd6f3ebd2547acdd209e75c8c239a0b3e7d6b12cc706da39f888b4300648deb982b1760186e676a39982f916e6bfba9c6cc08910b88de00a49fced650 + languageName: node + linkType: hard + "hast-util-parse-selector@npm:^4.0.0": version: 4.0.0 resolution: "hast-util-parse-selector@npm:4.0.0" @@ -8057,6 +8188,19 @@ __metadata: languageName: node linkType: hard +"hast-util-phrasing@npm:^3.0.0": + version: 3.0.1 + resolution: "hast-util-phrasing@npm:3.0.1" + dependencies: + "@types/hast": "npm:^3.0.0" + hast-util-embedded: "npm:^3.0.0" + hast-util-has-property: "npm:^3.0.0" + hast-util-is-body-ok-link: "npm:^3.0.0" + hast-util-is-element: "npm:^3.0.0" + checksum: 10/aff54f89b14af298e33379e0b1053bb01fddb089cfe7f40a6c5f9d7477d89e42f5e32cd6617e246c18a0e9da1aa0b62ab441b14bd8ce788fd0fa594e77b05042 + languageName: node + linkType: hard + "hast-util-raw@npm:^9.0.0": version: 9.1.0 resolution: "hast-util-raw@npm:9.1.0" @@ -8078,6 +8222,29 @@ __metadata: languageName: node linkType: hard +"hast-util-select@npm:^6.0.4": + version: 6.0.4 + resolution: "hast-util-select@npm:6.0.4" + dependencies: + "@types/hast": "npm:^3.0.0" + "@types/unist": "npm:^3.0.0" + bcp-47-match: "npm:^2.0.0" + comma-separated-tokens: "npm:^2.0.0" + css-selector-parser: "npm:^3.0.0" + devlop: "npm:^1.0.0" + direction: "npm:^2.0.0" + hast-util-has-property: "npm:^3.0.0" + hast-util-to-string: "npm:^3.0.0" + hast-util-whitespace: "npm:^3.0.0" + nth-check: "npm:^2.0.0" + property-information: "npm:^7.0.0" + space-separated-tokens: "npm:^2.0.0" + unist-util-visit: "npm:^5.0.0" + zwitch: "npm:^2.0.0" + checksum: 10/f4732960280d7459833ee7e15016414d1a745fd0fddcd7ab2478e251f203e54afbeacab388e777ce2878113c7348d3d66b186da6ecd0d167a32274e18d520e31 + languageName: node + linkType: hard + "hast-util-to-estree@npm:^3.0.0": version: 3.1.3 resolution: "hast-util-to-estree@npm:3.1.3" @@ -8102,6 +8269,25 @@ __metadata: languageName: node linkType: hard +"hast-util-to-html@npm:^9.0.0, hast-util-to-html@npm:^9.0.5": + version: 9.0.5 + resolution: "hast-util-to-html@npm:9.0.5" + dependencies: + "@types/hast": "npm:^3.0.0" + "@types/unist": "npm:^3.0.0" + ccount: "npm:^2.0.0" + comma-separated-tokens: "npm:^2.0.0" + hast-util-whitespace: "npm:^3.0.0" + html-void-elements: "npm:^3.0.0" + mdast-util-to-hast: "npm:^13.0.0" + property-information: "npm:^7.0.0" + space-separated-tokens: "npm:^2.0.0" + stringify-entities: "npm:^4.0.0" + zwitch: "npm:^2.0.4" + checksum: 10/4278e5246f43adf7a30bf3b87db4a4e628b5362b8c149eb4360bf7e0f731f81fa31e4e844e8090d1dd5f739d0884678f8165b28f97c14139e4da4f945f9ff5f7 + languageName: node + linkType: hard + "hast-util-to-jsx-runtime@npm:^2.0.0": version: 2.3.6 resolution: "hast-util-to-jsx-runtime@npm:2.3.6" @@ -8125,6 +8311,28 @@ __metadata: languageName: node linkType: hard +"hast-util-to-mdast@npm:^10.0.0": + version: 10.1.2 + resolution: "hast-util-to-mdast@npm:10.1.2" + dependencies: + "@types/hast": "npm:^3.0.0" + "@types/mdast": "npm:^4.0.0" + "@ungap/structured-clone": "npm:^1.0.0" + hast-util-phrasing: "npm:^3.0.0" + hast-util-to-html: "npm:^9.0.0" + hast-util-to-text: "npm:^4.0.0" + hast-util-whitespace: "npm:^3.0.0" + mdast-util-phrasing: "npm:^4.0.0" + mdast-util-to-hast: "npm:^13.0.0" + mdast-util-to-string: "npm:^4.0.0" + rehype-minify-whitespace: "npm:^6.0.0" + trim-trailing-lines: "npm:^2.0.0" + unist-util-position: "npm:^5.0.0" + unist-util-visit: "npm:^5.0.0" + checksum: 10/ef9b6a5e1be2e2a5091b4f81023a5d316246976fa2e714e7013d0bf826641e1660d91a8793381d7d97599ff86c6a1eeb3284e01005c24433940ebf6a9d3aae25 + languageName: node + linkType: hard + "hast-util-to-parse5@npm:^8.0.0": version: 8.0.0 resolution: "hast-util-to-parse5@npm:8.0.0" @@ -8140,6 +8348,27 @@ __metadata: languageName: node linkType: hard +"hast-util-to-string@npm:^3.0.0, hast-util-to-string@npm:^3.0.1": + version: 3.0.1 + resolution: "hast-util-to-string@npm:3.0.1" + dependencies: + "@types/hast": "npm:^3.0.0" + checksum: 10/a569518313a648bc86e712858bc907d1f65137ebba87bc71180dbc2f24f194f6035019ffa8e38b1f7897672d45a337046a4c9964ce6d2593953b5069e10d31c2 + languageName: node + linkType: hard + +"hast-util-to-text@npm:^4.0.0": + version: 4.0.2 + resolution: "hast-util-to-text@npm:4.0.2" + dependencies: + "@types/hast": "npm:^3.0.0" + "@types/unist": "npm:^3.0.0" + hast-util-is-element: "npm:^3.0.0" + unist-util-find-after: "npm:^5.0.0" + checksum: 10/71241e486a155b186b06355fa3bbdaa88602aa108a44ab00a6992e5cabcd7858b43dcb1211c5b17bfe76dddbe9acbbd97408a8e483c1ce83834032778bccd157 + languageName: node + linkType: hard + "hast-util-whitespace@npm:^3.0.0": version: 3.0.0 resolution: "hast-util-whitespace@npm:3.0.0" @@ -10621,7 +10850,7 @@ __metadata: languageName: node linkType: hard -"nth-check@npm:^2.0.1": +"nth-check@npm:^2.0.0, nth-check@npm:^2.0.1": version: 2.1.1 resolution: "nth-check@npm:2.1.1" dependencies: @@ -12969,6 +13198,27 @@ __metadata: languageName: node linkType: hard +"rehype-minify-whitespace@npm:^6.0.0": + version: 6.0.2 + resolution: "rehype-minify-whitespace@npm:6.0.2" + dependencies: + "@types/hast": "npm:^3.0.0" + hast-util-minify-whitespace: "npm:^1.0.0" + checksum: 10/4e759fd0e66e389192da5217621878354b87d527e596460a6bdc13dacad93d44fc552e7dadcf3eb428c0f2344bedba795485b6359e1592316f2b64538c6fed3a + languageName: node + linkType: hard + +"rehype-parse@npm:^9": + version: 9.0.1 + resolution: "rehype-parse@npm:9.0.1" + dependencies: + "@types/hast": "npm:^3.0.0" + hast-util-from-html: "npm:^2.0.0" + unified: "npm:^11.0.0" + checksum: 10/67855c6426d1cd39d64b4a38e934bb234e59f1d4df2f67008848b9bde01f9e068eed549d62a97f54d5c5eb8bfa56c7e2c4b7c3aad769fc4ded9218dc9078ef37 + languageName: node + linkType: hard + "rehype-raw@npm:^7.0.0": version: 7.0.0 resolution: "rehype-raw@npm:7.0.0" @@ -12991,6 +13241,19 @@ __metadata: languageName: node linkType: hard +"rehype-remark@npm:^10": + version: 10.0.1 + resolution: "rehype-remark@npm:10.0.1" + dependencies: + "@types/hast": "npm:^3.0.0" + "@types/mdast": "npm:^4.0.0" + hast-util-to-mdast: "npm:^10.0.0" + unified: "npm:^11.0.0" + vfile: "npm:^6.0.0" + checksum: 10/5119de01a1cab714830fcf65b1137518792095bd9375fe08d911d3d72fdf90edff8267daeaa987b91cb72f0ab64a2e2ff5c88157a8dfb6f24dd873eddceca921 + languageName: node + linkType: hard + "relateurl@npm:^0.2.7": version: 0.2.7 resolution: "relateurl@npm:0.2.7" @@ -13045,7 +13308,7 @@ __metadata: languageName: node linkType: hard -"remark-gfm@npm:^4.0.0": +"remark-gfm@npm:^4, remark-gfm@npm:^4.0.0": version: 4.0.1 resolution: "remark-gfm@npm:4.0.1" dependencies: @@ -13094,7 +13357,7 @@ __metadata: languageName: node linkType: hard -"remark-stringify@npm:^11.0.0": +"remark-stringify@npm:^11, remark-stringify@npm:^11.0.0": version: 11.0.0 resolution: "remark-stringify@npm:11.0.0" dependencies: @@ -13911,7 +14174,7 @@ __metadata: languageName: node linkType: hard -"string-width@npm:^5.0.1, string-width@npm:^5.1.2": +"string-width@npm:^5.0.0, string-width@npm:^5.0.1, string-width@npm:^5.1.2": version: 5.1.2 resolution: "string-width@npm:5.1.2" dependencies: @@ -14389,6 +14652,13 @@ __metadata: languageName: node linkType: hard +"trim-trailing-lines@npm:^2.0.0": + version: 2.1.0 + resolution: "trim-trailing-lines@npm:2.1.0" + checksum: 10/4bfed49a8c064c93d15e560bec81083fdbb0a525300f07006b76bcc753816091c5ef25e6a82d1bb6fe678e4e1ecde5a7f8dd7f6fa1c9da74b80d3a64497a87f6 + languageName: node + linkType: hard + "trough@npm:^2.0.0": version: 2.2.0 resolution: "trough@npm:2.2.0" @@ -14538,7 +14808,7 @@ __metadata: languageName: node linkType: hard -"unified@npm:^11.0.0, unified@npm:^11.0.3, unified@npm:^11.0.4": +"unified@npm:^11, unified@npm:^11.0.0, unified@npm:^11.0.3, unified@npm:^11.0.4": version: 11.0.5 resolution: "unified@npm:11.0.5" dependencies: @@ -14580,6 +14850,16 @@ __metadata: languageName: node linkType: hard +"unist-util-find-after@npm:^5.0.0": + version: 5.0.0 + resolution: "unist-util-find-after@npm:5.0.0" + dependencies: + "@types/unist": "npm:^3.0.0" + unist-util-is: "npm:^6.0.0" + checksum: 10/7960f98f99ae3c2585a8e16b23f338e5851b7c0f40c3e82e2aef9ddb4887ae63d4cb3906e793dc8ff8242f252425ef846a4e59afa1d3d91ebf0ac84732df2509 + languageName: node + linkType: hard + "unist-util-is@npm:^4.0.0": version: 4.1.0 resolution: "unist-util-is@npm:4.1.0" @@ -14654,6 +14934,17 @@ __metadata: languageName: node linkType: hard +"unist-util-visit@npm:^5": + version: 5.1.0 + resolution: "unist-util-visit@npm:5.1.0" + dependencies: + "@types/unist": "npm:^3.0.0" + unist-util-is: "npm:^6.0.0" + unist-util-visit-parents: "npm:^6.0.0" + checksum: 10/340fc1929062d21156200284105caad79cc188bd98f285b60aba887492a70e6e6cadbc7e383a68909c7e0fdd83f855cb9f4184ad8e5aa153eb2d810445aea8e5 + languageName: node + linkType: hard + "unist-util-visit@npm:^5.0.0": version: 5.0.0 resolution: "unist-util-visit@npm:5.0.0" @@ -15293,7 +15584,7 @@ __metadata: languageName: node linkType: hard -"zwitch@npm:^2.0.0": +"zwitch@npm:^2.0.0, zwitch@npm:^2.0.4": version: 2.0.4 resolution: "zwitch@npm:2.0.4" checksum: 10/f22ec5fc2d5f02c423c93d35cdfa83573a3a3bd98c66b927c368ea4d0e7252a500df2a90a6b45522be536a96a73404393c958e945fdba95e6832c200791702b6 From 95c882e21e6cc50213340f873dc84554df7ba0ca Mon Sep 17 00:00:00 2001 From: Jonathan Norris Date: Mon, 12 Oct 2026 21:41:23 -0400 Subject: [PATCH 2/2] docs: drop added page descriptions from llms.txt PR --- .../import-from-anywhere.md | 1 - docs/cli-guides/environments.md | 1 - docs/cli-guides/features.md | 1 - docs/cli-guides/keys.md | 1 - docs/cli-guides/projects.md | 1 - docs/cli-guides/self-targeting.md | 1 - docs/cli-guides/targeting.md | 1 - docs/cli-guides/variables.md | 1 - docs/cli-guides/variations.md | 1 - docs/essentials/architecture.md | 1 - docs/essentials/feature-hierarchy.md | 1 - docs/integrations/google-analytics-4.md | 1 - docs/integrations/index.mdx | 1 - docs/integrations/jira/jira-setup.md | 1 - docs/integrations/jira/jira.md | 1 - .../creating-and-managing-metrics.md | 1 - .../feature-experimentation.md | 1 - .../how-metrics-are-calculated.md | 1 - .../tutorial-funnel-experiment.md | 1 - docs/platform/extras/custom-domains.md | 1 - .../stale-feature-notifications.md | 1 - .../targeting/random-variations.md | 1 - .../feature-flags/targeting/rollouts.md | 1 - .../targeting/targeting-overview.md | 1 - .../variable-defaults.md | 1 - .../feature-obfuscation.md | 1 - docs/sdk/client-side-sdks/android/android.md | 1 - docs/sdk/client-side-sdks/flutter/flutter.md | 1 - docs/sdk/client-side-sdks/ios/ios.md | 1 - docs/sdk/client-side-sdks/react/react.md | 1 - docs/sdk/lifecycle.md | 1 - docs/sdk/sdk-proxy/index.md | 1 - docs/sdk/sdk-proxy/installation.md | 1 - docs/sdk/sdk-proxy/usage.md | 1 - docs/sdk/server-side-sdks/dotnet/dotnet.md | 1 - docs/sdk/server-side-sdks/go/go.md | 1 - docs/sdk/server-side-sdks/java/java.md | 1 - docs/sdk/server-side-sdks/php/php.md | 1 - docs/sdk/server-side-sdks/ruby/ruby.md | 1 - docusaurus.config.js | 98 ++++--------------- 40 files changed, 19 insertions(+), 118 deletions(-) diff --git a/docs/best-practices/edgedb-and-edge-flags/import-from-anywhere.md b/docs/best-practices/edgedb-and-edge-flags/import-from-anywhere.md index a2682aea..166b33b3 100644 --- a/docs/best-practices/edgedb-and-edge-flags/import-from-anywhere.md +++ b/docs/best-practices/edgedb-and-edge-flags/import-from-anywhere.md @@ -1,6 +1,5 @@ --- title: Super Segments Integrations via Zapier -description: Import user data from external sources like Salesforce into EdgeDB with Zapier sidebar_position: 3 --- diff --git a/docs/cli-guides/environments.md b/docs/cli-guides/environments.md index 755b6c90..a21c1e14 100644 --- a/docs/cli-guides/environments.md +++ b/docs/cli-guides/environments.md @@ -1,6 +1,5 @@ --- title: Environments -description: Create, view, and update Environments with the DevCycle CLI sidebar_position: 2 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/features.md b/docs/cli-guides/features.md index 7d024610..8b92d032 100644 --- a/docs/cli-guides/features.md +++ b/docs/cli-guides/features.md @@ -1,6 +1,5 @@ --- title: Features -description: Create, view, update, and delete Features with the DevCycle CLI sidebar_position: 4 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/keys.md b/docs/cli-guides/keys.md index b5298942..242d50f9 100644 --- a/docs/cli-guides/keys.md +++ b/docs/cli-guides/keys.md @@ -1,6 +1,5 @@ --- title: SDK Keys -description: Retrieve SDK keys for your Environments with the DevCycle CLI sidebar_position: 3 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/projects.md b/docs/cli-guides/projects.md index 1fe15de1..35e8eb62 100644 --- a/docs/cli-guides/projects.md +++ b/docs/cli-guides/projects.md @@ -1,6 +1,5 @@ --- title: Projects -description: Create and view Projects with the DevCycle CLI sidebar_position: 1 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/self-targeting.md b/docs/cli-guides/self-targeting.md index 17150908..8a17e3f7 100644 --- a/docs/cli-guides/self-targeting.md +++ b/docs/cli-guides/self-targeting.md @@ -1,6 +1,5 @@ --- title: Self-Targeting -description: Manage your DevCycle Identity and Self-Targeting Overrides with the DevCycle CLI sidebar_position: 8 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/targeting.md b/docs/cli-guides/targeting.md index dd3b2820..0104354a 100644 --- a/docs/cli-guides/targeting.md +++ b/docs/cli-guides/targeting.md @@ -1,6 +1,5 @@ --- title: Targeting Rules -description: View, update, enable, and disable Targeting Rules with the DevCycle CLI sidebar_position: 7 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/variables.md b/docs/cli-guides/variables.md index d2767955..0638a39c 100644 --- a/docs/cli-guides/variables.md +++ b/docs/cli-guides/variables.md @@ -1,6 +1,5 @@ --- title: Variables -description: Create, view, and update Variables with the DevCycle CLI sidebar_position: 5 displayed_sidebar: cli_mcp --- diff --git a/docs/cli-guides/variations.md b/docs/cli-guides/variations.md index 87cce698..d9e9f738 100644 --- a/docs/cli-guides/variations.md +++ b/docs/cli-guides/variations.md @@ -1,6 +1,5 @@ --- title: Variations -description: Create, view, and update Variations with the DevCycle CLI sidebar_position: 6 displayed_sidebar: cli_mcp --- diff --git a/docs/essentials/architecture.md b/docs/essentials/architecture.md index 533bd8c9..93db12eb 100644 --- a/docs/essentials/architecture.md +++ b/docs/essentials/architecture.md @@ -1,6 +1,5 @@ --- title: System Architecture -description: The design goals behind DevCycle and how its APIs, edge workers, and Client, Mobile, and Server SDKs deliver and evaluate Feature configurations sidebar_position: 3 --- diff --git a/docs/essentials/feature-hierarchy.md b/docs/essentials/feature-hierarchy.md index ef566a3a..a4492f8f 100644 --- a/docs/essentials/feature-hierarchy.md +++ b/docs/essentials/feature-hierarchy.md @@ -1,6 +1,5 @@ --- title: Feature Hierarchy -description: How Features, Variables, Variations, and Targeting Rules relate to each other in DevCycle sidebar_position: 4 --- In a traditional Feature Flagging platform, there is only one type of entity to worry about: a `Feature Flag`! In these diff --git a/docs/integrations/google-analytics-4.md b/docs/integrations/google-analytics-4.md index 1e49d478..19c9c8ca 100644 --- a/docs/integrations/google-analytics-4.md +++ b/docs/integrations/google-analytics-4.md @@ -1,6 +1,5 @@ --- title: "Sending DevCycle Data as a Custom Event to Google Analytics 4 (GTM Specific)" -description: Send DevCycle Feature and Variation data to Google Analytics 4 with Google Tag Manager sidebar_position: 1 --- diff --git a/docs/integrations/index.mdx b/docs/integrations/index.mdx index 363a5837..c5279b38 100644 --- a/docs/integrations/index.mdx +++ b/docs/integrations/index.mdx @@ -1,6 +1,5 @@ --- title: Integrations -description: First-party tools built on the DevCycle APIs, and third-party integrations that connect DevCycle to your other tools sidebar_class_name: hidden --- diff --git a/docs/integrations/jira/jira-setup.md b/docs/integrations/jira/jira-setup.md index ac3d4e5e..1ca2b512 100644 --- a/docs/integrations/jira/jira-setup.md +++ b/docs/integrations/jira/jira-setup.md @@ -1,6 +1,5 @@ --- title: 'DevCycle Jira Integration Setup' -description: Install the DevCycle app for Jira and connect it to your DevCycle Organization or Project sidebar_position: 1 --- diff --git a/docs/integrations/jira/jira.md b/docs/integrations/jira/jira.md index d242df4e..e72d42dc 100644 --- a/docs/integrations/jira/jira.md +++ b/docs/integrations/jira/jira.md @@ -1,6 +1,5 @@ --- title: DevCycle Feature Flag Management for Jira -description: Connect DevCycle Features to Jira issues with the DevCycle app for Jira --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/platform/experimentation/creating-and-managing-metrics.md b/docs/platform/experimentation/creating-and-managing-metrics.md index 0fb227d2..58d34562 100644 --- a/docs/platform/experimentation/creating-and-managing-metrics.md +++ b/docs/platform/experimentation/creating-and-managing-metrics.md @@ -1,6 +1,5 @@ --- title: Creating and Managing Metrics -description: Create, define, and manage Metrics in a Project, and attach them to Features to measure their impact sidebar_position: 2 --- diff --git a/docs/platform/experimentation/feature-experimentation.md b/docs/platform/experimentation/feature-experimentation.md index 36abe238..e3795ae3 100644 --- a/docs/platform/experimentation/feature-experimentation.md +++ b/docs/platform/experimentation/feature-experimentation.md @@ -1,6 +1,5 @@ --- title: Feature Experimentation -description: Why and how to run and analyze Experiments on your Features in DevCycle sidebar_position: 1 --- diff --git a/docs/platform/experimentation/how-metrics-are-calculated.md b/docs/platform/experimentation/how-metrics-are-calculated.md index d48a9a15..647c870c 100644 --- a/docs/platform/experimentation/how-metrics-are-calculated.md +++ b/docs/platform/experimentation/how-metrics-are-calculated.md @@ -1,6 +1,5 @@ --- title: How Metrics are Calculated -description: How DevCycle calculates Metric results and statistical significance for binary conversion and value optimization Metrics sidebar_position: 3 --- diff --git a/docs/platform/experimentation/tutorial-funnel-experiment.md b/docs/platform/experimentation/tutorial-funnel-experiment.md index 21800e04..1426eb04 100644 --- a/docs/platform/experimentation/tutorial-funnel-experiment.md +++ b/docs/platform/experimentation/tutorial-funnel-experiment.md @@ -1,6 +1,5 @@ --- title: "Tutorial: Funnel Experiment" -description: Set up and analyze a funnel experiment across a multi-step sign-up flow sidebar_position: 5 --- diff --git a/docs/platform/extras/custom-domains.md b/docs/platform/extras/custom-domains.md index 9732f515..e6730a2b 100644 --- a/docs/platform/extras/custom-domains.md +++ b/docs/platform/extras/custom-domains.md @@ -1,6 +1,5 @@ --- title: Custom Domains -description: Send DevCycle SDK requests and cookies through your own domain so ad blockers and browser privacy features don't block them sidebar_position: 1 --- diff --git a/docs/platform/feature-flags/stale-feature-notifications.md b/docs/platform/feature-flags/stale-feature-notifications.md index 1da7b7a5..eb5996cd 100644 --- a/docs/platform/feature-flags/stale-feature-notifications.md +++ b/docs/platform/feature-flags/stale-feature-notifications.md @@ -1,6 +1,5 @@ --- title: Stale Feature Notifications -description: How DevCycle detects potentially stale Features, and how to act on, snooze, or disable stale Feature notifications sidebar_position: 5 --- diff --git a/docs/platform/feature-flags/targeting/random-variations.md b/docs/platform/feature-flags/targeting/random-variations.md index 16f2f747..758f38a6 100644 --- a/docs/platform/feature-flags/targeting/random-variations.md +++ b/docs/platform/feature-flags/targeting/random-variations.md @@ -1,6 +1,5 @@ --- title: Random Variations -description: Serve a random distribution of Variations to users who match a Targeting Rule sidebar_position: 4 --- diff --git a/docs/platform/feature-flags/targeting/rollouts.md b/docs/platform/feature-flags/targeting/rollouts.md index ae87f58c..4b336ffc 100644 --- a/docs/platform/feature-flags/targeting/rollouts.md +++ b/docs/platform/feature-flags/targeting/rollouts.md @@ -1,6 +1,5 @@ --- title: Scheduling & Rollouts -description: Schedule Feature releases and configure gradual and multi-step rollouts sidebar_position: 5 --- diff --git a/docs/platform/feature-flags/targeting/targeting-overview.md b/docs/platform/feature-flags/targeting/targeting-overview.md index 0da9d767..ba4417f2 100644 --- a/docs/platform/feature-flags/targeting/targeting-overview.md +++ b/docs/platform/feature-flags/targeting/targeting-overview.md @@ -1,6 +1,5 @@ --- title: Targeting Overview -description: Use Targeting Rules to grant Features to specific user groups, roll out Features incrementally, and test different Feature configurations sidebar_position: 1 --- diff --git a/docs/platform/feature-flags/variables-and-variations/variable-defaults.md b/docs/platform/feature-flags/variables-and-variations/variable-defaults.md index 21589117..7244db5c 100644 --- a/docs/platform/feature-flags/variables-and-variations/variable-defaults.md +++ b/docs/platform/feature-flags/variables-and-variations/variable-defaults.md @@ -1,6 +1,5 @@ --- title: Variable Defaults -description: When DevCycle SDKs fall back to the default value you provide in code for a Variable sidebar_position: 3 --- diff --git a/docs/platform/security-and-guardrails/feature-obfuscation.md b/docs/platform/security-and-guardrails/feature-obfuscation.md index ec1fa2a3..e6e72c27 100644 --- a/docs/platform/security-and-guardrails/feature-obfuscation.md +++ b/docs/platform/security-and-guardrails/feature-obfuscation.md @@ -1,6 +1,5 @@ --- title: Feature Obfuscation -description: Obfuscate Variable keys in web SDKs so unreleased Feature names can't be found in the code shipped to users sidebar_position: 4 --- diff --git a/docs/sdk/client-side-sdks/android/android.md b/docs/sdk/client-side-sdks/android/android.md index 2f2deb9b..ed959ea2 100644 --- a/docs/sdk/client-side-sdks/android/android.md +++ b/docs/sdk/client-side-sdks/android/android.md @@ -1,6 +1,5 @@ --- title: Android SDK -description: The DevCycle Android Client SDK, which uses the Client SDK APIs and globally distributed edge workers for segmentation and bucketing sidebar_position: 4 --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/client-side-sdks/flutter/flutter.md b/docs/sdk/client-side-sdks/flutter/flutter.md index e9f99d77..f71a5920 100644 --- a/docs/sdk/client-side-sdks/flutter/flutter.md +++ b/docs/sdk/client-side-sdks/flutter/flutter.md @@ -1,6 +1,5 @@ --- title: Flutter SDK -description: The DevCycle Flutter Client SDK, which uses the Client SDK APIs and globally distributed edge workers for segmentation and bucketing --- import CustomDocCardList from '@site/src/components/CustomDocCardList' import {useCurrentSidebarCategory} from '@docusaurus/theme-common'; diff --git a/docs/sdk/client-side-sdks/ios/ios.md b/docs/sdk/client-side-sdks/ios/ios.md index e1298776..d14e344c 100644 --- a/docs/sdk/client-side-sdks/ios/ios.md +++ b/docs/sdk/client-side-sdks/ios/ios.md @@ -1,6 +1,5 @@ --- title: iOS SDK -description: The DevCycle Swift Client SDK for iOS, macOS, tvOS, and watchOS applications --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/client-side-sdks/react/react.md b/docs/sdk/client-side-sdks/react/react.md index ab4eeb0e..d5f38656 100644 --- a/docs/sdk/client-side-sdks/react/react.md +++ b/docs/sdk/client-side-sdks/react/react.md @@ -1,6 +1,5 @@ --- title: React SDK -description: The DevCycle React SDK for React web applications, also used by the React Native SDK --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/lifecycle.md b/docs/sdk/lifecycle.md index b7f5e794..2ddf1b57 100644 --- a/docs/sdk/lifecycle.md +++ b/docs/sdk/lifecycle.md @@ -1,6 +1,5 @@ --- title: SDK Release Lifecycle -description: How long each DevCycle SDK major version is supported, and which fixes are backported to previous versions --- # SDK Release Lifecycle diff --git a/docs/sdk/sdk-proxy/index.md b/docs/sdk/sdk-proxy/index.md index 221019fe..bc0b974e 100644 --- a/docs/sdk/sdk-proxy/index.md +++ b/docs/sdk/sdk-proxy/index.md @@ -1,6 +1,5 @@ --- title: Overview -description: A self-hosted proxy between DevCycle SDKs and the DevCycle APIs, for restricted networks or to share one external connection across many SDK instances --- diff --git a/docs/sdk/sdk-proxy/installation.md b/docs/sdk/sdk-proxy/installation.md index fe45a0fe..b165d763 100644 --- a/docs/sdk/sdk-proxy/installation.md +++ b/docs/sdk/sdk-proxy/installation.md @@ -1,6 +1,5 @@ --- title: Installation -description: Install the DevCycle SDK Proxy from source, as a Docker image, or as an OS packaged binary --- # Installation diff --git a/docs/sdk/sdk-proxy/usage.md b/docs/sdk/sdk-proxy/usage.md index 8c10ce20..b7db6a85 100644 --- a/docs/sdk/sdk-proxy/usage.md +++ b/docs/sdk/sdk-proxy/usage.md @@ -1,6 +1,5 @@ --- title: Usage -description: Run the SDK Proxy and configure server SDKs to connect to it --- ## Running the SDK Proxy diff --git a/docs/sdk/server-side-sdks/dotnet/dotnet.md b/docs/sdk/server-side-sdks/dotnet/dotnet.md index 0d5a0155..412e40af 100644 --- a/docs/sdk/server-side-sdks/dotnet/dotnet.md +++ b/docs/sdk/server-side-sdks/dotnet/dotnet.md @@ -1,6 +1,5 @@ --- title: .NET SDK -description: The DevCycle .NET / C# SDK for Cloud Bucketing and Local Bucketing --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/server-side-sdks/go/go.md b/docs/sdk/server-side-sdks/go/go.md index ac5c2905..bd3802be 100644 --- a/docs/sdk/server-side-sdks/go/go.md +++ b/docs/sdk/server-side-sdks/go/go.md @@ -1,6 +1,5 @@ --- title: Go SDK -description: The DevCycle Go Server SDK, supporting Local Bucketing and Cloud Bucketing modes --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/server-side-sdks/java/java.md b/docs/sdk/server-side-sdks/java/java.md index 558f3f22..b286a791 100644 --- a/docs/sdk/server-side-sdks/java/java.md +++ b/docs/sdk/server-side-sdks/java/java.md @@ -1,6 +1,5 @@ --- title: Java SDK -description: The DevCycle Java Server SDK, supporting Local Bucketing and Cloud Bucketing modes --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/server-side-sdks/php/php.md b/docs/sdk/server-side-sdks/php/php.md index 295dbcc4..a88cb766 100644 --- a/docs/sdk/server-side-sdks/php/php.md +++ b/docs/sdk/server-side-sdks/php/php.md @@ -1,6 +1,5 @@ --- title: PHP SDK -description: The DevCycle PHP Server SDK, which uses Cloud Bucketing, with local bucketing available through the SDK Proxy --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docs/sdk/server-side-sdks/ruby/ruby.md b/docs/sdk/server-side-sdks/ruby/ruby.md index e027529a..833f7d5a 100644 --- a/docs/sdk/server-side-sdks/ruby/ruby.md +++ b/docs/sdk/server-side-sdks/ruby/ruby.md @@ -1,6 +1,5 @@ --- title: Ruby SDK -description: The DevCycle Ruby Server SDK, supporting Local Bucketing and Cloud Bucketing modes --- import CustomDocCardList from '@site/src/components/CustomDocCardList' diff --git a/docusaurus.config.js b/docusaurus.config.js index c24fd508..223d6fd9 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -148,18 +148,6 @@ const LLMS_ROUTE_RULES = [ { route: '/examples', categoryName: 'Examples' }, ] -/** - * Prepend frontmatter to remote content. Without a description, Docusaurus - * uses the first line of the page, which is often a heading or badge. - */ -const withFrontMatter = (fields, content) => - '---\n' + - Object.entries(fields) - .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) - .join('\n') + - '\n---\n' + - content - const removeDocsSections = (content, sectionNames, headerIdentifier = '##') => { let result = content for (const sectionName of sectionNames) { @@ -306,29 +294,7 @@ const config = { return inFence ? line : line.replace(/^(#{1,5})\s/, '#$1 ') }) .join('\n') - return { - content: filename.includes('mcp-worker') - ? withFrontMatter( - { - title: 'DevCycle MCP Cloudflare Worker', - description: - 'The hosted DevCycle MCP server, running as a Cloudflare Worker with OAuth authentication', - }, - reduced, - ) - : reduced, - } - } - if (filename.endsWith('mcp.md')) { - return { - content: withFrontMatter( - { - description: - 'Tools, authentication, and configuration for the local and hosted DevCycle MCP servers', - }, - content, - ), - } + return { content: reduced } } return undefined }, @@ -349,18 +315,12 @@ const config = { '# DevCycle VSCode Extension \n##', ) return { - content: withFrontMatter( - { - description: - 'Manage and track DevCycle feature flags from Visual Studio Code', - }, - removeDocsSections(noTitle, [ - 'About DevCycle', - 'Documentation', - 'Sign Up for DevCycle', - 'Contributing', - ]), - ), + content: removeDocsSections(noTitle, [ + 'About DevCycle', + 'Documentation', + 'Sign Up for DevCycle', + 'Contributing', + ]), } } return undefined @@ -377,15 +337,10 @@ const config = { documents: ['README.md'], performCleanup: true, modifyContent: (filename, content) => ({ - content: withFrontMatter( - { - description: - 'Show DevCycle Variable code usages in the dashboard with a GitHub Action', - }, + content: '# GitHub: Feature Flag Code Usages \n' + - 'Get the integration on the [GitHub Marketplace](https://github.com/marketplace/actions/devcycle-feature-flag-code-usages)\n' + - content, - ), + 'Get the integration on the [GitHub Marketplace](https://github.com/marketplace/actions/devcycle-feature-flag-code-usages)\n' + + content, }), }, ], @@ -399,15 +354,10 @@ const config = { documents: ['README.md'], performCleanup: true, modifyContent: (filename, content) => ({ - content: withFrontMatter( - { - description: - 'Comment on pull requests with the DevCycle Features added or removed in each change, using a GitHub Action', - }, + content: '# GitHub: Feature Flag Change Insights on Pull Request \n' + - 'Get the integration on the [GitHub Marketplace](https://github.com/marketplace/actions/devcycle-feature-flag-insights-for-pull-requests)\n' + - content, - ), + 'Get the integration on the [GitHub Marketplace](https://github.com/marketplace/actions/devcycle-feature-flag-insights-for-pull-requests)\n' + + content, }), }, ], @@ -421,15 +371,10 @@ const config = { documents: ['README.md'], performCleanup: true, modifyContent: (filename, content) => ({ - content: withFrontMatter( - { - description: - 'Show DevCycle Variable code usages in the dashboard with a GitLab CI/CD pipeline', - }, + content: '# GitLab: Feature Flag Code Usages \n' + - 'Get the integration here: https://gitlab.com/devcycle/devcycle-usages-ci-cd\n' + - content, - ), + 'Get the integration here: https://gitlab.com/devcycle/devcycle-usages-ci-cd\n' + + content, }), }, ], @@ -443,15 +388,10 @@ const config = { documents: ['README.md'], performCleanup: true, modifyContent: (filename, content) => ({ - content: withFrontMatter( - { - description: - 'Comment on merge requests with the DevCycle Features added or removed in each change, using a GitLab CI/CD pipeline', - }, + content: '# GitLab: Feature Flag Change Insights on Merge Request\n' + - 'Get the integration here: https://gitlab.com/devcycle/devcycle-pr-insights-ci-cd\n' + - content, - ), + 'Get the integration here: https://gitlab.com/devcycle/devcycle-pr-insights-ci-cd\n' + + content, }), }, ],