diff --git a/.gitignore b/.gitignore
index d1595af42..e1a58eddd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -34,3 +34,6 @@ yarn-error.log*
# vercel
.vercel
+
+# packages
+dist
diff --git a/apps/web/package.json b/apps/web/package.json
index 64d37a401..6c3bb9515 100644
--- a/apps/web/package.json
+++ b/apps/web/package.json
@@ -11,12 +11,15 @@
"dependencies": {
"@clerk/nextjs": "^4.21.3",
"@openstatus/db": "workspace:^",
+ "@openstatus/tinybird": "workspace:*",
+ "@openstatus/upstash": "workspace:*",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-toast": "^1.1.4",
"@t3-oss/env-nextjs": "0.4.1",
"@upstash/redis": "^1.21.0",
"class-variance-authority": "^0.6.0",
"clsx": "^1.2.1",
+ "date-fns": "^2.30.0",
"lucide-react": "^0.244.0",
"next": "13.4.6",
"next-plausible": "3.7.2",
diff --git a/apps/web/src/app/_components/background.tsx b/apps/web/src/app/_components/background.tsx
index b43aa0dfa..fbd9d7117 100644
--- a/apps/web/src/app/_components/background.tsx
+++ b/apps/web/src/app/_components/background.tsx
@@ -11,7 +11,7 @@ export default function Background({
useMouseMove();
return (
<>
-
+
diff --git a/apps/web/src/app/api/v0/cron/route.ts b/apps/web/src/app/api/v0/cron/route.ts
new file mode 100644
index 000000000..d1f731af1
--- /dev/null
+++ b/apps/web/src/app/api/v0/cron/route.ts
@@ -0,0 +1,48 @@
+import { env } from "@/env.mjs";
+import { Tinybird, publishPingResponse } from "@openstatus/tinybird";
+
+// TODO: create one route per region
+export const preferredRegion = ["fra1"];
+export const runtime = "edge";
+
+const DEFAULT_URL =
+ process.env.NODE_ENV === "development"
+ ? "http://localhost:3000"
+ : process.env.VERCEL_URL;
+
+const tb = new Tinybird({ token: env.TINY_BIRD_API_KEY });
+
+// TODO: create a package for monitor
+async function monitor(
+ res: Response,
+ { latency, url }: { latency: number; url: string }
+) {
+ return await publishPingResponse(tb)({
+ id: "openstatus",
+ timestamp: Date.now(),
+ statusCode: res.status,
+ latency,
+ url,
+ // TODO: add region, res
+ });
+}
+
+// TODO: auth middleware for user API check (unkey)
+export async function GET(req: Request) {
+ try {
+ const { searchParams } = new URL(req.url);
+ const hasUrl = searchParams.has("url");
+ const url = hasUrl ? searchParams.get("url") : `${DEFAULT_URL}/api/v0/ping`;
+
+ const startTime = Date.now();
+ const res = await fetch(url, { cache: "no-store" });
+ const endTime = Date.now();
+ const latency = endTime - startTime;
+
+ await monitor(res, { latency, url });
+
+ return new Response("OK", { status: 200 });
+ } catch (e) {
+ return new Response("Error", { status: 500 });
+ }
+}
diff --git a/apps/web/src/app/api/v0/ping/route.ts b/apps/web/src/app/api/v0/ping/route.ts
new file mode 100644
index 000000000..acde0f849
--- /dev/null
+++ b/apps/web/src/app/api/v0/ping/route.ts
@@ -0,0 +1,17 @@
+import { Redis } from "@openstatus/upstash";
+
+const redis = Redis.fromEnv();
+
+export async function GET(req: Request) {
+ const RANDOM = Math.random() > 0.9;
+ try {
+ // TODO: connect tinybird, upstash and planetscale
+ await redis.ping();
+ if (RANDOM) {
+ throw new Error("Arg");
+ }
+ return new Response("OK", { status: 200 });
+ } catch {
+ return new Response("Error", { status: 500 });
+ }
+}
diff --git a/apps/web/src/app/layout.tsx b/apps/web/src/app/layout.tsx
index a8d861a77..0571c7431 100644
--- a/apps/web/src/app/layout.tsx
+++ b/apps/web/src/app/layout.tsx
@@ -14,21 +14,25 @@ const calSans = LocalFont({
variable: "--font-calsans",
});
+const TITLE = "OpenStatus";
+const DESCRIPTION =
+ "Open-Source alternative to your current monitoring service with beautiful status page";
+
export const metadata: Metadata = {
- title: "openstatus.dev",
- description: "An Open Source Alternative for your next Status Page.",
+ title: TITLE,
+ description: DESCRIPTION,
metadataBase: new URL("https://openstatus.dev"),
twitter: {
images: [`/api/og`],
card: "summary_large_image",
- title: "openstatus.dev",
- description: "An Open Source Alternative for your next Status Page.",
+ title: TITLE,
+ description: DESCRIPTION,
},
openGraph: {
type: "website",
images: [`/api/og`],
- title: "openstatus.dev",
- description: "An Open Source Alternative for your next Status Page.",
+ title: TITLE,
+ description: DESCRIPTION,
},
};
diff --git a/apps/web/src/app/page.tsx b/apps/web/src/app/page.tsx
index 92881cc39..56c7aa5fb 100644
--- a/apps/web/src/app/page.tsx
+++ b/apps/web/src/app/page.tsx
@@ -1,18 +1,22 @@
import { Badge } from "@/components/ui/badge";
-
-import { Metadata } from "next";
import { HeroForm } from "./_components/hero-form";
+import { Tinybird, getResponseList } from "@openstatus/tinybird";
+import { env } from "@/env.mjs";
+import { StatusContainer } from "./_components/status-container";
+import MOCK from "@/app/_mocks/response-list.json";
-export const metadata: Metadata = {
- title: "Open-source monitoring service",
- description:
- "OpenStatus is an open source alternative to your current monitoring service with beautiful status page",
-};
+const tb = new Tinybird({ token: env.TINY_BIRD_API_KEY });
-export default function Page() {
+export default async function Page() {
+ // REMINDER: to be removed
+ let data = MOCK;
+ if (process.env.NODE_ENV !== "development") {
+ const res = await getResponseList(tb)({});
+ data = res.data;
+ }
return (
-
+
Coming Soon
@@ -26,6 +30,9 @@ export default function Page() {
+
+
+