Openstatus www.openstatus.dev

chore: cli block (#1308)

* chore: cli block

* chore: landing page

* chore: data-rehype-pretty-code-caption

* chore: json ld description

* fix: styles

authored by

Maximilian Kaske and committed by
GitHub
e7b5b247 22218123

+144 -65
+1 -1
apps/web/src/app/(pages)/(content)/(landing)/[slug]/page.tsx
··· 92 92 function Hero({ hero, description }: { hero: string; description: string }) { 93 93 return ( 94 94 <div className="mx-auto my-12 flex flex-col items-center gap-4 sm:my-16 md:gap-6"> 95 - <div className="flex flex-col gap-4 text-center md:gap-6"> 95 + <div className="flex flex-col gap-2 text-center md:gap-4"> 96 96 <h1 className="font-cal text-5xl leading-tight md:text-6xl">{hero}</h1> 97 97 <h2 className="mx-auto max-w-md text-muted-foreground text-xl md:max-w-xl md:text-2xl"> 98 98 {description}
+2 -2
apps/web/src/app/(pages)/(content)/page.tsx
··· 16 16 "@context": "https://schema.org", 17 17 "@type": "Product", 18 18 name: "openstatus", 19 - description: "Opensource uptime and synthetic monitoring.", 19 + description: "Open-source uptime and synthetic monitoring with status pages.", 20 20 brand: { 21 21 "@type": "Brand", 22 22 name: "openstatus", ··· 56 56 "@context": "https://schema.org", 57 57 "@type": "WebPage", 58 58 name: "openstatus", 59 - description: "Opensource uptime and synthetic monitoring.", 59 + description: "Open-source uptime and synthetic monitoring with status pages.", 60 60 url: "https://openstatus.dev", 61 61 image: "https://openstatus.dev/assets/logos/OpenStatus-Logo.svg", 62 62 headline: "Showcase your uptime with a status page",
+6
apps/web/src/components/icons.tsx
··· 17 17 CreditCard, 18 18 Eye, 19 19 EyeOff, 20 + File, 20 21 FileClock, 22 + FileText, 21 23 Fingerprint, 22 24 Gauge, 23 25 Globe, ··· 62 64 UserCircle, 63 65 Users, 64 66 Webhook, 67 + Workflow, 65 68 Youtube, 66 69 Zap, 67 70 } from "lucide-react"; ··· 106 109 bell: Bell, 107 110 zap: Zap, 108 111 eye: Eye, 112 + file: File, 113 + "file-text": FileText, 114 + workflow: Workflow, 109 115 "eye-off": EyeOff, 110 116 network: Network, 111 117 users: Users,
+15 -2
apps/web/src/components/marketing/cli/card.tsx
··· 1 1 import { cardConfig } from "@/config/features"; 2 + import { Button } from "@openstatus/ui"; 3 + import Link from "next/link"; 2 4 import { 3 5 CardContainer, 4 6 CardContent, ··· 8 10 CardIcon, 9 11 CardTitle, 10 12 } from "../card"; 11 - import { Terminal } from "./terminal"; 13 + import { Code } from "./code"; 12 14 13 15 export function CLICard() { 14 16 const { icon, title, features } = cardConfig.cli; ··· 19 21 <CardTitle>{title}</CardTitle> 20 22 </CardHeader> 21 23 <CardContent> 22 - <Terminal /> 24 + <Code /> 23 25 <CardFeatureContainer> 24 26 {features?.map((feature, i) => ( 25 27 <CardFeature key={i} {...feature} /> 26 28 ))} 29 + <div className="text-center"> 30 + <Button className="rounded-full" asChild> 31 + <Link 32 + href="https://docs.openstatus.dev/cli/getting-started/" 33 + target="_blank" 34 + rel="noreferrer" 35 + > 36 + Learn more 37 + </Link> 38 + </Button> 39 + </div> 27 40 </CardFeatureContainer> 28 41 </CardContent> 29 42 </CardContainer>
+33
apps/web/src/components/marketing/cli/code.tsx
··· 1 + import { Mdx } from "@/components/content/mdx"; 2 + import { allUnrelateds } from "content-collections"; 3 + 4 + const blockYaml = allUnrelateds.find( 5 + (unrelated) => unrelated.slug === "yaml-file", 6 + ); 7 + 8 + const blockCLI = allUnrelateds.find( 9 + (unrelated) => unrelated.slug === "cli-block", 10 + ); 11 + 12 + export function Code() { 13 + if (!blockYaml) { 14 + throw new Error("Yaml block not found"); 15 + } 16 + 17 + if (!blockCLI) { 18 + throw new Error("CLI block not found"); 19 + } 20 + 21 + return ( 22 + <div className="flex flex-col gap-4"> 23 + <Mdx 24 + code={blockCLI.mdx} 25 + className="max-w-none prose-pre:overflow-hidden" 26 + /> 27 + <Mdx 28 + code={blockYaml.mdx} 29 + className="max-w-none prose-pre:overflow-hidden" 30 + /> 31 + </div> 32 + ); 33 + }
-42
apps/web/src/components/marketing/cli/terminal.tsx
··· 1 - "use client"; 2 - 3 - import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"; 4 - import { cn } from "@/lib/utils"; 5 - import { Button } from "@openstatus/ui"; 6 - import { CheckIcon, CopyIcon } from "lucide-react"; 7 - import type React from "react"; 8 - 9 - const command = "openstatus monitors trigger 420"; 10 - 11 - export function Terminal({ className, ...props }: React.ComponentProps<"pre">) { 12 - const { copy, isCopied } = useCopyToClipboard(); 13 - 14 - function handleCopy() { 15 - copy(command, { withToast: true }); 16 - } 17 - 18 - return ( 19 - <div className="relative truncate"> 20 - <pre 21 - className={cn("rounded-lg border bg-muted/50 px-4 py-2", className)} 22 - {...props} 23 - > 24 - <code className="text-sm"> 25 - <span className="text-muted-foreground">$</span> {command} 26 - </code> 27 - <Button 28 - variant="ghost" 29 - size="icon" 30 - onClick={handleCopy} 31 - className="absolute top-1 right-1 backdrop-blur-sm hover:bg-transparent" 32 - > 33 - {isCopied ? ( 34 - <CheckIcon className="size-4" /> 35 - ) : ( 36 - <CopyIcon className="size-4" /> 37 - )} 38 - </Button> 39 - </pre> 40 - </div> 41 - ); 42 - }
+31 -1
apps/web/src/components/marketing/feature/index.tsx
··· 475 475 ); 476 476 } 477 477 478 + const blockYaml = allUnrelateds.find( 479 + (unrelated) => unrelated.slug === "yaml-file", 480 + ); 481 + 482 + export function FeatureYAML( 483 + props: Partial<Pick<InteractiveFeatureProps, "position">>, 484 + ) { 485 + if (!blockYaml) { 486 + throw new Error("YAML file block not found"); 487 + } 488 + 489 + return ( 490 + <InteractiveFeature 491 + icon="file-text" 492 + iconText="YAML File" 493 + title="Monitoring as Code." 494 + subTitle="Use any version control system to manage your monitors." 495 + className="max-h-max" 496 + component={ 497 + <Mdx 498 + code={blockYaml.mdx} 499 + className="max-w-none prose-pre:overflow-hidden" 500 + /> 501 + } 502 + col={2} 503 + position={props.position || "right"} 504 + /> 505 + ); 506 + } 507 + 478 508 export function FeatureCLI( 479 509 props: Partial<Pick<InteractiveFeatureProps, "position">>, 480 510 ) { ··· 490 520 icon="terminal" 491 521 iconText="CLI" 492 522 title="Run everywhere." 493 - subTitle="Create your monitors from your favorite terminal." 523 + subTitle="Manage and trigger your monitors from your favorite terminal." 494 524 component={ 495 525 <Mdx 496 526 code={blockCLI.mdx}
+14 -15
apps/web/src/config/features.tsx
··· 107 107 title: "CLI", 108 108 features: [ 109 109 { 110 + icon: "file-text", 111 + catchline: "YAML file configuration", 112 + description: "Use version control to keep track of all your changes.", 113 + }, 114 + { 110 115 icon: "sparkles", 111 - catchline: "No ClickOps", 112 - description: ( 113 - <p> 114 - Use your config file to manage or trigger your monitors. Never leave 115 - your terminal.{" "} 116 - <a 117 - className="text-foreground" 118 - href="https://docs.openstatus.dev/cli/getting-started/" 119 - target="_blank" 120 - rel="noreferrer" 121 - > 122 - Learn more 123 - </a> 124 - </p> 125 - ), 116 + catchline: "Monitoring as Code", 117 + description: 118 + "Apply changes to your monitors directly from the terminal.", 119 + }, 120 + { 121 + icon: "workflow", 122 + catchline: "CI/CD", 123 + description: 124 + "Trigger a specific monitor or run your file within your workflows.", 126 125 }, 127 126 ], 128 127 },
+2
apps/web/src/config/landings.tsx
··· 21 21 FeatureSubscriptions, 22 22 FeatureTerraformProvider, 23 23 FeatureTimingAssertions, 24 + FeatureYAML, 24 25 SpeedBanner, 25 26 } from "@/components/marketing/feature"; 26 27 ··· 97 98 "Use configuration files to define your monitoring and store them in your codebase.", 98 99 blocks: [ 99 100 <FeatureCLI key="feature-cli" />, 101 + <FeatureYAML key="feature-yaml-file" position="top" />, 100 102 <FeatureGitHubAction key="feature-github-action" />, 101 103 <EnterpriseBanner key="enterprise-banner" />, 102 104 <FeatureAPIMonitoring key="feature-api-monitoring" />,
+1 -1
apps/web/src/content/unrelated/cli-block.mdx
··· 1 1 ```bash 2 - openstatus monitors create --config openstatus.yaml 2 + $ openstatus monitors apply 3 3 ```
+14
apps/web/src/content/unrelated/yaml-file.mdx
··· 1 + ```yaml title="openstatus.yaml" 2 + "openstat.us": 3 + active: true 4 + frequency: 1m 5 + kind: http 6 + name: openstat.us 7 + regions: 8 + - ams 9 + - iad 10 + - syd 11 + request: 12 + method: GET 13 + url: https://openstat.us 14 + ```
+25 -1
apps/web/src/styles/globals.css
··· 215 215 [data-highlighted-line] { 216 216 @apply bg-muted rounded; 217 217 } 218 - } 218 + 219 + [data-rehype-pretty-code-caption] { 220 + @apply mt-1 text-muted-foreground text-xs; 221 + } 222 + 223 + [data-rehype-pretty-code-title] { 224 + @apply mb-1 text-muted-foreground text-xs font-mono; 225 + } 226 + 227 + .dark [data-theme='dark'] { 228 + display: block; 229 + } 230 + 231 + [data-theme='dark'] { 232 + display: none; 233 + } 234 + 235 + [data-theme='light'] { 236 + display: block; 237 + } 238 + 239 + .dark [data-theme='light'] { 240 + display: none; 241 + } 242 + }