Openstatus www.openstatus.dev
6
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat: new changelog page and description (#446)

* feat: new changelog page and description

* fix: missing public route

authored by

Maximilian Kaske and committed by
GitHub
fc68d900 52791d2a

+148 -9
+1
apps/web/src/app/(content)/blog/page.tsx
··· 43 43 publishedAt={post.publishedAt} 44 44 imageSrc={post.image} 45 45 title={post.title} 46 + href={`./blog/${post.slug}`} 46 47 > 47 48 <div className="prose"> 48 49 <p>{post.description}</p>
+81
apps/web/src/app/(content)/changelog/[slug]/page.tsx
··· 1 + import type { Metadata } from "next"; 2 + import { notFound } from "next/navigation"; 3 + import { allChangelogs } from "contentlayer/generated"; 4 + 5 + import { 6 + defaultMetadata, 7 + ogMetadata, 8 + twitterMetadata, 9 + } from "@/app/shared-metadata"; 10 + import { Changelog } from "@/components/content/changelog"; 11 + import { Shell } from "@/components/dashboard/shell"; 12 + import { BackButton } from "@/components/layout/back-button"; 13 + 14 + // export const dynamic = "force-static"; 15 + 16 + export async function generateStaticParams() { 17 + return allChangelogs.map((post) => ({ 18 + slug: post.slug, 19 + })); 20 + } 21 + 22 + export async function generateMetadata({ 23 + params, 24 + }: { 25 + params: { slug: string }; 26 + }): Promise<Metadata | void> { 27 + const post = allChangelogs.find((post) => post.slug === params.slug); 28 + if (!post) { 29 + return; 30 + } 31 + 32 + const { title, publishedAt: publishedTime, description, slug, image } = post; 33 + 34 + return { 35 + ...defaultMetadata, 36 + title, 37 + description, 38 + openGraph: { 39 + ...ogMetadata, 40 + title, 41 + description, 42 + type: "article", 43 + publishedTime, 44 + url: `https://www.openstatus.dev/changelog/${slug}`, 45 + images: [ 46 + { 47 + url: `https://openstatus.dev/api/og/post?title=${title}&description=${description}&image=${image}`, 48 + }, 49 + ], 50 + }, 51 + twitter: { 52 + ...twitterMetadata, 53 + title, 54 + description, 55 + images: [ 56 + `https://openstatus.dev/api/og/post?title=${title}&description=${description}&image=${image}`, 57 + ], 58 + }, 59 + }; 60 + } 61 + 62 + export default function ChangelogPage({ 63 + params, 64 + }: { 65 + params: { slug: string }; 66 + }) { 67 + const post = allChangelogs.find((post) => post.slug === params.slug); 68 + 69 + if (!post) { 70 + notFound(); 71 + } 72 + 73 + return ( 74 + <> 75 + <BackButton href="/changelog" /> 76 + <Shell className="sm:py-8 md:py-12"> 77 + <Changelog post={post} /> 78 + </Shell> 79 + </> 80 + ); 81 + }
+2
apps/web/src/app/(content)/changelog/page.tsx
··· 1 1 import type { Metadata } from "next"; 2 + import Link from "next/link"; 2 3 import { allChangelogs } from "contentlayer/generated"; 3 4 4 5 import { ··· 40 41 publishedAt={post.publishedAt} 41 42 imageSrc={post.image} 42 43 title={post.title} 44 + href={`./changelog/${post.slug}`} 43 45 > 44 46 <Mdx code={post.body.code} /> 45 47 </Timeline.Article>
+35
apps/web/src/components/content/changelog.tsx
··· 1 + import type { Changelog } from "contentlayer/generated"; 2 + 3 + import { Mdx } from "@/components/content/mdx"; 4 + import { formatDate } from "@/lib/utils"; 5 + 6 + export function Changelog({ post }: { post: Changelog }) { 7 + return ( 8 + <article className="grid gap-8"> 9 + <div className="mx-auto grid w-full max-w-prose gap-3"> 10 + <p className="text-muted-foreground font-mono text-sm"> 11 + {formatDate(new Date(post.publishedAt))} 12 + </p> 13 + <h1 className="font-cal mb-5 text-3xl">{post.title}</h1> 14 + <div className="border-border relative h-64 w-full overflow-hidden rounded-lg border"> 15 + {/* <Image 16 + src={post.image} 17 + fill={true} 18 + alt={post.title} 19 + className="object-cover" 20 + /> */} 21 + {/* HOTFIX: plain `img` */} 22 + {/* eslint-disable-next-line @next/next/no-img-element */} 23 + <img 24 + src={post.image} 25 + alt={post.title} 26 + className="h-full w-full object-cover" 27 + /> 28 + </div> 29 + </div> 30 + <div className="prose-pre:overflow-y-auto prose-pre:max-w-xs md:prose-pre:max-w-none mx-auto max-w-prose"> 31 + <Mdx code={post.body.code} /> 32 + </div> 33 + </article> 34 + ); 35 + }
+19 -8
apps/web/src/components/content/timeline.tsx
··· 1 + import Link from "next/link"; 2 + 1 3 import { formatDate } from "@/lib/utils"; 2 4 3 5 interface TimelineProps { ··· 22 24 } 23 25 24 26 interface ArticleProps { 27 + href: string; 25 28 publishedAt: string; 26 29 imageSrc: string; 27 30 title: string; 28 31 children?: React.ReactNode; 29 32 } 30 33 31 - function Article({ publishedAt, imageSrc, title, children }: ArticleProps) { 34 + function Article({ 35 + publishedAt, 36 + imageSrc, 37 + title, 38 + children, 39 + href, 40 + }: ArticleProps) { 32 41 return ( 33 42 <article className="grid grid-cols-1 gap-4 md:grid-cols-5 md:gap-6"> 34 43 <time className="text-muted-foreground order-2 font-mono text-sm md:order-1 md:col-span-1"> 35 44 {formatDate(new Date(publishedAt))} 36 45 </time> 37 46 <div className="relative order-1 h-64 w-full md:order-2 md:col-span-4"> 38 - {/* same reason as blog post - missing image on prod */} 39 - {/* <Image 47 + <Link href={href}> 48 + {/* same reason as blog post - missing image on prod */} 49 + {/* <Image 40 50 src={imageSrc} 41 51 fill={true} 42 52 alt={title} 43 53 className="border-border rounded-md border object-cover" 44 54 /> */} 45 - <img 46 - src={imageSrc} 47 - alt={title} 48 - className="border-border h-64 w-full rounded-md border object-cover" 49 - /> 55 + <img 56 + src={imageSrc} 57 + alt={title} 58 + className="border-border h-64 w-full rounded-md border object-cover" 59 + /> 60 + </Link> 50 61 </div> 51 62 <div className="order-3 grid grid-cols-1 gap-4 md:col-span-4 md:col-start-2"> 52 63 <h3 className="text-foreground font-cal text-2xl">{title}</h3>
+2 -1
apps/web/src/content/changelog/multi-region-monitoring.mdx
··· 1 1 --- 2 2 title: Multi regions monitoring by default 3 + description: Your monitors are now being called from around the world. 3 4 publishedAt: 2023-10-25 4 5 image: /assets/changelog/multi-region-monitoring.png 5 6 --- 6 7 7 8 We have migrated our backend to [fly.io](https://fly.io) and we have enabled 8 - multi regions monitoring by default for every monitors at no extra costs. 9 + multi regions monitoring by default for every monitor at no extra costs. 9 10 10 11 Here are the list of regions we are monitoring from: 11 12
+1
apps/web/src/content/changelog/response-time-charts.mdx
··· 1 1 --- 2 2 title: Response Time Charts 3 + description: You have now access to new charts for better visualization. 3 4 publishedAt: 2023-10-08 4 5 image: /assets/changelog/response-time-charts.png 5 6 ---
+1
apps/web/src/content/changelog/slack-discord-notification.mdx
··· 1 1 --- 2 2 title: Slack and Discord notifications 3 + description: You can now send notifications to your favorite channels. 3 4 publishedAt: 2023-11-01 4 5 image: /assets/changelog/slack-discord-notification.png 5 6 ---
+1
apps/web/src/content/changelog/status-widget.mdx
··· 1 1 --- 2 2 title: Status Widget 3 + description: You can now access the status of your status page via a public api. 3 4 publishedAt: 2023-10-05 4 5 image: /assets/changelog/status-widget.png 5 6 ---
+4
apps/web/src/contentlayer/documents/changelog.ts
··· 10 10 type: "string", 11 11 required: true, 12 12 }, 13 + description: { 14 + type: "string", 15 + required: true, 16 + }, 13 17 image: { 14 18 type: "string", 15 19 required: true,
+1
apps/web/src/middleware.ts
··· 73 73 "/blog", 74 74 "/blog/(.*)", 75 75 "/changelog", 76 + "/changelog/(.*)", 76 77 "/legal/(.*)", 77 78 "/discord", 78 79 "/github",