Merge branch 'master' of github.com:supabase/supabase into docs/local-dev

This commit is contained in:
Copple committed 2023-08-03 13:00:32 +02:00
commit 1296cf8909
210 files changed
+2245 -777

No files matched your search

@@ -89,13 +89,13 @@ export const highlightSelectedNavItem = (id: string) => {
const navMenuItems = document.querySelectorAll<HTMLAnchorElement>('.function-link-item a')
// find any currently active items and remove them
const currentActiveItems = document.querySelectorAll('.function-link-list .text-brand-900')
currentActiveItems.forEach((item) => item.classList.remove('text-brand-900'))
const currentActiveItems = document.querySelectorAll('.function-link-list .text-brand')
currentActiveItems.forEach((item) => item.classList.remove('text-brand'))
// Add active class to the current item
navMenuItems.forEach((item) => {
if (item.href.split('/').at(-1) === id) {
item.classList.add('text-brand-900')
item.classList.add('text-brand')
}
})
}
@@ -46,7 +46,7 @@ const GuidesTableOfContents: FC<Props> = ({ list }) => {
<li key={`${item.level}-${i}`} className={item.level === 3 ? 'ml-4' : ''}>
<a
href={`#${formatSlug(item.link)}`}
className="text-scale-1000 hover:text-brand-900 transition-colors"
className="text-scale-1000 hover:text-brand transition-colors"
dangerouslySetInnerHTML={{ __html: formatTOCHeader(removeAnchor(item.text)) }}
/>
</li>
+6 -1
View File
@@ -28,6 +28,11 @@ const HomePageCover = (props) => {
icon: '/docs/img/icons/flutter-icon',
href: '/guides/getting-started/quickstarts/flutter',
},
{
tooltip: 'Android Kotlin',
icon: '/docs/img/icons/kotlin-icon',
href: '/guides/getting-started/quickstarts/kotlin',
},
{
tooltip: 'SvelteKit',
icon: '/docs/img/icons/svelte-icon',
@@ -69,7 +74,7 @@ const HomePageCover = (props) => {
<div className="md:max-w-xs xl:max-w-none">
<div className="flex items-center gap-3 mb-3">
<IconBackground>
<IconPlay className="text-brand-1100 dark:text-brand-900 w-4" />
<IconPlay className="text-brand-600 dark:text-brand w-4" strokeWidth={2} />
</IconBackground>
<h3 className="text-2xl m-0">Getting Started</h3>
</div>
+1 -1
View File
@@ -14,7 +14,7 @@ export default function LinkCard({
}) {
return (
<Link href={link || '#'}>
<a className="border-scale-200 hover:border-brand-900 dark:bg-scale-400 m-4 w-full cursor-pointer rounded-md border p-4 shadow-sm hover:shadow-2xl lg:w-2/5">
<a className="border-scale-200 hover:border-brand dark:bg-scale-400 m-4 w-full cursor-pointer rounded-md border p-4 shadow-sm hover:shadow-2xl lg:w-2/5">
{description ? (
<>
<h4 className="m-0 mb-4 p-0 text-base font-semibold">{title}</h4>
+1 -5
View File
@@ -29,11 +29,7 @@ const Footer = () => (
{Icon && <Icon width={16} height={16} />}
<p>{text}</p>
<Link href={url} passHref>
<a
className="text-brand-900 hover:underline"
target="_blank"
rel="noreferrer noopener"
>
<a className="text-brand hover:underline" target="_blank" rel="noreferrer noopener">
{ctaLabel}
</a>
</Link>
@@ -669,10 +669,23 @@ export const database: NavMenuConstant = {
name: 'RUM: inverted index for full-text search',
url: '/guides/database/extensions/rum',
},
],
},
{
name: 'Foreign Data Wrappers',
url: undefined,
items: [
{ name: 'Overview', url: '/guides/database/extensions/wrappers/overview' },
{ name: 'Connecting to Airtable', url: '/guides/database/extensions/wrappers/airtable' },
{ name: 'Connecting to AWS S3', url: '/guides/database/extensions/wrappers/s3' },
{ name: 'Connecting to BigQuery', url: '/guides/database/extensions/wrappers/bigquery' },
{
name: 'wrappers: 3rd Party Integrations',
url: '/guides/database/extensions/wrappers',
name: 'Connecting to ClickHouse',
url: '/guides/database/extensions/wrappers/clickhouse',
},
{ name: 'Connecting to Firebase', url: '/guides/database/extensions/wrappers/firebase' },
{ name: 'Connecting to Logflare', url: '/guides/database/extensions/wrappers/logflare' },
{ name: 'Connecting to Stripe', url: '/guides/database/extensions/wrappers/stripe' },
],
},
{
@@ -23,7 +23,7 @@ const NavigationMenuCliList = ({ currentLevel, setLevel, id }) => {
return (
<li key={id} className="function-link-item text-scale-1000 leading-3">
<Link href={`#${id}`} passHref>
<a className="cursor-pointer transition text-scale-1000 text-sm hover:text-brand-900 flex gap-3">
<a className="cursor-pointer transition text-scale-1000 text-sm hover:text-brand flex gap-3">
{icon && <img className="w-3" src={`${router.basePath}${icon}`} />}
{title}
</a>
@@ -100,7 +100,7 @@ const NavigationMenuCliList = ({ currentLevel, setLevel, id }) => {
<a
className={[
'flex items-center gap-1 text-xs group mb-3',
'text-base transition-all duration-200 text-brand-900 hover:text-brand-1200 hover:cursor-pointer ',
'text-base transition-all duration-200 text-brand hover:text-brand-600 hover:cursor-pointer ',
].join(' ')}
>
<div className="relative w-2">
@@ -19,7 +19,7 @@ const HeaderLink = React.memo(function HeaderLink(props: {
className={[
' ',
!props.title && 'capitalize',
props.url === router.pathname ? 'text-brand-900' : 'hover:text-brand-900 text-scale-1200',
props.url === router.pathname ? 'text-brand' : 'hover:text-brand text-scale-1200',
].join(' ')}
>
{props.title ?? props.id}
@@ -68,7 +68,7 @@ const ContentAccordionLink = React.memo(function ContentAccordionLink(props: any
'flex items-center gap-2',
'cursor-pointer transition text-sm',
activeItem
? 'text-brand-900 font-medium'
? 'text-brand font-medium'
: 'hover:text-scale-1200 dark:hover:text-scale-1100 text-scale-1000',
].join(' ')}
parent={props.subItem.parent}
@@ -97,8 +97,8 @@ const ContentAccordionLink = React.memo(function ContentAccordionLink(props: any
className={[
'cursor-pointer transition text-sm',
subSubItem.url === router.pathname
? 'text-brand-900'
: 'hover:text-brand-900 text-scale-1000',
? 'text-brand'
: 'hover:text-brand text-scale-1000',
].join(' ')}
>
{subSubItem.name}
@@ -124,7 +124,7 @@ const ContentLink = React.memo(function ContentLink(props: any) {
className={[
'cursor-pointer transition text-sm',
props.url === router.pathname
? 'text-brand-900'
? 'text-brand'
: 'hover:text-scale-1200 dark:hover:text-scale-1100 text-scale-1000',
].join(' ')}
>
@@ -152,7 +152,7 @@ const Content = (props) => {
<a
className={[
'flex items-center gap-1 text-xs group mb-3',
'text-base transition-all duration-200 text-brand-900 hover:text-brand-1200 hover:cursor-pointer ',
'text-base transition-all duration-200 text-brand hover:text-brand-600 hover:cursor-pointer ',
].join(' ')}
>
<div className="relative w-2">
@@ -166,7 +166,7 @@ const Content = (props) => {
<Link href={menu.url ?? ''} passHref>
<a>
<div className="flex items-center gap-3 my-3 text-brand-900">
<div className="flex items-center gap-3 my-3 text-brand">
<HomeMenuIconPicker icon={menu.icon} />
<HeaderLink title={menu.title} url={menu.url} id={id} />
</div>
@@ -16,7 +16,7 @@ import { deepFilterSections } from './NavigationMenu.utils'
const HeaderLink = React.memo(function HeaderLink(props: any) {
return (
<span className={['text-base text-brand-1200 ', !props.title && 'capitalize'].join(' ')}>
<span className={['text-base text-brand-600 ', !props.title && 'capitalize'].join(' ')}>
{props.title ?? props.id}
</span>
)
@@ -64,7 +64,7 @@ const FunctionLink = React.memo(function FunctionLink({
className={cn(
'cursor-pointer transition text-sm hover:text-scale-1200 gap-3 relative',
isParent ? 'flex justify-between' : 'leading-3',
active ? 'text-brand-900' : 'text-scale-1000'
active ? 'text-brand' : 'text-scale-1000'
)}
>
{icon && <Image width={16} height={16} alt={icon} src={`${router.basePath}${icon}`} />}
@@ -72,7 +72,7 @@ const FunctionLink = React.memo(function FunctionLink({
{active && !isSubItem && (
<div
aria-hidden="true"
className="absolute -left-[13px] top-0 bottom-0 w-[1px] bg-brand-1000"
className="absolute -left-[13px] top-0 bottom-0 w-[1px] bg-brand-600"
></div>
)}
{isParent && (
@@ -180,7 +180,7 @@ const NavigationMenuRefListItems = ({
<a
className={[
'flex items-center gap-1 text-xs group mb-3',
'text-base transition-all duration-200 text-scale-1100 hover:text-brand-1200 hover:cursor-pointer ',
'text-base transition-all duration-200 text-scale-1100 hover:text-brand-600 hover:cursor-pointer ',
].join(' ')}
>
<div className="relative w-2">
@@ -56,7 +56,7 @@ const TopNavBarRef: FC = () => {
}
return (
<nav className="h-[60px] border-b backdrop-blur backdrop-filter bg-white-1200 dark:bg-scale-200/90">
<nav className="h-[60px] border-b backdrop-blur backdrop-filter bg bg-opacity-75">
<div className="px-5 max-w-7xl mx-auto flex gap-3 justify-between items-center h-full">
<div className={['lg:hidden'].join(' ')}>
<Link href="/">
@@ -68,7 +68,7 @@ const TopNavBarRef: FC = () => {
height={24}
alt="Supabase Logo"
/>
<span className="font-mono text-sm font-medium text-brand-900">DOCS</span>
<span className="font-mono text-sm font-medium text-brand">DOCS</span>
</a>
</Link>
{/* {router.asPath.includes('/reference/') && <RefSwitcher />} */}
@@ -82,21 +82,22 @@ const TopNavBarRef: FC = () => {
group
items-center
justify-between
bg-scaleA-200
bg-surface-100
bg-opacity-75
hover:bg-surface-200
hover:bg-opacity-100
border
transition
hover:border-scale-600
hover:bg-scaleA-300
border-scale-500 pl-1.5 md:pl-3 pr-1.5 w-full h-[32px] rounded"
border-scale-500 pl-1.5 md:pl-3 pr-1.5 w-full h-[32px] rounded
text-lighter
"
>
<div className="flex items-center space-x-2">
<IconSearch className="text-scale-1100" size={18} strokeWidth={2} />
<p className="hidden md:flex text-scale-1100 text-sm group-hover:text-scale-1200 transition">
Search docs...
</p>
<IconSearch className="" size={18} strokeWidth={2} />
<p className="hidden md:flex text-sm">Search docs...</p>
</div>
<div className="hidden md:flex items-center space-x-1">
<div className="text-scale-1200 md:flex items-center justify-center h-5 w-10 border rounded bg-scale-500 border-scale-700 gap-1">
<div className="md:flex items-center justify-center h-5 w-10 border rounded bg-surface-300 gap-1">
<IconCommand size={12} strokeWidth={1.5} />
<span className="text-[12px]">K</span>
</div>
+5 -5
View File
@@ -83,7 +83,7 @@ const SideBar = ({ menuItems = [] }: { menuItems: any }) => {
'py-1.5 px-5 rounded text-sm transition',
`${
item.url === asPath
? 'bg-scale-200 text-brand-900'
? 'bg-scale-200 text-brand'
: 'text-scale-1100 hover:text-scale-1200'
}`,
].join(' ')}
@@ -109,7 +109,7 @@ const SideBar = ({ menuItems = [] }: { menuItems: any }) => {
size={14}
strokeWidth={2}
/>
<span className="text-scale-1200 text-sm group-hover:text-brand-900 transition">
<span className="text-scale-1200 text-sm group-hover:text-brand transition">
{group.label}
</span>
</Accordion.Trigger>
@@ -124,7 +124,7 @@ const SideBar = ({ menuItems = [] }: { menuItems: any }) => {
'py-1.5 px-5 rounded text-sm transition',
`${
section.url === asPath
? 'bg-scale-200 text-brand-900'
? 'bg-scale-200 text-brand'
: 'text-scale-1100 hover:text-scale-1200'
}`,
].join(' ')}
@@ -150,7 +150,7 @@ const SideBar = ({ menuItems = [] }: { menuItems: any }) => {
size={14}
strokeWidth={2}
/>
<span className="text-scale-1200 text-sm group-hover:text-brand-900 transition">
<span className="text-scale-1200 text-sm group-hover:text-brand transition">
{section.name}
</span>
</Accordion.Trigger>
@@ -164,7 +164,7 @@ const SideBar = ({ menuItems = [] }: { menuItems: any }) => {
'py-1.5 ml-4 px-5 rounded text-sm transition',
`${
item.url === asPath
? 'bg-scale-200 text-brand-900'
? 'bg-scale-200 text-brand'
: 'text-scale-1100 hover:text-scale-1200'
}`,
].join(' ')}
+1 -1
View File
@@ -27,7 +27,7 @@ const Pagination = ({ currentPage, totalCount }: { currentPage: number; totalCou
<Link href={`/discussions?page=${page}`}>
<a
className={`border-scale-600 inline-flex h-8 w-8 items-center justify-center rounded border ${
currentPage === page ? 'bg-brand-900' : 'bg-scale-300'
currentPage === page ? 'bg-brand' : 'bg-scale-300'
}`}
>
{page}
+1 -1
View File
@@ -69,7 +69,7 @@ const TableOfContents: FC<Props> = ({ toc, video }) => {
<li key={i} id={item.lvl} style={{ marginLeft: `${(item.lvl - 2) * 1}rem` }}>
<a
href={`#${formatSlug(item.slug)}`}
className="text-scale-1000 hover:text-brand-900 transition-colors"
className="text-scale-1000 hover:text-brand transition-colors"
dangerouslySetInnerHTML={{ __html: formatTOCHeader(removeAnchor(item.content)) }}
/>
</li>
@@ -96,7 +96,7 @@ const CliCommandSection = (props) => {
</div>
<a
href={`#${subcommand}`}
className="transition text-scale-1100 hover:text-brand-900"
className="transition text-scale-1100 hover:text-brand"
>
$ {subcommand.replace(/-/g, ' ')}
</a>
@@ -27,7 +27,7 @@ const OldVersionAlert = ({ sections }: OldVersionAlertProps) => {
You&apos;re viewing an older version of this library.
<br />
<Link href={latestVersionUrl}>
<a className="underline decoration-brand-700 underline-offset-4 decoration-1">
<a className="underline decoration-brand-400 underline-offset-4 decoration-1">
Switch to the latest
</a>
</Link>
@@ -174,7 +174,7 @@ const RefFunctionSection: React.FC<IRefFunctionSection> = (props) => {
<div className="bg-scale-300 border rounded prose max-w-none">
<div className="bg-scale-200 px-5 py-2">
<div className="flex gap-2 items-center">
<div className="text-brand-900">
<div className="text-brand">
<IconDatabase size={16} />
</div>
<h5 className="text-xs text-scale-1200">
+1 -1
View File
@@ -228,7 +228,7 @@ const HeaderLogo = memo(function HeaderLogo() {
height={24}
alt="Supabase Logo"
/>
<span className="font-mono text-sm font-medium text-brand-900">DOCS</span>
<span className="font-mono text-sm font-medium text-brand">DOCS</span>
</a>
</Link>
)
+1 -1
View File
@@ -115,7 +115,7 @@ const Layout: FC<Props> = (props) => {
].join(' ')}
>
{props.meta.breadcrumb && (
<p className="text-brand-900 tracking-wider mb-3">{props.meta.breadcrumb}</p>
<p className="text-brand tracking-wider mb-3">{props.meta.breadcrumb}</p>
)}
<article
ref={articleRef}
+1 -1
View File
@@ -107,7 +107,7 @@ const StickyHeader: FC<StickyHeader> = ({ icon, ...props }) => {
return (
<div className={['flex items-center gap-3 not-prose', icon && 'mb-8'].join(' ')}>
{icon && (
<div className="w-8 h-8 bg-brand-500 rounded flex items-center justify-center">
<div className="w-8 h-8 bg-brand-300 rounded flex items-center justify-center">
<Image width={16} height={16} alt={icon} src={`${icon}.svg`} />
</div>
)}
@@ -61,10 +61,10 @@ const Layout: FC<Props> = (props: Props) => {
].join(' ')}
>
<div>
<p className="text-brand-900 tracking-wider">Tutorials</p>
<p className="text-brand tracking-wider">Tutorials</p>
<article className={['prose dark:prose-dark ', 'max-w-none'].join(' ')}>
<h1>{props.meta.title}</h1>
<div className="max-w-xs w-32 h-[1px] bg-gradient-to-r from-brand-800 to-brand-900 my-16"></div>
<div className="max-w-xs w-32 h-[1px] bg-gradient-to-r from-brand-300 to-brand my-16"></div>
<MDXProvider components={components} children={props.children} />
</article>
+138
View File
@@ -0,0 +1,138 @@
import { Content, Paragraph, Parent } from 'mdast'
import { MdxJsxFlowElement } from 'mdast-util-mdx'
import { Node } from 'unist'
import { visit } from 'unist-util-visit'
/**
* Transforms PyMdown Tabs to Supabase Tabs.
*
* https://facelessuser.github.io/pymdown-extensions/extensions/tabbed/
*/
const remarkPyMdownTabs = function () {
return function transformer(root: Parent) {
visit(root, 'paragraph', (node: Paragraph, nodeIndex: number, parent: Parent) => {
for (let i = 0; i < node.children.length; i++) {
const child = node.children[i]
if (child.type !== 'text') {
continue
}
// Look for 3 '=', followed by an optionally quoted title,
// followed by optional newlines of text
const match = child.value.match(/^\n*=== ("?)(.+)\1\n?((?:.|\n)*)/)
if (!match) {
continue
}
// Extract the tab title along with the remaining text
const [, , title, value] = match
// Rewrite the node's value to remove the tab syntax
child.value = value
// Extract sibling nodes that should be linked to this tab
const siblingsToNest = extractLinkedSiblings(parent, node, nodeIndex)
const children: any[] = [...node.children.slice(i), ...siblingsToNest]
const tabPanelElement: MdxJsxFlowElement = {
type: 'mdxJsxFlowElement',
name: 'TabPanel',
attributes: [
{
type: 'mdxJsxAttribute',
name: 'id',
value: title,
},
{
type: 'mdxJsxAttribute',
name: 'label',
value: title,
},
],
children,
}
let nodesAdded = 0
const previousNode = parent.children[nodeIndex - 1]
if (previousNode?.type === 'mdxJsxFlowElement' && previousNode.name === 'Tabs') {
// Add TabPanel to existing Tabs component
previousNode.children.push(tabPanelElement)
// Remove this node
parent.children.splice(nodeIndex, 1)
nodesAdded--
} else {
// Create new Tabs components and add TabPanel
const tabsElement: MdxJsxFlowElement = {
type: 'mdxJsxFlowElement',
name: 'Tabs',
attributes: [
{
type: 'mdxJsxAttribute',
name: 'scrollable',
},
{
type: 'mdxJsxAttribute',
name: 'size',
value: 'small',
},
{
type: 'mdxJsxAttribute',
name: 'type',
value: 'underlined',
},
],
children: [tabPanelElement],
}
// Overwrite this paragraph node with Tabs component
parent.children.splice(nodeIndex, 1, tabsElement)
}
// If this wasn't the first child of the paragraph, create
// a new paragraph before this with the previous text children
if (i > 0) {
const previousChildren = node.children.slice(0, i)
const paragraph: Paragraph = {
type: 'paragraph',
children: previousChildren,
}
parent.children.splice(nodeIndex, 0, paragraph)
nodesAdded++
}
// Return the correct index for the next visit, since
// we may have added or removed an element in the array
return nodeIndex + nodesAdded
}
})
}
}
/**
* Identifies sibling nodes that should be linked to this admonition
* based on their indent level (ie. 4 spaces).
*
* Iterates through proceeding siblings until one is found that is
* not indented relative to the original node.
*
* Splices the discovered siblings out of the original parent and returns them.
*/
function extractLinkedSiblings(parent: Parent, node: Node, index: number, indentAmount = 4) {
const { column } = node.position.start
let nextSibling: Content
let i = index
do {
nextSibling = parent.children[++i]
} while (nextSibling?.position && nextSibling.position.start.column === column + indentAmount)
return parent.children.splice(index + 1, i - index - 1)
}
export default remarkPyMdownTabs
+1
View File
@@ -97,6 +97,7 @@
"remark-admonitions": "^1.2.1",
"remark-gfm": "^3.0.1",
"remark-slug": "^7.0.1",
"remark-emoji": "^3.1.2",
"shiki": "^0.11.1",
"sse.js": "^0.6.1",
"ui": "*",
@@ -162,6 +162,8 @@ import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
export const dynamic = 'force-dynamic'
export async function GET(request) {
const requestUrl = new URL(request.url)
const code = requestUrl.searchParams.get('code')
@@ -190,6 +192,8 @@ import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
import type { Database } from '@/lib/database.types'
export const dynamic = 'force-dynamic'
export async function GET(request: NextRequest) {
const requestUrl = new URL(request.url)
const code = requestUrl.searchParams.get('code')
@@ -369,13 +373,9 @@ TypeScript types can be [generated with the Supabase CLI](/docs/reference/javasc
### Server-side
The combination of [Server Components](https://nextjs.org/docs/getting-started/react-essentials#server-components) and [Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions) can be used to trigger the authentication process from form submissions.
The combination of [Server Components](https://nextjs.org/docs/getting-started/react-essentials#server-components) and [Route Handlers](https://nextjs.org/docs/app/building-your-application/routing/route-handlers) can be used to trigger the authentication process from form submissions.
<Admonition type="note">
Next.js [Server Actions](https://nextjs.org/docs/app/building-your-application/data-fetching/server-actions) are currently in Alpha and may change. For now we recommend [triggering the authentication flow client-side](/docs/guides/auth/auth-helpers/nextjs#client-side) for production applications.
</Admonition>
#### Sign Up Route
<Tabs
scrollable
@@ -385,57 +385,248 @@ Next.js [Server Actions](https://nextjs.org/docs/app/building-your-application/d
>
<TabPanel id="js" label="JavaScript">
```jsx app/login.js
import { createServerActionClient } from '@supabase/auth-helpers-nextjs'
import { revalidatePath } from 'next/cache'
```jsx app/auth/sign-up.js
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
export default async function Login() {
const handleSignUp = async (formData) => {
'use server'
const email = formData.get('email')
const password = formData.get('password')
export const dynamic = 'force-dynamic'
const supabase = createServerActionClient({ cookies })
await supabase.auth.signUp({
email,
password,
options: {
emailRedirectTo: 'http://localhost:3000/auth/callback',
},
})
export async function POST(request) {
const requestUrl = new URL(request.url)
const formData = await request.formData()
const email = formData.get('email')
const password = formData.get('password')
const supabase = createRouteHandlerClient({ cookies })
revalidatePath('/')
}
await supabase.auth.signUp({
email,
password,
options: {
emailRedirectTo: `${requestUrl.origin}/auth/callback`,
},
})
const handleSignIn = async (formData) => {
'use server'
const email = formData.get('email')
const password = formData.get('password')
return NextResponse.redirect(requestUrl.origin, {
status: 301,
})
}
```
const supabase = createServerActionClient({ cookies })
await supabase.auth.signInWithPassword({
email,
password,
})
</TabPanel>
revalidatePath('/')
}
<TabPanel id="ts" label="TypeScript">
const handleSignOut = async () => {
'use server'
const supabase = createServerActionClient({ cookies })
await supabase.auth.signOut()
revalidatePath('/')
}
```tsx app/auth/sign-up.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
import type { Database } from '@/lib/database.types'
export const dynamic = 'force-dynamic'
export async function POST(request: Request) {
const requestUrl = new URL(request.url)
const formData = await request.formData()
const email = String(formData.get('email'))
const password = String(formData.get('password'))
const supabase = createRouteHandlerClient<Database>({ cookies })
await supabase.auth.signUp({
email,
password,
options: {
emailRedirectTo: `${requestUrl.origin}/auth/callback`,
},
})
return NextResponse.redirect(requestUrl.origin, {
status: 301,
})
}
```
<Admonition type="note">
TypeScript types can be [generated with the Supabase CLI](/docs/reference/javascript/typescript-support) and passed to `createRouteHandlerClient` to add type support to the Supabase client.
</Admonition>
</TabPanel>
</Tabs>
<Admonition type="note">
Returning a `301` status redirects from a POST to a GET route
</Admonition>
#### Login Route
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
>
<TabPanel id="js" label="JavaScript">
```jsx app/auth/login.js
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
export const dynamic = 'force-dynamic'
export async function POST(request) {
const requestUrl = new URL(request.url)
const formData = await request.formData()
const email = formData.get('email')
const password = formData.get('password')
const supabase = createRouteHandlerClient({ cookies })
await supabase.auth.signInWithPassword({
email,
password,
})
return NextResponse.redirect(requestUrl.origin, {
status: 301,
})
}
```
</TabPanel>
<TabPanel id="ts" label="TypeScript">
```tsx app/auth/login.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
import type { Database } from '@/lib/database.types'
export const dynamic = 'force-dynamic'
export async function POST(request: Request) {
const requestUrl = new URL(request.url)
const formData = await request.formData()
const email = String(formData.get('email'))
const password = String(formData.get('password'))
const supabase = createRouteHandlerClient<Database>({ cookies })
await supabase.auth.signInWithPassword({
email,
password,
})
return NextResponse.redirect(requestUrl.origin, {
status: 301,
})
}
```
<Admonition type="note">
TypeScript types can be [generated with the Supabase CLI](/docs/reference/javascript/typescript-support) and passed to `createRouteHandlerClient` to add type support to the Supabase client.
</Admonition>
</TabPanel>
</Tabs>
<Admonition type="note">
Returning a `301` status redirects from a POST to a GET route
</Admonition>
#### Logout Route
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
>
<TabPanel id="js" label="JavaScript">
```jsx app/auth/logout.js
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
export const dynamic = 'force-dynamic'
export async function POST(request) {
const requestUrl = new URL(request.url)
const supabase = createRouteHandlerClient({ cookies })
await supabase.auth.signOut()
return NextResponse.redirect(`${requestUrl.origin}/login`, {
status: 301,
})
}
```
</TabPanel>
<TabPanel id="ts" label="TypeScript">
```tsx app/auth/logout.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { cookies } from 'next/headers'
import { NextResponse } from 'next/server'
import type { Database } from '@/lib/database.types'
export const dynamic = 'force-dynamic'
export async function POST(request: Request) {
const requestUrl = new URL(request.url)
const supabase = createRouteHandlerClient<Database>({ cookies })
await supabase.auth.signOut()
return NextResponse.redirect(`${requestUrl.origin}/login`, {
status: 301,
})
}
```
<Admonition type="note">
TypeScript types can be [generated with the Supabase CLI](/docs/reference/javascript/typescript-support) and passed to `createRouteHandlerClient` to add type support to the Supabase client.
</Admonition>
</TabPanel>
</Tabs>
#### Login Page
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
>
<TabPanel id="js" label="JavaScript">
```jsx app/login.jsx
export default function Login() {
return (
<form action={handleSignUp}>
<form action="/auth/login" method="post">
<label htmlFor="email">Email</label>
<input name="email" />
<label htmlFor="password">Password</label>
<input type="password" name="password" />
<button>Sign up</button>
<button formAction={handleSignIn}>Sign in</button>
<button formAction={handleSignOut}>Sign out</button>
<button>Sign In</button>
<button formAction="/auth/sign-up">Sign Up</button>
<button formAction="/auth/logout">Sign Out</button>
</form>
)
}
@@ -445,70 +636,21 @@ export default async function Login() {
<TabPanel id="ts" label="TypeScript">
```tsx app/login.ts
import { createServerActionClient } from '@supabase/auth-helpers-nextjs'
import { revalidatePath } from 'next/cache'
import { cookies } from 'next/headers'
import type { Database } from '@/lib/database.types'
export default async function Login() {
const handleSignUp = async (formData: FormData) => {
'use server'
const email = String(formData.get('email'))
const password = String(formData.get('password'))
const supabase = createServerActionClient<Database>({ cookies })
await supabase.auth.signUp({
email,
password,
options: {
emailRedirectTo: 'http://localhost:3000/auth/callback',
},
})
revalidatePath('/')
}
const handleSignIn = async (formData: FormData) => {
'use server'
const email = String(formData.get('email'))
const password = String(formData.get('password'))
const supabase = createServerActionClient<Database>({ cookies })
await supabase.auth.signInWithPassword({
email,
password,
})
revalidatePath('/')
}
const handleSignOut = async () => {
'use server'
const supabase = createServerActionClient<Database>({ cookies })
await supabase.auth.signOut()
revalidatePath('/')
}
```tsx app/login.tsx
export default function Login() {
return (
<form action={handleSignUp}>
<form action="/auth/login" method="post">
<label htmlFor="email">Email</label>
<input name="email" />
<label htmlFor="password">Password</label>
<input type="password" name="password" />
<button>Sign up</button>
<button formAction={handleSignIn}>Sign in</button>
<button formAction={handleSignOut}>Sign out</button>
<button>Sign In</button>
<button formAction="/auth/sign-up">Sign Up</button>
</form>
)
}
```
<Admonition type="note">
TypeScript types can be [generated with the Supabase CLI](/docs/reference/javascript/typescript-support) and passed to `createServerActionClient` to add type support to the Supabase client.
</Admonition>
</TabPanel>
</Tabs>
@@ -551,7 +693,7 @@ This allows for the Supabase client to be easily instantiated in the correct con
import { createClientComponentClient } from '@supabase/auth-helpers-nextjs'
import { useEffect, useState } from 'react'
export default function Home() {
export default function Page() {
const [todos, setTodos] = useState()
const supabase = createClientComponentClient()
@@ -582,7 +724,7 @@ import type { Database } from '@/lib/database.types'
type Todo = Database['public']['Tables']['todos']['Row']
export default function Home() {
export default function Page() {
const [todos, setTodos] = useState<Todo[] | null>(null)
const supabase = createClientComponentClient<Database>()
@@ -653,7 +795,9 @@ In order to use Supabase in Server Components, you need to have implemented the
import { cookies } from 'next/headers'
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'
export default async function Home() {
export const dynamic = 'force-dynamic'
export default async function Page() {
const supabase = createServerComponentClient({ cookies })
const { data } = await supabase.from('todos').select()
return <pre>{JSON.stringify(data, null, 2)}</pre>
@@ -670,6 +814,8 @@ import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'
import type { Database } from '@/lib/database.types'
export const dynamic = 'force-dynamic'
export default async function ServerComponent() {
const supabase = createServerComponentClient<Database>({ cookies })
const { data } = await supabase.from('todos').select()
@@ -724,6 +870,8 @@ import { cookies } from 'next/headers'
import { createServerActionClient } from '@supabase/auth-helpers-nextjs'
import { revalidatePath } from 'next/cache'
export const dynamic = 'force-dynamic'
export default async function NewTodo() {
const addTodo = async (formData) => {
'use server'
@@ -753,6 +901,8 @@ import { revalidatePath } from 'next/cache'
import type { Database } from '@/lib/database.types'
export const dynamic = 'force-dynamic'
export default async function NewTodo() {
const addTodo = async (formData: FormData) => {
'use server'
@@ -801,11 +951,13 @@ TypeScript types can be [generated with the Supabase CLI](/docs/reference/javasc
>
<TabPanel id="js" label="JavaScript">
```jsx app/api/todos/route.jsx
```jsx app/api/todos/route.js
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { NextResponse } from 'next/server'
import { cookies } from 'next/headers'
export const dynamic = 'force-dynamic'
export async function POST(request) {
const { title } = await request.json()
const supabase = createRouteHandlerClient({ cookies })
@@ -818,13 +970,15 @@ export async function POST(request) {
<TabPanel id="ts" label="TypeScript">
```tsx app/api/todos/route.tsx
```tsx app/api/todos/route.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { NextResponse } from 'next/server'
import { cookies } from 'next/headers'
import type { Database } from '@/lib/database.types'
export const dynamic = 'force-dynamic'
export async function POST(request: Request) {
const { title } = await request.json()
const supabase = createRouteHandlerClient<Database>({ cookies })
@@ -846,6 +1000,258 @@ TypeScript types can be [generated with the Supabase CLI](/docs/reference/javasc
See [refreshing session example](/docs/guides/auth/auth-helpers/nextjs#managing-session-with-middleware) above.
### Edge Runtime
The Next.js Edge Runtime allows you to host Server Components and Route Handlers from Edge nodes, serving the routes as close as possible to your user's location.
A route can be configured to use the Edge Runtime by exporting a `runtime` variable set to `edge`. Additionally, the `cookies()` function must be called from the Edge route, before creating a Supabase Client.
#### Server Components
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
>
<TabPanel id="js" label="JavaScript">
```jsx app/page.jsx
import { cookies } from 'next/headers'
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'
export const runtime = 'edge'
export const dynamic = 'force-dynamic'
export default async function Page() {
const cookieStore = cookies()
const supabase = createServerComponentClient({
cookies: () => cookieStore,
})
const { data } = await supabase.from('todos').select()
return <pre>{JSON.stringify(data, null, 2)}</pre>
}
```
</TabPanel>
<TabPanel id="ts" label="TypeScript">
```tsx app/page.tsx
import { cookies } from 'next/headers'
import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'
import type { Database } from '@/lib/database.types'
export const runtime = 'edge'
export const dynamic = 'force-dynamic'
export default async function Page() {
const cookieStore = cookies()
const supabase = createServerComponentClient<Database>({
cookies: () => cookieStore,
})
const { data } = await supabase.from('todos').select()
return <pre>{JSON.stringify(data, null, 2)}</pre>
}
```
<Admonition type="note">
TypeScript types can be [generated with the Supabase CLI](/docs/reference/javascript/typescript-support) and passed to `createServerComponentClient` to add type support to the Supabase client.
</Admonition>
</TabPanel>
</Tabs>
#### Route Handlers
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
>
<TabPanel id="js" label="JavaScript">
```jsx app/api/todos/route.js
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { NextResponse } from 'next/server'
import { cookies } from 'next/headers'
export const runtime = 'edge'
export const dynamic = 'force-dynamic'
export async function POST(request) {
const { title } = await request.json()
const cookieStore = cookies()
const supabase = createRouteHandlerClient({
cookies: () => cookieStore,
})
const { data } = await supabase.from('todos').insert({ title }).select()
return NextResponse.json(data)
}
```
</TabPanel>
<TabPanel id="ts" label="TypeScript">
```tsx app/api/todos/route.ts
import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
import { NextResponse } from 'next/server'
import { cookies } from 'next/headers'
import type { Database } from '@/lib/database.types'
export const runtime = 'edge'
export const dynamic = 'force-dynamic'
export async function POST(request: Request) {
const { title } = await request.json()
const cookieStore = cookies()
const supabase = createRouteHandlerClient<Database>({
cookies: () => cookieStore,
})
const { data } = await supabase.from('todos').insert({ title }).select()
return NextResponse.json(data)
}
```
<Admonition type="note">
TypeScript types can be [generated with the Supabase CLI](/docs/reference/javascript/typescript-support) and passed to `createRouteHandlerClient` to add type support to the Supabase client.
</Admonition>
</TabPanel>
</Tabs>
### Static Routes
Server Components and Route Handlers are static by default - data is fetched once at build time and the value is cached. Since the request to Supabase now happens at build time, there is no user, session or cookie to pass along with the request to Supabase. Therefore, the `createClient` function from `supabase-js` can be used to fetch data for static routes.
#### Server Components
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
>
<TabPanel id="js" label="JavaScript">
```jsx app/page.jsx
import { createClient } from '@supabase/supabase-js'
export default async function Page() {
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
)
const { data } = await supabase.from('todos').select()
return <pre>{JSON.stringify(data, null, 2)}</pre>
}
```
</TabPanel>
<TabPanel id="ts" label="TypeScript">
```tsx app/page.tsx
import { createClient } from '@supabase/supabase-js'
import type { Database } from '@/lib/database.types'
export default async function Page() {
const supabase = createClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
const { data } = await supabase.from('todos').select()
return <pre>{JSON.stringify(data, null, 2)}</pre>
}
```
<Admonition type="note">
TypeScript types can be [generated with the Supabase CLI](/docs/reference/javascript/typescript-support) and passed to `createClient` to add type support to the Supabase client.
</Admonition>
</TabPanel>
</Tabs>
#### Route Handlers
<Tabs
scrollable
size="small"
type="underlined"
defaultActiveId="js"
>
<TabPanel id="js" label="JavaScript">
```jsx app/api/todos/route.js
import { createClient } from '@supabase/supabase-js'
import { NextResponse } from 'next/server'
export async function POST(request) {
const { title } = await request.json()
const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
)
const { data } = await supabase.from('todos').insert({ title }).select()
return NextResponse.json(data)
}
```
</TabPanel>
<TabPanel id="ts" label="TypeScript">
```tsx app/api/todos/route.ts
import { createClient } from '@supabase/supabase-js'
import { NextResponse } from 'next/server'
import type { Database } from '@/lib/database.types'
export async function POST(request: Request) {
const { title } = await request.json()
const supabase = createClient<Database>(
process.env.NEXT_PUBLIC_SUPABASE_URL!,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
)
const { data } = await supabase.from('todos').insert({ title }).select()
return NextResponse.json(data)
}
```
<Admonition type="note">
TypeScript types can be [generated with the Supabase CLI](/docs/reference/javascript/typescript-support) and passed to `createClient` to add type support to the Supabase client.
</Admonition>
</TabPanel>
</Tabs>
## More examples
- [Build a Twitter Clone with the Next.js App Router and Supabase - free egghead course](https://egghead.io/courses/build-a-twitter-clone-with-the-next-js-app-router-and-supabase-19bebadb)
@@ -329,7 +329,7 @@ In some cases, you may wish to use WhatsApp as a delivery channel instead. Here
- You wish for a secure channel
- Your users mostly use WhatsApp as a messaging platform
To make use of WhatsApp OTP, please complete the following steps:
WhatsApp OTPs can be used with Twilio Verify without additional configuration. To make use of WhatsApp OTP with Twilio Programmable Messaging, please complete the following steps:
- Go through the [Twilio self sign up guide for WhatsApp](https://www.twilio.com/docs/whatsapp/self-sign-up)
- Submit a template via the [Twilio Guide For Submitting WhatsApp templates](https://www.twilio.com/docs/whatsapp/tutorial/send-whatsapp-notification-messages-templates#creating-message-templates-and-submitting-them-for-approval)
@@ -11,6 +11,7 @@ import Layout from '~/layouts/DefaultGuideLayout'
import { UrlTransformFunction, linkTransform } from '~/lib/mdx/plugins/rehypeLinkTransform'
import remarkMkDocsAdmonition from '~/lib/mdx/plugins/remarkAdmonition'
import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle'
import remarkPyMdownTabs from '~/lib/mdx/plugins/remarkTabs'
// We fetch these docs at build time from an external repo
const org = 'supabase'
@@ -134,6 +135,7 @@ export const getStaticProps: GetStaticProps<ActionDocsProps> = async ({ params }
remarkPlugins: [
remarkGfm,
remarkMkDocsAdmonition,
remarkPyMdownTabs,
[removeTitle, meta.title],
[remarkCodeHike, codeHikeOptions],
],
@@ -0,0 +1,181 @@
import { CodeHikeConfig, remarkCodeHike } from '@code-hike/mdx'
import { GetStaticPaths, GetStaticProps } from 'next'
import { MDXRemote, MDXRemoteSerializeResult } from 'next-mdx-remote'
import { serialize } from 'next-mdx-remote/serialize'
import { relative } from 'path'
import rehypeSlug from 'rehype-slug'
import remarkGfm from 'remark-gfm'
import emoji from 'remark-emoji'
import codeHikeTheme from 'config/code-hike.theme.json' assert { type: 'json' }
import components from '~/components'
import Layout from '~/layouts/DefaultGuideLayout'
import { UrlTransformFunction, linkTransform } from '~/lib/mdx/plugins/rehypeLinkTransform'
import remarkMkDocsAdmonition from '~/lib/mdx/plugins/remarkAdmonition'
import { removeTitle } from '~/lib/mdx/plugins/remarkRemoveTitle'
import remarkPyMdownTabs from '~/lib/mdx/plugins/remarkTabs'
// We fetch these docs at build time from an external repo
const org = 'supabase'
const repo = 'wrappers'
const branch = 'main'
const docsDir = 'docs'
const externalSite = 'https://supabase.github.io/wrappers'
// Each external docs page is mapped to a local page
const pageMap = [
{
slug: 'airtable',
meta: {
title: 'Airtable',
},
remoteFile: 'airtable.md',
},
{
slug: 's3',
meta: {
title: 'AWS S3',
},
remoteFile: 's3.md',
},
{
slug: 'bigquery',
meta: {
title: 'BigQuery',
},
remoteFile: 'bigquery.md',
},
{
slug: 'clickhouse',
meta: {
title: 'ClickHouse',
},
remoteFile: 'clickhouse.md',
},
{
slug: 'firebase',
meta: {
title: 'Firebase',
},
remoteFile: 'firebase.md',
},
{
slug: 'logflare',
meta: {
title: 'Logflare',
},
remoteFile: 'logflare.md',
},
{
slug: 'stripe',
meta: {
title: 'Stripe',
},
remoteFile: 'stripe.md',
},
]
interface WrappersDocsProps {
source: MDXRemoteSerializeResult
meta: {
title: string
description?: string
}
}
export default function WrappersDocs({ source, meta }: WrappersDocsProps) {
return (
<Layout meta={meta}>
<MDXRemote {...source} components={components} />
</Layout>
)
}
/**
* Fetch markdown from external repo and transform links
*/
export const getStaticProps: GetStaticProps<WrappersDocsProps> = async ({ params }) => {
const page = pageMap.find(({ slug }) => slug === params.slug)
if (!page) {
throw new Error(`No page mapping found for slug '${params.slug}'`)
}
const { remoteFile, meta } = page
const response = await fetch(
`https://raw.githubusercontent.com/${org}/${repo}/${branch}/${docsDir}/${remoteFile}`
)
const source = await response.text()
const urlTransform: UrlTransformFunction = (url) => {
try {
const externalSiteUrl = new URL(externalSite)
const placeholderHostname = 'placeholder'
const { hostname, pathname, hash } = new URL(url, `http://${placeholderHostname}`)
// Don't modify a url with a FQDN or a url that's only a hash
if (hostname !== placeholderHostname || pathname === '/') {
return url
}
const relativePage = (
pathname.endsWith('.md')
? pathname.replace(/\.md$/, '')
: relative(externalSiteUrl.pathname, pathname)
).replace(/^\//, '')
const page = pageMap.find(({ remoteFile }) => `${relativePage}.md` === remoteFile)
// If we have a mapping for this page, use the mapped path
if (page) {
return page.slug + hash
}
// If we don't have this page in our docs, link to original docs
return `${externalSite}/${relativePage}${hash}`
} catch (err) {
console.error('Error transforming markdown URL', err)
return url
}
}
const codeHikeOptions: CodeHikeConfig = {
theme: codeHikeTheme,
lineNumbers: true,
showCopyButton: true,
skipLanguages: [],
autoImport: false,
}
const mdxSource = await serialize(source, {
scope: {
chCodeConfig: codeHikeOptions,
},
mdxOptions: {
remarkPlugins: [
remarkGfm,
remarkMkDocsAdmonition,
emoji,
remarkPyMdownTabs,
[removeTitle, meta.title],
[remarkCodeHike, codeHikeOptions],
],
rehypePlugins: [[linkTransform, urlTransform], rehypeSlug],
},
})
return { props: { source: mdxSource, meta } }
}
export const getStaticPaths: GetStaticPaths = async () => {
return {
paths: pageMap.map(({ slug }) => ({
params: {
slug,
},
})),
fallback: false,
}
}
@@ -2,7 +2,7 @@ import Layout from '~/layouts/DefaultGuideLayout'
export const meta = {
id: 'wrappers',
title: 'wrappers: 3rd Party Integrations',
title: 'Wrappers: 3rd Party Integrations',
description: '3rd party integrations for PostgreSQL ',
}
@@ -60,12 +60,13 @@ A web interface for connecting to external data is coming to Supabase Studio in
## Integrations
- [Firebase](https://supabase.github.io/wrappers/firebase/)
- [Stripe](https://supabase.github.io/wrappers/stripe/)
- [BigQuery](https://supabase.github.io/wrappers/bigquery/)
- [AWS S3](https://supabase.github.io/wrappers/s3/)
- Airtable - Coming Soon
- Clickhouse - Coming Soon
- [Airtable](/docs/guides/database/extensions/wrappers/airtable)
- [AWS S3](/docs/guides/database/extensions/wrappers/s3)
- [BigQuery](/docs/guides/database/extensions/wrappers/bigquery)
- [ClickHouse](/docs/guides/database/extensions/wrappers/clickhouse)
- [Firebase](/docs/guides/database/extensions/wrappers/firebase)
- [Logflare](/docs/guides/database/extensions/wrappers/logflare)
- [Stripe](/docs/guides/database/extensions/wrappers/stripe)
## Resources
@@ -62,8 +62,6 @@ export const meta = {
```kotlin
implementation "io.github.jan-tennert.supabase:postgrest-kt:$supabase_version"
implementation "io.ktor:ktor-client-android:$ktor_version"
implementation "io.ktor:ktor-client-core:$ktor_version"
implementation "io.ktor:ktor-utils:$ktor_version"
```
</StepHikeCompact.Code>
@@ -102,10 +100,8 @@ export const meta = {
supabaseUrl = "https://xyzcompany.supabase.co",
supabaseKey = "public-anon-key"
) {
install(GoTrue)
install(Postgrest)
install(Storage)
}
install(Postgrest)
}
```
</StepHikeCompact.Code>
+5 -5
View File
@@ -25,7 +25,7 @@ export const meta = {
## Products
</div>
<div className="grid grid-cols-12 gap-6 not-prose [&_svg]:text-brand-1100 [&_svg]dark:text-brand-900">
<div className="grid grid-cols-12 gap-6 not-prose [&_svg]:text-brand-600 [&_svg]dark:text-brand">
{products.map((product) => {
return (
<Link href={product.href} key={product.title} passHref>
@@ -44,7 +44,7 @@ export const meta = {
<div className="col-span-4 flex flex-col gap-1 [&_h2]:m-0 [&_h3]:m-0">
<div className="md:max-w-xs 2xl:max-w-none">
<div className="flex items-center gap-3 mb-3 text-brand-1100 dark:text-brand-900">
<div className="flex items-center gap-3 mb-3 text-brand-600 dark:text-brand">
{/* <IconBackground>
<HomeMenuIconPicker icon="reference-cli" width={18} height={18} />
</IconBackground> */}
@@ -89,7 +89,7 @@ export const meta = {
<TextLink
label="Explore more resources"
url="/guides/resources"
className="no-underline text-brand-900 text-sm"
className="no-underline text-brand text-sm"
/>
</div>
@@ -148,7 +148,7 @@ export const meta = {
<div className="col-span-4 flex flex-col gap-1 [&_h2]:m-0 [&_h3]:m-0">
<div className="md:max-w-xs 2xl:max-w-none">
<div className="flex items-center gap-3 mb-3 text-brand-1100 dark:text-brand-900">
<div className="flex items-center gap-3 mb-3 text-brand-600 dark:text-brand">
<IconBackground>
<HomeMenuIconPicker icon="self-hosting" width={18} height={18} />
</IconBackground>
@@ -160,7 +160,7 @@ export const meta = {
<TextLink
label="More on Self-Hosting"
url="/guides/self-hosting"
className="no-underline text-brand-900 text-sm"
className="no-underline text-brand text-sm"
/>
</div>
+1 -1
View File
@@ -169,7 +169,7 @@ pre[class*='language-'] {
// ToC styles
.toc__menu-item--active {
color: var(--colors-brand9) !important;
color: hsl(var(--brand-default)) !important;
}
.video-container {
@@ -0,0 +1,105 @@
---
title: Supabase Beta July 2023
description: Launch Week 8 is coming - but we still shipped some goodies during July
author: ant_wilson
image: 2023-08-02-july-2023-beta-update/july-2023-beta-update.png
thumb: 2023-08-02-july-2023-beta-update/july-2023-beta-update.png
tags:
- release-notes
date: '2023-08-02'
toc_depth: 3
---
Next Monday is Launch Week 🎱, where we’ll be announcing a tonne of surprises. In the meantime, here’s a summary of everything we shipped in July. Read on!
## Supabase Launch Week 8
![Supabase Launch Week 8](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/launch-week.png)
Launch Week 8 starts next week. We’ll be announcing one new major feature every day for an entire week (with a few bonus surprises along the way). Get your ticket and tune in on Monday the 7th.
[Get your ticket](https://supabase.com/launch-week)
## New Android Kotlin Library
![New Android Kotlin Library](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/android-kotlin.png?t=2023-08-02T11%3A05%3A46.805Z)
Are you a mobile dev? We now have client libraries for Android. This is thanks to one of our community members - [@TheRealJanGER](https://twitter.com/TheRealJanGER). Try it out, and if you want to help us maintain the library let us know.
[Quickstart](https://supabase.com/docs/guides/getting-started/quickstarts/kotlin)
[Tutorial](https://supabase.com/docs/guides/getting-started/tutorials/with-kotlin)
## pgvector 0.4.0 performance
![pgvector 0.4.0 performance](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/pgvector.png)
There's been a lot of talk about pgvector performance, so we pushed it to the limits to figure out its strengths and limitations. The good news is that work has already [started](https://github.com/pgvector/pgvector/tree/hnsw) on HNSW, and isn’t far away.
[Read the benchmark](https://supabase.com/blog/pgvector-performance)
## Quick product announcements
- [Auth] There is a new OAuth provider in time: Login with Figma. [Docs](https://supabase.com/docs/guides/auth/social-login/auth-figma)
- [Auth] You can now use Resend as a custom SMTP provider. [Docs](https://resend.com/docs/send-with-supabase-smtp)
- [Postgres Tooling] pgsodium 3.1.8 released. [PR](https://github.com/michelp/pgsodium/releases/tag/v3.1.8)
- [Postgres Tooling] PostgREST 11.1 is now live. [Blog post](https://supabase.com/blog/postgrest-11-1-release)
## Egghead course: Twitter Clone with the Next.js App Router
![Egghead course: Twitter Clone with the Next.js App Router](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/egghead-course.png?t=2023-08-02T10%3A55%3A17.908Z)
Should we rebrand to X Clone? Next.js App router is ushering in the next era of web development. What a best way to learn to navigate it than by building a full-stack app?
[Course](https://egghead.io/courses/build-a-twitter-clone-with-the-next-js-app-router-and-supabase-19bebadb)
## Twitter Space: Launch Week 8 - Kickoff 🏈
![Twitter Space](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/twitter-space.png?t=2023-08-02T11%3A05%3A03.838Z)
After Monday's announcement, we are kicking off LW8 with a very cool Twitter Space, featuring the DevRel team and guests. Bring your questions!
10:00 AM PT | 1:00 PM ET | 06:00 PM UK
[Set reminder](https://twitter.com/i/spaces/1DXGyvjkeEeJM)
## Made with Supabase
![Made with Supabase: Snowchat](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/snowchat.png)
[snowChat](https://snowchat.streamlit.app/) | An intuitive and user-friendly application that allows you to interact with your Snowflake data using natural language queries. Built by [Kaarthik Andavar](https://twitter.com/kaarthikcodes) using Python, Streamlit, Open AI, and Supabase Vector.
## Extended Community Highlights
![Community Highlights](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/community-highlights.png)
- Build a Simple Dropbox clone using Deno, DenoKV, Fresh and Supabase. [Video Tutorial](https://www.youtube.com/watch?v=_WerF8YMqks)
- Safeguarding Data Integrity with pg_safeupdate in PostgreSQL and Supabase. [Blog post](https://www.notion.so/809925346af243b3a4ede8774e71472c?pvs=21)
- Supabase for C#: Streamlining Backend Development with Database Magic. [Blog post](https://themurph.hashnode.dev/supabase-csharp)
- Building an MVP app using Supabase. [Blog post](https://www.antstack.com/blog/building-an-mvp-app-using-supabase/)
- Fortify Your Application With Supabase: Exploring Fine-Grained Control with Row-Level Security and OAuth Sign-in. [Article](https://techconative.com/blog/supabase-rls-security-oauth-authentication/)
- Using Supabase authentication in NestJs. [Tutorial](https://blog.iamstarcode.com/using-supabase-authentication-in-nestjs)
- React Native file upload with Supabase Storage. [Tutorial](https://supabase.com/blog/react-native-storage) | [Video](https://www.youtube.com/watch?v=am6w5zEDk_g)
- Safeguarding Data Integrity with pg_safeupdate in PostgreSQL and Supabase. [Blog Post](https://blog.mansueli.com/safeguarding-data-integrity-with-pg-safeupdate-in-postgresql-and-supabase)
- Supabase almost SHUT ME DOWN. [Video](https://www.youtube.com/watch?v=2WHTZa4ENfc)
## Supabase in Times Square
![Supabase in Times Square](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/times-sq.png?t=2023-08-02T11%3A04%3A14.458Z)
The Redpoint team put together InfraRed 100, a report that recognizes 100 transformative companies in cloud infrastructure. We are honoured to be included with so many amazing companies we admire 🙇🏻‍♂️. They even featured us on a billboard in Times Square to celebrate.
[Read the full report](https://www.redpoint.com/infrared/100/)
## We’re Hiring
- [Support Engineer (APAC)](https://boards.greenhouse.io/supabase/jobs/4934378004)
- [FullStack Engineer Billing](https://www.notion.so/Beta-Update-July-Monday-31st-10386eba40934ea597ee5e5b1b81574e?pvs=21)
## ⚠️ Baking hot meme zone ⚠️
If you made it this far in the email you deserve a devilish treat.
NPCs represent…
![July's favorite meme](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/supabase-meme.png)
@@ -19,9 +19,9 @@ function AuthWidgetSection() {
const { basePath } = useRouter()
const [radius, setRadius] = useState('4px')
const [brandColor, setBrandColor] = useState({
brand: 'var(--colors-brand9)',
brandAccent: 'var(--colors-brand11)',
brandAccent2: 'var(--colors-brand3)',
brand: 'hsl(var(--brand-default))',
brandAccent: 'hsl(var(--brand-500))',
brandAccent2: 'hsl(var(--brand-200))',
})
const [layout, setLayout] = useState('horizontal')
@@ -140,15 +140,15 @@ function AuthWidgetSection() {
<button
onClick={() =>
setBrandColor({
brand: 'var(--colors-brand9)',
brandAccent: 'var(--colors-brand11)',
brandAccent2: 'var(--colors-brand3)',
brand: 'hsl(var(--brand-default))',
brandAccent: 'hsl(var(--brand-500))',
brandAccent2: 'hsl(var(--brand-200))',
})
}
className={[
'bg-brand-300 border-brand-900 h-10 w-10 rounded-full border-2 transition hover:scale-105',
brandColor.brand === 'var(--colors-brand9)'
? ' !bg-brand-900 ring-scale-400 border-scale-800 ring-2 drop-shadow-lg dark:ring-white'
'bg-brand-300 border-brand h-10 w-10 rounded-full border-2 transition hover:scale-105',
brandColor.brand === 'hsl(var(--brand-default))'
? ' !bg-brand ring-scale-400 border-scale-800 ring-2 drop-shadow-lg dark:ring-white'
: '',
].join(' ')}
></button>
+2 -2
View File
@@ -13,8 +13,8 @@ const Button = (props: Props) => {
const colorClass =
type === 'primary'
? 'px-3 py-2 shadow-sm border border-transparent text-white bg-brand-700 hover:bg-brand-800 focus:ring-2 focus:ring-offset-2 focus:ring-brand-500'
: 'text-brand-700 bg-none'
? 'px-3 py-2 shadow-sm border border-transparent text-white bg-brand-400 hover:bg-brand-300 focus:ring-2 focus:ring-offset-2 focus:ring-brand-300'
: 'text-brand-400 bg-none'
const textClass = type === 'primary' ? 'font-medium left-3 group-hover:left-0' : 'font-normal'
+1 -1
View File
@@ -7,7 +7,7 @@ import * as data from '~/data/blog/PostgresFTSComparison'
import remarkGfm from 'remark-gfm'
const barColors = {
pg: 'var(--colors-brand11)',
pg: 'hsl(var(--brand-600))',
meilisearch: 'var(--colors-blue11)',
typesense: 'var(--colors-violet11)',
'sqlite-disk': 'var(--colors-orange11)',
+1 -1
View File
@@ -119,7 +119,7 @@ function CodeBlock(props: CodeBlockProps) {
type="text"
icon={
copied ? (
<span className="text-brand-900">
<span className="text-brand">
<IconCheck strokeWidth={3} />
</span>
) : (
+1 -1
View File
@@ -41,7 +41,7 @@ const Hero = () => {
{showAnnouncement && (
<Link href="/launch-week">
<a className="group w-auto rounded-full p-1 mb-6 mt-8 md:mb-10 bg-gradient-to-b from-[#1b1f2124] to-[#02040550] hover:from-[#ffffff15] hover:to-[#ffffff05] transition-all backdrop-blur-lg border flex items-center justify-between gap-2 md:gap-4 text-scale-1100 hover:text-scale-1200 text-sm">
<div className="text-scale-200 rounded-full bg-brand-900 px-3 py-1 flex items-center justify-center">
<div className="text-scale-200 rounded-full bg-brand px-3 py-1 flex items-center justify-center">
Get your ticket
</div>
<span>Launch Week 8 - August 7-11</span>
@@ -34,9 +34,9 @@ const InteractiveShimmerCard = ({
const isActive = x > -3 && x < width + 3 && y > -3 && y < height + 3
const activeGlow =
hasActiveOnHover && isActive
? `radial-gradient(65rem circle at ${x}px ${y}px, var(--colors-brand9), transparent), `
? `radial-gradient(65rem circle at ${x}px ${y}px, hsl(var(--brand-default)), transparent), `
: ''
outerElement.style.background = isActive ? `var(--colors-brand9)` : `var(--colors-scale3)`
outerElement.style.background = isActive ? `hsl(var(--brand-default))` : `var(--colors-scale3)`
outerElement.style.backgroundImage = `
${activeGlow}radial-gradient(30rem circle at ${x}px ${y}px, ${
shimmerFromColor ?? 'var(--colors-scale8)'
@@ -44,7 +44,7 @@ export default function LaunchHero() {
<h3 className="text-scale-1200 text-lg">Submission</h3>
<p className="text-scale-1100 text-sm">
Submit your project through{' '}
<a className="text-brand-900" href="https://madewithsupabase.com">
<a className="text-brand" href="https://madewithsupabase.com">
madewithsupabase.com
</a>
.
@@ -9,7 +9,7 @@ const ArticleButtonListItem = (props: Article) => {
<div className="flex flex-row">
<div>
<div className="flex flex-col">
<span className="text-scale-1200 group-hover:text-brand-900 text-left text-base transition">
<span className="text-scale-1200 group-hover:text-brand text-left text-base transition">
{props.title}
</span>
<p className="text-scale-1100 text-left text-sm transition">{props.description}</p>
@@ -6,7 +6,7 @@ const ProductButton = (props: Article) => {
<div className="mr-2 mb-2 inline-block">
<button
className="
text-brand-1200
text-brand-600
hover:bg-scale-300 border-scale-500 flex items-start gap-3 rounded-md border bg-transparent p-3
px-6 transition
dark:drop-shadow-sm"
@@ -8,7 +8,7 @@ export const ProductButtonListItem = (props: Article) => {
<div className="inline-block">
<button
className="
text-brand-1200
text-brand-600
group
flex items-start gap-3 bg-transparent
transition
@@ -18,7 +18,7 @@ export const ProductButtonListItem = (props: Article) => {
<SparklesIcon strokeWidth={1} />
</div>
<div className="flex flex-col items-start gap-0">
<span className="group-hover:text-brand-900 text-sm">{props.title}</span>
<span className="group-hover:text-brand text-sm">{props.title}</span>
<p className="text-scale-1100 text-left text-sm">{props.description}</p>
</div>
</button>
@@ -25,7 +25,7 @@ export const LaunchSection = (props: WeekDayProps) => {
<div
className={[
'absolute mt-[4px] -ml-[21px] h-3 w-3 rounded-full border md:-ml-[37px] lg:-ml-[37.5px]',
props.shipped ? 'border-brand-900 bg-brand-400' : 'border-purple-900 bg-purple-300',
props.shipped ? 'border-brand bg-brand-400' : 'border-purple-900 bg-purple-300',
].join(' ')}
></div>
{/* END timeline dot */}
@@ -63,7 +63,7 @@ export const LaunchSection = (props: WeekDayProps) => {
nextDayNotShipped
? 'launch-week-timeline-border--approaching'
: props.shipped
? 'border-brand-900'
? 'border-brand'
: 'border-purple-700',
className,
].join(' ')}
@@ -152,7 +152,7 @@ export const LaunchSection = (props: WeekDayProps) => {
md:pl-8
lg:pl-8
`,
props.shipped ? 'border-brand-900' : 'border-purple-700',
props.shipped ? 'border-brand' : 'border-purple-700',
props.shippingHasStarted && 'lg:col-span-6',
!lastIndex && 'pb-8 lg:pb-16',
].join(' ')}
@@ -130,8 +130,8 @@
height: 56px;
margin-top: var(--space-4x);
border-radius: var(--space-2x);
border: 1px solid var(--brand);
background: var(--brand);
border: 1px solid hsl(var(--brand-default));
background: hsl(var(--brand-default));
cursor: pointer;
font-family: inherit;
font-size: var(--text-md);
@@ -170,7 +170,7 @@
.submit.default:hover,
.submit.default:focus {
background: black;
color: var(--brand);
color: hsl(var(--brand-default));
}
.submit.default.generate-with-github:hover path,
@@ -0,0 +1,56 @@
import React from 'react'
import SectionContainer from '../../Layouts/SectionContainer'
import { SmallCard } from '../8/Releases/components'
import Link from 'next/link'
import Image from 'next/image'
const LW8CalloutsSection = () => {
return (
<SectionContainer className="!py-0 w-full !px-0 !max-w-none">
<div className="grid grid-cols-1 lg:grid-cols-2 gap-4 scroll-mt-[105px]" id="hackathon">
<SmallCard className="hover:from-background-surface-300 hover:to-background-surface-300">
<Link href="https://twitter.com/i/spaces/1DXGyvjkeEeJM">
<a target="_blank" className="flex flex-row justify-between items-center w-full h-full">
<div className="relative flex-shrink flex items-center p-2 w-2/3 lg:w-1/2 md:w-auto">
<div className="flex flex-col gap-1 sm:pl-4">
<span className="text-white">Join us daily at Twitter Spaces </span>
<span className="">Next up: Monday – Opening Day</span>
</div>
</div>
<div className="relative flex !aspect-video h-[80px] md:h-[100px] gap-2 z-10 rounded overflow-hidden">
<Image
src="/images/launchweek/8/twitter-spaces-thumb.svg"
alt="twitter spaces thumbnail"
layout="fill"
objectFit="cover"
/>
</div>
</a>
</Link>
</SmallCard>
<SmallCard className="hover:from-background-surface-300 hover:to-background-surface-300">
<Link href="/blog/supabase-lw8-hackathon">
<a target="_blank" className="flex flex-row justify-between items-center w-full h-full">
<div className="relative h-full flex-shrink flex flex-col md:flex-row md:items-center p-2 w-2/3 lg:w-1/2 md:w-auto gap-1 md:gap-4">
<div className="flex flex-col gap-1 sm:pl-4">
<span className="text-white">LW8 Hackathon Aug 4 – Aug 13</span>
<span className="">Read more about rules and prizes on the blog</span>
</div>
</div>
<div className="relative flex !aspect-video h-[80px] md:h-[100px] gap-2 z-10 rounded overflow-hidden">
<Image
src="/images/launchweek/8/lw8-hackathon-thumb.svg"
alt="hackathon thumbnail"
layout="fill"
objectFit="cover"
/>
</div>
</a>
</Link>
</SmallCard>
</div>
</SectionContainer>
)
}
export default LW8CalloutsSection
@@ -0,0 +1,105 @@
import Link from 'next/link'
import React, { useEffect, useState } from 'react'
import { Badge } from 'ui'
import useConfData from '../hooks/use-conf-data'
export interface Meetup {
id?: any
title: string
isLive: boolean
link: string
display_info: string
start_at: string
}
const LW8Meetups = ({ meetups }: { meetups?: Meetup[] }) => {
const { supabase } = useConfData()
const [meets, setMeets] = useState<Meetup[]>(meetups ?? [])
const [realtimeChannel, setRealtimeChannel] = useState<ReturnType<
(typeof supabase)['channel']
> | null>(null)
useEffect(() => {
// Listen to realtime changes
if (supabase && !realtimeChannel) {
const channel = supabase
.channel('changes')
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'lw8_meetups',
},
async () => {
const { data: newMeets } = await supabase.from('lw8_meetups').select('*')
setMeets(newMeets)
}
)
.subscribe()
setRealtimeChannel(channel)
}
return () => {
// Cleanup realtime subscription on unmount
realtimeChannel?.unsubscribe()
}
}, [])
return (
<div className="max-w-6xl mx-auto grid grid-cols-1 xl:grid-cols-12 gap-8 xl:gap-8">
<div className="col-span-1 xl:col-span-4 flex flex-col justify-center max-w-lg">
<h2 className="text-2xl sm:text-3xl xl:text-4xl tracking-[-.5px]">Join the community</h2>
<p className="text-scale-1000 text-xs sm:text-sm xl:text-base py-3 xl:max-w-md">
Celebrate LW8 at our first-ever live community meetups across various locations. Join the
fun, grab some swag, and meet the Supabase community.
</p>
</div>
<div className="col-span-1 xl:col-span-7 xl:col-start-6 w-full max-w-4xl flex flex-col justify-between items-stretch">
{meets &&
meets
?.sort((a, b) => (new Date(a.start_at) > new Date(b.start_at) ? 1 : -1))
.map(({ display_info, link, isLive, title }: Meetup) => (
<Link href={link ?? '#'}>
<a
target="_blank"
className={[
'w-full group py-0 flex items-center gap-2 md:gap-4 text-lg sm:text-2xl xl:text-4xl border-b border-[#111718]',
'hover:text-scale-1200',
isLive ? 'text-scale-1100' : 'text-[#56646B]',
!link && 'pointer-events-none',
].join(' ')}
>
<div className="flex items-center gap-2 md:gap-4 py-2 md:py-0">
<span>{title}</span>
{isLive && <Badge>Live now</Badge>}
<span className="hidden md:inline opacity-0 -translate-x-2 transition-all md:group-hover:opacity-100 group-hover:translate-x-0">
<svg
width="47"
height="47"
viewBox="0 0 47 47"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M33.0387 16.2422L40.6691 23.8727M40.6691 23.8727L33.0387 31.5031M40.6691 23.8727L6.33203 23.8727"
stroke="currentColor"
strokeWidth="2"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
</span>
</div>
{display_info && (
<span className="text-sm text-right flex-1">{display_info}</span>
)}
</a>
</Link>
))}
</div>
</div>
)
}
export default LW8Meetups
@@ -0,0 +1,337 @@
import { Badge } from 'ui'
import Link from 'next/link'
import CountdownComponent from '../../Countdown'
export const PencilSvg = () => (
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M3.21792 11.2469L11.8015 2.66333L14.0953 4.95709L5.51167 13.5407M3.21792 11.2469L2.34219 14.4164L5.51167 13.5407M3.21792 11.2469L5.51167 13.5407"
stroke="#8F8F8F"
strokeMiterlimit="10"
strokeLinejoin="bevel"
/>
</svg>
)
export const DocsSvg = () => (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M4.96289 9.48618H10.9629M4.96289 7.48618H10.9629M4.96289 11.4862H8.96289M3 2.00034V13.9998H12.9996V5.60113L9.38156 2.00034H3ZM12.9644 5.58432L9.38004 2L9.38004 5.58432L12.9644 5.58432Z"
stroke="#8F8F8F"
strokeMiterlimit="10"
strokeLinejoin="bevel"
/>
</svg>
)
export const PlaySvg = () => (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M13.4287 8L8.74762 10.7026L4.06653 13.4053L4.06653 8L4.06653 2.59474L8.74762 5.29737L13.4287 8Z"
stroke="#8F8F8F"
strokeMiterlimit="10"
strokeLinejoin="bevel"
/>
</svg>
)
export const GithubSvg = () => (
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8.2125 1.75781C4.6765 1.75781 1.8125 4.62181 1.8125 8.15781C1.8125 10.9898 3.6445 13.3818 6.1885 14.2298C6.5085 14.2858 6.6285 14.0938 6.6285 13.9258C6.6285 13.7738 6.6205 13.2698 6.6205 12.7338C5.0125 13.0298 4.5965 12.3418 4.4685 11.9818C4.3965 11.7978 4.0845 11.2298 3.8125 11.0778C3.5885 10.9578 3.2685 10.6618 3.8045 10.6538C4.3085 10.6458 4.6685 11.1178 4.7885 11.3098C5.3645 12.2778 6.2845 12.0058 6.6525 11.8378C6.7085 11.4218 6.8765 11.1418 7.0605 10.9818C5.6365 10.8218 4.1485 10.2698 4.1485 7.82181C4.1485 7.12581 4.3965 6.54981 4.8045 6.10181C4.7405 5.94181 4.5165 5.28581 4.8685 4.40581C4.8685 4.40581 5.4045 4.23781 6.6285 5.06181C7.1405 4.91781 7.6845 4.84581 8.2285 4.84581C8.7725 4.84581 9.3165 4.91781 9.8285 5.06181C11.0525 4.22981 11.5885 4.40581 11.5885 4.40581C11.9405 5.28581 11.7165 5.94181 11.6525 6.10181C12.0605 6.54981 12.3085 7.11781 12.3085 7.82181C12.3085 10.2778 10.8125 10.8218 9.3885 10.9818C9.6205 11.1818 9.8205 11.5658 9.8205 12.1658C9.8205 13.0218 9.8125 13.7098 9.8125 13.9258C9.8125 14.0938 9.9325 14.2938 10.2525 14.2298C11.523 13.8009 12.627 12.9844 13.4092 11.8951C14.1913 10.8059 14.6122 9.49877 14.6125 8.15781C14.6125 4.62181 11.7485 1.75781 8.2125 1.75781Z"
fill="#8F8F8F"
/>
</svg>
)
export const LinkSvg = () => (
<svg width="17" height="16" viewBox="0 0 17 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M6.875 4.0013H4.20833C3.47195 4.0013 2.875 4.59826 2.875 5.33464V12.0013C2.875 12.7377 3.47195 13.3346 4.20833 13.3346H10.875C11.6114 13.3346 12.2083 12.7377 12.2083 12.0013V9.33464M9.54167 2.66797H13.5417M13.5417 2.66797V6.66797M13.5417 2.66797L6.875 9.33464"
stroke="#8F8F8F"
strokeWidth="1"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
)
export const ArrowTopRightSvg = () => (
<svg width="17" height="17" viewBox="0 0 17 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M3.44531 13.846L13.1152 4.17578"
stroke="#8F8F8F"
strokeMiterlimit="10"
strokeLinejoin="bevel"
/>
<path
d="M3.44531 4.09375H13.1152V13.7637"
stroke="#8F8F8F"
strokeMiterlimit="10"
strokeLinejoin="bevel"
/>
</svg>
)
export const HackernewsSvg = () => (
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M8.26821 7.87591L9.94194 4.47266H11.8008L8.82871 10.074V13.606H7.16205V10.0213L4.1875 4.47266H6.15549L7.86748 7.9537C7.87321 7.95954 7.87972 7.96606 7.88751 7.97386C7.95585 8.04219 7.98757 8.11202 8.00726 8.16124C8.01322 8.17614 8.01776 8.18804 8.02175 8.19849C8.02548 8.20824 8.02872 8.21672 8.03217 8.22518L8.04751 8.24052C8.11375 8.10585 8.19796 7.98119 8.26821 7.87591Z"
fill="#8F8F8F"
/>
</svg>
)
export const SmallCard = ({ className, children }: { className?: string; children: any }) => (
<div
className={[
'relative p-[1px] bg-gradient-to-b from-[#111718] to-[#1C1C1C60] rounded-2xl overflow-hidden shadow-lg',
className,
].join(' ')}
>
<div
className={[
'rounded-2xl text-sm text-[#9296AA] p-2 flex flex-row justify-between items-center backdrop-blur-md h-full',
'bg-[#030A0C]',
].join(' ')}
>
{children}
</div>
</div>
)
export const StyledArticleBadge = ({
className,
children,
}: {
className?: string
children: any
}) => (
<div
className={['relative bg-transparent border border-[#F4FFFA90] rounded-full', className].join(
' '
)}
>
<div className="!bg-transparent rounded-full !py-1 !px-4 w-full inset-[1px] text-sm border-none dark:from-white dark:to-[#6453C5] dark:border-none">
<span className="text-sm text-[#F4FFFA80] bg-clip-text bg-gradient-to-r from-[#F4FFFA] to-[#7E7AAD]">
{children}
</span>
<div className="absolute inset-0 w-full h-full bg-[#1C1C1C] rounded-full blur-2xl" />
</div>
</div>
)
export const AccordionHeader = ({
date,
day,
title,
shipped,
publishedAt,
shippable = true,
}: {
date: string
day: string
title: string
shipped?: boolean
publishedAt: string
shippable?: boolean
}) => {
return (
<div className="flex flex-1 flex-col sm:flex-row">
<div className="flex gap-4 w-full sm:w-auto sm:min-w-[240px] md:min-w-[380px] items-center">
<span className="text-scale-900 text-sm">
<span className="inline sm:hidden md:inline">{day} </span>
{date && (
<span>
<span className="inline sm:hidden md:inline">・</span> {date}
</span>
)}
</span>
</div>
{shippable && shipped && (
<Badge
className={`relative inset-0 !bg-transparent !py-1 !px-4 h-fit backdrop-blur-md ${
shipped
? 'bg-gradient-to-br from-[#05090B] to-[#05090B] !border-[#061517]'
: 'border-[#FFFFFF20]'
}`}
>
<span className="text-[#A0A0A0] text-sm font-normal bg-clip-text bg-gradient-to-r from-[#F4FFFA] to-[#675FA7]">
Shipped
</span>
</Badge>
)}
{shipped && <span className="text-scale-1200 text-lg mt-1 sm:mt-0">{title}</span>}
{shippable && !shipped && (
<span className="text-sm font-normal text-[#A0A0A0] mt-1 sm:mt-0 flex items-center gap-1 md:gap-4">
<svg
width="17"
height="17"
viewBox="0 0 17 17"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g opacity="0.5">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M4.32656 7.58047V5.98047C4.32656 3.77133 6.11742 1.98047 8.32656 1.98047C10.5357 1.98047 12.3266 3.77133 12.3266 5.98047V7.58047C13.2102 7.58047 13.9266 8.29681 13.9266 9.18047V13.1805C13.9266 14.0641 13.2102 14.7805 12.3266 14.7805H4.32656C3.44291 14.7805 2.72656 14.0641 2.72656 13.1805V9.18047C2.72656 8.29681 3.44291 7.58047 4.32656 7.58047ZM10.7266 5.98047V7.58047H5.92656V5.98047C5.92656 4.65499 7.00108 3.58047 8.32656 3.58047C9.65205 3.58047 10.7266 4.65499 10.7266 5.98047Z"
fill="#A0A0A0"
/>
</g>
</svg>
<CountdownComponent />
</span>
)}
</div>
)
}
export const MultistepSectionHeader = ({ title, blog }: any) => {
return (
<div className="flex flex-1 flex-col sm:flex-row py-8">
<div className="flex gap-4 w-full items-center justify-between md:justify-start">
{title && <span className="text-scale-1200 text-lg mt-3 sm:mt-0">{title}</span>}
{!!blog && (
<ChipLink href={blog} className="!w-auto !text-left !justify-between !flex-none">
Blog post
<div className="bg-[#313131] rounded-full hidden sm:inline-block p-1 ml-2">
<PencilSvg />
</div>
</ChipLink>
)}
</div>
</div>
)
}
export const ChipLink = ({
href,
uiOnly,
className,
target,
children,
}: {
href?: string
className?: string
uiOnly?: boolean
target?: '_blank' | '_self' | '_parent' | '_top' | 'framename'
children: any
}) =>
uiOnly ? (
<span
className={[
'flex flex-auto justify-center sm:justify-between w-full text-center sm:text-left min-h-[43px] sm:w-auto items-center border border-[#232323] bg-gradient-to-r text-white from-[#46444490] to-[#19191980] hover:from-[#4e4e4e90] hover:to-[#19191980] backdrop-blur-xl rounded-full text-sm py-2 px-3 sm:pr-2',
className,
].join(' ')}
>
{children}
</span>
) : !!href ? (
<Link href={href}>
<a
target={target ?? '_self'}
rel="noopener"
className={[
'flex flex-auto justify-center sm:justify-between w-full text-center sm:text-left min-h-[43px] sm:w-auto items-center border border-[#232323] bg-gradient-to-r text-white from-[#46444490] to-[#19191980] hover:from-[#4e4e4e90] hover:to-[#19191980] backdrop-blur-xl rounded-full text-sm py-2 px-3 sm:pr-2',
className,
].join(' ')}
>
{children}
</a>
</Link>
) : null
export const SectionButtons = ({
blog,
docs,
video,
github,
url,
hackernews,
mobileGrid,
}: {
blog?: string
docs?: string
video?: string
github?: string
url?: string
hackernews?: string
mobileGrid?: boolean
}) => {
return (
<div
className={[
'flex w-full max-w-full md:w-auto justify-center gap-2 z-10',
mobileGrid && 'grid grid-cols-2 gap-2 sm:flex',
].join(' ')}
>
{!!blog && (
<ChipLink href={blog}>
Blog post
<div className="bg-[#313131] rounded-full hidden sm:inline-block p-1 ml-2">
<PencilSvg />
</div>
</ChipLink>
)}
{!!docs && (
<ChipLink href={docs}>
Docs
<div className="bg-[#313131] rounded-full hidden sm:inline-block p-1 ml-2">
<DocsSvg />
</div>
</ChipLink>
)}
{!!video && (
<ChipLink href={video} target="_blank">
Video
<div className="bg-[#313131] rounded-full hidden sm:inline-block p-1 ml-2">
<PlaySvg />
</div>
</ChipLink>
)}
{!!github && (
<ChipLink href={github} target="_blank">
Github
<div className="bg-[#313131] rounded-full hidden sm:inline-block p-1 ml-2">
<GithubSvg />
</div>
</ChipLink>
)}
{!!url && (
<ChipLink href={url}>
Read
<div className="bg-[#313131] rounded-full hidden sm:inline-block p-1 ml-2">
<LinkSvg />
</div>
</ChipLink>
)}
{hackernews && (
<ChipLink href={hackernews} target="_blank">
Hackernews
<div className="bg-[#313131] rounded-full hidden sm:inline-block p-1 ml-2">
<HackernewsSvg />
</div>
</ChipLink>
)}
</div>
)
}
export const CartTitle = ({ children }: { children: any }) => (
<span className="z-0 relative text-[#F4FFFA90] bg-clip-text bg-gradient-to-r from-[#F4FFFA] to-[#675FA7] tracking-[-.5px] text-xl">
{children}
<div className="absolute -z-10 inset-0 w-full h-full bg-[#1C1C1C90] rounded-full blur-xl" />
</span>
)
export default {
AccordionHeader,
DocsSvg,
PencilSvg,
PlaySvg,
CartTitle,
ChipLink,
SectionButtons,
SmallCard,
StyledArticleBadge,
}
@@ -54,9 +54,7 @@ const TicketCustomizationForm = ({ supabase, user }: Props) => {
Connected account
</span>
)}
{IS_SAVED && (
<span className="opacity-0 animate-fade-in text-xs text-brand-900">Saved</span>
)}
{IS_SAVED && <span className="opacity-0 animate-fade-in text-xs text-brand">Saved</span>}
{HAS_ERROR && (
<span className="opacity-0 animate-fade-in text-xs text-tomato-900">
Something went wrong
@@ -72,7 +70,7 @@ const TicketCustomizationForm = ({ supabase, user }: Props) => {
disabled
placeholder="name"
value={user.name}
icon={<IconCheck strokeWidth={2} className="w-3 text-brand-900" />}
icon={<IconCheck strokeWidth={2} className="w-3 text-brand" />}
/>
<Input
className="[&_input]:border-scale-200"
@@ -91,7 +89,7 @@ const TicketCustomizationForm = ({ supabase, user }: Props) => {
className={[
'w-3',
IS_SAVING && 'text-scale-300',
!!formData.role ? 'text-brand-900' : 'text-scale-300',
!!formData.role ? 'text-brand' : 'text-scale-300',
].join(' ')}
/>
}
@@ -113,7 +111,7 @@ const TicketCustomizationForm = ({ supabase, user }: Props) => {
className={[
'w-3',
IS_SAVING && 'text-scale-300',
!!formData.company ? 'text-brand-900' : 'text-scale-300',
!!formData.company ? 'text-brand' : 'text-scale-300',
].join(' ')}
/>
}
@@ -135,7 +133,7 @@ const TicketCustomizationForm = ({ supabase, user }: Props) => {
className={[
'w-3 flex spin',
IS_SAVING && 'text-scale-300',
!!formData.location ? 'text-brand-900' : 'text-scale-300',
!!formData.location ? 'text-brand' : 'text-scale-300',
].join(' ')}
/>
}
@@ -130,8 +130,8 @@
height: 56px;
margin-top: var(--space-4x);
border-radius: var(--space-2x);
border: 1px solid var(--brand);
background: var(--brand);
border: 1px solid hsl(var(--brand-default));
background: hsl(var(--brand-default));
cursor: pointer;
font-family: inherit;
font-size: var(--text-md);
@@ -170,12 +170,12 @@
.submit.default:hover,
.submit.default:focus {
background: black;
color: var(--brand);
color: hsl(var(--brand-default));
}
.submit.default.generate-with-github:hover path,
.submit.default.generate-with-github:focus path {
fill: var(--brand);
fill: hsl(var(--brand-default));
}
.submit.error:hover,
@@ -3,10 +3,12 @@ import classNames from 'classnames'
interface Props {
children: React.ReactNode
className?: string
id?: string
}
const SectionContainer = ({ children, className }: Props) => (
const SectionContainer = ({ children, className, id }: Props) => (
<div
id={id}
className={classNames(
`sm:py-18 container relative mx-auto px-6 py-16 md:py-24 lg:px-16 lg:py-24 xl:px-20`,
className
+1 -1
View File
@@ -93,7 +93,7 @@ function Product({
lazyBoundary="100px"
/>
</motion.div>
<div className="text-brand-1100 dark:text-brand-900 flex justify-center relative opacity-70 md:absolute md:bottom-0 md:opacity-0 group-hover:opacity-100 transition-opacity md:translate-y-8 md:-left-20 md:md:-right-20 font-mono uppercase text-center text-xs mt-2">
<div className="text-brand-600 dark:text-brand flex justify-center relative opacity-70 md:absolute md:bottom-0 md:opacity-0 group-hover:opacity-100 transition-opacity md:translate-y-8 md:-left-20 md:md:-right-20 font-mono uppercase text-center text-xs mt-2">
<span>{product.name}</span>
</div>
</a>
+1 -1
View File
@@ -82,7 +82,7 @@ const Company = () => {
<div className="mt-6 text-sm font-medium">
<a
href="/blog"
className="dark:text-brand-900 dark:hover:text-brand-700 text-gray-600 transition duration-150 ease-in-out hover:text-gray-500"
className="dark:text-brand dark:hover:text-brand-400 text-gray-600 transition duration-150 ease-in-out hover:text-gray-500"
>
View all posts <span aria-hidden="true">&rarr;</span>
</a>
+8 -8
View File
@@ -85,7 +85,7 @@ const Nav = () => {
<p className="mt-1 text-sm text-scale-1100 dark:text-dark-100">{description}</p>
</div>
{url && (
<p className="mt-2 text-sm font-medium text-brand-900 lg:mt-4">
<p className="mt-2 text-sm font-medium text-brand lg:mt-4">
<TextLink label={label ? 'Get notified' : 'Learn more'} url={url} />
</p>
)}
@@ -120,7 +120,7 @@ const Nav = () => {
>
<button
className={[
'text-scale-900 focus:ring-brand-900 dark:bg-scale-200 dark:hover:bg-scale-300 inline-flex items-center justify-center rounded-md bg-gray-50 p-2 hover:bg-white focus:outline-none focus:ring-2 focus:ring-inset',
'text-scale-900 focus:ring-brand dark:bg-scale-200 dark:hover:bg-scale-300 inline-flex items-center justify-center rounded-md bg-gray-50 p-2 hover:bg-white focus:outline-none focus:ring-2 focus:ring-inset',
showLaunchWeekNavMode && '!bg-transparent border border-[#be9eea]',
].join(' ')}
aria-expanded="false"
@@ -166,7 +166,7 @@ const Nav = () => {
<div
className={[
`
text-scale-1200 hover:text-brand-900
text-scale-1200 hover:text-brand
inline-flex cursor-pointer items-center
border-b-2
border-transparent
@@ -258,7 +258,7 @@ const Nav = () => {
<Link href="/pricing">
<a
className={[
`text-scale-1200 hover:text-brand-900 hover:border-brand-900 dark:text-dark-100 dark:hover:border-dark-100 inline-flex items-center
`text-scale-1200 hover:text-brand hover:border-brand dark:text-dark-100 dark:hover:border-dark-100 inline-flex items-center
border-b-2 border-transparent p-5 px-1
text-sm font-medium`,
showLaunchWeekNavMode && '!text-white',
@@ -270,7 +270,7 @@ const Nav = () => {
<Link href="/docs">
<a
className={[
`text-scale-1200 hover:text-brand-900 hover:border-brand-900 dark:text-dark-100 dark:hover:border-dark-100 inline-flex items-center
`text-scale-1200 hover:text-brand hover:border-brand dark:text-dark-100 dark:hover:border-dark-100 inline-flex items-center
border-b-2 border-transparent p-5 px-1
text-sm font-medium`,
showLaunchWeekNavMode && '!text-white',
@@ -282,7 +282,7 @@ const Nav = () => {
<Link href="/blog">
<a
className={[
`text-scale-1200 hover:text-brand-900 hover:border-brand-900 dark:text-dark-100 dark:hover:border-dark-100 inline-flex items-center
`text-scale-1200 hover:text-brand hover:border-brand dark:text-dark-100 dark:hover:border-dark-100 inline-flex items-center
border-b-2 border-transparent p-5 px-1
text-sm font-medium`,
showLaunchWeekNavMode && '!text-white',
@@ -299,7 +299,7 @@ const Nav = () => {
className="hidden group lg:flex"
type="text"
icon={
<div className="flex items-center justify-center w-4 h-4 text-brand-800">
<div className="flex items-center justify-center w-4 h-4 text-brand-300">
<div
className={[
`text-scale-900 flex h-3 w-3 items-center justify-center
@@ -376,7 +376,7 @@ const Nav = () => {
<button
onClick={() => setOpen(false)}
type="button"
className="inline-flex items-center justify-center p-2 bg-white rounded-md text-scale-900 focus:ring-brand-900 dark:bg-scale-300 dark:hover:bg-scale-400 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset"
className="inline-flex items-center justify-center p-2 bg-white rounded-md text-scale-900 focus:ring-brand dark:bg-scale-300 dark:hover:bg-scale-400 hover:bg-gray-100 focus:outline-none focus:ring-2 focus:ring-inset"
>
<span className="sr-only">Close menu</span>
<svg
@@ -19,7 +19,7 @@ const PartnerLinkBox = ({
'bg-amber-400 dark:bg-scale-100 group-hover:bg-amber-500 dark:group-hover:bg-amber-300 text-amber-900',
blue: 'bg-blue-400 dark:bg-scale-100 group-hover:bg-blue-500 dark:group-hover:bg-blue-300 text-blue-900',
brand:
'bg-brand-400 dark:bg-scale-100 group-hover:bg-brand-500 dark:group-hover:bg-brand-300 text-brand-900',
'bg-brand-400 dark:bg-scale-100 group-hover:bg-brand-300 dark:group-hover:bg-brand-300 text-brand',
}
const content = (
@@ -119,7 +119,7 @@ export default function ComputePricingModal({ showComputeModal, setShowComputeMo
</th>
<td
className={`px-4 py-3 ${
column.key === 'plan' ? 'text-brand-900 pt-16 lg:pt-3' : ''
column.key === 'plan' ? 'text-brand pt-16 lg:pt-3' : ''
}`}
>
{column.key === 'dedicated' ? (
+2 -2
View File
@@ -9,13 +9,13 @@ function ProductIcon({ icon, color }: ProductIcon) {
className={[
'inline-flex h-8 w-8 flex-shrink-0 items-center justify-center rounded-md',
!color || color === 'black' ? 'bg-scale-1200 text-scale-100' : '',
color && color === 'green' ? 'bg-brand-800 dark:bg-brand-600 text-brand-100' : '',
color && color === 'green' ? 'bg-brand-300 dark:bg-brand-600 text-brand-100' : '',
].join(' ')}
>
<svg
className={[
'h-5 w-5 stroke-white dark:stroke-black',
color && color === 'green' ? 'dark:stroke-brand-900' : '',
color && color === 'green' ? 'dark:stroke-brand' : '',
].join(' ')}
xmlns="http://www.w3.org/2000/svg"
fill="none"
+1 -1
View File
@@ -21,7 +21,7 @@ export default function Quote(props: Props) {
<Avatar caption={caption} img={img} />
</div>
)}
<div className="absolute rounded-full w-1 h-full inset-0 right-auto bg-brand-900" />
<div className="absolute rounded-full w-1 h-full inset-0 right-auto bg-brand" />
</div>
</figure>
)
+1 -1
View File
@@ -68,7 +68,7 @@ const SOC2RequestForm = () => {
return (
<div>
{formSubmitted ? (
<h3 className="h3 text-brand-900 mt-12 text-center">
<h3 className="h3 text-brand mt-12 text-center">
Thank you for your submission! A member from the Supabase team will reach out to you
shortly!
</h3>
+1 -1
View File
@@ -30,7 +30,7 @@ const ScrollProgress = () => {
return (
<div className="h-[2px] w-full flex justify-start relative">
<div
className="h-full top-0 bottom-0 right-0 absolute w-screen bg-brand-900 will-change-transform transition-opacity"
className="h-full top-0 bottom-0 right-0 absolute w-screen bg-brand will-change-transform transition-opacity"
style={{
display: isActive ? 'absolute' : 'relative',
transform: `translate3d(${isActive ? progressPercentage - 100 + '%' : '0'},0,0)`,
@@ -130,7 +130,7 @@ const CommunitySlider = () => {
<p className="text-scale-900 my-3 text-base">{card.abstract}</p>
{card.url && (
<div className="text-brand-900 block cursor-pointer text-sm">Read Customer Story</div>
<div className="text-brand block cursor-pointer text-sm">Read Customer Story</div>
)}
</div>
)
@@ -74,7 +74,7 @@ const CustomerQuotesSection = (props: Props) => {
{customer.author}, {customer.role}
</p>
{customer.url && (
<div className="text-brand-900 border-t mt-4 pt-4 cursor-pointer text-sm flex items-center justify-between">
<div className="text-brand border-t mt-4 pt-4 cursor-pointer text-sm flex items-center justify-between">
<span>Read Customer Story</span>
<IconArrowUpRight />
</div>
@@ -53,7 +53,7 @@ const ProductHeaderCentered = (props: Types) => (
{props.icon && <ProductIcon icon={props.icon} />}
{props.title && (
<span
className="text-brand-900 font-mono uppercase tracking-widest text-sm"
className="text-brand font-mono uppercase tracking-widest text-sm"
key={`product-name-${props.title}`}
>
{props.title}
@@ -29,7 +29,7 @@ const Tab = ({ isActive, label, paragraph, onClick, progress, intervalDuration }
{isActive && (
<motion.div
className={[
'absolute inset-0 w-full right-full bg-brand-900 h-full transition-opacity',
'absolute inset-0 w-full right-full bg-brand h-full transition-opacity',
progress! > 99.7 ? 'opacity-0' : 'opacity-100',
].join(' ')}
style={{ x: `${progress! - 100}%` }}
+2 -2
View File
@@ -162,7 +162,7 @@ export default {
<>
<span className="heading-gradient">Simple yet</span>
<br />
<span className="text-brand-900">powerful APIs</span>
<span className="text-brand">powerful APIs</span>
</>
),
paragraph: 'Easy-to-use client libraries for managing and querying vector stores in Postgres.',
@@ -242,7 +242,7 @@ docs.query(
<>
<span className="heading-gradient">Powerful Features</span>
<br />
<span className="text-brand-900">Scale to millions</span>
<span className="text-brand">Scale to millions</span>
</>
),
paragraph:
+1 -1
View File
@@ -90,7 +90,7 @@ const LayoutComparison = ({ components, props }: Props) => {
{/* Title and description */}
<div className="mb-16 max-w-5xl space-y-8">
<div className="space-y-4">
<p className="text-brand-900 text-center">Alternative</p>
<p className="text-brand text-center">Alternative</p>
<h1 className="h1 text-center">{props.blog.title}</h1>
<div className="text-scale-900 flex justify-center space-x-3 text-sm">
<p>{props.blog.date}</p>
+29 -34
View File
@@ -118,7 +118,7 @@ const Hero = (props: Props) => {
<div className="col-span-12 text-scale-900 dark:text-white md:col-span-9 lg:col-span-8 xl:col-span-6">
<p className="mb-10 text-4xl">Supabase is an open source Firebase alternative.</p>
<p className="text-2xl">
Today, we're moving to <span className="text-brand-900">Beta</span>
Today, we're moving to <span className="text-brand">Beta</span>
</p>
<time itemProp="datePublished" dateTime="2020-12-03" className="text-sm opacity-80">
Published December 3rd, 2020
@@ -139,7 +139,7 @@ const Introduction = () => {
<a
href="https://news.ycombinator.com/item?id=23319901"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
Alpha
</a>{' '}
@@ -154,7 +154,7 @@ const Introduction = () => {
<a
href="/blog/2020/12/02/case-study-xendit"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
Xendit
</a>
@@ -162,7 +162,7 @@ const Introduction = () => {
<a
href="/blog/2020/12/02/case-study-monitoro"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
Monitoro
</a>
@@ -170,7 +170,7 @@ const Introduction = () => {
<a
href="/blog/2020/12/02/case-study-tayfa"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
TAYFA
</a>{' '}
@@ -223,8 +223,7 @@ const TableOfContents = (props: any) => {
<div className="container grid grid-cols-12 gap-4 px-8 py-20 mx-auto lg:px-28">
<div className="col-span-12 mb-10 text-base">
<p className="text-2xl text-black dark:text-white">
Supabase <span className="text-brand-900 dark:text-brand-900">Beta</span> is starting
now.
Supabase <span className="text-brand dark:text-brand">Beta</span> is starting now.
</p>
</div>
<div className="grid grid-cols-12 col-span-12 gap-y-10">
@@ -314,7 +313,7 @@ const Performance = () => {
<Bar
color={
stat.name === 'Supabase'
? 'bg-brand-900 dark:bg-brand-800'
? 'bg-brand dark:bg-brand-300'
: 'bg-brand-300 dark:bg-brand-400'
}
finalPercentage={Math.ceil((stat.value / maxValue) * 100)}
@@ -353,7 +352,7 @@ const Performance = () => {
<a
href="https://elixir-lang.org/"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
Elixir
</a>{' '}
@@ -361,7 +360,7 @@ const Performance = () => {
<a
href="https://github.com/supabase/realtime"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
Realtime engine
</a>
@@ -369,7 +368,7 @@ const Performance = () => {
<a
href="https://postgrest.org/en/v7.0.0/"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
PostgREST
</a>{' '}
@@ -381,7 +380,7 @@ const Performance = () => {
<a
href="https://github.com/supabase/benchmarks/"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
benchmarks
</a>{' '}
@@ -451,11 +450,7 @@ const Security = () => {
</li>
<li className="mb-5">
Adopted the{' '}
<a
href="https://snyk.io/"
target="_blank"
className="text-brand-900 hover:text-brand-900"
>
<a href="https://snyk.io/" target="_blank" className="text-brand hover:text-brand">
Snyk
</a>{' '}
dependency monitor as part of our SSDLC on several key component of our system, to
@@ -467,7 +462,7 @@ const Security = () => {
<a
href="https://github.com/PostgREST/postgrest/pull/1600#issuecomment-735257952"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
now uses
</a>{' '}
@@ -513,7 +508,7 @@ const Reliability = () => {
<a
href="https://status.supabase.com"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
https://status.supabase.com
</a>{' '}
@@ -557,7 +552,7 @@ const NewFeaturesAndIntegrations = () => {
<a
href="/docs/reference/javascript/auth-signup"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
JavaScript
</a>{' '}
@@ -565,7 +560,7 @@ const NewFeaturesAndIntegrations = () => {
<a
href="/docs/gotrue/server/about#endpoints"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
HTTP
</a>
@@ -587,7 +582,7 @@ const NewFeaturesAndIntegrations = () => {
<a
href="/docs/guides/client-libraries#realtime-changes"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
subscribe to changes in your database
</a>{' '}
@@ -606,7 +601,7 @@ const NewFeaturesAndIntegrations = () => {
<a
href="/docs/reference/javascript/select#query-foreign-tables"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
querying from multiple tables
</a>{' '}
@@ -614,7 +609,7 @@ const NewFeaturesAndIntegrations = () => {
<a
href="/docs/reference/javascript/rpc"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
invoke complex functions
</a>
@@ -703,7 +698,7 @@ const BetaPricing = () => (
<a
href="mailto:rory@supabase.io"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
rory@supabase.io
</a>
@@ -716,7 +711,7 @@ const BetaPricing = () => (
</ul>
<p>
The Supabase Base plan is now called the Supabase Pro plan as per the{' '}
<a href="https://supabase.com/pricing" className="text-brand-900 hover:text-brand-900">
<a href="https://supabase.com/pricing" className="text-brand hover:text-brand">
pricing page
</a>
.
@@ -747,7 +742,7 @@ const OpenSource = () => (
<a
href="https://github.com/sponsors/supabase/"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
sponsorship
</a>{' '}
@@ -759,7 +754,7 @@ const OpenSource = () => (
<a
href="/blog/2020/12/02/supabase-striveschool"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
partnering with Strive School
</a>{' '}
@@ -772,7 +767,7 @@ const OpenSource = () => (
<a
href="mailto:rory@supabase.io"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
rory@supabase.io
</a>{' '}
@@ -783,7 +778,7 @@ const OpenSource = () => (
<a
href="https://github.com/supabase"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
our GitHub.
</a>{' '}
@@ -819,7 +814,7 @@ const FundingPartners = () => (
<a
href="https://twitter.com/supabase"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
Twitter
</a>{' '}
@@ -856,7 +851,7 @@ const ScalingOurTeam = () => (
<a
href="mailto:work@supabase.io"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
work@supabase.io
</a>
@@ -917,7 +912,7 @@ const WhatsNext = () => (
<a
href="mailto:support@supabase.io"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
support@supabase.io
</a>{' '}
@@ -925,7 +920,7 @@ const WhatsNext = () => (
<a
href="https://github.com/supabase/supabase/discussions"
target="_blank"
className="text-brand-900 hover:text-brand-900"
className="text-brand hover:text-brand"
>
discussion
</a>{' '}
+1 -1
View File
@@ -202,7 +202,7 @@ function BlogPostPage(props: any) {
{/* Title and description */}
<div className="mb-16 max-w-5xl space-y-8">
<div className="space-y-4">
<p className="text-brand-900">Blog post</p>
<p className="text-brand">Blog post</p>
<h1 className="h1">{props.blog.title}</h1>
<div className="text-scale-900 flex space-x-3 text-sm">
<p>{props.blog.date}</p>
+7 -7
View File
@@ -101,7 +101,7 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => {
<DefaultLayout>
<div className="text-scale-1200">
<div className="container relative mx-auto px-6 py-10 lg:pt-12 lg:px-16 xl:px-20 text-center space-y-4">
<h1 className="text-sm text-brand-900 md:text-base">
<h1 className="text-sm text-brand md:text-base">
<span className="sr-only">Supabase </span>Careers
</h1>
<h2 className="text-3xl md:text-4xl xl:text-5xl lg:max-w-2xl xl:max-w-3xl lg:mx-auto tracking-[-1.5px]">
@@ -121,9 +121,9 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => {
return (
<div
key={i}
className="border-t-[1px] mt-6 mx-2 md:mx-2 md:mt-0 md:border-0 border-brand-900 w-[134px] md:max-w-none"
className="border-t-[1px] mt-6 mx-2 md:mx-2 md:mt-0 md:border-0 border-brand w-[134px] md:max-w-none"
>
<div className="hidden md:block border-t-[1px] lg:border-t-2 border-brand-900 w-[60px] lg:w-[100px]"></div>
<div className="hidden md:block border-t-[1px] lg:border-t-2 border-brand w-[60px] lg:w-[100px]"></div>
<h2 className="text-3xl lg:text-4xl pt-3 tracking-[-1.5px]">
{company.number}
</h2>
@@ -153,7 +153,7 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => {
Discord to stay connected to our team, and our community.
</p>
<div className="max-w-[300px] sm:max-w-md lg:max-w-md mt-20">
<div className="border-t-2 border-brand-900 w-4/12"></div>
<div className="border-t-2 border-brand w-4/12"></div>
<h2 className="text-2xl sm:text-3xl lg:text-4xl pt-2 tracking-[-1.5px]">
We deeply believe in the efficacy of collaborative open source
</h2>
@@ -445,10 +445,10 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => {
className="flex lg:block items-start space-x-6 lg:space-x-0 lg:w-full"
>
<div className="lg:flex items-center">
<h3 className="bg-brand-600 border-[1px] border-brand-800 text-brand-900 text-md text-center w-[44px] px-2 py-1.5 rounded-md">
<h3 className="bg-brand-600 border-[1px] border-brand-300 text-brand text-md text-center w-[44px] px-2 py-1.5 rounded-md">
{i + 1}
</h3>
<div className="h-[100px] w-[1px] sm:h-[100px] mx-auto lg:h-[1px] lg:w-full bg-brand-800 lg:pr-6"></div>
<div className="h-[100px] w-[1px] sm:h-[100px] mx-auto lg:h-[1px] lg:w-full bg-brand-300 lg:pr-6"></div>
</div>
<div className="lg:mt-6">
<h2 className="sm:text-lg max-w-[75%] xl:max-w-none xl:w-11/12 lg:max-w-none">
@@ -461,7 +461,7 @@ const CareerPage: NextPage = ({ jobs, contributors }: any) => {
</div>
)
})}
<h3 className="bg-brand-600 border-[1px] border-brand-800 text-brand-900 text-xl w-[44px] min-h-[40px] px-2 py-1 rounded-md grid justify-items-center items-center">
<h3 className="bg-brand-600 border-[1px] border-brand-300 text-brand text-xl w-[44px] min-h-[40px] px-2 py-1 rounded-md grid justify-items-center items-center">
<IconCheck />
</h3>
</div>
+1 -3
View File
@@ -122,9 +122,7 @@ function CaseStudyPage(props: any) {
<article className="flex flex-col gap-8">
<div className="flex flex-col gap-8 max-w-xxl">
<Link passHref href="/customers">
<a className="text-brand-900 hover:text-brand-1000 mb-2 mt-0">
Customer Stories
</a>
<a className="text-brand hover:text-brand-600 mb-2 mt-0">Customer Stories</a>
</Link>
<h1 className="text-scale-1200 text-4xl font-semibold xl:text-5xl">
{props.blog.title}
@@ -145,7 +145,7 @@ function Database() {
className="bg-scale-100 dark:bg-scale-300 group flex flex-col gap-4 rounded border px-8 py-6"
key={i}
>
<div className="bg-scale-300 dark:bg-scale-500 text-scale-1200 group-hover:text-brand-900 flex h-12 w-12 items-center justify-center rounded-md border transition-all group-hover:scale-105">
<div className="bg-scale-300 dark:bg-scale-500 text-scale-1200 group-hover:text-brand flex h-12 w-12 items-center justify-center rounded-md border transition-all group-hover:scale-105">
{item.icon ? item.icon : <IconCode strokeWidth={2} />}
</div>
+12 -12
View File
@@ -1018,7 +1018,7 @@ export default function launchweek() {
href="https://supabase.com/blog/launch-week-6-hackathon"
target="_blank"
rel="nooper noreferrer"
className="text-brand-900"
className="text-brand"
>
blog post
</a>
@@ -1052,7 +1052,7 @@ export default function launchweek() {
<a
href="https://discord.supabase.com/"
rel="noopener noreferrer"
className="text-brand-900 flex items-center"
className="text-brand flex items-center"
target="_blank"
>
Join our Discord <IconExternalLink size="small" className="inline-block ml-2" />
@@ -1064,7 +1064,7 @@ export default function launchweek() {
<p className="text-slate-900 w-[90%] lg:w-[80%]">
Submit your project through{' '}
<a
className="text-brand-900"
className="text-brand"
href="https://www.madewithsupabase.com/launch-week-6"
target="_blank"
>
@@ -1091,7 +1091,7 @@ export default function launchweek() {
<div className="border border-[#2E2E2E] rounded-xl pl-5 pr-9 py-4 mb-4 bg-[#121212] w-fit relative max-w-[250px]">
<img
src="/images/launchweek/link.svg"
className="absolute top-[16px] right-[10px] text-brand-900"
className="absolute top-[16px] right-[10px] text-brand"
></img>
<h3 className="text-white">Supabase Cache Helpers</h3>
<p className="text-slate-1000 text-xs">Previous Best Overall Project Winner</p>
@@ -1105,7 +1105,7 @@ export default function launchweek() {
<div className="border border-[#2E2E2E] rounded-xl pl-5 pr-9 py-4 mb-4 bg-[#121212] w-fit relative max-w-[250px]">
<img
src="/images/launchweek/link.svg"
className="absolute top-[16px] right-[10px] text-brand-900"
className="absolute top-[16px] right-[10px] text-brand"
></img>
<h3 className="text-white">Super UI</h3>
<p className="text-slate-1000 text-xs">Previous Best Overall Project Runner Up</p>
@@ -1120,7 +1120,7 @@ export default function launchweek() {
<div className="border border-[#2E2E2E] rounded-xl pl-5 pr-9 py-4 mb-4 bg-[#121212] w-fit relative max-w-[250px]">
<img
src="/images/launchweek/link.svg"
className="absolute top-[16px] right-[10px] text-brand-900"
className="absolute top-[16px] right-[10px] text-brand"
></img>
<h3 className="text-white">Quid Faciam Hodie?</h3>
<p className="text-slate-1000 text-xs">Winner Best Flutter Project</p>
@@ -1130,7 +1130,7 @@ export default function launchweek() {
<div className="border border-[#2E2E2E] rounded-xl pl-5 pr-9 py-4 mb-4 bg-[#121212] w-fit relative max-w-[250px]">
<img
src="/images/launchweek/link.svg"
className="absolute top-[16px] right-[10px] text-brand-900"
className="absolute top-[16px] right-[10px] text-brand"
></img>
<h3 className="text-white">That Hot Dog Game</h3>
<p className="text-slate-1000 text-xs">Previous Winner: Most Fun/Interesting</p>
@@ -1145,7 +1145,7 @@ export default function launchweek() {
<div className="border border-[#2E2E2E] rounded-xl pl-5 pr-9 py-4 bg-[#121212] w-fit relative max-w-[250px]">
<img
src="/images/launchweek/link.svg"
className="absolute top-[16px] right-[10px] text-brand-900"
className="absolute top-[16px] right-[10px] text-brand"
></img>
<h3 className="text-white">RepoWatch</h3>
<p className="text-slate-1000 text-xs">Previous Winner Best Realtime Project</p>
@@ -1177,10 +1177,10 @@ export default function launchweek() {
}}
>
<div className="relative group">
<div className="absolute -inset-0.5 bg-brand-1100 rounded-full opacity-75 group-hover:opacity-100 group-hover:blur-sm transition duration-500"></div>
<div className="absolute -inset-0.5 bg-brand-600 rounded-full opacity-75 group-hover:opacity-100 group-hover:blur-sm transition duration-500"></div>
<a href={creator.link} target="_blank" rel="noopener">
<img
className="relative rounded-full w-12 h-12 border border-[#2E2E2E] border-brand-900 hover:shadow-md"
className="relative rounded-full w-12 h-12 border border-[#2E2E2E] border-brand hover:shadow-md"
src={creator.profile_picture}
/>
</a>
@@ -1204,7 +1204,7 @@ export default function launchweek() {
We worked with more than 30 content creators from around the world to drop a mountain
of content simultaneously!
<a rel="noopener" target="_blank" href="/blog/the-supabase-content-storm">
<div className="text-brand-900 flex items-center mt-2">
<div className="text-brand flex items-center mt-2">
See all the content
<IconExternalLink size="small" className="inline-block ml-1" />
</div>
@@ -1220,7 +1220,7 @@ export default function launchweek() {
{activeCreator !== null && (
<p className="text-slate-900 ">{creators[activeCreator].description}</p>
)}
<p className="text-brand-900 mt-1">
<p className="text-brand mt-1">
<a rel="noopener" target="_blank" href={creators[activeCreator].link}>
<span>
{creators[activeCreator].link_title}
+22 -4
View File
@@ -11,16 +11,19 @@ import { PageState, ConfDataContext, UserData } from '~/components/LaunchWeek/ho
import DefaultLayout from '~/components/Layouts/Default'
import SectionContainer from '~/components/Layouts/SectionContainer'
import { LaunchWeekLogoHeader } from '~/components/LaunchWeek/8/LaunchWeekLogoHeader'
import { Meetup } from '~/components/LaunchWeek/8/LW8Meetups'
import { useTheme } from 'common/Providers'
import 'swiper/swiper.min.css'
import Head from 'next/head'
import LW8CalloutsSection from '../../components/LaunchWeek/8/LW8CalloutsSection'
const AnimatedParticles = dynamic(
() => import('~/components/LaunchWeek/8/AnimatedParticles/ParticlesCanvas')
)
const TicketContainer = dynamic(() => import('~/components/LaunchWeek/8/Ticket/TicketContainer'))
const LW8Meetups = dynamic(() => import('~/components/LaunchWeek/8/LW8Meetups'))
const LaunchWeekPrizeSection = dynamic(
() => import('~/components/LaunchWeek/8/LaunchWeekPrizeSection')
)
@@ -29,6 +32,7 @@ const CTABanner = dynamic(() => import('~/components/CTABanner'))
interface Props {
users?: UserData[]
meetups?: Meetup[]
}
const supabaseAdmin = createClient(
@@ -39,7 +43,7 @@ const supabaseAdmin = createClient(
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6Im9idWxkYW5ycHRsb2t0eGNmZnZuIiwicm9sZSI6ImFub24iLCJpYXQiOjE2Njk3MjcwMTIsImV4cCI6MTk4NTMwMzAxMn0.SZLqryz_-stF8dgzeVXmzZWPOqdOrBwqJROlFES8v3I'
)
export default function TicketHome({ users }: Props) {
export default function TicketHome({ users, meetups }: Props) {
const { query } = useRouter()
const TITLE = 'Supabase LaunchWeek 8'
@@ -149,7 +153,7 @@ export default function TicketHome({ users }: Props) {
/>
</div>
</SectionContainer>
<div className="absolute w-full aspect-[1/1] md:aspect-[1.5/1] lg:aspect-[2.5/1] inset-0 z-0">
<div className="absolute w-full aspect-[1/1] md:aspect-[1.5/1] lg:aspect-[2.5/1] inset-0 z-0 pointer-events-none">
<Image
src="/images/launchweek/8/LW8-gradient.png"
layout="fill"
@@ -162,6 +166,16 @@ export default function TicketHome({ users }: Props) {
</div>
</div>
<div id="twitter-spaces">
<SectionContainer className="!pb-0" id="hackathon">
<LW8CalloutsSection />
</SectionContainer>
</div>
<SectionContainer id="meetups">
<LW8Meetups meetups={meetups} />
</SectionContainer>
<div className="relative !w-full max-w-[100vw] min-h-[400px] !px-4 sm:max-w-xl md:max-w-4xl lg:max-w-7xl z-20 flex flex-col justify-around items-center !py-4 md:!py-8 lg:!pb-0 gap-2 md:gap-4 !mx-auto">
{supabase && (
<div className="w-full max-w-[100vw] px-4 flex justify-center py-8 md:py-20">
@@ -185,15 +199,19 @@ export default function TicketHome({ users }: Props) {
)
}
export const getServerSideProps: GetServerSideProps = async ({ req, res }) => {
export const getServerSideProps: GetServerSideProps = async () => {
// fetch users for the TicketBrickWall
const { data: users } = await supabaseAdmin!
.from('lw8_tickets_golden')
.select('username, golden', { count: 'exact' })
.select('username, golden')
.limit(1000)
const { data: meetups } = await supabaseAdmin!.from('lw8_meetups').select('*')
return {
props: {
users,
meetups,
},
}
}
@@ -114,7 +114,7 @@ export default function UsernamePage({ user, users, ogImageUrl }: Props) {
)}
</div>
</SectionContainer>
<div className="absolute w-full aspect-[1/1] md:aspect-[1.5/1] lg:aspect-[2.5/1] inset-0 z-0">
<div className="absolute w-full aspect-[1/1] md:aspect-[1.5/1] lg:aspect-[2.5/1] inset-0 z-0 pointer-events-none">
<Image
src="/images/launchweek/8/LW8-gradient.png"
layout="fill"
+1 -1
View File
@@ -154,7 +154,7 @@ export default function TicketsPage({ users }: Props) {
/>
</div>
</SectionContainer>
<div className="absolute w-full aspect-[1/1] md:aspect-[1.5/1] lg:aspect-[2.5/1] inset-0 z-0">
<div className="absolute w-full aspect-[1/1] md:aspect-[1.5/1] lg:aspect-[2.5/1] inset-0 z-0 pointer-events-none">
<Image
src="/images/launchweek/8/LW8-gradient.png"
layout="fill"
+1 -1
View File
@@ -52,7 +52,7 @@ const DPA = () => {
<p>You can download our latest DPA document by submitting your email here.</p>
{formSubmitted ? (
<p className="text-brand-900">
<p className="text-brand">
Thank you for your submission! A new tab should have opened with the DPA
document
</p>
+2 -2
View File
@@ -82,8 +82,8 @@ const OpenSource = () => {
{maintainerPills.map((x) => (
<li
key={x}
className={`mx-4 rounded-t-lg inline-block p-2 cursor-pointer hover:text-brand-800 ${
activePill == x ? 'bg-gray-200 dark:bg-gray-400 text-brand-800' : ''
className={`mx-4 rounded-t-lg inline-block p-2 cursor-pointer hover:text-brand-300 ${
activePill == x ? 'bg-gray-200 dark:bg-gray-400 text-brand-300' : ''
}`}
onClick={() => setActivePill(x)}
>
+3 -3
View File
@@ -160,7 +160,7 @@ function Partner({
<div className="flex items-center justify-between py-2">
<span className="text-scale-900">Category</span>
<Link href={`/partners/experts#${partner.category.toLowerCase()}`}>
<a className="text-brand-900 hover:text-brand-800 transition-colors">
<a className="text-brand hover:text-brand-300 transition-colors">
{partner.category}
</a>
</Link>
@@ -172,7 +172,7 @@ function Partner({
href={partner.website}
target="_blank"
rel="noreferrer"
className="text-brand-900 hover:text-brand-800 transition-colors"
className="text-brand hover:text-brand-300 transition-colors"
>
{new URL(partner.website).host}
</a>
@@ -185,7 +185,7 @@ function Partner({
href={partner.docs}
target="_blank"
rel="noreferrer"
className="text-brand-900 hover:text-brand-800 transition-colors"
className="text-brand hover:text-brand-300 transition-colors"
>
<span className="flex items-center space-x-1">
<span>Learn</span>
@@ -201,7 +201,7 @@ function Partner({
<div className="flex items-center justify-between py-2">
<span className="text-scale-900">Category</span>
<Link href={`/partners/integrations#${partner.category.toLowerCase()}`}>
<a className="text-brand-900 hover:text-brand-800 transition-colors">
<a className="text-brand hover:text-brand-300 transition-colors">
{partner.category}
</a>
</Link>
@@ -213,7 +213,7 @@ function Partner({
href={partner.website}
target="_blank"
rel="noreferrer"
className="text-brand-900 hover:text-brand-800 transition-colors"
className="text-brand hover:text-brand-300 transition-colors"
>
{new URL(partner.website).host}
</a>
@@ -226,7 +226,7 @@ function Partner({
href={partner.docs}
target="_blank"
rel="noreferrer"
className="text-brand-900 hover:text-brand-800 transition-colors"
className="text-brand hover:text-brand-300 transition-colors"
>
<span className="flex items-center space-x-1">
<span>Learn</span>
@@ -202,10 +202,10 @@ function IntegrationPartnersPage(props: Props) {
<a className="text-scale-1200">INTEGRATIONS</a>
</Link>
<Link href={`/partners/experts`}>
<a className="transition-colors text-brand-900 hover:text-brand-800">EXPERTS</a>
<a className="transition-colors text-brand hover:text-brand-300">EXPERTS</a>
</Link>
<Link href={`/partners/integrations#become-a-partner`}>
<a className="flex items-center space-x-1 transition-colors text-brand-900 hover:text-brand-800">
<a className="flex items-center space-x-1 transition-colors text-brand hover:text-brand-300">
BECOME A PARTNER <IconArrowRight />
</a>
</Link>
+15 -19
View File
@@ -104,7 +104,7 @@ export default function IndexPage() {
}) => {
return (
<div className="mt-8 px-4 mobile-header">
<h2 className="gradient-text-brand-500 dark:gradient-text-brand-100 text-3xl font-medium uppercase font-mono">
<h2 className="gradient-text-brand-300 dark:gradient-text-brand-100 text-3xl font-medium uppercase font-mono">
{plan}
</h2>
<div className="flex items-baseline gap-2">
@@ -150,7 +150,7 @@ export default function IndexPage() {
<div className="relative z-10 py-16 lg:py-28">
<div className="mx-auto max-w-7xl px-4 text-center sm:px-6 lg:px-8">
<div className="mx-auto max-w-3xl space-y-2 lg:max-w-none">
<h1 className="text-brand-900 text-base">Pricing</h1>
<h1 className="text-brand text-base">Pricing</h1>
<h2 className="h1">Predictable pricing, no surprises</h2>
<p className="p text-lg">
Start building for free, collaborate with a team, then scale to millions of users
@@ -174,7 +174,7 @@ export default function IndexPage() {
key={`row-${plan.name}`}
className={[
plan.name === 'Pro'
? 'bg-brand-1100 dark:bg-brand-900 border px-0.5 -mt-8 rounded-[6px]'
? 'bg-brand-600 dark:bg-brand border px-0.5 -mt-8 rounded-[6px]'
: '',
].join(' ')}
>
@@ -198,13 +198,13 @@ export default function IndexPage() {
<div className="mb-2 flex items-center gap-2">
<div className="flex items-center gap-2">
<h3
className="gradient-text-brand-500 dark:gradient-text-brand-100 text-2xl font-normal
className="gradient-text-brand-300 dark:gradient-text-brand-100 text-2xl font-normal
uppercase flex items-center gap-4 font-mono"
>
{plan.name}
</h3>
{plan.nameBadge && (
<span className="bg-brand-500 text-brand-1100 rounded-md bg-opacity-30 py-0.5 px-2 text-[13px] leading-4">
<span className="bg-brand-300 text-brand-600 rounded-md bg-opacity-30 py-0.5 px-2 text-[13px] leading-4">
{plan.nameBadge}
</span>
)}
@@ -249,7 +249,7 @@ export default function IndexPage() {
{plan.warning && (
<p className="-mt-2">
<span className="bg-scale-200 text-brand-1100 border shadow-sm rounded-md bg-opacity-30 py-0.5 px-2 text-[13px] leading-4">
<span className="bg-scale-200 text-brand-600 border shadow-sm rounded-md bg-opacity-30 py-0.5 px-2 text-[13px] leading-4">
{plan.warning}
</span>
</p>
@@ -273,7 +273,7 @@ export default function IndexPage() {
{plan.features.map((feature) => (
<li key={feature} className="flex items-center py-2 first:mt-0">
<IconCheck
className="text-brand-900 h-4 w-4"
className="text-brand h-4 w-4"
aria-hidden="true"
strokeWidth={3}
/>
@@ -308,7 +308,7 @@ export default function IndexPage() {
<div className="flex flex-col justify-center lg:px-8">
<div>
<h3
className="gradient-text-brand-500 dark:gradient-text-brand-100 text-2xl font-normal
className="gradient-text-brand-300 dark:gradient-text-brand-100 text-2xl font-normal
uppercase flex items-center gap-4 font-mono"
>
{planEnterprise.name}
@@ -331,11 +331,7 @@ export default function IndexPage() {
>
{planEnterprise.features.map((feature) => (
<li key={feature} className="flex items-center py-2 first:mt-0">
<IconCheck
className="text-brand-900 h-4 w-4 "
aria-hidden="true"
strokeWidth={3}
/>
<IconCheck className="text-brand h-4 w-4 " aria-hidden="true" strokeWidth={3} />
<span className="dark:text-scale-1200 mb-0 ml-3 ">{feature}</span>
</li>
))}
@@ -407,7 +403,7 @@ export default function IndexPage() {
</Link>
{addon.name === 'Optimized Compute' ? (
<button
className="text-brand-1000 text-[13px] leading-4 hover:underline "
className="text-brand-600 text-[13px] leading-4 hover:underline "
onClick={() => setShowComputeModal(true)}
>
{addon.rightCtaText}
@@ -440,7 +436,7 @@ export default function IndexPage() {
className="grid lg:grid-cols-2 gap-8 items-center mt-12 lg:mt-8 max-w-6xl mx-auto"
>
<div>
<span className="bg-brand-500 text-brand-1100 rounded-md bg-opacity-30 inline-block dark:bg-scale-400 dark:text-scale-1100 py-0.5 px-2 text-[13px] leading-4 mt-2">
<span className="bg-brand-300 text-brand-600 rounded-md bg-opacity-30 inline-block dark:bg-scale-400 dark:text-scale-1100 py-0.5 px-2 text-[13px] leading-4 mt-2">
Available for Pro plan
</span>
<h2 className="text-scale-1200 text-4xl mt-4">Cost control with spend caps</h2>
@@ -735,7 +731,7 @@ export default function IndexPage() {
scope="col"
key={plan.name}
>
<h3 className="gradient-text-brand-500 dark:gradient-text-brand-100 text-2xl font-mono font-normal uppercase flex items-center gap-4">
<h3 className="gradient-text-brand-300 dark:gradient-text-brand-100 text-2xl font-mono font-normal uppercase flex items-center gap-4">
{plan.name}
</h3>
<div
@@ -796,7 +792,7 @@ export default function IndexPage() {
{plan.warning && (
<p className="-mt-2">
<span className="bg-scale-100 text-brand-1100 border shadow-sm rounded-md bg-opacity-30 py-0.5 px-2 text-[13px] leading-4">
<span className="bg-scale-100 text-brand-600 border shadow-sm rounded-md bg-opacity-30 py-0.5 px-2 text-[13px] leading-4">
{plan.warning}
</span>
</p>
@@ -953,7 +949,7 @@ export default function IndexPage() {
<a
target="_blank"
href="https://supabase.com/dashboard/support/new"
className="transition text-brand-900 hover:text-brand-1000"
className="transition text-brand hover:text-brand-600"
>
open a support ticket
</a>{' '}
@@ -964,7 +960,7 @@ export default function IndexPage() {
<a
target="_blank"
href="https://supabase.com/dashboard/support/new"
className="transition text-brand-900 hover:text-brand-1000"
className="transition text-brand hover:text-brand-600"
>
you can contact the team here
</a>
+1 -1
View File
@@ -66,7 +66,7 @@ function RealtimePage() {
<div className="bg-scale-300 border-scale-500 relative flex h-[372px] w-[560px] items-center justify-center overflow-hidden rounded border drop-shadow-md">
<div
className={[
'border-brand-800 relative h-12 w-48 bg-[#34B27B]',
'border-brand-300 relative h-12 w-48 bg-[#34B27B]',
`flex items-center justify-center ${RealtimeStyles['shape']}`,
].join(' ')}
>
+7 -9
View File
@@ -38,9 +38,7 @@ const Index = ({}: Props) => {
<Container>
<SectionContainer className="">
<div className="space-y-2 text-center">
<h1 className="text-brand-900 font-mono text-base uppercase tracking-widest">
Support
</h1>
<h1 className="text-brand font-mono text-base uppercase tracking-widest">Support</h1>
<h1 className="h1">Get Support</h1>
<p className="text-scale-1100 lg:text-lg">
The Supabase Support Team is ready to help.
@@ -64,8 +62,8 @@ const Index = ({}: Props) => {
our GitHub issues. This can be feature requests too!
</p>
<p className="text-scale-1100 mt-2 text-sm">
<span className="text-brand-900 font-bold">Use this for:</span> Bugs and
other issues
<span className="text-brand font-bold">Use this for:</span> Bugs and other
issues
</p>
</p>
</div>
@@ -112,8 +110,8 @@ const Index = ({}: Props) => {
join us on Discord. Browse and ask questions.
</p>
<p className="text-scale-1100 mt-2 text-sm">
<span className="text-brand-900 text-sm font-bold">Use this for:</span>{' '}
General questions
<span className="text-brand text-sm font-bold">Use this for:</span> General
questions
</p>
</p>
</div>
@@ -183,8 +181,8 @@ const Index = ({}: Props) => {
or have an issue, please contact us here.
</p>
<p className="text-scale-1100 mt-2 text-sm">
<span className="text-brand-900 text-sm font-bold">Use this for:</span>{' '}
Issues or questions specific to you
<span className="text-brand text-sm font-bold">Use this for:</span> Issues
or questions specific to you
</p>
</p>
</div>
Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

@@ -0,0 +1,66 @@
<svg width="132" height="76" viewBox="0 0 132 76" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2932_199528)">
<path d="M135.023 -31.2891H-2.9375V106.672H135.023V-31.2891Z" fill="#020405" stroke="white"/>
<g opacity="0.3" filter="url(#filter0_f_2932_199528)">
<path d="M-12.1957 67.4624C2.39617 70.8852 14.3008 38.7141 18.4292 22.2007C27.8868 -9.77554 76.5265 2.15942 62.3399 -20.5841C48.1534 -43.3275 25.1847 -21.2597 -12.1957 -22.1604C-49.5761 -23.0611 -22.3289 12.743 -22.5541 37.5131C-22.7793 62.2832 -65.7892 62.7336 -63.7626 77.3705C-61.736 92.0074 -30.4355 63.184 -12.1957 67.4624Z" fill="#6F13A4"/>
</g>
<circle cx="84.4815" cy="49.1861" r="0.417039" transform="rotate(4.39775 84.4815 49.1861)" fill="#7E7E7E"/>
<circle cx="70.6654" cy="50.5636" r="0.417039" transform="rotate(108.965 70.6654 50.5636)" fill="#7E7E7E"/>
<circle cx="60.431" cy="61.7823" r="0.417039" transform="rotate(108.965 60.431 61.7823)" fill="#7E7E7E"/>
<circle cx="52.849" cy="74.38" r="0.417039" transform="rotate(108.965 52.849 74.38)" fill="#7E7E7E"/>
<circle cx="52.2982" cy="27.4893" r="0.417039" transform="rotate(108.965 52.2982 27.4893)" fill="#7E7E7E"/>
<circle cx="109.712" cy="62.0753" r="0.417039" transform="rotate(108.965 109.712 62.0753)" fill="#7E7E7E"/>
<circle cx="81.169" cy="47.1236" r="0.417039" transform="rotate(4.39775 81.169 47.1236)" fill="#7E7E7E"/>
<circle cx="120.923" cy="24.7525" r="0.417039" transform="rotate(4.39775 120.923 24.7525)" fill="#7E7E7E"/>
<circle cx="81.1416" cy="48.4634" r="0.417039" transform="rotate(4.39775 81.1416 48.4634)" fill="#7E7E7E"/>
<circle cx="77.4659" cy="4.05716" r="0.417039" transform="rotate(4.39775 77.4659 4.05716)" fill="#7E7E7E"/>
<circle cx="77.4971" cy="10.3579" r="0.417039" transform="rotate(4.39775 77.4971 10.3579)" fill="#7E7E7E"/>
<circle cx="82.6182" cy="8.56888" r="0.417039" transform="rotate(4.39775 82.6182 8.56888)" fill="#7E7E7E"/>
<circle cx="74.1849" cy="48.2198" r="0.417039" transform="rotate(108.965 74.1849 48.2198)" fill="#7E7E7E"/>
<circle cx="112.642" cy="50.5574" r="0.417039" transform="rotate(169.398 112.642 50.5574)" fill="#7E7E7E"/>
<circle cx="120.539" cy="29.4917" r="0.417039" transform="rotate(-86.0346 120.539 29.4917)" fill="#7E7E7E"/>
<circle cx="124.281" cy="29.019" r="0.417039" transform="rotate(-86.0346 124.281 29.019)" fill="#7E7E7E"/>
<circle cx="126.234" cy="20.0425" r="0.417039" transform="rotate(-86.0346 126.234 20.0425)" fill="#7E7E7E"/>
<circle cx="62.8511" cy="25.3355" r="0.417039" transform="rotate(-86.0346 62.8511 25.3355)" fill="#7E7E7E"/>
<circle cx="130.66" cy="35.4136" r="0.417039" transform="rotate(-86.0346 130.66 35.4136)" fill="#7E7E7E"/>
<circle cx="126.968" cy="8.71436" r="0.417039" transform="rotate(-86.0346 126.968 8.71436)" fill="#7E7E7E"/>
<circle cx="74.273" cy="11.9644" r="0.417039" transform="rotate(-86.0346 74.273 11.9644)" fill="#7E7E7E"/>
<circle cx="89.2027" cy="-0.0864194" r="0.417039" transform="rotate(-86.0346 89.2027 -0.0864194)" fill="#7E7E7E"/>
<circle cx="67.9839" cy="23.3433" r="0.417039" transform="rotate(-86.0346 67.9839 23.3433)" fill="#7E7E7E"/>
<circle cx="68.5503" cy="25.4175" r="0.417039" transform="rotate(-86.0346 68.5503 25.4175)" fill="#7E7E7E"/>
<circle cx="77.316" cy="29.8433" r="0.417039" transform="rotate(-86.0346 77.316 29.8433)" fill="#7E7E7E"/>
<circle cx="76.0738" cy="32.1011" r="0.417039" transform="rotate(-86.0346 76.0738 32.1011)" fill="#7E7E7E"/>
<circle cx="84.9293" cy="44.6362" r="0.417039" transform="rotate(-86.0346 84.9293 44.6362)" fill="#7E7E7E"/>
<circle cx="116.373" cy="51.702" r="0.417039" transform="rotate(169.398 116.373 51.702)" fill="#7E7E7E"/>
<circle cx="60.2868" cy="67.0926" r="0.417039" transform="rotate(169.398 60.2868 67.0926)" fill="#7E7E7E"/>
<circle cx="51.7594" cy="33.7059" r="0.417039" transform="rotate(169.398 51.7594 33.7059)" fill="#7E7E7E"/>
<circle cx="116.045" cy="50.3934" r="0.417039" transform="rotate(169.398 116.045 50.3934)" fill="#7E7E7E"/>
<circle cx="124.845" cy="75.4598" r="0.417039" transform="rotate(169.398 124.845 75.4598)" fill="#7E7E7E"/>
<g filter="url(#filter1_d_2932_199528)">
<ellipse cx="0.0105357" cy="0.0118572" rx="0.0105357" ry="0.0118572" transform="matrix(0.999179 0.040507 -0.108737 0.994071 81.8594 17.4141)" fill="#EADEEC"/>
<ellipse cx="0.0118517" cy="0.0105419" rx="0.0118517" ry="0.0105419" transform="matrix(0.102081 -0.994776 0.999487 0.0320441 80.8203 17.9219)" fill="#EADEEC"/>
<ellipse cx="0.0118517" cy="0.0105419" rx="0.0118517" ry="0.0105419" transform="matrix(0.102081 -0.994776 0.999487 0.0320441 81.5117 17.3398)" fill="#EADEEC"/>
</g>
<path d="M30.5417 38.0921H26.5594V42.1641H25.535V33.2263H26.5594V37.1958H30.5417V33.2263H31.5661V42.1641H30.5417V38.0921ZM40.6412 42.1641L39.8473 39.4878H36.6332L35.8393 42.1641H34.815L37.6064 33.2263H38.8869L41.6912 42.1641H40.6412ZM38.5796 35.2494L38.2979 34.1354H38.1698L37.8881 35.2494L36.8765 38.6427H39.6168L38.5796 35.2494ZM47.6 42.3177C47.0963 42.3177 46.6439 42.2281 46.2427 42.0488C45.8415 41.861 45.5 41.5793 45.2183 41.2037C44.9451 40.8281 44.7317 40.35 44.578 39.7696C44.4329 39.1805 44.3604 38.4891 44.3604 37.6952C44.3604 36.9013 44.4329 36.2141 44.578 35.6336C44.7317 35.0446 44.9451 34.5623 45.2183 34.1866C45.5 33.811 45.8415 33.5336 46.2427 33.3543C46.6439 33.1665 47.0963 33.0726 47.6 33.0726C48.3341 33.0726 48.9232 33.2305 49.3671 33.5464C49.811 33.8537 50.161 34.3275 50.4171 34.9677L49.5975 35.4671C49.4354 34.9805 49.2006 34.6135 48.8933 34.3659C48.5945 34.1098 48.1634 33.9818 47.6 33.9818C46.9171 33.9818 46.3878 34.2293 46.0122 34.7244C45.6451 35.211 45.4616 35.8683 45.4616 36.6964V38.6939C45.4616 39.522 45.6451 40.1836 46.0122 40.6787C46.3878 41.1653 46.9171 41.4086 47.6 41.4086C48.1805 41.4086 48.6286 41.2763 48.9445 41.0116C49.2604 40.7385 49.4994 40.3458 49.6616 39.8336L50.4811 40.3458C50.225 40.986 49.8622 41.4769 49.3927 41.8183C48.9317 42.1513 48.3341 42.3177 47.6 42.3177ZM56.0454 37.7336L54.8801 39.1933V42.1641H53.8558V33.2263H54.8801V36.2098L54.8033 38.0537H54.9314L56.2503 36.2098L58.4783 33.2263H59.6564L56.7112 37.0549L59.8484 42.1641H58.6448L56.0454 37.7336ZM68.2866 42.1641L67.4927 39.4878H64.2787L63.4848 42.1641H62.4604L65.2519 33.2263H66.5324L69.3366 42.1641H68.2866ZM66.225 35.2494L65.9433 34.1354H65.8153L65.5336 35.2494L64.522 38.6427H67.2622L66.225 35.2494ZM74.5931 34.1226V42.1641H73.5687V34.1226H71.0462V33.2263H77.1157V34.1226H74.5931ZM85.37 38.0921H81.3877V42.1641H80.3633V33.2263H81.3877V37.1958H85.37V33.2263H86.3944V42.1641H85.37V38.0921ZM93.459 42.3177C92.3749 42.3177 91.534 41.9464 90.9365 41.2037C90.3389 40.461 90.0402 39.2915 90.0402 37.6952C90.0402 36.0988 90.3389 34.9293 90.9365 34.1866C91.534 33.444 92.3749 33.0726 93.459 33.0726C94.5432 33.0726 95.384 33.444 95.9816 34.1866C96.5792 34.9293 96.8779 36.0988 96.8779 37.6952C96.8779 39.2915 96.5792 40.461 95.9816 41.2037C95.384 41.9464 94.5432 42.3177 93.459 42.3177ZM93.459 41.4086C94.2017 41.4086 94.7737 41.1653 95.1749 40.6787C95.5761 40.1836 95.7767 39.522 95.7767 38.6939V36.6964C95.7767 35.8683 95.5761 35.211 95.1749 34.7244C94.7737 34.2293 94.2017 33.9818 93.459 33.9818C92.7164 33.9818 92.1444 34.2293 91.7432 34.7244C91.342 35.211 91.1414 35.8683 91.1414 36.6964V38.6939C91.1414 39.522 91.342 40.1836 91.7432 40.6787C92.1444 41.1653 92.7164 41.4086 93.459 41.4086ZM102.342 36.3635L101.561 34.5196H101.433L101.522 36.3635V42.1641H100.523V33.2263H101.778L104.749 39.0269L105.53 40.8708H105.658L105.569 39.0269V33.2263H106.567V42.1641H105.312L102.342 36.3635Z" fill="#9296AA"/>
</g>
<defs>
<filter id="filter0_f_2932_199528" x="-111.277" y="-78.3514" width="223.636" height="207.347" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
<feGaussianBlur stdDeviation="23.7226" result="effect1_foregroundBlur_2932_199528"/>
</filter>
<filter id="filter1_d_2932_199528" x="79.6286" y="16.1247" width="3.44206" height="2.98893" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset/>
<feGaussianBlur stdDeviation="0.595867"/>
<feComposite in2="hardAlpha" operator="out"/>
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 0.980333 0 0 0 0 0.508333 0 0 0 0.5 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow_2932_199528"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow_2932_199528" result="shape"/>
</filter>
<clipPath id="clip0_2932_199528">
<rect width="131.914" height="75.3795" fill="white" transform="translate(0.0859375)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 8.6 KiB

@@ -0,0 +1,13 @@
<svg width="132" height="76" viewBox="0 0 132 76" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_2932_199515)">
<path d="M135.707 -30.9727H-2.25391V106.988H135.707V-30.9727Z" fill="#020405" stroke="white"/>
<path d="M53.5312 31.597C52.8096 31.925 52.0318 32.1405 51.2258 32.2436C52.0505 31.7469 52.6878 30.9597 52.9877 30.0132C52.2099 30.4818 51.3477 30.8098 50.4386 30.9972C49.6983 30.1912 48.658 29.7227 47.4772 29.7227C45.2748 29.7227 43.4755 31.522 43.4755 33.7431C43.4755 34.0617 43.513 34.371 43.5786 34.6615C40.2423 34.4928 37.2715 32.8903 35.294 30.463C34.9473 31.0534 34.7505 31.7469 34.7505 32.4779C34.7505 33.8743 35.4534 35.1113 36.5405 35.8142C35.8751 35.8142 35.2566 35.6268 34.713 35.3456C34.713 35.3456 34.713 35.3456 34.713 35.3738C34.713 37.3231 36.1 38.9537 37.9368 39.3192C37.5995 39.4129 37.2433 39.4598 36.8778 39.4598C36.6248 39.4598 36.3718 39.4317 36.1281 39.3848C36.6342 40.9686 38.1055 42.1495 39.8768 42.1776C38.5085 43.2647 36.7748 43.9019 34.8817 43.9019C34.5631 43.9019 34.2444 43.8832 33.9258 43.8457C35.7064 44.9891 37.8244 45.6544 40.0923 45.6544C47.4772 45.6544 51.5351 39.5254 51.5351 34.2117C51.5351 34.0336 51.5351 33.8649 51.5257 33.6869C52.3129 33.1246 52.9877 32.4123 53.5312 31.597Z" fill="#9296AA"/>
<line x1="72.6041" y1="23.8327" x2="61.7657" y2="51.7278" stroke="#9296AA" stroke-opacity="0.3" stroke-width="0.5"/>
<path d="M90.9633 36.3271L97.5885 28.7852H96.0188L90.2635 35.3323L85.6702 28.7852H80.3711L87.3187 38.6865L80.3711 46.5946H81.9408L88.0148 39.679L92.8666 46.5946H98.1657L90.9633 36.3271ZM88.8126 38.7734L88.1076 37.7868L82.5069 29.9441H84.9184L89.4396 36.2758L90.1417 37.2624L96.018 45.4922H93.6066L88.8126 38.7734Z" fill="#9296AA"/>
</g>
<defs>
<clipPath id="clip0_2932_199515">
<rect width="131.914" height="75.3795" fill="white" transform="translate(0.0859375)"/>
</clipPath>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

+17 -10
View File
@@ -95,11 +95,11 @@ h6:not(.overwrite) {
}
.heading-gradient-brand {
@apply text-[#3ECF8E00] bg-clip-text bg-gradient-to-b from-brand-1000 to-brand-900 dark:to-brand-800;
@apply text-[#3ECF8E00] bg-clip-text bg-gradient-to-b from-brand-600 to-brand dark:to-brand-300;
}
.toc-animate {
@apply !translate-x-1 !text-brand-900;
@apply !translate-x-1 !text-brand;
}
.prose-toc a {
@@ -328,7 +328,7 @@ launch week
*/
.launch-week-timeline-border--approaching {
border-image: linear-gradient(to bottom, var(--colors-brand9), var(--colors-purple7)) 1 100%;
border-image: linear-gradient(to bottom, hsl(var(--brand-default)), var(--colors-purple7)) 1 100%;
}
.launch-week-gradientBg {
@@ -472,9 +472,9 @@ launch week
filter: blur(calc(var(--auth-ui-card-height) / 6));
background-image: linear-gradient(
var(--rotate),
var(--colors-brand),
hsl(var(--brand-default)),
#3c67e3 43%,
var(--colors-brand)
hsl(var(--brand-default))
);
opacity: 1;
transition: opacity 0.5s;
@@ -683,19 +683,26 @@ launch week
}
[class*='gradient-text-']::selection {
background-color: var(--colors-brand9);
background-color: hsl(var(--brand-default));
background-clip: unset;
-webkit-text-fill-color: white;
}
@layer utilities {
.gradient-text-brand-100 {
background-image: linear-gradient(45deg, var(--colors-brand8) 0%, var(--colors-brand9) 100%);
background-image: linear-gradient(
45deg,
hsl(var(--brand-500)) 0%,
hsl(var(--brand-default)) 100%
);
}
.gradient-text-brand-500 {
background-image: linear-gradient(45deg, var(--colors-brand8) 0%, var(--colors-brand9) 100%);
.gradient-text-brand-300 {
background-image: linear-gradient(
45deg,
hsl(var(--brand-500)) 0%,
hsl(var(--brand-default)) 100%
);
}
.gradient-text-scale-100 {
background-image: -webkit-linear-gradient(45deg, #fff 0%, var(--colors-green12) 100%);
}
+3 -3
View File
@@ -61,7 +61,7 @@ services:
auth:
container_name: supabase-auth
image: supabase/gotrue:v2.62.1
image: supabase/gotrue:v2.82.4
depends_on:
db:
# Disable this if you are using an external Postgres database
@@ -247,7 +247,7 @@ services:
functions:
container_name: supabase-edge-functions
image: supabase/edge-runtime:v1.6.6
image: supabase/edge-runtime:v1.8.1
restart: unless-stopped
environment:
JWT_SECRET: ${JWT_SECRET}
@@ -267,7 +267,7 @@ services:
# Comment out everything below this point if you are using an external Postgres database
db:
container_name: supabase-db
image: supabase/postgres:15.1.0.90
image: supabase/postgres:15.1.0.103
healthcheck:
test: pg_isready -U postgres -h localhost
interval: 5s
+31
View File
@@ -87,6 +87,7 @@
"rehype-slug": "^5.1.0",
"remark": "^14.0.2",
"remark-admonitions": "^1.2.1",
"remark-emoji": "^3.1.2",
"remark-gfm": "^3.0.1",
"remark-slug": "^7.0.1",
"shiki": "^0.11.1",
@@ -20160,6 +20161,15 @@
"node": ">= 4"
}
},
"node_modules/emoticon": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/emoticon/-/emoticon-4.0.1.tgz",
"integrity": "sha512-dqx7eA9YaqyvYtUhJwT4rC1HIp82j5ybS1/vQ42ur+jBe17dJMwZE4+gvL1XadSFfxaPFFGt3Xsw+Y8akThDlw==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/wooorm"
}
},
"node_modules/encodeurl": {
"version": "1.0.2",
"dev": true,
@@ -29753,6 +29763,14 @@
"node": ">=10.5.0"
}
},
"node_modules/node-emoji": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
"integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==",
"dependencies": {
"lodash": "^4.17.21"
}
},
"node_modules/node-fetch": {
"version": "2.6.11",
"license": "MIT",
@@ -34592,6 +34610,19 @@
"url": "https://opencollective.com/unified"
}
},
"node_modules/remark-emoji": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/remark-emoji/-/remark-emoji-3.1.2.tgz",
"integrity": "sha512-QwhAzNk27Ol64uV4z/3n55MKrNz9bhr8wg+mO5aGqIYDS+jUarS1d8Y0ZIeEBVhfGkXj6gGYM+727sOgAPvV/A==",
"dependencies": {
"emoticon": "^4.0.1",
"mdast-util-find-and-replace": "^2.2.2",
"node-emoji": "^1.11.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/remark-external-links": {
"version": "8.0.0",
"dev": true,
+8 -6
View File
@@ -5,9 +5,9 @@
--ch-3: #ffcda1;
--ch-4: #f8f8f2;
--ch-5: #bda4ff;
--ch-6: var(--colors-brand10);
--ch-6: hsl(var(--brand-600));
--ch-7: #569cd6;
--ch-8: var(--colors-brand9);
--ch-8: hsl(var(--brand-default));
--ch-9: #ffa198;
--ch-10: #f0f6fc;
--ch-11: #490202;
@@ -15,7 +15,8 @@
--ch-13: #5a1e02;
--ch-14: #161b22;
--ch-15: #8b949e;
--ch-16: var(--colors-scale1);
// --ch-16: hsl(var(--foreground-lighter));
--ch-16: #2a2929;
--ch-17: #264f78;
--ch-18: #3794ff;
--ch-19: #ffffff0b;
@@ -34,9 +35,9 @@
--ch-3: #953800;
--ch-4: #24292f;
--ch-5: #8250df;
--ch-6: var(--colors-brand10);
--ch-6: hsl(var(--brand-600));
--ch-7: #cf222e;
--ch-8: var(--colors-brand9);
--ch-8: hsl(var(--brand-default));
--ch-9: #82071e;
--ch-10: #f6f8fa;
--ch-11: #ffebe9;
@@ -44,7 +45,8 @@
--ch-13: #ffd8b5;
--ch-14: #eaeef2;
--ch-15: #57606a;
--ch-16: var(--colors-scale1);
// --ch-16: hsl(var(--foreground-lighter));
--ch-16: #eeeeee;
--ch-17: #add6ff;
--ch-18: #1a85ff;
--ch-19: #fdff0033;
+2 -2
View File
@@ -28,8 +28,8 @@ module.exports = {
brand12: 'hsla(153, 60%, 95%, 1)',
},
contrast: {
'brand-hiContrast': 'var(--colors-brand-9)',
'brand-loContrast': 'var(--colors-brand-4)',
'brand-hiContrast': 'hsl(var(--brand-default))',
'brand-loContrast': 'hsl(var(--brand-300))',
},
scale: {
scale1: 'var(--colors-slate1)',
+2 -2
View File
@@ -216,12 +216,12 @@ const uiConfig = ui({
fontWeight: '400',
color: 'var(--colors-scale12)',
textDecorationLine: 'underline',
textDecorationColor: 'var(--colors-brand7)',
textDecorationColor: 'hsl(var(--brand-400))',
textDecorationThickness: '1px',
textUnderlineOffset: '4px',
},
'a:hover': {
textDecorationColor: 'var(--colors-brand9)',
textDecorationColor: 'hsl(var(--brand-default))',
},
figcaption: {
color: 'var(--colors-scale9)',
+2 -2
View File
@@ -26,7 +26,7 @@ const excludedRadixColors = [
// generates fixed scales
// based on the root/light mode version
const fixedOptions = ['scale', 'scaleA', 'brand']
const fixedOptions = ['scale', 'scaleA']
function radixColorKeys() {
let keys = Object.keys(radixUiColors)
@@ -51,7 +51,7 @@ function radixColorKeys() {
}
function generateColorClasses() {
const brandColors = ['brand', 'scale', 'scaleA']
const brandColors = ['scale', 'scaleA']
const colors = [...radixColorKeys(), ...brandColors]
let mappedColors = {}
-11
View File
@@ -204,17 +204,6 @@ export const pricing: Pricing = {
},
usage_based: false,
},
{
title: 'Supabase Auth emails',
tooltips: { main: 'Rate limits do not apply to Custom SMTP' },
plans: {
free: '30 / hour',
pro: '100 / hour',
team: '100 / hour',
enterprise: 'Contact Us',
},
usage_based: false,
},
{
title: 'Single Sign-On (SAML 2.0)',
plans: {
+1 -1
View File
@@ -1,6 +1,6 @@
/**
* Do not edit directly
* Generated on Mon, 17 Jul 2023 15:59:23 GMT
* Generated on Sun, 30 Jul 2023 09:03:47 GMT
*/
:root {
+6 -4
View File
@@ -1,13 +1,15 @@
/**
* Do not edit directly
* Generated on Mon, 17 Jul 2023 15:59:23 GMT
* Generated on Sun, 30 Jul 2023 09:03:47 GMT
*/
.dark {
--brand-default: 152.9deg 60% 52.9%;
--brand-400: 153.6deg 41% 12%;
--brand-300: 152.7deg 48.5% 26.7%;
--brand-200: 148.5deg 43.5% 82%;
--brand-600: 153deg 59.5% 70%;
--brand-500: 153.5deg 61.8% 21.6%;
--brand-400: 153.3deg 65.2% 13.5%;
--brand-300: 153.8deg 69.6% 9%;
--brand-200: 152.5deg 75% 6.3%;
--warning-default: 38.9deg 100% 57.1%;
--warning-600: 38.9deg 89.8% 49.8%;
--warning-500: 34.8deg 90.9% 21.6%;
+7 -5
View File
@@ -1,13 +1,15 @@
/**
* Do not edit directly
* Generated on Mon, 17 Jul 2023 15:59:23 GMT
* Generated on Sun, 30 Jul 2023 09:03:47 GMT
*/
.light {
--brand-primary: 152.9deg 60% 52.9%;
--brand-400: 153.7deg 68.7% 83.7%;
--brand-300: 153deg 46% 65.9%;
--brand-200: 148.5deg 43.5% 82%;
--brand-default: 152.9deg 60% 52.9%;
--brand-600: 153.2deg 49.7% 33.5%;
--brand-500: 148.7deg 42.7% 69.2%;
--brand-400: 149.1deg 59.3% 88.4%;
--brand-300: 148.6deg 77.8% 94.7%;
--brand-200: 156deg 71.4% 98.6%;
--warning-default: 38.9deg 100% 57.1%;
--warning-600: 30.2deg 100% 33.9%;
--warning-500: 36.3deg 85.7% 67.1%;
+11 -3
View File
@@ -529,15 +529,23 @@ module.exports = {
},
"brand-200": {
cssVariable: "var(--brand-200)",
value: "hsl(148.5, 43.5%, 82%)"
value: "hsl(152.5, 75%, 6.3%)"
},
"brand-300": {
cssVariable: "var(--brand-300)",
value: "hsl(152.70000000000005, 48.5%, 26.7%)"
value: "hsl(153.79999999999995, 69.6%, 9%)"
},
"brand-400": {
cssVariable: "var(--brand-400)",
value: "hsl(153.60000000000002, 41%, 12%)"
value: "hsl(153.29999999999995, 65.2%, 13.5%)"
},
"brand-500": {
cssVariable: "var(--brand-500)",
value: "hsl(153.5, 61.8%, 21.6%)"
},
"brand-600": {
cssVariable: "var(--brand-600)",
value: "hsl(153, 59.5%, 70%)"
},
"brand-DEFAULT": {
cssVariable: "var(--brand-default)",
@@ -21,7 +21,7 @@ export const Admonition = ({
: type === 'info'
? 'bg-scale-500 border-scale-800'
: type === 'tip'
? 'bg-brand-300 border-brand-800'
? 'bg-brand-300 border-brand-300'
: type === 'caution'
? 'bg-yellow-400 border-yellow-800'
: type === 'danger'
@@ -1,5 +1,5 @@
/* .sbui-badge {
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-500 bg-opacity-10 text-brand-800;
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-500 bg-opacity-10 text-brand-300;
}
.sbui-badge--large {
@@ -10,11 +10,11 @@
.sbui-breadcrumb--item {
@apply text-gray-500 hover:text-gray-600;
@apply cursor-pointer;
@apply dark:text-dark-200 dark:hover:text-brand-700;
@apply dark:text-dark-200 dark:hover:text-brand-400;
}
.sbui-breadcrumb--item__active {
@apply text-brand-700 dark:text-brand-700;
@apply text-brand-400 dark:text-brand-400;
}
.sbui-breadcrumb--separator {
@@ -50,8 +50,8 @@
Button varients
*/
/* .sbui-btn-primary {
@apply text-white bg-brand-800 hover:bg-brand-600;
@apply dark:hover:bg-brand-900;
@apply text-white bg-brand-300 hover:bg-brand-600;
@apply dark:hover:bg-brand;
} */
.dark .sbui-btn-primary {
text-shadow: 0px 0px 4px rgba(38 111 78 / 50%);
@@ -87,7 +87,7 @@
@apply dark:text-white dark:border-dark-400 dark:hover:text-white dark:hover:border-white;
} */
/* .sbui-btn-link {
@apply bg-transparent text-brand-800 border-none hover:bg-brand-900 hover:bg-opacity-25;
@apply bg-transparent text-brand-300 border-none hover:bg-brand hover:bg-opacity-25;
box-shadow: none;
} */
/* .sbui-btn-text {
Loaded 100 of 210 files, more files were not shown because too many files have changed in this diff. Show more