├── .dockerignore ├── .github ├── FUNDING.yml ├── ISSUE_TEMPLATE │ ├── bug_report.yml │ ├── config.yml │ ├── doc_report.yml │ └── feature_request.yml ├── pull_request_template.md └── workflows │ ├── checker.yml │ ├── deploy-checker.yml │ ├── deploy-workflows.yml │ ├── deploy.yml │ ├── dx.yml │ ├── lint.yml │ ├── migrate.yml │ ├── publish-checker.yml │ ├── synthetic.yml │ └── test.yml ├── .gitignore ├── .npmrc ├── .prettierignore ├── .vscode └── settings.json ├── CONTRIBUTING.MD ├── LICENSE ├── README.md ├── apps ├── checker │ ├── .golangci.yml │ ├── Dockerfile │ ├── README.md │ ├── cmd │ │ └── main.go │ ├── fly.toml │ ├── go.mod │ ├── go.sum │ ├── handlers │ │ ├── checker.go │ │ ├── checker_test.go │ │ ├── handler.go │ │ ├── ping.go │ │ ├── ping_test.go │ │ └── tcp.go │ ├── http.go │ ├── http_test.go │ ├── pkg │ │ ├── assertions │ │ │ ├── assertions.go │ │ │ └── assertions_test.go │ │ ├── logger │ │ │ └── logger.go │ │ ├── otel │ │ │ └── otel.go │ │ └── tinybird │ │ │ ├── client.go │ │ │ └── client_test.go │ ├── request │ │ └── request.go │ ├── tcp.go │ ├── tcp_test.go │ └── update.go ├── docs │ ├── .env.example │ ├── .gitignore │ ├── README.md │ ├── astro.config.mjs │ ├── package.json │ ├── public │ │ ├── favicon.ico │ │ └── fonts │ │ │ ├── CalSans-SemiBold.ttf │ │ │ ├── Inter-Light.ttf │ │ │ ├── Inter-Medium.ttf │ │ │ └── Inter-Regular.ttf │ ├── src │ │ ├── assets │ │ │ ├── cli │ │ │ │ └── CLI.png │ │ │ ├── guides │ │ │ │ ├── how-deploy-checker-koyeb │ │ │ │ │ ├── koyeb-1.png │ │ │ │ │ ├── koyeb-2.png │ │ │ │ │ └── koyeb-3.png │ │ │ │ ├── how-deploy-status-page-cf-pages │ │ │ │ │ └── status-page.png │ │ │ │ └── latency-ci-integration-test │ │ │ │ │ ├── github-api-token.png │ │ │ │ │ └── openstatus-api-token.png │ │ │ ├── houston.webp │ │ │ ├── icon.png │ │ │ ├── incident │ │ │ │ └── incident-detail.png │ │ │ ├── monitor │ │ │ │ ├── assertions.png │ │ │ │ ├── clone-monitor.png │ │ │ │ ├── create-monitor.png │ │ │ │ ├── create-tag.png │ │ │ │ ├── filter-tag.png │ │ │ │ ├── http-monitor.png │ │ │ │ ├── monitor-detail.png │ │ │ │ ├── monitor.png │ │ │ │ ├── notifications.png │ │ │ │ ├── overview.png │ │ │ │ ├── public-monitor.png │ │ │ │ ├── response-log-header.png │ │ │ │ ├── response-log-timing.png │ │ │ │ ├── response-log.png │ │ │ │ ├── setting-public-monitor.png │ │ │ │ └── tcp-monitor.png │ │ │ ├── notification │ │ │ │ ├── discord-notification.png │ │ │ │ ├── opsgenie │ │ │ │ │ ├── opsgenie-1.png │ │ │ │ │ ├── opsgenie-2.png │ │ │ │ │ ├── opsgenie-3.png │ │ │ │ │ ├── opsgenie-4.png │ │ │ │ │ └── opsgenie-5.png │ │ │ │ └── pagerduty │ │ │ │ │ ├── pagerduty-1.png │ │ │ │ │ ├── pagerduty-2.png │ │ │ │ │ └── pagerduty-3.png │ │ │ ├── setup-env │ │ │ │ ├── clerk-step1.png │ │ │ │ ├── clerk-step2.png │ │ │ │ ├── clerk-step3.png │ │ │ │ ├── clerk.png │ │ │ │ ├── drizzle-studio.png │ │ │ │ ├── resend.png │ │ │ │ └── tinybird.png │ │ │ ├── status-page │ │ │ │ ├── create-status-page.png │ │ │ │ ├── description.png │ │ │ │ ├── favicon.png │ │ │ │ ├── status-page-empty.png │ │ │ │ └── status-page.png │ │ │ └── status-widget │ │ │ │ └── widget-example.png │ │ ├── components │ │ │ ├── Footer.astro │ │ │ ├── Head.astro │ │ │ ├── Hero.astro │ │ │ ├── SiteTitle.astro │ │ │ ├── Status.astro │ │ │ └── utils.ts │ │ ├── content │ │ │ ├── config.ts │ │ │ └── docs │ │ │ │ ├── alerting │ │ │ │ ├── overview.mdx │ │ │ │ └── providers │ │ │ │ │ ├── discord.mdx │ │ │ │ │ ├── email.mdx │ │ │ │ │ ├── ntfy.mdx │ │ │ │ │ ├── opsgenie.mdx │ │ │ │ │ ├── pagerduty.mdx │ │ │ │ │ ├── phone-call.mdx │ │ │ │ │ ├── slack.mdx │ │ │ │ │ ├── sms.mdx │ │ │ │ │ ├── telegram.mdx │ │ │ │ │ └── webhook.mdx │ │ │ │ ├── cli │ │ │ │ ├── commands │ │ │ │ │ ├── monitors.mdx │ │ │ │ │ ├── run.mdx │ │ │ │ │ └── whoami.mdx │ │ │ │ └── getting-started.mdx │ │ │ │ ├── contributing │ │ │ │ ├── getting-started.mdx │ │ │ │ ├── requirements.mdx │ │ │ │ └── setup-env.mdx │ │ │ │ ├── getting-started │ │ │ │ └── introduction.mdx │ │ │ │ ├── guides │ │ │ │ ├── how-deploy-checker-koyeb.mdx │ │ │ │ ├── how-deploy-status-page-cf-pages.mdx │ │ │ │ ├── how-to-run-synthetic-test-github-action.mdx │ │ │ │ └── introduction.mdx │ │ │ │ ├── help │ │ │ │ └── support.mdx │ │ │ │ ├── incident │ │ │ │ ├── incident-detail.mdx │ │ │ │ ├── overview.mdx │ │ │ │ └── work-with-incident.mdx │ │ │ │ ├── index.mdx │ │ │ │ ├── logo │ │ │ │ ├── OpenStatus-dark.svg │ │ │ │ └── OpenStatus-light.svg │ │ │ │ ├── monitoring │ │ │ │ ├── clone-monitor.mdx │ │ │ │ ├── create-monitor.mdx │ │ │ │ ├── customization │ │ │ │ │ ├── assertions.mdx │ │ │ │ │ ├── frequency.mdx │ │ │ │ │ ├── locations.mdx │ │ │ │ │ ├── notification.mdx │ │ │ │ │ └── timing.mdx │ │ │ │ ├── group-monitor-tag.mdx │ │ │ │ ├── monitor-data-collected.mdx │ │ │ │ ├── opentelemetry.mdx │ │ │ │ ├── overview.mdx │ │ │ │ └── type │ │ │ │ │ ├── http.mdx │ │ │ │ │ └── tcp.mdx │ │ │ │ ├── status-page │ │ │ │ ├── advanced │ │ │ │ │ ├── badge.mdx │ │ │ │ │ ├── custom-domain.mdx │ │ │ │ │ ├── description.mdx │ │ │ │ │ ├── icon.mdx │ │ │ │ │ ├── monitors.mdx │ │ │ │ │ ├── password.mdx │ │ │ │ │ └── widget.mdx │ │ │ │ ├── create-status-page.mdx │ │ │ │ ├── overview.mdx │ │ │ │ └── work │ │ │ │ │ ├── color-status-bar.mdx │ │ │ │ │ ├── maintenances.mdx │ │ │ │ │ ├── reports.mdx │ │ │ │ │ └── subscribers.mdx │ │ │ │ └── tools │ │ │ │ ├── react.mdx │ │ │ │ ├── status-widget.mdx │ │ │ │ └── terraform.mdx │ │ ├── custom.css │ │ ├── env.d.ts │ │ └── tailwind.css │ ├── tailwind.config.mjs │ └── tsconfig.json ├── screenshot-service │ ├── .dockerignore │ ├── .gitignore │ ├── Dockerfile │ ├── README.md │ ├── fly.toml │ ├── package.json │ ├── src │ │ ├── env.ts │ │ └── index.ts │ └── tsconfig.json ├── server │ ├── .dockerignore │ ├── .env.example │ ├── .env.test │ ├── .gitignore │ ├── Dockerfile │ ├── README.md │ ├── dofigen.lock │ ├── dofigen.yml │ ├── env.ts │ ├── fly.sh │ ├── fly.toml │ ├── log │ │ └── fly.toml │ ├── package.json │ ├── src │ │ ├── env.ts │ │ ├── index.ts │ │ ├── libs │ │ │ ├── cache │ │ │ │ ├── index.ts │ │ │ │ └── memory.ts │ │ │ ├── checker │ │ │ │ ├── index.ts │ │ │ │ └── utils.ts │ │ │ ├── errors │ │ │ │ ├── index.ts │ │ │ │ ├── openapi-error-responses.ts │ │ │ │ └── utils.ts │ │ │ ├── middlewares │ │ │ │ ├── auth.ts │ │ │ │ ├── index.ts │ │ │ │ ├── plan.ts │ │ │ │ └── track.ts │ │ │ └── test │ │ │ │ └── preload.ts │ │ ├── routes │ │ │ ├── public │ │ │ │ ├── index.ts │ │ │ │ └── status.ts │ │ │ └── v1 │ │ │ │ ├── check │ │ │ │ ├── http │ │ │ │ │ ├── post.test.ts │ │ │ │ │ ├── post.ts │ │ │ │ │ └── schema.ts │ │ │ │ └── index.ts │ │ │ │ ├── incidents │ │ │ │ ├── get.test.ts │ │ │ │ ├── get.ts │ │ │ │ ├── get_all.test.ts │ │ │ │ ├── get_all.ts │ │ │ │ ├── index.ts │ │ │ │ ├── put.test.ts │ │ │ │ ├── put.ts │ │ │ │ └── schema.ts │ │ │ │ ├── index.ts │ │ │ │ ├── maintenances │ │ │ │ ├── get.test.ts │ │ │ │ ├── get.ts │ │ │ │ ├── get_all.test.ts │ │ │ │ ├── get_all.ts │ │ │ │ ├── index.ts │ │ │ │ ├── post.test.ts │ │ │ │ ├── post.ts │ │ │ │ ├── put.test.ts │ │ │ │ ├── put.ts │ │ │ │ └── schema.ts │ │ │ │ ├── monitors │ │ │ │ ├── delete.test.ts │ │ │ │ ├── delete.ts │ │ │ │ ├── get.test.ts │ │ │ │ ├── get.ts │ │ │ │ ├── get_all.test.ts │ │ │ │ ├── get_all.ts │ │ │ │ ├── index.ts │ │ │ │ ├── post.test.ts │ │ │ │ ├── post.ts │ │ │ │ ├── put.test.ts │ │ │ │ ├── put.ts │ │ │ │ ├── results │ │ │ │ │ └── get.ts │ │ │ │ ├── run │ │ │ │ │ ├── post.ts │ │ │ │ │ └── schema.ts │ │ │ │ ├── schema.ts │ │ │ │ ├── summary │ │ │ │ │ ├── get.test.ts │ │ │ │ │ ├── get.ts │ │ │ │ │ └── schema.ts │ │ │ │ ├── trigger │ │ │ │ │ ├── post.ts │ │ │ │ │ └── schema.ts │ │ │ │ └── utils.ts │ │ │ │ ├── notifications │ │ │ │ ├── get.test.ts │ │ │ │ ├── get.ts │ │ │ │ ├── get_all.test.ts │ │ │ │ ├── get_all.ts │ │ │ │ ├── index.ts │ │ │ │ ├── post.test.ts │ │ │ │ ├── post.ts │ │ │ │ └── schema.ts │ │ │ │ ├── pageSubscribers │ │ │ │ ├── index.ts │ │ │ │ ├── post.test.ts │ │ │ │ ├── post.ts │ │ │ │ └── schema.ts │ │ │ │ ├── pages │ │ │ │ ├── get.test.ts │ │ │ │ ├── get.ts │ │ │ │ ├── get_all.test.ts │ │ │ │ ├── get_all.ts │ │ │ │ ├── index.ts │ │ │ │ ├── post.test.ts │ │ │ │ ├── post.ts │ │ │ │ ├── put.test.ts │ │ │ │ ├── put.ts │ │ │ │ └── schema.ts │ │ │ │ ├── statusReportUpdates │ │ │ │ ├── get.test.ts │ │ │ │ ├── get.ts │ │ │ │ ├── index.ts │ │ │ │ ├── post.test.ts │ │ │ │ ├── post.ts │ │ │ │ └── schema.ts │ │ │ │ ├── statusReports │ │ │ │ ├── delete.test.ts │ │ │ │ ├── delete.ts │ │ │ │ ├── get.test.ts │ │ │ │ ├── get.ts │ │ │ │ ├── get_all.test.ts │ │ │ │ ├── get_all.ts │ │ │ │ ├── index.ts │ │ │ │ ├── post.test.ts │ │ │ │ ├── post.ts │ │ │ │ ├── schema.ts │ │ │ │ └── update │ │ │ │ │ └── post.ts │ │ │ │ ├── utils.ts │ │ │ │ └── whoami │ │ │ │ ├── get.test.ts │ │ │ │ ├── get.ts │ │ │ │ ├── index.ts │ │ │ │ └── schema.ts │ │ ├── types │ │ │ └── index.ts │ │ └── utils │ │ │ ├── audit-log.ts │ │ │ ├── not-empty.ts │ │ │ └── random-promise.ts │ └── tsconfig.json ├── web │ ├── .env.example │ ├── .gitignore │ ├── README.md │ ├── components.json │ ├── content-collections.ts │ ├── env.ts │ ├── next-env.d.ts │ ├── next.config.js │ ├── package.json │ ├── postcss.config.js │ ├── public │ │ └── assets │ │ │ ├── alternatives │ │ │ ├── betterstack.png │ │ │ ├── checkly.png │ │ │ ├── uptime-kuma.png │ │ │ └── uptime-robot.png │ │ │ ├── authors │ │ │ ├── max.png │ │ │ └── thibault.jpeg │ │ │ ├── changelog │ │ │ ├── CLI.png │ │ │ ├── Otel.png │ │ │ ├── auto-resolved-incidents.png │ │ │ ├── check-api.png │ │ │ ├── checker-playground.png │ │ │ ├── clone-monitor.png │ │ │ ├── content-type.png │ │ │ ├── curl-builder-playground.png │ │ │ ├── dark-theme-support.png │ │ │ ├── dashboard-metrics-card.png │ │ │ ├── docker-checker.png │ │ │ ├── github-action.png │ │ │ ├── golang-monitor-checker.png │ │ │ ├── individual-status-report-page.png │ │ │ ├── latency-quantiles.png │ │ │ ├── maintenance-status.png │ │ │ ├── monitor-tags.png │ │ │ ├── monitor-threshold.png │ │ │ ├── more-regions.png │ │ │ ├── multi-region-monitoring.png │ │ │ ├── ntfy.png │ │ │ ├── pagerduty-integration.png │ │ │ ├── password-protected-status-page.png │ │ │ ├── play-checker-improvements.png │ │ │ ├── public-monitors.png │ │ │ ├── raycast-integration.png │ │ │ ├── request-assertions.png │ │ │ ├── response-time-charts.png │ │ │ ├── screenshot-incident.png │ │ │ ├── slack-discord-notification.png │ │ │ ├── sms-notification.png │ │ │ ├── status-page-badge.jpeg │ │ │ ├── status-page-colors-and-more.png │ │ │ ├── status-page-feed.png │ │ │ ├── status-page-monitor-order.png │ │ │ ├── status-page-monitor-values-visibility.png │ │ │ ├── status-page-subscribers.png │ │ │ ├── status-report-location-change.png │ │ │ ├── status-update-subscriber.png │ │ │ ├── status-widget.png │ │ │ ├── tcp-request.png │ │ │ ├── team-invites.png │ │ │ ├── terraform.png │ │ │ └── webhook.png │ │ │ ├── checker │ │ │ └── glauber.png │ │ │ ├── logos │ │ │ ├── OpenStatus.png │ │ │ └── OpenStatus.svg │ │ │ ├── og │ │ │ └── dashboard.png │ │ │ ├── partners │ │ │ ├── documenso.svg │ │ │ ├── hanko.svg │ │ │ └── midday.svg │ │ │ └── posts │ │ │ ├── 2023-year-review │ │ │ ├── blog-hn.png │ │ │ ├── github-stars.png │ │ │ ├── monitors-per-week.png │ │ │ ├── mrr.png │ │ │ ├── pages-per-week.png │ │ │ ├── search-console.png │ │ │ ├── show-hn.png │ │ │ ├── tinybird.png │ │ │ ├── title.png │ │ │ ├── users-per-week.png │ │ │ └── visitors.png │ │ │ ├── data-table-redesign │ │ │ ├── after.png │ │ │ ├── before.png │ │ │ └── toolbox.png │ │ │ ├── dynamic-breadcrumb-nextjs │ │ │ └── breadcrumb.png │ │ │ ├── event-analytics-implementation │ │ │ └── event-analytics-implementation.png │ │ │ ├── github-trending-list.png │ │ │ ├── how-we-build-our-github-action │ │ │ └── GitHub.png │ │ │ ├── infra-openstatus │ │ │ ├── hosting.png │ │ │ ├── queue.png │ │ │ └── tech-infra.png │ │ │ ├── introducing-goatstack │ │ │ ├── bsky-post.png │ │ │ └── goat.png │ │ │ ├── live-mode-infinite-query │ │ │ ├── infinite-query.png │ │ │ ├── offset-caveat.png │ │ │ └── tanstack.png │ │ │ ├── migration-auth-clerk-to-next-auth │ │ │ ├── authjs.png │ │ │ └── title.png │ │ │ ├── migration-backend-from-vercel-to-fly │ │ │ ├── fly-dashboard.png │ │ │ ├── fly.png │ │ │ ├── hono-server.png │ │ │ └── next-server.png │ │ │ ├── migration-planetscale-to-turso │ │ │ ├── planetscale-latency.png │ │ │ ├── turso-latency.png │ │ │ └── turso.png │ │ │ ├── monitoring-latency │ │ │ ├── all-hosting-providers.png │ │ │ ├── cloudflare.json │ │ │ ├── fly-api.png │ │ │ ├── fly.json │ │ │ ├── koyeb.json │ │ │ ├── monitor-cloudflare-workers.png │ │ │ ├── monitor-fly.png │ │ │ ├── monitor-koyeb.png │ │ │ ├── monitor-railway.png │ │ │ ├── monitor-render.png │ │ │ ├── railway.json │ │ │ └── render.json │ │ │ ├── monitoring-vercel │ │ │ ├── serverless-vs-edge.png │ │ │ ├── vercel-cold.json │ │ │ ├── vercel-edge.json │ │ │ ├── vercel-roulette.json │ │ │ └── vercel-warm.json │ │ │ ├── openstatus-light-viewer │ │ │ ├── data-table-popover.png │ │ │ └── light-viewer.png │ │ │ ├── our-new-pricing-explained │ │ │ ├── ahref.png │ │ │ └── pricing-hard.png │ │ │ ├── pricing-update-july-2024 │ │ │ └── pricing.png │ │ │ ├── q1-2024-update │ │ │ ├── chart.png │ │ │ └── q1-2024-update.png │ │ │ ├── reflecting-1-year-building-openstatus │ │ │ ├── first-year.png │ │ │ ├── image.png │ │ │ ├── twitter.png │ │ │ ├── us.png │ │ │ └── users.png │ │ │ ├── secure-api-with-unkey │ │ │ ├── unkey-landing-old.png │ │ │ ├── unkey-landing.png │ │ │ └── unkey.png │ │ │ ├── the-first-48-hours │ │ │ ├── 48.png │ │ │ ├── enough-gas-workspace-slug.png │ │ │ ├── qstash-usage.png │ │ │ ├── vercel-usage.png │ │ │ └── wet-grandmother-workspace-slug.png │ │ │ └── vision-2025 │ │ │ └── vision-2025.png │ ├── sentry.client.config.ts │ ├── sentry.edge.config.ts │ ├── sentry.server.config.ts │ ├── src │ │ ├── app │ │ │ ├── (content) │ │ │ │ ├── (landing) │ │ │ │ │ └── [slug] │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── _components │ │ │ │ │ └── pagination.tsx │ │ │ │ ├── blog │ │ │ │ │ ├── [slug] │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── feed.xml │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── search-params.ts │ │ │ │ ├── changelog │ │ │ │ │ ├── [slug] │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── feed.xml │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── search-params.ts │ │ │ │ ├── compare │ │ │ │ │ ├── [slug] │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── _components │ │ │ │ │ │ └── comparison-table.tsx │ │ │ │ │ └── page.tsx │ │ │ │ └── layout.tsx │ │ │ ├── (redirect) │ │ │ │ ├── cal │ │ │ │ │ └── page.tsx │ │ │ │ ├── discord │ │ │ │ │ └── page.tsx │ │ │ │ ├── docs │ │ │ │ │ └── page.tsx │ │ │ │ ├── github │ │ │ │ │ └── page.tsx │ │ │ │ ├── linkedin │ │ │ │ │ └── page.tsx │ │ │ │ ├── schema.json │ │ │ │ │ └── page.tsx │ │ │ │ ├── twitter │ │ │ │ │ └── page.tsx │ │ │ │ └── youtube │ │ │ │ │ └── page.tsx │ │ │ ├── _components │ │ │ │ ├── background.tsx │ │ │ │ └── submit-button.tsx │ │ │ ├── about │ │ │ │ ├── _components │ │ │ │ │ └── member.tsx │ │ │ │ └── page.tsx │ │ │ ├── api │ │ │ │ ├── auth │ │ │ │ │ └── [...nextauth] │ │ │ │ │ │ └── route.ts │ │ │ │ ├── callback │ │ │ │ │ └── pagerduty │ │ │ │ │ │ └── route.ts │ │ │ │ ├── checker │ │ │ │ │ ├── cron │ │ │ │ │ │ ├── 10m │ │ │ │ │ │ │ └── route.ts │ │ │ │ │ │ ├── 1h │ │ │ │ │ │ │ └── route.ts │ │ │ │ │ │ ├── 1m │ │ │ │ │ │ │ └── route.ts │ │ │ │ │ │ ├── 30m │ │ │ │ │ │ │ └── route.ts │ │ │ │ │ │ ├── 30s │ │ │ │ │ │ │ └── route.ts │ │ │ │ │ │ ├── 5m │ │ │ │ │ │ │ └── route.ts │ │ │ │ │ │ ├── _cron.ts │ │ │ │ │ │ └── _sentry.ts │ │ │ │ │ ├── test │ │ │ │ │ │ ├── http │ │ │ │ │ │ │ └── route.ts │ │ │ │ │ │ └── tcp │ │ │ │ │ │ │ ├── route.ts │ │ │ │ │ │ │ └── schema.ts │ │ │ │ │ └── utils.ts │ │ │ │ ├── internal │ │ │ │ │ └── email │ │ │ │ │ │ └── route.ts │ │ │ │ ├── og │ │ │ │ │ ├── _components │ │ │ │ │ │ ├── background.tsx │ │ │ │ │ │ ├── basic-layout.tsx │ │ │ │ │ │ ├── status-check.tsx │ │ │ │ │ │ └── tracker.tsx │ │ │ │ │ ├── checker │ │ │ │ │ │ └── route.tsx │ │ │ │ │ ├── monitor │ │ │ │ │ │ └── route.tsx │ │ │ │ │ ├── page │ │ │ │ │ │ └── route.tsx │ │ │ │ │ ├── post │ │ │ │ │ │ └── route.tsx │ │ │ │ │ ├── route.tsx │ │ │ │ │ └── utils.ts │ │ │ │ ├── ping │ │ │ │ │ ├── cold │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── edge │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── route.ts │ │ │ │ │ ├── test │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── vercel │ │ │ │ │ │ └── route.ts │ │ │ │ │ └── warn │ │ │ │ │ │ └── route.ts │ │ │ │ ├── test │ │ │ │ │ └── timeout │ │ │ │ │ │ └── route.ts │ │ │ │ ├── trpc │ │ │ │ │ ├── edge │ │ │ │ │ │ └── [trpc] │ │ │ │ │ │ │ └── route.ts │ │ │ │ │ └── lambda │ │ │ │ │ │ └── [trpc] │ │ │ │ │ │ └── route.ts │ │ │ │ ├── upload │ │ │ │ │ └── route.ts │ │ │ │ └── webhook │ │ │ │ │ └── stripe │ │ │ │ │ └── route.ts │ │ │ ├── app │ │ │ │ ├── (auth) │ │ │ │ │ ├── login │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ ├── actions.ts │ │ │ │ │ │ │ └── magic-link-form.tsx │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ ├── sign-in │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── sign-up │ │ │ │ │ │ └── page.tsx │ │ │ │ ├── [workspaceSlug] │ │ │ │ │ ├── (dashboard) │ │ │ │ │ │ ├── incidents │ │ │ │ │ │ │ ├── (overview) │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ │ └── report-info-banner.tsx │ │ │ │ │ │ │ └── [id] │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── overview │ │ │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ │ │ └── event.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ ├── monitors │ │ │ │ │ │ │ ├── (overview) │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ │ │ ├── [id] │ │ │ │ │ │ │ │ ├── data │ │ │ │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ │ │ │ ├── data-table-wrapper.tsx │ │ │ │ │ │ │ │ │ │ └── download-csv-button.tsx │ │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ │ │ │ ├── details │ │ │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ │ │ │ ├── edit │ │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── overview │ │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── new │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ │ ├── notifications │ │ │ │ │ │ │ ├── (overview) │ │ │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ │ │ └── channel-table.tsx │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── [id] │ │ │ │ │ │ │ │ ├── edit │ │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── new │ │ │ │ │ │ │ │ ├── [channel] │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ └── pagerduty │ │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ ├── settings │ │ │ │ │ │ │ ├── api-token │ │ │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ │ │ ├── actions.ts │ │ │ │ │ │ │ │ │ ├── card.tsx │ │ │ │ │ │ │ │ │ ├── create-form.tsx │ │ │ │ │ │ │ │ │ ├── revoke-button.tsx │ │ │ │ │ │ │ │ │ └── submit-button.tsx │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── appearance │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── billing │ │ │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ │ │ ├── change-plan-button.tsx │ │ │ │ │ │ │ │ │ ├── customer-portal-button.tsx │ │ │ │ │ │ │ │ │ └── plan.tsx │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── general │ │ │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ │ │ └── copy-to-clipboard-button.tsx │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ ├── team │ │ │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ │ │ ├── info-banner.tsx │ │ │ │ │ │ │ │ │ └── invite-button.tsx │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── user │ │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ └── status-pages │ │ │ │ │ │ │ ├── (overview) │ │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ │ └── status-report-button.tsx │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── [id] │ │ │ │ │ │ │ ├── domain │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── edit │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ ├── maintenances │ │ │ │ │ │ │ │ ├── (overview) │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ ├── [maintenanceId] │ │ │ │ │ │ │ │ │ └── edit │ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── new │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ │ ├── reports │ │ │ │ │ │ │ │ ├── (overview) │ │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ ├── [reportId] │ │ │ │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ │ │ │ └── status-update-button.tsx │ │ │ │ │ │ │ │ │ ├── edit │ │ │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ │ ├── overview │ │ │ │ │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ │ │ │ │ └── header.tsx │ │ │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ │ └── new │ │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── subscribers │ │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ │ │ └── new │ │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ │ ├── loading.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── onboarding │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ └── description.tsx │ │ │ │ │ │ ├── layout.tsx │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── worskpace-client-cookie.ts │ │ │ │ ├── invite │ │ │ │ │ ├── _components │ │ │ │ │ │ └── link-cards.tsx │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── search-params.ts │ │ │ │ ├── layout.tsx │ │ │ │ ├── onboarding │ │ │ │ │ └── page.tsx │ │ │ │ └── page.tsx │ │ │ ├── apple-icon.ico │ │ │ ├── favicon.ico │ │ │ ├── global-error.tsx │ │ │ ├── icon.png │ │ │ ├── layout.tsx │ │ │ ├── legal │ │ │ │ └── [slug] │ │ │ │ │ ├── layout.tsx │ │ │ │ │ └── page.tsx │ │ │ ├── not-found.tsx │ │ │ ├── oss-friends │ │ │ │ └── page.tsx │ │ │ ├── page.tsx │ │ │ ├── play │ │ │ │ ├── checker │ │ │ │ │ ├── [id] │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ ├── _components │ │ │ │ │ │ ├── checker-form.tsx │ │ │ │ │ │ ├── checker-play.tsx │ │ │ │ │ │ ├── floating-action.tsx │ │ │ │ │ │ ├── global-monitoring.tsx │ │ │ │ │ │ └── testimonial.tsx │ │ │ │ │ ├── api │ │ │ │ │ │ ├── mock.ts │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── search-params.ts │ │ │ │ ├── curl │ │ │ │ │ ├── _components │ │ │ │ │ │ └── curl-form.tsx │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── search-params.ts │ │ │ │ ├── default.tsx │ │ │ │ ├── layout.tsx │ │ │ │ ├── page.tsx │ │ │ │ └── status │ │ │ │ │ ├── _components │ │ │ │ │ └── status-play.tsx │ │ │ │ │ ├── layout.tsx │ │ │ │ │ └── page.tsx │ │ │ ├── pricing │ │ │ │ └── page.tsx │ │ │ ├── public │ │ │ │ ├── layout.tsx │ │ │ │ └── monitors │ │ │ │ │ └── [id] │ │ │ │ │ ├── loading.tsx │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── search-params.ts │ │ │ ├── robots.ts │ │ │ ├── shared-metadata.ts │ │ │ ├── sitemap.ts │ │ │ ├── status-page │ │ │ │ └── [domain] │ │ │ │ │ ├── _components │ │ │ │ │ ├── actions.ts │ │ │ │ │ ├── footer.tsx │ │ │ │ │ ├── header.tsx │ │ │ │ │ ├── menu.tsx │ │ │ │ │ ├── password-form.tsx │ │ │ │ │ ├── password-protected.tsx │ │ │ │ │ ├── subscribe-button.tsx │ │ │ │ │ └── subscribe-modal.tsx │ │ │ │ │ ├── badge │ │ │ │ │ └── route.tsx │ │ │ │ │ ├── events │ │ │ │ │ ├── page.tsx │ │ │ │ │ ├── report │ │ │ │ │ │ └── [id] │ │ │ │ │ │ │ ├── _components │ │ │ │ │ │ │ └── copy-link-button.tsx │ │ │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── search-params.ts │ │ │ │ │ └── utils.tsx │ │ │ │ │ ├── feed │ │ │ │ │ └── [type] │ │ │ │ │ │ └── route.ts │ │ │ │ │ ├── incidents │ │ │ │ │ ├── [id] │ │ │ │ │ │ └── page.tsx │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── layout.tsx │ │ │ │ │ ├── loading.tsx │ │ │ │ │ ├── maintenances │ │ │ │ │ └── page.tsx │ │ │ │ │ ├── monitors │ │ │ │ │ ├── [id] │ │ │ │ │ │ ├── page.tsx │ │ │ │ │ │ └── search-params.ts │ │ │ │ │ ├── page.tsx │ │ │ │ │ └── search-params.ts │ │ │ │ │ ├── page.tsx │ │ │ │ │ ├── subscribe │ │ │ │ │ └── route.ts │ │ │ │ │ ├── utils.tsx │ │ │ │ │ └── verify │ │ │ │ │ └── [token] │ │ │ │ │ └── route.ts │ │ │ └── status │ │ │ │ ├── page.tsx │ │ │ │ └── utils.ts │ │ ├── components │ │ │ ├── banner │ │ │ │ └── coming-soon-banner.tsx │ │ │ ├── billing │ │ │ │ ├── pro-banner.tsx │ │ │ │ ├── pro-feature-alert.tsx │ │ │ │ ├── pro-feature-badge.tsx │ │ │ │ ├── pro-feature-hover-card.tsx │ │ │ │ └── utils.ts │ │ │ ├── content │ │ │ │ ├── article.tsx │ │ │ │ ├── callout.tsx │ │ │ │ ├── changelog.tsx │ │ │ │ ├── image-with-caption.tsx │ │ │ │ ├── mdx-components.tsx │ │ │ │ ├── mdx.tsx │ │ │ │ ├── pre.tsx │ │ │ │ ├── preview.tsx │ │ │ │ ├── simple-chart.tsx │ │ │ │ └── timeline.tsx │ │ │ ├── dashboard │ │ │ │ ├── container.tsx │ │ │ │ ├── copy-to-clipboard-button.tsx │ │ │ │ ├── empty-state.tsx │ │ │ │ ├── header.tsx │ │ │ │ ├── help-callout.tsx │ │ │ │ ├── info-alert-dialog.tsx │ │ │ │ ├── limit.tsx │ │ │ │ ├── shell.tsx │ │ │ │ ├── tabs-link.tsx │ │ │ │ └── tabs.tsx │ │ │ ├── data-table │ │ │ │ ├── columns.tsx │ │ │ │ ├── data-table-badges.tsx │ │ │ │ ├── data-table-column-header.tsx │ │ │ │ ├── data-table-faceted-filter.tsx │ │ │ │ ├── data-table-faceted-input-dropdown.tsx │ │ │ │ ├── data-table-filter-input.tsx │ │ │ │ ├── data-table-pagination.tsx │ │ │ │ ├── data-table-region-select.tsx │ │ │ │ ├── data-table-row-action.tsx │ │ │ │ ├── data-table-skeleton.tsx │ │ │ │ ├── data-table-status-badge.tsx │ │ │ │ ├── data-table-toolbar-skeleton.tsx │ │ │ │ ├── data-table-toolbar.tsx │ │ │ │ ├── data-table-view-options.tsx │ │ │ │ ├── data-table.tsx │ │ │ │ ├── incident │ │ │ │ │ ├── columns.tsx │ │ │ │ │ ├── data-table-row-actions.tsx │ │ │ │ │ └── data-table.tsx │ │ │ │ ├── invitation │ │ │ │ │ ├── columns.tsx │ │ │ │ │ ├── data-table-row-actions.tsx │ │ │ │ │ └── data-table.tsx │ │ │ │ ├── maintenance │ │ │ │ │ ├── columns.tsx │ │ │ │ │ ├── data-table-row-actions.tsx │ │ │ │ │ └── data-table.tsx │ │ │ │ ├── monitor │ │ │ │ │ ├── columns.tsx │ │ │ │ │ ├── data-table-column-header.tsx │ │ │ │ │ ├── data-table-floating-actions.tsx │ │ │ │ │ ├── data-table-pagination.tsx │ │ │ │ │ ├── data-table-row-actions.tsx │ │ │ │ │ ├── data-table-toolbar.tsx │ │ │ │ │ └── data-table.tsx │ │ │ │ ├── notification │ │ │ │ │ ├── columns.tsx │ │ │ │ │ ├── data-table-row-actions.tsx │ │ │ │ │ └── data-table.tsx │ │ │ │ ├── page-subscriber │ │ │ │ │ ├── columns.tsx │ │ │ │ │ ├── data-table-row-actions.tsx │ │ │ │ │ └── data-table.tsx │ │ │ │ ├── single-region │ │ │ │ │ ├── columns.tsx │ │ │ │ │ ├── data-table-column-header.tsx │ │ │ │ │ └── data-table.tsx │ │ │ │ ├── status-page │ │ │ │ │ ├── columns.tsx │ │ │ │ │ ├── data-table-row-actions.tsx │ │ │ │ │ └── data-table.tsx │ │ │ │ ├── status-report │ │ │ │ │ ├── columns.tsx │ │ │ │ │ ├── data-table-row-actions.tsx │ │ │ │ │ └── data-table.tsx │ │ │ │ └── user │ │ │ │ │ ├── columns.tsx │ │ │ │ │ ├── data-table-row-actions.tsx │ │ │ │ │ └── data-table.tsx │ │ │ ├── dev-mode-container.tsx │ │ │ ├── domains │ │ │ │ ├── domain-configuration.tsx │ │ │ │ └── domain-status-icon.tsx │ │ │ ├── forms │ │ │ │ ├── custom-domain-form.tsx │ │ │ │ ├── maintenance │ │ │ │ │ ├── form.tsx │ │ │ │ │ ├── general.tsx │ │ │ │ │ └── section-connect.tsx │ │ │ │ ├── monitor-tag │ │ │ │ │ └── form.tsx │ │ │ │ ├── monitor │ │ │ │ │ ├── form.tsx │ │ │ │ │ ├── general.tsx │ │ │ │ │ ├── request-test-button.tsx │ │ │ │ │ ├── section-assertions.tsx │ │ │ │ │ ├── section-danger.tsx │ │ │ │ │ ├── section-limits.tsx │ │ │ │ │ ├── section-notifications.tsx │ │ │ │ │ ├── section-otel.tsx │ │ │ │ │ ├── section-request-http.tsx │ │ │ │ │ ├── section-request-tcp.tsx │ │ │ │ │ ├── section-requests.tsx │ │ │ │ │ ├── section-scheduling.tsx │ │ │ │ │ ├── section-status-page.tsx │ │ │ │ │ ├── select-region.tsx │ │ │ │ │ └── tags-multi-box.tsx │ │ │ │ ├── notification │ │ │ │ │ ├── form.tsx │ │ │ │ │ ├── general.tsx │ │ │ │ │ ├── provider │ │ │ │ │ │ ├── actions.ts │ │ │ │ │ │ ├── section-discord.tsx │ │ │ │ │ │ ├── section-email.tsx │ │ │ │ │ │ ├── section-ntfy.tsx │ │ │ │ │ │ ├── section-opsgenie.tsx │ │ │ │ │ │ ├── section-pagerduty.tsx │ │ │ │ │ │ ├── section-slack.tsx │ │ │ │ │ │ ├── section-sms.tsx │ │ │ │ │ │ └── section-webhook.tsx │ │ │ │ │ └── section-connect.tsx │ │ │ │ ├── shared │ │ │ │ │ ├── checkbox-label.tsx │ │ │ │ │ ├── save-button.tsx │ │ │ │ │ └── section-header.tsx │ │ │ │ ├── skeleton-form.tsx │ │ │ │ ├── status-page │ │ │ │ │ ├── form.tsx │ │ │ │ │ ├── general.tsx │ │ │ │ │ ├── section-advanced.tsx │ │ │ │ │ ├── section-danger.tsx │ │ │ │ │ ├── section-monitor.tsx │ │ │ │ │ └── section-visibility.tsx │ │ │ │ ├── status-report-form.tsx │ │ │ │ ├── status-report-update-form.tsx │ │ │ │ ├── status-report-update │ │ │ │ │ ├── form.tsx │ │ │ │ │ ├── general.tsx │ │ │ │ │ ├── section-date.tsx │ │ │ │ │ └── section-message.tsx │ │ │ │ ├── status-report │ │ │ │ │ ├── form.tsx │ │ │ │ │ ├── general.tsx │ │ │ │ │ ├── section-connect.tsx │ │ │ │ │ └── section-update-message.tsx │ │ │ │ └── workspace-form.tsx │ │ │ ├── icons.tsx │ │ │ ├── kbd.tsx │ │ │ ├── layout │ │ │ │ ├── app-footer.tsx │ │ │ │ ├── app-link.tsx │ │ │ │ ├── app-menu.tsx │ │ │ │ ├── app-page-layout.tsx │ │ │ │ ├── app-page-with-sidebar-layout.tsx │ │ │ │ ├── app-sidebar.tsx │ │ │ │ ├── back-button.tsx │ │ │ │ ├── brand-name.tsx │ │ │ │ ├── header │ │ │ │ │ ├── app-header.tsx │ │ │ │ │ ├── app-tabs.tsx │ │ │ │ │ ├── breadcrumbs.tsx │ │ │ │ │ ├── copy-button.tsx │ │ │ │ │ └── user-nav.tsx │ │ │ │ ├── login-button.tsx │ │ │ │ ├── marketing-footer.tsx │ │ │ │ ├── marketing-header.tsx │ │ │ │ ├── marketing-layout.tsx │ │ │ │ ├── marketing-menu.tsx │ │ │ │ ├── public-header.tsx │ │ │ │ ├── public-layout.tsx │ │ │ │ ├── skeleton-tabs.tsx │ │ │ │ ├── social-icon-button.tsx │ │ │ │ └── status-widget-suspense.tsx │ │ │ ├── loading-animation.tsx │ │ │ ├── marketing │ │ │ │ ├── alert │ │ │ │ │ ├── card.tsx │ │ │ │ │ └── timeline.tsx │ │ │ │ ├── banner │ │ │ │ │ ├── booking-banner.tsx │ │ │ │ │ ├── enterprise-banner.tsx │ │ │ │ │ ├── generic-banner.tsx │ │ │ │ │ └── speed-banner.tsx │ │ │ │ ├── card.tsx │ │ │ │ ├── faqs.tsx │ │ │ │ ├── feature │ │ │ │ │ ├── assertions-timing-form-example.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ ├── interactive-feature.tsx │ │ │ │ │ ├── mock.ts │ │ │ │ │ ├── notifications-form-example.tsx │ │ │ │ │ ├── raycast-example.tsx │ │ │ │ │ └── tracker-example.tsx │ │ │ │ ├── hero.tsx │ │ │ │ ├── in-between-cta.tsx │ │ │ │ ├── lastest-changelogs.tsx │ │ │ │ ├── monitor │ │ │ │ │ ├── card.tsx │ │ │ │ │ └── globe.tsx │ │ │ │ ├── partners.tsx │ │ │ │ ├── pricing │ │ │ │ │ ├── enterprice-plan.tsx │ │ │ │ │ ├── pricing-plan-radio.tsx │ │ │ │ │ ├── pricing-slider.tsx │ │ │ │ │ ├── pricing-table.tsx │ │ │ │ │ └── pricing-wrapper.tsx │ │ │ │ ├── speed-checker-button.tsx │ │ │ │ ├── stats.tsx │ │ │ │ └── status-page │ │ │ │ │ ├── card.tsx │ │ │ │ │ └── tracker-example.tsx │ │ │ ├── modals │ │ │ │ └── failed-ping-alert-confirmation.tsx │ │ │ ├── monitor-charts │ │ │ │ ├── chart-wrapper.tsx │ │ │ │ ├── chart.tsx │ │ │ │ ├── combined-chart-wrapper.tsx │ │ │ │ ├── region-table.tsx │ │ │ │ ├── simple-chart-wrapper.tsx │ │ │ │ ├── simple-chart.tsx │ │ │ │ └── utils.tsx │ │ │ ├── monitor-dashboard │ │ │ │ ├── button-reset.tsx │ │ │ │ ├── date-picker-preset.tsx │ │ │ │ ├── interval-preset.tsx │ │ │ │ ├── metrics-card.tsx │ │ │ │ ├── metrics.tsx │ │ │ │ ├── pause-button.tsx │ │ │ │ ├── quantile-preset.tsx │ │ │ │ ├── region-preset.tsx │ │ │ │ ├── response-details.tsx │ │ │ │ └── search-params-preset.tsx │ │ │ ├── monitor │ │ │ │ ├── job-type-icon-with-tooltip.tsx │ │ │ │ ├── notification-icon-with-tooltip.tsx │ │ │ │ ├── status-code-badge.tsx │ │ │ │ ├── status-dot-with-tooltip.tsx │ │ │ │ ├── status-dot.tsx │ │ │ │ ├── tag-badge-with-tooltip.tsx │ │ │ │ ├── tag-badge.tsx │ │ │ │ ├── trigger-icon-with-tooltip.tsx │ │ │ │ └── visible-icon-with-tooltip.tsx │ │ │ ├── ping-response-analysis │ │ │ │ ├── columns.tsx │ │ │ │ ├── config.ts │ │ │ │ ├── copy-link-button.tsx │ │ │ │ ├── copy-to-clipboard-button.tsx │ │ │ │ ├── data-table-collapse-button.tsx │ │ │ │ ├── multi-region-chart.tsx │ │ │ │ ├── multi-region-table.tsx │ │ │ │ ├── multi-region-tabs.tsx │ │ │ │ ├── region-info.tsx │ │ │ │ ├── response-assertion.tsx │ │ │ │ ├── response-detail-tabs.tsx │ │ │ │ ├── response-header-analysis.tsx │ │ │ │ ├── response-header-table.tsx │ │ │ │ ├── response-timing-table.tsx │ │ │ │ └── utils.ts │ │ │ ├── play │ │ │ │ └── card.tsx │ │ │ ├── status-page │ │ │ │ ├── datetime-tooltip.tsx │ │ │ │ ├── day-header.tsx │ │ │ │ ├── feed.tsx │ │ │ │ ├── maintenance.tsx │ │ │ │ ├── monitor-list.tsx │ │ │ │ ├── monitor.tsx │ │ │ │ ├── process-message.tsx │ │ │ │ ├── status-check.tsx │ │ │ │ └── status-report.tsx │ │ │ ├── status-update │ │ │ │ ├── delete-status-update.tsx │ │ │ │ ├── edit-status-update.tsx │ │ │ │ ├── events.tsx │ │ │ │ ├── status-badge.tsx │ │ │ │ └── summary.tsx │ │ │ ├── support │ │ │ │ ├── action.ts │ │ │ │ ├── bubble.tsx │ │ │ │ └── contact-form.tsx │ │ │ ├── svg │ │ │ │ ├── documenso.tsx │ │ │ │ ├── hanko.tsx │ │ │ │ └── midday.tsx │ │ │ ├── tailwind-indicator.tsx │ │ │ ├── templates │ │ │ │ └── email-template.tsx │ │ │ ├── theme-provider.tsx │ │ │ ├── theme │ │ │ │ ├── theme-icon.tsx │ │ │ │ └── theme-toggle.tsx │ │ │ ├── tracker │ │ │ │ └── tracker.tsx │ │ │ ├── ui │ │ │ │ └── sonner.tsx │ │ │ └── workspace │ │ │ │ └── select-workspace.tsx │ │ ├── config │ │ │ ├── alternatives.ts │ │ │ ├── features.ts │ │ │ ├── landings.tsx │ │ │ ├── pages.ts │ │ │ ├── pricing-table.tsx │ │ │ └── socials.ts │ │ ├── content │ │ │ ├── changelog │ │ │ │ ├── auto-resolved-incidents.mdx │ │ │ │ ├── binary-payload.mdx │ │ │ │ ├── check-run-api.mdx │ │ │ │ ├── checker-playground.mdx │ │ │ │ ├── clone-monitor.mdx │ │ │ │ ├── curl-builder-playground.mdx │ │ │ │ ├── dark-theme-support.mdx │ │ │ │ ├── dashboard-metrics-card.mdx │ │ │ │ ├── docker-checker.mdx │ │ │ │ ├── github-action.mdx │ │ │ │ ├── golang-monitor-checker.mdx │ │ │ │ ├── individual-status-report-page.mdx │ │ │ │ ├── latency-quantiles.mdx │ │ │ │ ├── maintenance-status.mdx │ │ │ │ ├── monitor-tags.mdx │ │ │ │ ├── monitor-threshold.mdx │ │ │ │ ├── more-regions.mdx │ │ │ │ ├── multi-region-monitoring.mdx │ │ │ │ ├── ntfy-sh-integration.mdx │ │ │ │ ├── openstatus-cli.mdx │ │ │ │ ├── opentelemetry.mdx │ │ │ │ ├── pagerduty-integration.mdx │ │ │ │ ├── password-protected-status-page.mdx │ │ │ │ ├── play-checker-improvements.mdx │ │ │ │ ├── public-monitors.mdx │ │ │ │ ├── raycast-integration.mdx │ │ │ │ ├── request-assertions.mdx │ │ │ │ ├── response-time-charts.mdx │ │ │ │ ├── screenshot-incident.mdx │ │ │ │ ├── slack-discord-notification.mdx │ │ │ │ ├── sms-notification.mdx │ │ │ │ ├── status-page-badge.mdx │ │ │ │ ├── status-page-colors-and-more.mdx │ │ │ │ ├── status-page-feed.mdx │ │ │ │ ├── status-page-monitor-order.mdx │ │ │ │ ├── status-page-monitor-values-visibility.mdx │ │ │ │ ├── status-page-subscribers.mdx │ │ │ │ ├── status-report-location-change.mdx │ │ │ │ ├── status-update-subscriber.mdx │ │ │ │ ├── status-widget.mdx │ │ │ │ ├── tcp-monitoring.mdx │ │ │ │ ├── team-invites.mdx │ │ │ │ ├── terraform-provider.mdx │ │ │ │ └── webhook-integration.mdx │ │ │ ├── faq │ │ │ │ ├── about-us.mdx │ │ │ │ ├── functioning.mdx │ │ │ │ ├── help.mdx │ │ │ │ ├── limits.mdx │ │ │ │ └── supported-regions.mdx │ │ │ ├── legal │ │ │ │ ├── privacy.mdx │ │ │ │ └── terms.mdx │ │ │ ├── posts │ │ │ │ ├── 2023-year-review.mdx │ │ │ │ ├── data-table-redesign.mdx │ │ │ │ ├── dynamic-breadcrumb-nextjs.mdx │ │ │ │ ├── event-analytics-implementation.mdx │ │ │ │ ├── how-we-build-our-github-action.mdx │ │ │ │ ├── introducing-goatstack.mdx │ │ │ │ ├── live-mode-infinite-query.mdx │ │ │ │ ├── migration-auth-clerk-to-next-auth.mdx │ │ │ │ ├── migration-backend-from-vercel-to-fly.mdx │ │ │ │ ├── migration-planetscale-to-turso.mdx │ │ │ │ ├── monitoring-latency-cf-workers-fly-koyeb-raylway-render.mdx │ │ │ │ ├── monitoring-latency-vercel-edge-vs-serverless.mdx │ │ │ │ ├── openstatus-infra.mdx │ │ │ │ ├── openstatus-light-viewer.mdx │ │ │ │ ├── our-new-pricing-explained.mdx │ │ │ │ ├── pricing-update-july-2024.mdx │ │ │ │ ├── q1-2024-update.mdx │ │ │ │ ├── reflecting-1-year-building-openstatus.mdx │ │ │ │ ├── secure-api-with-unkey.mdx │ │ │ │ ├── the-first-48-hours.mdx │ │ │ │ └── vision-2025.mdx │ │ │ └── unrelated │ │ │ │ ├── ci-cd-features-block.mdx │ │ │ │ ├── cli-block.mdx │ │ │ │ ├── github-action-block.mdx │ │ │ │ ├── otel-block.mdx │ │ │ │ ├── our-story.mdx │ │ │ │ └── terraform-provider-block.mdx │ │ ├── data │ │ │ ├── code-dictionary.ts │ │ │ ├── incidents-dictionary.ts │ │ │ └── trigger-dictionary.ts │ │ ├── env.ts │ │ ├── hooks │ │ │ ├── use-cookie-state.ts │ │ │ ├── use-copy-to-clipboard.ts │ │ │ ├── use-debounce.ts │ │ │ ├── use-domain-status.ts │ │ │ ├── use-media-query.ts │ │ │ ├── use-mouse-move.tsx │ │ │ ├── use-preprocessor.tsx │ │ │ ├── use-update-search-params.ts │ │ │ ├── use-window-scroll.ts │ │ │ └── use-window-size.ts │ │ ├── instrumentation.ts │ │ ├── lib │ │ │ ├── auth │ │ │ │ ├── adapter.ts │ │ │ │ ├── helpers.ts │ │ │ │ ├── index.ts │ │ │ │ └── providers.ts │ │ │ ├── domains.ts │ │ │ ├── github.ts │ │ │ ├── maintenances │ │ │ │ └── utils.ts │ │ │ ├── monitor │ │ │ │ └── utils.ts │ │ │ ├── preferred-settings │ │ │ │ ├── client.ts │ │ │ │ ├── server.ts │ │ │ │ ├── shared.ts │ │ │ │ └── validation.ts │ │ │ ├── stream.ts │ │ │ ├── stripe │ │ │ │ └── client.ts │ │ │ ├── tb.ts │ │ │ ├── timezone.ts │ │ │ ├── toast.tsx │ │ │ └── utils.ts │ │ ├── middleware.ts │ │ ├── next-auth.d.ts │ │ ├── public │ │ │ └── fonts │ │ │ │ ├── CalSans-SemiBold.ttf │ │ │ │ ├── Inter-Light.ttf │ │ │ │ ├── Inter-Medium.ttf │ │ │ │ └── Inter-Regular.ttf │ │ ├── react-table.d.ts │ │ ├── styles │ │ │ └── globals.css │ │ ├── trpc │ │ │ ├── client.ts │ │ │ ├── query-client.ts │ │ │ ├── rq-client.tsx │ │ │ ├── rq-server.ts │ │ │ ├── server.ts │ │ │ └── shared.ts │ │ └── types │ │ │ └── utils.ts │ ├── tailwind.config.ts │ ├── tsconfig.json │ └── vercel.json └── workflows │ ├── .dockerignore │ ├── .env.test │ ├── .gitignore │ ├── Dockerfile │ ├── README.md │ ├── dofigen.lock │ ├── dofigen.yml │ ├── fly.toml │ ├── package.json │ ├── src │ ├── checker │ │ ├── alerting.test.ts │ │ ├── alerting.ts │ │ ├── index.ts │ │ └── utils.ts │ ├── cron │ │ ├── checker.ts │ │ ├── emails.ts │ │ ├── index.ts │ │ └── monitor.ts │ ├── env.ts │ ├── index.ts │ ├── scripts │ │ └── tinybird.ts │ └── utils │ │ └── audit-log.ts │ └── tsconfig.json ├── biome.jsonc ├── config.openstatus.yaml ├── devbox.json ├── devbox.lock ├── knip.ts ├── package.json ├── packages ├── analytics │ ├── .env.example │ ├── env.ts │ ├── package.json │ ├── src │ │ ├── events.ts │ │ ├── index.ts │ │ ├── server.ts │ │ └── utils.ts │ └── tsconfig.json ├── api │ ├── .env.test │ ├── index.ts │ ├── package.json │ ├── src │ │ ├── edge.ts │ │ ├── env.ts │ │ ├── lambda.ts │ │ ├── root.ts │ │ ├── router │ │ │ ├── domain.ts │ │ │ ├── email │ │ │ │ └── index.ts │ │ │ ├── incident.ts │ │ │ ├── integration.ts │ │ │ ├── invitation.ts │ │ │ ├── maintenance.ts │ │ │ ├── monitor.ts │ │ │ ├── monitorTag.ts │ │ │ ├── notification.ts │ │ │ ├── page.test.ts │ │ │ ├── page.ts │ │ │ ├── pageSubscriber.ts │ │ │ ├── statusReport.ts │ │ │ ├── stripe │ │ │ │ ├── index.ts │ │ │ │ ├── shared.ts │ │ │ │ ├── utils.ts │ │ │ │ └── webhook.ts │ │ │ ├── tinybird │ │ │ │ └── index.ts │ │ │ ├── user.ts │ │ │ ├── workspace.test.ts │ │ │ └── workspace.ts │ │ └── trpc.ts │ └── tsconfig.json ├── assertions │ ├── README.md │ ├── package.json │ ├── src │ │ ├── dictionary.ts │ │ ├── index.ts │ │ ├── serializing.ts │ │ ├── types.ts │ │ └── v1.ts │ └── tsconfig.json ├── db │ ├── .env.example │ ├── README.md │ ├── drizzle.config.ts │ ├── drizzle │ │ ├── 0000_lively_master_chief.sql │ │ ├── 0001_brainy_beast.sql │ │ ├── 0002_luxuriant_ser_duncan.sql │ │ ├── 0003_glamorous_living_mummy.sql │ │ ├── 0004_fixed_dakota_north.sql │ │ ├── 0005_even_baron_strucker.sql │ │ ├── 0006_tired_anita_blake.sql │ │ ├── 0007_complex_frog_thor.sql │ │ ├── 0008_overjoyed_sunset_bain.sql │ │ ├── 0009_small_maximus.sql │ │ ├── 0010_lame_songbird.sql │ │ ├── 0011_bright_jazinda.sql │ │ ├── 0012_tan_magma.sql │ │ ├── 0013_tired_paladin.sql │ │ ├── 0014_adorable_skaar.sql │ │ ├── 0015_bent_sister_grimm.sql │ │ ├── 0016_certain_praxagora.sql │ │ ├── 0017_loose_maggott.sql │ │ ├── 0018_neat_orphan.sql │ │ ├── 0019_dashing_malcolm_colcord.sql │ │ ├── 0020_flat_bedlam.sql │ │ ├── 0021_reflective_nico_minoru.sql │ │ ├── 0022_chunky_rockslide.sql │ │ ├── 0023_dry_blink.sql │ │ ├── 0024_young_proudstar.sql │ │ ├── 0025_strong_thunderball.sql │ │ ├── 0026_giant_absorbing_man.sql │ │ ├── 0027_bizarre_bastion.sql │ │ ├── 0028_thin_power_pack.sql │ │ ├── 0029_regular_marrow.sql │ │ ├── 0030_elite_barracuda.sql │ │ ├── 0031_lowly_gabe_jones.sql │ │ ├── 0032_hot_swordsman.sql │ │ ├── 0033_solid_colossus.sql │ │ ├── 0034_serious_shard.sql │ │ ├── 0035_open_the_professor.sql │ │ ├── 0036_gifted_deathbird.sql │ │ ├── 0037_equal_beyonder.sql │ │ ├── 0038_foamy_stardust.sql │ │ ├── 0039_lonely_jigsaw.sql │ │ ├── 0040_narrow_anthem.sql │ │ ├── 0041_nasty_jigsaw.sql │ │ ├── 0042_great_epoch.sql │ │ ├── 0043_low_lily_hollister.sql │ │ └── meta │ │ │ ├── 0000_snapshot.json │ │ │ ├── 0001_snapshot.json │ │ │ ├── 0002_snapshot.json │ │ │ ├── 0003_snapshot.json │ │ │ ├── 0004_snapshot.json │ │ │ ├── 0005_snapshot.json │ │ │ ├── 0006_snapshot.json │ │ │ ├── 0007_snapshot.json │ │ │ ├── 0008_snapshot.json │ │ │ ├── 0009_snapshot.json │ │ │ ├── 0010_snapshot.json │ │ │ ├── 0011_snapshot.json │ │ │ ├── 0012_snapshot.json │ │ │ ├── 0013_snapshot.json │ │ │ ├── 0014_snapshot.json │ │ │ ├── 0015_snapshot.json │ │ │ ├── 0016_snapshot.json │ │ │ ├── 0017_snapshot.json │ │ │ ├── 0018_snapshot.json │ │ │ ├── 0019_snapshot.json │ │ │ ├── 0020_snapshot.json │ │ │ ├── 0021_snapshot.json │ │ │ ├── 0022_snapshot.json │ │ │ ├── 0023_snapshot.json │ │ │ ├── 0024_snapshot.json │ │ │ ├── 0025_snapshot.json │ │ │ ├── 0026_snapshot.json │ │ │ ├── 0027_snapshot.json │ │ │ ├── 0028_snapshot.json │ │ │ ├── 0029_snapshot.json │ │ │ ├── 0030_snapshot.json │ │ │ ├── 0031_snapshot.json │ │ │ ├── 0032_snapshot.json │ │ │ ├── 0033_snapshot.json │ │ │ ├── 0034_snapshot.json │ │ │ ├── 0035_snapshot.json │ │ │ ├── 0036_snapshot.json │ │ │ ├── 0037_snapshot.json │ │ │ ├── 0038_snapshot.json │ │ │ ├── 0039_snapshot.json │ │ │ ├── 0040_snapshot.json │ │ │ ├── 0041_snapshot.json │ │ │ ├── 0042_snapshot.json │ │ │ ├── 0043_snapshot.json │ │ │ └── _journal.json │ ├── env.mjs │ ├── env.ts │ ├── package.json │ ├── src │ │ ├── db.ts │ │ ├── index.ts │ │ ├── migrate.mts │ │ ├── schema │ │ │ ├── applications │ │ │ │ ├── application.ts │ │ │ │ ├── index.ts │ │ │ │ └── validation.ts │ │ │ ├── check │ │ │ │ ├── check.ts │ │ │ │ ├── constants.ts │ │ │ │ └── index.ts │ │ │ ├── constants.ts │ │ │ ├── incidents │ │ │ │ ├── incident.ts │ │ │ │ ├── index.ts │ │ │ │ └── validation.ts │ │ │ ├── index.ts │ │ │ ├── integration.ts │ │ │ ├── invitations │ │ │ │ ├── index.ts │ │ │ │ ├── invitation.ts │ │ │ │ └── validation.ts │ │ │ ├── maintenances │ │ │ │ ├── index.ts │ │ │ │ ├── maintenance.ts │ │ │ │ └── validation.ts │ │ │ ├── monitor_run │ │ │ │ ├── index.ts │ │ │ │ └── monitor_run.ts │ │ │ ├── monitor_status │ │ │ │ ├── index.ts │ │ │ │ ├── monitor_status.ts │ │ │ │ └── validation.ts │ │ │ ├── monitor_tags │ │ │ │ ├── index.ts │ │ │ │ ├── monitor_tag.ts │ │ │ │ └── validation.ts │ │ │ ├── monitors │ │ │ │ ├── constants.ts │ │ │ │ ├── index.ts │ │ │ │ ├── monitor.ts │ │ │ │ └── validation.ts │ │ │ ├── notifications │ │ │ │ ├── constants.ts │ │ │ │ ├── index.ts │ │ │ │ ├── notification.ts │ │ │ │ └── validation.ts │ │ │ ├── page_subscribers │ │ │ │ ├── index.ts │ │ │ │ ├── page_subscribers.ts │ │ │ │ └── validation.ts │ │ │ ├── pages │ │ │ │ ├── constants.ts │ │ │ │ ├── index.ts │ │ │ │ ├── page.ts │ │ │ │ └── validation.ts │ │ │ ├── plan │ │ │ │ ├── config.ts │ │ │ │ ├── schema.ts │ │ │ │ └── utils.ts │ │ │ ├── shared.ts │ │ │ ├── status_reports │ │ │ │ ├── index.ts │ │ │ │ ├── status_reports.ts │ │ │ │ └── validation.ts │ │ │ ├── users │ │ │ │ ├── index.ts │ │ │ │ ├── user.ts │ │ │ │ └── validation.ts │ │ │ └── workspaces │ │ │ │ ├── constants.ts │ │ │ │ ├── index.ts │ │ │ │ ├── validation.ts │ │ │ │ └── workspace.ts │ │ ├── seed.mts │ │ └── utils.ts │ └── tsconfig.json ├── emails │ ├── emails │ │ ├── _components │ │ │ ├── footer.tsx │ │ │ ├── layout.tsx │ │ │ └── styles.ts │ │ ├── followup.tsx │ │ ├── monitor-alert.tsx │ │ ├── monitor-deactivation.tsx │ │ ├── monitor-paused.tsx │ │ ├── page-subscription.tsx │ │ ├── status-report.tsx │ │ ├── subscribe.tsx │ │ ├── team-invitation.tsx │ │ └── welcome.tsx │ ├── package.json │ ├── src │ │ ├── client.tsx │ │ ├── env.ts │ │ ├── index.ts │ │ ├── send.ts │ │ └── utils.ts │ └── tsconfig.json ├── error │ ├── index.ts │ ├── package.json │ ├── src │ │ ├── base-error.ts │ │ ├── error-code.ts │ │ ├── http-error.ts │ │ ├── schema-error.ts │ │ └── utils.ts │ └── tsconfig.json ├── header-analysis │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── parser │ │ │ ├── cache-control.ts │ │ │ ├── cf-cache-status.ts │ │ │ ├── cf-ray.ts │ │ │ ├── fly-request-id.ts │ │ │ ├── x-vercel-cache.ts │ │ │ └── x-vercel-id.ts │ │ ├── regions │ │ │ ├── cloudflare.ts │ │ │ ├── fly.ts │ │ │ └── vercel.ts │ │ └── types │ │ │ └── index.ts │ └── tsconfig.json ├── notifications │ ├── discord │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── mock.ts │ │ │ └── schema.ts │ │ └── tsconfig.json │ ├── email │ │ ├── .env.example │ │ ├── README.md │ │ ├── env.ts │ │ ├── package.json │ │ ├── src │ │ │ ├── index.ts │ │ │ └── mock.ts │ │ └── tsconfig.json │ ├── ntfy │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src │ │ │ ├── index.ts │ │ │ └── schema.ts │ │ └── tsconfig.json │ ├── opsgenie │ │ ├── package.json │ │ ├── src │ │ │ ├── index.ts │ │ │ └── schema.ts │ │ └── tsconfig.json │ ├── pagerduty │ │ ├── .env.example │ │ ├── package.json │ │ ├── src │ │ │ ├── env.ts │ │ │ ├── index.ts │ │ │ └── schema │ │ │ │ └── config.ts │ │ └── tsconfig.json │ ├── slack │ │ ├── package.json │ │ ├── src │ │ │ ├── index.ts │ │ │ ├── mock.ts │ │ │ └── schema.ts │ │ └── tsconfig.json │ ├── twillio-sms │ │ ├── .env.example │ │ ├── package.json │ │ ├── src │ │ │ ├── env.ts │ │ │ ├── index.ts │ │ │ └── schema │ │ │ │ └── config.ts │ │ └── tsconfig.json │ └── webhook │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── src │ │ ├── index.ts │ │ └── schema.ts │ │ └── tsconfig.json ├── react │ ├── README.md │ ├── package.json │ ├── src │ │ ├── index.ts │ │ ├── styles.css │ │ ├── utils.ts │ │ └── widget.tsx │ ├── tailwind.config.js │ ├── tsconfig.json │ └── tsup.config.js ├── tinybird │ ├── README.md │ ├── _legacy │ │ ├── aggregated_monitor_day_mv.pipe │ │ └── aggregated_monitor_per_day_mv.datasource │ ├── _migration │ │ ├── ping_response.datasource │ │ ├── tb_backfill_populate.pipe │ │ ├── tb_datasource_union.pipe │ │ └── tb_materialize_until_change_ingest.pipe │ ├── datasources │ │ ├── audit_log.datasource │ │ ├── check_response.datasource │ │ ├── check_response_http.datasource │ │ ├── external_status.datasource │ │ ├── mv__http_14d.datasource │ │ ├── mv__http_1d.datasource │ │ ├── mv__http_30d.datasource │ │ ├── mv__http_7d.datasource │ │ ├── mv__http_full_30d.datasource │ │ ├── mv__http_status_45d.datasource │ │ ├── mv__http_status_7d.datasource │ │ ├── mv__tcp_14d.datasource │ │ ├── mv__tcp_1d.datasource │ │ ├── mv__tcp_30d.datasource │ │ ├── mv__tcp_7d.datasource │ │ ├── mv__tcp_full_30d.datasource │ │ ├── mv__tcp_status_45d.datasource │ │ ├── mv__tcp_status_7d.datasource │ │ ├── ping_response.datasource │ │ ├── tcp_response.datasource │ │ └── web_vitals.datasource │ ├── package.json │ ├── pipes │ │ ├── __ttl_45d_count_utc_get.pipe │ │ ├── aggregate__http_14d.pipe │ │ ├── aggregate__http_1d.pipe │ │ ├── aggregate__http_30d.pipe │ │ ├── aggregate__http_7d.pipe │ │ ├── aggregate__http_full_30d.pipe │ │ ├── aggregate__http_status_45d.pipe │ │ ├── aggregate__http_status_7d.pipe │ │ ├── aggregate__tcp_14d.pipe │ │ ├── aggregate__tcp_1d.pipe │ │ ├── aggregate__tcp_30d.pipe │ │ ├── aggregate__tcp_7d.pipe │ │ ├── aggregate__tcp_full_30d.pipe │ │ ├── aggregate__tcp_status_45d.pipe │ │ ├── aggregate__tcp_status_7d.pipe │ │ ├── endpoint__http_get_30d.pipe │ │ ├── endpoint__http_list_14d.pipe │ │ ├── endpoint__http_list_1d.pipe │ │ ├── endpoint__http_list_7d.pipe │ │ ├── endpoint__http_metrics_14d.pipe │ │ ├── endpoint__http_metrics_1d.pipe │ │ ├── endpoint__http_metrics_7d.pipe │ │ ├── endpoint__http_metrics_by_interval_14d.pipe │ │ ├── endpoint__http_metrics_by_interval_1d.pipe │ │ ├── endpoint__http_metrics_by_interval_7d.pipe │ │ ├── endpoint__http_metrics_by_region_14d.pipe │ │ ├── endpoint__http_metrics_by_region_1d.pipe │ │ ├── endpoint__http_metrics_by_region_7d.pipe │ │ ├── endpoint__http_status_45d.pipe │ │ ├── endpoint__http_status_7d.pipe │ │ ├── endpoint__stats_global.pipe │ │ ├── endpoint__tcp_get_30d.pipe │ │ ├── endpoint__tcp_list_14d.pipe │ │ ├── endpoint__tcp_list_1d.pipe │ │ ├── endpoint__tcp_list_7d.pipe │ │ ├── endpoint__tcp_metrics_14d.pipe │ │ ├── endpoint__tcp_metrics_1d.pipe │ │ ├── endpoint__tcp_metrics_7d.pipe │ │ ├── endpoint__tcp_metrics_by_interval_14d.pipe │ │ ├── endpoint__tcp_metrics_by_interval_1d.pipe │ │ ├── endpoint__tcp_metrics_by_interval_7d.pipe │ │ ├── endpoint__tcp_metrics_by_region_14d.pipe │ │ ├── endpoint__tcp_metrics_by_region_1d.pipe │ │ ├── endpoint__tcp_metrics_by_region_7d.pipe │ │ ├── endpoint__tcp_status_45d.pipe │ │ ├── endpoint__tcp_status_7d.pipe │ │ ├── endpoint_audit_log.pipe │ │ ├── external_status.pipe │ │ ├── get_result_for_on_demand_check_http.pipe │ │ ├── public_status.pipe │ │ ├── response_details.pipe │ │ ├── response_graph.pipe │ │ ├── response_list.pipe │ │ ├── response_time_metrics.pipe │ │ ├── response_time_metrics_by_region.pipe │ │ ├── single_checks_get.pipe │ │ └── status_timezone.pipe │ ├── src │ │ ├── audit-log │ │ │ ├── README.md │ │ │ ├── action-schema.ts │ │ │ ├── action-validation.ts │ │ │ ├── base-validation.ts │ │ │ ├── client.ts │ │ │ ├── examples.ts │ │ │ └── index.ts │ │ ├── client.ts │ │ ├── index.ts │ │ └── schema.ts │ └── tsconfig.json ├── tracker │ ├── README.md │ ├── package.json │ ├── src │ │ ├── blacklist.ts │ │ ├── config.ts │ │ ├── index.ts │ │ ├── mock.ts │ │ ├── tracker.ts │ │ ├── types.ts │ │ └── utils.ts │ └── tsconfig.json ├── tsconfig │ ├── base.json │ ├── nextjs.json │ ├── package.json │ └── react-library.json ├── ui │ ├── package.json │ ├── src │ │ ├── components │ │ │ ├── accordion.tsx │ │ │ ├── alert-dialog.tsx │ │ │ ├── alert.tsx │ │ │ ├── avatar.tsx │ │ │ ├── badge.tsx │ │ │ ├── breadcrumb.tsx │ │ │ ├── button-with-disable-tooltip.tsx │ │ │ ├── button.tsx │ │ │ ├── calendar.tsx │ │ │ ├── card.tsx │ │ │ ├── chart.tsx │ │ │ ├── checkbox.tsx │ │ │ ├── collapsible.tsx │ │ │ ├── command.tsx │ │ │ ├── context-menu.tsx │ │ │ ├── date-picker.tsx │ │ │ ├── date-time-picker-popover.tsx │ │ │ ├── date-time-picker.tsx │ │ │ ├── dialog.tsx │ │ │ ├── dropdown-menu.tsx │ │ │ ├── form.tsx │ │ │ ├── hover-card.tsx │ │ │ ├── input-with-addons.tsx │ │ │ ├── input.tsx │ │ │ ├── label.tsx │ │ │ ├── multi-select.tsx │ │ │ ├── navigation-menu.tsx │ │ │ ├── pagination.tsx │ │ │ ├── popover.tsx │ │ │ ├── progress.tsx │ │ │ ├── radio-group.tsx │ │ │ ├── select.tsx │ │ │ ├── separator.tsx │ │ │ ├── sheet.tsx │ │ │ ├── skeleton.tsx │ │ │ ├── slider.tsx │ │ │ ├── sonner.tsx │ │ │ ├── sortable.tsx │ │ │ ├── switch.tsx │ │ │ ├── table.tsx │ │ │ ├── tabs.tsx │ │ │ ├── textarea.tsx │ │ │ ├── toggle.tsx │ │ │ └── tooltip.tsx │ │ ├── index.tsx │ │ └── lib │ │ │ ├── compose-refs.ts │ │ │ └── utils.ts │ ├── tailwind.config.ts │ └── tsconfig.json ├── upstash │ ├── package.json │ ├── src │ │ ├── index.ts │ │ └── redis │ │ │ └── client.ts │ └── tsconfig.json └── utils │ ├── index.ts │ ├── package.json │ └── tsconfig.json ├── pnpm-lock.yaml ├── pnpm-workspace.yaml ├── process-compose.yaml ├── turbo.json └── utils └── api-bruno ├── Monitor Summary.bru ├── OpenApi.bru ├── bruno.json ├── checker.bru ├── environments ├── local.bru └── prod.bru ├── incident_update └── Get Status Report Update.bru └── incidents ├── All Status Reports.bru └── Get Status Report.bru /.dockerignore: -------------------------------------------------------------------------------- 1 | **/.dockerignore 2 | **/node_modules 3 | **/npm-debug.log 4 | **/README.md 5 | **/.next 6 | **/.git 7 | node_modules 8 | openstatus.db -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | polar: openstatusHQ -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Discord community support 4 | url: https://www.openstatus.dev/discord 5 | about: Need any help? Found any bug? Please chat with us via Discord. 6 | -------------------------------------------------------------------------------- /.github/workflows/deploy.yml: -------------------------------------------------------------------------------- 1 | name: Fly Deploy 2 | on: 3 | push: 4 | branches: 5 | - main 6 | jobs: 7 | deploy: 8 | name: Deploy API 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v4 12 | - uses: superfly/flyctl-actions/setup-flyctl@master 13 | - run: 14 | flyctl deploy --config apps/server/fly.toml 15 | --dockerfile apps/server/Dockerfile --remote-only --wait-timeout=500 16 | env: 17 | FLY_API_TOKEN: ${{ secrets.FLY_API_TOKEN }} 18 | -------------------------------------------------------------------------------- /.github/workflows/synthetic.yml: -------------------------------------------------------------------------------- 1 | name: Run OpenStatus Synthetics CI 2 | 3 | on: 4 | workflow_dispatch: 5 | push: 6 | branches: [ main ] 7 | 8 | jobs: 9 | synthetic_ci: 10 | runs-on: ubuntu-latest 11 | name: Run OpenStatus Synthetics CI 12 | steps: 13 | - name: Checkout 14 | uses: actions/checkout@v4 15 | - name: Run OpenStatus Synthetics CI 16 | uses: openstatushq/openstatus-github-action@v1 17 | with: 18 | api_key: ${{ secrets.OPENSTATUS_API_KEY }} 19 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | auto-install-peers = true 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/.content-collections 2 | -------------------------------------------------------------------------------- /apps/checker/.golangci.yml: -------------------------------------------------------------------------------- 1 | linters: 2 | enable-all: true 3 | disable-all: false 4 | fast: true 5 | -------------------------------------------------------------------------------- /apps/checker/handlers/handler.go: -------------------------------------------------------------------------------- 1 | package handlers 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/openstatushq/openstatus/apps/checker/pkg/tinybird" 7 | ) 8 | 9 | type Handler struct { 10 | TbClient tinybird.Client 11 | Secret string 12 | CloudProvider string 13 | Region string 14 | } 15 | 16 | // Authorization could be handle by middleware 17 | 18 | func NewHTTPClient() *http.Client { 19 | return &http.Client{} 20 | } 21 | -------------------------------------------------------------------------------- /apps/checker/pkg/logger/logger.go: -------------------------------------------------------------------------------- 1 | package logger 2 | 3 | import ( 4 | "github.com/rs/zerolog" 5 | "github.com/rs/zerolog/log" 6 | ) 7 | 8 | func Configure(logLevel string) { 9 | level, err := zerolog.ParseLevel(logLevel) 10 | if err != nil { 11 | level = zerolog.InfoLevel 12 | } 13 | zerolog.SetGlobalLevel(level) 14 | 15 | zerolog.DefaultContextLogger = func() *zerolog.Logger { 16 | logger := log.With().Caller().Logger() 17 | return &logger 18 | }() 19 | } 20 | -------------------------------------------------------------------------------- /apps/docs/.env.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_OPENPANEL_CLIENT_ID= -------------------------------------------------------------------------------- /apps/docs/.gitignore: -------------------------------------------------------------------------------- 1 | # build output 2 | dist/ 3 | # generated types 4 | .astro/ 5 | 6 | # dependencies 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log* 11 | yarn-debug.log* 12 | yarn-error.log* 13 | pnpm-debug.log* 14 | 15 | # environment variables 16 | .env 17 | .env.production 18 | 19 | # macOS-specific files 20 | .DS_Store 21 | -------------------------------------------------------------------------------- /apps/docs/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/public/favicon.ico -------------------------------------------------------------------------------- /apps/docs/public/fonts/CalSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/public/fonts/CalSans-SemiBold.ttf -------------------------------------------------------------------------------- /apps/docs/public/fonts/Inter-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/public/fonts/Inter-Light.ttf -------------------------------------------------------------------------------- /apps/docs/public/fonts/Inter-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/public/fonts/Inter-Medium.ttf -------------------------------------------------------------------------------- /apps/docs/public/fonts/Inter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/public/fonts/Inter-Regular.ttf -------------------------------------------------------------------------------- /apps/docs/src/assets/cli/CLI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/cli/CLI.png -------------------------------------------------------------------------------- /apps/docs/src/assets/guides/how-deploy-checker-koyeb/koyeb-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/guides/how-deploy-checker-koyeb/koyeb-1.png -------------------------------------------------------------------------------- /apps/docs/src/assets/guides/how-deploy-checker-koyeb/koyeb-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/guides/how-deploy-checker-koyeb/koyeb-2.png -------------------------------------------------------------------------------- /apps/docs/src/assets/guides/how-deploy-checker-koyeb/koyeb-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/guides/how-deploy-checker-koyeb/koyeb-3.png -------------------------------------------------------------------------------- /apps/docs/src/assets/guides/how-deploy-status-page-cf-pages/status-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/guides/how-deploy-status-page-cf-pages/status-page.png -------------------------------------------------------------------------------- /apps/docs/src/assets/guides/latency-ci-integration-test/github-api-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/guides/latency-ci-integration-test/github-api-token.png -------------------------------------------------------------------------------- /apps/docs/src/assets/guides/latency-ci-integration-test/openstatus-api-token.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/guides/latency-ci-integration-test/openstatus-api-token.png -------------------------------------------------------------------------------- /apps/docs/src/assets/houston.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/houston.webp -------------------------------------------------------------------------------- /apps/docs/src/assets/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/icon.png -------------------------------------------------------------------------------- /apps/docs/src/assets/incident/incident-detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/incident/incident-detail.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/assertions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/assertions.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/clone-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/clone-monitor.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/create-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/create-monitor.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/create-tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/create-tag.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/filter-tag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/filter-tag.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/http-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/http-monitor.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/monitor-detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/monitor-detail.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/monitor.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/notifications.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/notifications.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/overview.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/public-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/public-monitor.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/response-log-header.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/response-log-header.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/response-log-timing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/response-log-timing.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/response-log.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/response-log.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/setting-public-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/setting-public-monitor.png -------------------------------------------------------------------------------- /apps/docs/src/assets/monitor/tcp-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/monitor/tcp-monitor.png -------------------------------------------------------------------------------- /apps/docs/src/assets/notification/discord-notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/notification/discord-notification.png -------------------------------------------------------------------------------- /apps/docs/src/assets/notification/opsgenie/opsgenie-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/notification/opsgenie/opsgenie-1.png -------------------------------------------------------------------------------- /apps/docs/src/assets/notification/opsgenie/opsgenie-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/notification/opsgenie/opsgenie-2.png -------------------------------------------------------------------------------- /apps/docs/src/assets/notification/opsgenie/opsgenie-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/notification/opsgenie/opsgenie-3.png -------------------------------------------------------------------------------- /apps/docs/src/assets/notification/opsgenie/opsgenie-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/notification/opsgenie/opsgenie-4.png -------------------------------------------------------------------------------- /apps/docs/src/assets/notification/opsgenie/opsgenie-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/notification/opsgenie/opsgenie-5.png -------------------------------------------------------------------------------- /apps/docs/src/assets/notification/pagerduty/pagerduty-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/notification/pagerduty/pagerduty-1.png -------------------------------------------------------------------------------- /apps/docs/src/assets/notification/pagerduty/pagerduty-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/notification/pagerduty/pagerduty-2.png -------------------------------------------------------------------------------- /apps/docs/src/assets/notification/pagerduty/pagerduty-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/notification/pagerduty/pagerduty-3.png -------------------------------------------------------------------------------- /apps/docs/src/assets/setup-env/clerk-step1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/setup-env/clerk-step1.png -------------------------------------------------------------------------------- /apps/docs/src/assets/setup-env/clerk-step2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/setup-env/clerk-step2.png -------------------------------------------------------------------------------- /apps/docs/src/assets/setup-env/clerk-step3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/setup-env/clerk-step3.png -------------------------------------------------------------------------------- /apps/docs/src/assets/setup-env/clerk.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/setup-env/clerk.png -------------------------------------------------------------------------------- /apps/docs/src/assets/setup-env/drizzle-studio.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/setup-env/drizzle-studio.png -------------------------------------------------------------------------------- /apps/docs/src/assets/setup-env/resend.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/setup-env/resend.png -------------------------------------------------------------------------------- /apps/docs/src/assets/setup-env/tinybird.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/setup-env/tinybird.png -------------------------------------------------------------------------------- /apps/docs/src/assets/status-page/create-status-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/status-page/create-status-page.png -------------------------------------------------------------------------------- /apps/docs/src/assets/status-page/description.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/status-page/description.png -------------------------------------------------------------------------------- /apps/docs/src/assets/status-page/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/status-page/favicon.png -------------------------------------------------------------------------------- /apps/docs/src/assets/status-page/status-page-empty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/status-page/status-page-empty.png -------------------------------------------------------------------------------- /apps/docs/src/assets/status-page/status-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/status-page/status-page.png -------------------------------------------------------------------------------- /apps/docs/src/assets/status-widget/widget-example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/docs/src/assets/status-widget/widget-example.png -------------------------------------------------------------------------------- /apps/docs/src/components/SiteTitle.astro: -------------------------------------------------------------------------------- 1 | --- 2 | import { Image } from "astro:assets"; 3 | import logo from "../assets/icon.png"; // Image is 1600x900 4 | --- 5 | 6 | 7 | 8 | OpenStatus 15 | OpenStatus 16 | -------------------------------------------------------------------------------- /apps/docs/src/content/config.ts: -------------------------------------------------------------------------------- 1 | import { defineCollection } from "astro:content"; 2 | import { docsLoader } from "@astrojs/starlight/loaders"; 3 | import { docsSchema } from "@astrojs/starlight/schema"; 4 | // import { glob } from "astro/loaders"; 5 | import { topicSchema } from "starlight-sidebar-topics/schema"; 6 | 7 | export const collections = { 8 | docs: defineCollection({ 9 | loader: docsLoader(), 10 | // loader: glob({ pattern: "**/*.mdx", base: "./src/content/docs" }), 11 | schema: docsSchema({ extend: topicSchema }), 12 | }), 13 | }; 14 | -------------------------------------------------------------------------------- /apps/docs/src/content/docs/alerting/providers/email.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Email 3 | description: "How to set up Email notifications in OpenStatus to get alerts when your synthetic check fail" 4 | 5 | --- 6 | 7 | When we create an incident we send an email to the email provided. 8 | -------------------------------------------------------------------------------- /apps/docs/src/content/docs/alerting/providers/ntfy.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: ntfy.sh 3 | description: "How to set up ntfy.sh notifications in OpenStatus to get alerts when your synthetic check fail" 4 | --- 5 | 6 | [ntfy.sh](https://ntfy.sh/) is an open-source servicer that allows you to receive push notifications on your phone. 7 | 8 | 9 | 10 | Go to the Notifications Page . Select `ntfy.sh` from the list of available integrations. 11 | 12 | Enter your ntfy topic (required), your custom server URL, and your bearer token. 13 | -------------------------------------------------------------------------------- /apps/docs/src/content/docs/alerting/providers/phone-call.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Phone call 3 | description: "How to set up phone call notifications in OpenStatus to get alerts when your synthetic check fail" 4 | 5 | --- 6 | 7 | Receive a phone call when your monitor is down. 8 | 9 | 🚧 Coming soon 🚧 10 | -------------------------------------------------------------------------------- /apps/docs/src/content/docs/alerting/providers/slack.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Slack 3 | description: "How to set up Slack notifications in OpenStatus to get alerts when your synthetic check fail" 4 | 5 | --- 6 | 7 | When a monitor is down, a message can be sent to a Slack channel. To enable this 8 | feature, you need to create a Slack webhook. You can do this by following the 9 | instructions [here](https://api.slack.com/incoming-webhooks). 10 | -------------------------------------------------------------------------------- /apps/docs/src/content/docs/alerting/providers/sms.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: SMS 3 | description: "How to set up SMS notifications in OpenStatus to get alerts when your synthetic check fail" 4 | 5 | --- 6 | 7 | When you subscribe to a paid plan you can receive SMS notifications when your 8 | monitor is down. 9 | -------------------------------------------------------------------------------- /apps/docs/src/content/docs/alerting/providers/telegram.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Telegram 3 | description: "How to set up Telegram notifications in OpenStatus to get alerts when your synthetic check fail" 4 | 5 | --- 6 | 7 | 🚧 Coming soon 🚧 8 | -------------------------------------------------------------------------------- /apps/docs/src/content/docs/cli/commands/whoami.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Whoami 3 | description: "How to check the currently authenticated user in OpenStatus with the whoami command" 4 | --- 5 | 6 | The `whoami` command is used to display the currently authenticated user. This command is useful to check if you are logged in and to see the workspace details. 7 | -------------------------------------------------------------------------------- /apps/docs/src/content/docs/guides/introduction.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Introduction 3 | description: Guides to get started with OpenStatus 4 | sidebar: 5 | label: Introduction 6 | order: 1 7 | --- 8 | 9 | Here's some content for the getting started with OpenStatus. 10 | 11 | - [How to deploy your own probe to Koyeb](/guides/how-deploy-checker-koyeb/) 12 | 13 | - [Deploy your own Status Page to Cloudflare Pages](/guides/how-deploy-status-page-cf-pages) 14 | 15 | - [How to run synthetic tests in your GitHub Actions](/guides/how-to-run-synthetic-test-github-action/) -------------------------------------------------------------------------------- /apps/docs/src/content/docs/help/support.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Need help? 3 | description: "We're always here to help." 4 | --- 5 | 6 | If you have any questions, feedback, or need help you can: 7 | - Schedule a [call](https://cal.com/team/openstatus/30min) with us. 8 | - Join our [Discord](https://www.openstatus.dev/discord) community. 9 | - Send us an email at [ping@openstatus.dev](mailto:ping@openstatus.dev) 10 | - Open an issue on our [GitHub](https://www.github.com/openstatushq/openstatus) repository. -------------------------------------------------------------------------------- /apps/docs/src/content/docs/incident/overview.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Overview 3 | description: "Discover what is an incident in OpenStatus" 4 | --- 5 | 6 | 7 | ## What is an incident 🧑‍🏫 8 | 9 | We automatically create an incident when we detect a problem with your service. 10 | When a monitor fails in more than 50% of the locations, we create an incident. 11 | We do that in order to avoid false positives. 12 | -------------------------------------------------------------------------------- /apps/docs/src/content/docs/monitoring/type/tcp.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: TCP 3 | description: "How to monitor your TCP services with OpenStatus" 4 | --- 5 | 6 | import { Image } from 'astro:assets'; 7 | 8 | import TCPMonitor from '../../../../assets/monitor/tcp-monitor.png'; 9 | 10 | TCP Monitor 14 | 15 | 16 | 17 | ### URI (Host:Port) 18 | Provide your Host and Port to monitor your TCP service. Could be a domain or IPv4/IPv6 address. -------------------------------------------------------------------------------- /apps/docs/src/content/docs/status-page/advanced/custom-domain.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Custom Domain 3 | description: "How to connect a custom domain to your status page in OpenStatus" 4 | --- 5 | 6 | import { Aside } from '@astrojs/starlight/components'; 7 | 8 | 9 | 10 | To connect a custom domain to your status page: _Select a status page → Domain →_. 11 | 12 | You will be asked to enter your custom domain. And we will provide you with a DNS record to add to your domain provider. -------------------------------------------------------------------------------- /apps/docs/src/content/docs/status-page/work/color-status-bar.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Understand the color of the status bar 3 | --- 4 | 5 | On your status page, each status bar can have a different color based on the status of the service. 6 | 7 | - **Green**: The service is up and running. 8 | - **Orange**: The service is slow or degraded. 9 | - **Red**: The service is down or unreachable. 10 | - **Gray**: The service is paused or disabled or there is no data. 11 | - **Blue**: The service is in maintenance or scheduled downtime. -------------------------------------------------------------------------------- /apps/docs/src/content/docs/status-page/work/maintenances.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Maintenance 3 | --- 4 | 5 | You can predefine maintenance periods for your services and inform your users about upcoming and/or current maintenance. 6 | 7 | During the maintenance period, the status of your service will be set to `Maintenance`. We will not ping your selected monitors during this time. 8 | 9 | To set up maintenance periods for your services: _Select a status page → Maintenance_. -------------------------------------------------------------------------------- /apps/docs/src/custom.css: -------------------------------------------------------------------------------- 1 | .card { 2 | border-radius: 0.5rem; 3 | } 4 | 5 | .card .icon { 6 | border: 1px solid var(--sl-color-gray-5); 7 | background-color: var(--sl-color-black); 8 | padding: 0.2em; 9 | border-radius: 0.25rem; 10 | } -------------------------------------------------------------------------------- /apps/docs/src/env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | -------------------------------------------------------------------------------- /apps/docs/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "astro/tsconfigs/strict", 3 | "compilerOptions": { 4 | "types": ["unplugin-icons/types/astro"] 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /apps/screenshot-service/.dockerignore: -------------------------------------------------------------------------------- 1 | # flyctl launch added from .gitignore 2 | **/node_modules 3 | **/dist 4 | **/.wrangler 5 | **/.dev.vars 6 | 7 | # Change them to your taste: 8 | **/package-lock.json 9 | **/yarn.lock 10 | **/pnpm-lock.yaml 11 | **/bun.lockb 12 | fly.toml 13 | 14 | node_modules 15 | -------------------------------------------------------------------------------- /apps/screenshot-service/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | .wrangler 4 | .dev.vars 5 | 6 | # Change them to your taste: 7 | package-lock.json 8 | yarn.lock 9 | pnpm-lock.yaml 10 | bun.lockb -------------------------------------------------------------------------------- /apps/screenshot-service/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:22-bookworm as dep 2 | 3 | RUN npx -y playwright@1.46.0 install --with-deps 4 | 5 | RUN npm install -g bun 6 | 7 | RUN npm install -g pnpm 8 | 9 | WORKDIR /app 10 | 11 | COPY . . 12 | 13 | # To keep the image small ;) 14 | RUN rm -rf /app/apps/docs &&\ 15 | rm -rf /app/apps/web &&\ 16 | rm -rf /app/apps/server &&\ 17 | rm -rf /app/packages/api &&\ 18 | rm -rf /app/packages/integrations/vercel 19 | 20 | RUN pnpm install 21 | EXPOSE 3000 22 | 23 | WORKDIR /app/apps/screenshot-service 24 | CMD ["bun", "start"] 25 | -------------------------------------------------------------------------------- /apps/screenshot-service/README.md: -------------------------------------------------------------------------------- 1 | # Screenshot Worker 2 | 3 | This is not used anymore. 4 | 5 | Will be used for browser check 6 | -------------------------------------------------------------------------------- /apps/screenshot-service/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/base.json", 3 | "include": ["src", "*.ts", "**/*.ts"], 4 | "compilerOptions": {} 5 | } 6 | -------------------------------------------------------------------------------- /apps/server/.dockerignore: -------------------------------------------------------------------------------- 1 | # This file is generated by Dofigen v2.3.2 2 | # See https://github.com/lenra-io/dofigen 3 | 4 | node_modules 5 | /apps/docs 6 | /apps/screenshot-service 7 | /apps/web 8 | /packages/api 9 | /packages/integrations/vercel 10 | -------------------------------------------------------------------------------- /apps/server/.env.example: -------------------------------------------------------------------------------- 1 | DATABASE_URL=http://127.0.0.1:8080 2 | DATABASE_AUTH_TOKEN= 3 | NODE_ENV=production 4 | UNKEY_TOKEN= 5 | TINY_BIRD_API_KEY= 6 | UPSTASH_REDIS_REST_URL= 7 | UPSTASH_REDIS_REST_TOKEN= 8 | RESEND_API_KEY= 9 | TWILLIO_AUTH_TOKEN=your_auth_token 10 | TWILLIO_ACCOUNT_ID=your_account_id 11 | 12 | SCREENSHOT_SERVICE_URL=http://your.endpoint 13 | QSTASH_TOKEN=your_token 14 | 15 | NEXT_PUBLIC_OPENPANEL_CLIENT_ID= 16 | OPENPANEL_CLIENT_SECRET= -------------------------------------------------------------------------------- /apps/server/.env.test: -------------------------------------------------------------------------------- 1 | DATABASE_URL=http://127.0.0.1:8080 2 | DATABASE_AUTH_TOKEN= 3 | NODE_ENV=test 4 | UNKEY_TOKEN=test 5 | TINY_BIRD_API_KEY=test 6 | UPSTASH_REDIS_REST_URL=test 7 | UPSTASH_REDIS_REST_TOKEN=test 8 | QSTASH_CURRENT_SIGNING_KEY=test 9 | QSTASH_NEXT_SIGNING_KEY=test 10 | FLY_REGION=ams 11 | RESEND_API_KEY=test 12 | SQLD_HTTP_AUTH=basic:token 13 | SCREENSHOT_SERVICE_URL=http://your.endpoint 14 | NEXT_PUBLIC_OPENPANEL_CLIENT_ID=test 15 | OPENPANEL_CLIENT_SECRET=test -------------------------------------------------------------------------------- /apps/server/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /apps/server/env.ts: -------------------------------------------------------------------------------- 1 | const file = Bun.file("./.env.example"); 2 | await Bun.write("./.env", file); 3 | -------------------------------------------------------------------------------- /apps/server/fly.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | fly machines list --json | jq .[].id | sed 's/"//g' | while read machine; do 5 | fly machines update $machine --restart always --yes 6 | done -------------------------------------------------------------------------------- /apps/server/log/fly.toml: -------------------------------------------------------------------------------- 1 | # fly.toml app configuration file generated for openstatus-log on 2023-10-19T00:44:54+02:00 2 | # 3 | # See https://fly.io/docs/reference/configuration/ for information about how to use this file. 4 | # 5 | 6 | app = "openstatus-log" 7 | primary_region = "ams" 8 | 9 | [build] 10 | image = "ghcr.io/superfly/fly-log-shipper:latest" 11 | 12 | [http_service] 13 | internal_port = 8686 14 | force_https = true 15 | auto_stop_machines = "suspend" 16 | auto_start_machines = true 17 | min_machines_running = 1 18 | processes = ["app"] 19 | -------------------------------------------------------------------------------- /apps/server/src/libs/cache/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./memory"; 2 | -------------------------------------------------------------------------------- /apps/server/src/libs/checker/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./utils"; 2 | -------------------------------------------------------------------------------- /apps/server/src/libs/errors/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./utils"; 2 | export * from "./openapi-error-responses"; 3 | -------------------------------------------------------------------------------- /apps/server/src/libs/middlewares/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./auth"; 2 | export * from "./track"; 3 | export * from "./plan"; 4 | -------------------------------------------------------------------------------- /apps/server/src/routes/public/index.ts: -------------------------------------------------------------------------------- 1 | import { Hono } from "hono"; 2 | import { cors } from "hono/cors"; 3 | import { timing } from "hono/timing"; 4 | 5 | import { status } from "./status"; 6 | 7 | export const publicRoute = new Hono(); 8 | publicRoute.use("*", cors()); 9 | publicRoute.use("*", timing()); 10 | 11 | publicRoute.route("/status", status); 12 | -------------------------------------------------------------------------------- /apps/server/src/routes/v1/check/index.ts: -------------------------------------------------------------------------------- 1 | import { OpenAPIHono } from "@hono/zod-openapi"; 2 | 3 | import type { Variables } from "../index"; 4 | 5 | import { handleZodError } from "@/libs/errors"; 6 | import { registerHTTPPostCheck } from "./http/post"; 7 | 8 | const checkApi = new OpenAPIHono<{ Variables: Variables }>({ 9 | defaultHook: handleZodError, 10 | }); 11 | 12 | registerHTTPPostCheck(checkApi); 13 | 14 | export { checkApi }; 15 | -------------------------------------------------------------------------------- /apps/server/src/routes/v1/monitors/run/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from "@hono/zod-openapi"; 2 | 3 | export const QuerySchema = z 4 | .object({ 5 | "no-wait": z.coerce.boolean().optional().default(false).openapi({ 6 | description: "Don't wait for the result", 7 | }), 8 | }) 9 | .openapi({ 10 | description: "Query parameters", 11 | }); 12 | -------------------------------------------------------------------------------- /apps/server/src/routes/v1/monitors/trigger/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from "@hono/zod-openapi"; 2 | import { ParamsSchema } from "../schema"; 3 | 4 | export { ParamsSchema }; 5 | 6 | export const TriggerSchema = z.object({ 7 | resultId: z.number().openapi({ description: "the id of your check result" }), 8 | }); 9 | 10 | export type TriggerSchema = z.infer; 11 | -------------------------------------------------------------------------------- /apps/server/src/routes/v1/pageSubscribers/index.ts: -------------------------------------------------------------------------------- 1 | import { OpenAPIHono } from "@hono/zod-openapi"; 2 | 3 | import { handleZodError } from "@/libs/errors"; 4 | import type { Variables } from "../index"; 5 | import { registerPostPageSubscriber } from "./post"; 6 | 7 | export const pageSubscribersApi = new OpenAPIHono<{ Variables: Variables }>({ 8 | defaultHook: handleZodError, 9 | }); 10 | 11 | registerPostPageSubscriber(pageSubscribersApi); 12 | -------------------------------------------------------------------------------- /apps/server/src/routes/v1/whoami/index.ts: -------------------------------------------------------------------------------- 1 | import { handleZodError } from "@/libs/errors"; 2 | import { OpenAPIHono } from "@hono/zod-openapi"; 3 | import type { Variables } from ".."; 4 | import { registerGetWhoami } from "./get"; 5 | 6 | export const whoamiApi = new OpenAPIHono<{ Variables: Variables }>({ 7 | defaultHook: handleZodError, 8 | }); 9 | 10 | registerGetWhoami(whoamiApi); 11 | -------------------------------------------------------------------------------- /apps/server/src/types/index.ts: -------------------------------------------------------------------------------- 1 | import type { Workspace } from "@openstatus/db/src/schema"; 2 | import type { RequestIdVariables } from "hono/request-id"; 3 | 4 | export type Variables = RequestIdVariables & { 5 | workspace: Workspace; 6 | }; 7 | -------------------------------------------------------------------------------- /apps/server/src/utils/audit-log.ts: -------------------------------------------------------------------------------- 1 | import { AuditLog, Tinybird } from "@openstatus/tinybird"; 2 | 3 | import { env } from "../env"; 4 | 5 | const tb = new Tinybird({ token: env.TINY_BIRD_API_KEY }); 6 | 7 | export const checkerAudit = new AuditLog({ tb }); 8 | -------------------------------------------------------------------------------- /apps/server/src/utils/not-empty.ts: -------------------------------------------------------------------------------- 1 | export function notEmpty( 2 | value: TValue | null | undefined, 3 | ): value is TValue { 4 | return value !== null && value !== undefined; 5 | } 6 | -------------------------------------------------------------------------------- /apps/server/src/utils/random-promise.ts: -------------------------------------------------------------------------------- 1 | export function fakePromiseWithRandomResolve() { 2 | return new Promise((resolve, reject) => { 3 | const randomTime = Math.floor(Math.random() * 1000); 4 | setTimeout(() => { 5 | const shouldResolve = Math.random() < 1; // 0.5 6 | if (shouldResolve) { 7 | resolve("Promise resolved successfully."); 8 | } else { 9 | reject(new Error("Promise rejected.")); 10 | } 11 | }, randomTime); 12 | }); 13 | } 14 | -------------------------------------------------------------------------------- /apps/server/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/base.json", 3 | "include": ["src", "*.ts", "**/*.ts"], 4 | "compilerOptions": { 5 | "jsx": "react-jsx", 6 | "jsxImportSource": "react", 7 | "allowJs": true, 8 | "types": ["bun-types"], 9 | "baseUrl": ".", 10 | "paths": { 11 | "@/*": ["src/*"] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "default", 4 | "rsc": true, 5 | "tailwind": { 6 | "config": "tailwind.config.js", 7 | "css": "src/styles/globals.css", 8 | "baseColor": "slate", 9 | "cssVariables": true 10 | }, 11 | "aliases": { 12 | "components": "@/components", 13 | "utils": "@/lib/utils" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/env.ts: -------------------------------------------------------------------------------- 1 | const file = Bun.file("./.env.example"); 2 | await Bun.write("./.env", file); 3 | -------------------------------------------------------------------------------- /apps/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/app/api-reference/config/typescript for more information. 6 | -------------------------------------------------------------------------------- /apps/web/postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | }; 7 | -------------------------------------------------------------------------------- /apps/web/public/assets/alternatives/betterstack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/alternatives/betterstack.png -------------------------------------------------------------------------------- /apps/web/public/assets/alternatives/checkly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/alternatives/checkly.png -------------------------------------------------------------------------------- /apps/web/public/assets/alternatives/uptime-kuma.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/alternatives/uptime-kuma.png -------------------------------------------------------------------------------- /apps/web/public/assets/alternatives/uptime-robot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/alternatives/uptime-robot.png -------------------------------------------------------------------------------- /apps/web/public/assets/authors/max.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/authors/max.png -------------------------------------------------------------------------------- /apps/web/public/assets/authors/thibault.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/authors/thibault.jpeg -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/CLI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/CLI.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/Otel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/Otel.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/auto-resolved-incidents.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/auto-resolved-incidents.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/check-api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/check-api.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/checker-playground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/checker-playground.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/clone-monitor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/clone-monitor.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/content-type.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/content-type.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/curl-builder-playground.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/curl-builder-playground.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/dark-theme-support.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/dark-theme-support.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/dashboard-metrics-card.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/dashboard-metrics-card.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/docker-checker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/docker-checker.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/github-action.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/github-action.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/golang-monitor-checker.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/golang-monitor-checker.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/individual-status-report-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/individual-status-report-page.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/latency-quantiles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/latency-quantiles.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/maintenance-status.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/maintenance-status.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/monitor-tags.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/monitor-tags.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/monitor-threshold.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/monitor-threshold.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/more-regions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/more-regions.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/multi-region-monitoring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/multi-region-monitoring.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/ntfy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/ntfy.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/pagerduty-integration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/pagerduty-integration.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/password-protected-status-page.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/password-protected-status-page.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/play-checker-improvements.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/play-checker-improvements.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/public-monitors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/public-monitors.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/raycast-integration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/raycast-integration.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/request-assertions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/request-assertions.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/response-time-charts.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/response-time-charts.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/screenshot-incident.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/screenshot-incident.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/slack-discord-notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/slack-discord-notification.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/sms-notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/sms-notification.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/status-page-badge.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/status-page-badge.jpeg -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/status-page-colors-and-more.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/status-page-colors-and-more.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/status-page-feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/status-page-feed.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/status-page-monitor-order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/status-page-monitor-order.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/status-page-monitor-values-visibility.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/status-page-monitor-values-visibility.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/status-page-subscribers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/status-page-subscribers.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/status-report-location-change.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/status-report-location-change.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/status-update-subscriber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/status-update-subscriber.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/status-widget.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/status-widget.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/tcp-request.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/tcp-request.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/team-invites.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/team-invites.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/terraform.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/terraform.png -------------------------------------------------------------------------------- /apps/web/public/assets/changelog/webhook.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/changelog/webhook.png -------------------------------------------------------------------------------- /apps/web/public/assets/checker/glauber.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/checker/glauber.png -------------------------------------------------------------------------------- /apps/web/public/assets/logos/OpenStatus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/logos/OpenStatus.png -------------------------------------------------------------------------------- /apps/web/public/assets/og/dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/og/dashboard.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/2023-year-review/blog-hn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/2023-year-review/blog-hn.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/2023-year-review/github-stars.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/2023-year-review/github-stars.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/2023-year-review/monitors-per-week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/2023-year-review/monitors-per-week.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/2023-year-review/mrr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/2023-year-review/mrr.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/2023-year-review/pages-per-week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/2023-year-review/pages-per-week.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/2023-year-review/search-console.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/2023-year-review/search-console.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/2023-year-review/show-hn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/2023-year-review/show-hn.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/2023-year-review/tinybird.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/2023-year-review/tinybird.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/2023-year-review/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/2023-year-review/title.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/2023-year-review/users-per-week.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/2023-year-review/users-per-week.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/2023-year-review/visitors.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/2023-year-review/visitors.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/data-table-redesign/after.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/data-table-redesign/after.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/data-table-redesign/before.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/data-table-redesign/before.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/data-table-redesign/toolbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/data-table-redesign/toolbox.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/dynamic-breadcrumb-nextjs/breadcrumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/dynamic-breadcrumb-nextjs/breadcrumb.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/event-analytics-implementation/event-analytics-implementation.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/event-analytics-implementation/event-analytics-implementation.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/github-trending-list.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/github-trending-list.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/how-we-build-our-github-action/GitHub.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/how-we-build-our-github-action/GitHub.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/infra-openstatus/hosting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/infra-openstatus/hosting.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/infra-openstatus/queue.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/infra-openstatus/queue.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/infra-openstatus/tech-infra.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/infra-openstatus/tech-infra.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/introducing-goatstack/bsky-post.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/introducing-goatstack/bsky-post.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/introducing-goatstack/goat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/introducing-goatstack/goat.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/live-mode-infinite-query/infinite-query.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/live-mode-infinite-query/infinite-query.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/live-mode-infinite-query/offset-caveat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/live-mode-infinite-query/offset-caveat.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/live-mode-infinite-query/tanstack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/live-mode-infinite-query/tanstack.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/migration-auth-clerk-to-next-auth/authjs.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/migration-auth-clerk-to-next-auth/authjs.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/migration-auth-clerk-to-next-auth/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/migration-auth-clerk-to-next-auth/title.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/migration-backend-from-vercel-to-fly/fly-dashboard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/migration-backend-from-vercel-to-fly/fly-dashboard.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/migration-backend-from-vercel-to-fly/fly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/migration-backend-from-vercel-to-fly/fly.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/migration-backend-from-vercel-to-fly/hono-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/migration-backend-from-vercel-to-fly/hono-server.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/migration-backend-from-vercel-to-fly/next-server.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/migration-backend-from-vercel-to-fly/next-server.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/migration-planetscale-to-turso/planetscale-latency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/migration-planetscale-to-turso/planetscale-latency.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/migration-planetscale-to-turso/turso-latency.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/migration-planetscale-to-turso/turso-latency.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/migration-planetscale-to-turso/turso.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/migration-planetscale-to-turso/turso.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/monitoring-latency/all-hosting-providers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/monitoring-latency/all-hosting-providers.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/monitoring-latency/fly-api.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/monitoring-latency/fly-api.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/monitoring-latency/monitor-cloudflare-workers.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/monitoring-latency/monitor-cloudflare-workers.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/monitoring-latency/monitor-fly.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/monitoring-latency/monitor-fly.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/monitoring-latency/monitor-koyeb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/monitoring-latency/monitor-koyeb.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/monitoring-latency/monitor-railway.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/monitoring-latency/monitor-railway.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/monitoring-latency/monitor-render.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/monitoring-latency/monitor-render.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/monitoring-vercel/serverless-vs-edge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/monitoring-vercel/serverless-vs-edge.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/openstatus-light-viewer/data-table-popover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/openstatus-light-viewer/data-table-popover.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/openstatus-light-viewer/light-viewer.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/openstatus-light-viewer/light-viewer.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/our-new-pricing-explained/ahref.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/our-new-pricing-explained/ahref.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/our-new-pricing-explained/pricing-hard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/our-new-pricing-explained/pricing-hard.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/pricing-update-july-2024/pricing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/pricing-update-july-2024/pricing.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/q1-2024-update/chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/q1-2024-update/chart.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/q1-2024-update/q1-2024-update.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/q1-2024-update/q1-2024-update.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/reflecting-1-year-building-openstatus/first-year.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/reflecting-1-year-building-openstatus/first-year.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/reflecting-1-year-building-openstatus/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/reflecting-1-year-building-openstatus/image.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/reflecting-1-year-building-openstatus/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/reflecting-1-year-building-openstatus/twitter.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/reflecting-1-year-building-openstatus/us.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/reflecting-1-year-building-openstatus/us.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/reflecting-1-year-building-openstatus/users.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/reflecting-1-year-building-openstatus/users.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/secure-api-with-unkey/unkey-landing-old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/secure-api-with-unkey/unkey-landing-old.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/secure-api-with-unkey/unkey-landing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/secure-api-with-unkey/unkey-landing.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/secure-api-with-unkey/unkey.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/secure-api-with-unkey/unkey.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/the-first-48-hours/48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/the-first-48-hours/48.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/the-first-48-hours/enough-gas-workspace-slug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/the-first-48-hours/enough-gas-workspace-slug.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/the-first-48-hours/qstash-usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/the-first-48-hours/qstash-usage.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/the-first-48-hours/vercel-usage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/the-first-48-hours/vercel-usage.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/the-first-48-hours/wet-grandmother-workspace-slug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/the-first-48-hours/wet-grandmother-workspace-slug.png -------------------------------------------------------------------------------- /apps/web/public/assets/posts/vision-2025/vision-2025.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/public/assets/posts/vision-2025/vision-2025.png -------------------------------------------------------------------------------- /apps/web/src/app/(content)/layout.tsx: -------------------------------------------------------------------------------- 1 | import { MarketingLayout } from "@/components/layout/marketing-layout"; 2 | import type { ReactNode } from "react"; 3 | 4 | export default function ContentLayout({ children }: { children: ReactNode }) { 5 | return {children}; 6 | } 7 | -------------------------------------------------------------------------------- /apps/web/src/app/(redirect)/cal/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function CalRedirect() { 4 | return redirect("http://cal.com/team/openstatus/30min"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/(redirect)/discord/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function DiscordRedirect() { 4 | return redirect("https://discord.gg/dHD4JtSfsn"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/(redirect)/docs/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function DiscordRedirect() { 4 | return redirect("https://docs.openstatus.dev"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/(redirect)/github/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function GithubRedirect() { 4 | return redirect("https://github.com/openstatusHQ/openstatus"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/(redirect)/linkedin/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function LinkedinRedirect() { 4 | return redirect("https://www.linkedin.com/company/openstatus"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/(redirect)/schema.json/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function SchemaJsonRedirect() { 4 | return redirect( 5 | "https://github.com/openstatusHQ/json-schema/releases/latest/download/schema.json", 6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/(redirect)/twitter/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function TwitterRedirect() { 4 | return redirect("https://twitter.com/openstatusHQ"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/(redirect)/youtube/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function YoutubeRedirect() { 4 | return redirect("https://www.youtube.com/@OpenStatusHQ"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/api/auth/[...nextauth]/route.ts: -------------------------------------------------------------------------------- 1 | import { handlers } from "@/lib/auth"; 2 | 3 | export const { GET, POST } = handlers; 4 | -------------------------------------------------------------------------------- /apps/web/src/app/api/callback/pagerduty/route.ts: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export async function GET(request: Request) { 4 | const { searchParams } = new URL(request.url); 5 | const workspace = searchParams.get("workspace"); 6 | const url = `${ 7 | process.env.NODE_ENV === "development" // FIXME: This sucks 8 | ? "http://localhost:3000" 9 | : "https://www.openstatus.dev" 10 | }/app/${workspace}/notifications/new/pagerduty?${searchParams}`; 11 | redirect(url); 12 | } 13 | -------------------------------------------------------------------------------- /apps/web/src/app/api/checker/utils.ts: -------------------------------------------------------------------------------- 1 | export const isAnInvalidTestUrl = (rawUrl: string) => { 2 | const url = new URL(rawUrl); 3 | const isSelfHostName = url.hostname 4 | .split(".") 5 | .slice(-2) // ex: any.sub.openstatus.dev 6 | .join(".") 7 | .includes("openstatus.dev"); // ex: openstatus.dev:80 8 | 9 | return isSelfHostName && url.pathname.startsWith("/api/checker/"); 10 | }; 11 | -------------------------------------------------------------------------------- /apps/web/src/app/api/ping/cold/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export const dynamic = "force-dynamic"; 4 | 5 | export const maxDuration = 30; // to trick and not using the same function as the other ping route 6 | 7 | export async function GET() { 8 | return NextResponse.json({ ping: "pong" }, { status: 200 }); 9 | } 10 | 11 | export async function POST(req: Request) { 12 | const body = await req.json(); 13 | return NextResponse.json({ ping: body }, { status: 200 }); 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/app/api/ping/edge/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export const runtime = "edge"; 4 | export const dynamic = "force-dynamic"; 5 | 6 | export async function GET() { 7 | return NextResponse.json({ ping: "pong" }, { status: 200 }); 8 | } 9 | 10 | export async function POST(req: Request) { 11 | const body = await req.json(); 12 | return NextResponse.json({ ping: body }, { status: 200 }); 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/app/api/ping/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export const dynamic = "force-dynamic"; 4 | 5 | export const maxDuration = 25; // to trick and not using the same function as the other ping route 6 | 7 | export async function GET() { 8 | return NextResponse.json({ ping: "pong" }, { status: 200 }); 9 | } 10 | 11 | export async function POST(req: Request) { 12 | const body = await req.json(); 13 | return NextResponse.json({ ping: body }, { status: 200 }); 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/app/api/ping/test/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export const dynamic = "force-dynamic"; 4 | 5 | export const maxDuration = 31; // to trick and not using the same function as the other ping route 6 | 7 | export async function GET() { 8 | return NextResponse.json({ ping: "pong" }, { status: 200 }); 9 | } 10 | 11 | export async function POST(req: Request) { 12 | const body = await req.json(); 13 | return NextResponse.json({ ping: body }, { status: 200 }); 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/app/api/ping/vercel/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export const dynamic = "force-dynamic"; 4 | 5 | export const maxDuration = 42; // to trick and not using the same function as the other ping route 6 | 7 | export async function GET() { 8 | return NextResponse.json({ ping: "pong" }, { status: 200 }); 9 | } 10 | 11 | export async function POST(req: Request) { 12 | const body = await req.json(); 13 | return NextResponse.json({ ping: body }, { status: 200 }); 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/app/api/ping/warn/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | export const dynamic = "force-dynamic"; 4 | export const maxDuration = 20; // to trick and not using the same function as the other ping route 5 | 6 | export async function GET() { 7 | return NextResponse.json({ ping: "pong" }, { status: 200 }); 8 | } 9 | 10 | export async function POST(req: Request) { 11 | const body = await req.json(); 12 | return NextResponse.json({ ping: body }, { status: 200 }); 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/app/api/test/timeout/route.ts: -------------------------------------------------------------------------------- 1 | import { NextResponse } from "next/server"; 2 | 3 | import { wait } from "@/lib/utils"; 4 | 5 | export async function POST() { 6 | await wait(10_000); 7 | return NextResponse.json({ message: "Hello, World!" }); 8 | } 9 | 10 | export async function GET() { 11 | await wait(10_000); 12 | return NextResponse.json({ message: "Hello, World!" }); 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/app/app/(auth)/login/_components/actions.ts: -------------------------------------------------------------------------------- 1 | "use server"; 2 | 3 | import { signIn } from "@/lib/auth"; 4 | 5 | export async function signInWithResendAction(formData: FormData) { 6 | try { 7 | await signIn("resend", formData); 8 | } catch (_e) { 9 | // console.error(e); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /apps/web/src/app/app/(auth)/login/search-params.ts: -------------------------------------------------------------------------------- 1 | import { createSearchParamsCache, parseAsString } from "nuqs/server"; 2 | 3 | export const searchParamsParsers = { 4 | redirectTo: parseAsString.withDefault("/app"), 5 | }; 6 | 7 | export const searchParamsCache = createSearchParamsCache(searchParamsParsers); 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/(auth)/sign-in/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function Page() { 4 | return redirect("/app/login"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/(auth)/sign-up/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default function Page() { 4 | return redirect("/app/login"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/incidents/(overview)/loading.tsx: -------------------------------------------------------------------------------- 1 | import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/incidents/[id]/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default async function Page(props: { 4 | params: Promise<{ workspaceSlug: string; id: string }>; 5 | }) { 6 | const params = await props.params; 7 | return redirect(`./${params.id}/overview`); 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/(overview)/loading.tsx: -------------------------------------------------------------------------------- 1 | import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"; 2 | import { DataTableToolbarSkeleton } from "@/components/data-table/data-table-toolbar-skeleton"; 3 | 4 | export default function Loading() { 5 | return ( 6 |
7 | 8 | 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/(overview)/search-params.ts: -------------------------------------------------------------------------------- 1 | import { 2 | createSearchParamsCache, 3 | parseAsArrayOf, 4 | parseAsBoolean, 5 | parseAsInteger, 6 | parseAsString, 7 | } from "nuqs/server"; 8 | 9 | export const searchParamsParsers = { 10 | tags: parseAsArrayOf(parseAsString), 11 | public: parseAsArrayOf(parseAsBoolean), 12 | pageSize: parseAsInteger.withDefault(10), 13 | pageIndex: parseAsInteger.withDefault(0), 14 | }; 15 | 16 | export const searchParamsCache = createSearchParamsCache(searchParamsParsers); 17 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/edit/loading.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonForm } from "@/components/forms/skeleton-form"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/edit/search-params.ts: -------------------------------------------------------------------------------- 1 | import { createSearchParamsCache, parseAsString } from "nuqs/server"; 2 | 3 | export const searchParamsParsers = { 4 | section: parseAsString.withDefault("request"), 5 | }; 6 | 7 | export const searchParamsCache = createSearchParamsCache(searchParamsParsers); 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/[id]/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default async function Page(props: { 4 | params: Promise<{ workspaceSlug: string; id: string }>; 5 | }) { 6 | const params = await props.params; 7 | return redirect(`./${params.id}/overview`); 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/new/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Header } from "@/components/dashboard/header"; 2 | import AppPageLayout from "@/components/layout/app-page-layout"; 3 | 4 | export default async function Layout({ 5 | children, 6 | }: { 7 | children: React.ReactNode; 8 | }) { 9 | return ( 10 | 11 |
12 | {children} 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/new/loading.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonForm } from "@/components/forms/skeleton-form"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/monitors/new/search-params.ts: -------------------------------------------------------------------------------- 1 | import { createSearchParamsCache, parseAsString } from "nuqs/server"; 2 | 3 | export const searchParamsParsers = { 4 | section: parseAsString.withDefault("request"), 5 | }; 6 | 7 | export const searchParamsCache = createSearchParamsCache(searchParamsParsers); 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/notifications/(overview)/loading.tsx: -------------------------------------------------------------------------------- 1 | import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/notifications/[id]/edit/loading.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonForm } from "@/components/forms/skeleton-form"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/notifications/[id]/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default async function Page(props: { 4 | params: Promise<{ workspaceSlug: string; id: string }>; 5 | }) { 6 | const params = await props.params; 7 | return redirect(`./${params.id}/edit`); 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/notifications/new/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Header } from "@/components/dashboard/header"; 2 | import AppPageLayout from "@/components/layout/app-page-layout"; 3 | 4 | export default async function Layout({ 5 | children, 6 | }: { 7 | children: React.ReactNode; 8 | }) { 9 | return ( 10 | 11 |
15 | {children} 16 | 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/notifications/new/loading.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonForm } from "@/components/forms/skeleton-form"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/notifications/new/pagerduty/search-params.ts: -------------------------------------------------------------------------------- 1 | import { createSearchParamsCache, parseAsString } from "nuqs/server"; 2 | 3 | export const searchParamsParsers = { 4 | config: parseAsString, 5 | }; 6 | 7 | export const searchParamsCache = createSearchParamsCache(searchParamsParsers); 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default async function DashboardRedirect(props: { 4 | params: Promise<{ workspaceSlug: string }>; 5 | }) { 6 | const params = await props.params; 7 | return redirect(`/app/${params.workspaceSlug}/monitors`); 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/api-token/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Header } from "@/components/dashboard/header"; 2 | import { getPageBySegment } from "@/config/pages"; 3 | 4 | const page = getPageBySegment(["settings", "api-token"]); 5 | 6 | export default function Layout({ children }: { children: React.ReactNode }) { 7 | return ( 8 | <> 9 |
10 | {children} 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/api-token/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from "@openstatus/ui"; 2 | 3 | // TODO: can be improved... 4 | 5 | export default function Loading() { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/appearance/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Header } from "@/components/dashboard/header"; 2 | import { getPageBySegment } from "@/config/pages"; 3 | 4 | const page = getPageBySegment(["settings", "appearance"]); 5 | 6 | export default function Layout({ children }: { children: React.ReactNode }) { 7 | return ( 8 | <> 9 |
10 | {children} 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/appearance/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from "@openstatus/ui"; 2 | 3 | // TODO: can be improved... 4 | 5 | export default function Loading() { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/billing/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Header } from "@/components/dashboard/header"; 2 | import { getPageBySegment } from "@/config/pages"; 3 | 4 | const page = getPageBySegment(["settings", "billing"]); 5 | 6 | export default function Layout({ children }: { children: React.ReactNode }) { 7 | return ( 8 | <> 9 |
10 | {children} 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/billing/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from "@openstatus/ui"; 2 | 3 | // TODO: can be improved... 4 | 5 | export default function Loading() { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/general/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Header } from "@/components/dashboard/header"; 2 | import { getPageBySegment } from "@/config/pages"; 3 | 4 | const page = getPageBySegment(["settings", "general"]); 5 | 6 | export default function Layout({ children }: { children: React.ReactNode }) { 7 | return ( 8 | <> 9 |
10 | {children} 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/general/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from "@openstatus/ui"; 2 | 3 | // TODO: can be improved... 4 | 5 | export default function Loading() { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/layout.tsx: -------------------------------------------------------------------------------- 1 | import AppPageWithSidebarLayout from "@/components/layout/app-page-with-sidebar-layout"; 2 | 3 | export default function SettingsLayout({ 4 | children, 5 | }: { 6 | children: React.ReactNode; 7 | }) { 8 | return ( 9 | 10 | {children} 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default async function SettingsPage(props: { 4 | params: Promise<{ workspaceSlug: string }>; 5 | }) { 6 | const params = await props.params; 7 | return redirect(`/app/${params.workspaceSlug}/settings/general`); 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/team/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Header } from "@/components/dashboard/header"; 2 | import { getPageBySegment } from "@/config/pages"; 3 | 4 | const page = getPageBySegment(["settings", "team"]); 5 | 6 | export default function Layout({ children }: { children: React.ReactNode }) { 7 | return ( 8 | <> 9 |
10 | {children} 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/team/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from "@openstatus/ui"; 2 | 3 | // TODO: can be improved... 4 | 5 | export default function Loading() { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/user/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Header } from "@/components/dashboard/header"; 2 | import { getPageBySegment } from "@/config/pages"; 3 | 4 | const page = getPageBySegment(["settings", "user"]); 5 | 6 | export default function Layout({ children }: { children: React.ReactNode }) { 7 | return ( 8 | <> 9 |
10 | {children} 11 | 12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/settings/user/loading.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from "@openstatus/ui"; 2 | 3 | // TODO: can be improved... 4 | 5 | export default function Loading() { 6 | return ; 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/(overview)/loading.tsx: -------------------------------------------------------------------------------- 1 | import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/domain/loading.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonForm } from "@/components/forms/skeleton-form"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/edit/loading.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonForm } from "@/components/forms/skeleton-form"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/edit/search-params.ts: -------------------------------------------------------------------------------- 1 | import { createSearchParamsCache, parseAsString } from "nuqs/server"; 2 | 3 | export const searchParamsParsers = { 4 | section: parseAsString.withDefault("monitors"), 5 | }; 6 | 7 | export const searchParamsCache = createSearchParamsCache(searchParamsParsers); 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default async function Page(props: { 4 | params: Promise<{ workspaceSlug: string; id: string }>; 5 | }) { 6 | const params = await props.params; 7 | return redirect(`./${params.id}/edit`); 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/(overview)/loading.tsx: -------------------------------------------------------------------------------- 1 | import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/edit/loading.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonForm } from "@/components/forms/skeleton-form"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/[reportId]/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default async function Page(props: { 4 | params: Promise<{ workspaceSlug: string; reportId: string }>; 5 | }) { 6 | const params = await props.params; 7 | return redirect(`./${params.reportId}/overview`); 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/reports/new/loading.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonForm } from "@/components/forms/skeleton-form"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/[id]/subscribers/loading.tsx: -------------------------------------------------------------------------------- 1 | import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/new/layout.tsx: -------------------------------------------------------------------------------- 1 | import { Header } from "@/components/dashboard/header"; 2 | import AppPageLayout from "@/components/layout/app-page-layout"; 3 | 4 | export default async function Layout({ 5 | children, 6 | }: { 7 | children: React.ReactNode; 8 | }) { 9 | return ( 10 | 11 |
12 | {children} 13 | 14 | ); 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/app/app/[workspaceSlug]/(dashboard)/status-pages/new/loading.tsx: -------------------------------------------------------------------------------- 1 | import { SkeletonForm } from "@/components/forms/skeleton-form"; 2 | 3 | export default function Loading() { 4 | return ; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/app/invite/search-params.ts: -------------------------------------------------------------------------------- 1 | import { createSearchParamsCache, parseAsString } from "nuqs/server"; 2 | 3 | export const searchParamsParsers = { 4 | token: parseAsString, 5 | }; 6 | 7 | export const searchParamsCache = createSearchParamsCache(searchParamsParsers); 8 | -------------------------------------------------------------------------------- /apps/web/src/app/app/onboarding/page.tsx: -------------------------------------------------------------------------------- 1 | import { auth } from "@/lib/auth"; 2 | import { api } from "@/trpc/server"; 3 | import { redirect } from "next/navigation"; 4 | 5 | export default async function OnboardingPage() { 6 | const session = await auth(); 7 | 8 | if (!session) redirect("/app/login"); 9 | 10 | const workspace = await api.workspace.getWorkspace.query(); 11 | 12 | if (!workspace) redirect("/app/login"); 13 | 14 | return redirect(`/app/${workspace.slug}/onboarding`); 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/app/apple-icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/src/app/apple-icon.ico -------------------------------------------------------------------------------- /apps/web/src/app/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/src/app/favicon.ico -------------------------------------------------------------------------------- /apps/web/src/app/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/src/app/icon.png -------------------------------------------------------------------------------- /apps/web/src/app/legal/[slug]/layout.tsx: -------------------------------------------------------------------------------- 1 | import { MarketingLayout } from "@/components/layout/marketing-layout"; 2 | import type { ReactNode } from "react"; 3 | 4 | export default function BlogLayout({ children }: { children: ReactNode }) { 5 | return {children}; 6 | } 7 | -------------------------------------------------------------------------------- /apps/web/src/app/play/checker/[id]/search-params.ts: -------------------------------------------------------------------------------- 1 | import { flyRegions } from "@openstatus/db/src/schema/constants"; 2 | import { 3 | createSearchParamsCache, 4 | parseAsArrayOf, 5 | parseAsString, 6 | parseAsStringLiteral, 7 | } from "nuqs/server"; 8 | 9 | export const searchParamsParsers = { 10 | regions: parseAsArrayOf(parseAsStringLiteral(flyRegions)), 11 | }; 12 | 13 | export const searchParamsCache = createSearchParamsCache(searchParamsParsers); 14 | -------------------------------------------------------------------------------- /apps/web/src/app/play/checker/search-params.ts: -------------------------------------------------------------------------------- 1 | import { createSearchParamsCache, parseAsString } from "nuqs/server"; 2 | 3 | export const searchParamsParsers = { 4 | id: parseAsString, 5 | }; 6 | 7 | export const searchParamsCache = createSearchParamsCache(searchParamsParsers); 8 | -------------------------------------------------------------------------------- /apps/web/src/app/play/default.tsx: -------------------------------------------------------------------------------- 1 | export default function Default() { 2 | return null; 3 | } 4 | -------------------------------------------------------------------------------- /apps/web/src/app/robots.ts: -------------------------------------------------------------------------------- 1 | import type { MetadataRoute } from "next"; 2 | 3 | export default function robots(): MetadataRoute.Robots { 4 | return { 5 | rules: { 6 | userAgent: "*", 7 | allow: "/", 8 | }, 9 | sitemap: "https://www.openstatus.dev/sitemap.xml", 10 | }; 11 | } 12 | -------------------------------------------------------------------------------- /apps/web/src/app/status-page/[domain]/events/search-params.ts: -------------------------------------------------------------------------------- 1 | import { createSearchParamsCache, parseAsStringLiteral } from "nuqs/server"; 2 | 3 | export const searchParamsParsers = { 4 | filter: parseAsStringLiteral(["all", "maintenances", "reports"]).withDefault( 5 | "all", 6 | ), 7 | }; 8 | export const searchParamsCache = createSearchParamsCache(searchParamsParsers); 9 | -------------------------------------------------------------------------------- /apps/web/src/app/status-page/[domain]/events/utils.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | export function formatter(value: string) { 4 | return {value}; 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/status-page/[domain]/incidents/[id]/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default async function IncidentPage(props: { 4 | params: Promise<{ domain: string; id: string }>; 5 | }) { 6 | const params = await props.params; 7 | redirect(`../events/report/${params.id}`); 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/app/status-page/[domain]/incidents/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default async function Page() { 4 | redirect("./events?filter=reports"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/status-page/[domain]/maintenances/page.tsx: -------------------------------------------------------------------------------- 1 | import { redirect } from "next/navigation"; 2 | 3 | export default async function Page() { 4 | redirect("./events?filter=maintenances"); 5 | } 6 | -------------------------------------------------------------------------------- /apps/web/src/app/status-page/[domain]/monitors/search-params.ts: -------------------------------------------------------------------------------- 1 | import { quantiles } from "@/lib/monitor/utils"; 2 | import { createSearchParamsCache, parseAsStringLiteral } from "nuqs/server"; 3 | 4 | export const searchParamsParsers = { 5 | quantile: parseAsStringLiteral(quantiles).withDefault("p95"), 6 | period: parseAsStringLiteral(["7d"]).withDefault("7d"), 7 | }; 8 | export const searchParamsCache = createSearchParamsCache(searchParamsParsers); 9 | -------------------------------------------------------------------------------- /apps/web/src/components/billing/pro-feature-badge.tsx: -------------------------------------------------------------------------------- 1 | import type { WorkspacePlan } from "@openstatus/db/src/schema"; 2 | import { Badge } from "@openstatus/ui"; 3 | import { upgradePlan } from "./utils"; 4 | 5 | export function ProFeatureBadge({ 6 | plan, 7 | minRequiredPlan, 8 | }: { 9 | plan: WorkspacePlan; 10 | minRequiredPlan: WorkspacePlan; 11 | }) { 12 | const shouldUpgrade = upgradePlan(plan, minRequiredPlan); 13 | 14 | if (!shouldUpgrade) return null; 15 | 16 | return {minRequiredPlan}; 17 | } 18 | -------------------------------------------------------------------------------- /apps/web/src/components/billing/utils.ts: -------------------------------------------------------------------------------- 1 | import { workspacePlanHierarchy } from "@openstatus/db/src/schema"; 2 | import type { WorkspacePlan } from "@openstatus/db/src/schema/workspaces/validation"; 3 | 4 | export function upgradePlan(current: WorkspacePlan, required: WorkspacePlan) { 5 | return workspacePlanHierarchy[current] < workspacePlanHierarchy[required]; 6 | } 7 | -------------------------------------------------------------------------------- /apps/web/src/components/content/preview.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useProcessor } from "@/hooks/use-preprocessor"; 4 | 5 | interface Props { 6 | md?: string; 7 | } 8 | 9 | export function Preview({ md }: Props) { 10 | const Component = useProcessor(md || ""); 11 | return ( 12 |
13 | {Component} 14 |
15 | ); 16 | } 17 | -------------------------------------------------------------------------------- /apps/web/src/components/dashboard/shell.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | type ShellProps = React.HTMLAttributes; 4 | 5 | function Shell({ children, className }: ShellProps) { 6 | return ( 7 |
13 | {children} 14 |
15 | ); 16 | } 17 | 18 | export { Shell }; 19 | -------------------------------------------------------------------------------- /apps/web/src/components/data-table/data-table-region-select.tsx: -------------------------------------------------------------------------------- 1 | export default function DataTableRegionSelect() { 2 | return
; 3 | } 4 | -------------------------------------------------------------------------------- /apps/web/src/components/data-table/data-table-status-badge.tsx: -------------------------------------------------------------------------------- 1 | import { Badge } from "@openstatus/ui/src/components/badge"; 2 | 3 | import { StatusCodeBadge } from "@/components/monitor/status-code-badge"; 4 | 5 | export function DataTableStatusBadge({ 6 | statusCode, 7 | }: { 8 | statusCode?: number | null; 9 | }) { 10 | if (!statusCode) { 11 | return Error; 12 | } 13 | return ; 14 | } 15 | -------------------------------------------------------------------------------- /apps/web/src/components/data-table/data-table-toolbar-skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { Skeleton } from "@openstatus/ui"; 2 | 3 | export function DataTableToolbarSkeleton() { 4 | return ( 5 |
6 |
7 | 8 |
9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /apps/web/src/components/forms/shared/section-header.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | 3 | export function SectionHeader({ 4 | title, 5 | description, 6 | className, 7 | }: { 8 | title: string; 9 | description: React.ReactNode; 10 | className?: string; 11 | }) { 12 | return ( 13 |
14 |

{title}

15 |

{description}

16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /apps/web/src/components/layout/public-header.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "@/lib/utils"; 2 | import { BrandName } from "./brand-name"; 3 | import { LoginButton } from "./login-button"; 4 | 5 | interface Props { 6 | className?: string; 7 | } 8 | 9 | export function PublicHeader({ className }: Props) { 10 | return ( 11 |
14 | 15 | 16 |
17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /apps/web/src/components/monitor/tag-badge.tsx: -------------------------------------------------------------------------------- 1 | import { Badge } from "@openstatus/ui/src/components/badge"; 2 | 3 | function getStyle(color: string) { 4 | return { 5 | borderColor: `${color}10`, 6 | backgroundColor: `${color}20`, 7 | color, 8 | }; 9 | } 10 | 11 | interface TagBadgeProps { 12 | name: string; 13 | color: string; 14 | } 15 | 16 | export function TagBadge({ color, name }: TagBadgeProps) { 17 | return {name}; 18 | } 19 | -------------------------------------------------------------------------------- /apps/web/src/components/templates/email-template.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | interface EmailTemplateProps { 4 | firstName: string; 5 | } 6 | 7 | // TODO: rename and content 8 | export const EmailTemplate = ({ firstName }: EmailTemplateProps) => ( 9 |
10 |

Welcome, {firstName}!

11 |
12 | ); 13 | -------------------------------------------------------------------------------- /apps/web/src/components/theme-provider.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { ThemeProvider as NextThemesProvider } from "next-themes"; 4 | import type { ThemeProviderProps } from "next-themes/dist/types"; 5 | import * as React from "react"; 6 | 7 | export function ThemeProvider({ children, ...props }: ThemeProviderProps) { 8 | return {children}; 9 | } 10 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/binary-payload.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Binary payload 3 | description: Send binary payloads with your HTTP synthetic check requests. 4 | image: /assets/changelog/content-type.png 5 | publishedAt: 2024-09-09 6 | --- 7 | 8 | You can now include binary payloads in your HTTP synthetic check requests, which is handy for sending files or other binary data in the request body. 9 | 10 | Additionally, you have the flexibility to set the Content-Type to your preference, such as `application/octet-stream` or `application/edn`. 11 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/check-run-api.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Run Check API 3 | description: Launch a check with our API to test your endpoint's latency. 4 | image: /assets/changelog/check-api.png 5 | publishedAt: 2024-06-18 6 | --- 7 | 8 | We have added a new API to launch a check with OpenStatus. You can now test your endpoint's latency programmatically. 9 | 10 | It's useful if you want to integrate OpenStatus with your CI/CD pipeline. 11 | 12 | You can read the [API documentation](https://api.openstatus.dev/v1#tag/monitor/POST/monitor/:id/trigger). 13 | 14 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/clone-monitor.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Clone Monitor 3 | description: No more work. Just a click. 4 | image: /assets/changelog/clone-monitor.png 5 | publishedAt: 2024-07-14 6 | --- 7 | Sometimes you need to create a copy of your monitor with the same settings quickly and easily. 8 | 9 | You can now clone a monitor directly from the action menu in the monitor table. 10 | 11 | We have added this feature to the monitor settings. 12 | 13 | Shout-out to [@Ipriyankrajai](https://x.com/Ipriyankrajai) for his contribution! 14 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/curl-builder-playground.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: cURL Builder 3 | description: An online curl command line builder. Generate curl commands to test your API endpoints. 4 | image: /assets/changelog/curl-builder-playground.png 5 | publishedAt: 2024-11-14 6 | --- 7 | 8 | An online curl command line builder. Generate curl commands to test your API endpoints. 9 | 10 | Go to the **[Playground](/play/curl)** and test it. -------------------------------------------------------------------------------- /apps/web/src/content/changelog/dark-theme-support.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Dark mode support 3 | description: Choose your favorite theme. Dark or light. 4 | image: /assets/changelog/dark-theme-support.png 5 | publishedAt: 2023-11-27 6 | --- 7 | 8 | You can now use dark mode on the website, after a long awaited pull request 9 | [#73](https://github.com/openstatusHQ/openstatus/pull/73) has been merged. 10 | 11 | The **default** theme will still be **light** mode. You can change the theme in 12 | the footer of the website. 13 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/individual-status-report-page.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Invidivual Status Report Page 3 | description: Every created status report now has its own page. 4 | publishedAt: 2023-12-22 5 | image: /assets/changelog/individual-status-report-page.png 6 | --- 7 | 8 | Every created status report now has its own page. That will make it easier to 9 | share the status report with your team and across your users. 10 | 11 | Additionally, we've addded a neutral blue color to the tracker whenever a status 12 | report has been published. 13 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/monitor-tags.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Monitor Tags 3 | description: Easily categorize your monitors with tags. 4 | image: /assets/changelog/monitor-tags.png 5 | publishedAt: 2024-03-20 6 | --- 7 | 8 | You can now create tags for your monitors to easily categorize them. Tags can be 9 | used to filter monitors on the dashboard and in the monitor list. 10 | 11 | Create, update or delete a tag via your monitor settings. 12 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/monitor-threshold.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Monitor Threshold 3 | description: Set custom request timeouts and degradation timing. 4 | image: /assets/changelog/monitor-threshold.png 5 | publishedAt: 2024-07-01 6 | --- 7 | Sometimes you need to get notified if your monitor is taking too long to respond or if it's degrading. 8 | 9 | You can set custom request timeouts and degradation timing for your monitors. 10 | 11 | We have added this feature to the monitor settings. 12 | 13 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/ntfy-sh-integration.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: ntfy.sh Integration 3 | description: Get notified via ntfy.sh if we detect an Incident. 4 | image: /assets/changelog/ntfy.png 5 | publishedAt: 2025-03-17 6 | --- 7 | You can now receive notifications via ntfy.sh when we detect an incident. 8 | 9 | [ntfy.sh](https://ntfy.sh/) is an open-source servicer that allows you to receive push notifications on your phone. 10 | 11 | We love open source, so we've added this integration to our free plan. 12 | 13 | Open source FTW 🚀 -------------------------------------------------------------------------------- /apps/web/src/content/changelog/pagerduty-integration.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: PagerDuty Integration 3 | description: Get notified via PagerDuty if we detect an incident. 4 | image: /assets/changelog/pagerduty-integration.png 5 | publishedAt: 2024-06-25 6 | --- 7 | 8 | We've added a PagerDuty integration to the notification feature. This allows you to receive incident alerts through PagerDuty. -------------------------------------------------------------------------------- /apps/web/src/content/changelog/play-checker-improvements.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Speed Checker 3 | description: Improving the speed checker playground for a better experience. 4 | image: /assets/changelog/play-checker-improvements.png 5 | publishedAt: 2024-08-27 6 | --- 7 | 8 | We've refreshed the Playground for a better experience. Now, access real-time data without leaving the page. 9 | 10 | Check out the [Speed Checker](/play/checker). -------------------------------------------------------------------------------- /apps/web/src/content/changelog/response-time-charts.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Response Time Charts 3 | description: You have now access to new charts for better visualization. 4 | publishedAt: 2023-10-08 5 | image: /assets/changelog/response-time-charts.png 6 | --- 7 | 8 | You can now assess your monitor's response time using the new charts and get a 9 | better overview of your monitor's performance. 10 | 11 | Powered by [tremor.so](https://tremor.so). 12 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/slack-discord-notification.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Slack and Discord notifications 3 | description: You can now send notifications to your favorite channels. 4 | publishedAt: 2023-11-01 5 | image: /assets/changelog/slack-discord-notification.png 6 | --- 7 | 8 | We have just released a new feature that allows you to receive notifications in 9 | Slack or Discord when your monitor is down. 10 | 11 | Thanks [Kelvin](https://github.com/AmoabaKelvin) for the help 🔥 12 | 13 | Expect more integration to come soon! 14 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/status-page-colors-and-more.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Status Page rework 3 | description: New status specific colors, improved navigation and more. 4 | publishedAt: 2024-07-21 5 | image: /assets/changelog/status-page-colors-and-more.png 6 | --- 7 | 8 | We have reworked our status page! 9 | 10 | - **less flashy colors** for _operational_, _degraded_, _downtime_ and _maintenance_ 11 | - **new sticky navigation** bar, merging _maintenances_ and _incidents_ into an _events_ page (your old links will still work) 12 | - redesign of **status reports** -------------------------------------------------------------------------------- /apps/web/src/content/changelog/status-page-feed.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Status Page Feeds 3 | description: Subscribe to status page updates via RSS and Atom feed. 4 | image: /assets/changelog/status-page-feed.png 5 | publishedAt: 2025-01-04 6 | --- 7 | 8 | You can now subscribe via RSS and Atom feed on any status page! 9 | 10 | S/o to [@washingtonserip](https://x.com/washingtonserip) for this contribution. -------------------------------------------------------------------------------- /apps/web/src/content/changelog/status-page-monitor-values-visibility.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Monitor values visibility 3 | description: Hide the uptime and number of request on your status pages. 4 | publishedAt: 2024-10-20 5 | image: /assets/changelog/status-page-monitor-values-visibility.png 6 | --- 7 | 8 | 9 | You can now hide your request values. 10 | 11 | We have added a checkbox within your Status Page settings to hide/show the number of total and failed requests incl. the average percentage for each monitor connected to the page. -------------------------------------------------------------------------------- /apps/web/src/content/changelog/status-report-location-change.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Status Report location change 3 | description: Each report is now saved within a Status Page. 4 | publishedAt: 2024-07-14 5 | image: /assets/changelog/status-report-location-change.png 6 | --- 7 | 8 | The location of your reports has changed. The can be found within the connected status page. No need to connect manually to a status page. 9 | 10 | If you encounter any issues. Please [contact us](mailto:ping@openstatus.dev). -------------------------------------------------------------------------------- /apps/web/src/content/changelog/status-update-subscriber.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Status Update Subscriber 3 | description: You can now subscribe to pro plan status updates via email. 4 | publishedAt: 2023-12-11 5 | image: /assets/changelog/status-update-subscriber.png 6 | --- 7 | 8 | You can now subscribe to pro plan status updates via email. 9 | 10 | As a subscriber, we require you to verify your email address to avoid spam. You 11 | can do this by clicking the link in the email we send you after you subscribe. 12 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/team-invites.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Team invites 3 | description: Invite your team members to your workspace 4 | image: /assets/changelog/team-invites.png 5 | publishedAt: 2023-12-08 6 | --- 7 | 8 | As a Pro plan user, you can now invite you favorite team members to your 9 | workspace and collaborate on your project together. 10 | -------------------------------------------------------------------------------- /apps/web/src/content/changelog/webhook-integration.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Webhook Integration 3 | description: Get notified via webhook if we detect an Incident.. 4 | image: /assets/changelog/webhook.png 5 | publishedAt: 2025-04-08 6 | --- 7 | 8 | When your monitor's status changes, you can receive notifications through a webhook. 9 | 10 | This feature is included in every plan. 11 | 12 | For more information, check our [documentation](https://docs.openstatus.dev/alerting/providers/webhook/). 13 | -------------------------------------------------------------------------------- /apps/web/src/content/faq/about-us.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: Who are we? 3 | order: 2 4 | --- 5 | 6 | We are [Thibault](https://bsky.app/profile/thibaultleouay.dev) and 7 | [Max](https://twitter.com/mxkaske) and we take you with us on our journey. 8 | 9 | Read more on our [about](/about) page. 10 | -------------------------------------------------------------------------------- /apps/web/src/content/faq/functioning.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: How does it work? 3 | order: 3 4 | --- 5 | 6 | We ping your endpoints from multiple regions to calculate uptime and display the 7 | current status on your status page. We also collect response time data like 8 | `headers` and `timing` phases and display it on your dashboard. 9 | 10 | Try out the [Speed Checker](/play/checker). 11 | -------------------------------------------------------------------------------- /apps/web/src/content/faq/limits.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: What are the limits? 3 | order: 1 4 | --- 5 | 6 | As free user you will start with a total of **1 monitor** and **1 status page** 7 | as well as cron jobs of min. `10m`. You can upgrade to a paid plan at any time. 8 | Check the pricing table for more details. 9 | 10 | **No credit card** is required to sign up and you can cancel at any time. 11 | -------------------------------------------------------------------------------- /apps/web/src/content/unrelated/ci-cd-features-block.mdx: -------------------------------------------------------------------------------- 1 | ```ts 2 | test("should fail if slow", async () => { 3 | const data = await fetch("https://api.openstatus.dev/v1/monitor/:id/run", { 4 | method: "POST", 5 | headers: { "x-openstatus-key": process.env.OPENSTATUS_API_KEY }, 6 | }); 7 | const body = await data.json(); 8 | 9 | expect(body.status).toBe(200); 10 | expect(body.latency).toBeLessThan(1000); 11 | }); 12 | ``` 13 | -------------------------------------------------------------------------------- /apps/web/src/content/unrelated/cli-block.mdx: -------------------------------------------------------------------------------- 1 | ```bash 2 | openstatus monitors trigger [id] 3 | ``` 4 | -------------------------------------------------------------------------------- /apps/web/src/content/unrelated/github-action-block.mdx: -------------------------------------------------------------------------------- 1 | ```yaml 2 | name: Run OpenStatus Synthetics CI 3 | 4 | on: 5 | workflow_dispatch: 6 | push: 7 | branches: [main] 8 | 9 | jobs: 10 | synthetic_ci: 11 | runs-on: ubuntu-latest 12 | name: Run OpenStatus Synthetics CI 13 | steps: 14 | - name: Checkout 15 | uses: actions/checkout@v4 16 | - name: Run OpenStatus Synthetics CI 17 | uses: openstatushq/openstatus-github-action@v1 18 | with: 19 | api_key: ${{ secrets.OPENSTATUS_API_KEY }} 20 | ``` -------------------------------------------------------------------------------- /apps/web/src/content/unrelated/terraform-provider-block.mdx: -------------------------------------------------------------------------------- 1 | ```hcl 2 | provider "openstatus" { 3 | openstatus_api_token= "YOUR_API_TOKEN" 4 | } 5 | 6 | resource "openstatus_monitor" "my_monitor" { 7 | url = "https://www.openstatus.dev" 8 | regions= ["iad", "jnb"] 9 | periodicity = "10m" 10 | name = "test-monitor" 11 | active = true 12 | description = "This is a test monitor" 13 | } 14 | ``` -------------------------------------------------------------------------------- /apps/web/src/hooks/use-debounce.ts: -------------------------------------------------------------------------------- 1 | import * as React from "react"; 2 | 3 | // consider using https://github.com/xnimorz/use-debounce 4 | export function useDebounce(value: T, delay?: number): T { 5 | const [debouncedValue, setDebouncedValue] = React.useState(value); 6 | 7 | React.useEffect(() => { 8 | const timer = setTimeout(() => setDebouncedValue(value), delay ?? 500); 9 | 10 | return () => { 11 | clearTimeout(timer); 12 | }; 13 | }, [value, delay]); 14 | 15 | return debouncedValue; 16 | } 17 | -------------------------------------------------------------------------------- /apps/web/src/instrumentation.ts: -------------------------------------------------------------------------------- 1 | import * as Sentry from "@sentry/nextjs"; 2 | 3 | export async function register() { 4 | if (process.env.NEXT_RUNTIME === "nodejs") { 5 | await import("../sentry.server.config"); 6 | } 7 | 8 | if (process.env.NEXT_RUNTIME === "edge") { 9 | await import("../sentry.edge.config"); 10 | } 11 | } 12 | 13 | export const onRequestError = Sentry.captureRequestError; 14 | -------------------------------------------------------------------------------- /apps/web/src/lib/github.ts: -------------------------------------------------------------------------------- 1 | import * as z from "zod"; 2 | 3 | const schema = z.object({ 4 | stargazers_count: z.number(), 5 | }); 6 | 7 | export async function getGitHubStars() { 8 | const res = await fetch( 9 | "https://api.github.com/repos/openstatusHQ/openstatus", 10 | { next: { revalidate: 600 } }, // 10min 11 | ); 12 | const json = await res.json(); 13 | const github = schema.safeParse(json); 14 | 15 | if (!github.success) return 0; 16 | return github.data.stargazers_count; 17 | } 18 | -------------------------------------------------------------------------------- /apps/web/src/lib/maintenances/utils.ts: -------------------------------------------------------------------------------- 1 | import type { Maintenance } from "@openstatus/db/src/schema"; 2 | 3 | export function isActiveMaintenance(maintenances?: Maintenance[]) { 4 | if (!maintenances) return false; 5 | return maintenances.some((maintenance) => { 6 | return maintenance.from <= new Date() && maintenance.to >= new Date(); 7 | }); 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/lib/preferred-settings/shared.ts: -------------------------------------------------------------------------------- 1 | export const COOKIE_NAME = "preferred-settings"; 2 | -------------------------------------------------------------------------------- /apps/web/src/lib/preferred-settings/validation.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const preferencesSchema = z 4 | .object({ 5 | combinedRegions: z.boolean().nullable().default(false).optional(), 6 | // ... other settings to store user preferences 7 | // accessible via document.cookie in the client and cookies() on the server 8 | }) 9 | .optional(); 10 | 11 | export type PreferredSettings = z.infer; 12 | -------------------------------------------------------------------------------- /apps/web/src/lib/stripe/client.ts: -------------------------------------------------------------------------------- 1 | import type { Stripe as StripeProps } from "@stripe/stripe-js"; 2 | import { loadStripe } from "@stripe/stripe-js"; 3 | 4 | import { env } from "@/env"; 5 | 6 | let stripePromise: Promise; 7 | 8 | export const getStripe = () => { 9 | if (!stripePromise) { 10 | stripePromise = loadStripe(env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY); 11 | } 12 | 13 | return stripePromise; 14 | }; 15 | -------------------------------------------------------------------------------- /apps/web/src/next-auth.d.ts: -------------------------------------------------------------------------------- 1 | import type NextAuth from "next-auth"; 2 | 3 | import type { User as DefaultUserSchema } from "@openstatus/db/src/schema"; 4 | 5 | declare module "next-auth" { 6 | interface User extends DefaultUserSchema {} 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/public/fonts/CalSans-SemiBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/src/public/fonts/CalSans-SemiBold.ttf -------------------------------------------------------------------------------- /apps/web/src/public/fonts/Inter-Light.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/src/public/fonts/Inter-Light.ttf -------------------------------------------------------------------------------- /apps/web/src/public/fonts/Inter-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/src/public/fonts/Inter-Medium.ttf -------------------------------------------------------------------------------- /apps/web/src/public/fonts/Inter-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openstatusHQ/openstatus/fa299c4801e04dd6701034928f6c587d4247bf39/apps/web/src/public/fonts/Inter-Regular.ttf -------------------------------------------------------------------------------- /apps/web/src/react-table.d.ts: -------------------------------------------------------------------------------- 1 | import "@tanstack/react-table"; 2 | 3 | declare module "@tanstack/react-table" { 4 | interface ColumnMeta { 5 | headerClassName?: string; 6 | cellClassName?: string; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /apps/web/src/types/utils.ts: -------------------------------------------------------------------------------- 1 | export type Writeable = { -readonly [P in keyof T]: T[P] }; 2 | -------------------------------------------------------------------------------- /apps/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/nextjs.json", 3 | "compilerOptions": { 4 | "baseUrl": ".", 5 | "paths": { 6 | "content-collections": ["./.content-collections/generated"], 7 | "@/*": ["./src/*"] 8 | }, 9 | "plugins": [{ "name": "next" }], 10 | "strictNullChecks": true, 11 | "strict": true 12 | }, 13 | "include": [ 14 | "next-env.d.ts", 15 | "**/*.ts", 16 | "**/*.tsx", 17 | ".next/types/**/*.ts", 18 | "**/*.mjs" 19 | ], 20 | "exclude": ["node_modules", "env.ts"] 21 | } 22 | -------------------------------------------------------------------------------- /apps/workflows/.dockerignore: -------------------------------------------------------------------------------- 1 | # This file is generated by Dofigen v2.3.2 2 | # See https://github.com/lenra-io/dofigen 3 | 4 | node_modules 5 | /apps/docs 6 | /apps/screenshot-service 7 | /apps/server 8 | /apps/web 9 | /packages/analytics 10 | /packages/api 11 | /packages/error 12 | /packages/tracker 13 | -------------------------------------------------------------------------------- /apps/workflows/.env.test: -------------------------------------------------------------------------------- 1 | DATABASE_URL=http://127.0.0.1:8080 2 | DATABASE_AUTH_TOKEN= 3 | NODE_ENV=test 4 | UNKEY_TOKEN=test 5 | TINY_BIRD_API_KEY=test 6 | UPSTASH_REDIS_REST_URL=test 7 | UPSTASH_REDIS_REST_TOKEN=test 8 | QSTASH_CURRENT_SIGNING_KEY=test 9 | QSTASH_NEXT_SIGNING_KEY=test 10 | FLY_REGION=ams 11 | RESEND_API_KEY=test 12 | SQLD_HTTP_AUTH=basic:token 13 | SCREENSHOT_SERVICE_URL=http://your.endpoint 14 | NEXT_PUBLIC_OPENPANEL_CLIENT_ID=test 15 | OPENPANEL_CLIENT_SECRET=test 16 | -------------------------------------------------------------------------------- /apps/workflows/.gitignore: -------------------------------------------------------------------------------- 1 | # deps 2 | node_modules/ 3 | -------------------------------------------------------------------------------- /apps/workflows/src/utils/audit-log.ts: -------------------------------------------------------------------------------- 1 | import { AuditLog, Tinybird } from "@openstatus/tinybird"; 2 | 3 | import { env } from "../env"; 4 | 5 | const tb = new Tinybird({ token: env().TINY_BIRD_API_KEY }); 6 | 7 | export const checkerAudit = new AuditLog({ tb }); 8 | -------------------------------------------------------------------------------- /apps/workflows/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/base.json", 3 | "compilerOptions": { 4 | "jsx": "react-jsx", 5 | "jsxImportSource": "hono/jsx" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /config.openstatus.yaml: -------------------------------------------------------------------------------- 1 | tests: 2 | ids: 3 | - 1 4 | - 771 5 | - 2662 6 | -------------------------------------------------------------------------------- /devbox.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.10.6/.schema/devbox.schema.json", 3 | "packages": ["turso-cli@latest", "nodejs@20", "bun@latest", "sqld@latest"], 4 | "env": { 5 | "DEVBOX_COREPACK_ENABLED": "true", 6 | "COREPACK_ENABLE_DOWNLOAD_PROMPT": "0" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /knip.ts: -------------------------------------------------------------------------------- 1 | /** @type {import('knip').KnipConfig} */ 2 | const config = { 3 | workspaces: { 4 | "packages/shared": { 5 | includeEntryExports: true, 6 | }, 7 | }, 8 | }; 9 | 10 | export default config; 11 | -------------------------------------------------------------------------------- /packages/analytics/.env.example: -------------------------------------------------------------------------------- 1 | NEXT_PUBLIC_OPENPANEL_CLIENT_ID=something 2 | OPENPANEL_CLIENT_SECRET=something -------------------------------------------------------------------------------- /packages/analytics/env.ts: -------------------------------------------------------------------------------- 1 | import { createEnv } from "@t3-oss/env-core"; 2 | import { z } from "zod"; 3 | 4 | export const env = createEnv({ 5 | server: { 6 | OPENPANEL_CLIENT_SECRET: z.string(), 7 | }, 8 | client: { 9 | NEXT_PUBLIC_OPENPANEL_CLIENT_ID: z.string(), 10 | }, 11 | clientPrefix: "NEXT_PUBLIC_", 12 | runtimeEnv: { 13 | OPENPANEL_CLIENT_SECRET: process.env.OPENPANEL_CLIENT_SECRET, 14 | NEXT_PUBLIC_OPENPANEL_CLIENT_ID: 15 | process.env.NEXT_PUBLIC_OPENPANEL_CLIENT_ID, 16 | }, 17 | }); 18 | -------------------------------------------------------------------------------- /packages/analytics/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/analytics", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.ts", 6 | "dependencies": { 7 | "@openpanel/sdk": "1.0.0", 8 | "@t3-oss/env-core": "0.7.0", 9 | "zod": "3.23.8" 10 | }, 11 | "devDependencies": { 12 | "@openstatus/tsconfig": "workspace:*", 13 | "@types/node": "22.10.2", 14 | "typescript": "5.6.2" 15 | }, 16 | "scripts": {}, 17 | "keywords": [], 18 | "author": "", 19 | "license": "ISC" 20 | } 21 | -------------------------------------------------------------------------------- /packages/analytics/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./events"; 2 | export * from "./server"; 3 | export * from "./utils"; 4 | -------------------------------------------------------------------------------- /packages/analytics/src/utils.ts: -------------------------------------------------------------------------------- 1 | export function parseInputToProps( 2 | json: unknown, 3 | eventProps?: string[], 4 | ): Record { 5 | if (typeof json !== "object" || json === null) return {}; 6 | 7 | if (!eventProps) return {}; 8 | 9 | return eventProps.reduce( 10 | (acc, prop) => { 11 | if (prop in json) { 12 | acc[prop] = json[prop as keyof typeof json]; 13 | } 14 | return acc; 15 | }, 16 | {} as Record, 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/api/.env.test: -------------------------------------------------------------------------------- 1 | RESEND_API_KEY='test' 2 | NEXT_PUBLIC_OPENPANEL_CLIENT_ID='test' 3 | OPENPANEL_CLIENT_SECRET='test' -------------------------------------------------------------------------------- /packages/api/src/lambda.ts: -------------------------------------------------------------------------------- 1 | import { emailRouter } from "./router/email"; 2 | import { stripeRouter } from "./router/stripe"; 3 | import { createTRPCRouter } from "./trpc"; 4 | // Deployed to /trpc/lambda/** 5 | export const lambdaRouter = createTRPCRouter({ 6 | stripeRouter: stripeRouter, 7 | emailRouter: emailRouter, 8 | }); 9 | 10 | export { stripe } from "./router/stripe/shared"; 11 | -------------------------------------------------------------------------------- /packages/api/src/root.ts: -------------------------------------------------------------------------------- 1 | import { edgeRouter } from "./edge"; 2 | import { lambdaRouter } from "./lambda"; 3 | import { mergeRouters } from "./trpc"; 4 | 5 | export const appRouter = mergeRouters(edgeRouter, lambdaRouter); 6 | export type AppRouter = typeof appRouter; 7 | -------------------------------------------------------------------------------- /packages/api/src/router/user.ts: -------------------------------------------------------------------------------- 1 | import { eq } from "@openstatus/db"; 2 | import { user } from "@openstatus/db/src/schema"; 3 | 4 | import { createTRPCRouter, protectedProcedure } from "../trpc"; 5 | 6 | export const userRouter = createTRPCRouter({ 7 | getCurrentUser: protectedProcedure.query(async (opts) => { 8 | const currentUser = await opts.ctx.db 9 | .select() 10 | .from(user) 11 | .where(eq(user.id, opts.ctx.user.id)) 12 | .get(); 13 | return currentUser; 14 | }), 15 | }); 16 | -------------------------------------------------------------------------------- /packages/api/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/nextjs.json", 3 | "include": ["src", "*.ts"], 4 | "compilerOptions": { 5 | "types": ["bun-types"] 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/assertions/README.md: -------------------------------------------------------------------------------- 1 | Biggest props to [@chronark\_](https://twitter.com/chronark_/) for providing us 2 | the snippets. 3 | -------------------------------------------------------------------------------- /packages/assertions/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/assertions", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.ts", 6 | "scripts": {}, 7 | "dependencies": { 8 | "jsonpath-plus": "7.2.0" 9 | }, 10 | "devDependencies": { 11 | "@openstatus/tsconfig": "workspace:*", 12 | "typescript": "5.6.2", 13 | "zod": "3.23.8" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC" 18 | } 19 | -------------------------------------------------------------------------------- /packages/assertions/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./dictionary"; 2 | export * from "./types"; 3 | export * from "./serializing"; 4 | export * from "./v1"; 5 | -------------------------------------------------------------------------------- /packages/assertions/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/base.json", 3 | "compilerOptions": { 4 | "lib": ["es2015", "dom"] 5 | }, 6 | "include": ["src", "*.ts"] 7 | } 8 | -------------------------------------------------------------------------------- /packages/db/.env.example: -------------------------------------------------------------------------------- 1 | DATABASE_URL=http://127.0.0.1:8080 2 | DATABASE_AUTH_TOKEN=any-token 3 | -------------------------------------------------------------------------------- /packages/db/drizzle.config.ts: -------------------------------------------------------------------------------- 1 | import type { Config } from "drizzle-kit"; 2 | 3 | import { env } from "./env.mjs"; 4 | 5 | export default { 6 | schema: "./src/schema/index.ts", 7 | out: "./drizzle", 8 | dbCredentials: { 9 | url: env.DATABASE_URL, 10 | authToken: env.DATABASE_AUTH_TOKEN, 11 | }, 12 | strict: true, 13 | dialect: "turso", 14 | } satisfies Config; 15 | -------------------------------------------------------------------------------- /packages/db/drizzle/0001_brainy_beast.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE monitor ADD `regions` text DEFAULT '' NOT NULL; 2 | 3 | -------------------------------------------------------------------------------- /packages/db/drizzle/0002_luxuriant_ser_duncan.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE user ADD `first_name` text DEFAULT '';--> statement-breakpoint 2 | ALTER TABLE user ADD `last_name` text DEFAULT '';--> statement-breakpoint 3 | ALTER TABLE user ADD `email` text DEFAULT '';--> statement-breakpoint 4 | ALTER TABLE user ADD `photo_url` text DEFAULT ''; -------------------------------------------------------------------------------- /packages/db/drizzle/0005_even_baron_strucker.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE workspace ADD `subscription_id` text;--> statement-breakpoint 2 | ALTER TABLE workspace ADD `plan` text(3);--> statement-breakpoint 3 | ALTER TABLE workspace ADD `ends_at` integer;--> statement-breakpoint 4 | ALTER TABLE workspace ADD `paid_until` integer; -------------------------------------------------------------------------------- /packages/db/drizzle/0007_complex_frog_thor.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `integration` ( 2 | `id` integer PRIMARY KEY NOT NULL, 3 | `name` text(256) NOT NULL, 4 | `workspace_id` integer, 5 | `credential` text, 6 | `external_id` text NOT NULL, 7 | `created_at` integer DEFAULT (strftime('%s', 'now')), 8 | `updated_at` integer DEFAULT (strftime('%s', 'now')), 9 | `data` text NOT NULL, 10 | FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE no action ON DELETE no action 11 | ); 12 | -------------------------------------------------------------------------------- /packages/db/drizzle/0009_small_maximus.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `incidents_to_pages` ( 2 | `page_id` integer NOT NULL, 3 | `incident_id` integer NOT NULL, 4 | PRIMARY KEY(`incident_id`, `page_id`), 5 | FOREIGN KEY (`page_id`) REFERENCES `page`(`id`) ON UPDATE no action ON DELETE cascade, 6 | FOREIGN KEY (`incident_id`) REFERENCES `incident`(`id`) ON UPDATE no action ON DELETE cascade 7 | ); 8 | -------------------------------------------------------------------------------- /packages/db/drizzle/0010_lame_songbird.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `monitor_status` ( 2 | `monitor_id` integer NOT NULL, 3 | `region` text DEFAULT '' NOT NULL, 4 | `status` text DEFAULT 'active' NOT NULL, 5 | `created_at` integer DEFAULT (strftime('%s', 'now')), 6 | `updated_at` integer DEFAULT (strftime('%s', 'now')), 7 | PRIMARY KEY(`monitor_id`, `region`), 8 | FOREIGN KEY (`monitor_id`) REFERENCES `monitor`(`id`) ON UPDATE no action ON DELETE cascade 9 | ); 10 | --> statement-breakpoint 11 | CREATE INDEX `monitor_status_idx` ON `monitor_status` (`monitor_id`,`region`); -------------------------------------------------------------------------------- /packages/db/drizzle/0012_tan_magma.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `invitation` ( 2 | `id` integer PRIMARY KEY NOT NULL, 3 | `email` text NOT NULL, 4 | `role` text DEFAULT 'member' NOT NULL, 5 | `workspace_id` integer NOT NULL, 6 | `token` text NOT NULL, 7 | `expires_at` integer NOT NULL, 8 | `created_at` integer DEFAULT (strftime('%s', 'now')), 9 | `accepted_at` integer 10 | ); 11 | --> statement-breakpoint 12 | ALTER TABLE users_to_workspaces ADD `role` text DEFAULT 'owner' NOT NULL; -------------------------------------------------------------------------------- /packages/db/drizzle/0013_tired_paladin.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `page_subscriber` ( 2 | `id` integer PRIMARY KEY NOT NULL, 3 | `email` text NOT NULL, 4 | `page_id` integer, 5 | `token` text, 6 | `accepted_at` integer, 7 | `expires_at` integer, 8 | `created_at` integer DEFAULT (strftime('%s', 'now')), 9 | `updated_at` integer DEFAULT (strftime('%s', 'now')), 10 | FOREIGN KEY (`page_id`) REFERENCES `page`(`id`) ON UPDATE no action ON DELETE no action 11 | ); 12 | -------------------------------------------------------------------------------- /packages/db/drizzle/0014_adorable_skaar.sql: -------------------------------------------------------------------------------- 1 | DROP TABLE IF EXISTS `page_subscriber`; 2 | --> statement-breakpoint 3 | 4 | CREATE TABLE `page_subscriber` ( 5 | `id` integer PRIMARY KEY NOT NULL, 6 | `email` text NOT NULL, 7 | `page_id` integer NOT NULL, 8 | `token` text, 9 | `accepted_at` integer, 10 | `expires_at` integer, 11 | `created_at` integer DEFAULT (strftime('%s', 'now')), 12 | `updated_at` integer DEFAULT (strftime('%s', 'now')), 13 | FOREIGN KEY (`page_id`) REFERENCES `page`(`id`) ON UPDATE no action ON DELETE no action 14 | ); 15 | -------------------------------------------------------------------------------- /packages/db/drizzle/0018_neat_orphan.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE incident ADD `auto_resolved` integer DEFAULT false; -------------------------------------------------------------------------------- /packages/db/drizzle/0019_dashing_malcolm_colcord.sql: -------------------------------------------------------------------------------- 1 | DROP INDEX IF EXISTS `incident_monitor_id_started_at_unique`;--> statement-breakpoint 2 | DROP INDEX IF EXISTS `composite_incident_new_id_started_at_unique`;--> statement-breakpoint 3 | CREATE UNIQUE INDEX `incident_id_monitor_id_started_at_unique` ON `incident` (`id`,`monitor_id`,`started_at`); -------------------------------------------------------------------------------- /packages/db/drizzle/0020_flat_bedlam.sql: -------------------------------------------------------------------------------- 1 | DROP INDEX IF EXISTS `incident_id_monitor_id_started_at_unique`;--> statement-breakpoint 2 | CREATE UNIQUE INDEX `incident_monitor_id_started_at_unique` ON `incident` (`monitor_id`,`started_at`); -------------------------------------------------------------------------------- /packages/db/drizzle/0022_chunky_rockslide.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE monitor ADD `assertions` text; -------------------------------------------------------------------------------- /packages/db/drizzle/0023_dry_blink.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE incident ADD `incident_screenshot_url` text;--> statement-breakpoint 2 | ALTER TABLE incident ADD `recovery_screenshot_url` text; -------------------------------------------------------------------------------- /packages/db/drizzle/0024_young_proudstar.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE monitor ADD `deleted_at` integer; -------------------------------------------------------------------------------- /packages/db/drizzle/0025_strong_thunderball.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE monitor ADD `public` integer DEFAULT false; -------------------------------------------------------------------------------- /packages/db/drizzle/0026_giant_absorbing_man.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE workspace ADD `dsn` text;--> statement-breakpoint 2 | CREATE UNIQUE INDEX `workspace_id_dsn_unique` ON `workspace` (`id`,`dsn`); -------------------------------------------------------------------------------- /packages/db/drizzle/0027_bizarre_bastion.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE page ADD `password` text(256);--> statement-breakpoint 2 | ALTER TABLE page ADD `password_protected` integer DEFAULT false; -------------------------------------------------------------------------------- /packages/db/drizzle/0029_regular_marrow.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `monitors_to_pages` ADD `order` integer DEFAULT 0; -------------------------------------------------------------------------------- /packages/db/drizzle/0030_elite_barracuda.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `application` ( 2 | `id` integer PRIMARY KEY NOT NULL, 3 | `name` text, 4 | `dsn` text, 5 | `workspace_id` integer, 6 | `created_at` integer DEFAULT (strftime('%s', 'now')), 7 | `updated_at` integer DEFAULT (strftime('%s', 'now')), 8 | FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE no action ON DELETE no action 9 | ); 10 | --> statement-breakpoint 11 | CREATE UNIQUE INDEX `application_dsn_unique` ON `application` (`dsn`); -------------------------------------------------------------------------------- /packages/db/drizzle/0032_hot_swordsman.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `check` ( 2 | `id` integer PRIMARY KEY AUTOINCREMENT NOT NULL, 3 | `regions` text DEFAULT '' NOT NULL, 4 | `url` text(4096) NOT NULL, 5 | `headers` text DEFAULT '', 6 | `body` text DEFAULT '', 7 | `method` text DEFAULT 'GET', 8 | `count_requests` integer DEFAULT 1, 9 | `workspace_id` integer, 10 | `created_at` integer DEFAULT (strftime('%s', 'now')), 11 | FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE no action ON DELETE no action 12 | ); 13 | -------------------------------------------------------------------------------- /packages/db/drizzle/0033_solid_colossus.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `monitor` ADD `timeout` integer DEFAULT 45000 NOT NULL;--> statement-breakpoint 2 | ALTER TABLE `monitor` ADD `degraded_after` integer; -------------------------------------------------------------------------------- /packages/db/drizzle/0034_serious_shard.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `status_report` ADD `page_id` integer REFERENCES page(id);--> statement-breakpoint 2 | 3 | UPDATE `status_report` SET `page_id` = `t`.`page_id` from (select `page_id`, `status_report_id` from `status_reports_to_pages`) `t` where `t`.`status_report_id` = `id` ; -------------------------------------------------------------------------------- /packages/db/drizzle/0035_open_the_professor.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `workspace` ADD `limits` text DEFAULT '{}' NOT NULL; -------------------------------------------------------------------------------- /packages/db/drizzle/0036_gifted_deathbird.sql: -------------------------------------------------------------------------------- 1 | UPDATE `monitor` SET `job_type` = 'http' ; -------------------------------------------------------------------------------- /packages/db/drizzle/0037_equal_beyonder.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `page` ADD `show_monitor_values` integer DEFAULT true; -------------------------------------------------------------------------------- /packages/db/drizzle/0038_foamy_stardust.sql: -------------------------------------------------------------------------------- 1 | CREATE TABLE `monitor_run` ( 2 | `id` integer PRIMARY KEY NOT NULL, 3 | `workspace_id` integer, 4 | `monitor_id` integer, 5 | `runned_at` integer, 6 | `created_at` integer DEFAULT (strftime('%s', 'now')), 7 | FOREIGN KEY (`workspace_id`) REFERENCES `workspace`(`id`) ON UPDATE no action ON DELETE no action, 8 | FOREIGN KEY (`monitor_id`) REFERENCES `monitor`(`id`) ON UPDATE no action ON DELETE no action 9 | ); 10 | -------------------------------------------------------------------------------- /packages/db/drizzle/0039_lonely_jigsaw.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `monitor` ADD `otel_endpoint` text;--> statement-breakpoint 2 | ALTER TABLE `monitor` ADD `otel_headers` text; -------------------------------------------------------------------------------- /packages/db/drizzle/0043_low_lily_hollister.sql: -------------------------------------------------------------------------------- 1 | ALTER TABLE `monitor` ADD `retry` integer DEFAULT 3; -------------------------------------------------------------------------------- /packages/db/env.ts: -------------------------------------------------------------------------------- 1 | const file = Bun.file("./.env.example"); 2 | await Bun.write("./.env", file); 3 | -------------------------------------------------------------------------------- /packages/db/src/db.ts: -------------------------------------------------------------------------------- 1 | import { drizzle } from "drizzle-orm/libsql/http"; 2 | 3 | import { env } from "../env.mjs"; 4 | import * as schema from "./schema"; 5 | 6 | export const db = drizzle({ 7 | connection: { 8 | url: env.DATABASE_URL, 9 | authToken: env.DATABASE_AUTH_TOKEN, 10 | }, 11 | schema, 12 | }); 13 | -------------------------------------------------------------------------------- /packages/db/src/index.ts: -------------------------------------------------------------------------------- 1 | export * as schema from "./schema"; 2 | export * from "drizzle-orm"; 3 | export * from "./db"; 4 | export * from "./utils"; 5 | -------------------------------------------------------------------------------- /packages/db/src/schema/applications/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./application"; 2 | export * from "./validation"; 3 | -------------------------------------------------------------------------------- /packages/db/src/schema/applications/validation.ts: -------------------------------------------------------------------------------- 1 | import { createSelectSchema } from "drizzle-zod"; 2 | import { application } from "./application"; 3 | 4 | export const selectApplicationSchema = createSelectSchema(application); 5 | -------------------------------------------------------------------------------- /packages/db/src/schema/check/constants.ts: -------------------------------------------------------------------------------- 1 | export const flyCheckerRegions = [ 2 | // TODO: Add more regions 3 | "ams", 4 | "iad", 5 | "hkg", 6 | "jnb", 7 | "syd", 8 | "gru", 9 | ] as const; 10 | -------------------------------------------------------------------------------- /packages/db/src/schema/check/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./check"; 2 | export * from "./constants"; 3 | -------------------------------------------------------------------------------- /packages/db/src/schema/incidents/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./incident"; 2 | export * from "./validation"; 3 | -------------------------------------------------------------------------------- /packages/db/src/schema/incidents/validation.ts: -------------------------------------------------------------------------------- 1 | import { createSelectSchema } from "drizzle-zod"; 2 | import { z } from "zod"; 3 | 4 | import { incidentTable } from "./incident"; 5 | 6 | export const selectIncidentSchema = createSelectSchema(incidentTable).extend({ 7 | monitorName: z.string().optional(), 8 | }); 9 | 10 | export type Incident = z.infer; 11 | -------------------------------------------------------------------------------- /packages/db/src/schema/invitations/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./invitation"; 2 | export * from "./validation"; 3 | -------------------------------------------------------------------------------- /packages/db/src/schema/invitations/validation.ts: -------------------------------------------------------------------------------- 1 | import { createInsertSchema, createSelectSchema } from "drizzle-zod"; 2 | import { z } from "zod"; 3 | 4 | import { invitation } from "./invitation"; 5 | 6 | export const insertInvitationSchema = createInsertSchema(invitation, { 7 | email: z.string().email(), 8 | }); 9 | 10 | export const selectInvitationSchema = createSelectSchema(invitation); 11 | 12 | export type InsertInvitation = z.infer; 13 | export type Invitation = z.infer; 14 | -------------------------------------------------------------------------------- /packages/db/src/schema/maintenances/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./maintenance"; 2 | export * from "./validation"; 3 | -------------------------------------------------------------------------------- /packages/db/src/schema/monitor_run/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./monitor_run"; 2 | -------------------------------------------------------------------------------- /packages/db/src/schema/monitor_status/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./monitor_status"; 2 | export * from "./validation"; 3 | export type * from "./validation"; 4 | -------------------------------------------------------------------------------- /packages/db/src/schema/monitor_tags/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./monitor_tag"; 2 | export * from "./validation"; 3 | -------------------------------------------------------------------------------- /packages/db/src/schema/monitor_tags/validation.ts: -------------------------------------------------------------------------------- 1 | import { createInsertSchema, createSelectSchema } from "drizzle-zod"; 2 | import type { z } from "zod"; 3 | 4 | import { monitorTag } from "./monitor_tag"; 5 | 6 | export const selectMonitorTagSchema = createSelectSchema(monitorTag); 7 | 8 | export const insertMonitorTagSchema = createInsertSchema(monitorTag); 9 | 10 | export type InsertMonitorTag = z.infer; 11 | export type MonitorTag = z.infer; 12 | -------------------------------------------------------------------------------- /packages/db/src/schema/monitors/constants.ts: -------------------------------------------------------------------------------- 1 | export const monitorMethods = [ 2 | "GET", 3 | "POST", 4 | "HEAD", 5 | "PUT", 6 | "PATCH", 7 | "DELETE", 8 | "TRACE", 9 | "CONNECT", 10 | "OPTIONS", 11 | ] as const; 12 | export const monitorStatus = ["active", "error", "degraded"] as const; 13 | 14 | export const monitorJobTypes = [ 15 | "http", 16 | "tcp", 17 | "imcp", 18 | "udp", 19 | "dns", 20 | "ssl", 21 | ] as const; 22 | -------------------------------------------------------------------------------- /packages/db/src/schema/monitors/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./constants"; 2 | export * from "./monitor"; 3 | export * from "./validation"; 4 | export type * from "./validation"; 5 | -------------------------------------------------------------------------------- /packages/db/src/schema/notifications/constants.ts: -------------------------------------------------------------------------------- 1 | export const notificationProvider = [ 2 | "email", 3 | "discord", 4 | "ntfy", 5 | "pagerduty", 6 | "opsgenie", 7 | "slack", 8 | "sms", 9 | "webhook", 10 | ] as const; 11 | -------------------------------------------------------------------------------- /packages/db/src/schema/notifications/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./constants"; 2 | export * from "./notification"; 3 | export * from "./validation"; 4 | export type * from "./validation"; 5 | -------------------------------------------------------------------------------- /packages/db/src/schema/page_subscribers/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./page_subscribers"; 2 | export * from "./validation"; 3 | export type * from "./validation"; 4 | -------------------------------------------------------------------------------- /packages/db/src/schema/pages/constants.ts: -------------------------------------------------------------------------------- 1 | export const subdomainSafeList = [ 2 | "api", 3 | "app", 4 | "www", 5 | "docs", 6 | "checker", 7 | "time", 8 | "help", 9 | "data-table", 10 | "light", 11 | "workflows", 12 | ]; 13 | -------------------------------------------------------------------------------- /packages/db/src/schema/pages/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./page"; 2 | export * from "./validation"; 3 | export type * from "./validation"; 4 | export * from "./constants"; 5 | -------------------------------------------------------------------------------- /packages/db/src/schema/status_reports/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./status_reports"; 2 | export * from "./validation"; 3 | export type * from "./validation"; 4 | -------------------------------------------------------------------------------- /packages/db/src/schema/users/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./user"; 2 | export * from "./validation"; 3 | -------------------------------------------------------------------------------- /packages/db/src/schema/users/validation.ts: -------------------------------------------------------------------------------- 1 | import { createInsertSchema, createSelectSchema } from "drizzle-zod"; 2 | import type { z } from "zod"; 3 | 4 | import { user } from "./user"; 5 | 6 | export const insertUserSchema = createInsertSchema(user); 7 | 8 | export const selectUserSchema = createSelectSchema(user); 9 | 10 | export type InsertUser = z.infer; 11 | export type User = z.infer; 12 | -------------------------------------------------------------------------------- /packages/db/src/schema/workspaces/constants.ts: -------------------------------------------------------------------------------- 1 | export const workspacePlans = ["free", "starter", "team"] as const; 2 | export const workspaceRole = ["owner", "admin", "member"] as const; 3 | 4 | export const workspacePlanHierarchy: Record< 5 | (typeof workspacePlans)[number], 6 | number 7 | > = { 8 | free: 0, 9 | starter: 1, 10 | team: 2, 11 | }; 12 | -------------------------------------------------------------------------------- /packages/db/src/schema/workspaces/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./constants"; 2 | export * from "./workspace"; 3 | export * from "./validation"; 4 | export type * from "./validation"; 5 | -------------------------------------------------------------------------------- /packages/emails/src/env.ts: -------------------------------------------------------------------------------- 1 | import { createEnv } from "@t3-oss/env-core"; 2 | import { z } from "zod"; 3 | 4 | export const env = createEnv({ 5 | server: { 6 | RESEND_API_KEY: z.string().min(1), 7 | }, 8 | runtimeEnv: { 9 | RESEND_API_KEY: process.env.RESEND_API_KEY, 10 | }, 11 | }); 12 | -------------------------------------------------------------------------------- /packages/emails/src/utils.ts: -------------------------------------------------------------------------------- 1 | export const validateEmailNotDisposable = async (mailHost: string) => { 2 | const response = await fetch( 3 | `https://open.kickbox.com/v1/disposable/${mailHost}`, 4 | ); 5 | const status = (await response.json()) as Record; 6 | 7 | return status.disposable; 8 | }; 9 | -------------------------------------------------------------------------------- /packages/emails/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/react-library.json", 3 | "include": [".", "src/env.ts"], 4 | "exclude": ["dist", "build", "node_modules"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/error/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./src/base-error"; 2 | export * from "./src/error-code"; 3 | export * from "./src/http-error"; 4 | export * from "./src/schema-error"; 5 | export * from "./src/utils"; 6 | -------------------------------------------------------------------------------- /packages/error/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/error", 3 | "version": "0.0.0", 4 | "description": "", 5 | "main": "index.ts", 6 | "scripts": {}, 7 | "dependencies": { 8 | "zod": "3.23.8" 9 | }, 10 | "devDependencies": { 11 | "@openstatus/tsconfig": "workspace:*", 12 | "typescript": "5.6.2" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC" 17 | } 18 | -------------------------------------------------------------------------------- /packages/error/src/error-code.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const ErrorCodes = [ 4 | "BAD_REQUEST", 5 | "FORBIDDEN", 6 | "INTERNAL_SERVER_ERROR", 7 | "PAYMENT_REQUIRED", 8 | "CONFLICT", 9 | "NOT_FOUND", 10 | "UNAUTHORIZED", 11 | "METHOD_NOT_ALLOWED", 12 | "UNPROCESSABLE_ENTITY", 13 | ] as const; 14 | 15 | export const ErrorCodeEnum = z.enum(ErrorCodes); 16 | 17 | export type ErrorCode = z.infer; 18 | -------------------------------------------------------------------------------- /packages/error/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/base.json", 3 | "include": ["src", "*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/header-analysis/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/header-analysis", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.ts", 6 | "scripts": {}, 7 | "dependencies": {}, 8 | "devDependencies": { 9 | "@openstatus/tsconfig": "workspace:*", 10 | "typescript": "5.6.2" 11 | }, 12 | "keywords": [], 13 | "author": "", 14 | "license": "ISC" 15 | } 16 | -------------------------------------------------------------------------------- /packages/header-analysis/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./parser/cache-control"; 2 | export * from "./parser/cf-cache-status"; 3 | export * from "./parser/cf-ray"; 4 | export * from "./parser/fly-request-id"; 5 | export * from "./parser/x-vercel-cache"; 6 | export * from "./parser/x-vercel-id"; 7 | -------------------------------------------------------------------------------- /packages/header-analysis/src/types/index.ts: -------------------------------------------------------------------------------- 1 | export type Region = { 2 | code: string; 3 | location: string; 4 | flag: string; 5 | }; 6 | 7 | export type ParserReturn = 8 | | { status: "success"; data: T } 9 | | { status: "failed"; error: Error }; 10 | -------------------------------------------------------------------------------- /packages/header-analysis/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/base.json", 3 | "include": ["src", "*.ts"], 4 | "compilerOptions": { 5 | "resolveJsonModule": true 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/notifications/discord/README.md: -------------------------------------------------------------------------------- 1 | # @openstatus/notifications-discord 2 | 3 | To install dependencies: 4 | 5 | ```bash 6 | bun install 7 | ``` 8 | 9 | To run: 10 | 11 | ```bash 12 | bun run src/index.ts 13 | ``` 14 | 15 | This project was created using `bun init` in bun v1.0.0. [Bun](https://bun.sh) 16 | is a fast all-in-one JavaScript runtime. 17 | -------------------------------------------------------------------------------- /packages/notifications/discord/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/notification-discord", 3 | "version": "1.0.0", 4 | "main": "src/index.ts", 5 | "dependencies": { 6 | "@openstatus/db": "workspace:*", 7 | "zod": "3.23.8" 8 | }, 9 | "devDependencies": { 10 | "@openstatus/tsconfig": "workspace:*", 11 | "@types/node": "22.10.2", 12 | "typescript": "5.6.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/notifications/discord/src/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const DataSchema = z.object({ 4 | discord: z.string(), 5 | }); 6 | -------------------------------------------------------------------------------- /packages/notifications/discord/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/nextjs.json", 3 | "include": ["src", "*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/notifications/email/.env.example: -------------------------------------------------------------------------------- 1 | RESEND_API_KEY=1 2 | -------------------------------------------------------------------------------- /packages/notifications/email/README.md: -------------------------------------------------------------------------------- 1 | # 2 | -------------------------------------------------------------------------------- /packages/notifications/email/env.ts: -------------------------------------------------------------------------------- 1 | import { createEnv } from "@t3-oss/env-core"; 2 | import { z } from "zod"; 3 | 4 | export const env = createEnv({ 5 | server: { 6 | RESEND_API_KEY: z.string().min(1), 7 | }, 8 | runtimeEnv: { 9 | RESEND_API_KEY: process.env.RESEND_API_KEY, 10 | }, 11 | skipValidation: process.env.NODE_ENV === "test", 12 | }); 13 | -------------------------------------------------------------------------------- /packages/notifications/email/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/nextjs.json", 3 | "include": ["src", "*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/notifications/ntfy/README.md: -------------------------------------------------------------------------------- 1 | # @openstatus/notification-ntfy 2 | To install dependencies: 3 | 4 | ```bash 5 | bun install 6 | ``` 7 | 8 | To run: 9 | 10 | ```bash 11 | bun run src/index.ts 12 | ``` 13 | 14 | This project was created using `bun init` in bun v1.0.0. [Bun](https://bun.sh) 15 | is a fast all-in-one JavaScript runtime. 16 | -------------------------------------------------------------------------------- /packages/notifications/ntfy/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/notification-ntfy", 3 | "version": "1.0.0", 4 | "main": "src/index.ts", 5 | "dependencies": { 6 | "@openstatus/db": "workspace:*", 7 | "zod": "3.23.8" 8 | }, 9 | "devDependencies": { 10 | "@openstatus/tsconfig": "workspace:*", 11 | "@types/node": "22.10.2", 12 | "typescript": "5.6.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/notifications/ntfy/src/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const NtfySchema = z.object({ 4 | ntfy: z.object({ 5 | topic: z.string(), 6 | serverUrl: z.string().default("https://ntfy.sh"), 7 | token: z.string().optional(), 8 | }), 9 | }); 10 | -------------------------------------------------------------------------------- /packages/notifications/ntfy/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/nextjs.json", 3 | "include": ["src", "*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/notifications/opsgenie/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/nextjs.json", 3 | "include": ["src", "*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/notifications/pagerduty/.env.example: -------------------------------------------------------------------------------- 1 | PAGERDUTY_APP_ID=your_auth_token 2 | -------------------------------------------------------------------------------- /packages/notifications/pagerduty/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/nextjs.json", 3 | "include": ["src", "*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/notifications/slack/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/notification-slack", 3 | "version": "0.0.0", 4 | "main": "src/index.ts", 5 | "dependencies": { 6 | "@openstatus/db": "workspace:*", 7 | "zod": "3.23.8" 8 | }, 9 | "devDependencies": { 10 | "@openstatus/tsconfig": "workspace:*", 11 | "@types/node": "22.10.2", 12 | "typescript": "5.6.2" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/notifications/slack/src/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod"; 2 | 3 | export const DataSchema = z.object({ 4 | slack: z.string(), 5 | }); 6 | -------------------------------------------------------------------------------- /packages/notifications/slack/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/nextjs.json", 3 | "include": ["src", "*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/notifications/twillio-sms/.env.example: -------------------------------------------------------------------------------- 1 | TWILLIO_AUTH_TOKEN=your_auth_token 2 | TWILLIO_ACCOUNT_ID=your_account_id 3 | -------------------------------------------------------------------------------- /packages/notifications/twillio-sms/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/notification-twillio-sms", 3 | "version": "0.0.0", 4 | "main": "src/index.ts", 5 | "dependencies": { 6 | "@openstatus/db": "workspace:*", 7 | "@t3-oss/env-core": "0.7.1", 8 | "validator": "13.12.0", 9 | "zod": "3.23.8" 10 | }, 11 | "devDependencies": { 12 | "@openstatus/tsconfig": "workspace:*", 13 | "@types/node": "22.10.2", 14 | "@types/validator": "13.12.0", 15 | "typescript": "5.6.2" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /packages/notifications/twillio-sms/src/schema/config.ts: -------------------------------------------------------------------------------- 1 | import isMobilephone from "validator/lib/isMobilePhone"; 2 | import { z } from "zod"; 3 | 4 | export const SmsConfigurationSchema = z.object({ 5 | sms: z.string().refine(isMobilephone), 6 | }); 7 | -------------------------------------------------------------------------------- /packages/notifications/twillio-sms/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/nextjs.json", 3 | "include": ["src", "*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/notifications/webhook/README.md: -------------------------------------------------------------------------------- 1 | # @openstatus/notification-webhook 2 | To install dependencies: 3 | 4 | ```bash 5 | bun install 6 | ``` 7 | 8 | To run: 9 | 10 | ```bash 11 | bun run src/index.ts 12 | ``` 13 | 14 | This project was created using `bun init` in bun v1.0.0. [Bun](https://bun.sh) 15 | is a fast all-in-one JavaScript runtime. 16 | -------------------------------------------------------------------------------- /packages/notifications/webhook/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/notification-webhook", 3 | "version": "1.0.0", 4 | "main": "src/index.ts", 5 | "dependencies": { 6 | "@openstatus/db": "workspace:*", 7 | "@openstatus/utils": "workspace:*", 8 | 9 | "zod": "3.23.8" 10 | }, 11 | "devDependencies": { 12 | "@openstatus/tsconfig": "workspace:*", 13 | "@types/node": "22.10.2", 14 | "typescript": "5.6.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/notifications/webhook/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/nextjs.json", 3 | "include": ["src", "*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /packages/react/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./widget"; 2 | -------------------------------------------------------------------------------- /packages/react/src/styles.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | -------------------------------------------------------------------------------- /packages/react/tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ["./src/**/*.{ts,tsx}"], 4 | theme: { 5 | extend: {}, 6 | }, 7 | plugins: [], 8 | }; 9 | -------------------------------------------------------------------------------- /packages/react/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/react-library.json", 3 | "exclude": ["node_modules"], 4 | "compilerOptions": { 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "isolatedModules": true, 8 | "moduleResolution": "node", 9 | "preserveWatchOutput": true, 10 | "skipLibCheck": true, 11 | "noEmit": true, 12 | "strict": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/react/tsup.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "tsup"; 2 | 3 | export default defineConfig({ 4 | entry: ["src/index.ts"], 5 | format: ["cjs", "esm"], 6 | splitting: false, 7 | sourcemap: true, 8 | clean: true, 9 | bundle: true, 10 | dts: true, 11 | }); 12 | -------------------------------------------------------------------------------- /packages/tinybird/_legacy/aggregated_monitor_per_day_mv.datasource: -------------------------------------------------------------------------------- 1 | # REMINDER: legacy 2 | 3 | # Data Source created from Pipe 'aggregated_monitor_day_mv' 4 | VERSION 0 5 | 6 | SCHEMA > 7 | `day` Int64, 8 | `monitorId` String, 9 | `avgLatency` AggregateFunction(avg, Int16), 10 | `count` AggregateFunction(count), 11 | `ok` AggregateFunction(count, Nullable(UInt8)) 12 | 13 | ENGINE "AggregatingMergeTree" 14 | ENGINE_SORTING_KEY "day, monitorId" 15 | -------------------------------------------------------------------------------- /packages/tinybird/_migration/tb_datasource_union.pipe: -------------------------------------------------------------------------------- 1 | NODE union_all 2 | SQL > 3 | 4 | SELECT count() FROM ping_response__v8 5 | UNION ALL 6 | SELECT count() FROM ping_response__v7 7 | -------------------------------------------------------------------------------- /packages/tinybird/datasources/audit_log.datasource: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | SCHEMA > 4 | `action` String `json:$.action`, 5 | `actor` String `json:$.actor`, 6 | `id` String `json:$.id`, 7 | `targets` Nullable(String) `json:$.targets`, 8 | `metadata` Nullable(String) `json:$.metadata`, 9 | `timestamp` Int64 `json:$.timestamp`, 10 | `version` Int16 `json:$.version` 11 | 12 | ENGINE "MergeTree" 13 | ENGINE_SORTING_KEY "id, timestamp, action" 14 | -------------------------------------------------------------------------------- /packages/tinybird/datasources/external_status.datasource: -------------------------------------------------------------------------------- 1 | 2 | SCHEMA > 3 | `description` String `json:$.description`, 4 | `fetched_at` Int64 `json:$.fetched_at`, 5 | `indicator` String `json:$.indicator`, 6 | `name` String `json:$.name`, 7 | `time_zone` String `json:$.time_zone`, 8 | `updated_at` Int64 `json:$.updated_at`, 9 | `url` String `json:$.url` 10 | 11 | ENGINE "MergeTree" 12 | ENGINE_SORTING_KEY "description, time_zone, updated_at, url" 13 | -------------------------------------------------------------------------------- /packages/tinybird/datasources/mv__http_status_45d.datasource: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | # Data Source created from Pipe 'aggregate__http_status_45d__v0' 3 | 4 | SCHEMA > 5 | `time` DateTime('UTC'), 6 | `monitorId` String, 7 | `count` AggregateFunction(count), 8 | `ok` AggregateFunction(count, Nullable(UInt8)) 9 | 10 | ENGINE "AggregatingMergeTree" 11 | ENGINE_PARTITION_KEY "toYYYYMM(time)" 12 | ENGINE_SORTING_KEY "monitorId, time" 13 | ENGINE_TTL "time + toIntervalDay(45)" 14 | -------------------------------------------------------------------------------- /packages/tinybird/datasources/mv__http_status_7d.datasource: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | # Data Source created from Pipe 'aggregate__http_status_7d__v0' 3 | 4 | SCHEMA > 5 | `time` DateTime('UTC'), 6 | `monitorId` String, 7 | `count` AggregateFunction(count), 8 | `ok` AggregateFunction(count, Nullable(UInt8)) 9 | 10 | ENGINE "AggregatingMergeTree" 11 | ENGINE_PARTITION_KEY "toYYYYMM(time)" 12 | ENGINE_SORTING_KEY "monitorId, time" 13 | ENGINE_TTL "time + toIntervalDay(7)" 14 | -------------------------------------------------------------------------------- /packages/tinybird/datasources/mv__tcp_14d.datasource: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | # Data Source created from Pipe 'aggregate__tcp_14d__v0' 3 | 4 | SCHEMA > 5 | `time` DateTime, 6 | `latency` Int64, 7 | `error` Int16, 8 | `region` String, 9 | `trigger` Nullable(String), 10 | `timestamp` Int64, 11 | `cronTimestamp` Int64, 12 | `monitorId` Int32, 13 | `workspaceId` Int32 14 | 15 | ENGINE "MergeTree" 16 | ENGINE_PARTITION_KEY "toYYYYMM(time)" 17 | ENGINE_SORTING_KEY "monitorId, time" 18 | ENGINE_TTL "time + toIntervalDay(14)" 19 | -------------------------------------------------------------------------------- /packages/tinybird/datasources/mv__tcp_1d.datasource: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | # Data Source created from Pipe 'aggregate__tcp_1d__v0' 3 | 4 | SCHEMA > 5 | `time` DateTime, 6 | `latency` Int64, 7 | `error` Int16, 8 | `region` String, 9 | `trigger` Nullable(String), 10 | `timestamp` Int64, 11 | `cronTimestamp` Int64, 12 | `monitorId` Int32, 13 | `workspaceId` Int32 14 | 15 | ENGINE "MergeTree" 16 | ENGINE_PARTITION_KEY "toYYYYMM(time)" 17 | ENGINE_SORTING_KEY "monitorId, time" 18 | ENGINE_TTL "time + toIntervalDay(1)" 19 | -------------------------------------------------------------------------------- /packages/tinybird/datasources/mv__tcp_30d.datasource: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | # Data Source created from Pipe 'aggregate__tcp_30d__v0' 3 | 4 | SCHEMA > 5 | `time` DateTime, 6 | `latency` Int64, 7 | `error` Int16, 8 | `region` String, 9 | `trigger` Nullable(String), 10 | `timestamp` Int64, 11 | `cronTimestamp` Int64, 12 | `monitorId` Int32, 13 | `workspaceId` Int32 14 | 15 | ENGINE "MergeTree" 16 | ENGINE_PARTITION_KEY "toYYYYMM(time)" 17 | ENGINE_SORTING_KEY "monitorId, time" 18 | ENGINE_TTL "time + toIntervalDay(30)" 19 | -------------------------------------------------------------------------------- /packages/tinybird/datasources/mv__tcp_7d.datasource: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | # Data Source created from Pipe 'aggregate__tcp_7d__v0' 3 | 4 | SCHEMA > 5 | `time` DateTime, 6 | `latency` Int64, 7 | `error` Int16, 8 | `region` String, 9 | `trigger` Nullable(String), 10 | `timestamp` Int64, 11 | `cronTimestamp` Int64, 12 | `monitorId` Int32, 13 | `workspaceId` Int32 14 | 15 | ENGINE "MergeTree" 16 | ENGINE_PARTITION_KEY "toYYYYMM(time)" 17 | ENGINE_SORTING_KEY "monitorId, time" 18 | ENGINE_TTL "time + toIntervalDay(7)" 19 | -------------------------------------------------------------------------------- /packages/tinybird/datasources/mv__tcp_status_45d.datasource: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | # Data Source created from Pipe 'aggregate__tcp_status_45d__v0' 3 | 4 | SCHEMA > 5 | `time` DateTime('UTC'), 6 | `monitorId` Int32, 7 | `count` AggregateFunction(count), 8 | `ok` AggregateFunction(count, Nullable(UInt8)) 9 | 10 | ENGINE "AggregatingMergeTree" 11 | ENGINE_PARTITION_KEY "toYYYYMM(time)" 12 | ENGINE_SORTING_KEY "monitorId, time" 13 | ENGINE_TTL "time + toIntervalDay(45)" 14 | -------------------------------------------------------------------------------- /packages/tinybird/datasources/mv__tcp_status_7d.datasource: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | # Data Source created from Pipe 'aggregate__tcp_status_7d__v0' 3 | 4 | SCHEMA > 5 | `time` DateTime('UTC'), 6 | `monitorId` Int32, 7 | `count` AggregateFunction(count), 8 | `ok` AggregateFunction(count, Nullable(UInt8)) 9 | 10 | ENGINE "AggregatingMergeTree" 11 | ENGINE_PARTITION_KEY "toYYYYMM(time)" 12 | ENGINE_SORTING_KEY "monitorId, time" 13 | ENGINE_TTL "time + toIntervalDay(7)" 14 | -------------------------------------------------------------------------------- /packages/tinybird/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/tinybird", 3 | "version": "0.0.0", 4 | "main": "src/index.ts", 5 | "license": "MIT", 6 | "dependencies": { 7 | "@chronark/zod-bird": "0.3.6", 8 | "zod": "3.23.8" 9 | }, 10 | "devDependencies": { 11 | "@openstatus/tsconfig": "workspace:*", 12 | "@openstatus/utils": "workspace:*", 13 | "@types/node": "22.10.2", 14 | "typescript": "5.6.2" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/endpoint__http_get_30d.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | TAGS http 4 | 5 | NODE endpoint 6 | SQL > 7 | 8 | % 9 | SELECT * 10 | FROM mv__http_full_30d__v0 11 | WHERE 12 | monitorId = {{ String(monitorId, '1', required=True) }} 13 | AND cronTimestamp = {{ Int64(cronTimestamp, 1709477432205, required=True) }} 14 | AND region = {{ String(region, 'ams', required=True) }} 15 | ORDER BY cronTimestamp DESC 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/endpoint__http_list_14d.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | TAGS http 4 | 5 | NODE endpoint 6 | SQL > 7 | 8 | % 9 | SELECT * FROM mv__http_14d__v0 10 | WHERE 11 | monitorId = {{ String(monitorId, '1', required=True) }} 12 | ORDER BY cronTimestamp DESC 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/endpoint__http_list_1d.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | TAGS http 4 | 5 | NODE endpoint 6 | SQL > 7 | 8 | % 9 | SELECT * FROM mv__http_1d__v0 10 | WHERE 11 | monitorId = {{ String(monitorId, '1', required=True) }} 12 | ORDER BY cronTimestamp DESC 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/endpoint__http_list_7d.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | TAGS http 4 | 5 | NODE endpoint 6 | SQL > 7 | 8 | % 9 | SELECT * FROM mv__http_7d__v0 10 | WHERE 11 | monitorId = {{ String(monitorId, '1', required=True) }} 12 | ORDER BY cronTimestamp DESC 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/endpoint__tcp_get_30d.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | TAGS tcp 4 | 5 | NODE endpoint 6 | SQL > 7 | 8 | % 9 | SELECT * 10 | FROM mv__tcp_full_30d__v0 11 | WHERE 12 | monitorId = {{ String(monitorId, '1', required=True) }} 13 | AND cronTimestamp = {{ Int64(cronTimestamp, 1709477432205, required=True) }} 14 | AND region = {{ String(region, 'ams', required=True) }} 15 | ORDER BY cronTimestamp DESC 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/endpoint__tcp_list_14d.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | TAGS tcp 4 | 5 | NODE endpoint 6 | SQL > 7 | 8 | % 9 | SELECT * FROM mv__tcp_14d__v0 10 | WHERE 11 | monitorId = {{ String(monitorId, '1', required=True) }} 12 | ORDER BY cronTimestamp DESC 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/endpoint__tcp_list_1d.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | TAGS tcp 4 | 5 | NODE endpoint 6 | SQL > 7 | 8 | % 9 | SELECT * FROM mv__tcp_1d__v0 10 | WHERE 11 | monitorId = {{ String(monitorId, '1', required=True) }} 12 | ORDER BY cronTimestamp DESC 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/endpoint__tcp_list_7d.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | TAGS tcp 4 | 5 | NODE endpoint 6 | SQL > 7 | 8 | % 9 | SELECT * FROM mv__tcp_7d__v0 10 | WHERE 11 | monitorId = {{ String(monitorId, '1', required=True) }} 12 | ORDER BY cronTimestamp DESC 13 | 14 | 15 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/endpoint_audit_log.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | NODE endpoint_audit_pipe_0 4 | SQL > 5 | 6 | % SELECT * FROM audit_log__v0 WHERE id = {{ String(event_id, 1) }} ORDER BY timestamp DESC 7 | 8 | 9 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/external_status.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | NODE external_status_0 3 | SQL > 4 | 5 | % 6 | SELECT * 7 | FROM external_status 8 | WHERE name = {{ String(name, 'OpenAI') }} 9 | ORDER BY fetched_at DESC 10 | LIMIT {{ Int16(limit, 10000) }} 11 | 12 | 13 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/response_details.pipe: -------------------------------------------------------------------------------- 1 | VERSION 0 2 | 3 | NODE response_graph_0 4 | SQL > 5 | 6 | % 7 | SELECT * 8 | FROM ping_response__v7 9 | WHERE 10 | monitorId = {{ String(monitorId, '1') }} 11 | {% if defined(url) %} AND url = {{ String(url) }} {% end %} 12 | AND cronTimestamp = {{ Int64(cronTimestamp, 1706467215188) }} 13 | AND region = {{ String(region, 'ams') }} 14 | 15 | 16 | -------------------------------------------------------------------------------- /packages/tinybird/pipes/single_checks_get.pipe: -------------------------------------------------------------------------------- 1 | VERSION 1 2 | 3 | NODE endpoint 4 | SQL > 5 | 6 | % 7 | SELECT * 8 | from check_response_http 9 | WHERE 10 | workspaceId = {{ Int16(workspaceId, 1) }} 11 | {% if defined(requestId) %} AND requestId = {{ Int16(requestId) }} {% end %} 12 | ORDER BY timestamp DESC 13 | LIMIT {{ Int32(pageSize, 10) }} 14 | OFFSET {{ Int32(page, 0) * Int32(pageSize, 10) }} 15 | 16 | 17 | -------------------------------------------------------------------------------- /packages/tinybird/src/audit-log/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./client"; 2 | -------------------------------------------------------------------------------- /packages/tinybird/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./client"; 2 | export * from "./audit-log"; 3 | export * from "@chronark/zod-bird"; 4 | -------------------------------------------------------------------------------- /packages/tinybird/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/base.json", 3 | "exclude": ["node_modules"], 4 | "compilerOptions": { 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "isolatedModules": true, 8 | "moduleResolution": "node", 9 | "preserveWatchOutput": true, 10 | "skipLibCheck": true, 11 | "noEmit": true, 12 | "strict": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/tracker/README.md: -------------------------------------------------------------------------------- 1 | TODO: Update the different component/files to use the package as source of 2 | truth! 3 | 4 | - [x] public/status 5 | - [ ] package/react dev deps 6 | - [x] `status-check` on status page 7 | - [x] tracker `bar` on status page 8 | - [x] og image api `status-check` 9 | - [x] monitor (overview) dasboard 10 | -------------------------------------------------------------------------------- /packages/tracker/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/tracker", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "src/index.ts", 6 | "scripts": {}, 7 | "dependencies": { 8 | "@openstatus/db": "workspace:*", 9 | "@openstatus/tinybird": "workspace:*", 10 | "zod": "3.23.8" 11 | }, 12 | "devDependencies": { 13 | "@openstatus/tsconfig": "workspace:*", 14 | "typescript": "5.6.2" 15 | }, 16 | "keywords": [], 17 | "author": "", 18 | "license": "ISC" 19 | } 20 | -------------------------------------------------------------------------------- /packages/tracker/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./tracker"; 2 | export * from "./types"; 3 | export * from "./config"; 4 | export * from "./utils"; 5 | -------------------------------------------------------------------------------- /packages/tracker/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/base.json", 3 | "include": ["src", "*.ts"], 4 | "compilerOptions": { 5 | "target": "ES2021" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /packages/tsconfig/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/tsconfig", 3 | "version": "0.0.1" 4 | } 5 | -------------------------------------------------------------------------------- /packages/tsconfig/react-library.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/tsconfig", 3 | "display": "React Library", 4 | "extends": "./base.json", 5 | "compilerOptions": { 6 | "jsx": "react-jsx", 7 | "lib": ["ES2015", "DOM"], 8 | "module": "ESNext", 9 | "target": "es6" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /packages/ui/src/components/collapsible.tsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"; 4 | 5 | const Collapsible = CollapsiblePrimitive.Root; 6 | 7 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger; 8 | 9 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent; 10 | 11 | export { Collapsible, CollapsibleTrigger, CollapsibleContent }; 12 | -------------------------------------------------------------------------------- /packages/ui/src/components/skeleton.tsx: -------------------------------------------------------------------------------- 1 | import { cn } from "../lib/utils"; 2 | 3 | function Skeleton({ 4 | className, 5 | ...props 6 | }: React.HTMLAttributes) { 7 | return ( 8 |
12 | ); 13 | } 14 | 15 | export { Skeleton }; 16 | -------------------------------------------------------------------------------- /packages/ui/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import type { ClassValue } from "clsx"; 2 | import { clsx } from "clsx"; 3 | import { twMerge } from "tailwind-merge"; 4 | 5 | export function cn(...inputs: ClassValue[]) { 6 | return twMerge(clsx(inputs)); 7 | } 8 | -------------------------------------------------------------------------------- /packages/ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/react-library.json", 3 | "include": ["."], 4 | "exclude": ["dist", "build", "node_modules"], 5 | "compilerOptions": { 6 | "paths": { 7 | "@/*": ["./src/*"] 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /packages/upstash/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/upstash", 3 | "version": "0.0.0", 4 | "license": "MIT", 5 | "main": "./src/index.ts", 6 | "dependencies": { 7 | "@upstash/kafka": "1.3.3", 8 | "@upstash/qstash": "2.6.2", 9 | "@upstash/ratelimit": "0.4.4", 10 | "@upstash/redis": "1.22.1" 11 | }, 12 | "devDependencies": { 13 | "@openstatus/tsconfig": "workspace:*", 14 | "@types/node": "22.10.2", 15 | "tsup": "7.2.0", 16 | "typescript": "5.6.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/upstash/src/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./redis/client"; 2 | export * from "@upstash/redis"; 3 | -------------------------------------------------------------------------------- /packages/upstash/src/redis/client.ts: -------------------------------------------------------------------------------- 1 | import { Redis } from "@upstash/redis"; 2 | 3 | // TO BE TESTED 4 | export const redis = Redis.fromEnv(); 5 | -------------------------------------------------------------------------------- /packages/upstash/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/base.json", 3 | "exclude": ["node_modules"], 4 | "compilerOptions": { 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "isolatedModules": true, 8 | "moduleResolution": "node", 9 | "preserveWatchOutput": true, 10 | "skipLibCheck": true, 11 | "noEmit": true, 12 | "strict": true 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /packages/utils/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@openstatus/utils", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.ts", 6 | "scripts": {}, 7 | "dependencies": {}, 8 | "devDependencies": { 9 | "@openstatus/assertions": "workspace:*", 10 | "@openstatus/db": "workspace:*", 11 | "@openstatus/tsconfig": "workspace:*", 12 | "typescript": "5.6.2", 13 | "zod": "3.23.8" 14 | }, 15 | "keywords": [], 16 | "author": "", 17 | "license": "ISC" 18 | } 19 | -------------------------------------------------------------------------------- /packages/utils/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@openstatus/tsconfig/base.json", 3 | "include": ["src", "*.ts"] 4 | } 5 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "apps/*" 3 | - "packages/**/*" 4 | - "packages/config/*" 5 | - "packages/emails/.react-email" 6 | -------------------------------------------------------------------------------- /utils/api-bruno/Monitor Summary.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Monitor Summary 3 | type: http 4 | seq: 3 5 | } 6 | 7 | get { 8 | url: {{url}}/v1/monitor/1/summary 9 | body: none 10 | auth: none 11 | } 12 | 13 | headers { 14 | x-openstatus-key: 1 15 | } 16 | -------------------------------------------------------------------------------- /utils/api-bruno/OpenApi.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: OpenApi 3 | type: http 4 | seq: 1 5 | } 6 | 7 | get { 8 | url: {{url}}/v1/openapi 9 | body: none 10 | auth: none 11 | } 12 | -------------------------------------------------------------------------------- /utils/api-bruno/bruno.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1", 3 | "name": "OpenStatus", 4 | "type": "collection" 5 | } 6 | -------------------------------------------------------------------------------- /utils/api-bruno/environments/local.bru: -------------------------------------------------------------------------------- 1 | vars { 2 | url: http://localhost:3000 3 | } 4 | -------------------------------------------------------------------------------- /utils/api-bruno/environments/prod.bru: -------------------------------------------------------------------------------- 1 | vars { 2 | url: https://api.openstatus.dev 3 | } 4 | -------------------------------------------------------------------------------- /utils/api-bruno/incident_update/Get Status Report Update.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Get Status Report Update 3 | type: http 4 | seq: 1 5 | } 6 | 7 | get { 8 | url: {{url}}/v1/status_report_update/{{updateId}} 9 | body: none 10 | auth: none 11 | } 12 | 13 | headers { 14 | x-openstatus-key: api-key 15 | } 16 | 17 | vars:pre-request { 18 | updateId: 32 19 | } 20 | -------------------------------------------------------------------------------- /utils/api-bruno/incidents/All Status Reports.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: All Status Reports 3 | type: http 4 | seq: 1 5 | } 6 | 7 | get { 8 | url: {{url}}/v1/status_report 9 | body: none 10 | auth: none 11 | } 12 | 13 | headers { 14 | x-openstatus-key: api-key 15 | } 16 | -------------------------------------------------------------------------------- /utils/api-bruno/incidents/Get Status Report.bru: -------------------------------------------------------------------------------- 1 | meta { 2 | name: Get on status report 3 | type: http 4 | seq: 2 5 | } 6 | 7 | get { 8 | url: {{url}}/v1/status_report/{{id}} 9 | body: none 10 | auth: none 11 | } 12 | 13 | headers { 14 | x-openstatus-key: api-key 15 | } 16 | 17 | vars:pre-request { 18 | id: 31 19 | } 20 | --------------------------------------------------------------------------------