Openstatus www.openstatus.dev

๐ŸŒ More guides and seo (#884)

* ๐Ÿ“ wip

* ๐Ÿš€ guide astro status page

* ๐Ÿ”ฅ more data

* ๐Ÿš€ improve look

* ๐Ÿš€ few improvment

authored by

Thibault Le Ouay and committed by
GitHub
34c3420d 22d08615

+272 -7
+112
apps/docs/guides/how-deploy-status-page-cf-pages.mdx
··· 1 + --- 2 + title: How to deploy your own status page to Cloudflare Pages 3 + description: Learn how to use OpenStatus monitoring data and deploy your own Status Page to cloudflare pages. 4 + --- 5 + 6 + ## Introduction 7 + 8 + At OpenStatus, we believe that monitoring your endpoints should be easy and accessible to everyone. 9 + We also believe that having a status page is essential for your users to know the status of your services. 10 + We also think that manually updating your status page is a waste of time. The best way to update your status page is to automate it. That's why we built OpenStatus. 11 + 12 + In this guide, we will show you how to deploy your own status page to Cloudflare Pages using OpenStatus monitoring data. 13 + 14 + For the Status Page, we will use [Astro](https://astro.build/) a new JavaScript web framework, that allows you to build faster websites with less JavaScript. 15 + 16 + The code showcased in this guide is available on [GitHub](https://github.com/openstatusHQ/astro-status-page) 17 + 18 + 19 + 20 + <Frame caption="Astro Status Pages"> 21 + <img 22 + src="/images/guides/how-deploy-status-page-cf-pages/status-page.png" 23 + alt="Astro Status Page" 24 + /> 25 + </Frame> 26 + 27 + 28 + ## Prerequisites 29 + 30 + To follow this guide, you need: 31 + 32 + - A Cloudflare Account. 33 + - An [OpenStatus](https://www.openstatus.dev) Account. 34 + 35 + ## Start monitoring your services 36 + 37 + To get your monitoring data, you need to create a monitor on OpenStatus. 38 + We will monitor the status of your endpoint and get the data to display on your status page. 39 + 40 + 41 + ### How to create a monitor 42 + 43 + To create a monitor, follow these steps: 44 + 1. Go to the OpenStatus dashboard. 45 + 2. Click on the `Monitors` tab. 46 + 3. Click on the `Create Monitor` button. 47 + 4. Fill in the form with your endpoint details. 48 + 5. Click on the `Create Monitor` button. 49 + 50 + 51 + ### Get your OpenStatus API key 52 + 53 + To get your API key, follow these steps: 54 + 55 + 1. Go to the OpenStatus dashboard. 56 + 2. Click on the `Settings` tab. 57 + 3. Click on the `API Token` tab. 58 + 4. Click on the `Create API Key` button. 59 + 5. Copy your API key. 60 + 61 + ## Deploy your own status page 62 + 63 + With OpenStatus monitoring data, you can bring your status page to life. You can really make it your own. 64 + We are going to deploy a simple status page that shows the status of your endpoint. 65 + 66 + For this guide we are going to use our [Astro Status Page](https://github.com/openstatusHQ/astro-status-page) template. 67 + 68 + ### Customize the Astro Status Page 69 + 70 + In the `index.astro` we are fetching the monitor data from OpenStatus and displaying it on the page. 71 + 72 + ```ts 73 + const response = await fetch("https://api.openstatus.dev/v1/monitor", { 74 + headers: { 75 + "x-openstatus-key": env.API_KEY, 76 + }, 77 + }); 78 + 79 + const data = await response.json(); 80 + 81 + 82 + const r = monitorsSchema.parse(data); 83 + 84 + // our monitors id 85 + const monitorIds = [1] 86 + const result = r.filter((m) => monitorIds.find(id => m.id === id) ); 87 + ``` 88 + 89 + In the line `const monitorIds = [1]` you need to replace `1` with the list of monitors id you want to display. 90 + 91 + 92 + ### Deploy the Astro Status Page to Cloudflare Pages 93 + 94 + First in your Cloudflare dashboard you need to set the environment variable. 95 + 96 + Go to your Cloudflare dashboard and click on the `Workers & Pages`. 97 + 98 + Select your site and click on the `Settings` tab. 99 + 100 + You can add your OpenStatus API key as an environment variable. 101 + 102 + ```env 103 + API_KEY=your-api-key 104 + ``` 105 + 106 + Now you can deploy your Astro Status Page to Cloudflare Pages with the following command: 107 + 108 + ```bash 109 + npm run pages:deploy 110 + ``` 111 + 112 + Your Status Page is now live on Cloudflare Pages. ๐ŸŽ‰
+1
apps/docs/guides/introduction.mdx
··· 6 6 7 7 - [How to use OpenStatus to test latency in GitHub Actions](/guides/test-latency-cf-workers-in-github-actions) 8 8 9 + - [Deploy your own Status Page to Cloudflare Pages](/guides/how-deploy-status-page-cf-pages)
apps/docs/images/guides/how-deploy-status-page-cf-pages/status-page.png

This is a binary file and will not be displayed.

+2 -1
apps/docs/mint.json
··· 211 211 "group": "Guides", 212 212 "pages": [ 213 213 "guides/introduction", 214 - "guides/test-latency-cf-workers-in-github-actions" 214 + "guides/test-latency-cf-workers-in-github-actions", 215 + "guides/how-deploy-status-page-cf-pages" 215 216 ] 216 217 } 217 218 ],
apps/web/public/assets/checker/glauber.png

This is a binary file and will not be displayed.

+2 -2
apps/web/src/app/play/checker/_components/checker-play.tsx
··· 6 6 return ( 7 7 <Shell className="flex flex-col gap-8"> 8 8 <HeaderPlay 9 - title="Is your endpoint fast?" 10 - description="Test the performance of your website, API from the different continents." 9 + title="Is your endpoint globally fast?" 10 + description="Test your website and API performance across all continents. " 11 11 /> 12 12 <div className="mx-auto grid w-full max-w-xl gap-6"> 13 13 <CheckerForm />
+60
apps/web/src/app/play/checker/_components/global-monitoring.tsx
··· 1 + import Link from "next/link"; 2 + 3 + import { Button } from "@openstatus/ui"; 4 + 5 + import { 6 + CardContainer, 7 + CardFeature, 8 + CardFeatureContainer, 9 + CardIcon, 10 + CardContent, 11 + CardHeader, 12 + CardTitle, 13 + } from "@/components/marketing/card"; 14 + import { Globe } from "@/components/marketing/monitor/globe"; 15 + import type { ValidIcon } from "@/components/icons"; 16 + import { Shell } from "@/components/dashboard/shell"; 17 + 18 + const features: { 19 + icon: ValidIcon; 20 + catchline: string; 21 + description: string; 22 + }[] = [ 23 + { 24 + icon: "globe", 25 + catchline: "Latency Monitoring.", 26 + description: 27 + "Monitor the latency of your endpoints from all over the world. We support 35 regions.", 28 + }, 29 + { 30 + icon: "play", 31 + catchline: "Monitor anything.", 32 + description: 33 + "We can monitor your website, API, DNS, TCP or any other service you have running. ", 34 + }, 35 + { 36 + icon: "bot", 37 + catchline: "Synthetic Monitoring.", 38 + description: "Run your tests in your CI/CD pipeline, or on a schedule. ", 39 + }, 40 + ]; 41 + export const GlobalMonitoring = () => { 42 + return ( 43 + <Shell className="mx-auto"> 44 + <CardHeader> 45 + <CardIcon icon={"activity"} /> 46 + <CardTitle>Start monitoring your services</CardTitle> 47 + </CardHeader> 48 + <> 49 + <div className="mt-12"> 50 + <div className="list-none space-y-4"> 51 + {features?.map((feature, i) => ( 52 + // biome-ignore lint/suspicious/noArrayIndexKey: <explanation> 53 + <CardFeature key={i} {...feature} /> 54 + ))} 55 + </div> 56 + </div> 57 + </> 58 + </Shell> 59 + ); 60 + };
+27
apps/web/src/app/play/checker/_components/testimonial.tsx
··· 1 + import { Shell } from "@/components/dashboard/shell"; 2 + 3 + export const Testimonial = () => { 4 + return ( 5 + <div className="mx-auto max-w-2xl lg:max-w-4xl"> 6 + <figure className="mt-10"> 7 + <blockquote className="text-center font-semibold text-2xl leading-8 sm:text-2xl sm:leading-9"> 8 + <p>โ€œJust don't give up on your usersโ€</p> 9 + </blockquote> 10 + <figcaption className="mt-10"> 11 + <div className="mt-4 flex items-center justify-center space-x-3 text-base"> 12 + <div> 13 + <div className="font-semibold">Glauber Costa</div> 14 + 15 + <div className="text-muted-foreground">CEO of Turso</div> 16 + </div> 17 + <img 18 + className="h-10 w-10 rounded-full" 19 + src="/assets/checker/glauber.png" 20 + alt="" 21 + /> 22 + </div> 23 + </figcaption> 24 + </figure> 25 + </div> 26 + ); 27 + };
+14 -2
apps/web/src/app/play/checker/page.tsx
··· 2 2 3 3 import { BackButton } from "@/components/layout/back-button"; 4 4 import CheckerPlay from "./_components/checker-play"; 5 + import { Testimonial } from "./_components/testimonial"; 6 + import { BottomCTA } from "@/components/marketing/in-between-cta"; 7 + import { GlobalMonitoring } from "./_components/global-monitoring"; 5 8 6 9 export const metadata: Metadata = { 7 10 title: "Speed Checker", ··· 17 20 export default async function PlayPage() { 18 21 return ( 19 22 <> 20 - <BackButton href="/" /> 21 - <CheckerPlay /> 23 + <div className="mx-auto space-y-12"> 24 + <div className="mt-12"> 25 + <BackButton href="/" /> 26 + <CheckerPlay /> 27 + </div> 28 + <Testimonial /> 29 + <GlobalMonitoring /> 30 + <div className="mx-auto max-w-2xl lg:max-w-4xl"> 31 + <BottomCTA /> 32 + </div> 33 + </div> 22 34 </> 23 35 ); 24 36 }
+1 -1
apps/web/src/components/marketing/in-between-cta.tsx
··· 48 48 export function BottomCTA() { 49 49 return ( 50 50 <InBetweenCTA 51 - description="Learn over time how your services are performing, and inform your users when there are issues." 51 + description="Learn how your services are performing over time, and notify your users of any issues." 52 52 actions={{ 53 53 primary: { label: "Start for Free", href: "/app/login" }, 54 54 secondary: { label: "Schedule a Demo", href: "/cal", target: "_blank" },
+53 -1
apps/web/src/components/marketing/monitor/globe.tsx
··· 19 19 export function Globe() { 20 20 const canvasRef = useRef<HTMLCanvasElement>(null); 21 21 const prefersReducedMotion = useMediaQuery( 22 - "(prefers-reduced-motion: reduce)", 22 + "(prefers-reduced-motion: reduce)" 23 23 ); 24 24 const [disabledWebGL, setDisabledWebGL] = useState(false); 25 25 ··· 58 58 { location: [-33.8688, 151.2093], size: 0.05 }, 59 59 // GRU 60 60 { location: [-23.5558, -46.6396], size: 0.05 }, 61 + // ARN 62 + { location: [59.6519, 17.9186], size: 0.05 }, 63 + // ATL 64 + { location: [33.6407, -84.4277], size: 0.05 }, 65 + // BOG 66 + { location: [4.711, -74.0721], size: 0.05 }, 67 + // BOM 68 + { location: [19.0896, 72.8656], size: 0.05 }, 69 + // CDG 70 + { location: [49.0097, 2.5479], size: 0.05 }, 71 + // DEN 72 + { location: [39.8561, -104.6737], size: 0.05 }, 73 + // DFW 74 + { location: [32.8998, -97.0403], size: 0.05 }, 75 + // EWR 76 + { location: [40.6895, -74.1745], size: 0.05 }, 77 + // EZE 78 + { location: [-34.8226, -58.5336], size: 0.05 }, 79 + // FRA 80 + { location: [50.0349, 8.5622], size: 0.05 }, 81 + // GDI 82 + { location: [20.6752, -103.34], size: 0.05 }, 83 + // LAX 84 + { location: [33.9416, -118.4085], size: 0.05 }, 85 + // MAD 86 + { location: [40.4168, -3.7038], size: 0.05 }, 87 + // MIA 88 + { location: [25.7617, -80.1918], size: 0.05 }, 89 + // NRT 90 + { location: [35.6895, 139.6917], size: 0.05 }, 91 + // ORD 92 + { location: [41.9742, -87.9073], size: 0.05 }, 93 + // OTP 94 + { location: [44.4268, 26.1025], size: 0.05 }, 95 + // PHX 96 + { location: [33.4484, -112.074], size: 0.05 }, 97 + // QRO 98 + { location: [20.5881, -100.3899], size: 0.05 }, 99 + // SCL 100 + { location: [-33.4489, -70.6693], size: 0.05 }, 101 + // SEA 102 + { location: [47.6062, -122.3321], size: 0.05 }, 103 + // SIN 104 + { location: [1.3521, 103.8198], size: 0.05 }, 105 + // SJC 106 + { location: [37.3541, -121.9552], size: 0.05 }, 107 + // WAW 108 + { location: [52.2297, 21.0122], size: 0.05 }, 109 + // YUL 110 + { location: [45.5017, -73.5673], size: 0.05 }, 111 + // YYZ 112 + { location: [43.6511, -79.347], size: 0.05 }, 61 113 ], 62 114 onRender: (state) => { 63 115 // Called on every animation frame.