diff --git a/README.md b/README.md
index 70298a09e54..491a08b1009 100644
--- a/README.md
+++ b/README.md
@@ -67,7 +67,7 @@ You can also [self-host](https://supabase.com/docs/guides/hosting/overview) and
- [pg_graphql](http://github.com/supabase/pg_graphql/) a PostgreSQL extension that exposes a GraphQL API
- [Storage](https://github.com/supabase/storage-api) provides a RESTful interface for managing Files stored in S3, using Postgres to manage permissions.
- [postgres-meta](https://github.com/supabase/postgres-meta) is a RESTful API for managing your Postgres, allowing you to fetch tables, add roles, and run queries, etc.
-- [GoTrue](https://github.com/supabase/gotrue) is an JWT based API for managing users and issuing JWT tokens.
+- [GoTrue](https://github.com/supabase/gotrue) is a JWT based API for managing users and issuing JWT tokens.
- [Kong](https://github.com/Kong/kong) is a cloud-native API gateway.
#### Client libraries
diff --git a/apps/docs/components/MDX/storage_management.mdx b/apps/docs/components/MDX/storage_management.mdx
index ce28a1684c8..94aaa57a999 100644
--- a/apps/docs/components/MDX/storage_management.mdx
+++ b/apps/docs/components/MDX/storage_management.mdx
@@ -61,13 +61,16 @@ as $$
declare
status int;
content text;
+ avatar_name text;
begin
if coalesce(old.avatar_url, '') <> ''
and (tg_op = 'DELETE' or (old.avatar_url <> new.avatar_url)) then
+ -- extract avatar name
+ avatar_name := substring(old.avatar_url from '/([^\/]+)\?.*$');
select
into status, content
result.status, result.content
- from public.delete_avatar(old.avatar_url) as result;
+ from public.delete_avatar(avatar_name) as result;
if status <> 200 then
raise warning 'Could not delete avatar: % %', status, content;
end if;
diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
index 488226925ee..81f0c44369e 100644
--- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
+++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
@@ -495,22 +495,36 @@ export const auth = {
{ name: 'Managing User Data', url: '/guides/auth/managing-user-data' },
{ name: 'Multi-Factor Authentication', url: '/guides/auth/auth-mfa' },
{ name: 'Row Level Security', url: '/guides/auth/row-level-security' },
- { name: 'Server-side Rendering', url: '/guides/auth/server-side-rendering' },
],
},
{
- name: 'Auth Helpers',
+ name: 'Server-side Auth',
url: undefined,
items: [
{ name: 'Overview', url: '/guides/auth/auth-helpers' },
- { name: 'Auth UI', url: '/guides/auth/auth-helpers/auth-ui' },
- { name: 'Flutter Auth UI', url: '/guides/auth/auth-helpers/flutter-auth-ui' },
{
name: 'Next.js',
url: '/guides/auth/auth-helpers/nextjs',
},
{ name: 'Remix', url: '/guides/auth/auth-helpers/remix' },
{ name: 'SvelteKit', url: '/guides/auth/auth-helpers/sveltekit' },
+ { name: 'Server-side Rendering', url: '/guides/auth/server-side-rendering' },
+ {
+ name: 'Email Auth with PKCE flow for SSR',
+ url: '/guides/auth/server-side/email-based-auth-with-pkce-flow-for-ssr',
+ },
+ {
+ name: 'OAuth with PKCE flow for SSR',
+ url: '/guides/auth/server-side/oauth-with-pkce-flow-for-ssr',
+ },
+ ],
+ },
+ {
+ name: 'Auth UI',
+ url: undefined,
+ items: [
+ { name: 'Auth UI', url: '/guides/auth/auth-helpers/auth-ui' },
+ { name: 'Flutter Auth UI', url: '/guides/auth/auth-helpers/flutter-auth-ui' },
],
},
{
diff --git a/apps/docs/layouts/SiteLayout.tsx b/apps/docs/layouts/SiteLayout.tsx
index 94cd0ae0631..1b0f0a75df1 100644
--- a/apps/docs/layouts/SiteLayout.tsx
+++ b/apps/docs/layouts/SiteLayout.tsx
@@ -244,7 +244,7 @@ const Container = memo(function Container(props) {
className={[
// 'overflow-x-auto',
'w-full h-screen transition-all ease-out',
- 'absolute lg:relative',
+ // 'absolute lg:relative',
mobileMenuOpen
? '!w-auto ml-[75%] sm:ml-[50%] md:ml-[33%] overflow-hidden'
: 'overflow-auto',
diff --git a/apps/docs/pages/guides/auth/auth-helpers.mdx b/apps/docs/pages/guides/auth/auth-helpers.mdx
index 26b798b820b..041df7fa54b 100644
--- a/apps/docs/pages/guides/auth/auth-helpers.mdx
+++ b/apps/docs/pages/guides/auth/auth-helpers.mdx
@@ -2,31 +2,15 @@ import Layout from '~/layouts/DefaultGuideLayout'
export const meta = {
id: 'index',
- title: 'Auth Helpers Overview',
- description: 'A collection of framework-specific Auth utilities for working with Supabase.',
+ title: 'Server-Side Auth Overview',
+ description: 'Server-Side Auth guides and utilities for working with Supabase.',
sidebar_label: 'Overview',
}
-A collection of framework-specific Auth utilities for working with Supabase.
+Working with server-side frameworks is slightly different to client-side frameworks. In this section we cover the various ways of handling server-side authentication and demonstrate how to use the Supabase helper-libraries to make the process more seamless.
- {/* Auth UI */}
-
-
-
- {/* Flutter Auth UI */}
-
-
-
{/* Next.js */}
+
+
+
+```bash
+npm install @supabase/auth-helpers-nextjs @supabase/supabase-js
+```
+
+
+
+
+
+```bash
+npm install @supabase/auth-helpers-sveltekit @supabase/supabase-js
+```
+
+
+
+
+
+### Set environment variables
+
+Create an `.env.local` file in your project root directory. You can get your `SITE_URL` and `ANON_KEY` from inside of the [dashboard](https://supabase.com/dashboard/project/_/settings/api).
+
+
+
+
+
+```bash .env.local
+NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
+NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
+```
+
+
+
+
+```bash .env.local
+PUBLIC_SUPABASE_URL=your_supabase_project_url
+PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
+```
+
+
+
+
+### Setting up the Auth Helpers
+
+When using the Supabase client on the server, you must perform extra steps to ensure the user's auth session remains active. Since the user's session is tracked in a cookie, we need to read this cookie and update it if necessary.
+
+
+
+Next.js Server Components allow you to read a cookie but not write back to it. Middleware on the other hand allow you to both read and write to cookies.
+
+Next.js [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) runs immediately before each route is rendered. We'll use Middleware to refresh the user's session before loading Server Component routes.
+
+Create a new `middleware.js` file in the root of your project and populate with the following:
+
+```js middleware.js
+import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'
+import { NextResponse } from 'next/server'
+
+export async function middleware(req) {
+ const res = NextResponse.next()
+ const supabase = createMiddlewareClient({ req, res })
+ await supabase.auth.getSession()
+ return res
+}
+```
+
+
+
+Create a new `hooks.server.js` file in the root of your project and populate with the following:
+
+```ts src/hooks.server.js
+import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public'
+import { createSupabaseServerClient } from '@supabase/auth-helpers-sveltekit'
+import type { Handle } from '@sveltejs/kit'
+
+export const handle: Handle = async ({ event, resolve }) => {
+ event.locals.supabase = createSupabaseServerClient({
+ supabaseUrl: PUBLIC_SUPABASE_URL,
+ supabaseKey: PUBLIC_SUPABASE_ANON_KEY,
+ event,
+ })
+
+ event.locals.getSession = async () => {
+ const {
+ data: { session },
+ } = await event.locals.supabase.auth.getSession()
+ return session
+ }
+
+ return resolve(event, {
+ filterSerializedResponseHeaders(name) {
+ return name === 'content-range'
+ },
+ })
+}
+```
+
+
+
+
+### Create API endpoint for handling `token_hash`
+
+In order to use the updated email links we will need to setup a endpoint for verifying the `token_hash` along with the `type` to exchange `token_hash` for the user's `session`, which is set as a cookie for future requests made to Supabase.
+
+
+
+Create a new file at `app/auth/confirm/route.js` and populate with the following:
+
+```js app/auth/confirm/route.js
+import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
+import { cookies } from 'next/headers'
+import { NextResponse } from 'next/server'
+
+export async function GET(req) {
+ const { searchParams } = new URL(req.url)
+ const token_hash = searchParams.get('token_hash')
+ const type = searchParams.get('type')
+ const next = searchParams.get('next') ?? '/'
+
+ if (token_hash && type) {
+ const supabase = createRouteHandlerClient({ cookies })
+ const { error } = await supabase.auth.verifyOtp({ type, token_hash })
+ if (!error) {
+ return NextResponse.redirect(new URL(`/${next.slice(1)}`, req.url))
+ }
+ }
+
+ // return the user to an error page with some instructions
+ return NextResponse.redirect(new URL('/auth/auth-code-error', req.url))
+}
+```
+
+
+
+Create a new file at `src/routes/auth/confirm/+server.js` and populate with the following:
+
+```js src/routes/auth/confirm/+server.js
+import { redirect } from '@sveltejs/kit';
+
+export const GET = async (event) => {
+ const {
+ url,
+ locals: { supabase }
+ } = event;
+ const token_hash = url.searchParams.get('token') as string;
+ const type = url.searchParams.get('type') as string;
+ const next = url.searchParams.get('next') ?? '/';
+
+ if (token_hash && type) {
+ const { error } = await supabase.auth.verifyOtp({ token_hash, type });
+ if (!error) {
+ throw redirect(303, `/${next.slice(1)}`);
+ }
+ }
+
+ // return the user to an error page with some instructions
+ throw redirect(303, '/auth/auth-code-error');
+};
+```
+
+
+
+
+### Update email templates with URL for API endpoint
+
+Let's update the URL in our email templates to point to our new confirmation endpoint for the user to get confirmed.
+
+**Confirm signup template**
+
+```html
+
+```
+
+export const Page = ({ children }) =>
+
+export default Page
diff --git a/apps/docs/pages/guides/auth/server-side/oauth-with-pkce-flow-for-ssr.mdx b/apps/docs/pages/guides/auth/server-side/oauth-with-pkce-flow-for-ssr.mdx
new file mode 100644
index 00000000000..60f6fb53a1c
--- /dev/null
+++ b/apps/docs/pages/guides/auth/server-side/oauth-with-pkce-flow-for-ssr.mdx
@@ -0,0 +1,207 @@
+import Layout from '~/layouts/DefaultGuideLayout'
+
+export const meta = {
+ title: 'OAuth with PKCE flow for SSR',
+ description:
+ 'Learn how to configure OAuth authentication in your server-side rendering (SSR) application to work with the PKCE flow.',
+ subtitle:
+ 'Learn how to configure OAuth authentication in your server-side rendering (SSR) application to work with the PKCE flow.',
+}
+
+### Install Supabase Auth Helpers
+
+The Auth Helpers assist with user authentication within server-side rendering (SSR) frameworks.
+
+
+
+
+```bash
+npm install @supabase/auth-helpers-nextjs @supabase/supabase-js
+```
+
+
+
+
+```bash
+npm install @supabase/auth-helpers-sveltekit @supabase/supabase-js
+```
+
+
+
+
+### Set environment variables
+
+Create an `.env.local` file in your project root directory. You can get your `SITE_URL` and `ANON_KEY` from inside of the [dashboard](https://supabase.com/dashboard/project/_/settings/api).
+
+
+
+
+```bash .env.local
+NEXT_PUBLIC_SUPABASE_URL=your_supabase_project_url
+NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
+```
+
+
+
+
+```bash .env.local
+PUBLIC_SUPABASE_URL=your_supabase_project_url
+PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
+```
+
+
+
+
+### Setting up the Auth Helpers
+
+For SSR, the Supabase client requires extra steps to ensure the user's auth session remains active. Since the user's session is tracked in a cookie, we need to read this cookie and update it if necessary.
+
+
+
+Next.js Server Components allow you to read a cookie but not write back to it. Middleware on the other hand allow you to both read and write to cookies.
+
+Next.js [Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware) runs immediately before each route is rendered. We'll use Middleware to refresh the user's session before loading Server Component routes.
+
+Create a new `middleware.js` file in the root of your project and populate with the following:
+
+```js middleware.js
+import { createMiddlewareClient } from '@supabase/auth-helpers-nextjs'
+import { NextResponse } from 'next/server'
+
+export async function middleware(req) {
+ const res = NextResponse.next()
+ const supabase = createMiddlewareClient({ req, res })
+ await supabase.auth.getSession()
+ return res
+}
+```
+
+
+
+Create a new `hooks.server.js` file in the root of your project and populate with the following:
+
+```ts src/hooks.server.js
+import { PUBLIC_SUPABASE_URL, PUBLIC_SUPABASE_ANON_KEY } from '$env/static/public'
+import { createSupabaseServerClient } from '@supabase/auth-helpers-sveltekit'
+import type { Handle } from '@sveltejs/kit'
+
+export const handle: Handle = async ({ event, resolve }) => {
+ event.locals.supabase = createSupabaseServerClient({
+ supabaseUrl: PUBLIC_SUPABASE_URL,
+ supabaseKey: PUBLIC_SUPABASE_ANON_KEY,
+ event,
+ })
+
+ event.locals.getSession = async () => {
+ const {
+ data: { session },
+ } = await event.locals.supabase.auth.getSession()
+ return session
+ }
+
+ return resolve(event, {
+ filterSerializedResponseHeaders(name) {
+ return name === 'content-range'
+ },
+ })
+}
+```
+
+
+
+
+### Create API endpoint for handling the `code` exchange
+
+In order to use OAuth we will need to setup a endpoint for the `code` exchange, to exchange an auth `code` for the user's `session`, which is set as a cookie for future requests made to Supabase.
+
+
+
+Create a new file at `app/auth/callback/route.js` and populate with the following:
+
+```js app/auth/callback/route.js
+import { createRouteHandlerClient } from '@supabase/auth-helpers-nextjs'
+import { cookies } from 'next/headers'
+import { NextResponse } from 'next/server'
+
+export async function GET(req) {
+ const { searchParams } = new URL(req.url)
+ const code = searchParams.get('code')
+ const next = searchParams.get('next') ?? '/'
+
+ if (code) {
+ const supabase = createRouteHandlerClient({ cookies: () => cookies() })
+ const { error } = await supabase.auth.exchangeCodeForSession(code)
+ if (!error) {
+ return NextResponse.redirect(new URL(`/${next.slice(1)}`, req.url))
+ }
+ }
+
+ // return the user to an error page with instructions
+ return NextResponse.redirect(new URL('/auth/auth-code-error', req.url))
+}
+```
+
+
+
+Create a new file at `src/routes/auth/callback/+server.js` and populate with the following:
+
+```js src/routes/auth/callback/+server.js
+import { redirect } from '@sveltejs/kit';
+
+export const GET = async (event) => {
+ const {
+ url,
+ locals: { supabase }
+ } = event;
+ const code = url.searchParams.get('code') as string;
+ const next = url.searchParams.get('next') ?? '/';
+
+ if (code) {
+ const { error } = await supabase.auth.exchangeCodeForSession(code)
+ if (!error) {
+ throw redirect(303, `/${next.slice(1)}`);
+ }
+ }
+
+ // return the user to an error page with instructions
+ throw redirect(303, '/auth/auth-code-error');
+};
+```
+
+
+
+
+Let's point our `.signInWithOAuth` method's redirect to the callback route we create above:
+
+```js
+await supabase.auth.signInWithOAuth({
+ email,
+ options: {
+ redirectTo: `http://example.com/auth/callback`,
+ },
+})
+```
+
+export const Page = ({ children }) =>
+
+export default Page
diff --git a/apps/docs/pages/guides/platform/compute-add-ons.mdx b/apps/docs/pages/guides/platform/compute-add-ons.mdx
index d3bd4ad528a..e809e93476a 100644
--- a/apps/docs/pages/guides/platform/compute-add-ons.mdx
+++ b/apps/docs/pages/guides/platform/compute-add-ons.mdx
@@ -8,21 +8,23 @@ export const meta = {
Every project on the Supabase Platform comes with its own dedicated Postgres instance running inside a virtual machine (VM). The following table describes the base instance with additional compute add-ons available if you need extra performance when scaling up Supabase.
-| Plan | Pricing | CPU | Memory | Connections: Direct | Connections: Pooler |
-| --------------- | ------- | ----------------------- | ------ | ------------------- | ------------------- |
-| Free (Included) | $0 | 2-core ARM (shared) | 1 GB | 60 | 200 |
-| Small | $5 | 2-core ARM (shared) | 2 GB | 90 | 200 |
-| Medium | $50 | 2-core ARM (shared) | 4 GB | 120 | 200 |
-| Large | $100 | 2-core ARM (dedicated) | 8 GB | 160 | 300 |
-| XL | $200 | 4-core ARM (dedicated) | 16 GB | 240 | 700 |
-| 2XL | $400 | 8-core ARM (dedicated) | 32 GB | 380 | 1500 |
-| 4XL | $950 | 16-core ARM (dedicated) | 64 GB | 480 | 3000 |
-| 8XL | $1,860 | 32-core ARM (dedicated) | 128 GB | 490 | 6000 |
-| 12XL | $2,790 | 48-core ARM (dedicated) | 192 GB | 500 | 9000 |
-| 16XL | $3,720 | 64-core ARM (dedicated) | 256 GB | 500 | 12,000 |
+| Plan | Hourly Price USD | Monthly Price USD | CPU | Memory | Connections: Direct | Connections: Pooler |
+| ------- | ---------------- | ----------------- | ----------------------- | ------ | ------------------- | ------------------- |
+| Starter | $0.01344 | ~$10 | 2-core ARM (shared) | 1 GB | 60 | 200 |
+| Small | $0.0206 | ~$15 | 2-core ARM (shared) | 2 GB | 90 | 200 |
+| Medium | $0.0822 | ~$60 | 2-core ARM (shared) | 4 GB | 120 | 200 |
+| Large | $0.1517 | ~$110 | 2-core ARM (dedicated) | 8 GB | 160 | 300 |
+| XL | $0.2877 | ~$210 | 4-core ARM (dedicated) | 16 GB | 240 | 700 |
+| 2XL | $0.562 | ~$410 | 8-core ARM (dedicated) | 32 GB | 380 | 1500 |
+| 4XL | $1.32 | ~$960 | 16-core ARM (dedicated) | 64 GB | 480 | 3000 |
+| 8XL | $2.562 | ~$1,870 | 32-core ARM (dedicated) | 128 GB | 490 | 6000 |
+| 12XL | $3.836 | ~$2,800 | 48-core ARM (dedicated) | 192 GB | 500 | 9000 |
+| 16XL | $5.12 | ~$3,730 | 64-core ARM (dedicated) | 256 GB | 500 | 12,000 |
Number of connections above are recommended values.
+We charge hourly for additional compute based on your usage. Read more about [usage-based billing for compute](/docs/guides/platform/org-based-billing#usage-based-billing-for-compute).
+
[Contact us](https://supabase.com/contact/enterprise) if you require a custom plan.
## Dedicated vs. shared CPU
@@ -37,18 +39,18 @@ When considering compute upgrades, assess whether your bottlenecks are hardware-
SSD Disks are attached to your servers and the disk performance depends on the compute add-on of your instance. Disk IO refers to two metrics: throughput (Megabits per Second) and IOPS (Input/Output Operations per Second).
-| Plan | Pricing | Max Disk Throughput | Baseline Disk Throughput | Max IOPS | Baseline IOPS |
-| --------------- | ------- | ------------------- | ------------------------ | ----------- | ------------- |
-| Free (Included) | $0 | 2,085 Mbps | 87 Mbps | 11,800 IOPS | 500 IOPS |
-| Small | $5 | 2,085 Mbps | 174 Mbps | 11,800 IOPS | 1,000 IOPS |
-| Medium | $50 | 2,085 Mbps | 347 Mbps | 11,800 IOPS | 2,000 IOPS |
-| Large | $100 | 4,750 Mbps | 630 Mbps | 20,000 IOPS | 3,600 IOPS |
-| XL | $200 | 4,750 Mbps | 1,188 Mbps | 20,000 IOPS | 6,000 IOPS |
-| 2XL | $400 | 4,750 Mbps | 2,375 Mbps | 20,000 IOPS | 12,000 IOPS |
-| 4XL | $950 | 4,750 Mbps | 4,750 Mbps | 20,000 IOPS | 20,000 IOPS |
-| 8XL | $1,860 | 9,500 Mbps | 9,500 Mbps | 40,000 IOPS | 40,000 IOPS |
-| 12XL | $2,790 | 14,250 Mbps | 14,250 Mbps | 50,000 IOPS | 50,000 IOPS |
-| 16XL | $3,720 | 19,000 Mbps | 19,000 Mbps | 80,000 IOPS | 80,000 IOPS |
+| Plan | Max Disk Throughput | Baseline Disk Throughput | Max IOPS | Baseline IOPS |
+| ------- | ------------------- | ------------------------ | ----------- | ------------- |
+| Starter | 2,085 Mbps | 87 Mbps | 11,800 IOPS | 500 IOPS |
+| Small | 2,085 Mbps | 174 Mbps | 11,800 IOPS | 1,000 IOPS |
+| Medium | 2,085 Mbps | 347 Mbps | 11,800 IOPS | 2,000 IOPS |
+| Large | 4,750 Mbps | 630 Mbps | 20,000 IOPS | 3,600 IOPS |
+| XL | 4,750 Mbps | 1,188 Mbps | 20,000 IOPS | 6,000 IOPS |
+| 2XL | 4,750 Mbps | 2,375 Mbps | 20,000 IOPS | 12,000 IOPS |
+| 4XL | 4,750 Mbps | 4,750 Mbps | 20,000 IOPS | 20,000 IOPS |
+| 8XL | 9,500 Mbps | 9,500 Mbps | 40,000 IOPS | 40,000 IOPS |
+| 12XL | 14,250 Mbps | 14,250 Mbps | 50,000 IOPS | 50,000 IOPS |
+| 16XL | 19,000 Mbps | 19,000 Mbps | 80,000 IOPS | 80,000 IOPS |
[Contact us](https://supabase.com/contact/enterprise) if you require a custom plan.
diff --git a/apps/docs/pages/guides/realtime/realtime-with-nextjs.mdx b/apps/docs/pages/guides/realtime/realtime-with-nextjs.mdx
index e60afb4f74a..fd9e8d98675 100644
--- a/apps/docs/pages/guides/realtime/realtime-with-nextjs.mdx
+++ b/apps/docs/pages/guides/realtime/realtime-with-nextjs.mdx
@@ -7,8 +7,8 @@ export const meta = {
sidebar_label: 'Videos',
}
-In this guide we explore the best ways to receive realtime Postgres changes with your Next.js application.
-We'll show both client and serverside updates, and explore the which option is best.
+In this guide, we explore the best ways to receive real-time Postgres changes with your Next.js application.
+We'll show both client and server side updates, and explore which option is best.
+pgvector v0.5.0: Faster semantic search with HNSW indexes
+
There are a few pgvector benchmarks floating around the internet, most recently a [pgvector vs Qdrant](https://nirantk.com/writing/pgvector-vs-qdrant/) comparison by NirantK. We wanted to reproduce (or improve!) the results.
There is an obvious bias here: we're a Postgres company. It's not our goal to prove that pgvector is better than Qdrant for running vector workloads. From everything we hear about Qdrant, it's fantastic.
@@ -87,7 +95,7 @@ Let's start with NirantK's results as a baseline:
/>
-They aren't very flattering! Repeating our statements above, these benchmarks are using the defaults for both engines. Our goal now is to replicate the results, and then see what improvements need to be made as developers scale up their workload.
+They aren't very flattering! Repeating our statements above, these benchmarks use the defaults for both engines. Our goal now is to replicate the results, and then see what improvements need to be made as developers scale up their workload.
## Results
@@ -301,7 +309,8 @@ pgvector is still early in development. As with any open source tool, it needs t
What's next on the roadmap? Andrew has an impressive list of features [planned for v0.5.0](https://github.com/pgvector/pgvector/issues/27):
-- Adding HNSW: an index with better speed & precision than IVFFlat (at a higher memory cost)
+✅ Adding HNSW: an index with better speed & precision than IVFFlat (at a higher memory cost)
+
- Product quantization: better storage for IVFFLAT, improving speed and recall
- Parallel index builds: building your IVFFLAT indexes will be much faster
@@ -311,3 +320,4 @@ What's next on the roadmap? Andrew has an impressive list of features [planned f
- [Docs pgvector: Embeddings and vector similarity](https://supabase.com/docs/guides/database/extensions/pgvector)
- [pgvector vs Qdrant](https://nirantk.com/writing/pgvector-vs-qdrant)
- [Choosing Compute Add-on for AI workloads](https://supabase.com/docs/guides/ai/choosing-compute-addon)
+- [pgvector v0.5.0: Faster semantic search with HNSW indexes](https://supabase.com/blog/pgvector-v0-5-0-hnsw)
diff --git a/apps/www/_blog/2023-08-03-fewer-dimensions-are-better-pgvector.mdx b/apps/www/_blog/2023-08-03-fewer-dimensions-are-better-pgvector.mdx
index 7424e19c317..23b71f93f4c 100644
--- a/apps/www/_blog/2023-08-03-fewer-dimensions-are-better-pgvector.mdx
+++ b/apps/www/_blog/2023-08-03-fewer-dimensions-are-better-pgvector.mdx
@@ -148,7 +148,7 @@ Ultimately the choice of embedding model will depend on your specific use case a
- **Dimension size:** What is the operational cost of storing and comparing embeddings?
- **Language:** Which written languages do you need to support? Many of the smaller models only support English.
-The goal is to maximize similarity performance and sequence length, while minimizing model size and dimension size. Notably, if we can find a model that performs well while producing as few dimensions as possible, we can immediately improve many of the above challenges developers are facing with pgvector.
+The goal is to maximize similarity performance and sequence length while minimizing model size and dimension size. Notably, if we can find a model that performs well while producing as few dimensions as possible, we can immediately improve many of the above challenges developers are facing with pgvector.
For example [gte-small](https://huggingface.co/thenlper/gte-small), a model recently trained by the [Alibaba DAMO Academy,](https://damo.alibaba.com/) produces only 384 dimensions while ranking higher than `text-embedding-ada-002` on the MTEB leaderboard.
@@ -162,10 +162,18 @@ It's important to keep in mind that using an alternative embedding model doesn't
While dimensionality reduction techniques like Principal Component Analysis ([PCA](https://en.wikipedia.org/wiki/Principal_component_analysis)) or t-Distributed Stochastic Neighbor Embedding ([t-SNE](https://en.wikipedia.org/wiki/T-distributed_stochastic_neighbor_embedding)) may seem like a good alternative to trim down the size of text embedding vectors, there is some risk to consider.
-First, these tools may not appropriately model the relationships in high dimensional space. Both PCA and t-SNE are likely to oversimplify the multivariate relationships among different dimensions, leading to loss of important semantic information. This is particularly the case with PCA, which assumes linearity and would fail to preserve nonlinear interactions found in high-dimensional text embeddings.
+First, these tools may not appropriately model the relationships in high-dimensional space. Both PCA and t-SNE are likely to oversimplify the multivariate relationships among different dimensions, leading to the loss of important semantic information. This is particularly the case with PCA, which assumes linearity and would fail to preserve nonlinear interactions found in high-dimensional text embeddings.
Additionally, the validity of the dimensionality reduction models could change over time if the distribution of text data shifts. If the model was trained on older data, it might not accurately reflect or accommodate these shifts. For example, if your company gets a large new customer in the legal field and your embedding dataset contained no legal documents when the dimensionality reduction model was trained, otherwise exploitable structure may be destructively compressed. Both PCA and t-SNE are not inherently adaptable to such changes, which could result in an increasingly poor fit over time. In summary, the derived low-dimensional representations may not maintain semantic coherence of the original high-dimensional vectors.
## What's next?
At Supabase we are working on ways to make it easy to generate embeddings using open source, high performance, and low dimension embedding models. Stay tuned for [Launch Week 8](/launch-week) next week!
+
+## More pgvector and AI resources
+
+- [Hugging Face is now supported in Supabase](https://supabase.com/blog/hugging-face-supabase)
+- [How to build ChatGPT Plugin from scratch with Supabase Edge Runtime](https://supabase.com/blog/building-chatgpt-plugins-template)
+- [Docs pgvector: Embeddings and vector similarity](https://supabase.com/docs/guides/database/extensions/pgvector)
+- [Choosing Compute Add-on for AI workloads](https://supabase.com/docs/guides/ai/choosing-compute-addon)
+- [pgvector v0.5.0: Faster semantic search with HNSW indexes](https://supabase.com/blog/pgvector-v0-5-0-hnsw)
diff --git a/apps/www/_blog/2023-08-31-organization-based-billing.mdx b/apps/www/_blog/2023-08-31-organization-based-billing.mdx
index 858902bf07f..7cb1d53be42 100644
--- a/apps/www/_blog/2023-08-31-organization-based-billing.mdx
+++ b/apps/www/_blog/2023-08-31-organization-based-billing.mdx
@@ -30,7 +30,7 @@ We've been documenting Kevin's updates to our billing system while it's being us
## Moving from project-based to org-based billing
-Supabase has organizations and projects. An organization may contain multiple projects. A project is a Supabase instance. Preivously, each project had an individual subscription, plan and add-ons.
+Supabase has organizations and projects. An organization may contain multiple projects. A project is a Supabase instance. Previously, each project had an individual subscription, plan and add-ons.

diff --git a/apps/www/components/Panel/index.tsx b/apps/www/components/Panel/index.tsx
index f88a5fb2b16..f5069629119 100644
--- a/apps/www/components/Panel/index.tsx
+++ b/apps/www/components/Panel/index.tsx
@@ -1,5 +1,6 @@
import React, { PropsWithChildren, useEffect, useRef } from 'react'
import { motion } from 'framer-motion'
+import { detectBrowser } from 'common'
interface Props {
outerClassName?: string
@@ -28,7 +29,7 @@ const Panel = ({
const trackCursor = hasShimmer || hasInnerShimmer
const handleGlow = (event: any) => {
- if (!trackCursor || !outerRef.current || !innerRef.current) return null
+ if (!outerRef.current || !innerRef.current) return null
const outerElement = outerRef.current as HTMLDivElement
const innerElement = innerRef.current as HTMLDivElement
@@ -58,7 +59,7 @@ const Panel = ({
}
useEffect(() => {
- if (typeof window === 'undefined') return
+ if (typeof window === 'undefined' || !trackCursor) return
window.addEventListener('mousemove', handleGlow)
return () => {
diff --git a/apps/www/components/Pricing/ComputePricingModal.tsx b/apps/www/components/Pricing/ComputePricingModal.tsx
index 7e4149fcd13..4da3e700122 100644
--- a/apps/www/components/Pricing/ComputePricingModal.tsx
+++ b/apps/www/components/Pricing/ComputePricingModal.tsx
@@ -1,9 +1,10 @@
import React, { Fragment, useMemo } from 'react'
import { useRouter } from 'next/router'
import { useTheme } from 'common/Providers'
-import { IconCheckCircle, IconXCircle, Modal } from 'ui'
+import { IconXCircle, Modal } from 'ui'
import pricingAddOn from '~/data/PricingAddOnTable.json'
import { IconPricingIncludedCheck, IconPricingMinus } from './PricingIcons'
+import Link from 'next/link'
interface Props {
showComputeModal: boolean
@@ -47,12 +48,33 @@ export default function ComputePricingModal({ showComputeModal, setShowComputeMo
Choose best compute setup for you
-
+
Every project on the Supabase Platform comes with its own dedicated Postgres
instance running inside a virtual machine (VM). The following table describes the
base instance with additional compute add-ons available if you need extra
performance when scaling up Supabase.
+
+ Compute instances are billed hourly and you can scale up or down at any time if you
+ need extra performance. You'll only be charged at the end of the month for the hours
+ you've used. Paid plans come with $10 in Compute Credits to cover one Starter
+ instance or parts of any other instance. Read more on{' '}
+
+
+ usage-based billing for compute
+
+ {' '}
+ or{' '}
+
+
+ Compute Add-ons
+
+
+ .
+