From 3819b03715171d0f23c65e96ae86b17119d7687a Mon Sep 17 00:00:00 2001 From: mohamedh Date: Thu, 25 Jun 2026 20:47:47 +0100 Subject: [PATCH 01/15] feat: wire numbus up --- .gitignore | 2 + .nimbus/lint.json | 17 + .prettierignore | 5 + astro.config.ts | 328 +++-- eslint.config.js | 4 + package.json | 9 + pnpm-lock.yaml | 202 ++- pnpm-workspace.yaml | 25 + .../changelog/waf/2026-05-04-waf-release.mdx | 18 +- src/nimbus/README.md | 42 + src/nimbus/astro-config.ts | 199 +++ src/nimbus/components.ts | 249 ++++ src/nimbus/components/AgentDirective.astro | 16 + src/nimbus/components/BackgroundLines.astro | 60 + src/nimbus/components/CopyPromptButton.astro | 91 ++ src/nimbus/components/CornerMarks.astro | 45 + src/nimbus/components/Header.astro | 117 ++ src/nimbus/components/ProductCard.astro | 86 ++ src/nimbus/components/ProductCardGrid.astro | 25 + src/nimbus/components/Render.astro | 119 ++ .../components/SubtractIPCalculator.tsx | 10 + src/nimbus/components/_stubs/Deferred.astro | 14 + src/nimbus/components/_stubs/Stub.astro | 34 + src/nimbus/components/agents.ts | 20 + src/nimbus/components/cf/APIRequest.astro | 200 +++ .../components/cf/AgentsPlatformDiagram.astro | 465 ++++++ src/nimbus/components/cf/AnchorHeading.astro | 42 + .../cf/AnimatedWorkflowDiagram.astro | 361 +++++ .../components/cf/AutoconfigDiagram.astro | 560 ++++++++ .../cf/AvailableNotifications.astro | 93 ++ src/nimbus/components/cf/CURL.astro | 83 ++ .../components/cf/CompatibilityFlags.astro | 68 + src/nimbus/components/cf/DashButton.astro | 44 + src/nimbus/components/cf/Description.astro | 13 + src/nimbus/components/cf/Details.astro | 30 + .../components/cf/DirectoryListing.astro | 103 ++ .../components/cf/DirectoryListingItem.astro | 40 + src/nimbus/components/cf/Example.astro | 33 + .../components/cf/ExtraFlagDetails.astro | 20 + src/nimbus/components/cf/Feature.astro | 68 + src/nimbus/components/cf/FeatureTable.astro | 87 ++ src/nimbus/components/cf/Flex.astro | 11 + src/nimbus/components/cf/FourCardGrid.astro | 40 + src/nimbus/components/cf/GitHubCode.astro | 100 ++ src/nimbus/components/cf/Glossary.astro | 135 ++ .../components/cf/GlossaryDefinition.astro | 46 + .../components/cf/GlossaryTooltip.astro | 84 ++ src/nimbus/components/cf/InlineBadge.astro | 50 + src/nimbus/components/cf/LinkButton.astro | 59 + src/nimbus/components/cf/LinkCard.astro | 27 + src/nimbus/components/cf/LinkTitleCard.astro | 32 + src/nimbus/components/cf/ListCard.astro | 61 + src/nimbus/components/cf/ListTutorials.astro | 66 + src/nimbus/components/cf/Markdown.astro | 33 + src/nimbus/components/cf/MetaInfo.astro | 15 + .../components/cf/PagesBuildEnvironment.astro | 38 + .../cf/PagesBuildEnvironmentLanguages.astro | 43 + .../cf/PagesBuildEnvironmentTools.astro | 41 + .../components/cf/PagesBuildPreset.astro | 55 + src/nimbus/components/cf/Plan.astro | 55 + .../components/cf/ProductFeatures.astro | 129 ++ .../components/cf/ProductReleaseNotes.astro | 122 ++ src/nimbus/components/cf/PublicStats.astro | 27 + .../components/cf/R2LocalUploadsDiagram.astro | 1259 +++++++++++++++++ src/nimbus/components/cf/RSSButton.astro | 45 + src/nimbus/components/cf/ReactSelect.tsx | 90 ++ src/nimbus/components/cf/RelatedProduct.astro | 36 + .../components/cf/ResourcesBySelector.astro | 195 +++ .../components/cf/ResourcesBySelector.tsx | 517 +++++++ src/nimbus/components/cf/RuleID.astro | 49 + src/nimbus/components/cf/Stream.astro | 199 +++ src/nimbus/components/cf/Type.astro | 21 + .../components/cf/TypeScriptExample.astro | 75 + src/nimbus/components/cf/WARPRelease.astro | 132 ++ src/nimbus/components/cf/WARPReleases.astro | 66 + src/nimbus/components/cf/Width.astro | 27 + .../cf/WorkersArchitectureDiagram.astro | 1064 ++++++++++++++ .../components/cf/WorkersIsolateDiagram.astro | 310 ++++ src/nimbus/components/cf/WranglerArg.astro | 55 + .../components/cf/WranglerCommand.astro | 112 ++ src/nimbus/components/cf/WranglerConfig.astro | 86 ++ .../components/cf/WranglerNamespace.astro | 59 + src/nimbus/components/cf/YouTube.astro | 33 + .../components/changelog/ChangelogEntry.astro | 59 + .../components/changelog/ChangelogFeed.astro | 135 ++ .../components/changelog/DateRail.astro | 30 + src/nimbus/components/changelog/Header.astro | 180 +++ .../components/changelog/Pagination.astro | 103 ++ .../components/changelog/ProductPills.astro | 31 + .../components/directory/Directory.astro | 212 +++ .../components/directory/directory.client.ts | 179 +++ src/nimbus/components/directory/grid.ts | 79 ++ .../landing/AccelerateSection.astro | 46 + .../components/landing/AgentSetup.astro | 61 + .../components/landing/BuildFromScratch.astro | 185 +++ .../components/landing/ChangelogSection.astro | 177 +++ .../components/landing/CommandBlock.astro | 126 ++ .../components/landing/CommunityGrid.astro | 85 ++ .../components/landing/FullPageLines.astro | 61 + .../landing/HalftoneBackground.astro | 44 + src/nimbus/components/landing/Hero.astro | 29 + .../components/landing/SectionHeading.astro | 18 + .../components/landing/SecureSection.astro | 107 ++ src/nimbus/components/landing/Sidebar.astro | 82 ++ .../components/landing/StructuralGrid.astro | 83 ++ src/nimbus/components/landing/TabBar.astro | 287 ++++ .../components/landing/ViewAllLink.astro | 24 + .../components/landing/accelerate-data.ts | 79 ++ src/nimbus/components/landing/animation.ts | 4 + src/nimbus/components/landing/sidebar-data.ts | 239 ++++ .../components/models/CopyableCode.astro | 75 + .../components/models/ExampleCard.astro | 215 +++ .../components/models/ModelBadges.astro | 66 + src/nimbus/components/models/ModelCard.astro | 129 ++ .../components/models/ModelCatalog.astro | 152 ++ .../components/models/ModelDetailPage.astro | 607 ++++++++ .../components/models/ModelFeatures.astro | 213 +++ src/nimbus/components/models/OutputBody.astro | 66 + .../components/models/SchemaDisplay.astro | 429 ++++++ src/nimbus/components/models/SchemaTree.tsx | 441 ++++++ .../models/SchemaVariantSelector.tsx | 87 ++ .../components/models/SchemaVariantTabs.tsx | 71 + .../models/code/Bge-Reranker-Base.astro | 79 ++ .../components/models/code/DeepgramAura.astro | 47 + .../models/code/Flux-1-Schnell.astro | 75 + .../models/code/ObjectDetectionCode.astro | 53 + .../models/code/SummarizationCode.astro | 47 + .../models/code/TextClassificationCode.astro | 64 + .../models/code/TextEmbeddingCode.astro | 90 ++ .../models/code/TextGenerationCode.astro | 162 +++ .../models/code/TranslationCode.astro | 73 + src/nimbus/components/models/data.ts | 251 ++++ src/nimbus/components/models/models.client.ts | 229 +++ src/nimbus/components/models/types.ts | 25 + .../components/react/SubtractIPCalculator.tsx | 125 ++ .../AgentPrimitivesDiagram.tsx | 334 +++++ .../components/react/diagram/ActionBar.tsx | 14 + .../components/react/diagram/ActionButton.tsx | 60 + .../components/react/diagram/CardBadge.tsx | 37 + .../components/react/diagram/ChipGroup.tsx | 69 + .../react/diagram/DiagramControls.tsx | 64 + .../components/react/diagram/DiagramDebug.tsx | 55 + .../components/react/diagram/DiagramDefs.tsx | 59 + .../react/diagram/DiagramPauseAll.tsx | 50 + .../components/react/diagram/DiagramStage.tsx | 56 + src/nimbus/components/react/diagram/Tabs.tsx | 112 ++ src/nimbus/components/react/diagram/index.ts | 37 + src/nimbus/components/react/diagram/scene.tsx | 244 ++++ .../components/react/diagram/welding.ts | 177 +++ src/nimbus/components/ui/aside/Aside.astro | 75 + src/nimbus/components/ui/aside/index.ts | 1 + src/nimbus/components/ui/badge/Badge.astro | 42 + src/nimbus/components/ui/badge/index.ts | 1 + src/nimbus/components/ui/banner/Banner.astro | 82 ++ .../components/ui/banner/banner.client.ts | 49 + src/nimbus/components/ui/banner/index.ts | 1 + .../ui/breadcrumbs/Breadcrumbs.astro | 84 ++ src/nimbus/components/ui/breadcrumbs/index.ts | 1 + src/nimbus/components/ui/button/Button.astro | 71 + src/nimbus/components/ui/button/index.ts | 13 + src/nimbus/components/ui/button/variants.ts | 81 ++ .../components/ui/card-grid/CardGrid.astro | 15 + src/nimbus/components/ui/card-grid/index.ts | 1 + src/nimbus/components/ui/card/Card.astro | 21 + src/nimbus/components/ui/card/index.ts | 1 + .../components/ui/checkbox/Checkbox.astro | 92 ++ .../ui/checkbox/CheckboxGroup.astro | 59 + src/nimbus/components/ui/checkbox/index.ts | 8 + src/nimbus/components/ui/checkbox/variants.ts | 35 + src/nimbus/components/ui/code/Code.astro | 26 + src/nimbus/components/ui/code/index.ts | 1 + .../ui/collapsible/Collapsible.astro | 25 + .../ui/collapsible/CollapsibleContent.astro | 27 + .../ui/collapsible/CollapsibleTrigger.astro | 21 + .../ui/collapsible/collapsible.client.ts | 22 + src/nimbus/components/ui/collapsible/index.ts | 3 + .../components/ui/combobox/Combobox.astro | 227 +++ .../ui/combobox/ComboboxGroup.astro | 25 + .../ui/combobox/ComboboxGroupLabel.astro | 23 + .../ui/combobox/ComboboxOption.astro | 40 + .../components/ui/combobox/combobox.client.ts | 305 ++++ src/nimbus/components/ui/combobox/index.ts | 4 + src/nimbus/components/ui/dialog/Dialog.astro | 54 + .../components/ui/dialog/DialogClose.astro | 36 + .../components/ui/dialog/DialogContent.astro | 21 + src/nimbus/components/ui/dialog/index.ts | 3 + .../components/ui/file-tree/FileTree.astro | 263 ++++ src/nimbus/components/ui/file-tree/index.ts | 1 + .../components/ui/layer-card/LayerCard.astro | 23 + .../ui/layer-card/LayerCardContent.astro | 16 + .../ui/layer-card/LayerCardHeader.astro | 16 + src/nimbus/components/ui/layer-card/index.ts | 3 + .../ui/link-button/LinkButton.astro | 76 + src/nimbus/components/ui/link-button/index.ts | 1 + .../ui/package-managers/PackageManagers.astro | 112 ++ .../components/ui/package-managers/index.ts | 1 + .../package-managers.client.ts | 55 + .../ui/page-actions/PageActions.astro | 65 + .../components/ui/page-actions/index.ts | 1 + .../ui/page-actions/page-actions.client.ts | 54 + .../components/ui/pagination/Pagination.astro | 36 + src/nimbus/components/ui/pagination/index.ts | 1 + .../components/ui/search/SearchDialog.astro | 113 ++ .../components/ui/search/SearchTrigger.astro | 41 + src/nimbus/components/ui/search/index.ts | 2 + .../ui/search/providers/pagefind.ts | 80 ++ .../components/ui/search/search.client.ts | 201 +++ .../components/ui/sidebar/Sidebar.astro | 63 + .../components/ui/sidebar/SidebarFilter.astro | 26 + .../components/ui/sidebar/SidebarGroup.astro | 208 +++ .../components/ui/sidebar/SidebarLink.astro | 37 + .../ui/sidebar/SidebarProductNav.astro | 37 + src/nimbus/components/ui/sidebar/index.ts | 5 + .../components/ui/sidebar/sidebar.client.ts | 209 +++ src/nimbus/components/ui/steps/Step.astro | 26 + src/nimbus/components/ui/steps/Steps.astro | 115 ++ src/nimbus/components/ui/steps/index.ts | 2 + .../components/ui/steps/steps.client.ts | 20 + src/nimbus/components/ui/tabs/TabItem.astro | 30 + src/nimbus/components/ui/tabs/Tabs.astro | 36 + .../components/ui/tabs/TabsContent.astro | 24 + src/nimbus/components/ui/tabs/TabsList.astro | 26 + .../components/ui/tabs/TabsTrigger.astro | 31 + src/nimbus/components/ui/tabs/index.ts | 5 + src/nimbus/components/ui/tabs/tabs.client.ts | 72 + .../ui/theme-toggle/ThemeToggle.astro | 32 + .../components/ui/theme-toggle/index.ts | 1 + .../ui/theme-toggle/theme-toggle.client.ts | 31 + src/nimbus/components/ui/toc/TOC.astro | 95 ++ src/nimbus/components/ui/toc/index.ts | 1 + src/nimbus/components/ui/toc/toc.client.ts | 178 +++ src/nimbus/content.config.ts | 398 ++++++ src/nimbus/layouts/BaseLayout.astro | 124 ++ src/nimbus/layouts/ChangelogLayout.astro | 138 ++ src/nimbus/layouts/DocsLayout.astro | 369 +++++ src/nimbus/lib/cn.ts | 7 + src/nimbus/pages/[...changelog].xml.ts | 153 ++ src/nimbus/pages/[...slug].astro | 92 ++ src/nimbus/pages/[...slug]/index.md.ts | 79 ++ src/nimbus/pages/[section]/llms.txt.ts | 64 + src/nimbus/pages/ai/models/[...name].astro | 33 + src/nimbus/pages/ai/models/[...name].md.ts | 30 + .../pages/ai/models/[...schema].json.ts | 49 + src/nimbus/pages/ai/models/index.astro | 36 + src/nimbus/pages/changelog/[...page].astro | 55 + .../pages/changelog/post/[...slug].astro | 85 ++ .../product-group/[group]/[...page].astro | 58 + .../product/[product]/[...page].astro | 71 + src/nimbus/pages/changelog/rss/[area].xml.ts | 63 + .../pages/changelog/rss/[product].xml.ts | 54 + src/nimbus/pages/changelog/rss/index.xml.ts | 25 + src/nimbus/pages/directory.astro | 58 + src/nimbus/pages/index.astro | 205 +++ src/nimbus/pages/llms.txt.ts | 48 + src/nimbus/pages/resources/index.astro | 66 + src/nimbus/pages/robots.txt.ts | 17 + src/nimbus/pages/videos/[...slug].astro | 57 + .../pages/workers-ai/models/[...name].astro | 29 + .../pages/workers-ai/models/[...name].md.ts | 30 + .../workers-ai/models/[...schema].json.ts | 49 + .../platform/compatibility-flags.json.ts | 31 + .../plugins/rehype/autolink-headings.ts | 72 + .../plugins/rehype/empty-table-headers.ts | 21 + src/nimbus/plugins/rehype/heading-slugs.ts | 88 ++ src/nimbus/plugins/rehype/index.ts | 43 + src/nimbus/plugins/rehype/mermaid.ts | 47 + src/nimbus/plugins/rehype/shift-headings.ts | 43 + src/nimbus/plugins/rehype/types.ts | 38 + src/nimbus/schemas/compatibility-flags.ts | 12 + src/nimbus/schemas/index.ts | 3 + src/nimbus/schemas/warp-releases.ts | 24 + src/nimbus/scripts/mermaid.client.ts | 258 ++++ src/nimbus/styles/globals.css | 646 +++++++++ src/nimbus/styles/markdown-pipeline.css | 302 ++++ src/nimbus/styles/prose.css | 229 +++ src/nimbus/tsconfig.json | 17 + src/nimbus/util/api.ts | 32 + src/nimbus/util/changelog.ts | 207 +++ src/nimbus/util/container.ts | 49 + src/nimbus/util/content-type.ts | 13 + src/nimbus/util/directory.ts | 39 + src/nimbus/util/model-markdown.ts | 150 ++ src/nimbus/util/models/facets.ts | 99 ++ src/nimbus/util/models/index.ts | 9 + src/nimbus/util/models/model-helpers.ts | 14 + src/nimbus/util/models/model-properties.ts | 38 + src/nimbus/util/models/model-resolver.ts | 228 +++ src/nimbus/util/models/model-schema.ts | 112 ++ src/nimbus/util/models/model-types.ts | 85 ++ src/nimbus/util/release-notes.ts | 60 + src/nimbus/util/sidebar.ts | 67 + src/nimbus/util/url.ts | 18 + src/nimbus/util/warp-platforms.json | 82 ++ src/nimbus/util/zaraz.ts | 9 + tsconfig.json | 2 +- 295 files changed, 27353 insertions(+), 173 deletions(-) create mode 100644 .nimbus/lint.json create mode 100644 src/nimbus/README.md create mode 100644 src/nimbus/astro-config.ts create mode 100644 src/nimbus/components.ts create mode 100644 src/nimbus/components/AgentDirective.astro create mode 100644 src/nimbus/components/BackgroundLines.astro create mode 100644 src/nimbus/components/CopyPromptButton.astro create mode 100644 src/nimbus/components/CornerMarks.astro create mode 100644 src/nimbus/components/Header.astro create mode 100644 src/nimbus/components/ProductCard.astro create mode 100644 src/nimbus/components/ProductCardGrid.astro create mode 100644 src/nimbus/components/Render.astro create mode 100644 src/nimbus/components/SubtractIPCalculator.tsx create mode 100644 src/nimbus/components/_stubs/Deferred.astro create mode 100644 src/nimbus/components/_stubs/Stub.astro create mode 100644 src/nimbus/components/agents.ts create mode 100644 src/nimbus/components/cf/APIRequest.astro create mode 100644 src/nimbus/components/cf/AgentsPlatformDiagram.astro create mode 100644 src/nimbus/components/cf/AnchorHeading.astro create mode 100644 src/nimbus/components/cf/AnimatedWorkflowDiagram.astro create mode 100644 src/nimbus/components/cf/AutoconfigDiagram.astro create mode 100644 src/nimbus/components/cf/AvailableNotifications.astro create mode 100644 src/nimbus/components/cf/CURL.astro create mode 100644 src/nimbus/components/cf/CompatibilityFlags.astro create mode 100644 src/nimbus/components/cf/DashButton.astro create mode 100644 src/nimbus/components/cf/Description.astro create mode 100644 src/nimbus/components/cf/Details.astro create mode 100644 src/nimbus/components/cf/DirectoryListing.astro create mode 100644 src/nimbus/components/cf/DirectoryListingItem.astro create mode 100644 src/nimbus/components/cf/Example.astro create mode 100644 src/nimbus/components/cf/ExtraFlagDetails.astro create mode 100644 src/nimbus/components/cf/Feature.astro create mode 100644 src/nimbus/components/cf/FeatureTable.astro create mode 100644 src/nimbus/components/cf/Flex.astro create mode 100644 src/nimbus/components/cf/FourCardGrid.astro create mode 100644 src/nimbus/components/cf/GitHubCode.astro create mode 100644 src/nimbus/components/cf/Glossary.astro create mode 100644 src/nimbus/components/cf/GlossaryDefinition.astro create mode 100644 src/nimbus/components/cf/GlossaryTooltip.astro create mode 100644 src/nimbus/components/cf/InlineBadge.astro create mode 100644 src/nimbus/components/cf/LinkButton.astro create mode 100644 src/nimbus/components/cf/LinkCard.astro create mode 100644 src/nimbus/components/cf/LinkTitleCard.astro create mode 100644 src/nimbus/components/cf/ListCard.astro create mode 100644 src/nimbus/components/cf/ListTutorials.astro create mode 100644 src/nimbus/components/cf/Markdown.astro create mode 100644 src/nimbus/components/cf/MetaInfo.astro create mode 100644 src/nimbus/components/cf/PagesBuildEnvironment.astro create mode 100644 src/nimbus/components/cf/PagesBuildEnvironmentLanguages.astro create mode 100644 src/nimbus/components/cf/PagesBuildEnvironmentTools.astro create mode 100644 src/nimbus/components/cf/PagesBuildPreset.astro create mode 100644 src/nimbus/components/cf/Plan.astro create mode 100644 src/nimbus/components/cf/ProductFeatures.astro create mode 100644 src/nimbus/components/cf/ProductReleaseNotes.astro create mode 100644 src/nimbus/components/cf/PublicStats.astro create mode 100644 src/nimbus/components/cf/R2LocalUploadsDiagram.astro create mode 100644 src/nimbus/components/cf/RSSButton.astro create mode 100644 src/nimbus/components/cf/ReactSelect.tsx create mode 100644 src/nimbus/components/cf/RelatedProduct.astro create mode 100644 src/nimbus/components/cf/ResourcesBySelector.astro create mode 100644 src/nimbus/components/cf/ResourcesBySelector.tsx create mode 100644 src/nimbus/components/cf/RuleID.astro create mode 100644 src/nimbus/components/cf/Stream.astro create mode 100644 src/nimbus/components/cf/Type.astro create mode 100644 src/nimbus/components/cf/TypeScriptExample.astro create mode 100644 src/nimbus/components/cf/WARPRelease.astro create mode 100644 src/nimbus/components/cf/WARPReleases.astro create mode 100644 src/nimbus/components/cf/Width.astro create mode 100644 src/nimbus/components/cf/WorkersArchitectureDiagram.astro create mode 100644 src/nimbus/components/cf/WorkersIsolateDiagram.astro create mode 100644 src/nimbus/components/cf/WranglerArg.astro create mode 100644 src/nimbus/components/cf/WranglerCommand.astro create mode 100644 src/nimbus/components/cf/WranglerConfig.astro create mode 100644 src/nimbus/components/cf/WranglerNamespace.astro create mode 100644 src/nimbus/components/cf/YouTube.astro create mode 100644 src/nimbus/components/changelog/ChangelogEntry.astro create mode 100644 src/nimbus/components/changelog/ChangelogFeed.astro create mode 100644 src/nimbus/components/changelog/DateRail.astro create mode 100644 src/nimbus/components/changelog/Header.astro create mode 100644 src/nimbus/components/changelog/Pagination.astro create mode 100644 src/nimbus/components/changelog/ProductPills.astro create mode 100644 src/nimbus/components/directory/Directory.astro create mode 100644 src/nimbus/components/directory/directory.client.ts create mode 100644 src/nimbus/components/directory/grid.ts create mode 100644 src/nimbus/components/landing/AccelerateSection.astro create mode 100644 src/nimbus/components/landing/AgentSetup.astro create mode 100644 src/nimbus/components/landing/BuildFromScratch.astro create mode 100644 src/nimbus/components/landing/ChangelogSection.astro create mode 100644 src/nimbus/components/landing/CommandBlock.astro create mode 100644 src/nimbus/components/landing/CommunityGrid.astro create mode 100644 src/nimbus/components/landing/FullPageLines.astro create mode 100644 src/nimbus/components/landing/HalftoneBackground.astro create mode 100644 src/nimbus/components/landing/Hero.astro create mode 100644 src/nimbus/components/landing/SectionHeading.astro create mode 100644 src/nimbus/components/landing/SecureSection.astro create mode 100644 src/nimbus/components/landing/Sidebar.astro create mode 100644 src/nimbus/components/landing/StructuralGrid.astro create mode 100644 src/nimbus/components/landing/TabBar.astro create mode 100644 src/nimbus/components/landing/ViewAllLink.astro create mode 100644 src/nimbus/components/landing/accelerate-data.ts create mode 100644 src/nimbus/components/landing/animation.ts create mode 100644 src/nimbus/components/landing/sidebar-data.ts create mode 100644 src/nimbus/components/models/CopyableCode.astro create mode 100644 src/nimbus/components/models/ExampleCard.astro create mode 100644 src/nimbus/components/models/ModelBadges.astro create mode 100644 src/nimbus/components/models/ModelCard.astro create mode 100644 src/nimbus/components/models/ModelCatalog.astro create mode 100644 src/nimbus/components/models/ModelDetailPage.astro create mode 100644 src/nimbus/components/models/ModelFeatures.astro create mode 100644 src/nimbus/components/models/OutputBody.astro create mode 100644 src/nimbus/components/models/SchemaDisplay.astro create mode 100644 src/nimbus/components/models/SchemaTree.tsx create mode 100644 src/nimbus/components/models/SchemaVariantSelector.tsx create mode 100644 src/nimbus/components/models/SchemaVariantTabs.tsx create mode 100644 src/nimbus/components/models/code/Bge-Reranker-Base.astro create mode 100644 src/nimbus/components/models/code/DeepgramAura.astro create mode 100644 src/nimbus/components/models/code/Flux-1-Schnell.astro create mode 100644 src/nimbus/components/models/code/ObjectDetectionCode.astro create mode 100644 src/nimbus/components/models/code/SummarizationCode.astro create mode 100644 src/nimbus/components/models/code/TextClassificationCode.astro create mode 100644 src/nimbus/components/models/code/TextEmbeddingCode.astro create mode 100644 src/nimbus/components/models/code/TextGenerationCode.astro create mode 100644 src/nimbus/components/models/code/TranslationCode.astro create mode 100644 src/nimbus/components/models/data.ts create mode 100644 src/nimbus/components/models/models.client.ts create mode 100644 src/nimbus/components/models/types.ts create mode 100644 src/nimbus/components/react/SubtractIPCalculator.tsx create mode 100644 src/nimbus/components/react/diagram-showcase/AgentPrimitivesDiagram.tsx create mode 100644 src/nimbus/components/react/diagram/ActionBar.tsx create mode 100644 src/nimbus/components/react/diagram/ActionButton.tsx create mode 100644 src/nimbus/components/react/diagram/CardBadge.tsx create mode 100644 src/nimbus/components/react/diagram/ChipGroup.tsx create mode 100644 src/nimbus/components/react/diagram/DiagramControls.tsx create mode 100644 src/nimbus/components/react/diagram/DiagramDebug.tsx create mode 100644 src/nimbus/components/react/diagram/DiagramDefs.tsx create mode 100644 src/nimbus/components/react/diagram/DiagramPauseAll.tsx create mode 100644 src/nimbus/components/react/diagram/DiagramStage.tsx create mode 100644 src/nimbus/components/react/diagram/Tabs.tsx create mode 100644 src/nimbus/components/react/diagram/index.ts create mode 100644 src/nimbus/components/react/diagram/scene.tsx create mode 100644 src/nimbus/components/react/diagram/welding.ts create mode 100644 src/nimbus/components/ui/aside/Aside.astro create mode 100644 src/nimbus/components/ui/aside/index.ts create mode 100644 src/nimbus/components/ui/badge/Badge.astro create mode 100644 src/nimbus/components/ui/badge/index.ts create mode 100644 src/nimbus/components/ui/banner/Banner.astro create mode 100644 src/nimbus/components/ui/banner/banner.client.ts create mode 100644 src/nimbus/components/ui/banner/index.ts create mode 100644 src/nimbus/components/ui/breadcrumbs/Breadcrumbs.astro create mode 100644 src/nimbus/components/ui/breadcrumbs/index.ts create mode 100644 src/nimbus/components/ui/button/Button.astro create mode 100644 src/nimbus/components/ui/button/index.ts create mode 100644 src/nimbus/components/ui/button/variants.ts create mode 100644 src/nimbus/components/ui/card-grid/CardGrid.astro create mode 100644 src/nimbus/components/ui/card-grid/index.ts create mode 100644 src/nimbus/components/ui/card/Card.astro create mode 100644 src/nimbus/components/ui/card/index.ts create mode 100644 src/nimbus/components/ui/checkbox/Checkbox.astro create mode 100644 src/nimbus/components/ui/checkbox/CheckboxGroup.astro create mode 100644 src/nimbus/components/ui/checkbox/index.ts create mode 100644 src/nimbus/components/ui/checkbox/variants.ts create mode 100644 src/nimbus/components/ui/code/Code.astro create mode 100644 src/nimbus/components/ui/code/index.ts create mode 100644 src/nimbus/components/ui/collapsible/Collapsible.astro create mode 100644 src/nimbus/components/ui/collapsible/CollapsibleContent.astro create mode 100644 src/nimbus/components/ui/collapsible/CollapsibleTrigger.astro create mode 100644 src/nimbus/components/ui/collapsible/collapsible.client.ts create mode 100644 src/nimbus/components/ui/collapsible/index.ts create mode 100644 src/nimbus/components/ui/combobox/Combobox.astro create mode 100644 src/nimbus/components/ui/combobox/ComboboxGroup.astro create mode 100644 src/nimbus/components/ui/combobox/ComboboxGroupLabel.astro create mode 100644 src/nimbus/components/ui/combobox/ComboboxOption.astro create mode 100644 src/nimbus/components/ui/combobox/combobox.client.ts create mode 100644 src/nimbus/components/ui/combobox/index.ts create mode 100644 src/nimbus/components/ui/dialog/Dialog.astro create mode 100644 src/nimbus/components/ui/dialog/DialogClose.astro create mode 100644 src/nimbus/components/ui/dialog/DialogContent.astro create mode 100644 src/nimbus/components/ui/dialog/index.ts create mode 100644 src/nimbus/components/ui/file-tree/FileTree.astro create mode 100644 src/nimbus/components/ui/file-tree/index.ts create mode 100644 src/nimbus/components/ui/layer-card/LayerCard.astro create mode 100644 src/nimbus/components/ui/layer-card/LayerCardContent.astro create mode 100644 src/nimbus/components/ui/layer-card/LayerCardHeader.astro create mode 100644 src/nimbus/components/ui/layer-card/index.ts create mode 100644 src/nimbus/components/ui/link-button/LinkButton.astro create mode 100644 src/nimbus/components/ui/link-button/index.ts create mode 100644 src/nimbus/components/ui/package-managers/PackageManagers.astro create mode 100644 src/nimbus/components/ui/package-managers/index.ts create mode 100644 src/nimbus/components/ui/package-managers/package-managers.client.ts create mode 100644 src/nimbus/components/ui/page-actions/PageActions.astro create mode 100644 src/nimbus/components/ui/page-actions/index.ts create mode 100644 src/nimbus/components/ui/page-actions/page-actions.client.ts create mode 100644 src/nimbus/components/ui/pagination/Pagination.astro create mode 100644 src/nimbus/components/ui/pagination/index.ts create mode 100644 src/nimbus/components/ui/search/SearchDialog.astro create mode 100644 src/nimbus/components/ui/search/SearchTrigger.astro create mode 100644 src/nimbus/components/ui/search/index.ts create mode 100644 src/nimbus/components/ui/search/providers/pagefind.ts create mode 100644 src/nimbus/components/ui/search/search.client.ts create mode 100644 src/nimbus/components/ui/sidebar/Sidebar.astro create mode 100644 src/nimbus/components/ui/sidebar/SidebarFilter.astro create mode 100644 src/nimbus/components/ui/sidebar/SidebarGroup.astro create mode 100644 src/nimbus/components/ui/sidebar/SidebarLink.astro create mode 100644 src/nimbus/components/ui/sidebar/SidebarProductNav.astro create mode 100644 src/nimbus/components/ui/sidebar/index.ts create mode 100644 src/nimbus/components/ui/sidebar/sidebar.client.ts create mode 100644 src/nimbus/components/ui/steps/Step.astro create mode 100644 src/nimbus/components/ui/steps/Steps.astro create mode 100644 src/nimbus/components/ui/steps/index.ts create mode 100644 src/nimbus/components/ui/steps/steps.client.ts create mode 100644 src/nimbus/components/ui/tabs/TabItem.astro create mode 100644 src/nimbus/components/ui/tabs/Tabs.astro create mode 100644 src/nimbus/components/ui/tabs/TabsContent.astro create mode 100644 src/nimbus/components/ui/tabs/TabsList.astro create mode 100644 src/nimbus/components/ui/tabs/TabsTrigger.astro create mode 100644 src/nimbus/components/ui/tabs/index.ts create mode 100644 src/nimbus/components/ui/tabs/tabs.client.ts create mode 100644 src/nimbus/components/ui/theme-toggle/ThemeToggle.astro create mode 100644 src/nimbus/components/ui/theme-toggle/index.ts create mode 100644 src/nimbus/components/ui/theme-toggle/theme-toggle.client.ts create mode 100644 src/nimbus/components/ui/toc/TOC.astro create mode 100644 src/nimbus/components/ui/toc/index.ts create mode 100644 src/nimbus/components/ui/toc/toc.client.ts create mode 100644 src/nimbus/content.config.ts create mode 100644 src/nimbus/layouts/BaseLayout.astro create mode 100644 src/nimbus/layouts/ChangelogLayout.astro create mode 100644 src/nimbus/layouts/DocsLayout.astro create mode 100644 src/nimbus/lib/cn.ts create mode 100644 src/nimbus/pages/[...changelog].xml.ts create mode 100644 src/nimbus/pages/[...slug].astro create mode 100644 src/nimbus/pages/[...slug]/index.md.ts create mode 100644 src/nimbus/pages/[section]/llms.txt.ts create mode 100644 src/nimbus/pages/ai/models/[...name].astro create mode 100644 src/nimbus/pages/ai/models/[...name].md.ts create mode 100644 src/nimbus/pages/ai/models/[...schema].json.ts create mode 100644 src/nimbus/pages/ai/models/index.astro create mode 100644 src/nimbus/pages/changelog/[...page].astro create mode 100644 src/nimbus/pages/changelog/post/[...slug].astro create mode 100644 src/nimbus/pages/changelog/product-group/[group]/[...page].astro create mode 100644 src/nimbus/pages/changelog/product/[product]/[...page].astro create mode 100644 src/nimbus/pages/changelog/rss/[area].xml.ts create mode 100644 src/nimbus/pages/changelog/rss/[product].xml.ts create mode 100644 src/nimbus/pages/changelog/rss/index.xml.ts create mode 100644 src/nimbus/pages/directory.astro create mode 100644 src/nimbus/pages/index.astro create mode 100644 src/nimbus/pages/llms.txt.ts create mode 100644 src/nimbus/pages/resources/index.astro create mode 100644 src/nimbus/pages/robots.txt.ts create mode 100644 src/nimbus/pages/videos/[...slug].astro create mode 100644 src/nimbus/pages/workers-ai/models/[...name].astro create mode 100644 src/nimbus/pages/workers-ai/models/[...name].md.ts create mode 100644 src/nimbus/pages/workers-ai/models/[...schema].json.ts create mode 100644 src/nimbus/pages/workers/platform/compatibility-flags.json.ts create mode 100644 src/nimbus/plugins/rehype/autolink-headings.ts create mode 100644 src/nimbus/plugins/rehype/empty-table-headers.ts create mode 100644 src/nimbus/plugins/rehype/heading-slugs.ts create mode 100644 src/nimbus/plugins/rehype/index.ts create mode 100644 src/nimbus/plugins/rehype/mermaid.ts create mode 100644 src/nimbus/plugins/rehype/shift-headings.ts create mode 100644 src/nimbus/plugins/rehype/types.ts create mode 100644 src/nimbus/schemas/compatibility-flags.ts create mode 100644 src/nimbus/schemas/index.ts create mode 100644 src/nimbus/schemas/warp-releases.ts create mode 100644 src/nimbus/scripts/mermaid.client.ts create mode 100644 src/nimbus/styles/globals.css create mode 100644 src/nimbus/styles/markdown-pipeline.css create mode 100644 src/nimbus/styles/prose.css create mode 100644 src/nimbus/tsconfig.json create mode 100644 src/nimbus/util/api.ts create mode 100644 src/nimbus/util/changelog.ts create mode 100644 src/nimbus/util/container.ts create mode 100644 src/nimbus/util/content-type.ts create mode 100644 src/nimbus/util/directory.ts create mode 100644 src/nimbus/util/model-markdown.ts create mode 100644 src/nimbus/util/models/facets.ts create mode 100644 src/nimbus/util/models/index.ts create mode 100644 src/nimbus/util/models/model-helpers.ts create mode 100644 src/nimbus/util/models/model-properties.ts create mode 100644 src/nimbus/util/models/model-resolver.ts create mode 100644 src/nimbus/util/models/model-schema.ts create mode 100644 src/nimbus/util/models/model-types.ts create mode 100644 src/nimbus/util/release-notes.ts create mode 100644 src/nimbus/util/sidebar.ts create mode 100644 src/nimbus/util/url.ts create mode 100644 src/nimbus/util/warp-platforms.json create mode 100644 src/nimbus/util/zaraz.ts diff --git a/.gitignore b/.gitignore index 0bf53323328..1e200745676 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # build output dist/ +dist-nimbus/ distmd/ distllms/ @@ -8,6 +9,7 @@ distllms/ # Astro build cache .astro-cache/ +.astro-cache-nimbus/ # skills/ is fetched from middlecache via bin/fetch-skills.ts skills/ diff --git a/.nimbus/lint.json b/.nimbus/lint.json new file mode 100644 index 00000000000..4b09489d34a --- /dev/null +++ b/.nimbus/lint.json @@ -0,0 +1,17 @@ +{ + "version": 1, + "rules": { + "nimbus/frontmatter-shape": "error", + "nimbus/image-ref": [ + "error", + { + "aliases": { + "~/assets/": "src/assets/" + } + } + ], + "nimbus/internal-link": "off" + }, + "collections": {}, + "site": "https://developers.cloudflare.com" +} diff --git a/.prettierignore b/.prettierignore index 19d0667aa0f..09c40cff5d8 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,5 +1,10 @@ dist .astro + +# Nimbus migration target (vendored app code, behind BUILD_TARGET=nimbus). +# Excluded from repo formatting during priming; format/re-enable before cutover. +src/nimbus/ +dist-nimbus/ # fetched at prebuild/predev by bin/fetch-skills.ts .tmp # generated actions JS diff --git a/astro.config.ts b/astro.config.ts index 721a58f543f..ad9fccef18f 100644 --- a/astro.config.ts +++ b/astro.config.ts @@ -96,24 +96,41 @@ const externalLinkPaths = await getExternalLinkPaths("src/content/docs"); const RUN_LINK_CHECK = process.env.RUN_LINK_CHECK?.toLowerCase() === "true" || false; +// Second build target, shared in place. Nimbus reads src/nimbus while +// Starlight stays at src; content/assets stay at src/content / src/assets. +const isNimbus = process.env.BUILD_TARGET === "nimbus"; + +// Nimbus markdown/integrations/vite, loaded only when active so the default +// Starlight build never pulls nimbus-docs or src/nimbus into its graph. +const nimbus = isNimbus ? await import("./src/nimbus/astro-config.ts") : null; + // https://astro.build/config export default defineConfig({ site: "https://developers.cloudflare.com", - cacheDir: ".astro-cache", - markdown: { - gfm: true, - smartypants: false, - remarkPlugins: [remarkValidateImages], - rehypePlugins: [ - rehypeMermaid, - rehypeExternalLinks, - rehypeHeadingSlugs, - rehypeAutolinkHeadings, - // @ts-expect-error plugins types are outdated but functional - rehypeTitleFigure, - rehypeShiftHeadings, - ], - }, + // Separate cache dir so the two targets' content stores never collide. + ...(isNimbus + ? { + srcDir: "./src/nimbus", + outDir: "./dist-nimbus", + cacheDir: ".astro-cache-nimbus", + } + : { cacheDir: ".astro-cache" }), + markdown: nimbus + ? nimbus.markdown + : { + gfm: true, + smartypants: false, + remarkPlugins: [remarkValidateImages], + rehypePlugins: [ + rehypeMermaid, + rehypeExternalLinks, + rehypeHeadingSlugs, + rehypeAutolinkHeadings, + // @ts-expect-error plugins types are outdated but functional + rehypeTitleFigure, + rehypeShiftHeadings, + ], + }, image: { service: { entrypoint: "astro/assets/services/sharp", @@ -128,148 +145,155 @@ export default defineConfig({ server: { port: 1111, }, - integrations: [ - starlight({ - title: "Cloudflare Docs", - logo: { - src: "./src/assets/logo.svg", - }, - favicon: "/favicon.png", - social: [ - { - label: "GitHub", - icon: "github", - href: "https://github.com/cloudflare/cloudflare-docs", - }, - { label: "X.com", icon: "x.com", href: "https://x.com/cloudflare" }, - { - label: "YouTube", - icon: "youtube", - href: "https://www.youtube.com/cloudflare", - }, - ], - editLink: { - baseUrl: - "https://github.com/cloudflare/cloudflare-docs/edit/production/", - }, - components: { - Banner: "./src/components/overrides/Banner.astro", - Footer: "./src/components/overrides/Footer.astro", - Head: "./src/components/overrides/Head.astro", - Header: "./src/components/overrides/Header.astro", - Hero: "./src/components/overrides/Hero.astro", - MarkdownContent: "./src/components/overrides/MarkdownContent.astro", - Sidebar: "./src/components/overrides/Sidebar.astro", - PageTitle: "./src/components/overrides/PageTitle.astro", - SkipLink: "./src/components/overrides/SkipLink.astro", - TableOfContents: "./src/components/overrides/TableOfContents.astro", - }, - sidebar, - customCss, - pagination: false, - plugins: [ - ...(RUN_LINK_CHECK - ? [ - starlightLinksValidator({ - failOnError: false, - errorOnInvalidHashes: false, - errorOnLocalLinks: false, - reporters: { - json: true, - }, - exclude: [ - "/api/", - "/api/**", - "/changelog/**", - "/http/resources/**", - "/llms.txt", - "/llms-full.txt", - "**/llms.txt", - "**/index.md", - "{props.*}", - "/", - "/glossary/", - "/directory/", - "/rules/snippets/examples/?operation=*", - "/rules/transform/examples/?operation=*", - "/ruleset-engine/rules-language/fields/reference/**", - "/workers/examples/?languages=*", - "/workers/llms-full.txt", - "/workers-ai/models/**", - "/markdown.zip", - "/style-guide/index.md", - "/agent-setup/", - "/videos/**", - ], - }), - ] - : []), - starlightDocSearch({ - clientOptionsModule: "./src/plugins/docsearch/index.ts", - }), - starlightImageZoom(), - starlightScrollToTop({ - tooltipText: "Back to top", - showTooltip: true, - svgPath: "M12 6L6 12M12 6L18 12M12 12L6 18M12 12L18 18", - showProgressRing: true, - progressRingColor: "white", - showOnHomepage: false, // Hide on homepage (default) + integrations: nimbus + ? nimbus.integrations + : [ + starlight({ + title: "Cloudflare Docs", + logo: { + src: "./src/assets/logo.svg", + }, + favicon: "/favicon.png", + social: [ + { + label: "GitHub", + icon: "github", + href: "https://github.com/cloudflare/cloudflare-docs", + }, + { label: "X.com", icon: "x.com", href: "https://x.com/cloudflare" }, + { + label: "YouTube", + icon: "youtube", + href: "https://www.youtube.com/cloudflare", + }, + ], + editLink: { + baseUrl: + "https://github.com/cloudflare/cloudflare-docs/edit/production/", + }, + components: { + Banner: "./src/components/overrides/Banner.astro", + Footer: "./src/components/overrides/Footer.astro", + Head: "./src/components/overrides/Head.astro", + Header: "./src/components/overrides/Header.astro", + Hero: "./src/components/overrides/Hero.astro", + MarkdownContent: "./src/components/overrides/MarkdownContent.astro", + Sidebar: "./src/components/overrides/Sidebar.astro", + PageTitle: "./src/components/overrides/PageTitle.astro", + SkipLink: "./src/components/overrides/SkipLink.astro", + TableOfContents: "./src/components/overrides/TableOfContents.astro", + }, + sidebar, + customCss, + pagination: false, + plugins: [ + ...(RUN_LINK_CHECK + ? [ + starlightLinksValidator({ + failOnError: false, + errorOnInvalidHashes: false, + errorOnLocalLinks: false, + reporters: { + json: true, + }, + exclude: [ + "/api/", + "/api/**", + "/changelog/**", + "/http/resources/**", + "/llms.txt", + "/llms-full.txt", + "**/llms.txt", + "**/index.md", + "{props.*}", + "/", + "/glossary/", + "/directory/", + "/rules/snippets/examples/?operation=*", + "/rules/transform/examples/?operation=*", + "/ruleset-engine/rules-language/fields/reference/**", + "/workers/examples/?languages=*", + "/workers/llms-full.txt", + "/workers-ai/models/**", + "/markdown.zip", + "/style-guide/index.md", + "/agent-setup/", + "/videos/**", + ], + }), + ] + : []), + starlightDocSearch({ + clientOptionsModule: "./src/plugins/docsearch/index.ts", + }), + starlightImageZoom(), + starlightScrollToTop({ + tooltipText: "Back to top", + showTooltip: true, + svgPath: "M12 6L6 12M12 6L18 12M12 12L6 18M12 12L18 18", + showProgressRing: true, + progressRingColor: "white", + showOnHomepage: false, // Hide on homepage (default) + }), + ], + lastUpdated: true, + markdown: { + headingLinks: false, + processedDirs: [ + "./src/content/partials/", + "./src/content/changelog/", + ], + }, + disable404Route: true, }), - ], - lastUpdated: true, - markdown: { - headingLinks: false, - processedDirs: ["./src/content/partials/", "./src/content/changelog/"], - }, - disable404Route: true, - }), - icon(), - sitemap({ - filter(page) { - if (page.includes("/style-guide/")) { - return false; - } + icon(), + sitemap({ + filter(page) { + if (page.includes("/style-guide/")) { + return false; + } - if (page.endsWith("/404/")) { - return false; - } + if (page.endsWith("/404/")) { + return false; + } - const pathname = new URL(page).pathname; + const pathname = new URL(page).pathname; - // Exclude external_link pages - if (externalLinkPaths.has(pathname)) { - return false; - } + // Exclude external_link pages + if (externalLinkPaths.has(pathname)) { + return false; + } - // Exclude pages disallowed in robots.txt - if (isDisallowedByRobots(pathname)) { - return false; - } + // Exclude pages disallowed in robots.txt + if (isDisallowedByRobots(pathname)) { + return false; + } - return true; - }, - serialize: createSitemapLastmodSerializer(), - }), - react(), - skills(), - ], - vite: { - resolve: { - alias: { - "./Page.astro": fileURLToPath( - new URL("./src/components/overrides/Page.astro", import.meta.url), - ), - "../components/Page.astro": fileURLToPath( - new URL("./src/components/overrides/Page.astro", import.meta.url), - ), - "./SidebarSublist.astro": fileURLToPath( - new URL( - "./src/components/overrides/SidebarSublist.astro", - import.meta.url, - ), - ), + return true; + }, + serialize: createSitemapLastmodSerializer(), + }), + react(), + skills(), + ], + vite: nimbus + ? nimbus.vite + : { + resolve: { + alias: { + "./Page.astro": fileURLToPath( + new URL("./src/components/overrides/Page.astro", import.meta.url), + ), + "../components/Page.astro": fileURLToPath( + new URL("./src/components/overrides/Page.astro", import.meta.url), + ), + "./SidebarSublist.astro": fileURLToPath( + new URL( + "./src/components/overrides/SidebarSublist.astro", + import.meta.url, + ), + ), + }, + }, }, - }, - }, }); diff --git a/eslint.config.js b/eslint.config.js index 80242ad09a6..554d74d075e 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -33,7 +33,11 @@ export default [ ".flue/.flue-vite/", ".flue/.wrangler/", "dist/", + "dist-nimbus/", ".github/", + // Nimbus migration target (vendored, behind BUILD_TARGET=nimbus). + // Excluded from repo lint during priming; re-enable before cutover. + "src/nimbus/", ], }, { diff --git a/package.json b/package.json index 64c42f90704..c08e5ec7f62 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,12 @@ "@expressive-code/plugin-collapsible-sections": "0.43.1", "@expressive-code/plugin-line-numbers": "0.43.1", "@floating-ui/react": "0.27.19", + "@fontsource-variable/inter": "5.2.8", + "@fontsource-variable/jetbrains-mono": "5.2.8", "@iarna/toml": "2.2.5", + "@iconify-json/ph": "1.2.2", + "@iconify-json/simple-icons": "1.2.86", + "@iconify-json/vscode-icons": "1.2.56", "@iconify/utils": "3.1.3", "@marsidev/react-turnstile": "1.5.3", "@nanostores/react": "1.1.0", @@ -85,6 +90,7 @@ "astro-icon": "1.1.5", "astro-skills": "0.1.0", "cidr-tools": "12.0.3", + "clsx": "2.1.1", "codeowners-utils": "1.0.2", "date-fns": "4.4.0", "dedent": "1.7.2", @@ -117,6 +123,7 @@ "mermaid": "11.15.0", "micromark-extension-mdxjs": "3.0.0", "nanostores": "1.3.0", + "nimbus-docs": "0.1.15", "node-html-parser": "7.1.0", "openapi-types": "12.1.3", "parse-duration": "2.1.6", @@ -141,6 +148,7 @@ "remark": "15.0.1", "remark-gfm": "4.0.1", "remark-stringify": "11.0.0", + "satteri": "0.6.3", "sharp": "0.35.1", "solarflare-theme": "0.0.6", "space-separated-tokens": "2.0.2", @@ -151,6 +159,7 @@ "starlight-showcases": "0.3.2", "strip-markdown": "6.0.0", "svgo": "4.0.1", + "tailwind-merge": "3.6.0", "tailwindcss": "4.1.4", "tippy.js": "6.3.7", "ts-blank-space": "0.9.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 7b1d080e2bd..c5a48b7a33e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,9 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +overrides: + nimbus-docs: link:/Users/mhassan/Documents/dev/nimbus/monorepo/packages/nimbus-docs + importers: .: @@ -46,7 +49,7 @@ importers: version: 5.0.0(@astrojs/starlight@0.40.0(astro@6.4.7(@types/node@25.9.3)(jiti@2.7.0)(lightningcss@1.32.0)(rollup@4.62.0)(tsx@4.22.4)(yaml@2.9.0))(typescript@5.9.3))(tailwindcss@4.1.4) '@base-ui/react': specifier: 1.5.0 - version: 1.5.0(@types/react@19.0.7)(date-fns@4.4.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + version: 1.5.0(@date-fns/tz@1.5.0)(@types/react@19.0.7)(date-fns@4.4.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) '@cloudflare/vitest-pool-workers': specifier: 0.16.15 version: 0.16.15(@cloudflare/workers-types@4.20260615.1)(@vitest/runner@4.1.9)(@vitest/snapshot@4.1.9)(vitest@4.1.9(@types/node@25.9.3)(happy-dom@20.10.3)(vite@7.3.5(@types/node@25.9.3)(jiti@2.7.0)(lightningcss@1.32.0)(tsx@4.22.4)(yaml@2.9.0))) @@ -68,9 +71,24 @@ importers: '@floating-ui/react': specifier: 0.27.19 version: 0.27.19(react-dom@19.0.0(react@19.0.0))(react@19.0.0) + '@fontsource-variable/inter': + specifier: 5.2.8 + version: 5.2.8 + '@fontsource-variable/jetbrains-mono': + specifier: 5.2.8 + version: 5.2.8 '@iarna/toml': specifier: 2.2.5 version: 2.2.5 + '@iconify-json/ph': + specifier: 1.2.2 + version: 1.2.2 + '@iconify-json/simple-icons': + specifier: 1.2.86 + version: 1.2.86 + '@iconify-json/vscode-icons': + specifier: 1.2.56 + version: 1.2.56 '@iconify/utils': specifier: 3.1.3 version: 3.1.3 @@ -149,6 +167,9 @@ importers: cidr-tools: specifier: 12.0.3 version: 12.0.3 + clsx: + specifier: 2.1.1 + version: 2.1.1 codeowners-utils: specifier: 1.0.2 version: 1.0.2 @@ -245,6 +266,9 @@ importers: nanostores: specifier: 1.3.0 version: 1.3.0 + nimbus-docs: + specifier: link:/Users/mhassan/Documents/dev/nimbus/monorepo/packages/nimbus-docs + version: link:../nimbus/monorepo/packages/nimbus-docs node-html-parser: specifier: 7.1.0 version: 7.1.0 @@ -317,6 +341,9 @@ importers: remark-stringify: specifier: 11.0.0 version: 11.0.0 + satteri: + specifier: 0.6.3 + version: 0.6.3 sharp: specifier: 0.35.1 version: 0.35.1 @@ -347,6 +374,9 @@ importers: svgo: specifier: 4.0.1 version: 4.0.1 + tailwind-merge: + specifier: 3.6.0 + version: 3.6.0 tailwindcss: specifier: 4.1.4 version: 4.1.4 @@ -739,6 +769,32 @@ packages: '@braintree/sanitize-url@7.1.2': resolution: {integrity: sha512-jigsZK+sMF/cuiB7sERuo9V7N9jx+dhmHHnQyDSVdpZwVutaBu7WvNYqMDLSgFgfB30n452TP3vjDAvFC973mA==} + '@bruits/satteri-darwin-arm64@0.6.3': + resolution: {integrity: sha512-oKgMfpmNzQ8vaqmkE37PBu8tOyVjoOc4s+DV2tLpWvO6WO467qn/+Nbcirm/ceer7wUM8v4vMLGcZO0gkRzBEg==} + cpu: [arm64] + os: [darwin] + + '@bruits/satteri-darwin-x64@0.6.3': + resolution: {integrity: sha512-9I5pbwZRWH5LvhoCtwpRr4rYSDe43/dLvps6zO70ipVF2XbH4rJ20T+EfvPcmou5jsWMsq9Ybn5GX3PwlSrBaw==} + cpu: [x64] + os: [darwin] + + '@bruits/satteri-linux-x64-gnu@0.6.3': + resolution: {integrity: sha512-aFfw2DL2HpIcAQ8I3ZEtKuz+/GoF0H0sq387jAlvr00Q7buiiFbvARFuQlvTk00N7u3SJIh/3+YkKssTJDT+yQ==} + cpu: [x64] + os: [linux] + libc: [glibc] + + '@bruits/satteri-wasm32-wasi@0.6.3': + resolution: {integrity: sha512-DdpfnJ+04Mb4YtHaxAeETUvhdxFKg3URnroGY39FvweJEgeXx8cFNutuF5w904BhqaiblhmF76AoBnJwNLxsXg==} + engines: {node: '>=14.0.0'} + cpu: [wasm32] + + '@bruits/satteri-win32-x64-msvc@0.6.3': + resolution: {integrity: sha512-J/CZqACnBbv77eImx/JeO5RmCuCyliihiC81u3M4VobA8eupsygaPen3/UFFqf3yfeHvMlE3myilouh/2iHMOA==} + cpu: [x64] + os: [win32] + '@capsizecss/unpack@4.0.1': resolution: {integrity: sha512-CuNiSqg7+e1cO/GjffyMOm5Tt2jUF9CWHHnvQ/UkqvtkGfHdgwEC0wpmq7fkN3gxwpRnrAN0WzO3vREKmNolMQ==} engines: {node: '>=18'} @@ -755,11 +811,11 @@ packages: engines: {node: '>= 20.12.0'} '@cloudflare/kv-asset-handler@0.5.0': - resolution: {integrity: sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==, tarball: https://registry.npmjs.org/@cloudflare/kv-asset-handler/-/kv-asset-handler-0.5.0.tgz} + resolution: {integrity: sha512-jxQYkj8dSIzc0cD6cMMNdOc1UVjqSqu8BZdor5s8cGjW2I8BjODt/kWPVdY+u9zj3ms75Q5qaZgnxUad83+eAg==} engines: {node: '>=22.0.0'} '@cloudflare/unenv-preset@2.16.1': - resolution: {integrity: sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==, tarball: https://registry.npmjs.org/@cloudflare/unenv-preset/-/unenv-preset-2.16.1.tgz} + resolution: {integrity: sha512-ECxObrMfyTl5bhQf/lZCXwo5G6xX9IAUo+nDMKK4SZ8m4Jvvxp52vilxyySSWh2YTZz8+HQ07qGH/2rEom1vDw==} peerDependencies: unenv: 2.0.0-rc.24 workerd: '>1.20260305.0 <2.0.0-0' @@ -768,44 +824,44 @@ packages: optional: true '@cloudflare/vitest-pool-workers@0.16.15': - resolution: {integrity: sha512-R0kZhIm4uSxOeTWPHY9xYIFPGRBEHPzl/n9BbHZSY/gk0n16uDU7T1JZe372oTF+diXG1uVBWqiiRc7Hxstdow==, tarball: https://registry.npmjs.org/@cloudflare/vitest-pool-workers/-/vitest-pool-workers-0.16.15.tgz} + resolution: {integrity: sha512-R0kZhIm4uSxOeTWPHY9xYIFPGRBEHPzl/n9BbHZSY/gk0n16uDU7T1JZe372oTF+diXG1uVBWqiiRc7Hxstdow==} peerDependencies: '@vitest/runner': ^4.1.0 '@vitest/snapshot': ^4.1.0 vitest: ^4.1.0 '@cloudflare/workerd-darwin-64@1.20260611.1': - resolution: {integrity: sha512-iJICldmi4sBGgi7IrQles8cStOGXM/Tmv95C4OODVs6VIbMsJPqThUM5h3uYVQNULuJ8I/aVvnJ3Eh/wZCKwuA==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260611.1.tgz} + resolution: {integrity: sha512-iJICldmi4sBGgi7IrQles8cStOGXM/Tmv95C4OODVs6VIbMsJPqThUM5h3uYVQNULuJ8I/aVvnJ3Eh/wZCKwuA==} engines: {node: '>=16'} cpu: [x64] os: [darwin] '@cloudflare/workerd-darwin-arm64@1.20260611.1': - resolution: {integrity: sha512-yBbVXvbZyltR3I7NJdC4C4ItkItjZSiabcA/3HzEWOUQjLVKFqRh4so6ToHr70VCYh8VGeR8EDZL23igLhXqFQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260611.1.tgz} + resolution: {integrity: sha512-yBbVXvbZyltR3I7NJdC4C4ItkItjZSiabcA/3HzEWOUQjLVKFqRh4so6ToHr70VCYh8VGeR8EDZL23igLhXqFQ==} engines: {node: '>=16'} cpu: [arm64] os: [darwin] '@cloudflare/workerd-linux-64@1.20260611.1': - resolution: {integrity: sha512-PfNjpxOlaIgZFYuhD7+neEEewCN2Ud993wEEN0fmbtSOax1AK53LGqmXUDvFhnbkHxJLFAxYCSNISW8QbzaAIg==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260611.1.tgz} + resolution: {integrity: sha512-PfNjpxOlaIgZFYuhD7+neEEewCN2Ud993wEEN0fmbtSOax1AK53LGqmXUDvFhnbkHxJLFAxYCSNISW8QbzaAIg==} engines: {node: '>=16'} cpu: [x64] os: [linux] '@cloudflare/workerd-linux-arm64@1.20260611.1': - resolution: {integrity: sha512-GEp4XbuIKjlF8pakqXcUDJfKiJosD/Q7S83J0d+r+z9XIlYGfF3ntm08e2aiF5TFTwp3fnG4yMoPUAKNhNJpvQ==, tarball: https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260611.1.tgz} + resolution: {integrity: sha512-GEp4XbuIKjlF8pakqXcUDJfKiJosD/Q7S83J0d+r+z9XIlYGfF3ntm08e2aiF5TFTwp3fnG4yMoPUAKNhNJpvQ==} engines: {node: '>=16'} cpu: [arm64] os: [linux] '@cloudflare/workerd-windows-64@1.20260611.1': - resolution: {integrity: sha512-S6JkS0kEbcCKs19RGqEPhjCRbP8GBkQwqYLp2fhBJtD/KTlwqLzOJ9E6PQ7gQKgWHtxy1NBG3oXarlNFRNU/dw==, tarball: https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260611.1.tgz} + resolution: {integrity: sha512-S6JkS0kEbcCKs19RGqEPhjCRbP8GBkQwqYLp2fhBJtD/KTlwqLzOJ9E6PQ7gQKgWHtxy1NBG3oXarlNFRNU/dw==} engines: {node: '>=16'} cpu: [x64] os: [win32] '@cloudflare/workers-types@4.20260615.1': - resolution: {integrity: sha512-fGOiTwoLj/8bU8mj3VAfa1EULx4ceZhDwnjvY+afDBlSXI9pvY7PE9t62rGEhJjbAOGd7i5WUDun0eZCWBDrzg==, tarball: https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260615.1.tgz} + resolution: {integrity: sha512-fGOiTwoLj/8bU8mj3VAfa1EULx4ceZhDwnjvY+afDBlSXI9pvY7PE9t62rGEhJjbAOGd7i5WUDun0eZCWBDrzg==} '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} @@ -815,6 +871,9 @@ packages: resolution: {integrity: sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==} engines: {node: '>=14'} + '@date-fns/tz@1.5.0': + resolution: {integrity: sha512-lwYN/vDPeNRULcepoE/LO2Pgx+7/RV+S9ARfbc9lr2DtGkOD7pAiruHvbR1RX3Qyf6ja47EWJDMsNK5vK08DJg==} + '@docsearch/css@3.9.0': resolution: {integrity: sha512-cQbnVbq0rrBwNAKegIac/t6a8nWoUAn8frnkLFW6YARaRmAQr5/Eoe6Ln2fqkUCZ40KpdrKbpSAmgrkviOxuWA==} @@ -859,9 +918,18 @@ packages: '@emmetio/stream-reader@2.2.0': resolution: {integrity: sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==} + '@emnapi/core@1.9.1': + resolution: {integrity: sha512-mukuNALVsoix/w1BJwFzwXBN/dHeejQtuVzcDsfOEsdpCumXb/E9j8w11h5S54tT1xhifGfbbSm/ICrObRb3KA==} + '@emnapi/runtime@1.11.1': resolution: {integrity: sha512-vgj7R3y3Wgx24IQaGPA/R6YFXLHVMOZ0uVEyIQPaWs+rd1AzfEMXlAC22FYwO1XkKR6NPsq7mUandH8oIRdZFw==} + '@emnapi/runtime@1.9.1': + resolution: {integrity: sha512-VYi5+ZVLhpgK4hQ0TAjiQiZ6ol0oe4mBx7mVv7IflsiEp0OWoVsp/+f9Vc1hOhE0TtkORVrI1GvzyreqpgWtkA==} + + '@emnapi/wasi-threads@1.2.0': + resolution: {integrity: sha512-N10dEJNSsUx41Z6pZsXU8FjPjpBEplgH24sfkmITrBED1/U2Esum9F3lfLrMjKHHjmi557zQn7kR9R+XWXu5Rg==} + '@emotion/babel-plugin@11.13.5': resolution: {integrity: sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==} @@ -1464,6 +1532,12 @@ packages: '@floating-ui/utils@0.2.11': resolution: {integrity: sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==} + '@fontsource-variable/inter@5.2.8': + resolution: {integrity: sha512-kOfP2D+ykbcX/P3IFnokOhVRNoTozo5/JxhAIVYLpea/UBmCQ/YWPBfWIDuBImXX/15KH+eKh4xpEUyS2sQQGQ==} + + '@fontsource-variable/jetbrains-mono@5.2.8': + resolution: {integrity: sha512-WBA9elru6Jdp5df2mES55wuOO0WIrn3kpXnI4+W2ek5u3ZgLS9XS4gmIlcQhiZOWEKl95meYdvK7xI+ETLCq/Q==} + '@humanfs/core@0.19.2': resolution: {integrity: sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==} engines: {node: '>=18.18.0'} @@ -1487,6 +1561,15 @@ packages: '@iarna/toml@2.2.5': resolution: {integrity: sha512-trnsAYxU3xnS1gPHPyU961coFyLkh4gAD/0zQ5mymY4yOZ+CYvsPqUbOFSw0aDM4y0tV7tiFxL/1XfXPNC6IPg==} + '@iconify-json/ph@1.2.2': + resolution: {integrity: sha512-PgkEZNtqa8hBGjHXQa4pMwZa93hmfu8FUSjs/nv4oUU6yLsgv+gh9nu28Kqi8Fz9CCVu4hj1MZs9/60J57IzFw==} + + '@iconify-json/simple-icons@1.2.86': + resolution: {integrity: sha512-t3jck5qPQuK1qy+bRn9eCoDQhIB7XSazKz1Fjp8hcan3XOAsTI5Mq/s3F0ekOKSvMQqkVORYK6ns6o6T9f5EMA==} + + '@iconify-json/vscode-icons@1.2.56': + resolution: {integrity: sha512-AZYFHK0IuynkOwO4h22IGZQ4+2/dHAZocUHSO9rPGwU6MrZtzAyb6atdO6iEocHOcB5PQdG7xmCkRCYsGTo3iQ==} + '@iconify/tools@4.2.0': resolution: {integrity: sha512-WRxPva/ipxYkqZd1+CkEAQmd86dQmrwH0vwK89gmp2Kh2WyyVw57XbPng0NehP3x4V1LzLsXUneP1uMfTMZmUA==} @@ -1874,6 +1957,12 @@ packages: nanostores: ^1.2.0 react: '>=18.0.0' + '@napi-rs/wasm-runtime@1.1.6': + resolution: {integrity: sha512-ZLv/JdUfkvOy9eCnnBaGfiO+XimbjebAeO+MRQqD/B+FR1tnRN0tpKSJHRbE8sFfS6aqsXZ67TQjfwfsxULVbg==} + peerDependencies: + '@emnapi/core': ^1.7.1 + '@emnapi/runtime': ^1.7.1 + '@nodable/entities@2.2.0': resolution: {integrity: sha512-9uGyhaQavEUMC8AIddIjau4NsnsXhou+j5sBAGojCM1oxmQpVKTWR/9JxABD6UAv12vpIms55fPZKFQEhG6uBg==} @@ -2343,6 +2432,9 @@ packages: '@tokenizer/token@0.3.0': resolution: {integrity: sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==} + '@tybys/wasm-util@0.10.3': + resolution: {integrity: sha512-F3fo1MYrRJYL3zER0OUOmkutjr1Vp23m7OsSgp7nq4SP6OqX6C/56XFIPAl5bt3zaBRjmW7SGz3u/6LwFpYcOg==} + '@types/aria-query@5.0.4': resolution: {integrity: sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==} @@ -5560,6 +5652,9 @@ packages: sass-formatter@0.7.9: resolution: {integrity: sha512-CWZ8XiSim+fJVG0cFLStwDvft1VI7uvXdCNJYXhDvowiv+DsbD1nXLiQ4zrE5UBvj5DWZJ93cwN0NX5PMsr1Pw==} + satteri@0.6.3: + resolution: {integrity: sha512-iY5xd2tBDQveYRFkL1F0cegkabWSVoXHi64e1p49SiCs1bZDaqTQPGQI+PqEQIaWkz0iqK80CuQQUYvhsssviw==} + sax@1.6.0: resolution: {integrity: sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==} engines: {node: '>=11.0.0'} @@ -5870,6 +5965,9 @@ packages: tabbable@6.4.0: resolution: {integrity: sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg==} + tailwind-merge@3.6.0: + resolution: {integrity: sha512-uxL7qAVQriqRQPAyK3pj66VqskWqoZ37PW94jwOTwNfq/z9oyu1V+eqrZqtR2+fCiXdYOZe/Modt8GtvqNzu+w==} + tailwindcss@4.1.4: resolution: {integrity: sha512-1ZIUqtPITFbv/DxRmDr5/agPqJwF69d24m9qmM1939TJehgY539CtzeZRjbLt5G6fSy/7YqqYsfvoTEw9xUI2A==} @@ -7136,7 +7234,7 @@ snapshots: '@babel/helper-string-parser': 7.29.7 '@babel/helper-validator-identifier': 7.29.7 - '@base-ui/react@1.5.0(@types/react@19.0.7)(date-fns@4.4.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + '@base-ui/react@1.5.0(@date-fns/tz@1.5.0)(@types/react@19.0.7)(date-fns@4.4.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@babel/runtime': 7.29.7 '@base-ui/utils': 0.2.9(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -7146,6 +7244,7 @@ snapshots: react-dom: 19.0.0(react@19.0.0) use-sync-external-store: 1.6.0(react@19.0.0) optionalDependencies: + '@date-fns/tz': 1.5.0 '@types/react': 19.0.7 date-fns: 4.4.0 @@ -7164,6 +7263,25 @@ snapshots: '@braintree/sanitize-url@7.1.2': {} + '@bruits/satteri-darwin-arm64@0.6.3': + optional: true + + '@bruits/satteri-darwin-x64@0.6.3': + optional: true + + '@bruits/satteri-linux-x64-gnu@0.6.3': + optional: true + + '@bruits/satteri-wasm32-wasi@0.6.3': + dependencies: + '@emnapi/core': 1.9.1 + '@emnapi/runtime': 1.9.1 + '@napi-rs/wasm-runtime': 1.1.6(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1) + optional: true + + '@bruits/satteri-win32-x64-msvc@0.6.3': + optional: true + '@capsizecss/unpack@4.0.1': dependencies: fontkitten: 1.0.3 @@ -7228,6 +7346,9 @@ snapshots: '@ctrl/tinycolor@4.2.0': {} + '@date-fns/tz@1.5.0': + optional: true + '@docsearch/css@3.9.0': {} '@docsearch/js@3.9.0(@algolia/client-search@5.54.1)(@types/react@19.0.7)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)(search-insights@2.17.3)': @@ -7278,11 +7399,27 @@ snapshots: '@emmetio/stream-reader@2.2.0': {} + '@emnapi/core@1.9.1': + dependencies: + '@emnapi/wasi-threads': 1.2.0 + tslib: 2.8.1 + optional: true + '@emnapi/runtime@1.11.1': dependencies: tslib: 2.8.1 optional: true + '@emnapi/runtime@1.9.1': + dependencies: + tslib: 2.8.1 + optional: true + + '@emnapi/wasi-threads@1.2.0': + dependencies: + tslib: 2.8.1 + optional: true + '@emotion/babel-plugin@11.13.5': dependencies: '@babel/helper-module-imports': 7.29.7 @@ -7691,6 +7828,10 @@ snapshots: '@floating-ui/utils@0.2.11': {} + '@fontsource-variable/inter@5.2.8': {} + + '@fontsource-variable/jetbrains-mono@5.2.8': {} + '@humanfs/core@0.19.2': dependencies: '@humanfs/types': 0.15.0 @@ -7709,6 +7850,18 @@ snapshots: '@iarna/toml@2.2.5': {} + '@iconify-json/ph@1.2.2': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify-json/simple-icons@1.2.86': + dependencies: + '@iconify/types': 2.0.0 + + '@iconify-json/vscode-icons@1.2.56': + dependencies: + '@iconify/types': 2.0.0 + '@iconify/tools@4.2.0': dependencies: '@iconify/types': 2.0.0 @@ -8042,6 +8195,13 @@ snapshots: nanostores: 1.3.0 react: 19.0.0 + '@napi-rs/wasm-runtime@1.1.6(@emnapi/core@1.9.1)(@emnapi/runtime@1.9.1)': + dependencies: + '@emnapi/core': 1.9.1 + '@emnapi/runtime': 1.9.1 + '@tybys/wasm-util': 0.10.3 + optional: true + '@nodable/entities@2.2.0': {} '@nodelib/fs.scandir@2.1.5': @@ -8458,6 +8618,11 @@ snapshots: '@tokenizer/token@0.3.0': {} + '@tybys/wasm-util@0.10.3': + dependencies: + tslib: 2.8.1 + optional: true + '@types/aria-query@5.0.4': {} '@types/babel__core@7.20.5': @@ -12689,6 +12854,19 @@ snapshots: dependencies: suf-log: 2.5.3 + satteri@0.6.3: + dependencies: + '@types/estree-jsx': 1.0.5 + '@types/hast': 3.0.4 + '@types/mdast': 4.0.4 + '@types/unist': 3.0.3 + optionalDependencies: + '@bruits/satteri-darwin-arm64': 0.6.3 + '@bruits/satteri-darwin-x64': 0.6.3 + '@bruits/satteri-linux-x64-gnu': 0.6.3 + '@bruits/satteri-wasm32-wasi': 0.6.3 + '@bruits/satteri-win32-x64-msvc': 0.6.3 + sax@1.6.0: {} scheduler@0.25.0: {} @@ -13107,6 +13285,8 @@ snapshots: tabbable@6.4.0: {} + tailwind-merge@3.6.0: {} + tailwindcss@4.1.4: {} tailwindcss@4.3.1: {} diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index ddb3e37e077..efb7cd3f2a8 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -1,7 +1,32 @@ +# ⚠️ LOCAL DEV LINK — DO NOT COMMIT. Points nimbus-docs at the in-progress local +# checkout so migration bugs can be found/fixed incrementally without a publish +# per fix. Remove this block (revert to the published version) before the +# consolidated release / cutover. Valid for `astro sync` + build-time work; +# switch back to a published version for the full render build (peer resolution). +overrides: + nimbus-docs: "link:/Users/mhassan/Documents/dev/nimbus/monorepo/packages/nimbus-docs" + # Minimum age (in minutes) a package version must be published before pnpm will install it. # 1440 minutes = 24 hours. Reduces risk from newly-published compromised packages. minimumReleaseAge: 1440 +# First-party package published as part of the Nimbus migration; exempt from the +# age guard so freshly-cut versions install without a 24h wait. +minimumReleaseAgeExclude: + - nimbus-docs + +# @astrojs/mdx's @astrojs/markdown-satteri peer is optional and only engages when +# markdown.processor is Sätteri (the Nimbus target, via nimbus-docs's pinned mdx +# 6.0.1 + markdown-satteri 0.2.1). nimbus-docs pulls 0.2.1 into the tree, and pnpm +# satisfies every mdx's optional peer from it — including Starlight's mdx 6.0.3, +# which prefers 0.3.0 but never loads the Sätteri bridge (verified inert). The +# wiring is identical with or without this rule; it only silences the cosmetic +# version-mismatch warning. Pulling markdown-satteri 0.3.x instead would drag in +# an unused satteri 0.9 major, so accept 0.2.1 for the peer everywhere. +peerDependencyRules: + allowedVersions: + "@astrojs/mdx>@astrojs/markdown-satteri": "0.2.1" + # Prevent transitive dependencies from using exotic sources (git repos, direct tarball URLs). # Only direct dependencies may use exotic sources. blockExoticSubdeps: true diff --git a/src/content/changelog/waf/2026-05-04-waf-release.mdx b/src/content/changelog/waf/2026-05-04-waf-release.mdx index 1d27b8dbad9..58a075d12fa 100644 --- a/src/content/changelog/waf/2026-05-04-waf-release.mdx +++ b/src/content/changelog/waf/2026-05-04-waf-release.mdx @@ -3,21 +3,21 @@ title: "WAF Release - 2026-05-04" description: Cloudflare WAF managed rulesets 2026-05-04 release date: 2026-05-04 --- - + import { RuleID } from "~/components"; - + This week's release focuses on new detections to expand coverage across command injection, SQL injection, PHP object injection, remote code execution, and XSS attack vectors. - + **Key Findings** - + - Existing rule enhancements have been deployed to improve detection resilience against broad classes of web attacks and strengthen behavioral coverage. - - + + **Continuous Rule Improvements** - + We are continuously refining our managed rules to provide more resilient protection and deeper insights into attack patterns. To ensure an optimal security posture, we recommend consistently monitoring the Security Events dashboard and adjusting rule actions as these enhancements are deployed. - - + + diff --git a/src/nimbus/README.md b/src/nimbus/README.md new file mode 100644 index 00000000000..a50d8aca137 --- /dev/null +++ b/src/nimbus/README.md @@ -0,0 +1,42 @@ +# `src/nimbus` — the Nimbus build target + +This directory is the **Nimbus** documentation app. It is built only when +`BUILD_TARGET=nimbus` (Astro `srcDir: src/nimbus` → `dist-nimbus/`); the default +build is Starlight at `srcDir: src` → `dist/`. The two never share a `src/pages` +or component graph. See `astro.config.ts` and `src/nimbus/astro-config.ts`. + +## What lives here vs. what is shared in place + +**Only app code lives here** — components, layouts, routes, schemas, util, the +`components.ts` MDX barrel, and the rehype/Sätteri pipeline. + +**Content and assets are NOT copied here — they are shared in place** from the +project root and read by both build targets: + +| Shared resource | Root location | How Nimbus reads it | +| --- | --- | --- | +| Content (MDX, data collections) | `src/content` | collection `base` is project-root-relative; `~/content` alias for direct imports | +| Images / assets | `src/assets` | `~/assets` alias → root `src/assets` | +| Local icons | `src/icons` | `astro-icon` resolves `iconDir` against the project root for both targets | + +**Do not add content, assets, or icons under `src/nimbus`.** If a component needs +shared content data, import it via `~/content/…` (not a copy). + +## Why `components/cf/*` looks like `src/components/*` + +The `cf/` components are **ports** of the root (Starlight) `src/components/*`, +not duplicates: same rendered output, different rendering stack (Nimbus +primitives + `nimbus-docs` instead of Starlight internals). Both component +graphs coexist **by design** during priming — that is the cost of a big-bang +cutover, and it collapses to one set at cleanup (Epic H1: delete the Starlight +`src/*` bits, promote `src/nimbus` → `src`). + +## Drift to watch (Epic F3) + +A few app files here are currently byte-identical to their root counterparts +because they needed no stack adaptation (the architecture diagrams, plus +`util/warp-platforms.json`, `util/content-type.ts`, `schemas/compatibility-flags.ts`). +They are separate files in separate graphs, so a root-side edit during priming +will **not** propagate automatically. The re-baseline/drift protocol (F3) tracks +these. Note `util/warp-platforms.json` and the `compatibility-flags` schema/route +are content-derived/generated — regenerate, don't hand-edit. diff --git a/src/nimbus/astro-config.ts b/src/nimbus/astro-config.ts new file mode 100644 index 00000000000..22224b6353c --- /dev/null +++ b/src/nimbus/astro-config.ts @@ -0,0 +1,199 @@ +import { resolve } from "node:path"; +import { fileURLToPath } from "node:url"; +import react from "@astrojs/react"; +import icon from "astro-icon"; +import nimbus, { defineConfig as defineNimbusConfig } from "nimbus-docs"; +import { rehypePlugins } from "./plugins/rehype"; + +// Resolved against this file (src/nimbus/). `~` → src/nimbus, `~/assets` → +// the shared root src/assets, partials → the shared root src/content/partials. +const here = (p: string) => + fileURLToPath(new URL(p, import.meta.url)).replace(/\/$/, ""); +const partialsRoot = here("../content/partials"); + +const nimbusConfig = defineNimbusConfig({ + site: "https://developers.cloudflare.com", + title: "Cloudflare Docs", + description: "Cloudflare's documentation.", + locale: "en", + github: "https://github.com/cloudflare/cloudflare-docs", + socialImageAlt: "Cloudflare documentation", + // Search is Algolia DocSearch (wired in E4); Pagefind off. + search: false, + sidebar: { + items: [ + { label: "Agents", items: [{ autogenerate: { directory: "agents" } }] }, + { label: "Queues", items: [{ autogenerate: { directory: "queues" } }] }, + { label: "KV", items: [{ autogenerate: { directory: "kv" } }] }, + { + label: "Workflows", + items: [{ autogenerate: { directory: "workflows" } }], + }, + { + label: "Workers AI", + items: [{ autogenerate: { directory: "workers-ai" } }], + }, + { + label: "AI", + segment: "/ai", + items: [ + { label: "Overview", link: "/ai/" }, + { label: "Models", link: "/ai/models/" }, + ], + }, + { + label: "Learning paths", + items: [{ autogenerate: { directory: "learning-paths" } }], + }, + ], + overviewLabel: "Overview", + scope: "section", + isolate: { boundaries: ["learning-paths/*"] }, + defaultCollapsed: true, + }, +}); + +// Maps Starlight icon names used in shared content to the iconify sets we ship, +// without touching content on disk: a pre-stage, MDX-scoped string rewrite. +const iconAlias = { + name: "cf-nimbus:icon-alias", + enforce: "pre" as const, + transform(code: string, id: string) { + const [pathOnly] = id.split("?", 1); + if (!pathOnly?.endsWith(".mdx") && !pathOnly?.endsWith(".md")) return null; + if (!/icon\s*=/.test(code)) return null; + + const SETI: Record = { + javascript: "vscode-icons:file-type-js-official", + typescript: "vscode-icons:file-type-typescript-official", + python: "vscode-icons:file-type-python", + shell: "vscode-icons:file-type-shell", + }; + const BARE: Record = { + document: "ph:file-text", + "open-book": "ph:book-open", + pen: "ph:pencil-simple", + discord: "simple-icons:discord", + "x.com": "simple-icons:x", + }; + + let out = code; + out = out.replace(/(["'])seti:([a-z0-9_-]+)\1/gi, (match, q, name) => { + const mapped = SETI[name.toLowerCase()]; + return mapped ? `${q}${mapped}${q}` : match; + }); + out = out.replace( + /\bicon\s*=\s*(["'])([a-z0-9_.-]+)\1/gi, + (match, q, name) => { + if (name.includes(":")) return match; + const mapped = BARE[name.toLowerCase()]; + return mapped ? `icon=${q}${mapped}${q}` : match; + }, + ); + return out === code ? null : { code: out, map: null }; + }, +}; + +// The Nimbus target's markdown / integrations / vite, branched into +// astro.config.ts when BUILD_TARGET=nimbus. +export const markdown = { + syntaxHighlight: { + type: "shiki" as const, + excludeLangs: ["math", "mermaid"], + }, + smartypants: false, +}; + +export const integrations = [ + icon(), + react(), + nimbus(nimbusConfig, { + markdown: { hastPlugins: rehypePlugins }, + incrementalBuilds: false, + // MDX validation gated until the component barrel covers the full tree (C2). + validateMdx: false, + partialResolver: (name: string, props: Record) => { + if (name !== "Render" || !props.file) return null; + const path = props.product + ? `${props.product}/${props.file}.mdx` + : `${props.file}.mdx`; + return resolve(partialsRoot, path); + }, + rules: { + "nimbus/frontmatter-shape": "error", + "nimbus/image-ref": [ + "error", + { aliases: { "~/assets/": "src/assets/" } }, + ], + "nimbus/internal-link": "off", + }, + }), +]; + +// Make the Nimbus app aliases authoritatively beat Astro's tsconfig-derived +// `~` (the root `~/*`→`src/*` the Starlight target needs). +// +// Astro injects the root tsconfig paths into `vite.resolve.alias` via the +// `astro:tsconfig-alias` plugin's `config()` hook, where the per-entry +// customResolver returns the ROOT file whenever `src/` exists on disk. +// Vite's built-in `vite:alias` plugin (resolve.alias) runs BEFORE user +// `enforce:"pre"` plugins, so a `resolveId` override can never win where the +// root file exists (e.g. `~/components/changelog/Header.astro`). +// +// Fix: contribute our OWN `resolve.alias` entries from a `config` hook with +// `order: "post"`. Vite's `mergeAlias` PREPENDS each later config's aliases +// (`[...newer, ...older]`), and config hooks ordered "post" run after +// `astro:tsconfig-alias`'s (unordered) hook — so our entries land FIRST in +// the final alias array and the built-in alias plugin matches them first. +// `~/assets` and `~/content` precede `~` so the shared root tree still wins. +// +// This only applies to the Nimbus target (this config is loaded solely when +// BUILD_TARGET=nimbus); the default Starlight build is untouched and keeps +// `~`→src via its own tsconfig alias. +const nimbusDir = here("."); +const rootAssets = here("../assets"); +const rootContent = here("../content"); + +const aliasResolver = { + name: "cf-nimbus:alias", + enforce: "pre" as const, + config: { + order: "post" as const, + handler() { + return { + resolve: { + alias: [ + { find: /^~\/assets(\/.*)?$/, replacement: `${rootAssets}$1` }, + { find: /^~\/content(\/.*)?$/, replacement: `${rootContent}$1` }, + { find: /^~(\/.*)?$/, replacement: `${nimbusDir}$1` }, + { find: /^@(\/.*)?$/, replacement: `${nimbusDir}$1` }, + ], + }, + }; + }, + }, + // Defense-in-depth fallback for any context the alias array doesn't cover. + async resolveId( + this: { resolve: (s: string, i?: string, o?: object) => Promise<{ id: string } | null> }, + source: string, + importer: string | undefined, + options: object, + ) { + let mapped: string | null = null; + if (source === "~/assets" || source.startsWith("~/assets/")) + mapped = rootAssets + source.slice("~/assets".length); + else if (source === "~/content" || source.startsWith("~/content/")) + mapped = rootContent + source.slice("~/content".length); + else if (source === "~" || source.startsWith("~/")) + mapped = nimbusDir + source.slice(1); + else if (source === "@" || source.startsWith("@/")) + mapped = nimbusDir + source.slice(1); + if (mapped === null) return null; + const resolved = await this.resolve(mapped, importer, { ...options, skipSelf: true }); + return resolved ?? { id: mapped }; + }, +}; + +export const vite = { + plugins: [aliasResolver, iconAlias], +}; diff --git a/src/nimbus/components.ts b/src/nimbus/components.ts new file mode 100644 index 00000000000..478ba5050d3 --- /dev/null +++ b/src/nimbus/components.ts @@ -0,0 +1,249 @@ +/** + * MDX globals registry — components available inside MDX without `import`. + * Wired via `` in `[...slug].astro`. + * Add new components here as you build (or install) them. + * + * Also serves as the import target for `~/components` resolution + * (e.g. `import { APIRequest } from "~/components"`). Every component + * imported this way must have a named export here. + */ + +import { Aside } from "./components/ui/aside"; +import RenderImpl from "./components/Render.astro"; +import { Card } from "./components/ui/card"; +import { CardGrid as CardGridImpl } from "./components/ui/card-grid"; +import { PackageManagers as PackageManagersImpl } from "./components/ui/package-managers"; +import { Step, Steps as StepsImpl } from "./components/ui/steps"; +import { Tabs as TabsImpl, TabItem as TabItemImpl } from "./components/ui/tabs"; +import { Badge as BadgeImpl } from "./components/ui/badge"; +import { Code as CodeImpl } from "./components/ui/code"; +import { FileTree as FileTreeImpl } from "./components/ui/file-tree"; +// CF-domain components. +import APIRequestImpl from "./components/cf/APIRequest.astro"; +import DashButtonImpl from "./components/cf/DashButton.astro"; +import DirectoryListingImpl from "./components/cf/DirectoryListing.astro"; +import DescriptionImpl from "./components/cf/Description.astro"; +import DetailsImpl from "./components/cf/Details.astro"; +import MetaInfoImpl from "./components/cf/MetaInfo.astro"; +import TypeImpl from "./components/cf/Type.astro"; +import WranglerConfigImpl from "./components/cf/WranglerConfig.astro"; +import WranglerNamespaceImpl from "./components/cf/WranglerNamespace.astro"; +import FeatureImpl from "./components/cf/Feature.astro"; +import GlossaryImpl from "./components/cf/Glossary.astro"; +import GlossaryTooltipImpl from "./components/cf/GlossaryTooltip.astro"; +import LinkButtonImpl from "./components/ui/link-button/LinkButton.astro"; +import LinkCardImpl from "./components/cf/LinkCard.astro"; +import LinkTitleCardImpl from "./components/cf/LinkTitleCard.astro"; +import ListTutorialsImpl from "./components/cf/ListTutorials.astro"; +import PlanImpl from "./components/cf/Plan.astro"; +import ProductReleaseNotesImpl from "./components/cf/ProductReleaseNotes.astro"; +import RelatedProductImpl from "./components/cf/RelatedProduct.astro"; +import TypeScriptExampleImpl from "./components/cf/TypeScriptExample.astro"; +import InlineBadgeImpl from "./components/cf/InlineBadge.astro"; +import YouTubeImpl from "./components/cf/YouTube.astro"; +import ExampleImpl from "./components/cf/Example.astro"; +import MarkdownImpl from "./components/cf/Markdown.astro"; +import CURLImpl from "./components/cf/CURL.astro"; +import GitHubCodeImpl from "./components/cf/GitHubCode.astro"; +import FlexImpl from "./components/cf/Flex.astro"; +import WidthImpl from "./components/cf/Width.astro"; +import RuleIDImpl from "./components/cf/RuleID.astro"; +import PublicStatsImpl from "./components/cf/PublicStats.astro"; +import RSSButtonImpl from "./components/cf/RSSButton.astro"; +import GlossaryDefinitionImpl from "./components/cf/GlossaryDefinition.astro"; +import WranglerCommandImpl from "./components/cf/WranglerCommand.astro"; +import AnchorHeadingImpl from "./components/cf/AnchorHeading.astro"; +import FeatureTableImpl from "./components/cf/FeatureTable.astro"; +import ProductFeaturesImpl from "./components/cf/ProductFeatures.astro"; +import PagesBuildPresetImpl from "./components/cf/PagesBuildPreset.astro"; +import AvailableNotificationsImpl from "./components/cf/AvailableNotifications.astro"; +import ExtraFlagDetailsImpl from "./components/cf/ExtraFlagDetails.astro"; +import FourCardGridImpl from "./components/cf/FourCardGrid.astro"; +import ListCardImpl from "./components/cf/ListCard.astro"; +import StreamImpl from "./components/cf/Stream.astro"; +import PagesBuildEnvironmentImpl from "./components/cf/PagesBuildEnvironment.astro"; +import PagesBuildEnvironmentLanguagesImpl from "./components/cf/PagesBuildEnvironmentLanguages.astro"; +import PagesBuildEnvironmentToolsImpl from "./components/cf/PagesBuildEnvironmentTools.astro"; +import WARPReleasesImpl from "./components/cf/WARPReleases.astro"; +import WARPReleaseImpl from "./components/cf/WARPRelease.astro"; +import CompatibilityFlagsImpl from "./components/cf/CompatibilityFlags.astro"; +import AutoconfigDiagramImpl from "./components/cf/AutoconfigDiagram.astro"; +import WorkersArchitectureDiagramImpl from "./components/cf/WorkersArchitectureDiagram.astro"; +import WorkersIsolateDiagramImpl from "./components/cf/WorkersIsolateDiagram.astro"; +import AnimatedWorkflowDiagramImpl from "./components/cf/AnimatedWorkflowDiagram.astro"; +import AgentsPlatformDiagramImpl from "./components/cf/AgentsPlatformDiagram.astro"; +import R2LocalUploadsDiagramImpl from "./components/cf/R2LocalUploadsDiagram.astro"; +import { AgentPrimitivesDiagram } from "./components/react/diagram-showcase/AgentPrimitivesDiagram"; +import ResourcesBySelectorImpl from "./components/cf/ResourcesBySelector.astro"; +import SubtractIPCalculatorImpl from "./components/react/SubtractIPCalculator"; + +// --- Nimbus components (re-exported by name so `~/components` imports resolve) --- +export const Render = RenderImpl; +export const PackageManagers = PackageManagersImpl; +export const Steps = StepsImpl; +export const Tabs = TabsImpl; +export const TabItem = TabItemImpl; +export const CardGrid = CardGridImpl; +export { Aside, Card }; + +// --- CF-domain components -------------------------------------------------- +export const DashButton = DashButtonImpl; +export const DirectoryListing = DirectoryListingImpl; +export const Description = DescriptionImpl; +export const Details = DetailsImpl; +export const MetaInfo = MetaInfoImpl; +export const Type = TypeImpl; +export const WranglerConfig = WranglerConfigImpl; +export const WranglerNamespace = WranglerNamespaceImpl; +export const Feature = FeatureImpl; +export const Glossary = GlossaryImpl; +export const GlossaryTooltip = GlossaryTooltipImpl; +export const LinkButton = LinkButtonImpl; +export const LinkCard = LinkCardImpl; +export const LinkTitleCard = LinkTitleCardImpl; +export const ListTutorials = ListTutorialsImpl; +export const Plan = PlanImpl; +export const ProductReleaseNotes = ProductReleaseNotesImpl; +export const RelatedProduct = RelatedProductImpl; +export const TypeScriptExample = TypeScriptExampleImpl; +export const InlineBadge = InlineBadgeImpl; +export const YouTube = YouTubeImpl; +export const Example = ExampleImpl; +export const Markdown = MarkdownImpl; +export const CURL = CURLImpl; +export const GitHubCode = GitHubCodeImpl; +export const Flex = FlexImpl; +export const Width = WidthImpl; +export const RuleID = RuleIDImpl; +export const PublicStats = PublicStatsImpl; +export const RSSButton = RSSButtonImpl; +export const GlossaryDefinition = GlossaryDefinitionImpl; +export const WranglerCommand = WranglerCommandImpl; +export const AnchorHeading = AnchorHeadingImpl; +export const FeatureTable = FeatureTableImpl; +export const ProductFeatures = ProductFeaturesImpl; +export const PagesBuildPreset = PagesBuildPresetImpl; +export const AvailableNotifications = AvailableNotificationsImpl; +export const ExtraFlagDetails = ExtraFlagDetailsImpl; +export const FourCardGrid = FourCardGridImpl; +export const ListCard = ListCardImpl; +export const Stream = StreamImpl; +export const PagesBuildEnvironment = PagesBuildEnvironmentImpl; +export const PagesBuildEnvironmentLanguages = PagesBuildEnvironmentLanguagesImpl; +export const PagesBuildEnvironmentTools = PagesBuildEnvironmentToolsImpl; +export const WARPReleases = WARPReleasesImpl; +export const WARPRelease = WARPReleaseImpl; +export const CompatibilityFlags = CompatibilityFlagsImpl; +export const AutoconfigDiagram = AutoconfigDiagramImpl; +export const WorkersArchitectureDiagram = WorkersArchitectureDiagramImpl; +export const WorkersIsolateDiagram = WorkersIsolateDiagramImpl; +export const AnimatedWorkflowDiagram = AnimatedWorkflowDiagramImpl; +export const AgentsPlatformDiagram = AgentsPlatformDiagramImpl; +export const R2LocalUploadsDiagram = R2LocalUploadsDiagramImpl; + +// SubtractIPCalculator — real port (Phase B / W12, D9). React island +// (`cidr-tools`); analytics `track()` is stubbed to a no-op via +// `~/util/zaraz`. Used by 2 cloudflare-one partials (warp split tunnels / +// tunnel route IPs), which import it directly from +// `~/components/SubtractIPCalculator.tsx` (re-export shim → react/ impl). +export const SubtractIPCalculator = SubtractIPCalculatorImpl; + +// Registry UI aliased under the upstream (Starlight) names so MDX imports +// like `import { Badge } from "~/components"` resolve unchanged. +export const Badge = BadgeImpl; +export const Code = CodeImpl; +export const FileTree = FileTreeImpl; + +// APIRequest — real port (D1). Build-time OpenAPI fetch (`~/util/api.ts`, +// pinned commit, swagger-parser deref) + dot-prop lookup, rendered via +// CURL/Details. Registry-global: this single flip un-stubs all 60 invocations +// across the 26 already-migrated pages — validated against the pinned schema. +// CF-domain; destined for the `cf-api-request` registry slug (deferred). +export const APIRequest = APIRequestImpl; + +// ResourcesBySelector — real port (Phase A / W3). Aggregates docs + videos + +// learning-paths into a filterable card grid. NOTE: this is registry-global, +// so flipping it un-stubs ALL MDX usages. The 3 RA "demos" pages +// (kv/demos, queues/demos, workers-ai/.../demos-architectures) filter on +// content types cf-nimbus has zero of and would hit the zero-match throw at +// build — they intentionally keep their own per-page Deferred wrapping and +// are NOT touched here (see D8). +export const ResourcesBySelector = ResourcesBySelectorImpl; + +// --- MDX globals registry (parsed by `nimbus-docs` integration) ---------- +export const components = { + // Nimbus built-ins + Aside, + Card, + CardGrid, + Step, + // Re-exports (also available via `~/components` imports) + PackageManagers, + Render, + Steps, + TabItem, + Tabs, + // CF-domain components (mix of real ports + remaining stubs) + APIRequest, + DashButton, + Markdown, + Details, + DirectoryListing, + Example, + FileTree, + GitHubCode, + Glossary, + GlossaryTooltip, + ListTutorials, + MetaInfo, + ProductReleaseNotes, + ResourcesBySelector, + Type, + TypeScriptExample, + WranglerConfig, + WranglerNamespace, + // CF-domain real ports + Description, + Feature, + LinkButton, + LinkCard, + LinkTitleCard, + Plan, + RelatedProduct, + InlineBadge, + YouTube, + CURL, + Flex, + Width, + RuleID, + PublicStats, + RSSButton, + GlossaryDefinition, + WranglerCommand, + AnchorHeading, + FeatureTable, + ProductFeatures, + PagesBuildPreset, + AvailableNotifications, + ExtraFlagDetails, + FourCardGrid, + ListCard, + Stream, + PagesBuildEnvironment, + PagesBuildEnvironmentLanguages, + PagesBuildEnvironmentTools, + WARPReleases, + WARPRelease, + CompatibilityFlags, + AutoconfigDiagram, + WorkersArchitectureDiagram, + WorkersIsolateDiagram, + AnimatedWorkflowDiagram, + AgentsPlatformDiagram, + R2LocalUploadsDiagram, + SubtractIPCalculator, + // Registry UI aliased to upstream Starlight names + Badge, + Code, + AgentPrimitivesDiagram +}; diff --git a/src/nimbus/components/AgentDirective.astro b/src/nimbus/components/AgentDirective.astro new file mode 100644 index 00000000000..c2617dfc23e --- /dev/null +++ b/src/nimbus/components/AgentDirective.astro @@ -0,0 +1,16 @@ +--- +interface Props { + /** Absolute or site-relative URL for this page's markdown version. */ + markdownUrl: string; + /** Absolute or site-relative URL for the top-level llms.txt index. */ + llmsUrl: string; +} + +const { markdownUrl, llmsUrl } = Astro.props; +--- + + diff --git a/src/nimbus/components/BackgroundLines.astro b/src/nimbus/components/BackgroundLines.astro new file mode 100644 index 00000000000..e9819b46d78 --- /dev/null +++ b/src/nimbus/components/BackgroundLines.astro @@ -0,0 +1,60 @@ +--- +/** + * BackgroundLines — decorative blueprint backdrop modelled on cloudflare.com + * and the "big move" blog. A centered content-width inner frame is flanked by + * dashed vertical rules; a wider outer frame carries a dot-grid and its own + * dashed rules. The inner frame paints a solid background so the dots show + * only in the side gutters between the two frames. Desktop-only, purely + * decorative, animation-free. + * + * Tokens: dashed rules use --nb-border; dots use --nb-grid-line. + */ +interface Props { + /** Inner (content) frame width in px — match the content max-width. */ + inner?: number; + /** Outer frame width in px — defines the dot-grid gutters. */ + outer?: number; +} + +const { inner = 1120, outer = 1360 } = Astro.props; + +// 1px vertical dashed rule: 16px dash + 16px gap (32px period). +const dashed = + "background-image:linear-gradient(to bottom,var(--nb-border) 50%,transparent 50%);background-size:1px 32px;background-repeat:repeat-y"; +--- + + diff --git a/src/nimbus/components/CopyPromptButton.astro b/src/nimbus/components/CopyPromptButton.astro new file mode 100644 index 00000000000..5dad9599b75 --- /dev/null +++ b/src/nimbus/components/CopyPromptButton.astro @@ -0,0 +1,91 @@ +--- +import { AGENTS, type AgentId } from "./agents"; +import { Button } from "@/components/ui/button"; + +interface Props { + /** Agent ids shown in the icon row. */ + agentIds?: readonly AgentId[]; + class?: string; + /** Optional native title tooltip. */ + tooltip?: string; +} + +const { + agentIds = ["claude", "cursor", "codex", "opencode"] as const, + class: className = "", + tooltip, +} = Astro.props; + +const featuredAgents = AGENTS.filter((a) => + (agentIds as readonly string[]).includes(a.id), +); +--- + + + + diff --git a/src/nimbus/components/CornerMarks.astro b/src/nimbus/components/CornerMarks.astro new file mode 100644 index 00000000000..5bfad982e5f --- /dev/null +++ b/src/nimbus/components/CornerMarks.astro @@ -0,0 +1,45 @@ +--- +type Corner = "tl" | "tr" | "bl" | "br"; +type Tone = "neutral" | "accent"; + +interface Props { + corners?: Corner[]; + size?: number; + offset?: number; + tone?: Tone; + class?: string; +} + +const { + corners = ["tl", "tr", "bl", "br"] as Corner[], + size = 14, + offset = -7, + tone = "neutral", + class: className = "", +} = Astro.props; + +const positions: Record = { + tl: `left:${offset}px;top:${offset}px;`, + tr: `right:${offset}px;top:${offset}px;`, + bl: `left:${offset}px;bottom:${offset}px;`, + br: `right:${offset}px;bottom:${offset}px;`, +}; + +const borderColor = + tone === "accent" ? "rgba(255, 251, 245, 0.32)" : "var(--color-border)"; + +const baseStyle = `width:${size}px;height:${size}px;border:1px solid ${borderColor};border-radius:3px;`; + +const fillClasses = + tone === "accent" ? "bg-primary" : "bg-background dark:bg-background"; +--- + +{ + corners.map((c) => ( +
+ {entry.data.enable_date && ( + + + + + )} + {entry.data.enable_flag && ( + + + + + )} + {entry.data.disable_flag && ( + + + + + )} +
+ Default as of + {entry.data.enable_date}
+ Flag to enable + + {entry.data.enable_flag} +
+ Flag to disable + + {entry.data.disable_flag} +
+ + + ); + }) +} diff --git a/src/nimbus/components/cf/DashButton.astro b/src/nimbus/components/cf/DashButton.astro new file mode 100644 index 00000000000..fd8fd925a02 --- /dev/null +++ b/src/nimbus/components/cf/DashButton.astro @@ -0,0 +1,44 @@ +--- +/** + * DashButton — "Go to " deep link into the Cloudflare dashboard. + * Validates the deeplink against CF's generated dash-routes data so docs + * can't link to dashboard pages that don't exist. + * + * CF source: cloudflare-docs/src/components/DashButton.astro + * Reads the shared route data in place via `~/content` (→ root src/content); + * Starlight LinkButton → our cf/LinkButton port. + */ +import CoreManuallyDefinedRoutes from "~/content/dash-routes/core-manually-defined.json"; +import CoreRoutes from "~/content/dash-routes/core.json"; +import ZeroTrustRoutes from "~/content/dash-routes/zero-trust.json"; +import LinkButton from "./LinkButton.astro"; + +interface Props { + url: string; + zeroTrust?: boolean; + buttonName?: string; +} + +const { url, zeroTrust = false, buttonName } = Astro.props; + +const routes = zeroTrust + ? ZeroTrustRoutes + : [...CoreRoutes, ...CoreManuallyDefinedRoutes]; + +const route = routes.find((route) => route.deeplink === url); + +if (!route) { + throw new Error(`[DashButton] No route found for ${url}`); +} + +const name = buttonName ?? route.name; +const baseUrl = zeroTrust + ? "https://one.dash.cloudflare.com" + : "https://dash.cloudflare.com"; + +const { href } = new URL(route.deeplink, baseUrl); +--- + +Go to {name} ↗ diff --git a/src/nimbus/components/cf/Description.astro b/src/nimbus/components/cf/Description.astro new file mode 100644 index 00000000000..4e51ecc961f --- /dev/null +++ b/src/nimbus/components/cf/Description.astro @@ -0,0 +1,13 @@ +--- +/** + * Description — styled subtitle/lede paragraph used immediately after the + * page H1 on CF product landing pages. Replaces the Stub placeholder. + * + * CF source: cloudflare-docs/src/components/Description.astro + * Mapping: rendered as regular prose — no subtitle sizing or muted color. + */ +--- + +
+ +
diff --git a/src/nimbus/components/cf/Details.astro b/src/nimbus/components/cf/Details.astro new file mode 100644 index 00000000000..6c5d47e3187 --- /dev/null +++ b/src/nimbus/components/cf/Details.astro @@ -0,0 +1,30 @@ +--- +/** + * Details — collapsible disclosure with a markdown-capable header. + * + * CF source: cloudflare-docs/src/components/Details.astro — 1:1 port + * (header is rendered through `marked` so inline code/links work). + */ +import { marked } from "marked"; + +interface Props { + header: string; + open?: boolean; + id?: string; +} + +const { header, open, id } = Astro.props; +--- + +
+ + +
+ + diff --git a/src/nimbus/components/cf/DirectoryListing.astro b/src/nimbus/components/cf/DirectoryListing.astro new file mode 100644 index 00000000000..77311f80f2d --- /dev/null +++ b/src/nimbus/components/cf/DirectoryListing.astro @@ -0,0 +1,103 @@ +--- +/** + * DirectoryListing — lists child pages of the current page (or a given + * folder) from the docs collection. + * + * CF source: cloudflare-docs/src/components/DirectoryListing.astro + * Mapping notes: upstream derives the folder from `Astro.params.slug`; + * we derive it from `Astro.url.pathname` (same value in this app's + * [...slug] route). `sortBySidebarOrder` is inlined — upstream's helper + * also handles Starlight sidebar entries, which we don't have. + * `external_link` frontmatter isn't used by Queues content, so links + * always point at `/${page.id}/`. + */ +import { getCollection, type CollectionEntry } from "astro:content"; +import DirectoryListingItem from "./DirectoryListingItem.astro"; + +interface PageNode { + page: CollectionEntry<"docs">; + children: PageNode[]; +} + +interface Props { + button?: boolean; + descriptions?: boolean; + folder?: string; + maxDepth?: number; + tag?: string; +} + +const { button = false, descriptions = false, maxDepth = 1, tag } = Astro.props; + +// Strip leading/trailing slashes; default to the current page's path. +const folder = (Astro.props.folder ?? Astro.url.pathname).replace(/^\/|\/$/g, ""); + +const baseDepth = folder.split("/").length; + +const allPages = await getCollection("docs", (page) => { + const pageDepth = page.id.split("/").length; + return page.id.startsWith(`${folder}/`) && pageDepth <= baseDepth + maxDepth; +}); + +const collator = new Intl.Collator("en"); +allPages.sort((a, b) => { + const aOrder = a.data.sidebar?.order ?? Number.MAX_VALUE; + const bOrder = b.data.sidebar?.order ?? Number.MAX_VALUE; + if (aOrder !== bOrder) return aOrder - bOrder; + return collator.compare(a.data.title, b.data.title); +}); + +function getChildren(parentPath: string, depth: number) { + return allPages.filter((page) => { + const pageDepth = page.id.split("/").length; + return ( + pageDepth === depth && + page.id.startsWith(parentPath) && + (tag ? page.data.tags?.includes(tag) : true) + ); + }); +} + +function buildPageTree(parentPath: string, currentDepth: number): PageNode[] { + const children = getChildren(parentPath, currentDepth); + return children.map((page) => ({ + page, + children: + currentDepth < baseDepth + maxDepth + ? buildPageTree(page.id, currentDepth + 1) + : [], + })); +} + +const pageTree = buildPageTree(folder, baseDepth + 1); + +if (pageTree.length === 0) { + console.warn( + `[DirectoryListing] No child pages for "${folder}" — rendering empty. ` + + `Expected during the bounded port when the target product's docs aren't migrated yet.`, + ); +} +--- + +{ + button ? ( +
+ ) : ( + + ) +} diff --git a/src/nimbus/components/cf/DirectoryListingItem.astro b/src/nimbus/components/cf/DirectoryListingItem.astro new file mode 100644 index 00000000000..c446fd46103 --- /dev/null +++ b/src/nimbus/components/cf/DirectoryListingItem.astro @@ -0,0 +1,40 @@ +--- +/** + * DirectoryListingItem — recursive
  • for DirectoryListing. + * + * CF source: cloudflare-docs/src/components/DirectoryListingItem.astro + */ +import { marked } from "marked"; +import type { CollectionEntry } from "astro:content"; + +interface Props { + node: { + page: CollectionEntry<"docs">; + children: Array; + }; + descriptions: boolean; +} + +const { node, descriptions } = Astro.props; +--- + +
  • + {node.page.data.title} + { + descriptions && node.page.data.description && ( + <> + : + + + ) + } + { + node.children.length > 0 && ( +
      + {node.children.map((child) => ( + + ))} +
    + ) + } +
  • diff --git a/src/nimbus/components/cf/Example.astro b/src/nimbus/components/cf/Example.astro new file mode 100644 index 00000000000..30e39e7b0a1 --- /dev/null +++ b/src/nimbus/components/cf/Example.astro @@ -0,0 +1,33 @@ +--- +/** + * Example — bordered card wrapper for inline demos / rendered output. + * + * CF source: cloudflare-docs/src/components/Example.astro + * + * Mapping notes: + * - Upstream wraps the slot in Starlight's . Nimbus has no global + * `.card` class to hook the no-title gap removal, so the card chrome is + * reproduced inline (same tokens as ui/card/Card.astro) and the title + * heading is simply omitted when `title` is empty. + */ +import { cn } from "@/lib/cn"; + +interface Props { + title?: string; +} + +const { title = "" } = Astro.props; +--- + +
    + { + title && ( +

    + {title} +

    + ) + } +
    + +
    +
    diff --git a/src/nimbus/components/cf/ExtraFlagDetails.astro b/src/nimbus/components/cf/ExtraFlagDetails.astro new file mode 100644 index 00000000000..b903ac9b179 --- /dev/null +++ b/src/nimbus/components/cf/ExtraFlagDetails.astro @@ -0,0 +1,20 @@ +--- +/** + * ExtraFlagDetails — marker wrapper for compatibility-flag extra details. + * + * CF source: cloudflare-docs/src/components/ExtraFlagDetails.astro (verbatim). + * The data-attributes are consumed by the compatibility-flags client script. + */ +import { z } from "astro/zod"; + +const props = z.object({ + key: z.string(), + mode: z.enum(["append", "replace"]).default("append"), +}); + +const { key, mode } = props.parse(Astro.props); +--- + +
    + +
    diff --git a/src/nimbus/components/cf/Feature.astro b/src/nimbus/components/cf/Feature.astro new file mode 100644 index 00000000000..084c95c7421 --- /dev/null +++ b/src/nimbus/components/cf/Feature.astro @@ -0,0 +1,68 @@ +--- +/** + * Feature — bordered card used in CF landing-page "Features" sections. + * Renders a header, slotted description, and a CTA link with arrow. + * + * CF source: cloudflare-docs/src/components/Feature.astro + * + * Mapping: + * - Starlight Icon "right-arrow" → astro-icon ph:arrow-right. + * - --sl-color-text / --color-cl1-* → Nimbus tailwind tokens. + * - Top-divider styling preserved; the `:not(.feature + .feature)` + * selector strips the border off the first feature in a group, so + * consecutive Features form a single visual list. + */ +import { Icon } from "astro-icon/components"; + +interface Props { + header: string; + href: string; + cta?: string; +} + +const { header, href, cta } = Astro.props; +const title = cta ?? `Use ${header}`; +--- + +
    +

    + {header} +

    +
    + +
    + + {title} + + +
    + + diff --git a/src/nimbus/components/cf/FeatureTable.astro b/src/nimbus/components/cf/FeatureTable.astro new file mode 100644 index 00000000000..c990efb5a2e --- /dev/null +++ b/src/nimbus/components/cf/FeatureTable.astro @@ -0,0 +1,87 @@ +--- +/** + * FeatureTable — plan-comparison table for a product, driven by plans data. + * + * CF source: cloudflare-docs/src/components/FeatureTable.astro + * + * Mapping notes: + * - `~/util/plans` indexPlans is inlined (getEntry over the `plans` + * collection + a small dot-path getter, replacing dot-prop). + * - CF Starlight table CSS vars swapped for Nimbus design tokens. + */ +import { z } from "astro/zod"; +import { getEntry } from "astro:content"; +import { marked } from "marked"; + +type Props = z.infer; + +const props = z + .object({ + id: z.string(), + }) + .strict(); + +const { id } = props.parse(Astro.props); + +function getByPath(obj: any, path: string) { + return path.split(".").reduce((acc, key) => (acc == null ? acc : acc[key]), obj); +} + +const entry = await getEntry("plans", "index"); +if (!entry) { + throw new Error(`[FeatureTable] Failed to load plans JSON.`); +} +const plan = getByPath(entry.data, id) as any; +if (!plan) { + throw new Error(`[FeatureTable] Failed to find ${id} in plans JSON.`); +} + +const features: any[] = Object.values(plan.properties); + +const hasFree = features.some((x) => x.free); +const hasPro = features.some((x) => x.pro); +const hasBiz = features.some((x) => x.biz); +const hasEnt = features.some((x) => x.ent); +const hasEntPlus = features.some((x) => x.ent_plus); + +const markdown = (content: any) => { + if (typeof content !== "string") return content; + return marked.parse(content); +}; + +const th = "border-b border-border bg-muted px-4 py-3 text-[0.8125rem] font-semibold"; +--- + + + + + + {hasFree && } + {hasPro && } + {hasBiz && } + {hasEnt && } + {hasEntPlus && } + + + + { + features.map((feature, i) => { + const isLast = i === features.length - 1; + const cellBorder = isLast ? "" : "border-b border-border"; + return ( + + + ); + }) + } + +
    FreeProBusinessEnterprise{plan.ent_plus}
    + {hasFree && } + {hasPro && } + {hasBiz && } + {hasEnt && } + {hasEntPlus && } +
    diff --git a/src/nimbus/components/cf/Flex.astro b/src/nimbus/components/cf/Flex.astro new file mode 100644 index 00000000000..792fe4099c2 --- /dev/null +++ b/src/nimbus/components/cf/Flex.astro @@ -0,0 +1,11 @@ +--- +/** + * Flex — column-on-mobile, row-on-desktop flex container. + * + * CF source: cloudflare-docs/src/components/Flex.astro (ported verbatim). + */ +--- + +
    + +
    diff --git a/src/nimbus/components/cf/FourCardGrid.astro b/src/nimbus/components/cf/FourCardGrid.astro new file mode 100644 index 00000000000..57afb12428c --- /dev/null +++ b/src/nimbus/components/cf/FourCardGrid.astro @@ -0,0 +1,40 @@ +--- +/** + * FourCardGrid — four-column responsive card grid, optionally staggered. + * + * CF source: cloudflare-docs/src/components/FourCardGrid.astro (verbatim). + */ +interface Props { + stagger?: boolean; +} + +const { stagger = false } = Astro.props; +--- + +
    + + diff --git a/src/nimbus/components/cf/GitHubCode.astro b/src/nimbus/components/cf/GitHubCode.astro new file mode 100644 index 00000000000..93ade4d1236 --- /dev/null +++ b/src/nimbus/components/cf/GitHubCode.astro @@ -0,0 +1,100 @@ +--- +/** + * GitHubCode — embed source pulled from the gh-code worker at build time. + * + * CF source: cloudflare-docs/src/components/GitHubCode.astro + * + * Mapping notes: + * - Fetch + line/tag slicing logic is ported verbatim. + * - Upstream renders through Starlight's ; Nimbus uses ui/code/Code, + * so a `title` in the `code` prop is translated to a `meta` string. + * - The `useTypeScriptExample` path wraps a rendered ts in + * cf/TypeScriptExample, which recovers the raw source from the rendered + * block (its slot-based contract) rather than a `code` prop. + */ +import { z } from "astro/zod"; +import { Code } from "../ui/code"; +import TypeScriptExample from "./TypeScriptExample.astro"; + +type Props = z.infer; + +const props = z + .object({ + repo: z.string(), + commit: z.string(), + file: z.string(), + lang: z.string(), + lines: z + .string() + .transform((val) => val.split("-").map(Number)) + .optional(), + tag: z.string().optional(), + useTypeScriptExample: z.boolean().default(false), + code: z.custom>().optional(), + }) + .strict() + .refine((val) => !(val.lines && val.tag), { + message: "Lines and tag are mutually exclusive filters.", + }) + .refine((val) => !val.useTypeScriptExample || val.lang === "ts", { + message: "useTypeScriptExample can only be used when 'lang' is set to 'ts'", + }); + +const { repo, commit, file, lang, lines, tag, useTypeScriptExample, code } = + props.parse(Astro.props); + +const res = await fetch( + `https://gh-code.developers.cloudflare.com/${repo}/${commit}/${file}`, +); + +if (!res.ok) { + throw new Error(`[GitHubCode] Received ${res.status} from Worker.`); +} + +const content = await res.text(); +let contentLines = content.split("\n"); + +if (lines) { + const [start, end] = lines; + + if (contentLines.length < end - 1) { + throw new Error( + `[GitHubCode] End line requested is beyond content length (${contentLines.length}).`, + ); + } + + contentLines = contentLines.slice(start - 1, end); +} else if (tag) { + const startTag = contentLines.findIndex((x) => + x.includes(``), + ); + const endTag = contentLines.findIndex((x) => + x.includes(``), + ); + + if (startTag === -1 || endTag === -1) { + throw new Error(`[GitHubCode] Unable to find a region using tag "${tag}".`); + } + + contentLines = contentLines.slice(startTag + 1, endTag); +} + +contentLines = contentLines.filter( + (line) => !/<[/]?docs-tag name=".*">/.test(line), +); + +const finalCode = contentLines.join("\n"); + +const { title, ...restCode } = (code ?? {}) as Record; +const meta = title ? `title="${title}"` : undefined; +--- + +{ + useTypeScriptExample ? ( + + + + ) : ( + + ) +} diff --git a/src/nimbus/components/cf/Glossary.astro b/src/nimbus/components/cf/Glossary.astro new file mode 100644 index 00000000000..fa4cf18f491 --- /dev/null +++ b/src/nimbus/components/cf/Glossary.astro @@ -0,0 +1,135 @@ +--- +/** + * Glossary — searchable table of glossary terms, optionally filtered to + * one product. + * + * CF source: cloudflare-docs/src/components/Glossary.astro + * Mapping notes: upstream reads the `glossary` collection via + * `~/util/glossary`; the collection lookup is inlined here. Search + + * "view more" pagination behavior is kept verbatim. CF brand classes + * swapped for Nimbus tokens. + */ +import { getCollection } from "astro:content"; +import { marked } from "marked"; + +interface Props { + product?: string; +} + +const { product } = Astro.props; + +const glossaries = await getCollection("glossary"); +const terms = glossaries + .flatMap((g) => + !product || g.id === product + ? g.data.entries.map((e) => ({ product: g.data.productName, ...e })) + : [], + ) + .sort((a, b) => a.term.localeCompare(b.term)); + +const INITIAL_VISIBLE_ROWS = 20; +--- + +
    + +
    +{/* No class attrs on table/th — prose.css table styling targets :not([class]). */} + + + + + + {!product && } + + + + { + terms.map((entry, idx) => ( + INITIAL_VISIBLE_ROWS }]}> + + } + + )) + } + +
    TermDefinitionProduct
    {entry.term} + {!product && {entry.product}
    + +{ + terms.length > INITIAL_VISIBLE_ROWS && ( +
    + +
    + ) +} + + diff --git a/src/nimbus/components/cf/GlossaryDefinition.astro b/src/nimbus/components/cf/GlossaryDefinition.astro new file mode 100644 index 00000000000..08f778a5516 --- /dev/null +++ b/src/nimbus/components/cf/GlossaryDefinition.astro @@ -0,0 +1,46 @@ +--- +/** + * GlossaryDefinition — render the definition for a single glossary term. + * + * CF source: cloudflare-docs/src/components/GlossaryDefinition.astro + * + * Mapping notes: + * - Upstream reads `~/util/glossary`'s getGlossaryEntry; the lookup is + * inlined here over the `glossary` collection (same source the Glossary + * and GlossaryTooltip ports use). + */ +import { getCollection } from "astro:content"; +import { z } from "astro/zod"; +import { marked } from "marked"; + +type Props = z.infer; + +const props = z + .object({ + term: z.string(), + prepend: z.string().optional(), + }) + .strict(); + +const { term, prepend } = props.parse(Astro.props); + +const glossaries = await getCollection("glossary"); +const entry = glossaries + .flatMap((g) => g.data.entries) + .find((e) => e.term === term); + +if (!entry) { + throw new Error(`[GlossaryDefinition] Unable to find entry for ${term}`); +} + +let general_definition = entry.general_definition; + +if (prepend) { + general_definition = prepend.concat(general_definition); +} + +general_definition = + general_definition.charAt(0).toUpperCase() + general_definition.slice(1); +--- + + diff --git a/src/nimbus/components/cf/GlossaryTooltip.astro b/src/nimbus/components/cf/GlossaryTooltip.astro new file mode 100644 index 00000000000..c782dd65335 --- /dev/null +++ b/src/nimbus/components/cf/GlossaryTooltip.astro @@ -0,0 +1,84 @@ +--- +/** + * GlossaryTooltip — dashed-underlined term that reveals its glossary + * definition on hover/focus. + * + * CF source: cloudflare-docs/src/components/GlossaryTooltip.astro + * Mapping notes: upstream positions the bubble with Tippy.js; this port + * is CSS-only (absolutely-positioned bubble, hover/focus visibility), + * which keeps the component dependency-free. Term lookup spans every + * glossary file, same as upstream's `getGlossaryEntry`. + */ +import { getCollection } from "astro:content"; +import { marked } from "marked"; + +interface Props { + term: string; + prepend?: string; + link?: string; +} + +const { term, prepend, link } = Astro.props; + +const glossaries = await getCollection("glossary"); +const entry = glossaries + .flatMap((g) => g.data.entries) + .find((e) => e.term === term); + +if (!entry) { + throw new Error(`[GlossaryTooltip] Unable to find entry for ${term}`); +} + +let definition = prepend + ? prepend.concat(entry.general_definition) + : entry.general_definition; +definition = definition.charAt(0).toUpperCase() + definition.slice(1); +definition = definition.split(/\r?\n/)[0]!; +--- + + +{link ? : } + + diff --git a/src/nimbus/components/cf/InlineBadge.astro b/src/nimbus/components/cf/InlineBadge.astro new file mode 100644 index 00000000000..6647db996bb --- /dev/null +++ b/src/nimbus/components/cf/InlineBadge.astro @@ -0,0 +1,50 @@ +--- +// CF's InlineBadge — a Badge with preset shorthands for product-status +// labels (alpha/beta/deprecated/early-access/legacy). Ports CF's +// `src/components/InlineBadge.astro`, swapping Starlight's Badge for +// Nimbus's `ui/badge`. The variant names line up (success/caution/danger/ +// note), so the preset map carries over unchanged. +import { Badge } from "@/components/ui/badge"; +import type { ComponentProps } from "astro/types"; + +type BadgeProps = ComponentProps; + +interface Props extends Partial { + preset?: "alpha" | "beta" | "deprecated" | "early-access" | "legacy"; +} + +let { preset, text, variant, ...attrs } = Astro.props; + +if (!preset && !text) { + throw new Error( + `[InlineBadge] Expected 'preset' or 'text', got neither, on ${Astro.url.pathname}`, + ); +} + +if (preset) { + switch (preset) { + case "alpha": + text = "Alpha"; + variant = "success"; + break; + case "beta": + text = "Beta"; + variant = "caution"; + break; + case "deprecated": + text = "Deprecated"; + variant = "danger"; + break; + case "early-access": + text = "Early Access"; + variant = "note"; + break; + case "legacy": + text = "Legacy"; + variant = "danger"; + break; + } +} +--- + + diff --git a/src/nimbus/components/cf/LinkButton.astro b/src/nimbus/components/cf/LinkButton.astro new file mode 100644 index 00000000000..3ac1e730354 --- /dev/null +++ b/src/nimbus/components/cf/LinkButton.astro @@ -0,0 +1,59 @@ +--- +/** + * LinkButton — button-styled anchor. + * + * CF source: re-exported from `@astrojs/starlight/components` via their + * barrel. Queues usage is the simple form: `label`. + * Variants beyond `primary` can be added when content needs them. + */ +interface Props { + href: string; + variant?: "primary" | "secondary" | "minimal"; + target?: "_blank"; +} + +const { href, variant = "primary", target } = Astro.props; +--- + + + + diff --git a/src/nimbus/components/cf/LinkCard.astro b/src/nimbus/components/cf/LinkCard.astro new file mode 100644 index 00000000000..5112958d26d --- /dev/null +++ b/src/nimbus/components/cf/LinkCard.astro @@ -0,0 +1,27 @@ +--- +/** + * LinkCard — full-card link with title and optional description. + * + * CF source: re-exported from `@astrojs/starlight/components` via their + * barrel. Queues usage: ``. + * Mapping notes: rendered with the Nimbus ui/card Card (same approach + * as LinkTitleCard) — stretched overlay link, title underlines on hover. + * Starlight's trailing arrow is dropped. + */ +import { Card } from "../ui/card"; + +interface Props { + title: string; + href: string; + description?: string; +} + +const { title, href, description } = Astro.props; +--- + +
    + + {description && } + + +
    diff --git a/src/nimbus/components/cf/LinkTitleCard.astro b/src/nimbus/components/cf/LinkTitleCard.astro new file mode 100644 index 00000000000..48525394369 --- /dev/null +++ b/src/nimbus/components/cf/LinkTitleCard.astro @@ -0,0 +1,32 @@ +--- +/** + * LinkTitleCard — card with icon, title, and slotted body; the whole + * card links to `href`. Used in CF landing-page "More resources" + * sections, often in a 2x2 grid. + * + * CF source: cloudflare-docs/src/components/LinkTitleCard.astro + * + * Mapping notes: + * - Rendered with the Nimbus ui/card Card instead of CF's bordered + * card with the 4-color `:nth-child` accent cycle. + * - Card doesn't take an href, so a stretched overlay link covers the + * card; the title underlines on hover. + * - Starlight Icon → astro-icon (icon name passed straight through). + */ +import { Card } from "../ui/card"; + +interface Props { + icon?: string; + title: string; + href: string; +} + +const { icon, title, href } = Astro.props; +--- + +
    + + + + +
    diff --git a/src/nimbus/components/cf/ListCard.astro b/src/nimbus/components/cf/ListCard.astro new file mode 100644 index 00000000000..5c989bde35e --- /dev/null +++ b/src/nimbus/components/cf/ListCard.astro @@ -0,0 +1,61 @@ +--- +/** + * ListCard — a Card whose body is a borderless link list with arrow affordances. + * + * CF source: cloudflare-docs/src/components/astro/ListCard.astro + * + * Mapping notes: + * - Starlight → Nimbus ui/card Card. + * - `--sl-color-gray-6` divider swapped for a theme-agnostic currentColor mix. + */ +import { Card } from "../ui/card"; + +interface Props { + title: string; + icon?: string; +} +--- + + + + + + diff --git a/src/nimbus/components/cf/ListTutorials.astro b/src/nimbus/components/cf/ListTutorials.astro new file mode 100644 index 00000000000..6930daa0fc7 --- /dev/null +++ b/src/nimbus/components/cf/ListTutorials.astro @@ -0,0 +1,66 @@ +--- +/** + * ListTutorials — table of every tutorial in the current product section + * (pages with `pcx_content_type: tutorial`), newest-reviewed first. + * + * CF source: cloudflare-docs/src/components/ListTutorials.astro + * Mapping notes: upstream also pulls cross-product tutorials via the + * `directory` collection + `products` frontmatter references; this app + * only carries Queues content, so the section-prefix filter is enough. + * date-fns `formatDistance` → Intl.RelativeTimeFormat; rehype external + * link processing dropped (tutorial links here are always internal). + */ +import { getCollection } from "astro:content"; + +const currentSection = (Astro.params.slug as string).split("/")[0]; + +const tutorials = await getCollection( + "docs", + (entry) => + entry.data.pcx_content_type === "tutorial" && + entry.id.startsWith(`${currentSection}/`), +); + +const toDate = (value?: string | Date) => + value ? new Date(value) : undefined; + +tutorials.sort( + (a, b) => + (toDate(b.data.reviewed)?.getTime() ?? 0) - + (toDate(a.data.reviewed)?.getTime() ?? 0), +); + +function timeAgo(value?: string | Date) { + const date = toDate(value); + if (!date) return undefined; + + const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" }); + const days = Math.round((date.getTime() - Date.now()) / 86_400_000); + if (Math.abs(days) < 30) return rtf.format(days, "day"); + if (Math.abs(days) < 365) return rtf.format(Math.round(days / 30), "month"); + return rtf.format(Math.round(days / 365), "year"); +} +--- + + + + + + + + + + + { + tutorials.map((tutorial) => ( + + + + + + )) + } + +
    NameLast UpdatedDifficulty
    + {tutorial.data.title} + {timeAgo(tutorial.data.reviewed)}{tutorial.data.difficulty}
    diff --git a/src/nimbus/components/cf/Markdown.astro b/src/nimbus/components/cf/Markdown.astro new file mode 100644 index 00000000000..a867893439b --- /dev/null +++ b/src/nimbus/components/cf/Markdown.astro @@ -0,0 +1,33 @@ +--- +/** + * Markdown — render a markdown string prop to HTML. + * + * CF source: cloudflare-docs/src/components/Markdown.astro + * + * Mapping notes: + * - Upstream uses the `dedent` package; reproduced here with a minimal + * common-leading-whitespace strip to avoid adding a dependency. + */ +import { z } from "astro/zod"; +import { marked } from "marked"; + +type Props = z.infer; + +function dedent(input: string): string { + const lines = input.replace(/^[ \t]*\n/, "").replace(/\n[ \t]*$/, "").split("\n"); + const indents = lines + .filter((l) => l.trim().length > 0) + .map((l) => l.match(/^[ \t]*/)?.[0].length ?? 0); + const min = indents.length ? Math.min(...indents) : 0; + return lines.map((l) => l.slice(min)).join("\n"); +} + +const props = z.object({ + text: z.string().transform((val) => dedent(val)), + inline: z.boolean().default(true), +}); + +const { text, inline } = props.parse(Astro.props); +--- + + diff --git a/src/nimbus/components/cf/MetaInfo.astro b/src/nimbus/components/cf/MetaInfo.astro new file mode 100644 index 00000000000..79caf34adc7 --- /dev/null +++ b/src/nimbus/components/cf/MetaInfo.astro @@ -0,0 +1,15 @@ +--- +/** + * MetaInfo — small inline annotation next to a parameter or type + * (e.g. "optional", default values). + * + * CF source: cloudflare-docs/src/components/MetaInfo.astro — 1:1 port. + */ +interface Props { + text: string; +} + +const { text } = Astro.props; +--- + +{text} diff --git a/src/nimbus/components/cf/PagesBuildEnvironment.astro b/src/nimbus/components/cf/PagesBuildEnvironment.astro new file mode 100644 index 00000000000..dff249d76fa --- /dev/null +++ b/src/nimbus/components/cf/PagesBuildEnvironment.astro @@ -0,0 +1,38 @@ +--- +/** + * PagesBuildEnvironment — per-version OS/architecture table for Pages builds. + * + * CF source: cloudflare-docs/src/components/PagesBuildEnvironment.astro + * Mapping notes: Starlight Tabs/TabItem → ui/tabs. + */ +import { getCollection } from "astro:content"; +import { Tabs, TabItem } from "../ui/tabs"; +import { marked } from "marked"; + +const versions = await getCollection("pages-build-environment"); +--- + + + { + versions.reverse().map((version) => ( + + + + + + + + + + + +
    + Build environment + +
    + Architecture + {version.data.build_environment.architecture}
    +
    + )) + } +
    diff --git a/src/nimbus/components/cf/PagesBuildEnvironmentLanguages.astro b/src/nimbus/components/cf/PagesBuildEnvironmentLanguages.astro new file mode 100644 index 00000000000..3e6973bf3ac --- /dev/null +++ b/src/nimbus/components/cf/PagesBuildEnvironmentLanguages.astro @@ -0,0 +1,43 @@ +--- +/** + * PagesBuildEnvironmentLanguages — per-version language support table. + * + * CF source: cloudflare-docs/src/components/PagesBuildEnvironmentLanguages.astro + * Mapping notes: Starlight Tabs/TabItem → ui/tabs. + */ +import { getCollection } from "astro:content"; +import { Tabs, TabItem } from "../ui/tabs"; + +const versions = await getCollection("pages-build-environment"); +--- + + + { + versions.reverse().map((version) => ( + + + + + + + + + + + {version.data.languages.map((language) => ( + + + + + + + + ))} + +
    ToolDefault versionSupported versionsEnvironment variableFile
    + {language.name} + {language.default}{language.supported}{language.environment_variable && {language.environment_variable}}{language.file?.join(", ")}
    +
    + )) + } +
    diff --git a/src/nimbus/components/cf/PagesBuildEnvironmentTools.astro b/src/nimbus/components/cf/PagesBuildEnvironmentTools.astro new file mode 100644 index 00000000000..51f3ba09ae5 --- /dev/null +++ b/src/nimbus/components/cf/PagesBuildEnvironmentTools.astro @@ -0,0 +1,41 @@ +--- +/** + * PagesBuildEnvironmentTools — per-version build tool support table. + * + * CF source: cloudflare-docs/src/components/PagesBuildEnvironmentTools.astro + * Mapping notes: Starlight Tabs/TabItem → ui/tabs. + */ +import { getCollection } from "astro:content"; +import { Tabs, TabItem } from "../ui/tabs"; + +const versions = await getCollection("pages-build-environment"); +--- + + + { + versions.reverse().map((version) => ( + + + + + + + + + + {version.data.tools.map((tool) => ( + + + + + + + ))} + +
    ToolDefault versionSupported versionsEnvironment variable
    + {tool.name} + {tool.default}{tool.supported}{tool.environment_variable && {tool.environment_variable}}
    +
    + )) + } +
    diff --git a/src/nimbus/components/cf/PagesBuildPreset.astro b/src/nimbus/components/cf/PagesBuildPreset.astro new file mode 100644 index 00000000000..b7cf78edef1 --- /dev/null +++ b/src/nimbus/components/cf/PagesBuildPreset.astro @@ -0,0 +1,55 @@ +--- +/** + * PagesBuildPreset — build configuration table for a Pages framework preset. + * + * CF source: cloudflare-docs/src/components/PagesBuildPreset.astro (verbatim; + * reads the `pages-framework-presets` collection via getEntry). + */ +import { z } from "astro/zod"; +import { getEntry } from "astro:content"; + +type Props = z.infer; + +const props = z.object({ + framework: z.string(), +}); + +const { framework } = props.parse(Astro.props); + +const entry = await getEntry("pages-framework-presets", "index"); + +if (!entry) { + throw new Error("Failed to load data"); +} + +const presets = entry.data.build_configs; + +const preset = presets[framework]; + +if (!preset) { + throw new Error( + `[PagesBuildPreset] Failed to find preset for ${framework}, included on ${Astro.params.slug}`, + ); +} +--- + + + + + + + + + + + + + + + + + + + + +
    Configuration optionValue
    Production branchmain
    Build command{preset.build_command}
    Build directory{preset.build_output_directory}
    diff --git a/src/nimbus/components/cf/Plan.astro b/src/nimbus/components/cf/Plan.astro new file mode 100644 index 00000000000..7ac8d88337d --- /dev/null +++ b/src/nimbus/components/cf/Plan.astro @@ -0,0 +1,55 @@ +--- +/** + * Plan — small inline badge showing a feature's CF plan availability. + * Renders to a single styled string (e.g. "Available on all plans", + * "Enterprise-only"). + * + * CF source: cloudflare-docs/src/components/Plan.astro + * + * Two upstream input shapes: + * 1. `` — static taxonomy lookup + * against the `mappings` table. Fully supported here. + * 2. `` — dynamic lookup via a yaml + * `plans.yaml` indexed by `indexPlans()`. **Not supported yet** — + * requires porting the CF plans data file + util. Until then, the + * `id` branch falls through to a placeholder string so authors see + * what's missing. + */ +import { z } from "astro/zod"; + +const MAPPINGS = { + all: "Available on all plans", + paid: "Available on Paid plans", + pro: "Pro and above", + business: "Business and above", + enterprise: "Enterprise-only", + "add-on": "Add-on feature", + "ent-add-on": "Enterprise-only paid add-on", + "workers-all": "Available on Free and Paid plans", + "workers-paid": "Available on Workers Paid plan", +} as const satisfies Record; + +type PlanType = keyof typeof MAPPINGS; + +const props = z + .object({ + type: z.enum(Object.keys(MAPPINGS) as [PlanType, ...PlanType[]]), + }) + .or(z.object({ id: z.string() })); + +const input = props.parse(Astro.props); + +let availability: string; +if ("type" in input) { + availability = MAPPINGS[input.type]; +} else { + // Pending: port `cloudflare-docs/src/content/plans/*.yaml` + the + // `indexPlans()` lookup util. Until then, surface a stub label so it's + // visible which Plan calls are still unresolved. + availability = `[Plan id="${input.id}" pending data port]`; +} +--- + +
    + {availability} +
    diff --git a/src/nimbus/components/cf/ProductFeatures.astro b/src/nimbus/components/cf/ProductFeatures.astro new file mode 100644 index 00000000000..b18f06ca4bd --- /dev/null +++ b/src/nimbus/components/cf/ProductFeatures.astro @@ -0,0 +1,129 @@ +--- +/** + * ProductFeatures — descriptive per-plan feature breakdown for a product. + * + * CF source: cloudflare-docs/src/components/ProductFeatures.astro + * + * Mapping notes: + * - `~/util/plans` indexPlans is inlined (getEntry over the `plans` + * collection + a small dot-path getter). Markup ported verbatim. + */ +import { z } from "astro/zod"; +import { marked } from "marked"; +import { getEntry } from "astro:content"; + +type Props = z.infer; + +const props = z + .object({ + id: z.string(), + additional_descriptions: z.boolean().optional(), + }) + .strict(); + +const { id, additional_descriptions } = props.parse(Astro.props); + +function getByPath(obj: any, path: string) { + return path.split(".").reduce((acc, key) => (acc == null ? acc : acc[key]), obj); +} + +const entry = await getEntry("plans", "index"); +if (!entry) { + throw new Error(`[ProductFeatures] Failed to load plans JSON.`); +} +const plan = getByPath(entry.data, id) as any; +if (!plan) { + throw new Error(`[ProductFeatures] Failed to find ${id} in plans JSON.`); +} + +const entries = Object.entries(plan); +--- + +{ + entries.map(([key, value]: [string, any]) => { + if (key === "title" || key === "link") return; + + return ( +
    +

    {value.title}

    + {value.link && ( +

    + Link: {value.title} +

    + )} + {Object.values(value.properties).map((value: any) => ( +
    + + {value.title !== "Availability" && value.summary && ( + + )} +
      + {value.free !== undefined && ( +
    • + Free:{" "} + +
    • + )} + {additional_descriptions && ( + <> + {value.lite !== undefined ? ( +
    • + Lite:{" "} + +
    • + ) : ( + value.free !== undefined && ( +
    • + Lite:{" "} + +
    • + ) + )} + + )} + {value.pro !== undefined && ( +
    • + Pro:{" "} + +
    • + )} + {additional_descriptions && ( + <> + {value.pro_plus !== undefined ? ( +
    • + Pro Plus:{" "} + +
    • + ) : ( + value.pro !== undefined && ( +
    • + Pro Plus:{" "} + +
    • + ) + )} + + )} + {value.biz !== undefined && ( +
    • + Business:{" "} + +
    • + )} + {value.ent !== undefined && ( +
    • + Enterprise:{" "} + +
    • + )} +
    +
    + ))} +
    + ); + }) +} diff --git a/src/nimbus/components/cf/ProductReleaseNotes.astro b/src/nimbus/components/cf/ProductReleaseNotes.astro new file mode 100644 index 00000000000..8eb27a94b52 --- /dev/null +++ b/src/nimbus/components/cf/ProductReleaseNotes.astro @@ -0,0 +1,122 @@ +--- +/** + * ProductReleaseNotes — renders a product changelog from the + * `release-notes` collection, grouped by publish date (newest first). + * The page's `release_notes_file_name` frontmatter names the data file. + * + * CF source: cloudflare-docs/src/components/ProductReleaseNotes.astro + * + * Faithful port. Grouping is delegated to `~/util/release-notes`; the + * `individual_page` entry shape is rendered via `~/util/container` + * (`entryToString`) exactly as upstream. The RSS link is shown on pages + * tagged `pcx_content_type: changelog` and points at the per-page feed + * served by `src/pages/[...changelog].xml.ts` (`//index.xml`). + * AnchorHeading is this app's port of the upstream component. + */ +import { getEntry, type CollectionEntry } from "astro:content"; +import { marked } from "marked"; +import { entryToString } from "~/util/container"; +import { getReleaseNotes } from "~/util/release-notes"; + +import AnchorHeading from "~/components/cf/AnchorHeading.astro"; +import RSSButton from "~/components/cf/RSSButton.astro"; + +const page = await getEntry("docs", Astro.params.slug!); + +if (!page) { + throw new Error( + `[ProductReleaseNotes] Failed to find entry for ${Astro.params.slug}.`, + ); +} + +if (!page.data.release_notes_file_name) { + throw new Error( + `[ProductReleaseNotes] ${Astro.params.slug} does not have a 'release_notes_file_name' frontmatter property.`, + ); +} + +if ( + page.data.release_notes_file_name && + page.data.release_notes_file_name.length > 1 +) { + throw new Error( + `[ProductReleaseNotes] This component cannot be used on files that have more than 1 entry in their 'release_notes_file_name' frontmatter property.`, + ); +} + +const name = page.data.release_notes_file_name?.[0]; + +let releaseNotes; + +if (name === "api-deprecations") { + ({ releaseNotes } = await getReleaseNotes({ deprecationsOnly: true })); +} else { + ({ releaseNotes } = await getReleaseNotes({ + filter: (entry: CollectionEntry<"release-notes">) => { + return entry.id === name; + }, + })); +} + +if (!releaseNotes) { + throw new Error( + `[ProductReleaseNotes] Failed to find release notes called ${name}.`, + ); +} +--- + +{ + page.data.pcx_content_type === "changelog" && ( +

    + +

    + ) +} + +{ + releaseNotes.map(([date, entries]) => ( +
    + {(entries ?? []).map(async (entry) => { + let description; + if (entry.individual_page) { + const link = entry.individual_page; + + if (!link) + throw new Error( + `Changelog entry points to individual page but no link is provided`, + ); + + const linked = await getEntry("docs", link.slice(1, -1)); + + if (!linked) + throw new Error( + `Changelog entry points to ${link.slice(1, -1)} but unable to find entry with that slug`, + ); + + description = (await entryToString(linked, Astro.locals)) ?? linked.body; + + return ( +
    + + + +

    {entry.date}

    + {} +
    + ); + } else { + description = marked.parse(entry.description as string); + return ( + <> + +
    + {entry.title && {entry.title}} + {} +
    + + ); + } + })} +
    + )) +} diff --git a/src/nimbus/components/cf/PublicStats.astro b/src/nimbus/components/cf/PublicStats.astro new file mode 100644 index 00000000000..feefda7f358 --- /dev/null +++ b/src/nimbus/components/cf/PublicStats.astro @@ -0,0 +1,27 @@ +--- +/** + * PublicStats — inline a canonical Cloudflare network stat by id. + * + * CF source: cloudflare-docs/src/components/PublicStats.astro + * + * Mapping notes: + * - `zodEnumFromObjKeys` helper is inlined; values match upstream. + */ +import { z } from "astro/zod"; + +const mappings = { + data_center_cities: "over 330 cities", + total_bandwidth: "over 405 Tbps network capacity", + network_peers: "over 13,000 network peers", +} as const satisfies Record; + +const props = z.object({ + id: z.enum(Object.keys(mappings) as [keyof typeof mappings, ...(keyof typeof mappings)[]]), +}); + +const { id } = props.parse(Astro.props); + +const stat = mappings[id]; +--- + +{stat} diff --git a/src/nimbus/components/cf/R2LocalUploadsDiagram.astro b/src/nimbus/components/cf/R2LocalUploadsDiagram.astro new file mode 100644 index 00000000000..067f6f1892e --- /dev/null +++ b/src/nimbus/components/cf/R2LocalUploadsDiagram.astro @@ -0,0 +1,1259 @@ +--- +interface Props { + mode?: "without" | "with" | "comparison"; + autoPlay?: boolean; + loop?: boolean; +} + +const { mode = "comparison", autoPlay = true, loop = true } = Astro.props; +--- + + +
    + { + mode === "comparison" && ( +
    + + Local uploads + + +
    + ) + } +
    + +
    +
    +
    + + + + +
    +
    + Client + Eastern North America +
    +
    +
    + + +
    + + +
    + Edge + Eastern North America +
    +
    +
    + + + + + +
    + R2 Gateway Worker +
    +
    +
    + + +
    + + + + + + + + + + + + + Object metadata + Object data + + + + +
    + + + + + + + + +
    +
    + Your bucket + Eastern Europe +
    +
    +
    + + + + +
    + Metadata Service +
    +
    +
    + + + + + +
    + Object Data Infra +
    +
    +
    +
    +
    + +
    + + + + + Data is uploaded and accessible +
    +
    +
    + + + + diff --git a/src/nimbus/components/cf/RSSButton.astro b/src/nimbus/components/cf/RSSButton.astro new file mode 100644 index 00000000000..6f588f68701 --- /dev/null +++ b/src/nimbus/components/cf/RSSButton.astro @@ -0,0 +1,45 @@ +--- +/** + * RSSButton — link to a changelog RSS feed (or arbitrary href). + * + * CF source: cloudflare-docs/src/components/RSSButton.astro + * + * Mapping notes: + * - Starlight's is swapped for astro-icon. The Starlight icon name + * `rss` maps to Phosphor `ph:rss-simple`; an explicit `ph:`/`:`-qualified + * name passes through unchanged. + */ +import { z } from "astro/zod"; +import { Icon } from "astro-icon/components"; + +const props = z + .object({ + text: z.string().default("Subscribe to RSS"), + icon: z.string().default("rss"), + }) + .and( + z + .object({ + changelog: z + .string() + .transform((val) => val.toLowerCase().replaceAll(" ", "-")), + }) + .or( + z.object({ + href: z.string(), + }), + ), + ); + +const input = props.parse(Astro.props); +const iconName = input.icon.includes(":") ? input.icon : "ph:rss-simple"; +--- + + + {input.text} + + diff --git a/src/nimbus/components/cf/ReactSelect.tsx b/src/nimbus/components/cf/ReactSelect.tsx new file mode 100644 index 00000000000..12e8aaeafd4 --- /dev/null +++ b/src/nimbus/components/cf/ReactSelect.tsx @@ -0,0 +1,90 @@ +import Select, { type Props } from "react-select"; +import type { ActionMeta, StylesConfig } from "react-select"; +import { setSearchParams } from "~/util/url"; + +export type Option = { + label: string; + value: string; +}; + +export default function ReactSelect(props: Props & { urlParam?: string }) { + // CF source: cloudflare-docs/src/components/ReactSelect.tsx (faithful port). + // The Starlight `--sl-color-gray-1..6` scale is undefined in cf-nimbus, so + // the styles are remapped onto cf-nimbus's Tailwind theme tokens (emitted + // as `--color-*` CSS vars from globals.css `@theme`): + // gray-6 (panel bg) → --color-card + // gray-5 (focused option) → --color-muted + // gray-4 (border/active) → --color-border + // gray-3 (focus border) → --color-border-strong + // gray-3 (group heading) → --color-muted-foreground + // gray-1 (text) → --color-foreground + const selectStyles: StylesConfig = { + control: (base, state) => ({ + ...base, + backgroundColor: "var(--color-card)", + borderColor: state.isFocused + ? "var(--color-border-strong)" + : "var(--color-border)", + "&:hover": { + borderColor: "var(--color-border-strong)", + }, + boxShadow: state.isFocused + ? "0 0 0 1px var(--color-border-strong)" + : "none", + }), + menu: (base) => ({ + ...base, + backgroundColor: "var(--color-card)", + borderColor: "var(--color-border)", + }), + option: (base, state) => ({ + ...base, + backgroundColor: state.isFocused + ? "var(--color-muted)" + : "var(--color-card)", + color: "var(--color-foreground)", + "&:active": { + backgroundColor: "var(--color-border)", + }, + }), + singleValue: (base) => ({ + ...base, + color: "var(--color-foreground)", + }), + input: (base) => ({ + ...base, + color: "var(--color-foreground)", + }), + groupHeading: (base) => ({ + ...base, + color: "var(--color-muted-foreground)", + }), + }; + + const onChangeHandler = ( + option: Option | null, + actionMeta: ActionMeta