Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 46 additions & 13 deletions apps/docs/app/guides/database/database-advisors/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Octokit } from '@octokit/core'
import { capitalize } from 'lodash-es'
import rehypeSlug from 'rehype-slug'
import { Heading } from 'ui'
import { Admonition } from 'ui-patterns'

import { GuideTemplate, newEditLink } from '~/features/docs/GuidesMdx.template'
import { genGuideMeta } from '~/features/docs/GuidesMdx.utils'
Expand Down Expand Up @@ -43,7 +44,18 @@ In the dashboard, navigate to [Security Advisor](https://supabase.com/dashboard/
const getBasename = (path: string) => path.split('/').at(-1)!.replace(/\.md$/, '')

const DatabaseAdvisorDocs = async () => {
const { lints, lintsList } = await getLints()
let lints: Awaited<ReturnType<typeof getLints>>['lints'] = []
let lintsList: Awaited<ReturnType<typeof getLints>>['lintsList'] = []
let fetchError: Error | null = null

try {
const data = await getLints()
lints = data.lints
lintsList = data.lintsList
} catch (error) {
fetchError = error instanceof Error ? error : new Error('Unknown error fetching advisor docs')
console.error('[database-advisors] Failed to fetch advisor docs from GitHub', fetchError)
}

const options = {
mdxOptions: {
Expand All @@ -56,19 +68,40 @@ const DatabaseAdvisorDocs = async () => {
<GuideTemplate meta={meta} editLink={editLink}>
<MDXRemoteBase source={markdownIntro} />
<Heading tag="h2">Available checks</Heading>
<Tabs listClassNames="flex flex-wrap gap-2 [&>button]:!m-0" queryGroup="lint">
{lints.map((lint) => (
<TabPanel
key={lint.path}
id={lint.path}
label={capitalize(getBasename(lint.path).replace(/_/g, ' '))}

{fetchError ? (
<Admonition type="note" title="Couldn’t load the full Advisor library">
We fetch remediation guides straight from the <code>supabase/splinter</code> repository
during the build. GitHub timed out just now, so we’re showing the overview only.
<br />
<br />
You can check back in a few minutes or browse the
{` `}
<a
className="underline decoration-dashed underline-offset-2"
href="https://github.com/supabase/splinter/tree/main/docs"
target="_blank"
rel="noreferrer"
>
<section id={getBasename(lint.path)}>
<MDXRemoteBase source={lint.content} options={options} />
</section>
</TabPanel>
))}
</Tabs>
latest Markdown on GitHub (opens in a new tab)
</a>
.
</Admonition>
) : (
<Tabs listClassNames="flex flex-wrap gap-2 [&>button]:!m-0" queryGroup="lint">
{lints.map((lint) => (
<TabPanel
key={lint.path}
id={lint.path}
label={capitalize(getBasename(lint.path).replace(/_/g, ' '))}
>
<section id={getBasename(lint.path)}>
<MDXRemoteBase source={lint.content} options={options} />
</section>
</TabPanel>
))}
</Tabs>
)}
</GuideTemplate>
)
}
Expand Down
116 changes: 116 additions & 0 deletions apps/docs/components/MetricsStackCards.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
import Link from 'next/link'
import { Datadog, Grafana } from 'icons'
import { Flame } from 'lucide-react'
import type { ReactNode } from 'react'

interface MetricsStackOption {
title: string
description: ReactNode
href: string
icon: ReactNode
iconColor: string
iconBg: string
badges: { label: string; variant: 'default' | 'community' }[]
}

const metricsStackOptions: MetricsStackOption[] = [
{
title: 'Grafana Cloud (SaaS)',
description: (
<>
Use Grafana Cloud’s managed Prometheus (works on Free + Pro tiers) and import the Supabase
dashboard without running any infrastructure.
</>
),
href: '/guides/telemetry/metrics/grafana-cloud',
icon: <Grafana className="h-5 w-5" />,
iconColor: '#F05A28',
iconBg: 'rgba(240,90,40,0.1)',
badges: [
{ label: 'Supabase guide', variant: 'default' },
{ label: 'Community', variant: 'community' },
],
},
{
title: 'Grafana + self-hosted Prometheus',
description: (
<>
Run Prometheus yourself following the official installation guidance and pair it with
Grafana plus our dashboard JSON and alert pack.
</>
),
href: '/guides/telemetry/metrics/grafana-self-hosted',
icon: <Grafana className="h-5 w-5" />,
iconColor: '#F05A28',
iconBg: 'rgba(240,90,40,0.1)',
badges: [{ label: 'Supabase guide', variant: 'default' }],
},
{
title: 'Datadog',
description: (
<>
Scrape the Metrics API with the Datadog Agent or Prometheus remote write and monitor
Supabase alongside your app telemetry.
</>
),
href: '/guides/telemetry/metrics/datadog',
icon: <Datadog className="h-5 w-5" />,
iconColor: '#632CA6',
iconBg: 'rgba(99,44,166,0.1)',
badges: [
{ label: 'Supabase guide', variant: 'default' },
{ label: 'Community', variant: 'community' },
],
},
{
title: 'Vendor-agnostic / BYO Prometheus',
description: (
<>
Connect AWS AMP, Grafana Mimir, VictoriaMetrics, or any Prometheus-compatible SaaS with the
same scrape job pattern.
</>
),
href: '/guides/telemetry/metrics/vendor-agnostic',
icon: <Flame className="h-5 w-5" strokeWidth={1.5} />,
iconColor: '#0BA678',
iconBg: 'rgba(11,166,120,0.1)',
badges: [{ label: 'Supabase guide', variant: 'default' }],
},
]

export function MetricsStackCards() {
return (
<div className="grid gap-4 not-prose md:grid-cols-2">
{metricsStackOptions.map((option) => (
<Link key={option.href} href={option.href} className="col-span-1 block h-full">
<div className="relative flex h-full flex-col gap-4 rounded-2xl border border-foreground/10 bg-surface-75/50 p-5 text-left transition duration-200 hover:border-foreground/30 hover:bg-surface-100">
<div className="flex items-center gap-3">
<span
className="flex h-10 w-10 items-center justify-center rounded-full text-base font-semibold"
style={{ color: option.iconColor, backgroundColor: option.iconBg }}
>
{option.icon}
</span>
<p className="text-base font-medium text-foreground">{option.title}</p>
</div>
<div className="text-sm text-foreground-light">{option.description}</div>
<div className="mt-auto flex flex-wrap gap-2">
{option.badges.map((badge) => (
<span
key={`${option.href}-${badge.label}`}
className={`inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-medium ${
badge.variant === 'community'
? 'border-warning/40 text-warning'
: 'border-brand-500/50 text-brand'
}`}
>
{badge.label}
</span>
))}
</div>
</div>
</Link>
))}
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -2754,6 +2754,28 @@ export const telemetry: NavMenuConstant = {
{
name: 'Metrics',
url: '/guides/telemetry/metrics' as `/${string}`,
items: [
{
name: 'Overview',
url: '/guides/telemetry/metrics' as `/${string}`,
},
{
name: 'Grafana Cloud',
url: '/guides/telemetry/metrics/grafana-cloud' as `/${string}`,
},
{
name: 'Grafana self-hosted',
url: '/guides/telemetry/metrics/grafana-self-hosted' as `/${string}`,
},
{
name: 'Datadog',
url: '/guides/telemetry/metrics/datadog' as `/${string}`,
},
{
name: 'Vendor-agnostic setup',
url: '/guides/telemetry/metrics/vendor-agnostic' as `/${string}`,
},
],
},
{
name: 'Sentry integration',
Expand Down Expand Up @@ -2929,22 +2951,25 @@ export const integrations: NavMenuConstant = {
},
{
name: 'Build Your Own',
url: undefined,
items: [
{
name: 'Build a Supabase integration',
url: '/guides/integrations/build-a-supabase-integration',
name: 'Supabase OAuth Integration',
url: '/guides/integrations/build-a-supabase-oauth-integration',
items: [
{
name: 'Overview',
url: '/guides/integrations/build-a-supabase-integration' as `/${string}`,
url: '/guides/integrations/build-a-supabase-oauth-integration',
},
{
name: 'OAuth scopes',
url: '/guides/integrations/build-a-supabase-integration/oauth-scopes' as `/${string}`,
url: '/guides/integrations/build-a-supabase-oauth-integration/oauth-scopes',
},
],
},
{
name: 'Supabase for Platforms',
url: '/guides/integrations/supabase-for-platforms',
},
],
},
{ name: 'Integrations', url: undefined, items: [] },
Expand Down
50 changes: 50 additions & 0 deletions apps/docs/content/_partials/metrics_access.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
<Accordion
type="default"
openBehaviour="multiple"
chevronAlign="right"
justified
size="medium"
className="text-foreground-light mt-8 mb-6 [&>div]:space-y-4"
>

<AccordionItem
header={<span className="text-foreground">What you can do with the Metrics API</span>}
id="how-do-i-check-when-a-user-went-through-mfa"
>

Every Supabase project exposes a metrics feed at `https://<project-ref>.supabase.co/customer/v1/privileged/metrics`. Replace `<project-ref>` with the identifier from your project URL or from the dashboard sidebar.

1. Copy your project reference and confirm the base URL using the helper below.

<ProjectConfigVariables variable="url" />

2. Configure your collector to scrape once per minute. The endpoint already emits the full set of metrics on each request.
3. Authenticate with HTTP Basic Auth:

- **Username**: `service_role`
- **Password**: a service role secret (JWT) from [**Project Settings > JWT** (opens in a new tab)](/dashboard/project/_/settings/jwt) or any other Secret API key from [**Project Settings > API keys** (opens in a new tab)](/dashboard/project/_/settings/api-keys)

Testing locally is as simple as running `curl` with your service role secret:

```bash
curl <project-url>/customer/v1/privileged/metrics \
--user 'service_role:sb_secret_...'
```

You can provision long-lived automation tokens in two ways:

- Create an account access token once at [**Account Settings > Access Tokens (opens in a new tab)**](/dashboard/account/tokens) and reuse it wherever you configure observability tooling.
- **Optional**: programmatically exchange an access token for project API keys via the [Management API ](/docs/reference/api/management-projects-api-keys-retrieve').

```bash
# (Optional) Exchange an account access token for project API keys
export SUPABASE_ACCESS_TOKEN="your-access-token"
export PROJECT_REF="your-project-ref"

curl -H "Authorization: Bearer $SUPABASE_ACCESS_TOKEN" \
"https://api.supabase.com/v1/projects/$PROJECT_REF/api-keys?reveal=true"
```

</AccordionItem>

</Accordion>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
id: 'build-a-supabase-integration'
id: 'build-a-supabase-oauth-integration'
title: 'Build a Supabase Integration'
subtitle: "This guide steps through building a Supabase Integration using OAuth2 and the management API, allowing you to manage users' organizations and projects on their behalf."
description: 'Build a Supabase Integration using OAuth2 and the Management API.'
Expand Down
Loading
Loading