mirror of
https://github.com/supabase/supabase.git
synced 2026-10-12 21:05:06 +03:00
1015 lines
41 KiB
TypeScript
1015 lines
41 KiB
TypeScript
import Head from 'next/head'
|
|
import { useRouter } from 'next/router'
|
|
import { useEffect, useRef, useState } from 'react'
|
|
import Container from 'components/Container'
|
|
import Layout from 'components/Layout'
|
|
import CountUp from 'components/CountUp'
|
|
import FlyOut from 'components/UI/FlyOut'
|
|
import CTABanner from 'components/CTABanner/index'
|
|
import { APP_NAME, DESCRIPTION } from 'lib/constants'
|
|
import { AlphaNumbers, IntroductionSegments, PerformanceComparisonData } from 'data/BetaPage'
|
|
import { render } from 'react-dom'
|
|
import Link from 'next/link'
|
|
import { addBasePath } from 'next/dist/next-server/lib/router/router'
|
|
|
|
const site_title = `${APP_NAME} | We are now in Beta`
|
|
|
|
// Dark text: text-dark-400
|
|
// Light text: text-dark-300
|
|
|
|
const NavFlyOutMenu = (props: any) => {
|
|
const { scrollTo } = props
|
|
const segments = IntroductionSegments.map((segment: any) => segment.chapters)
|
|
|
|
return (
|
|
<>
|
|
<div className="col-span-12 grid grid-cols-12 items-center border-dark-300 dark:border-dark-400 sm:border-r border-b border-dashed">
|
|
{segments.flat().map((segment: any) => (
|
|
<div
|
|
key={segment.key}
|
|
onClick={() => scrollTo(segment.key)}
|
|
className={`
|
|
col-span-12 lg:col-span-4 px-4 lg:px-6 py-4 lg:py-10 text-dark-300 dark:text-dark-400 cursor-pointer bg-white dark:bg-dark-600
|
|
hover:bg-dark-100 dark:hover:bg-dark-500 border-dark-300 dark:border-dark-400 border-t sm:border-l border-dashed`}
|
|
>
|
|
<p className="flex items-center text-black dark:text-white">
|
|
<span className="font-mono text-xs text-dark-300 dark:text-dark-400 mr-2">
|
|
0{segment.no}
|
|
</span>
|
|
<span>{segment.name}</span>
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</>
|
|
)
|
|
}
|
|
|
|
const VideoShot = (props: any) => {
|
|
const { src } = props
|
|
return (
|
|
<div className="p-2 rounded-xl bg-gradient-to-r from-green-400 via-violet-500 to-blue-500">
|
|
<div className="shadow-lg rounded-md" style={{ height: 'fit-content' }}>
|
|
<div className="w-full rounded-t-md h-5 bg-dark-400 flex items-center justify-start px-2">
|
|
<div className="h-2 w-2 mr-2 rounded-full bg-dark-500" />
|
|
<div className="h-2 w-2 mr-2 rounded-full bg-dark-500" />
|
|
<div className="h-2 w-2 mr-2 rounded-full bg-dark-500" />
|
|
</div>
|
|
<video className="rounded-b-md" src={src} autoPlay loop muted playsInline>
|
|
Your browser does not support the video tag
|
|
</video>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const HamburgerMenu = (props: any) => {
|
|
const { openMenu } = props
|
|
return (
|
|
<div className="cursor-pointer" onClick={openMenu}>
|
|
<svg
|
|
viewBox="0 0 24 24"
|
|
width="24"
|
|
height="24"
|
|
stroke="white"
|
|
strokeWidth="2"
|
|
fill="none"
|
|
strokeLinecap="round"
|
|
strokeLinejoin="round"
|
|
>
|
|
<line x1="3" y1="12" x2="21" y2="12" />
|
|
<line x1="3" y1="6" x2="21" y2="6" />
|
|
<line x1="3" y1="18" x2="21" y2="18" />
|
|
</svg>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const SectionHeader = (props: any) => {
|
|
const { sectionNumber, header } = props
|
|
return (
|
|
<div className="col-span-12">
|
|
<span className="block font-mono text-3xl text-dark-300 dark:text-dark-400 mb-3">
|
|
0{sectionNumber}
|
|
</span>
|
|
<h3 className="text-black dark:text-white text-6xl">{header}</h3>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const Hero = () => {
|
|
const { basePath } = useRouter()
|
|
return (
|
|
<div
|
|
style={{
|
|
backgroundImage: `url('${basePath}/images/beta-hero.png')`,
|
|
backgroundSize: '65%',
|
|
backgroundPosition: '120% 50%',
|
|
}}
|
|
className="w-screen py-16 lg:py-36 bg-dark-800 bg-no-repeat"
|
|
>
|
|
<div className="container mx-auto px-8 lg:px-28 py-20 h-full grid grid-cols-12 gap-4 items-center text-dark-300">
|
|
<div className="col-span-12 md:col-span-9 lg:col-span-8 xl:col-span-6 text-white">
|
|
<p className="mb-10 text-4xl">Supabase is an opensource Firebase alternative.</p>
|
|
<p className="text-2xl">
|
|
Today, we're moving to <span className="text-brand-700">Beta</span>
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const Introduction = () => {
|
|
return (
|
|
<div className="bg-dark-900">
|
|
<div className="container mx-auto px-8 lg:px-28 py-20 grid grid-cols-12 gap-4 text-dark-300">
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-8">
|
|
<p>
|
|
<span className="text-2xl block text-white">
|
|
After the launch of our{' '}
|
|
<a
|
|
href="https://news.ycombinator.com/item?id=23319901"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
Alpha
|
|
</a>{' '}
|
|
Program in June,
|
|
</span>
|
|
</p>
|
|
</div>
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-6 text-base mb-20">
|
|
<p>
|
|
we've been fortunate to work with thousands of early adopters on improving both our Open
|
|
Source, and Hosted offerings. Companies like{' '}
|
|
<a
|
|
href="/blog/2020/12/02/case-study-xendit"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
Xendit
|
|
</a>
|
|
,{' '}
|
|
<a
|
|
href="/blog/2020/12/02/case-study-monitoro"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
Monitoro
|
|
</a>
|
|
, and{' '}
|
|
<a
|
|
href="/blog/2020/12/02/case-study-tayfa"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
TAYFA
|
|
</a>{' '}
|
|
are using Supabase to ship more products, faster.
|
|
</p>
|
|
</div>
|
|
|
|
<div className="col-span-12 text-base mb-10">
|
|
<p className="w-60 pb-2 border-b-2 border-dark-200 dark:border-dark-400">
|
|
Alpha Program in Numbers
|
|
</p>
|
|
</div>
|
|
|
|
<div
|
|
id="alphaNumbers"
|
|
className="col-span-12 grid grid-cols-12 gap-y-12 lg:gap-y-20 mb-20 gap-x-3 sm:gap-x-0"
|
|
>
|
|
{AlphaNumbers.map((stat: any, idx: number) => (
|
|
<div
|
|
key={`stat_${idx}`}
|
|
className="col-span-6 sm:col-span-4 grid grid-cols-8 sm:grid-cols-12 gap-x-1 md:gap-x-0 xl:gap-x-6 items-center"
|
|
>
|
|
<div className="col-span-4 sm:col-span-4 md:col-span-3 xl:col-span-2">
|
|
<div className="w-12 h-12 rounded-md bg-dark-700 flex items-center justify-center bg-gray-900 dark:bg-white">
|
|
{stat.icon}
|
|
</div>
|
|
</div>
|
|
<div className="col-span-7 sm-col-span-8 md:col-span-9 xl:col-span-10">
|
|
<p className="text-5xl lg:text-6xl">
|
|
<CountUp triggerAnimOnScroll={true} referenceElId="alphaNumbers">
|
|
{stat.value}
|
|
</CountUp>
|
|
{stat.unit && <span className="text-2xl ml-1">{stat.unit}</span>}
|
|
</p>
|
|
</div>
|
|
<div className="col-span-12 sm:col-span-9 md:col-span-10 col-start-0 sm:col-start-5 md:col-start-4 xl:col-start-3">
|
|
<p className="text-xs lg:text-base text-dark-300 dark:text-dark-400">{stat.name}</p>
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const TableOfContents = (props: any) => {
|
|
const { scrollTo } = props
|
|
return (
|
|
<div className="bg-gray-50 dark:bg-dark-700 text-dark-400 dark:text-dark-200">
|
|
<div className="container mx-auto px-8 lg:px-28 py-20 grid grid-cols-12 gap-4">
|
|
<div className="col-span-12 text-base mb-10">
|
|
<p className="text-2xl text-black dark:text-white">
|
|
Supabase <span className="text-brand-600 dark:text-brand-700">Beta</span> is starting
|
|
now.
|
|
</p>
|
|
</div>
|
|
<div className="col-span-12 grid grid-cols-12 gap-y-10">
|
|
{IntroductionSegments.map((segment: any, segmentIdx: number) => (
|
|
<div key={`introSegment_${segmentIdx}`} className="col-span-12 grid grid-cols-12">
|
|
<div className="col-span-12 mb-10 sm:col-span-5 xl:col-span-4 sm:mb-0">
|
|
<p>{segment.description}</p>
|
|
</div>
|
|
<div className="hidden sm:block sm:col-span-1 xl:col-span-2" />
|
|
<div className="col-span-12 sm:col-span-6 flex flex-col">
|
|
{segment.chapters.map((chapter: any, idx: number) => (
|
|
<div
|
|
key={`section_select_${idx}`}
|
|
className="flex items-center mb-5 cursor-pointer"
|
|
onClick={() => scrollTo(chapter.key)}
|
|
>
|
|
<p className="font-mono text-xs text-dark-300 dark:text-dark-400">{`0${chapter.no}`}</p>
|
|
<p className="ml-4 transition text-base border-b border-gray-400 hover:text-black dark:hover:text-white">
|
|
{chapter.name}
|
|
</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
))}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const Performance = () => {
|
|
const Bar = (props: any) => {
|
|
const { color, finalPercentage, duration = 2000 } = props
|
|
const countTo = parseInt(finalPercentage, 10)
|
|
const [count, setCount] = useState<number>(0)
|
|
const [animTriggered, setAnimTriggered] = useState<boolean>(false)
|
|
|
|
const easeOutQuad = (t: number) => t * (2 - t)
|
|
const frameDuration = 1000 / 60
|
|
|
|
useEffect(() => {
|
|
let frame = 0
|
|
const totalFrames = Math.round(duration / frameDuration)
|
|
|
|
async function handleScroll() {
|
|
const reference = document.getElementById('performanceCharts')
|
|
if (reference && !animTriggered) {
|
|
const yOffset = reference.getBoundingClientRect().top - window.innerHeight + 20
|
|
if (yOffset <= 0) {
|
|
setAnimTriggered(true)
|
|
setCount(0)
|
|
const counter = setInterval(() => {
|
|
frame++
|
|
const progress = easeOutQuad(frame / totalFrames)
|
|
setCount(countTo * progress)
|
|
|
|
if (frame === totalFrames) clearInterval(counter)
|
|
}, frameDuration)
|
|
}
|
|
}
|
|
}
|
|
|
|
window.addEventListener('scroll', handleScroll, { passive: true })
|
|
return () => window.removeEventListener('scroll', handleScroll)
|
|
}, [animTriggered])
|
|
|
|
return <div className={`${color} rounded-full h-3`} style={{ width: `${count.toFixed(2)}%` }} />
|
|
}
|
|
|
|
const ComparisonChart = () => {
|
|
const maxValue = 1600
|
|
return (
|
|
<div id="performanceCharts">
|
|
{PerformanceComparisonData.map((metric: any) => {
|
|
const multiplier = (metric.stats[0].value / metric.stats[1].value).toFixed(1)
|
|
return (
|
|
<div key={`${metric.key}`} className="mb-10 text-dark-400 dark:text-dark-300">
|
|
<p className="sm:w-36 pb-2 mb-4">{metric.title}</p>
|
|
<div className="flex flex-col sm:flex-row sm:items-center">
|
|
<div className="w-full sm:w-5/6">
|
|
{metric.stats.map((stat: any, idx: number) => (
|
|
<div key={`metric_${metric.key}_${idx}`} className="flex items-center">
|
|
<p className="w-20 lg:w-24 border-r py-2 pr-4 mr-4 text-left sm:text-right">
|
|
{stat.name}
|
|
</p>
|
|
<Bar
|
|
color={
|
|
stat.name === 'Supabase'
|
|
? 'bg-brand-600 dark:bg-brand-700'
|
|
: 'bg-dark-300 dark:bg-dark-400'
|
|
}
|
|
finalPercentage={Math.ceil((stat.value / maxValue) * 100)}
|
|
/>
|
|
<p className="ml-2">{stat.value}/s</p>
|
|
</div>
|
|
))}
|
|
</div>
|
|
<div className="text-left sm:w-1/6 sm:text-right flex flex-col">
|
|
<p className="text-6xl text-dark-700 dark:text-dark-100">{multiplier}x</p>
|
|
<p className="text-sm -mt-2">more {metric.key}s per second</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
})}
|
|
</div>
|
|
)
|
|
}
|
|
|
|
return (
|
|
<div id="performance" className="bg-white dark:bg-dark-800">
|
|
<div className="container mx-auto px-8 lg:px-28 py-20 grid grid-cols-12 gap-y-10 text-dark-400 dark:text-dark-300">
|
|
<SectionHeader sectionNumber={1} header="Performance" />
|
|
|
|
<div className="col-span-12 grid grid-cols-12 gap-x-2 lg:gap-x-8 mb-10 items-center">
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-7 text-base">
|
|
<p className="mb-10">
|
|
We started Supabase to give developers a web-ready database that is delightful to use,
|
|
without sacrificing speed and scale. Postgres makes this possible, handling massive
|
|
amounts of data without sacrificing read and write speed.
|
|
</p>
|
|
<p className="mb-10">
|
|
We tweaked our stack obsessively during our Alpha program to tease out superior
|
|
performance. We chose the hyper-scalable{' '}
|
|
<a
|
|
href="https://elixir-lang.org/"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
Elixir
|
|
</a>{' '}
|
|
to handle our{' '}
|
|
<a
|
|
href="https://github.com/supabase/realtime"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
Realtime engine
|
|
</a>
|
|
, and have supported the{' '}
|
|
<a
|
|
href="https://postgrest.org/en/v7.0.0/"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
PostgREST
|
|
</a>{' '}
|
|
team while they improved the performance of their auto-generated CRUD APIs.
|
|
</p>
|
|
<p className="text-dark-400 dark:text-dark-300">
|
|
We're publishing the results of our benchmarks here and we'll continue to seek gains
|
|
throughout our Beta program and beyond. Our{' '}
|
|
<a
|
|
href="https://github.com/supabase/benchmarks/"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
benchmarks
|
|
</a>{' '}
|
|
are open source so that the community can better our methodologies and identify areas
|
|
of improvement for the tools which we support at Supabase.
|
|
</p>
|
|
</div>
|
|
<div className="col-span-12 mt-10 mb-10">
|
|
<ComparisonChart />
|
|
</div>
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-7 text-base">
|
|
<p className="mb-10">
|
|
Benchmarks were run from a neutral host (Digital Ocean Droplet 4 GB Memory / 80 GB
|
|
Disk / SGP1 - Ubuntu 20.04 (LTS) x64) against a table/collection pre-populated with 1
|
|
million rows. The Supabase database and API used are each running on AWS EC2 t3a.micro
|
|
instances.
|
|
</p>
|
|
<p className="mb-10">
|
|
Supabase is available in 7 different geographic regions. We're adding more regions as
|
|
we build up multi-cloud support. Soon we'll offer read-replicas to scale your database
|
|
right to the edge - reducing latency and giving your users a better experience.
|
|
</p>
|
|
<p>
|
|
One of our key metrics at Supabase is "Time to Value". How fast can a user go from
|
|
sign up, to making their first API request? How fast can they go from development to
|
|
production? We've built several case studies on our blog, demonstrating how Supabase
|
|
enables them to build and scale their product in as little time as possible.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const Security = () => {
|
|
return (
|
|
<div id="security" className="bg-gray-50 dark:bg-dark-700">
|
|
<div className="container mx-auto px-8 lg:px-28 py-20 grid grid-cols-12 gap-y-10 text-dark-400 dark:text-dark-200">
|
|
<SectionHeader sectionNumber={2} header="Security" />
|
|
|
|
<div className="col-span-12 grid grid-cols-12 gap-x-2 lg:gap-x-8">
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-7 text-base">
|
|
<p className="mb-10">
|
|
As an infrastructure provider, security has been a priority from day one. While we had
|
|
to resolve brute force attacks on our customers' databases, we internally run pen
|
|
tests to ensure that our own systems are air-tight.
|
|
</p>
|
|
<p className="mb-10">
|
|
Approaching the launch of our Beta period, we worked with security advisors and
|
|
specialists globally to enforce new measures and processes:
|
|
</p>
|
|
<ul className="list-disc list-outside ml-6">
|
|
<li className="mb-5">
|
|
Employed DigitalXRAID to run a full Pen Test on both our internal and customer
|
|
infrastructure. We immediately patched one medium priority issue and are currently
|
|
in the process of resolving the minor and informational issues.
|
|
</li>
|
|
<li className="mb-5">
|
|
Published a disclosure policy so that ethical hackers can help us find
|
|
vulnerabilities in our systems. We've received reports from this initiative already,
|
|
and we'll continue to formalise our bounty program throughout the Beta.
|
|
</li>
|
|
<li className="mb-5">
|
|
We now run an ongoing internal Capture the Flag competition, where team members are
|
|
challenged to breach various components of our systems.
|
|
</li>
|
|
<li className="mb-5">
|
|
Adopted the{' '}
|
|
<a
|
|
href="https://snyk.io/"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
Snyk
|
|
</a>{' '}
|
|
dependency monitor as part of our SSDLC on several key component of our system, to
|
|
help locate potential vulnerabilities in third party Open Source dependencies.
|
|
</li>
|
|
<li>
|
|
Worked with several of the open source tools that we use to improve their own
|
|
security. For example, PostgREST{' '}
|
|
<a
|
|
href="https://github.com/PostgREST/postgrest/pull/1600#issuecomment-735257952"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
now uses
|
|
</a>{' '}
|
|
"parametrized" inputs, where they were previously "escaped".
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const Reliability = () => {
|
|
const { basePath } = useRouter()
|
|
return (
|
|
<div id="reliability" className="bg-white dark:bg-dark-800">
|
|
<div className="container mx-auto px-8 lg:px-28 py-12 grid grid-cols-12 gap-y-10 text-dark-400 dark:text-dark-300 ">
|
|
<SectionHeader sectionNumber={3} header="Reliability" />
|
|
|
|
<div className="col-span-12 grid grid-cols-12 gap-x-2 lg:gap-x-8 mb-10">
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-7 text-base">
|
|
<p className="mb-5">
|
|
During Alpha we experienced 2 availability incidents, neither affecting customer
|
|
access to their data. These were:
|
|
</p>
|
|
<ul className="list-disc list-outside ml-6 mb-10">
|
|
<li className="mb-5">
|
|
A third-party CDN API outage. As a result, subdomains were not created for new
|
|
projects.
|
|
</li>
|
|
<li>
|
|
Cloud resource limits. We maxed out our Virtual Machines limits in some popular
|
|
regions, and we hit the maximum number of subdomains allowed by our DNS provider.
|
|
These limitations are artificial and our cloud providers quickly lifted them.
|
|
</li>
|
|
</ul>
|
|
<p className="mb-10">
|
|
Availability is one of our highest priority goals. We're continuing efforts to
|
|
maximize uptime and ensure user data is backed up in a secure and encrypted location.
|
|
</p>
|
|
<p className="mb-10">
|
|
We're launching{' '}
|
|
<a
|
|
href="https://status.supabase.io"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
https://status.supabase.io
|
|
</a>{' '}
|
|
to keep track of uptime across all of our services and critical infrastructure.
|
|
</p>
|
|
<div className="mb-10">
|
|
<VideoShot src={`${basePath}/videos/statusPage.mp4`} />
|
|
</div>
|
|
<p>
|
|
For our Alpha & Beta Users we take free, encrypted daily database backups up to 20GB.
|
|
They are available to download at any time via the dashboard.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const NewFeaturesAndIntegrations = () => {
|
|
const { basePath } = useRouter()
|
|
return (
|
|
<div id="newFeaturesAndIntegrations" className="bg-gray-50 dark:bg-dark-700">
|
|
<div className="container mx-auto px-8 lg:px-28 py-20 grid grid-cols-12 gap-y-10 text-dark-400 dark:text-dark-200">
|
|
<SectionHeader sectionNumber={4} header="New Features & Integrations" />
|
|
|
|
<div className="col-span-12 grid grid-cols-12 gap-x-2 lg:gap-x-8 mb-10">
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-7 text-base">
|
|
<p className="mb-5">
|
|
If you're new to Supabase, here's a few of the things you get when you choose us as
|
|
your backend.
|
|
</p>
|
|
<ul className="">
|
|
<li className="mb-10">
|
|
<p className="w-20 pb-2 mb-2 border-b-2 border-dark-200 dark:border-dark-400">
|
|
Auth
|
|
</p>
|
|
<p className="mb-5">
|
|
If you're new to Supabase, here's a few of the things you get when you choose us
|
|
as your backend. We provide{' '}
|
|
<a
|
|
href="/docs/client/auth-signup"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
JavaScript
|
|
</a>{' '}
|
|
(and{' '}
|
|
<a
|
|
href="/docs/gotrue/server/about#endpoints"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
HTTP
|
|
</a>
|
|
) APIs for your users to sign in and out of your application. You can define the
|
|
rows in your database that logged-in users can access (e.g. only his or her
|
|
shopping cart). We even provide account confirmation, recovery, and invite email
|
|
templates which you can customize on the dashboard, and we handle the
|
|
transactional emails for you. We support passwordless links, and we offer several
|
|
OAuth providers including Google, GitHub, with more on the way.
|
|
</p>
|
|
<VideoShot src={`${basePath}/videos/tabAuthRules.mp4`} />
|
|
</li>
|
|
<li className="mb-10">
|
|
<p className="w-20 pb-2 mb-2 border-b-2 border-dark-200 dark:border-dark-400">
|
|
Realtime
|
|
</p>
|
|
<p>
|
|
You can{' '}
|
|
<a
|
|
href="/docs/guides/client-libraries#realtime-changes"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
subscribe to changes in your database
|
|
</a>{' '}
|
|
over websockets, receiving your data in realtime. Companies are using Supabase to
|
|
build chat applications, trigger notifications, and pipe data to analytics
|
|
dashboards whenever it changes in their database.
|
|
</p>
|
|
</li>
|
|
<li className="mb-10">
|
|
<p className="w-24 pb-2 mb-2 border-b-2 border-dark-200 dark:border-dark-400">
|
|
CRUD API
|
|
</p>
|
|
<p>
|
|
You can use your database immediately, without an ORM or an API backend. We
|
|
support GraphQL-like{' '}
|
|
<a
|
|
href="/docs/client/select#query-foreign-tables"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
querying from multiple tables
|
|
</a>{' '}
|
|
in a single request, and you can even{' '}
|
|
<a
|
|
href="/docs/client/rpc"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
invoke complex functions
|
|
</a>
|
|
.
|
|
</p>
|
|
</li>
|
|
<li className="mb-10">
|
|
<p className="w-44 pb-2 mb-2 border-b-2 border-dark-200 dark:border-dark-400">
|
|
Quickstart Templates
|
|
</p>
|
|
<p>
|
|
If you're unfamiliar with SQL, we provide a set of Quickstart Templates to get you
|
|
building quickly. Very soon you'll be able to deploy entire apps (front and back
|
|
end) with just the click of a button.
|
|
</p>
|
|
</li>
|
|
<li className="mb-10">
|
|
<p className="w-24 pb-2 mb-2 border-b-2 border-dark-200 dark:border-dark-400">
|
|
Table View
|
|
</p>
|
|
<p className="mb-5">
|
|
View and edit your data like a spreadsheet from within the Supabase dashboard.
|
|
Build your schema, create complex relationships, and import and export to csv.
|
|
</p>
|
|
<VideoShot src={`${basePath}/videos/tabTableEditor.mp4`} />
|
|
</li>
|
|
<li>
|
|
<p className="w-24 pb-2 mb-2 border-b-2 border-dark-200 dark:border-dark-400">
|
|
SQL Editor
|
|
</p>
|
|
<p className="mb-5">
|
|
No need to install third party SQL tools, you can run queries directly from the
|
|
Supabase Dashboard.
|
|
</p>
|
|
<VideoShot src={`${basePath}/videos/tabSqlEditor.mp4`} />
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
const BetaPricing = () => (
|
|
<div id="betaPricing" className="bg-white dark:bg-dark-800">
|
|
<div className="container mx-auto px-8 lg:px-28 py-20 grid grid-cols-12 gap-y-10 text-dark-400 dark:text-dark-300">
|
|
<SectionHeader sectionNumber={5} header="Beta Pricing" />
|
|
|
|
<div className="col-span-12 grid grid-cols-12 gap-x-2 lg:gap-x-8 mb-10">
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-7 text-base">
|
|
<p className="mb-10">
|
|
We're working closely with many open source projects, infrastructure providers, and of
|
|
course our Alpha Users, to provide a predictable and sustainable pricing model.
|
|
</p>
|
|
<p className="mb-5">Our key aims going into this exercise were:</p>
|
|
<ul className="list-disc list-outside ml-6 mb-10">
|
|
<li className="mb-5">
|
|
To continue offering free Supabase instances for Students, Hobbyists, and Early
|
|
Adopters
|
|
</li>
|
|
<li className="mb-5">
|
|
To price based on <span className="italic">predictable</span> metrics (no shock bills
|
|
at the end of the month)
|
|
</li>
|
|
<li>
|
|
To grow with our users, providing a pricing model that supports their growth and allow
|
|
them to create value for their customers
|
|
</li>
|
|
</ul>
|
|
<p className="mb-10">
|
|
Whilst we're not yet ready to publish a standardized pricing model, we are committing to
|
|
the following initiatives:
|
|
</p>
|
|
<ul className="list-decimal list-outside ml-6 mb-10">
|
|
<li className="mb-5">
|
|
All Alpha Users will receive credits equivalent of 2 years of base tier usage. These
|
|
will automatically be credited to your account if you signed up prior to December
|
|
2020.
|
|
</li>
|
|
<li className="mb-5">
|
|
All Beta Users (new users from December 2020) will receive 1 year of base tier usage
|
|
for free.
|
|
</li>
|
|
<li className="mb-5">
|
|
University (and participating code school) Students will be eligible for 2 years of
|
|
base tier usage (Code Schools can contact{' '}
|
|
<a
|
|
href="mailto:rory@supabase.io"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
rory@supabase.io
|
|
</a>
|
|
)
|
|
</li>
|
|
<li>
|
|
Early stage startups participating in selected incubator programs can claim additional
|
|
credits which can be applied to products outside of the base tier.
|
|
</li>
|
|
</ul>
|
|
<p>
|
|
The Supabase Base Tier constitutes a Supabase Instance running in a single region, on 2
|
|
vCPUs, 1 GiB Memory, with 2 GB of storage, and daily backups.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
|
|
const OpenSource = () => (
|
|
<div id="openSource" className="bg-gray-50 dark:bg-dark-700">
|
|
<div className="container mx-auto px-8 lg:px-28 py-20 grid grid-cols-12 gap-y-10 text-dark-400 dark:text-dark-200">
|
|
<SectionHeader sectionNumber={6} header="Open Source" />
|
|
|
|
<div className="col-span-12 grid grid-cols-12 gap-x-2 lg:gap-x-8 mb-10">
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-7 text-base">
|
|
<p className="mb-10">
|
|
Great software is multi generational and stretches beyond any single company.
|
|
</p>
|
|
<p className="mb-10">
|
|
Supabase is a collection of many projects, and we rely on making contributors to help us
|
|
build and improve. Because of this, we aim to make open source more accessible and
|
|
attractive to anyone who wants to contribute.
|
|
</p>
|
|
<p className="mb-10">
|
|
Every dollar that is given to Supabase in{' '}
|
|
<a
|
|
href="https://github.com/sponsors/supabase/"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
sponsorship
|
|
</a>{' '}
|
|
will be funneled back to the community to support the next generation of Open Source
|
|
maintainers.
|
|
</p>
|
|
<p className="mb-10">
|
|
One of the biggest barriers to Open Source is knowing exactly how to get started. We're{' '}
|
|
<a
|
|
href="/blog/2020/12/02/supabase-striveschool"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
partnering with Strive School
|
|
</a>{' '}
|
|
to educate the next generation of programmers in Open Source - providing tutorials,
|
|
Founder Office Hours, and other free resources.
|
|
</p>
|
|
<p className="mb-10">
|
|
If you teach programming, and you're interested in offering OSS tuition to your
|
|
students, we're actively looking for more education partners. Email{' '}
|
|
<a
|
|
href="mailto:rory@supabase.io"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
rory@supabase.io
|
|
</a>{' '}
|
|
to find out more.
|
|
</p>
|
|
<p>
|
|
Come and get involved in{' '}
|
|
<a
|
|
href="https://github.com/supabase"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
our GitHub.
|
|
</a>{' '}
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
|
|
const FundingPartners = () => (
|
|
<div id="fundingPartners" className="bg-white dark:bg-dark-800">
|
|
<div className="container mx-auto px-8 lg:px-28 py-20 grid grid-cols-12 gap-y-10 text-dark-400 dark:text-dark-300">
|
|
<SectionHeader sectionNumber={7} header="Funding Partners" />
|
|
<div className="col-span-12 grid grid-cols-12 gap-x-2 lg:gap-x-8 mb-10">
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-7 text-base">
|
|
<p className="mb-10">
|
|
Building a platform that can offer all the amazing features of Firebase will take
|
|
resources - more than most open source tools. Ours will be a long journey and it will
|
|
require the help of many experienced engineers.
|
|
</p>
|
|
<p className="mb-10">
|
|
The partners we choose for this journey must be aligned with our ethos as an open source
|
|
company. In a few weeks we'll release the full details of our Seed round. Today, we're
|
|
happy to announce one key partner who needs no introduction: Mozilla.
|
|
</p>
|
|
<p className="mb-10">
|
|
Open source is at the very core of what Mozilla do - we're humbled and excited to work
|
|
with them.
|
|
</p>
|
|
<p>
|
|
Follow us on{' '}
|
|
<a
|
|
href="https://twitter.com/supabase_io"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
Twitter
|
|
</a>{' '}
|
|
and we'll let you know when we announce the details of the round.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
|
|
const ScalingOurTeam = () => (
|
|
<div id="scalingOurTeam" className="bg-gray-50 dark:bg-dark-700">
|
|
<div className="container mx-auto px-8 lg:px-28 py-20 grid grid-cols-12 gap-y-10 text-dark-400 dark:text-dark-200">
|
|
<SectionHeader sectionNumber={8} header="Scaling Our Team" />
|
|
|
|
<div className="col-span-12 grid grid-cols-12 gap-x-2 lg:gap-x-8 mb-10">
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-7 text-base">
|
|
<p className="mb-10">
|
|
We are extremely proud of our team. We're a mix of 11 engineers, from 8 different
|
|
countries. Half of the team are previous founders - collectively we've founded 15
|
|
companies, generating millions in revenue.
|
|
</p>
|
|
<p className="mb-10">
|
|
We're also passionate about tech and open source. We hire open source maintainers to
|
|
work full time on the products we use, and we spend every Friday dogfooding Supabase to
|
|
make it better.
|
|
</p>
|
|
<p>
|
|
We are hiring across multiple positions including PostgreSQL engineers, Cloud engineers,
|
|
SRE's, and Developer Advocates. We are a fully remote team, spanning 4 continents and 10
|
|
nationalities. If you are interested and think you can be a factor in the success of
|
|
Supabase, get in touch at{' '}
|
|
<a
|
|
href="mailto:work@supabase.io"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
work@supabase.io
|
|
</a>
|
|
.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
|
|
const WhatsNext = () => (
|
|
<div
|
|
id="whatsNext"
|
|
className="border-b-2 border-gray-50 bg-white dark:bg-dark-800 dark:border-dark-800"
|
|
>
|
|
<div className="container mx-auto px-8 lg:px-28 py-20 grid grid-cols-12 gap-y-10 text-dark-400 dark:text-dark-300">
|
|
<SectionHeader sectionNumber={9} header="What's Next" />
|
|
|
|
<div className="col-span-12 grid grid-cols-12 gap-x-2 lg:gap-x-8 mb-10">
|
|
<div className="col-span-12 sm:col-span-9 xl:col-span-7 text-base">
|
|
<p className="mb-5">
|
|
If you watch our repos you'll see that development never stops, we ship every day (and
|
|
night!). We're constantly improving Supabase based on user feedback. Alongside
|
|
performance, security, and reliability improvements, here are some new features we're
|
|
working on for 2021:
|
|
</p>
|
|
<ul className="list-disc list-outside ml-6 mb-10">
|
|
<li className="mb-5">Storage - Making blob storage easier than ever before</li>
|
|
<li className="mb-5">
|
|
Functions - write and deploy serverless functions that have access to your Supabase
|
|
context
|
|
</li>
|
|
<li className="mb-5">
|
|
Local Emulator - Making local development more accessible with a quick start CLI for
|
|
any environment
|
|
</li>
|
|
<li className="mb-5">
|
|
High Availability - Database and API replicas spread globally to serve a global user
|
|
base
|
|
</li>
|
|
<li className="mb-5">
|
|
Multicloud - Spread your Supabase instances across multiple datacenter providers to
|
|
protect against outages
|
|
</li>
|
|
<li className="mb-5">
|
|
Self Hosted - 'Bring your own cloud' is essential for some businesses, and so we're
|
|
working on easy-deploy tooling for customers with this requirement
|
|
</li>
|
|
<li>
|
|
More client libraries - members of the community are helping us build client libraries
|
|
for many different languages including TypeScript, Python, Dart, C#, and Rust. Come
|
|
and help us bring Supabase to your favourite language or framework.
|
|
</li>
|
|
</ul>
|
|
<p className="mb-10">
|
|
We depend on your feedback to continually improve Supabase. Email us at{' '}
|
|
<a
|
|
href="mailto:beta@supabase.io"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
beta@supabase.io
|
|
</a>{' '}
|
|
or join the{' '}
|
|
<a
|
|
href="https://github.com/supabase/supabase/discussions"
|
|
target="_blank"
|
|
className="text-brand-700 hover:text-brand-800"
|
|
>
|
|
discussion
|
|
</a>{' '}
|
|
on GitHub to let us know how we can help you build things faster.
|
|
</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
)
|
|
|
|
const Beta = () => {
|
|
const [menuOpen, setMenuOpen] = useState<boolean>(false)
|
|
const { basePath } = useRouter()
|
|
|
|
const references: any = {
|
|
performance: useRef<HTMLDivElement>(null),
|
|
security: useRef<HTMLDivElement>(null),
|
|
reliability: useRef<HTMLDivElement>(null),
|
|
features: useRef<HTMLDivElement>(null),
|
|
pricing: useRef<HTMLDivElement>(null),
|
|
openSource: useRef<HTMLDivElement>(null),
|
|
fundingPartners: useRef<HTMLDivElement>(null),
|
|
scaling: useRef<HTMLDivElement>(null),
|
|
next: useRef<HTMLDivElement>(null),
|
|
}
|
|
|
|
const scrollTo = (key: string) => {
|
|
if (references[key]) {
|
|
references[key].current.scrollIntoView({ behavior: 'smooth', block: 'start' })
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Layout hideHeader={true}>
|
|
<Head>
|
|
<title>{site_title}</title>
|
|
<meta name="og:title" property="og:title" content={site_title} />
|
|
<meta name="twitter:site" content={site_title} />
|
|
<meta name="twitter:text:title" content={site_title} />
|
|
</Head>
|
|
<Container>
|
|
<div className="relative shadow-lg py-5 px-5 xl:px-20 sticky inset-0 bg-dark-800 z-50 flex items-center justify-between">
|
|
<a href="/">
|
|
<img className="h-5" src={`${basePath}/images/logo-dark.png`} />
|
|
</a>
|
|
<HamburgerMenu openMenu={() => setMenuOpen(!menuOpen)} />
|
|
<FlyOut
|
|
open={menuOpen}
|
|
handleCancel={() => setMenuOpen(false)}
|
|
className="lg:col-span-1"
|
|
singleBgColor={true}
|
|
>
|
|
<NavFlyOutMenu scrollTo={scrollTo} />
|
|
</FlyOut>
|
|
</div>
|
|
<Hero />
|
|
<Introduction />
|
|
<TableOfContents scrollTo={scrollTo} />
|
|
<div ref={references['performance']}>
|
|
<Performance />
|
|
</div>
|
|
<div ref={references['security']}>
|
|
<Security />
|
|
</div>
|
|
<div ref={references['reliability']}>
|
|
<Reliability />
|
|
</div>
|
|
<div ref={references['features']}>
|
|
<NewFeaturesAndIntegrations />
|
|
</div>
|
|
<div ref={references['pricing']}>
|
|
<BetaPricing />
|
|
</div>
|
|
<div ref={references['openSource']}>
|
|
<OpenSource />
|
|
</div>
|
|
<div ref={references['fundingPartners']}>
|
|
<FundingPartners />
|
|
</div>
|
|
<div ref={references['scaling']}>
|
|
<ScalingOurTeam />
|
|
</div>
|
|
<div ref={references['next']}>
|
|
<WhatsNext />
|
|
</div>
|
|
<CTABanner darkerBg={true} />
|
|
</Container>
|
|
</Layout>
|
|
)
|
|
}
|
|
|
|
export default Beta
|