mirror of
https://github.com/supabase/supabase.git
synced 2026-10-10 20:05:06 +03:00
## Summary
- Adds `breadcrumbListSchema(items)` helper to `apps/www/lib/json-ld.ts`
and a hand-curated `apps/www/lib/breadcrumbs.ts` route map.
- Wires inline `<script type="application/ld+json">` BreadcrumbList
blocks into 18 marketing surfaces: blog (index + slug), customers (index
+ slug), events (index + slug), 5 product pages (database, auth,
storage, edge-functions, realtime), 3 modules (vector, cron, queues),
pricing, careers, company, features.
- Pages router callers wrap the script in `<Head>`; app router callers
place it directly in JSX. Dynamic surfaces append a leaf at render time
using the page's title (`frontmatter.title` for blog, `meta_title ??
title` for customers, `event.meta_title ?? event.title` for events).
- Modules sit at `Home > {Name}` since no `/modules` index page exists;
products sit at `Home > {Product}` (no shared products parent). Absolute
`https://supabase.com` URLs match the existing `CANONICAL_ORIGIN`
convention so anchors stay stable across Vercel previews.
Linear:
[GROWTH-822](https://linear.app/supabase/issue/GROWTH-822/add-breadcrumblist-json-ld-to-www-marketing-surfaces)
(sub-issue under
[GROWTH-724](https://linear.app/supabase/issue/GROWTH-724)).
> **Note on branch name:** the branch is
`pamela/growth-820-www-breadcrumb-jsonld`; the actual Linear issue is
GROWTH-822. The branch was named before the sub-issue was created.
Ignore the `820` in the branch.
Explicitly deferred (separate PRs / low SEO ROI): `/launch-week/*`,
`/solutions/*`, `/partners/*`, `/alternatives/*`, `/changelog`,
`/legal/dpa`, `/aws-reinvent-2025`, `/wrapped`, `/contribute/*`,
`/brand-assets`, `/ga`, `/ga-week`, `/state-of-startups*`, and the
homepage (Organization + WebSite already cover homepage entity signals;
single-item BreadcrumbList is ignored by Google).
## Test plan
- [x] On the Vercel preview, `curl -s https://<preview>/database | grep
'"BreadcrumbList"'` returns the script block with `Home > Database`.
- [x] `curl -s https://<preview>/blog/<recent-slug> | grep
'"BreadcrumbList"'` returns `Home > Blog > {post title}`.
- [x] `curl -s https://<preview>/customers/<slug> | grep
'"BreadcrumbList"'` returns `Home > Customer Stories > {customer
title}`.
- [x] `curl -s https://<preview>/events/<slug> | grep
'"BreadcrumbList"'` returns `Home > Events > {event title}`.
- [x] `curl -s https://<preview>/modules/vector | grep
'"BreadcrumbList"'` returns `Home > Vector`.
284 lines
11 KiB
TypeScript
284 lines
11 KiB
TypeScript
import { useBreakpoint } from 'common'
|
|
import { ArrowUpRight, Briefcase, Eye, Link as IconLink, Shield } from 'lucide-react'
|
|
import { NextSeo } from 'next-seo'
|
|
import dynamic from 'next/dynamic'
|
|
import Head from 'next/head'
|
|
import NextImage from 'next/image'
|
|
import Link from 'next/link'
|
|
import { useRouter } from 'next/router'
|
|
import { PRODUCT_NAMES } from 'shared-data/products'
|
|
import { Button } from 'ui'
|
|
import { Image } from 'ui-patterns/Image'
|
|
|
|
import EventCallout from '@/components/EventCallout'
|
|
import DefaultLayout from '@/components/Layouts/Default'
|
|
import SectionContainer from '@/components/Layouts/SectionContainer'
|
|
import ProductsNav from '@/components/Products/ProductsNav'
|
|
import ProductHeader from '@/components/Sections/ProductHeader'
|
|
import AuthProviders from '@/data/auth.json'
|
|
import MainProducts from '@/data/MainProducts'
|
|
import ApiExamples from '@/data/products/auth/auth-api-examples'
|
|
import AuthSqlRulesExamples from '@/data/products/auth/auth-sql-rules-examples'
|
|
import { breadcrumbs } from '@/lib/breadcrumbs'
|
|
import { breadcrumbListSchema, serializeJsonLd, softwareApplicationSchema } from '@/lib/json-ld'
|
|
|
|
const SplitCodeBlockCarousel = dynamic(
|
|
() => import('~/components/Carousels/SplitCodeBlockCarousel')
|
|
)
|
|
const SingleQuote = dynamic(() => import('~/components/Sections/SingleQuote'))
|
|
const CTABanner = dynamic(() => import('~/components/CTABanner'))
|
|
const FeatureColumn = dynamic(() => import('~/components/FeatureColumn'))
|
|
const APISection = dynamic(() => import('~/components/Sections/APISection'))
|
|
const GithubExamples = dynamic(() => import('~/components/Sections/GithubExamples'))
|
|
|
|
// When updating page content, also update public/llms/auth.txt
|
|
|
|
function AuthPage() {
|
|
const isMobile = useBreakpoint(768)
|
|
const { basePath } = useRouter()
|
|
|
|
const meta_title = 'Auth | Built-in user management'
|
|
const meta_description =
|
|
'Authentication that you can afford that is built in to your supabase project.'
|
|
|
|
return (
|
|
<>
|
|
<NextSeo
|
|
title={meta_title}
|
|
description={meta_description}
|
|
openGraph={{
|
|
title: meta_title,
|
|
description: meta_description,
|
|
url: `https://supabase.com/auth`,
|
|
images: [
|
|
{
|
|
url: `https://supabase.com${basePath}/images/product/auth/auth-og.jpg`,
|
|
},
|
|
],
|
|
}}
|
|
/>
|
|
<Head>
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{
|
|
__html: serializeJsonLd(
|
|
softwareApplicationSchema({
|
|
name: 'Supabase Auth',
|
|
description: meta_description,
|
|
url: 'https://supabase.com/auth',
|
|
image: `https://supabase.com${basePath}/images/product/auth/auth-og.jpg`,
|
|
})
|
|
),
|
|
}}
|
|
/>
|
|
<script
|
|
type="application/ld+json"
|
|
dangerouslySetInnerHTML={{
|
|
__html: serializeJsonLd(breadcrumbListSchema(breadcrumbs.auth)),
|
|
}}
|
|
/>
|
|
</Head>
|
|
<DefaultLayout>
|
|
<ProductsNav activePage={PRODUCT_NAMES.AUTHENTICATION} />
|
|
<ProductHeader
|
|
callout={
|
|
<EventCallout
|
|
size={isMobile ? 'tiny' : 'small'}
|
|
className="mb-4 lg:mb-8 -mt-8 lg:-mt-10"
|
|
/>
|
|
}
|
|
icon={MainProducts['authentication'].icon}
|
|
title={MainProducts['authentication'].name}
|
|
h1={[
|
|
<span key={'authentication-h1'}>
|
|
Open Source Auth
|
|
<br /> (with tons of integrations)
|
|
</span>,
|
|
]}
|
|
subheader={[
|
|
'Every Supabase project comes with a complete User Management system that works without any additional tools.',
|
|
"Including PostgreSQL's policy engine, for fine-grained access rules.",
|
|
]}
|
|
image={[
|
|
<Image
|
|
src={{
|
|
light: `${basePath}/images/product/auth/header--light.png`,
|
|
dark: `${basePath}/images/product/auth/header--dark.png`,
|
|
}}
|
|
alt="auth header"
|
|
layout="responsive"
|
|
width="1372"
|
|
height="1074"
|
|
/>,
|
|
]}
|
|
documentation_url={'/docs/guides/auth'}
|
|
/>
|
|
|
|
<SectionContainer>
|
|
<div className="grid grid-cols-12">
|
|
<div className="col-span-12 mb-10 lg:col-span-3 lg:mb-0">
|
|
<div className="mb-4 mt-[-1.9rem]">
|
|
<div className="grid grid-flow-col grid-rows-2 gap-2 xl:w-64">
|
|
<div className="flex w-fit items-center">
|
|
<svg
|
|
xmlns="http://www.w3.org/2000/svg"
|
|
viewBox="0 0 32.58 31.77"
|
|
width={21}
|
|
height={21}
|
|
className="text-foreground-light"
|
|
>
|
|
<path
|
|
fill="currentColor"
|
|
d="M16.29,0a16.29,16.29,0,0,0-5.15,31.75c.82.15,1.11-.36,1.11-.79s0-1.41,0-2.77C7.7,29.18,6.74,26,6.74,26a4.36,4.36,0,0,0-1.81-2.39c-1.47-1,.12-1,.12-1a3.43,3.43,0,0,1,2.49,1.68,3.48,3.48,0,0,0,4.74,1.36,3.46,3.46,0,0,1,1-2.18c-3.62-.41-7.42-1.81-7.42-8a6.3,6.3,0,0,1,1.67-4.37,5.94,5.94,0,0,1,.16-4.31s1.37-.44,4.48,1.67a15.41,15.41,0,0,1,8.16,0c3.11-2.11,4.47-1.67,4.47-1.67A5.91,5.91,0,0,1,25,11.07a6.3,6.3,0,0,1,1.67,4.37c0,6.26-3.81,7.63-7.44,8a3.85,3.85,0,0,1,1.11,3c0,2.18,0,3.94,0,4.47s.29.94,1.12.78A16.29,16.29,0,0,0,16.29,0Z"
|
|
/>
|
|
</svg>
|
|
</div>
|
|
{AuthProviders.map((auth, i) => {
|
|
return (
|
|
<div className="flex w-fit items-center text-foreground-light" key={i}>
|
|
<NextImage
|
|
src={`${basePath}/images/product/auth/${auth.name}-icon.svg`}
|
|
alt={`${auth.name} auth login icon`}
|
|
key={auth.name}
|
|
height={21}
|
|
width={21}
|
|
/>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
</div>
|
|
<h4 className="h4">All the social providers</h4>
|
|
<p className="p text-base">
|
|
Enable social logins with the click of a button. Google, Facebook, GitHub, Azure
|
|
(Microsoft), Gitlab, Twitter, Discord, and many more.
|
|
</p>
|
|
</div>
|
|
<div className="col-span-12 mb-10 lg:col-span-3 lg:col-start-5 lg:mb-0">
|
|
<div className="p mb-4">
|
|
<IconLink />
|
|
</div>
|
|
<h4 className="h4">Fully integrated</h4>
|
|
<p className="p text-base">
|
|
Incredibly simple Auth, without a single external authentication service. Built-in
|
|
Authentication, Authorization, and User Management.
|
|
</p>
|
|
</div>
|
|
<div className="col-span-12 lg:col-span-3 lg:col-start-9">
|
|
<div className="p mb-4">
|
|
<Shield />
|
|
</div>
|
|
<h4 className="h4">Own your data</h4>
|
|
<p className="p text-base">
|
|
User data stored in your Supabase database so you never have to worry about 3rd
|
|
party privacy issues. Host your data in 16 different locations.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</SectionContainer>
|
|
|
|
<SingleQuote
|
|
id="quote"
|
|
className="[&_q]:max-w-2xl"
|
|
quote={{
|
|
text: 'Supabase is not only super easy to get started, but also provides all the backend solutions we require as we continue to grow.',
|
|
author: 'Alfred Lua',
|
|
role: 'Cofounder of Pebblely',
|
|
link: '/customers/pebblely',
|
|
logo: (
|
|
<NextImage
|
|
draggable={false}
|
|
src="/images/blog/avatars/alfred-lua-pebblely.jpeg"
|
|
alt="Alfred Lua, Cofounder of Pebblely"
|
|
className="w-10 h-10 rounded-full overflow-hidden object-cover"
|
|
width={28}
|
|
height={28}
|
|
/>
|
|
),
|
|
}}
|
|
/>
|
|
|
|
<SectionContainer>
|
|
<APISection
|
|
title="Simple APIs"
|
|
// @ts-ignore
|
|
content={ApiExamples}
|
|
size="large"
|
|
text={[
|
|
<p key={0} className="text-base lg:text-lg">
|
|
APIs that you can understand. With powerful libraries that work on client and
|
|
server-side applications.
|
|
</p>,
|
|
]}
|
|
footer={[
|
|
<div className="mt-8 grid grid-cols-12 md:gap-8 lg:gap-0 xl:gap-16" key={0}>
|
|
<div className="col-span-12 sm:col-span-6 lg:col-span-12 xl:col-span-4">
|
|
<FeatureColumn
|
|
icon={<Briefcase />}
|
|
title="Enterprise logins"
|
|
text="Support for SAML, Azure. More enterprise providers and SSO coming soon."
|
|
/>
|
|
</div>
|
|
<div className="col-span-12 sm:col-span-6 lg:col-span-12 xl:col-span-4">
|
|
<FeatureColumn
|
|
icon={<Eye />}
|
|
title="Social login scopes"
|
|
text="Request additional user data permissions when using social logins."
|
|
/>
|
|
</div>
|
|
</div>,
|
|
]}
|
|
documentation_link={'/docs/guides/auth'}
|
|
/>
|
|
</SectionContainer>
|
|
|
|
<div className="relative">
|
|
<div className="section--masked">
|
|
<div className="section--bg-masked">
|
|
<div className="section--bg border-t border-b border-control"></div>
|
|
</div>
|
|
<div className="section-container pt-12 pb-0">
|
|
<div className="overflow-x-hidden">
|
|
<SectionContainer className="mb-0 pb-8">
|
|
<GithubExamples />
|
|
</SectionContainer>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<SectionContainer>
|
|
<div className="grid grid-cols-12 lg:mt-16 lg:gap-16">
|
|
<div className="col-span-12 mb-8 lg:col-span-5">
|
|
<h2 className="h3">User permissions without the middleware</h2>
|
|
|
|
<p className="p text-base lg:text-lg">
|
|
Supabase Auth works without any additional servers. Build Authorization rules with
|
|
Postgres' Row Level Security, controlling who can create, edit and delete specific
|
|
rows in your database.
|
|
</p>
|
|
<p className="p">Policies can be written in SQL or using the dashboard online.</p>
|
|
|
|
<Button asChild size="small" type="default" className="mt-4" icon={<ArrowUpRight />}>
|
|
<Link href="/docs/guides/database/postgres/row-level-security">
|
|
Explore documentation
|
|
</Link>
|
|
</Button>
|
|
</div>
|
|
<div className="col-span-12 lg:col-span-6 lg:col-start-7">
|
|
<SplitCodeBlockCarousel
|
|
// @ts-ignore
|
|
content={AuthSqlRulesExamples}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</SectionContainer>
|
|
|
|
<CTABanner />
|
|
</DefaultLayout>
|
|
</>
|
|
)
|
|
}
|
|
|
|
export default AuthPage
|