diff --git a/.gitignore b/.gitignore index 88297ef381c..de5d7122e93 100644 --- a/.gitignore +++ b/.gitignore @@ -125,9 +125,12 @@ apps/new-docs/* # UI tokens packages/ui/tokens/**/*.json +# UI Storybook build +packages/ui/storybook-static + # For self-hosted logs: https://github.com/supabase/supabase/blob/86e3ab20abfdb9c3e666334d3d2f8efeef9ccf2c/docker/docker-compose-logging.yml#L101 gcloud.json # sitemaps # apps/www/public/*.xml -# apps/docs/public/*.xml \ No newline at end of file +# apps/docs/public/*.xml diff --git a/DEVELOPERS.md b/DEVELOPERS.md index 1a4e1a1e27c..26618c6f400 100644 --- a/DEVELOPERS.md +++ b/DEVELOPERS.md @@ -69,11 +69,11 @@ To contribute code to [Supabase](https://supabase.com), you must fork the [Supab Then visit, and edit, any of the following sites: -| Site | Directory | Scope name | Description | Local development server | -| ---------------------------------------------- | ------------ | ---------- | ------------------------------------ | -------------------------- | -| [supabase.com](https://supabase.com) | `/apps/www` | www | The main website | http://localhost:3000 | -| [app.supabase.com](https://app.supabase.com) | `/studio` | studio | Studio dashboard | http://localhost:8082 | -| [supabase.com/docs](https://supabase.com/docs) | `/apps/docs` | docs | Guides and Reference (Next.js based) | http://localhost:3001/docs | +| Site | Directory | Scope name | Description | Local development server | +| -------------------------------------------------------- | ------------ | ---------- | ------------------------------------ | -------------------------- | +| [supabase.com](https://supabase.com) | `/apps/www` | www | The main website | http://localhost:3000 | +| [supabase.com/dashboard](https://supabase.com/dashboard) | `/studio` | studio | Studio dashboard | http://localhost:8082 | +| [supabase.com/docs](https://supabase.com/docs) | `/apps/docs` | docs | Guides and Reference (Next.js based) | http://localhost:3001/docs | #### Running sites individually diff --git a/README.md b/README.md index 2e3acce6815..da83a9e1e4e 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ To see how to Contribute, visit [Getting Started](./DEVELOPERS.md) ## Status - [x] Alpha: We are testing Supabase with a closed set of customers -- [x] Public Alpha: Anyone can sign up over at [app.supabase.com](https://app.supabase.com). But go easy on us, there are a few kinks +- [x] Public Alpha: Anyone can sign up over at [supabase.com/dashboard](https://supabase.com/dashboard). But go easy on us, there are a few kinks - [x] Public Beta: Stable enough for most non-enterprise use-cases - [ ] Public: General Availability [[status](https://supabase.com/docs/guides/getting-started/features#feature-status)] @@ -56,7 +56,7 @@ Supabase is a combination of open source tools. We’re building the features of **Architecture** -Supabase is a [hosted platform](https://app.supabase.com). You can sign up and start using Supabase without installing anything. +Supabase is a [hosted platform](https://supabase.com/dashboard). You can sign up and start using Supabase without installing anything. You can also [self-host](https://supabase.com/docs/guides/hosting/overview) and [develop locally](https://supabase.com/docs/guides/local-development). ![Architecture](https://github.com/supabase/supabase/blob/master/apps/docs/public/img/supabase-architecture.png) @@ -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/netlify/gotrue) is an SWT based API for managing users and issuing SWT tokens. +- [GoTrue](https://github.com/supabase/gotrue) is an 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/Extensions.tsx b/apps/docs/components/Extensions.tsx index b7b7260cd64..b49c5ad83d3 100644 --- a/apps/docs/components/Extensions.tsx +++ b/apps/docs/components/Extensions.tsx @@ -3,14 +3,25 @@ import React, { useState } from 'react' import { GlassPanel, IconLink, IconX, Input } from 'ui' import extensions from '../data/extensions.json' -type extension = { +type Extension = { name: string comment: string tags: string[] - link?: string + link: string } -function getUniqueTags(json: extension[]) { +type LinkTarget = React.ComponentProps<'a'>['target'] + +function getLinkTarget(link: string): LinkTarget { + // Link is relative, open in the same tab + if (link.startsWith('/')) { + return '_self' + } + // Link is external, open in a new tab + return '_blank' +} + +function getUniqueTags(json: Extension[]): string[] { const tags = [] for (const item of json) { if (item.tags) { @@ -21,12 +32,12 @@ function getUniqueTags(json: extension[]) { } export default function Extensions() { - const [searchTerm, setSearchTerm] = useState('') - const [filters, setFilters] = useState([]) + const [searchTerm, setSearchTerm] = useState('') + const [filters, setFilters] = useState([]) const tags = getUniqueTags(extensions) - function handleChecked(tag) { + function handleChecked(tag: string) { if (filters.includes(tag)) { setFilters(filters.filter((x) => x !== tag)) } else { @@ -94,15 +105,8 @@ export default function Extensions() { filters.length === 0 ? x : x.tags.some((item) => filters.includes(item)) ) .map((extension) => ( - - + +

{extension.comment.charAt(0).toUpperCase() + extension.comment.slice(1)} diff --git a/apps/docs/components/Frameworks.tsx b/apps/docs/components/Frameworks.tsx index a1b6d0da29b..94464c4c395 100644 --- a/apps/docs/components/Frameworks.tsx +++ b/apps/docs/components/Frameworks.tsx @@ -85,6 +85,14 @@ const Frameworks = () => { }, href: '/guides/with-vue-3', }, + { + name: 'refine', + logo: { + light: '/docs/img/icons/refine-icon.svg', + dark: '/docs/img/icons/refine-icon.svg', + }, + href: '/guides/getting-started/tutorials/with-refine', + }, ] return (

diff --git a/apps/docs/components/HomePageCover.tsx b/apps/docs/components/HomePageCover.tsx index 3bf27c6b2a0..e760c411dc3 100644 --- a/apps/docs/components/HomePageCover.tsx +++ b/apps/docs/components/HomePageCover.tsx @@ -48,6 +48,11 @@ const HomePageCover = (props) => { icon: '/docs/img/icons/nuxt-icon', href: '/guides/getting-started/quickstarts/nuxtjs', }, + { + tooltip: 'refine', + icon: '/docs/img/icons/refine-icon', + href: '/guides/getting-started/quickstarts/refine', + }, ] const GettingStarted = () => ( @@ -72,7 +77,7 @@ const HomePageCover = (props) => { Discover how to set up a database to an app making queries in just a few minutes.

-
+
{frameworks.map((framework, i) => ( @@ -93,7 +98,7 @@ const HomePageCover = (props) => { return (
-
+

{props.meta?.title}

@@ -103,7 +108,7 @@ const HomePageCover = (props) => {

-
+
diff --git a/apps/docs/components/MDX/database_setup.mdx b/apps/docs/components/MDX/database_setup.mdx index 2a6e853f9c2..c54b9b32f84 100644 --- a/apps/docs/components/MDX/database_setup.mdx +++ b/apps/docs/components/MDX/database_setup.mdx @@ -12,7 +12,7 @@ Your database will be available in less than a minute. **Finding your credentials:** -You can find your project credentials inside the project [settings](https://app.supabase.com/project/_/settings/), including: +You can find your project credentials inside the project [settings](https://supabase.com/dashboard/project/_/settings/), including: -- [Database credentials](https://app.supabase.com/project/_/settings/database): connection strings and connection pooler details. -- [API credentials](https://app.supabase.com/project/_/settings/database): your serverless API URL and `anon` / `service_role` keys. +- [Database credentials](https://supabase.com/dashboard/project/_/settings/database): connection strings and connection pooler details. +- [API credentials](https://supabase.com/dashboard/project/_/settings/database): your serverless API URL and `anon` / `service_role` keys. diff --git a/apps/docs/components/MDX/project_setup.mdx b/apps/docs/components/MDX/project_setup.mdx index 2003a3a2220..d7b095e1288 100644 --- a/apps/docs/components/MDX/project_setup.mdx +++ b/apps/docs/components/MDX/project_setup.mdx @@ -8,7 +8,7 @@ Before we start building we're going to set up our Database and API. This is as ### Create a project -1. [Create a new project](https://app.supabase.com) in the Supabase Dashboard. +1. [Create a new project](https://supabase.com/dashboard) in the Supabase Dashboard. 1. Enter your project details. 1. Wait for the new database to launch. @@ -24,7 +24,7 @@ Now we are going to set up the database schema. We can use the "User Management > -1. Go to the [SQL Editor](https://app.supabase.com/project/_/sql) page in the Dashboard. +1. Go to the [SQL Editor](https://supabase.com/dashboard/project/_/sql) page in the Dashboard. 2. Click **User Management Starter**. 3. Click **Run**. @@ -41,5 +41,5 @@ Now we are going to set up the database schema. We can use the "User Management Now that you've created some database tables, you are ready to insert data using the auto-generated API. We just need to get the Project URL and `anon` key from the API settings. -1. Go to the [API Settings](https://app.supabase.com/project/_/settings/api) page in the Dashboard. +1. Go to the [API Settings](https://supabase.com/dashboard/project/_/settings/api) page in the Dashboard. 1. Find your Project `URL`, `anon`, and `service_role` keys on this page. diff --git a/apps/docs/components/MDX/social_provider_settings_supabase.mdx b/apps/docs/components/MDX/social_provider_settings_supabase.mdx index 38e0d9e5bfe..394673df620 100644 --- a/apps/docs/components/MDX/social_provider_settings_supabase.mdx +++ b/apps/docs/components/MDX/social_provider_settings_supabase.mdx @@ -1,6 +1,6 @@ -- Go to your [Supabase Project Dashboard](https://app.supabase.com) +- Go to your [Supabase Project Dashboard](https://supabase.com/dashboard) - In the left sidebar, click the `Authentication` icon (near the top) -- Click on [`Providers`](https://app.supabase.com/project/_/auth/providers) under the Configuration section +- Click on [`Providers`](https://supabase.com/dashboard/project/_/auth/providers) under the Configuration section - Click on **{props.provider}** from the accordion list to expand and turn **{props.provider} Enabled** to ON - Enter your **{props.provider} Client ID** and **{props.provider} Client Secret** saved in the previous step - Click `Save` diff --git a/apps/docs/components/MDX/social_provider_setup.mdx b/apps/docs/components/MDX/social_provider_setup.mdx index 4e32c3bf401..e6c1fe7e6dc 100644 --- a/apps/docs/components/MDX/social_provider_setup.mdx +++ b/apps/docs/components/MDX/social_provider_setup.mdx @@ -2,7 +2,7 @@ The next step requires a callback URL, which looks like this: `https://.supabase.co/auth/v1/callback` -- Go to your [Supabase Project Dashboard](https://app.supabase.com) +- Go to your [Supabase Project Dashboard](https://supabase.com/dashboard) - Click on the `Authentication` icon in the left sidebar -- Click on [`Providers`](https://app.supabase.com/project/_/auth/providers) under the Configuration section +- Click on [`Providers`](https://supabase.com/dashboard/project/_/auth/providers) under the Configuration section - Click on **{props.provider}** from the accordion list to expand and you'll find your **Redirect URL**, you can click `Copy` to copy it to the clipboard diff --git a/apps/docs/components/MDX/storage_management.mdx b/apps/docs/components/MDX/storage_management.mdx index e8f0184b88e..ce28a1684c8 100644 --- a/apps/docs/components/MDX/storage_management.mdx +++ b/apps/docs/components/MDX/storage_management.mdx @@ -7,7 +7,7 @@ triggers. Note that it is not sufficient to delete the objects from the `storage.objects` table because that would orphan and leak the actual storage objects in the S3 backend. Instead, invoke the storage API within Postgres via the `http` extension. -Enable the [http extension for the `extensions` schema](https://app.supabase.com/project/_/database/extensions) in the Dashboard. +Enable the [http extension for the `extensions` schema](https://supabase.com/dashboard/project/_/database/extensions) in the Dashboard. Then, define the following SQL functions in the SQL Editor to delete storage objects via the API: diff --git a/apps/docs/components/Navigation/NavigationMenu/HomeMenuIcons.tsx b/apps/docs/components/Navigation/NavigationMenu/HomeMenuIcons.tsx index 6925319d68d..4d2e53f6ea2 100644 --- a/apps/docs/components/Navigation/NavigationMenu/HomeMenuIcons.tsx +++ b/apps/docs/components/Navigation/NavigationMenu/HomeMenuIcons.tsx @@ -1,3 +1,5 @@ +import { products } from 'shared-data' + type HomeMenuIcon = { width?: number height?: number @@ -50,7 +52,7 @@ export function IconMenuAuth({ width = 16, height = 16 }: HomeMenuIcon) { xmlns="http://www.w3.org/2000/svg" > = (props) => { > {item.examples && item.examples.map((example, exampleIndex) => { - const exampleString = '' + const exampleString = + '' + + (example.code && + example.code + .trim() + .replace(/^```.*/, '') + .replace(/```$/, '')) const codeBlockLang = example?.code?.startsWith('```js') ? 'js' @@ -133,7 +139,6 @@ const RefFunctionSection: React.FC = (props) => { // // Create a single supabase client for interacting with your database // const supabase = createClient('https://xyzcompany.supabase.co', 'public-anon-key') // ` - const currentExampleId = example.id const staticExample = item.examples[exampleIndex] const response = staticExample.response @@ -152,15 +157,7 @@ const RefFunctionSection: React.FC = (props) => { language={codeBlockLang} hideLineNumbers={true} > - {exampleString + - (example.code && - example.code - .replace(/```/g, '') - .replace('js', '') - .replace('ts', '') - .replace('dart', '') - .replace('c#', '') - .replace('kotlin', ''))} + {exampleString} {((tables && tables.length > 0) || sql) && ( diff --git a/apps/docs/data/authProviders.ts b/apps/docs/data/authProviders.ts index a1053a30772..9694f1daf12 100644 --- a/apps/docs/data/authProviders.ts +++ b/apps/docs/data/authProviders.ts @@ -79,6 +79,16 @@ const authProviders = [ selfHosted: true, authType: 'social', }, + { + name: 'Kakao', + logo: '/docs/img/icons/kakao-icon', + href: '/guides/auth/social-login/auth-kakao', + official: true, + supporter: 'Supabase', + platform: true, + selfHosted: true, + authType: 'social', + }, { name: 'Keycloak', logo: '/docs/img/icons/keycloak-icon', diff --git a/apps/docs/data/extensions.json b/apps/docs/data/extensions.json index c46542b2cfd..af7f7342fba 100644 --- a/apps/docs/data/extensions.json +++ b/apps/docs/data/extensions.json @@ -3,460 +3,414 @@ "name": "address_standardizer", "comment": "Used to parse an address into constituent elements. Generally used to support geocoding address normalization step.", "tags": ["Utility"], - "link": "http://supabase.com/docs/guides/extensions/etc/etc/etc" - }, - { - "name": "address_standardizer-3", - "comment": "Used to parse an address into constituent elements. Generally used to support geocoding address normalization step.", - "tags": ["Utility"] + "link": "https://postgis.net/docs/manual-2.5/Address_Standardizer.html" }, { "name": "address_standardizer_data_us", "comment": "Address Standardizer US dataset example", - "tags": ["Dataset"] - }, - { - "name": "address_standardizer_data_us-3", - "comment": "Address Standardizer US dataset example", - "tags": ["Dataset"] - }, - { - "name": "adminpack", - "comment": "administrative functions for PostgreSQL", - "tags": ["Admin", "Utility"] + "tags": ["Dataset"], + "link": "https://postgis.net/docs/manual-2.5/Address_Standardizer.html" }, { "name": "amcheck", "comment": "functions for verifying relation integrity", - "tags": ["Admin", "Utility"] + "tags": ["Admin", "Utility"], + "link": "https://www.postgresql.org/docs/current/amcheck.html" }, { "name": "autoinc", "comment": "functions for autoincrementing fields", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "https://www.postgresql.org/docs/current/contrib-spi.html#id-1.11.7.50.6" }, { "name": "bloom", "comment": "bloom access method - signature file based index", - "tags": ["Index"] + "tags": ["Index"], + "link": "https://www.postgresql.org/docs/current/bloom.html" }, { "name": "btree_gin", "comment": "support for indexing common datatypes in GIN", - "tags": ["Index"] + "tags": ["Index"], + "link": "https://www.postgresql.org/docs/current/btree-gin.html" }, { "name": "btree_gist", "comment": "support for indexing common datatypes in GiST", - "tags": ["Index"] + "tags": ["Index"], + "link": "https://www.postgresql.org/docs/current/btree-gist.html" }, { "name": "citext", "comment": "data type for case-insensitive character strings", - "tags": ["Data Type"] + "tags": ["Data Type"], + "link": "https://www.postgresql.org/docs/current/citext.html" }, { "name": "cube", "comment": "data type for multidimensional cubes", - "tags": ["Data Type"] + "tags": ["Data Type"], + "link": "https://www.postgresql.org/docs/current/cube.html" }, { "name": "dblink", "comment": "connect to other PostgreSQL databases from within a database", - "tags": ["Admin", "Utility"] + "tags": ["Admin", "Utility"], + "link": "https://www.postgresql.org/docs/current/contrib-dblink-function.html" }, { "name": "dict_int", "comment": "text search dictionary template for integers", - "tags": ["Search"] + "tags": ["Search"], + "link": "https://www.postgresql.org/docs/current/dict-int.html" }, { "name": "dict_xsyn", "comment": "text search dictionary template for extended synonym processing", - "tags": ["Search"] + "tags": ["Search"], + "link": "https://www.postgresql.org/docs/current/dict-xsyn.html" }, { "name": "earthdistance", "comment": "calculate great-circle distances on the surface of the Earth", - "tags": ["Geo", "Utility"] - }, - { - "name": "file_fdw", - "comment": "foreign-data wrapper for flat file access", - "tags": ["Admin", "Utility"] + "tags": ["Geo", "Utility"], + "link": "https://www.postgresql.org/docs/current/earthdistance.html" }, { "name": "fuzzystrmatch", "comment": "determine similarities and distance between strings", - "tags": ["Search"] + "tags": ["Search"], + "link": "https://www.postgresql.org/docs/current/fuzzystrmatch.html" }, { "name": "hstore", "comment": "data type for storing sets of (key, value) pairs", - "tags": ["Data Type"] + "tags": ["Data Type"], + "link": "https://www.postgresql.org/docs/current/hstore.html" }, { "name": "hypopg", "comment": "Hypothetical indexes for PostgreSQL", - "link": "https://supabase.com/docs/guides/database/extensions/hypopg", - "tags": ["Admin", "Index"] + "tags": ["Admin", "Index"], + "link": "/guides/database/extensions/hypopg" }, { "name": "http", "comment": "HTTP client for PostgreSQL, allows web page retrieval inside the database.", - "link": "https://supabase.com/docs/guides/database/extensions/http", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "/guides/database/extensions/http" }, { "name": "insert_username", "comment": "functions for tracking who changed a table", - "tags": ["Audit", "Utility"] + "tags": ["Audit", "Utility"], + "link": "https://www.postgresql.org/docs/current/contrib-spi.html#id-1.11.7.50.7" }, { "name": "old_snapshot", "comment": "utilities in support of old_snapshot_threshold", - "tags": ["Admin", "Utility"] - }, - { - "name": "intagg", - "comment": "integer aggregator and enumerator (obsolete)", - "tags": ["Utility"] + "tags": ["Admin", "Utility"], + "link": "https://www.postgresql.org/docs/current/oldsnapshot.html" }, { "name": "intarray", "comment": "functions, operators, and index support for 1-D arrays of integers", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "https://www.postgresql.org/docs/current/intarray.html" }, { "name": "isn", "comment": "data types for international product numbering standards", - "tags": ["Data Type"] + "tags": ["Data Type"], + "link": "https://www.postgresql.org/docs/current/isn.html" }, { "name": "lo", "comment": "Large Object maintenance", - "tags": ["Data Type"] + "tags": ["Data Type"], + "link": "https://www.postgresql.org/docs/current/lo.html" }, { "name": "ltree", "comment": "data type for hierarchical tree-like structures", - "tags": ["Data Type"] + "tags": ["Data Type"], + "link": "https://www.postgresql.org/docs/current/ltree.html" }, { "name": "moddatetime", "comment": "functions for tracking last modification time", - "tags": ["Audit", "Utility"] - }, - { - "name": "pageinspect", - "comment": "inspect the contents of database pages at a low level", - "tags": ["Admin", "Utility"] - }, - { - "name": "pg_buffercache", - "comment": "examine the shared buffer cache", - "tags": ["Admin", "Utility"] + "tags": ["Audit", "Utility"], + "link": "https://www.postgresql.org/docs/current/contrib-spi.html#id-1.11.7.50.8" }, { "name": "pg_cron", "comment": "Job scheduler for PostgreSQL", - "link": "https://supabase.com/docs/guides/database/extensions/pgcron", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "/guides/database/extensions/pg_cron" }, { "name": "pg_freespacemap", "comment": "examine the free space map (FSM)", - "tags": ["Admin", "Utility"] + "tags": ["Admin", "Utility"], + "link": "https://www.postgresql.org/docs/current/pgfreespacemap.html" }, { "name": "pg_graphql", "comment": "pg_graphql: GraphQL support", - "link": "https://supabase.com/docs/guides/database/extensions/pg_graphql", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "/guides/database/extensions/pg_graphql" }, { "name": "pg_hashids", "comment": "pg_hashids", - "link": "https://supabase.com/docs/guides/database/extensions/pg_hashids", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "/guides/database/extensions/pg_hashids" }, { "name": "pg_jsonschema", "comment": "pg_jsonschema", - "link": "https://supabase.com/docs/guides/database/extensions/pg_jsonschema", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "/guides/database/extensions/pg_jsonschema" }, { "name": "pg_net", "comment": "Async HTTP", - "link": "https://supabase.com/docs/guides/database/extensions/pgnet", - "tags": ["Utility", "Notifications"] + "tags": ["Utility", "Notifications"], + "link": "/guides/database/extensions/pg_net" }, { "name": "pg_prewarm", "comment": "prewarm relation data", - "tags": ["Admin", "Utility"] + "tags": ["Admin", "Utility"], + "link": "https://www.postgresql.org/docs/current/pgprewarm.html" }, { "name": "pg_stat_monitor", "comment": "The pg_stat_monitor is a PostgreSQL Query Performance Monitoring tool, based on PostgreSQL contrib module pg_stat_statements. pg_stat_monitor provides aggregated statistics, client information, plan details including plan, and histogram information.", - "link": "https://supabase.com/docs/guides/database/extensions/pg_stat_monitor", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "/guides/database/extensions/pg_stat_monitor" }, { "name": "pg_stat_statements", "comment": "track execution statistics of all SQL statements executed", - "link": "https://supabase.com/docs/guides/database/extensions/pg_stat_statements", - "tags": ["Admin", "Utility"] + "tags": ["Admin", "Utility"], + "link": "/guides/database/extensions/pg_stat_statements" }, { "name": "pg_surgery", "comment": "extension to perform surgery on a damaged relation", - "tags": ["Admin", "Utility"] + "tags": ["Admin", "Utility"], + "link": "https://www.postgresql.org/docs/current/pgsurgery.html" }, { "name": "pg_trgm", "comment": "text similarity measurement and index searching based on trigrams", - "tags": ["Search"] - }, - { - "name": "pg_visibility", - "comment": "examine the visibility map (VM) and page-level visibility info", - "tags": ["Admin", "Utility"] + "tags": ["Search"], + "link": "https://www.postgresql.org/docs/current/pgtrgm.html" }, { "name": "pgaudit", "comment": "provides auditing functionality", - "link": "https://supabase.com/docs/guides/database/extensions/pgaudit", - "tags": ["Audit", "Utility"] + "tags": ["Audit", "Utility"], + "link": "/guides/database/extensions/pgaudit" }, { "name": "pg_walinspect", "comment": "functions to inspect contents of PostgreSQL Write-Ahead Log", - "tags": ["Admin", "Utility"] + "tags": ["Admin", "Utility"], + "link": "https://www.postgresql.org/docs/current/pgwalinspect.html" }, { "name": "pgcrypto", "comment": "cryptographic functions", - "tags": ["Utility", "Cryptography"] + "tags": ["Utility", "Cryptography"], + "link": "https://www.postgresql.org/docs/current/pgcrypto.html" }, { "name": "pgjwt", "comment": "JSON Web Token API for Postgresql", - "link": "https://supabase.com/docs/guides/database/extensions/pgjwt", - "tags": ["Utility", "Cryptography"] + "tags": ["Utility", "Cryptography"], + "link": "/guides/database/extensions/pgjwt" }, { "name": "pgroonga", "comment": "Super fast and all languages supported full text search index based on Groonga", - "link": "https://supabase.com/docs/guides/database/extensions/pgroonga", - "tags": ["Search"] + "tags": ["Search"], + "link": "/guides/database/extensions/pgroonga" }, { "name": "pgroonga_database", "comment": "PGroonga database management module", - "tags": ["Admin"] + "tags": ["Admin"], + "link": "https://pgroonga.github.io/reference/modules/pgroonga-database.html" }, { "name": "pgrouting", "comment": "pgRouting Extension", - "link": "https://supabase.com/docs/guides/database/extensions/pgrouting", - "tags": ["Geo", "Utility"] + "tags": ["Geo", "Utility"], + "link": "/guides/database/extensions/pgrouting" }, { "name": "pgrowlocks", "comment": "show row-level locking information", - "tags": ["Admin", "Utility"] + "tags": ["Admin", "Utility"], + "link": "https://www.postgresql.org/docs/current/pgrowlocks.html" }, { "name": "pgsodium", "comment": "Postgres extension for libsodium functions", - "link": "https://supabase.com/docs/guides/database/extensions/pgsodium", - "tags": ["Utility", "Cryptography"] + "tags": ["Utility", "Cryptography"], + "link": "/guides/database/extensions/pgsodium" }, { "name": "pgstattuple", "comment": "show tuple-level statistics", - "tags": ["Admin", "Utility"] + "tags": ["Admin", "Utility"], + "link": "https://www.postgresql.org/docs/current/pgstattuple.html" }, { "name": "pgtap", "comment": "Unit testing for PostgreSQL", - "link": "https://supabase.com/docs/guides/database/extensions/pgtap", - "tags": ["Utility", "Testing"] + "tags": ["Utility", "Testing"], + "link": "/guides/database/extensions/pgtap" }, { "name": "plcoffee", "comment": "PL/CoffeeScript (v8) trusted procedural language", - "tags": ["Language"] + "tags": ["Language"], + "link": "https://github.com/plv8/plv8/blob/master/doc/plv8.md#coffeescript-extension" }, { "name": "pljava", "comment": "PL/Java procedural language (https://tada.github.io/pljava/)", - "tags": ["Language"] + "tags": ["Language"], + "link": "https://tada.github.io/pljava/" }, { "name": "plls", "comment": "PL/LiveScript (v8) trusted procedural language", - "tags": ["Language"] + "tags": ["Language"], + "link": "https://github.com/plv8/plv8/blob/master/doc/plv8.md#livescript-extension" }, { "name": "plpgsql", "comment": "PL/pgSQL procedural language", - "tags": ["Language"] + "tags": ["Language"], + "link": "https://www.postgresql.org/docs/current/plpgsql.html" }, { "name": "plpgsql_check", "comment": "extended check for plpgsql functions", - "href": "https://supabase.com/docs/guides/database/extensions/plpgsql_check", - "tags": ["Utility", "Testing"] + "tags": ["Utility", "Testing"], + "link": "/guides/database/extensions/plpgsql_check" }, { "name": "plv8", "comment": "PL/JavaScript (v8) trusted procedural language", - "link": "http://localhost:3001/docs/guides/database/extensions/plv8", - "tags": ["Language"] + "tags": ["Language"], + "link": "/guides/database/extensions/plv8" }, { "name": "postgis", "comment": "PostGIS geometry and geography spatial types and functions", - "link": "https://supabase.com/docs/guides/database/extensions/postgis", - "tags": ["Geo"] - }, - { - "name": "postgis-3", - "comment": "PostGIS geometry and geography spatial types and functions", - "tags": ["Geo"] - }, - { - "name": "postgis_raster", - "comment": "PostGIS raster types and functions", - "tags": ["Geo"] - }, - { - "name": "postgis_raster-3", - "comment": "PostGIS raster types and functions", - "tags": ["Geo"] - }, - { - "name": "postgis_sfcgal", - "comment": "PostGIS SFCGAL functions", - "tags": ["Geo"] - }, - { - "name": "postgis_sfcgal-3", - "comment": "PostGIS SFCGAL functions", - "tags": ["Geo"] - }, - { - "name": "postgis_tiger_geocoder", - "comment": "PostGIS tiger geocoder and reverse geocoder", - "tags": ["Geo"] - }, - { - "name": "postgis_tiger_geocoder-3", - "comment": "PostGIS tiger geocoder and reverse geocoder", - "tags": ["Geo"] - }, - { - "name": "postgis_topology", - "comment": "PostGIS topology spatial types and functions", - "tags": ["Geo"] - }, - { - "name": "postgis_topology-3", - "comment": "PostGIS topology spatial types and functions", - "tags": ["Geo"] + "tags": ["Geo"], + "link": "/guides/database/extensions/postgis" }, { "name": "postgres_fdw", "comment": "foreign-data wrapper for remote PostgreSQL servers", - "tags": ["Admin"] + "tags": ["Admin"], + "link": "https://www.postgresql.org/docs/current/postgres-fdw.html" }, { "name": "refint", "comment": "functions for implementing referential integrity (obsolete)", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "https://www.postgresql.org/docs/current/contrib-spi.html#id-1.11.7.50.5" }, { "name": "rum", "comment": "GIN-like index for text search", - "link": "https://supabase.com/docs/guides/database/extensions/rum", - "tags": ["Index", "Search"] + "tags": ["Index", "Search"], + "link": "/guides/database/extensions/rum" }, { "name": "seg", "comment": "data type for representing line segments or floating-point intervals", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "https://www.postgresql.org/docs/current/seg.html" }, { "name": "sslinfo", "comment": "information about SSL certificates", - "tags": ["Admin", "Utility"] + "tags": ["Admin", "Utility"], + "link": "https://www.postgresql.org/docs/current/sslinfo.html" }, { "name": "supautils", "comment": "Supabase standard library", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "https://supabase.github.io/supautils/" }, { "name": "tablefunc", "comment": "functions that manipulate whole tables, including crosstab", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "https://www.postgresql.org/docs/current/tablefunc.html" }, { "name": "tcn", "comment": "Triggered change notifications", - "tags": ["Utility", "Notifications"] + "tags": ["Utility", "Notifications"], + "link": "https://www.postgresql.org/docs/current/tcn.html" }, { "name": "timescaledb", "comment": "Enables scalable inserts and complex queries for time-series data", - "link": "https://supabase.com/docs/guides/database/extensions/timescaledb", - "tags": ["Time Series", "Data Type", "Utility"] + "tags": ["Time Series", "Data Type", "Utility"], + "link": "/guides/database/extensions/timescaledb" }, { "name": "tsm_system_rows", "comment": "TABLESAMPLE method which accepts number of rows as a limit", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "https://www.postgresql.org/docs/current/tsm-system-rows.html" }, { "name": "tsm_system_time", "comment": "TABLESAMPLE method which accepts time in milliseconds as a limit", - "tags": ["Utility"] + "tags": ["Utility"], + "link": "https://www.postgresql.org/docs/current/tsm-system-time.html" }, { "name": "unaccent", "comment": "text search dictionary that removes accents", - "tags": ["Search"] + "tags": ["Search"], + "link": "https://www.postgresql.org/docs/current/unaccent.html" }, { "name": "uuid-ossp", "comment": "generate universally unique identifiers (UUIDs)", - "link": "https://supabase.com/docs/guides/database/extensions/uuid-ossp", - "tags": ["Utility", "Data Type"] + "tags": ["Utility", "Data Type"], + "link": "/guides/database/extensions/uuid-ossp" }, { "name": "pgvector", "comment": "vector data type with similarity search", - "link": "https://supabase.com/docs/guides/database/extensions/pgvector", - "tags": ["AI", "Data Type", "Search"] + "tags": ["AI", "Data Type", "Search"], + "link": "/guides/database/extensions/pgvector" }, { "name": "pg_repack", "comment": "Optimize physical storage and remove bloat from tables and indexes", - "link": "https://supabase.com/docs/guides/database/extensions/pgrepack", - "tags": ["Admin", "Utility"] + "tags": ["Admin", "Utility"], + "link": "/guides/database/extensions/pg_repack" }, { "name": "wrappers", "comment": "Foreign data wrappers developed by Supabase", - "link": "https://supabase.com/docs/guides/database/extensions/wrappers", - "tags": ["Admin", "Utility"] - }, - { - "name": "xml2", - "comment": "XPath querying and XSLT", - "tags": ["Utility"] + "tags": ["Admin", "Utility"], + "link": "/guides/database/extensions/wrappers" } ] diff --git a/apps/docs/docs/ref/api/api.mdx b/apps/docs/docs/ref/api/api.mdx index 371041af0bd..70bb75ee9f6 100644 --- a/apps/docs/docs/ref/api/api.mdx +++ b/apps/docs/docs/ref/api/api.mdx @@ -15,7 +15,7 @@ The Management API is in `beta`. It is usable in it's current state, but it's li ## Authentication All API requests require a Supabase Personal token to be included in the Authorization header: `Authorization Bearer -### Add KotlinX Serialization (required for PostgREST and Realtime serialization) +### Serialization + +supabase-kt provides several different ways to encode and decode your custom objects. +By default, [KotlinX Serialization](https://github.com/Kotlin/kotlinx.serialization) is used. - + - Add the serialization plugin + Use [KotlinX Serialization](https://github.com/Kotlin/kotlinx.serialization). + + + - - Now you can create serializable classes in your project: ```kotlin - @Serializable - data class Message( - val id: Int, - val content: String, - @SerialName("author_id") - val authorId: String - ) + val client = createSupabaseClient(supabaseUrl, supabaseKey) { + //Already the default serializer + } ``` - And use them in your Supabase queries: + + + + + + + Use [Moshi](https://github.com/square/moshi). + + + + + + + + ```kotlin + implementation("io.github.jan-tennert.supabase:serializer-moshi:VERSION") + ``` + + + + + ```groovy + implementation 'io.github.jan-tennert.supabase:serializer-moshi:VERSION' + ``` + + + + + ```xml + + io.github.jan-tennert.supabase + serializer-moshi + VERSION + + ``` + + + ```kotlin - val messages = client.postgrest["messages"].select().decodeList() + val client = createSupabaseClient(supabaseUrl, supabaseKey) { + defaultSerializer = MoshiSerializer() + } + ``` + + + + + + + + Use [Jackson](https://github.com/FasterXML/jackson-module-kotlin). + + + + + + + + ```kotlin + implementation("io.github.jan-tennert.supabase:serializer-jackson:VERSION") + ``` + + + + + ```groovy + implementation 'io.github.jan-tennert.supabase:serializer-jackson:VERSION' + ``` + + + + + ```xml + + io.github.jan-tennert.supabase + serializer-jackson + VERSION + + ``` + + + + ```kotlin + val client = createSupabaseClient(supabaseUrl, supabaseKey) { + defaultSerializer = JacksonSerializer() + } + ``` + + + + + + + + Use custom serializer. + + + + + ```kotlin + class CustomSerializer: SupabaseSerializer { + + override fun encode(type: KType, value: T): String { + //encode value to string + } + + override fun decode(type: KType, value: String): T { + //decode value + } + + } + ``` + + ```kotlin + val client = createSupabaseClient(supabaseUrl, supabaseKey) { + defaultSerializer = CustomSerializer() + } ``` diff --git a/apps/docs/docs/ref/kotlin/introduction.mdx b/apps/docs/docs/ref/kotlin/introduction.mdx index 36be6dd7a89..7f1f3784175 100644 --- a/apps/docs/docs/ref/kotlin/introduction.mdx +++ b/apps/docs/docs/ref/kotlin/introduction.mdx @@ -18,15 +18,28 @@ This reference documents every object and method available in Supabase's Kotlin Supported Kotlin targets: -- JVM -- Android -- iOS (Experimental) -- JS (Browser) +| **Module** | **GoTrue** | **Realtime** | **Postgrest** | **Storage** | **Functions** | **Apollo-GraphQL** | +| -------------------------------------- | ---------- | ------------ | ------------- | ----------- | ------------- | ------------------ | +| **JVM** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| **Android** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| **JS** _(Browser)_ | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| **IOS** | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| **MacOS** _(macosX64 & macosArm64)_ 🚧 | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ | +| **Windows** _(mingwX64)_ 🚧 | ☑️ | ✅ | ✅ | ✅ | ✅ | ❌ | +| **Linux** _(linuxX64)_ 🚧 | ☑️ | ✅ | ✅ | ✅ | ✅ | ❌ | + +✅ = full support + +☑️ = partial support: no built-in OAuth/OTP link handling. Linux also has no persistent storage. + +🚧 = experimental/needs feedback + +❌ = not supported
-

The Kotlin client library is created and maintained by the Supabase community, and is not an official library. Please be tolerant of areas where the library is still being developed, and — as with all the libraries — feel free to contribute wherever you find issues.

+

The Kotlin client library is created and maintained by the Supabase community, and is not an official library. Please be tolerant of areas where the library is still being developed, and — as with all the libraries — feel free to contribute wherever you find issues.

Huge thanks to official maintainer, [jan-tennert](https://github.com/jan-tennert).

diff --git a/apps/docs/docs/ref/self-hosting-analytics/introduction.mdx b/apps/docs/docs/ref/self-hosting-analytics/introduction.mdx index ccf1ee1c932..a1cb8d81c9a 100644 --- a/apps/docs/docs/ref/self-hosting-analytics/introduction.mdx +++ b/apps/docs/docs/ref/self-hosting-analytics/introduction.mdx @@ -122,6 +122,10 @@ Download your Google Cloud API JWT and store it under gcloud.json in your workin required. +### Storage Location + +Currently, all BigQuery datasets stored and managed by Analytics, whether via CLI or self-hosted, will default to the US region. + ## Production Recommendations To self-host in a production setting, we recommend performing the following for a better experience. diff --git a/apps/docs/docs/reference/api.mdx b/apps/docs/docs/reference/api.mdx index 371041af0bd..70bb75ee9f6 100644 --- a/apps/docs/docs/reference/api.mdx +++ b/apps/docs/docs/reference/api.mdx @@ -15,7 +15,7 @@ The Management API is in `beta`. It is usable in it's current state, but it's li ## Authentication All API requests require a Supabase Personal token to be included in the Authorization header: `Authorization Bearer + + +Emdeddings of 1536 dimensions by OpenAI for dbpedia dataset with 1,000,000 vectors. + +| Plan | Vectors | Lists | RPS | Latency Mean | Latency p95 | RAM Usage | RAM | +| ------ | --------- | ----- | ---- | ------------ | ----------- | ------------------ | ------ | +| Free | 20,000 | 40 | 135 | 0.372 sec | 0.412 sec | 1 GB + 200 Mb Swap | 1 GB | +| Small | 50,000 | 100 | 140 | 0.357 sec | 0.398 sec | 1.8 GB | 2 GB | +| Medium | 100,000 | 200 | 130 | 0.383 sec | 0.446 sec | 3.7 GB | 4 GB | +| Large | 250,000 | 500 | 130 | 0.378 sec | 0.434 sec | 7 GB | 8 GB | +| XL | 500,000 | 1000 | 235 | 0.213 sec | 0.271 sec | 13.5 GB | 16 GB | +| 2XL | 1,000,000 | 2000 | 380 | 0.133 sec | 0.236 sec | 30 GB | 32 GB | +| 4XL | 1,000,000 | 2000 | 720 | 0.068 sec | 0.120 sec | 35 GB | 64 GB | +| 8XL | 1,000,000 | 2000 | 1250 | 0.039 sec | 0.066 sec | 38 GB | 128 GB | +| 12XL | 1,000,000 | 2000 | 1600 | 0.030 sec | 0.052 sec | 41 GB | 192 GB | +| 16XL | 1,000,000 | 2000 | 1790 | 0.029 sec | 0.051 sec | 45 GB | 256 GB | + +For 1,000,000 vectors 10 probes results to precision of 0.91. And for 500,000 vectors and below 10 probes results to precision in the range of 0.95 - 0.99. To increase precision, you need to increase the number of probes. + + + + +Emdeddings of 1536 dimensions by OpenAI for dbpedia dataset with 1,000,000 vectors. + +| Plan | Vectors | Lists | RPS | Latency Mean | Latency p95 | RAM Usage | RAM | +| ------ | --------- | ----- | --- | ------------ | ----------- | --------- | ------ | +| Free | 20,000 | 40 | - | - | - | - | 1 GB | +| Small | 50,000 | 100 | - | - | - | - | 2 GB | +| Medium | 100,000 | 200 | - | - | - | - | 4 GB | +| Large | 250,000 | 500 | - | - | - | - | 8 GB | +| XL | 500,000 | 1000 | - | - | - | - | 16 GB | +| 2XL | 1,000,000 | 2000 | 140 | 0.358 sec | 0.575 sec | 30 GB | 32 GB | +| 4XL | 1,000,000 | 2000 | 270 | 0.186 sec | 0.304 sec | 35 GB | 64 GB | +| 8XL | 1,000,000 | 2000 | 470 | 0.104 sec | 0.166 sec | 38 GB | 128 GB | +| 12XL | 1,000,000 | 2000 | 600 | 0.085 sec | 0.132 sec | 41 GB | 192 GB | +| 16XL | 1,000,000 | 2000 | 670 | 0.081 sec | 0.129 sec | 45 GB | 256 GB | + +For 1,000,000 vectors 40 probes results to precision of 0.98. Note that exact values may vary depending on the dataset and queries, we recommend to run benchmarks with your own data to get precise results. Use this table as a reference. + + + + +Emdeddings of 960 dimensions from gist-960 dataset with 1,000,000 vectors. + +| Plan | Vectors | Lists | RPS | Latency Mean | Latency p95 | RAM Usage | RAM | +| ------ | --------- | ----- | ---- | ------------ | ----------- | ------------------ | ------ | +| Free | 30,000 | 30 | 75 | 0.065 sec | 0.088 sec | 1 GB + 100 Mb Swap | 1 GB | +| Small | 100,000 | 100 | 78 | 0.064 sec | 0.092 sec | 1.8 GB | 2 GB | +| Medium | 250,000 | 250 | 58 | 0.085 sec | 0.129 sec | 3.2 GB | 4 GB | +| Large | 500,000 | 500 | 55 | 0.088 sec | 0.140 sec | 5 GB | 8 GB | +| XL | 1,000,000 | 1000 | 110 | 0.046 sec | 0.070 sec | 14 GB | 16 GB | +| 2XL | 1,000,000 | 1000 | 235 | 0.083 sec | 0.136 sec | 10 GB | 32 GB | +| 4XL | 1,000,000 | 1000 | 420 | 0.071 sec | 0.106 sec | 11 GB | 64 GB | +| 8XL | 1,000,000 | 1000 | 815 | 0.072 sec | 0.106 sec | 13 GB | 128 GB | +| 12XL | 1,000,000 | 1000 | 1150 | 0.052 sec | 0.078 sec | 15.5 GB | 192 GB | +| 16XL | 1,000,000 | 1000 | 1345 | 0.072 sec | 0.106 sec | 17.5 GB | 256 GB | + + + + +Emdeddings of 512 dimensions from GloVe Reddit comments dataset with 1,623,397 vectors. + +| Plan | Vectors | Lists | RPS | Latency Mean | Latency p95 | RAM Usage | RAM | +| ------ | --------- | ----- | ---- | ------------ | ----------- | ------------------ | ------ | +| Free | 100,000 | 100 | 250 | 0.395 sec | 0.432 sec | 1 GB + 300 Mb Swap | 1 GB | +| Small | 250,000 | 250 | 440 | 0.223 sec | 0.250 sec | 2 GB + 200 Mb Swap | 2 GB | +| Medium | 500,000 | 500 | 425 | 0.116 sec | 0.143 sec | 3.7 GB | 4 GB | +| Large | 1,000,000 | 1000 | 515 | 0.096 sec | 0.116 sec | 7.5 GB | 8 GB | +| XL | 1,623,397 | 1275 | 465 | 0.212 sec | 0.272 sec | 14 GB | 16 GB | +| 2XL | 1,623,397 | 1275 | 1400 | 0.061 sec | 0.075 sec | 22 GB | 32 GB | +| 4XL | 1,623,397 | 1275 | 1800 | 0.027 sec | 0.043 sec | 20 GB | 64 GB | +| 8XL | 1,623,397 | 1275 | 2850 | 0.032 sec | 0.049 sec | 21 GB | 128 GB | +| 12XL | 1,623,397 | 1275 | 3700 | 0.020 sec | 0.036 sec | 26 GB | 192 GB | +| 16XL | 1,623,397 | 1275 | 3700 | 0.025 sec | 0.042 sec | 29 GB | 256 GB | + +Random vectors were generated for queries. + + + + +Emdeddings of 512 dimensions from GloVe Reddit comments dataset with 1,623,397 vectors. + +| Plan | Vectors | Lists | RPS | Latency Mean | Latency p95 | RAM Usage | RAM | +| ------ | --------- | ----- | --- | ------------ | ----------- | --------- | ------ | +| Free | 100,000 | 100 | - | - | - | - | 1 GB | +| Small | 250,000 | 250 | - | - | - | - | 2 GB | +| Medium | 500,000 | 500 | 75 | 0.656 sec | 0.750 sec | 3.7 GB | 4 GB | +| Large | 1,000,000 | 1000 | 102 | 0.488 sec | 0.580 sec | 7.5 GB | 8 GB | +| XL | 1,000,000 | 1000 | 188 | 0.525 sec | 0.596 sec | 14 GB | 16 GB | +| XL | 1,623,397 | 1275 | 75 | 0.679 sec | 0.798 sec | 14 GB | 16 GB | +| 2XL | 1,623,397 | 1275 | 160 | 0.314 sec | 0.384 sec | 22 GB | 32 GB | +| 4XL | 1,623,397 | 1275 | 300 | 0.083 sec | 0.113 sec | 20 GB | 64 GB | +| 8XL | 1,623,397 | 1275 | 565 | 0.105 sec | 0.141 sec | 21 GB | 128 GB | +| 12XL | 1,623,397 | 1275 | 840 | 0.093 sec | 0.124 sec | 26 GB | 192 GB | +| 16XL | 1,623,397 | 1275 | 940 | 0.084 sec | 0.108 sec | 29 GB | 256 GB | + +Random vectors were generated for queries. + + + + + + +It is possible to upload more vectors to a single table if Memory allows it (for example, 4XL plan and higher for OpenAI embeddings). But it will affect the performance of the queries: RPS will be lower, and latency will be higher. Scaling should be almost linear, but it is recommended to benchmark your workload to find the optimal number of vectors per table and per database instance. + + + +## Methodology + +We follow techniques outlined in the [ANN Benchmarks](https://github.com/erikbern/ann-benchmarks) methodology. A Python test runner is responsible for uploading the data, creating the index, and running the queries. The pgvector engine is implemented using [vecs](https://github.com/supabase/vecs), a Python client for pgvector. + +
+ multi database + multi database +
+ +Each test is run for a minimum of 30-40 minutes. They include a series of experiments executed at different concurrency levels to measure the engine's performance under different load types. The results are then averaged. + +As a general recommendation, we suggest using a concurrency level of 5 or more for most workloads and 30 or more for high-load workloads. + +export const Page = ({ children }) => + +export default Page diff --git a/apps/docs/pages/guides/ai/choosing-instance-type.mdx b/apps/docs/pages/guides/ai/choosing-instance-type.mdx deleted file mode 100644 index c6bb503c4aa..00000000000 --- a/apps/docs/pages/guides/ai/choosing-instance-type.mdx +++ /dev/null @@ -1,79 +0,0 @@ -import Layout from '~/layouts/DefaultGuideLayout' - -export const meta = { - id: 'ai-choosing-instance-type', - title: 'Choosing Instance Type', - description: 'Choosing the right instance type for your workload.', - subtitle: 'Choosing the right instance type for your workload.', - sidebar_label: 'Choosing Instance Type', -} - -This guide will help you choose the right instance type for your workload. We'll provide general guidance, as it is impossible to provide specific instructions for every possible use case. The goal is to give you a starting point from which you can make your own benchmarks and optimizations. - -For more information about engineering at scale, see our [Engineering for Scale](/docs/guides/ai/engineering-for-scale) guide. - -## Simple workloads - -We've run a set of benchmarks using the [gist-960-angular](http://corpus-texmex.irisa.fr/) dataset. This dataset contains 1,000,000 embeddings for images, with each embedding being 960 dimensions. - -We used [Vecs](https://github.com/supabase/vecs) to create a collection, upload the embeddings to a single table, and create an `inner-product` index for the embedding column. We then ran a series of queries to measure the performance of different instance types: - -### Results - -The number of vectors in `gist-960-angular` was cut to fit the instance size. - -| Plan | CPU | Memory | Vectors | RPS | Latency Mean | Latency p95 | CPU Usage - Max % | Memory Usage - Max | -| ------ | ------ | ------ | ------- | --- | ------------ | ----------- | ----------------- | ------------------ | -| Free | 2-core | 1 GB | 30,000 | 75 | 0.065 sec | 0.088 sec | 90% | 1 GB + 100 Mb Swap | -| Small | 2-core | 2 GB | 100,000 | 78 | 0.064 sec | 0.092 sec | 80% | 1.8 GB | -| Medium | 2-core | 4 GB | 250,000 | 58 | 0.085 sec | 0.129 sec | 90% | 3.2 GB | -| Large | 2-core | 8 GB | 500,000 | 55 | 0.088 sec | 0.140 sec | 90% | 5 GB | - -The full number of vectors in `gist-960-angular` dataset - 1,000,000. - -| Plan | CPU | Memory | Vectors | RPS | Latency Mean | Latency p95 | CPU Usage - Max % | Memory Usage - Max | -| ---- | ------- | ------ | --------- | ---- | ------------ | ----------- | ----------------- | ------------------ | -| XL | 4-core | 16 GB | 1,000,000 | 110 | 0.046 sec | 0.070 sec | 45% | 14 GB | -| 2XL | 8-core | 32 GB | 1,000,000 | 235 | 0.083 sec | 0.136 sec | 33% | 10 GB | -| 4XL | 16-core | 64 GB | 1,000,000 | 420 | 0.071 sec | 0.106 sec | 45% | 11 GB | -| 8XL | 32-core | 128 GB | 1,000,000 | 815 | 0.072 sec | 0.106 sec | 75% | 13 GB | -| 12XL | 48-core | 192 GB | 1,000,000 | 1150 | 0.052 sec | 0.078 sec | 70% | 15.5 GB | -| 16XL | 64-core | 256 GB | 1,000,000 | 1345 | 0.072 sec | 0.106 sec | 60% | 17.5 GB | - -- Lists set to `Number of vectors / 1000` -- Probes set to `10` - - - -It is possible to upload more than 1,000,000 vectors to a single table if Memory allows it (for example, 2XL instance and higher). But it will affect the performance of the queries: RPS will be lower, and latency will be higher. Scaling should be almost linear, but it is recommended to benchmark your workload to find the optimal number of vectors per table and per instance. - - - -## Methodology - -We follow techniques outlined in the [ANN Benchmarks](https://github.com/erikbern/ann-benchmarks) methodology. A Python test runner is responsible for uploading the data, creating the index, and running the queries. The pgvector engine is implemented using [vecs](https://github.com/supabase/vecs), a Python client for pgvector. - -
- multi database - multi database -
- -Each test is run for a minimum of 30-40 minutes. They include a series of experiments executed at different concurrency levels to measure the engine's performance under different load types. The results are then averaged. - -As a general recommendation, we suggest using a concurrency level of 5 or more for most workloads and 30 or more for high-load workloads. - -## Future benchmarks - -We'll continue to add more benchmarks on datasets consisting of different vector dimensions, number of `lists` in the index, and number of `probes` in the index. Stay tuned for more information about how it may affect the performance and precision of your queries. - -export const Page = ({ children }) => - -export default Page diff --git a/apps/docs/pages/guides/ai/examples/headless-vector-search.mdx b/apps/docs/pages/guides/ai/examples/headless-vector-search.mdx index 467d3788a38..31cabb29dcf 100644 --- a/apps/docs/pages/guides/ai/examples/headless-vector-search.mdx +++ b/apps/docs/pages/guides/ai/examples/headless-vector-search.mdx @@ -37,7 +37,7 @@ There are 3 steps to build similarity search inside your documentation: ### Prepare your database -To prepare, create a [new Supabase project](https://database.new) and store the database and API credentials, which you can find in the project [settings](https://app.supabase.com/_/settings). +To prepare, create a [new Supabase project](https://database.new) and store the database and API credentials, which you can find in the project [settings](https://supabase.com/dashboard/_/settings). Now we can use the [Headless Vector Search](https://github.com/supabase/headless-vector-search#set-up) instructions to set up the database: @@ -46,7 +46,7 @@ Now we can use the [Headless Vector Search](https://github.com/supabase/headless 3. Apply the database migrations: `supabase db push` 4. Set your OpenAI key as a secret: `supabase secrets set OPENAI_KEY=sk-xxx` 5. Deploy the Edge Functions: `supabase functions deploy --no-verify-jwt` -6. Expose `docs` schema via API in Supabase Dashboard [settings](https://app.supabase.com/project/_/settings/api) > `API Settings` > `Exposed schemas` +6. Expose `docs` schema via API in Supabase Dashboard [settings](https://supabase.com/dashboard/project/_/settings/api) > `API Settings` > `Exposed schemas` ### Ingest your documentation diff --git a/apps/docs/pages/guides/ai/examples/huggingface-image-captioning.mdx b/apps/docs/pages/guides/ai/examples/huggingface-image-captioning.mdx index 1f891655d85..163422ee325 100644 --- a/apps/docs/pages/guides/ai/examples/huggingface-image-captioning.mdx +++ b/apps/docs/pages/guides/ai/examples/huggingface-image-captioning.mdx @@ -20,15 +20,15 @@ We can combine Hugging Face with [Supabase Storage](https://supabase.com/storage ## Setup -- Open your Supabase project dashboard or [create a new project](https://app.supabase.com/projects). -- [Create a new bucket](https://app.supabase.com/project/_/storage/buckets) called `images`. +- Open your Supabase project dashboard or [create a new project](https://supabase.com/dashboard/projects). +- [Create a new bucket](https://supabase.com/dashboard/project/_/storage/buckets) called `images`. - Generate TypeScript types from remote Database. - Create a new Database table called `image_caption`. - Create `id` column of type `uuid` which references `storage.objects.id`. - Create a `caption` column of type `text`. - Regenerate TypeScript types to include new `image_caption` table. - Deploy the function to Supabase: `supabase functions deploy huggingface-image-captioning`. -- Create the Database Webhook in the [Supabase Dashboard](https://app.supabase.com/project/_/database/hooks) to trigger the `huggingface-image-captioning` function anytime a record is added to the `storage.objects` table. +- Create the Database Webhook in the [Supabase Dashboard](https://supabase.com/dashboard/project/_/database/hooks) to trigger the `huggingface-image-captioning` function anytime a record is added to the `storage.objects` table. ## Generate TypeScript Types diff --git a/apps/docs/pages/guides/ai/examples/nextjs-vector-search.mdx b/apps/docs/pages/guides/ai/examples/nextjs-vector-search.mdx index b340a6607b6..017eb68ec95 100644 --- a/apps/docs/pages/guides/ai/examples/nextjs-vector-search.mdx +++ b/apps/docs/pages/guides/ai/examples/nextjs-vector-search.mdx @@ -22,13 +22,13 @@ We assume that you have a Next.js project with a collection of `.mdx` files nest ## Create a project -1. [Create a new project](https://app.supabase.com) in the Supabase Dashboard. +1. [Create a new project](https://supabase.com/dashboard) in the Supabase Dashboard. 1. Enter your project details. 1. Wait for the new database to launch. ## Prepare the database -Let's prepare the database schema. We can use the "OpenAI Vector Search" quickstart in the [SQL Editor](https://app.supabase.com/project/_/sql), or you can copy/paste the SQL below and run it yourself. +Let's prepare the database schema. We can use the "OpenAI Vector Search" quickstart in the [SQL Editor](https://supabase.com/dashboard/project/_/sql), or you can copy/paste the SQL below and run it yourself. -1. Go to the [SQL Editor](https://app.supabase.com/project/_/sql) page in the Dashboard. +1. Go to the [SQL Editor](https://supabase.com/dashboard/project/_/sql) page in the Dashboard. 2. Click **OpenAI Vector Search**. 3. Click **Run**. diff --git a/apps/docs/pages/guides/ai/google-colab.mdx b/apps/docs/pages/guides/ai/google-colab.mdx index c3e02029842..d6edee7ba26 100644 --- a/apps/docs/pages/guides/ai/google-colab.mdx +++ b/apps/docs/pages/guides/ai/google-colab.mdx @@ -17,7 +17,7 @@ export const meta = { Google Colab is a hosted Jupyter Notebook service. It provides free access to computing resources, including GPUs and TPUs, and is well-suited to machine learning, data science, and education. We can use Colab to manage collections using [Supabase Vecs](/docs/guides/ai/vecs-python-client). -In this tutorial we'll connect to a database running on the Supabase [platform](https://app.supabase.com/). If you don't already have a database, you can create one here: [database.new](https://database.new). +In this tutorial we'll connect to a database running on the Supabase [platform](https://supabase.com/dashboard/). If you don't already have a database, you can create one here: [database.new](https://database.new). ## Create a new notebook @@ -39,7 +39,7 @@ pip install vecs ## Connect to your database -Find the Postgres connection string for your Supabase project in the [database settings](https://app.supabase.com/_/settings/database) of the dashboard. Copy the "URI" format, which should look something like `postgresql:/postgres:@:5432/postgres` +Find the Postgres connection string for your Supabase project in the [database settings](https://supabase.com/dashboard/_/settings/database) of the dashboard. Copy the "URI" format, which should look something like `postgresql:/postgres:@:5432/postgres` Create a new code block below the install block (`ctrl+m b`) and add the following code using the Postgres URI you copied above: @@ -79,7 +79,7 @@ collection.upsert( ) ``` -This will create a table inside your database within the `vecs` schema, called `colab_collection`. You can view the inserted items in the [Table Editor](https://app.supabase.com/project/_/editor/), by selecting the `vecs` schema from the schema dropdown. +This will create a table inside your database within the `vecs` schema, called `colab_collection`. You can view the inserted items in the [Table Editor](https://supabase.com/dashboard/project/_/editor/), by selecting the `vecs` schema from the schema dropdown. ![Colab documents](/docs/img/ai/google-colab/colab-documents.png) diff --git a/apps/docs/pages/guides/ai/integrations/llamaindex.mdx b/apps/docs/pages/guides/ai/integrations/llamaindex.mdx index 59db32b9cd3..b1aa7f80b2a 100644 --- a/apps/docs/pages/guides/ai/integrations/llamaindex.mdx +++ b/apps/docs/pages/guides/ai/integrations/llamaindex.mdx @@ -52,7 +52,7 @@ Replace the `DB_CONNECTION` with your own connection string for your database, w Now all that's left is to step through the notebook. You can do this by clicking the "execute" button (`ctrl+enter`) at the top left of each code cell. The notebook guides you through the process of creating a collection, adding data to it, and querying it. -You can view the inserted items in the [Table Editor](https://app.supabase.com/project/_/editor/), by selecting the `vecs` schema from the schema dropdown. +You can view the inserted items in the [Table Editor](https://supabase.com/dashboard/project/_/editor/), by selecting the `vecs` schema from the schema dropdown. ![Colab documents](/docs/img/ai/google-colab/colab-documents.png) diff --git a/apps/docs/pages/guides/ai/langchain.mdx b/apps/docs/pages/guides/ai/langchain.mdx index 3f66da36b3e..fa8320819a2 100644 --- a/apps/docs/pages/guides/ai/langchain.mdx +++ b/apps/docs/pages/guides/ai/langchain.mdx @@ -1,4 +1,6 @@ import Layout from '~/layouts/DefaultGuideLayout' +import { Tabs } from 'ui' +export const TabPanel = Tabs.Panel export const meta = { id: 'ai-lang-chain', @@ -14,6 +16,21 @@ export const meta = { Prepare you database with the relevant tables: + + + +1. Go to the [SQL Editor](https://supabase.com/dashboard/project/_/sql) page in the Dashboard. +2. Click **LangChain** in the Quick start section. +3. Click **Run**. + + + + ```sql -- Enable the pgvector extension to work with embedding vectors create extension vector; @@ -55,6 +72,9 @@ end; $$; ``` + + + ## Usage You can now search your documents using any Node.js application. This is intended to be run on a secure server route. diff --git a/apps/docs/pages/guides/ai/managing-collections.mdx b/apps/docs/pages/guides/ai/managing-collections.mdx index 58e700e2927..5ed4d45ce42 100644 --- a/apps/docs/pages/guides/ai/managing-collections.mdx +++ b/apps/docs/pages/guides/ai/managing-collections.mdx @@ -9,7 +9,7 @@ export const meta = { A collection is a group of vector records managed by the `vecs` Python library. Records can be added to or updated in a collection. Collections can be queried at any time, but should be indexed for scalable query performance. -Supabase provides a [Python client](/docs/guides/ai/vecs-python-client) called `vecs` for managing unstructured vector stores in Postgres. If you come from a data science background, this unstructured data approach will feel familiar. If you are more interested in a structured data approach, see [Vector columns](/docs/guides/ai/vector-columns) or read our guide on [Structured & Unstructured Embeddings](/docs/guides/ai/structured-unstructured-embeddings). +Supabase provides a [Python client](/docs/guides/ai/vecs-python-client) called `vecs` for managing unstructured vector stores in Postgres. If you come from a data science background, this unstructured data approach will feel familiar. If you are more interested in a structured data approach, see [Vector columns](/docs/guides/ai/vector-columns) or read our guide on [Structured & Unstructured Embeddings](/docs/guides/ai/structured-unstructured). Under the hood `vecs` will manage the necessary Postgres tables and columns to store and query your collections. diff --git a/apps/docs/pages/guides/ai/quickstarts/face-similarity.mdx b/apps/docs/pages/guides/ai/quickstarts/face-similarity.mdx index 6996f4c1046..160ed479b6d 100644 --- a/apps/docs/pages/guides/ai/quickstarts/face-similarity.mdx +++ b/apps/docs/pages/guides/ai/quickstarts/face-similarity.mdx @@ -49,7 +49,7 @@ Replace the `DB_CONNECTION` with your own connection string for your database, w Now all that's left is to step through the notebook. You can do this by clicking the "execute" button (`ctrl+enter`) at the top left of each code cell. The notebook guides you through the process of creating a collection, adding data to it, and querying it. -You can view the inserted items in the [Table Editor](https://app.supabase.com/project/_/editor/), by selecting the `vecs` schema from the schema dropdown. +You can view the inserted items in the [Table Editor](https://supabase.com/dashboard/project/_/editor/), by selecting the `vecs` schema from the schema dropdown. ![Colab documents](/docs/img/ai/google-colab/colab-documents.png) diff --git a/apps/docs/pages/guides/ai/quickstarts/hello-world.mdx b/apps/docs/pages/guides/ai/quickstarts/hello-world.mdx index 7b678dc1d20..d612ed23d86 100644 --- a/apps/docs/pages/guides/ai/quickstarts/hello-world.mdx +++ b/apps/docs/pages/guides/ai/quickstarts/hello-world.mdx @@ -49,7 +49,7 @@ Replace the `DB_CONNECTION` with your own connection string for your database, w Now all that's left is to step through the notebook. You can do this by clicking the "execute" button (`ctrl+enter`) at the top left of each code cell. The notebook guides you through the process of creating a collection, adding data to it, and querying it. -You can view the inserted items in the [Table Editor](https://app.supabase.com/project/_/editor/), by selecting the `vecs` schema from the schema dropdown. +You can view the inserted items in the [Table Editor](https://supabase.com/dashboard/project/_/editor/), by selecting the `vecs` schema from the schema dropdown. ![Colab documents](/docs/img/ai/google-colab/colab-documents.png) diff --git a/apps/docs/pages/guides/ai/quickstarts/text-deduplication.mdx b/apps/docs/pages/guides/ai/quickstarts/text-deduplication.mdx index 8d20cf9cca4..d15cbbd1289 100644 --- a/apps/docs/pages/guides/ai/quickstarts/text-deduplication.mdx +++ b/apps/docs/pages/guides/ai/quickstarts/text-deduplication.mdx @@ -50,7 +50,7 @@ Replace the `DB_CONNECTION` with your own connection string for your database, w Now all that's left is to step through the notebook. You can do this by clicking the "execute" button (`ctrl+enter`) at the top left of each code cell. The notebook guides you through the process of creating a collection, adding data to it, and querying it. -You can view the inserted items in the [Table Editor](https://app.supabase.com/project/_/editor/), by selecting the `vecs` schema from the schema dropdown. +You can view the inserted items in the [Table Editor](https://supabase.com/dashboard/project/_/editor/), by selecting the `vecs` schema from the schema dropdown. ![Colab documents](/docs/img/ai/google-colab/colab-documents.png) diff --git a/apps/docs/pages/guides/ai/structured-unstructured.mdx b/apps/docs/pages/guides/ai/structured-unstructured.mdx index 0c392c20e09..04b35b5b4cb 100644 --- a/apps/docs/pages/guides/ai/structured-unstructured.mdx +++ b/apps/docs/pages/guides/ai/structured-unstructured.mdx @@ -23,7 +23,7 @@ create table docs ( ); insert into docs - (id, content, url, embedding) + (id, embedding, content, url) values ('79409372-7556-4ccc-ab8f-5786a6cfa4f7', array[0.1, 0.2, 0.3], 'Hello world', '/hello-world'); ``` @@ -89,7 +89,7 @@ create table docs ( ); insert into docs - (id, embedding, meta) + (id, embedding, content, url, meta) values ( '79409372-7556-4ccc-ab8f-5786a6cfa4f7', diff --git a/apps/docs/pages/guides/ai/vector-columns.mdx b/apps/docs/pages/guides/ai/vector-columns.mdx index d941c164302..7c768606e0b 100644 --- a/apps/docs/pages/guides/ai/vector-columns.mdx +++ b/apps/docs/pages/guides/ai/vector-columns.mdx @@ -23,7 +23,7 @@ Vectors in Supabase are enabled via [pgvector](https://github.com/pgvector/pgvec > -1. Go to the [Database](https://app.supabase.com/project/_/database/tables) page in the Dashboard. +1. Go to the [Database](https://supabase.com/dashboard/project/_/database/tables) page in the Dashboard. 2. Click on **Extensions** in the sidebar. 3. Search for "vector" and enable the extension. diff --git a/apps/docs/pages/guides/api.mdx b/apps/docs/pages/guides/api.mdx index 7ca9052585d..5ac4bc65ba3 100644 --- a/apps/docs/pages/guides/api.mdx +++ b/apps/docs/pages/guides/api.mdx @@ -50,7 +50,7 @@ Reference: ## GraphQL API [#graphql-api-overview] Supabase uses [pg_graphql](https://supabase.github.io/pg_graphql/) to expose a GraphQL API endpoint at `https://.supabase.co/graphql/v1/`. -You can introspect and query the GraphQL API of an existing Supabase project within Studio [here](https://app.supabase.com/project/_/api/graphiql), +You can introspect and query the GraphQL API of an existing Supabase project within Studio [here](https://supabase.com/dashboard/project/_/api/graphiql), or navigate there manually at `API Docs > GraphQL > GraphiQL`. The GraphQL interface is automatically reflected from your database's schema and supports: @@ -72,11 +72,11 @@ Reference: Supabase provides a Realtime API using [Realtime](https://github.com/supabase/realtime). You can use this to listen to database changes over websockets. Realtime leverages PostgreSQL's built-in logical replication. You can manage your Realtime API simply by managing Postgres publications. -Go to your project's [Replication section](https://app.supabase.com/project/_/database/replication) to get started. +Go to your project's [Replication section](https://supabase.com/dashboard/project/_/database/replication) to get started. ## API URL and Keys -You can find the API URL and Keys in the [Dashboard](https://app.supabase.com/project/_/settings/api). +You can find the API URL and Keys in the [Dashboard](https://supabase.com/dashboard/project/_/settings/api).
Accept the invite + +``` +When the user clicks on the link, the request will hit `https://api.example.com/v1/authenticate` and you can grab the `token_hash` and `type` query parameters from the URL. Then, you can call the [`verifyOtp`](/docs/reference/javascript/auth-verifyotp) method to get back an authenticated session before redirecting the user back to the client. Since the `verifyOtp` method makes a `POST` request to Supabase Auth to verify the user, the session will be returned in the response body, which can be read by the server. For example: + +```js +const { token_hash, type } = Object.fromEntries(new URLSearchParams(window.location.search)) +const { data: { session }, error } = supabase.auth.verifyOtp({ token_hash, type }) + +// subsequently redirect the user back to the client +// ... + +``` + export const Page = ({ children }) => export default Page diff --git a/apps/docs/pages/guides/auth/auth-email.mdx b/apps/docs/pages/guides/auth/auth-email.mdx index ce29b1e970b..2aa114b48a2 100644 --- a/apps/docs/pages/guides/auth/auth-email.mdx +++ b/apps/docs/pages/guides/auth/auth-email.mdx @@ -10,13 +10,13 @@ export const meta = { Setting up Email logins for your Supabase application. -- Add Email authenticator to your [Supabase Project](https://app.supabase.com) +- Add Email authenticator to your [Supabase Project](https://supabase.com/dashboard) - Add the login code to your application - [JavaScript](https://github.com/supabase/supabase-js) | [Flutter](https://github.com/supabase/supabase-flutter) ## Configure email settings -1. For [Site URL](https://app.supabase.com/project/_/auth/url-configuration), enter the final (hosted) URL of your app. -1. For [Auth Providers](https://app.supabase.com/project/_/auth/providers), **enable email provider**. +1. For [Site URL](https://supabase.com/dashboard/project/_/auth/url-configuration), enter the final (hosted) URL of your app. +1. For [Auth Providers](https://supabase.com/dashboard/project/_/auth/providers), **enable email provider**. diff --git a/apps/docs/pages/guides/auth/auth-helpers/nextjs-pages.mdx b/apps/docs/pages/guides/auth/auth-helpers/nextjs-pages.mdx index bfadfe16dd3..fc23df156a4 100644 --- a/apps/docs/pages/guides/auth/auth-helpers/nextjs-pages.mdx +++ b/apps/docs/pages/guides/auth/auth-helpers/nextjs-pages.mdx @@ -31,7 +31,7 @@ npm install @supabase/auth-helpers-react ## Set up environment variables -Retrieve your project URL and anon key in your project's [API settings](https://app.supabase.com/project/_/settings/api) in the Dashboard to set up the following environment variables. For local development you can set them in a `.env.local` file. See an [example](https://github.com/supabase/auth-helpers/blob/main/examples/nextjs/.env.local.example). +Retrieve your project URL and anon key in your project's [API settings](https://supabase.com/dashboard/project/_/settings/api) in the Dashboard to set up the following environment variables. For local development you can set them in a `.env.local` file. See an [example](https://github.com/supabase/auth-helpers/blob/main/examples/nextjs/.env.local.example). ```bash .env.local NEXT_PUBLIC_SUPABASE_URL=your-supabase-url diff --git a/apps/docs/pages/guides/auth/auth-helpers/nextjs.mdx b/apps/docs/pages/guides/auth/auth-helpers/nextjs.mdx index 14a578741ad..c66d2e48e4c 100644 --- a/apps/docs/pages/guides/auth/auth-helpers/nextjs.mdx +++ b/apps/docs/pages/guides/auth/auth-helpers/nextjs.mdx @@ -43,7 +43,7 @@ This creates a new Next.js app configured with: ### Declare Environment Variables -Retrieve your project's URL and anon key from your [API settings](https://app.supabase.com/project/_/settings/api), and create a `.env.local` file with the following environment variables: +Retrieve your project's URL and anon key from your [API settings](https://supabase.com/dashboard/project/_/settings/api), and create a `.env.local` file with the following environment variables: ```bash .env.local NEXT_PUBLIC_SUPABASE_URL=your-supabase-url @@ -68,7 +68,7 @@ npm install @supabase/auth-helpers-nextjs @supabase/supabase-js ### Declare Environment Variables -Retrieve your project's URL and anon key from your [API settings](https://app.supabase.com/project/_/settings/api), and create a `.env.local` file with the following environment variables: +Retrieve your project's URL and anon key from your [API settings](https://supabase.com/dashboard/project/_/settings/api), and create a `.env.local` file with the following environment variables: ```bash .env.local NEXT_PUBLIC_SUPABASE_URL=your-supabase-url @@ -79,7 +79,7 @@ NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key 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. -In Next.js Server Components, you can read a cookie, but you can't write back to it. Middleware on the other hand, allow you to both read a write to cookies. +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. @@ -528,7 +528,7 @@ This allows for the Supabase client to be easily instantiated in the correct con
-
- -## Install `supabase-js` Client - -```bash -npm install @supabase/supabase-js -``` - -## Cursor Positions - -[Broadcast](/docs/guides/realtime/broadcast) allows a client to send messages and multiple clients to receive the messages. The broadcasted messages are ephemeral. They are not persisted to the database and are directly relayed through the Realtime servers. This is ideal for sending information like cursor positions where minimal latency is important, but persisting them is not. - -In [multiplayer.dev](https://multiplayer.dev), client's cursor positions are sent to other clients in the room. However, cursor positions will be randomly generated for this example. - -You need to get the public `anon` access token from your project's [API settings](https://app.supabase.com/project/_/settings/api). Then you can set up the Supabase client and start sending a client's cursor positions to other clients in channel `room1`: - -```js -const { createClient } = require('@supabase/supabase-js') - -const supabase = createClient('https://your-project-ref.supabase.co', 'anon-key', { - realtime: { - params: { - eventsPerSecond: 10, - }, - }, -}) - -// Channel name can be any string. -// Create channels with the same name for both the broadcasting and receiving clients. -const channel = supabase.channel('room1') - -// Subscribe registers your client with the server -channel.subscribe((status) => { - if (status === 'SUBSCRIBED') { - // now you can start broadcasting cursor positions - setInterval(() => { - channel.send({ - type: 'broadcast', - event: 'cursor-pos', - payload: { x: Math.random(), y: Math.random() }, - }) - console.log(status) - }, 100) - } -}) -``` - - - -JavaScript client has a default rate limit of 1 Realtime event every 100 milliseconds that's configured by `eventsPerSecond`. - - - -Another client can subscribe to channel `room1` and receive cursor positions: - -```js -// Supabase client setup - -// Listen to broadcast messages. -supabase - .channel('room1') - .on('broadcast', { event: 'cursor-pos' }, (payload) => console.log(payload)) - .subscribe((status) => { - if (status === 'SUBSCRIBED') { - // your callback function will now be called with the messages broadcast by the other client - } - }) -``` - - - -`type` must be `broadcast` and the `event` must match for clients subscribed to the channel. - - - -## Roundtrip Latency - -You can also configure the channel so that the server must return an acknowledgement that it received the `broadcast` message. This is useful if you want to measure the roundtrip latency: - -```js -// Supabase client setup - -const channel = supabase.channel('calc-latency', { - config: { - broadcast: { ack: true }, - }, -}) - -channel.subscribe(async (status) => { - if (status === 'SUBSCRIBED') { - const begin = performance.now() - - await channel.send({ - type: 'broadcast', - event: 'latency', - payload: {}, - }) - - const end = performance.now() - - console.log(`Latency is ${end - begin} milliseconds`) - } -}) -``` - -## Track and Display Which Users Are Online - -[Presence](/docs/guides/realtime/presence) stores and synchronize shared state across clients. The `sync` event is triggered whenever the shared state changes. The `join` event is triggered when new clients join the channel and `leave` event is triggered when clients leave. - -Each client can use the channel's `track` method to store an object in shared state. Each client can only track one object, and if `track` is called again by the same client, then the new object overwrites the previously tracked object in the shared state. You can use one client to track and display users who are online: - -```js -// Supabase client setup - -const channel = supabase.channel('online-users', { - config: { - presence: { - key: 'user1', - }, - }, -}) - -channel.on('presence', { event: 'sync' }, () => { - console.log('Online users: ', channel.presenceState()) -}) - -channel.on('presence', { event: 'join' }, ({ newPresences }) => { - console.log('New users have joined: ', newPresences) -}) - -channel.on('presence', { event: 'leave' }, ({ leftPresences }) => { - console.log('Users have left: ', leftPresences) -}) - -channel.subscribe(async (status) => { - if (status === 'SUBSCRIBED') { - const status = await channel.track({ online_at: new Date().toISOString() }) - console.log(status) - } -}) -``` - -Then you can use another client to add another user to the channel's Presence state: - -```js -// Supabase client setup - -const channel = supabase.channel('online-users', { - config: { - presence: { - key: 'user2', - }, - }, -}) - -// Presence event handlers setup - -channel.subscribe(async (status) => { - if (status === 'SUBSCRIBED') { - const status = await channel.track({ online_at: new Date().toISOString() }) - console.log(status) - } -}) -``` - -If a channel is set up without a presence key, the server generates a random UUID. `type` must be `presence` and `event` must be either `sync`, `join`, or `leave`. - -## Insert and Receive Persisted Messages - -[Postgres Changes](/docs/guides/realtime#postgres-changes) enables your client to insert, update, or delete database records and send the changes to clients. Create a `messages` table to keep track of messages created by users in specific rooms: - -```sql -create table messages ( - id serial primary key, - message text, - user_id text, - room_id text, - created_at timestamptz default now() -) - -alter table messages enable row level security; - -create policy "anon_ins_policy" -ON messages -for insert -to anon -with check (true); - -create policy "anon_sel_policy" -ON messages -for select -to anon -using (true); -``` - -If it doesn't already exist, create a `supabase_realtime` publication and add `messages` table to the publication: - -```sql -begin; - -- remove the supabase_realtime publication - drop publication if exists supabase_realtime; - - -- re-create the supabase_realtime publication with no tables and only for insert - create publication supabase_realtime with (publish = 'insert'); -commit; - --- add a table to the publication -alter publication supabase_realtime add table messages; -``` - -You can then have a client listen for changes on the `messages` table for a specific room and send and receive persisted messages: - -```js -// Supabase client setup - -const channel = supabase.channel('db-messages') - -const roomId = 'room1' -const userId = 'user1' - -channel.on( - 'postgres_changes', - { - event: 'INSERT', - schema: 'public', - table: 'messages', - filter: `room_id=eq.${roomId}`, - }, - (payload) => console.log(payload) -) - -channel.subscribe(async (status) => { - if (status === 'SUBSCRIBED') { - const res = await supabase.from('messages').insert({ - room_id: roomId, - user_id: userId, - message: 'Welcome to Realtime!', - }) - console.log(res) - } -}) -``` - -export const Page = ({ children }) => - -export default Page diff --git a/apps/docs/pages/guides/realtime/quotas.mdx b/apps/docs/pages/guides/realtime/quotas.mdx index dc083129c4f..8f9ec1e6121 100644 --- a/apps/docs/pages/guides/realtime/quotas.mdx +++ b/apps/docs/pages/guides/realtime/quotas.mdx @@ -9,7 +9,7 @@ export const meta = { -Upgrade your plan to increase your quotas. Without a spend cap, or on an Enterprise plan, some quotas are still in place to protect budgets. All quotas are configurable per project. [Contact support](https://app.supabase.com/support/new) if you need your quotas increased. Our cluster supports millions of concurrent connections and message throughput for production workloads. +Upgrade your plan to increase your quotas. Without a spend cap, or on an Enterprise plan, some quotas are still in place to protect budgets. All quotas are configurable per project. [Contact support](https://supabase.com/dashboard/support/new) if you need your quotas increased. Our cluster supports millions of concurrent connections and message throughput for production workloads. @@ -26,13 +26,13 @@ Upgrade your plan to increase your quotas. Without a spend cap, or on an Enterpr | **Broadcast payload size KB** | 256 | 3,000 | 3,000 | 3,000 | 3,000 | | **Postgres change payload size KB ([**read more**](#postgres-changes-payload-quota))** | 1,024 | 1,024 | 1,024 | 1,024 | 1,024 | -Beyond the Free and Pro plan you can customize your quotas by [contacting support](https://app.supabase.com/support/new). +Beyond the Free and Pro plan you can customize your quotas by [contacting support](https://supabase.com/dashboard/support/new). ## Client-Side Limiting Some basic WebSocket message rate limiting is implemented client-side. -For example, the [multiplayer.dev demo](/docs/guides/realtime/quickstart#cursor-positions) instantiates the Supabase client with an `eventsPerSecond` parameter. +For example, the [multiplayer.dev](https://multiplayer.dev) instantiates the Supabase client with an `eventsPerSecond` parameter. ## Quota Errors @@ -46,7 +46,7 @@ Use the [Realtime Inspector](https://realtime.supabase.com/inspector/new) to rep ### Backend Logs -If your project is being limited by a quota, check your [Realtime logs](https://app.supabase.com/project/_/database/realtime-logs). +If your project is being limited by a quota, check your [Realtime logs](https://supabase.com/dashboard/project/_/database/realtime-logs). ### WebSocket Errors diff --git a/apps/docs/pages/guides/resources/examples.mdx b/apps/docs/pages/guides/resources/examples.mdx index a414b43b63e..32c45d50c01 100644 --- a/apps/docs/pages/guides/resources/examples.mdx +++ b/apps/docs/pages/guides/resources/examples.mdx @@ -59,7 +59,7 @@ By [Fireship](https://www.youtube.com/watch?v=WiwfiVdfRIc). Build a basic Todo List with Supabase and your favorite frontend framework: - [Expo Todo List.](https://github.com/supabase/examples/tree/main/supabase-js-v1/todo-list/expo-todo-list) -- [Next.js Todo List.](https://github.com/supabase/examples/tree/main/supabase-js-v1/todo-list/nextjs-todo-list) +- [Next.js Todo List.](https://github.com/supabase/supabase/tree/master/examples/todo-list/nextjs-todo-list) - [React Todo List.](https://github.com/supabase/examples/tree/main/supabase-js-v1/todo-list/react-todo-list) - [Svelte Todo List.](https://github.com/supabase/supabase/tree/master/examples/todo-list/sveltejs-todo-list) - [Vue 3 Todo List (Typescript).](https://github.com/supabase/examples/tree/main/supabase-js-v1/todo-list/vue3-ts-todo-list) @@ -69,7 +69,7 @@ Build a basic Todo List with Supabase and your favorite frontend framework: ### Auth examples - [Supabase Auth with vanilla JavaScript.](https://github.com/supabase/examples/tree/main/supabase-js-v1/auth/javascript-auth). Use Supabase without any frontend frameworks. -- [Supabase Auth with Next.js](https://github.com/supabase/supabase/tree/master/examples/user-management/nextjs-ts-user-management). +- [Supabase Auth with Next.js](https://github.com/supabase/supabase/tree/master/examples/user-management/nextjs-user-management). - [Supabase Auth with RedwoodJS.](https://redwood-playground-auth.netlify.app/supabase) Try out Supabase authentication in the [RedwoodJS](https://redwoodjs.com) Authentication Playground complete with OAuth support and code samples. ### Collaborative @@ -110,6 +110,7 @@ Build a basic Todo List with Supabase and your favorite frontend framework: - Flutter Supabase Authentication [Blog](https://www.sandromaglione.com/2021/04/24/flutter-supabase-authentication/) - Supabase in 6 minutes [Video](https://www.youtube.com/watch?v=c8DNV9yl0mg) - Supabase React Auth UI Tutorial [Video](https://youtu.be/6ch1PtIqCUw) +- Supabase React File Upload Tutorial [Video](https://youtu.be/HvOvdD2nX1k) - Let's build SupaAuth - Build an Authentication System using Supabase, Next.js and Typescript [6-part Blog Series](https://aalam.in/blog/supabase-auth-intro-setup-next) - In-depth self-hosting guide using Nginx [Blog](https://dev.to/chronsyn/self-hosting-with-supabase-1aii) - Build an Email and Social Auth for Next JS with Supabase, Tailwind CSS 3.0 and TypeScript [Blog](https://creativedesignsguru.com/next-js-supabase-auth/) diff --git a/apps/docs/pages/guides/resources/migrating-to-supabase/amazon-rds.mdx b/apps/docs/pages/guides/resources/migrating-to-supabase/amazon-rds.mdx index b81e0266558..3a2f4315d65 100644 --- a/apps/docs/pages/guides/resources/migrating-to-supabase/amazon-rds.mdx +++ b/apps/docs/pages/guides/resources/migrating-to-supabase/amazon-rds.mdx @@ -23,10 +23,10 @@ Supabase's core is Postgres, enabling the use of row-level security and providin ## Retrieve your Supabase Host [#retrieve-supabase-host] -1. If you're new to Supabase, [create a project](https://app.supabase.com). -1. Go to the [Database settings](https://app.supabase.com/project/_/settings/database) for your project in the Supabase Dashboard. +1. If you're new to Supabase, [create a project](https://supabase.com/dashboard). +1. Go to the [Database settings](https://supabase.com/dashboard/project/_/settings/database) for your project in the Supabase Dashboard. 1. Under **Connection Info**, note your Host (`$SUPABASE_HOST`). -1. Save your password or [reset it](https://app.supabase.com/project/_/settings/database) if you forgot it. +1. Save your password or [reset it](https://supabase.com/dashboard/project/_/settings/database) if you forgot it. ![Finding Supabase host address](/docs/img/guides/resources/migrating-to-supabase/amazon-rds/supabase_dashboard.png) @@ -95,7 +95,7 @@ pgloader config.load -- If you plan on migrating a database larger than 6 GB, we recommend [contacting support](https://app.supabase.com/support/new) to ensure that you'll have the proper disk size pre-provisioned. You can read more about how the disk is managed on Supabase on the [Database usage](/docs/guides/platform/database-size#disk-management). +- If you plan on migrating a database larger than 6 GB, we recommend [contacting support](https://supabase.com/dashboard/support/new) to ensure that you'll have the proper disk size pre-provisioned. You can read more about how the disk is managed on Supabase on the [Database usage](/docs/guides/platform/database-size#disk-management). - We also recommend upgrading to at least a [Large instance](/docs/guides/platform/compute-add-ons) for the migration (you can downgrade later) to avoid running out of IO-Budget. diff --git a/apps/docs/pages/guides/resources/migrating-to-supabase/firebase-auth.mdx b/apps/docs/pages/guides/resources/migrating-to-supabase/firebase-auth.mdx index 2a4aa49db48..9b898785f38 100644 --- a/apps/docs/pages/guides/resources/migrating-to-supabase/firebase-auth.mdx +++ b/apps/docs/pages/guides/resources/migrating-to-supabase/firebase-auth.mdx @@ -32,7 +32,7 @@ git clone https://github.com/supabase-community/firebase-to-supabase.git } ``` -1. Go to the [Database settings](https://app.supabase.com/project/_/settings/database) for your project in the Supabase Dashboard. +1. Go to the [Database settings](https://supabase.com/dashboard/project/_/settings/database) for your project in the Supabase Dashboard. 1. Under **Connection Info**, copy the Host string and replace the entry in your `supabase-service.json` file. 1. Enter the password you used when you created your Supabase project in the `password` entry in the `supabase-service.json` file. diff --git a/apps/docs/pages/guides/resources/migrating-to-supabase/firebase-storage.mdx b/apps/docs/pages/guides/resources/migrating-to-supabase/firebase-storage.mdx index 1516dd2537b..6159663db96 100644 --- a/apps/docs/pages/guides/resources/migrating-to-supabase/firebase-storage.mdx +++ b/apps/docs/pages/guides/resources/migrating-to-supabase/firebase-storage.mdx @@ -21,7 +21,7 @@ git clone https://github.com/supabase-community/firebase-to-supabase.git ``` 1. In the `/storage` directory, rename [supabase-keys-sample.js](https://github.com/supabase-community/firebase-to-supabase/blob/main/storage/supabase-keys-sample.js) to `supabase-keys.js`. -1. Go to your Supabase project's [API settings](https://app.supabase.com/project/_/settings/api) in the Dashboard. +1. Go to your Supabase project's [API settings](https://supabase.com/dashboard/project/_/settings/api) in the Dashboard. 1. Copy the **Project URL** and update the `SUPABASE_URL` value in `supabase-keys.js`. 1. Under **Project API keys**, copy the **service_role** key and update the `SUPABASE_KEY` value in `supabase-keys.js`. @@ -57,7 +57,7 @@ To process in batches using multiple command-line executions, you must use the s -If the bucket doesn't exist, it's created as a `non-public` bucket. You must set permissions on this new bucket in the [Supabase Dashboard](https://app.supabase.com/project/_/storage/buckets) before users can download any files. +If the bucket doesn't exist, it's created as a `non-public` bucket. You must set permissions on this new bucket in the [Supabase Dashboard](https://supabase.com/dashboard/project/_/storage/buckets) before users can download any files. diff --git a/apps/docs/pages/guides/resources/migrating-to-supabase/firestore-data.mdx b/apps/docs/pages/guides/resources/migrating-to-supabase/firestore-data.mdx index 24dd49fa488..c8d30b87b40 100644 --- a/apps/docs/pages/guides/resources/migrating-to-supabase/firestore-data.mdx +++ b/apps/docs/pages/guides/resources/migrating-to-supabase/firestore-data.mdx @@ -31,7 +31,7 @@ git clone https://github.com/supabase-community/firebase-to-supabase.git } ``` -1. Go to the [Database settings](https://app.supabase.com/project/_/settings/database) for your project in the Supabase Dashboard. +1. Go to the [Database settings](https://supabase.com/dashboard/project/_/settings/database) for your project in the Supabase Dashboard. 1. Under **Connection Info**, copy the Host string and replace the entry in your `supabase-service.json` file. 1. Enter the password you used when you created your Supabase project in the `password` entry in the `supabase-service.json` file. diff --git a/apps/docs/pages/guides/resources/migrating-to-supabase/heroku.mdx b/apps/docs/pages/guides/resources/migrating-to-supabase/heroku.mdx index f2ed7478c6d..930ded5270a 100644 --- a/apps/docs/pages/guides/resources/migrating-to-supabase/heroku.mdx +++ b/apps/docs/pages/guides/resources/migrating-to-supabase/heroku.mdx @@ -36,8 +36,8 @@ Alternatively, use the [Heroku to Supabase migration tool](https://migrate.supab ## Retrieve your Supabase Host [#retrieve-supabase-host] -1. If you're new to Supabase, [create a project](https://app.supabase.com). -1. Go to the [Database settings](https://app.supabase.com/project/_/settings/database) for your project in the Supabase Dashboard. +1. If you're new to Supabase, [create a project](https://supabase.com/dashboard). +1. Go to the [Database settings](https://supabase.com/dashboard/project/_/settings/database) for your project in the Supabase Dashboard. 1. Under **Connection Info**, note your Host (`$SUPABASE_HOST`). ## Export your Heroku database to a file [#export-heroku-database] @@ -69,7 +69,7 @@ Run `pg_dump --help` for a full list of options. -- If you plan on migrating a database larger than 6 GB, we recommend [contacting support](https://app.supabase.com/support/new) to ensure that you'll have the proper disk size pre-provisioned. You can read more about how the disk is managed on Supabase on the [Database usage](/docs/guides/platform/database-size#disk-management). +- If you plan on migrating a database larger than 6 GB, we recommend [contacting support](https://supabase.com/dashboard/support/new) to ensure that you'll have the proper disk size pre-provisioned. You can read more about how the disk is managed on Supabase on the [Database usage](/docs/guides/platform/database-size#disk-management). - We also recommend upgrading to at least a [Large instance](/docs/guides/platform/compute-add-ons) for the migration (you can downgrade later) to avoid running out of IO-Budget. diff --git a/apps/docs/pages/guides/resources/migrating-to-supabase/render.mdx b/apps/docs/pages/guides/resources/migrating-to-supabase/render.mdx index 6d0eae2c6de..2eb6dd79214 100644 --- a/apps/docs/pages/guides/resources/migrating-to-supabase/render.mdx +++ b/apps/docs/pages/guides/resources/migrating-to-supabase/render.mdx @@ -27,10 +27,10 @@ Example: ## Retrieve your Supabase Host [#retrieve-supabase-host] -1. If you're new to Supabase, [create a project](https://app.supabase.com). -1. Go to the [Database settings](https://app.supabase.com/project/_/settings/database) for your project in the Supabase Dashboard. +1. If you're new to Supabase, [create a project](https://supabase.com/dashboard). +1. Go to the [Database settings](https://supabase.com/dashboard/project/_/settings/database) for your project in the Supabase Dashboard. 1. Under **Connection Info**, note your Host (`$SUPABASE_HOST`). -1. Save your password or [reset it](https://app.supabase.com/project/_/settings/database) if you forgot it. +1. Save your password or [reset it](https://supabase.com/dashboard/project/_/settings/database) if you forgot it. ![Finding Supabase host address](/docs/img/guides/resources/migrating-to-supabase/render/supabase_dashboard.png) @@ -85,7 +85,7 @@ Run `pg_dump --help` for a full list of options. -- If you plan on migrating a database larger than 6 GB, we recommend [contacting support](https://app.supabase.com/support/new) to ensure that you'll have the proper disk size pre-provisioned. You can read more about how the disk is managed on Supabase on the [Database usage](/docs/guides/platform/database-size#disk-management). +- If you plan on migrating a database larger than 6 GB, we recommend [contacting support](https://supabase.com/dashboard/support/new) to ensure that you'll have the proper disk size pre-provisioned. You can read more about how the disk is managed on Supabase on the [Database usage](/docs/guides/platform/database-size#disk-management). - We also recommend upgrading to at least a [Large instance](/docs/guides/platform/compute-add-ons) for the migration (you can downgrade later) to avoid running out of IO-Budget. diff --git a/apps/docs/pages/guides/self-hosting.mdx b/apps/docs/pages/guides/self-hosting.mdx index 4a6fdd2919d..aadf096723b 100644 --- a/apps/docs/pages/guides/self-hosting.mdx +++ b/apps/docs/pages/guides/self-hosting.mdx @@ -7,7 +7,7 @@ export const meta = { There are several ways to use Supabase: -- [Supabase Cloud](https://app.supabase.com): you don't need to deploy anything. We will manage and scale your infrastructure. +- [Supabase Cloud](https://supabase.com/dashboard): you don't need to deploy anything. We will manage and scale your infrastructure. - [Docker](/docs/guides/self-hosting/docker): deploy to your own infrastructure. ### Community diff --git a/apps/docs/pages/guides/self-hosting/docker.mdx b/apps/docs/pages/guides/self-hosting/docker.mdx index f496cd10efe..f83e0b7c3dc 100644 --- a/apps/docs/pages/guides/self-hosting/docker.mdx +++ b/apps/docs/pages/guides/self-hosting/docker.mdx @@ -136,6 +136,11 @@ However, you might miss important log messages such as database errors. Configur By default, Storage backend is set to `file`, which is to use local files as the storage backend. To make it work on macOS, you need to choose `VirtioFS` as the Docker container file sharing implementation (in Docker Desktop -> Preferences -> General). +### Setting up logging with the Analytics server + +Additional configuration is required for self-hosting the Analytics server. For the full setup instructions, see [Self Hosting Analytics](https://supabase.com/docs/reference/self-hosting-analytics/introduction#getting-started). + + export const Page = ({ children }) => export default Page diff --git a/apps/docs/pages/guides/storage/cdn.mdx b/apps/docs/pages/guides/storage/cdn.mdx index 8a96b745eb2..57f39faab52 100644 --- a/apps/docs/pages/guides/storage/cdn.mdx +++ b/apps/docs/pages/guides/storage/cdn.mdx @@ -7,7 +7,7 @@ export const meta = { sidebar_label: 'CDN', } -All assets uploaded to Supabase Storage are cached on a Content Delivery Network (CDN) to improve the latency for users all around the world. CDNs are a geographically distributed set of servers or **nodes** which caches content from an **origin server**. For Supabase Storage, the origin is the storage server running in the [same region as your project](https://app.supabase.com/project/_/settings/general). Aside from performance, CDNs also help with security and availability by mitigating Distributed Denial of Service and other application attacks. +All assets uploaded to Supabase Storage are cached on a Content Delivery Network (CDN) to improve the latency for users all around the world. CDNs are a geographically distributed set of servers or **nodes** which caches content from an **origin server**. For Supabase Storage, the origin is the storage server running in the [same region as your project](https://supabase.com/dashboard/project/_/settings/general). Aside from performance, CDNs also help with security and availability by mitigating Distributed Denial of Service and other application attacks. ## Basic CDN diff --git a/apps/docs/pages/guides/storage/quickstart.mdx b/apps/docs/pages/guides/storage/quickstart.mdx index 118bd2513dd..b94c588ce4b 100644 --- a/apps/docs/pages/guides/storage/quickstart.mdx +++ b/apps/docs/pages/guides/storage/quickstart.mdx @@ -7,7 +7,7 @@ export const meta = { sidebar_label: 'Quickstart', } -This guide shows the basic functionality of Supabase Storage. Find a full [example application on GitHub](https://github.com/supabase/supabase/tree/master/examples/user-management/nextjs-ts-user-management) or deploy it with [Vercel for a preview](https://vercel.com/new/git/external?repository-url=https%3A%2F%2Fgithub.com%2Fsupabase%2Fsupabase%2Ftree%2Fmaster%2Fexamples%2Fuser-management%2Fnextjs-ts-user-management&project-name=supabase-user-management&repository-name=supabase-user-management&demo-title=Supabase%20User%20Management&demo-description=An%20example%20web%20app%20using%20Supabase%20and%20Next.js&demo-url=https%3A%2F%2Fsupabase-nextjs-ts-user-management.vercel.app&demo-image=https%3A%2F%2Fi.imgur.com%2FZ3HkQqe.png&integration-ids=oac_jUduyjQgOyzev1fjrW83NYOv&external-id=nextjs-user-management). +This guide shows the basic functionality of Supabase Storage. Find a full [example application on GitHub](https://github.com/supabase/supabase/tree/master/examples/user-management/nextjs-user-management). @@ -29,7 +29,7 @@ client libraries. Here we create a bucket called "avatars": > -1. Go to the [Storage](https://app.supabase.com/project/_/storage/buckets) page in the Dashboard. +1. Go to the [Storage](https://supabase.com/dashboard/project/_/storage/buckets) page in the Dashboard. 2. Click **New Bucket** and enter a name for the bucket. 3. Click **Create Bucket**. @@ -86,7 +86,7 @@ You can upload a file from the Dashboard, or within a browser using our JS libra > -1. Go to the [Storage](https://app.supabase.com/project/_/storage/buckets) page in the Dashboard. +1. Go to the [Storage](https://supabase.com/dashboard/project/_/storage/buckets) page in the Dashboard. 2. Select the bucket you want to upload the file to. 3. Click **Upload File**. 4. Select the file you want to upload. @@ -137,7 +137,7 @@ You can download a file from the Dashboard, or within a browser using our JS lib > -1. Go to the [Storage](https://app.supabase.com/project/_/storage/buckets) page in the Dashboard. +1. Go to the [Storage](https://supabase.com/dashboard/project/_/storage/buckets) page in the Dashboard. 2. Select the bucket that contains the file. 3. Select the file that you want to download. 4. Click **Download**. @@ -184,7 +184,7 @@ To restrict access to your files you can use either the Dashboard or SQL. > -1. Go to the [Storage](https://app.supabase.com/project/_/storage/buckets) page in the Dashboard. +1. Go to the [Storage](https://supabase.com/dashboard/project/_/storage/buckets) page in the Dashboard. 2. Click **Policies** in the sidebar. 3. Click **Add Policies** in the `OBJECTS` table to add policies for Files. You can also create policies for Buckets. 4. Choose whether you want the policy to apply to downloads (SELECT), uploads (INSERT), updates (UPDATE), or deletes (DELETE). diff --git a/apps/docs/pages/index.mdx b/apps/docs/pages/index.mdx index 00432dc6d16..8024c9629a4 100644 --- a/apps/docs/pages/index.mdx +++ b/apps/docs/pages/index.mdx @@ -159,7 +159,7 @@ export const meta = {

@@ -232,7 +232,7 @@ export const products = [ }, { title: 'Edge Functions', - icon: 'functions', + icon: 'edge-functions', hasLightIcon: true, href: '/guides/functions', description: diff --git a/apps/docs/pages/learn/auth-deep-dive/auth-deep-dive-jwts.mdx b/apps/docs/pages/learn/auth-deep-dive/auth-deep-dive-jwts.mdx index d33020220ed..d621ec7ade2 100644 --- a/apps/docs/pages/learn/auth-deep-dive/auth-deep-dive-jwts.mdx +++ b/apps/docs/pages/learn/auth-deep-dive/auth-deep-dive-jwts.mdx @@ -191,7 +191,7 @@ Now that you understand what JWTs are and where they're used in Supabase, you ca - [Part Three: Policies](../../learn/auth-deep-dive/auth-policies) - [Part Four: GoTrue](../../learn/auth-deep-dive/auth-gotrue) - [Part Five: Google Oauth](../../learn/auth-deep-dive/auth-google-oauth) -- Sign up for Supabase: [app.supabase.com](https://app.supabase.com) +- Sign up for Supabase: [supabase.com/dashboard](https://supabase.com/dashboard) export const Page = ({ children }) => diff --git a/apps/docs/pages/learn/auth-deep-dive/auth-google-oauth.mdx b/apps/docs/pages/learn/auth-deep-dive/auth-google-oauth.mdx index c2b91673f74..d10f98e5d73 100644 --- a/apps/docs/pages/learn/auth-deep-dive/auth-google-oauth.mdx +++ b/apps/docs/pages/learn/auth-deep-dive/auth-google-oauth.mdx @@ -97,7 +97,7 @@ For any support please get in touch at beta at [supabase.com](https://supabase.c - Watch [Part Three: Policies](../../learn/auth-deep-dive/auth-policies) - Watch [Part Four: GoTrue](../../learn/auth-deep-dive/auth-gotrue) {/* */} -- Sign up for Supabase: [app.supabase.com](https://app.supabase.com) +- Sign up for Supabase: [supabase.com/dashboard](https://supabase.com/dashboard) export const Page = ({ children }) => diff --git a/apps/docs/pages/learn/auth-deep-dive/auth-gotrue.mdx b/apps/docs/pages/learn/auth-deep-dive/auth-gotrue.mdx index ed9dd72dec7..a9531106ed8 100644 --- a/apps/docs/pages/learn/auth-deep-dive/auth-gotrue.mdx +++ b/apps/docs/pages/learn/auth-deep-dive/auth-gotrue.mdx @@ -78,7 +78,7 @@ In the next guide we'll be looking at how to setup external OAuth providers: Wat - Watch [Part Three: Policies](../../learn/auth-deep-dive/auth-policies) {/* */} - Watch [Part Five: Google Oauth](../../learn/auth-deep-dive/auth-google-oauth) -- Sign up for Supabase: [app.supabase.com](https://app.supabase.com) +- Sign up for Supabase: [supabase.com/dashboard](https://supabase.com/dashboard) export const Page = ({ children }) => diff --git a/apps/docs/pages/learn/auth-deep-dive/auth-policies.mdx b/apps/docs/pages/learn/auth-deep-dive/auth-policies.mdx index 94fe1602450..b75e75aa2d0 100644 --- a/apps/docs/pages/learn/auth-deep-dive/auth-policies.mdx +++ b/apps/docs/pages/learn/auth-deep-dive/auth-policies.mdx @@ -44,7 +44,7 @@ http://localhost:3000/#access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdWQ Let's break this up so that it's easier to read: ```jsx -// the base url - whatever you set in the Auth Settings in app.supabase.com dashboard +// the base url - whatever you set in the Auth Settings in supabase.com/dashboard dashboard http://localhost:3000/ // note we use the '#' (fragment) instead of '?' query param @@ -183,7 +183,7 @@ You can get as creative as you like with these policies. {/* */} - Watch [Part Four: GoTrue](../../learn/auth-deep-dive/auth-gotrue) - Watch [Part Five: Google Oauth](../../learn/auth-deep-dive/auth-google-oauth) -- Sign up for Supabase: [app.supabase.com](https://app.supabase.com) +- Sign up for Supabase: [supabase.com/dashboard](https://supabase.com/dashboard) export const Page = ({ children }) => diff --git a/apps/docs/pages/learn/auth-deep-dive/auth-row-level-security.mdx b/apps/docs/pages/learn/auth-deep-dive/auth-row-level-security.mdx index c75b446e972..81424abf45f 100644 --- a/apps/docs/pages/learn/auth-deep-dive/auth-row-level-security.mdx +++ b/apps/docs/pages/learn/auth-deep-dive/auth-row-level-security.mdx @@ -82,7 +82,7 @@ or via the Supabase Dashboard, by navigating to Auth > Policies, and clicking th ![Enable row level security in Supabase](/docs/img/auth-deep-dive-2.png) -You'll notice that both reading and writing now fail with an error like: +You'll notice that reading will return no rows and writing will now fail with an error like: ```jsx { @@ -128,7 +128,7 @@ In the next guide we will look at using Policies in combination with User Accoun - Watch [Part Three: Policies](../../learn/auth-deep-dive/auth-policies) - Watch [Part Four: GoTrue](../../learn/auth-deep-dive/auth-gotrue) - Watch [Part Five: Google Oauth](../../learn/auth-deep-dive/auth-google-oauth) -- Sign up for Supabase: [app.supabase.com](https://app.supabase.com) +- Sign up for Supabase: [supabase.com/dashboard](https://supabase.com/dashboard) export const Page = ({ children }) => diff --git a/apps/docs/public/img/guides/auth-kakao/kakao-developers-consent-items-set.png b/apps/docs/public/img/guides/auth-kakao/kakao-developers-consent-items-set.png new file mode 100644 index 00000000000..b59c4616984 Binary files /dev/null and b/apps/docs/public/img/guides/auth-kakao/kakao-developers-consent-items-set.png differ diff --git a/apps/docs/public/img/guides/auth-kakao/kakao-developers-page.png b/apps/docs/public/img/guides/auth-kakao/kakao-developers-page.png new file mode 100644 index 00000000000..81d30550eb6 Binary files /dev/null and b/apps/docs/public/img/guides/auth-kakao/kakao-developers-page.png differ diff --git a/apps/docs/public/img/icons/kakao-icon.svg b/apps/docs/public/img/icons/kakao-icon.svg new file mode 100644 index 00000000000..e721ec2b432 --- /dev/null +++ b/apps/docs/public/img/icons/kakao-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/docs/public/img/icons/refine-icon.svg b/apps/docs/public/img/icons/refine-icon.svg new file mode 100644 index 00000000000..7f2e1f8d82c --- /dev/null +++ b/apps/docs/public/img/icons/refine-icon.svg @@ -0,0 +1,12 @@ + + + + + + + + + + + + diff --git a/apps/docs/public/img/refine-qs-countries-ui.png b/apps/docs/public/img/refine-qs-countries-ui.png new file mode 100644 index 00000000000..e062c721878 Binary files /dev/null and b/apps/docs/public/img/refine-qs-countries-ui.png differ diff --git a/apps/docs/public/img/refine-qs-welcome-page.png b/apps/docs/public/img/refine-qs-welcome-page.png new file mode 100644 index 00000000000..376740a35f7 Binary files /dev/null and b/apps/docs/public/img/refine-qs-welcome-page.png differ diff --git a/apps/docs/public/img/supabase-refine-demo.png b/apps/docs/public/img/supabase-refine-demo.png new file mode 100644 index 00000000000..6a8f15ff6ed Binary files /dev/null and b/apps/docs/public/img/supabase-refine-demo.png differ diff --git a/apps/docs/styles/main.scss b/apps/docs/styles/main.scss index d6b1d9cc720..ec6e38a814e 100644 --- a/apps/docs/styles/main.scss +++ b/apps/docs/styles/main.scss @@ -2,6 +2,10 @@ @tailwind components; @tailwind utilities; +@import './../../../packages/ui/build/css/source/global.css'; +@import './../../../packages/ui/build/css/themes/dark.css'; +@import './../../../packages/ui/build/css/themes/light.css'; + @font-face { font-family: 'custom-font'; src: url(../../../packages/common/assets/fonts/CustomFont-Book.woff2) format('woff2'), diff --git a/apps/docs/tsconfig.json b/apps/docs/tsconfig.json index c87a0e51e07..3600bbffffc 100644 --- a/apps/docs/tsconfig.json +++ b/apps/docs/tsconfig.json @@ -4,7 +4,8 @@ "noImplicitAny": false, "baseUrl": ".", "paths": { - "~/*": ["./*"] + "~/*": ["./*"], + "@ui/*": ["./../../packages/ui/src/*"] // handle ui package paths }, "target": "es2015", "lib": ["dom", "dom.iterable", "esnext"], diff --git a/apps/www/_alternatives/supabase-vs-firebase.mdx b/apps/www/_alternatives/supabase-vs-firebase.mdx index 1b0c44cb5c7..2ed8ec1883f 100644 --- a/apps/www/_alternatives/supabase-vs-firebase.mdx +++ b/apps/www/_alternatives/supabase-vs-firebase.mdx @@ -66,4 +66,4 @@ We also have guides and tools for [migrating Firebase Auth to Supabase Auth](htt These are by far the most complete Firebase to Postgres migration tools available anywhere on the web. -You can [try Supabase for free](https://app.supabase.com). If you require Enterprise level support with your project or migration, please get in touch using our [Enterprise contact form](https://forms.supabase.com/enterprise). +You can [try Supabase for free](https://supabase.com/dashboard). If you require Enterprise level support with your project or migration, please get in touch using our [Enterprise contact form](https://forms.supabase.com/enterprise). diff --git a/apps/www/_blog/2020-05-01-supabase-alpha-april-2020.mdx b/apps/www/_blog/2020-05-01-supabase-alpha-april-2020.mdx index 964cfe71934..59816be570d 100644 --- a/apps/www/_blog/2020-05-01-supabase-alpha-april-2020.mdx +++ b/apps/www/_blog/2020-05-01-supabase-alpha-april-2020.mdx @@ -11,7 +11,7 @@ tags: date: '06-01-2020' --- -Now in [Supabase](https://app.supabase.com): +Now in [Supabase](https://supabase.com/dashboard): - Set up Postgres in less than 2 minutes - Auto-generated APIs! (they are a bit flaky, go easy) @@ -58,6 +58,6 @@ Send realtime database changes to other systems, like queues or webhooks (Slack ## Follow us -Start using Supabase today: [app.supabase.com](https://app.supabase.com) +Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard) Make sure to star us on github! [github.com/supabase/supabase](https://github.com/supabase/supabase) diff --git a/apps/www/_blog/2020-06-01-supabase-alpha-may-2020.mdx b/apps/www/_blog/2020-06-01-supabase-alpha-may-2020.mdx index fc9d49b9ba6..b3db04f166c 100644 --- a/apps/www/_blog/2020-06-01-supabase-alpha-may-2020.mdx +++ b/apps/www/_blog/2020-06-01-supabase-alpha-may-2020.mdx @@ -56,6 +56,6 @@ This one is still very unstable, but we wanted to ship it anyway. It's a little ## Follow us -Start using Supabase today: [app.supabase.com](https://app.supabase.com) +Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard) Make sure to star us on github! [github.com/supabase/supabase](https://github.com/supabase/supabase) diff --git a/apps/www/_blog/2020-07-01-supabase-alpha-june-2020.mdx b/apps/www/_blog/2020-07-01-supabase-alpha-june-2020.mdx index 4baf3f31a58..f8a2d6a8e1a 100644 --- a/apps/www/_blog/2020-07-01-supabase-alpha-june-2020.mdx +++ b/apps/www/_blog/2020-07-01-supabase-alpha-june-2020.mdx @@ -93,7 +93,7 @@ We have a number of small improvements: ### Get started -- Start using Supabase today: [app.supabase.com](https://app.supabase.com) +- Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard) - Make sure to [star us on GitHub](https://github.com/supabase/supabase) - Follow us [on Twitter](https://twitter.com/supabase) - Become a [sponsor](https://github.com/sponsors/supabase) diff --git a/apps/www/_blog/2020-07-10-alpha-launch-postmortem.mdx b/apps/www/_blog/2020-07-10-alpha-launch-postmortem.mdx index f0186212be6..50484573981 100644 --- a/apps/www/_blog/2020-07-10-alpha-launch-postmortem.mdx +++ b/apps/www/_blog/2020-07-10-alpha-launch-postmortem.mdx @@ -51,7 +51,7 @@ We have since migrated our middleware to multiple ECS clusters, globally load-ba We serve our marketing site ([supabase.io](/)) from Netlify. It's a static-build [Docusaurus (v2)](https://v2.docusaurus.io/) site, so it had no problems (apart from one developer in Russia who couldn't access the site - it looks like some of Netlify's IP addresses are blocked there). -We serve our app ([app.supabase.com](https://app.supabase.com)) using Vercel, and the login system uses Auth0. These were both rock-solid. Before the launch we noticed that Vercel was extremely slow on their free plan, and once we upgraded to their Pro Plan for multi-region deploys it solved performance issues. It looks like they are changing their plans again so buyer beware. +We serve our app ([supabase.com/dashboard](https://supabase.com/dashboard)) using Vercel, and the login system uses Auth0. These were both rock-solid. Before the launch we noticed that Vercel was extremely slow on their free plan, and once we upgraded to their Pro Plan for multi-region deploys it solved performance issues. It looks like they are changing their plans again so buyer beware. ## The Bad diff --git a/apps/www/_blog/2020-08-02-supabase-alpha-july-2020.mdx b/apps/www/_blog/2020-08-02-supabase-alpha-july-2020.mdx index 3d450ab4765..4dbc736616a 100644 --- a/apps/www/_blog/2020-08-02-supabase-alpha-july-2020.mdx +++ b/apps/www/_blog/2020-08-02-supabase-alpha-july-2020.mdx @@ -79,7 +79,7 @@ We have a number of small improvements: ### Get started -- Start using Supabase today: [app.supabase.com](https://app.supabase.com) +- Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard) - Make sure to [star us on GitHub](https://github.com/supabase/supabase) - Follow us [on Twitter](https://twitter.com/supabase) - Become a [sponsor](https://github.com/sponsors/supabase) diff --git a/apps/www/_blog/2020-08-05-supabase-auth.mdx b/apps/www/_blog/2020-08-05-supabase-auth.mdx index 404b0e1d0de..708b0d4d099 100644 --- a/apps/www/_blog/2020-08-05-supabase-auth.mdx +++ b/apps/www/_blog/2020-08-05-supabase-auth.mdx @@ -95,6 +95,6 @@ Supabase has a culture of shipping early and often. Our Auth release is another ### Get started -Supabase Auth is ready for you to start using today, free of charge: [app.supabase.com](https://app.supabase.com) +Supabase Auth is ready for you to start using today, free of charge: [supabase.com/dashboard](https://supabase.com/dashboard) To see the full power of our auth system, watch [this demo](https://youtu.be/2oqIZW5S-lQ) where I deploy a secure, real-time slack clone to Vercel in less than 3 minutes. diff --git a/apps/www/_blog/2020-09-03-supabase-alpha-august-2020.mdx b/apps/www/_blog/2020-09-03-supabase-alpha-august-2020.mdx index 14678e98687..d33c6c02d6f 100644 --- a/apps/www/_blog/2020-09-03-supabase-alpha-august-2020.mdx +++ b/apps/www/_blog/2020-09-03-supabase-alpha-august-2020.mdx @@ -91,7 +91,7 @@ Our focus now is to move from Alpha to Beta. This involves stabilising our Auth ### Get started -- Start using Supabase today: [app.supabase.com](https://app.supabase.com) +- Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard) - Make sure to [star us on GitHub](https://github.com/supabase/supabase) - Follow us [on Twitter](https://twitter.com/supabase) - Become a [sponsor](https://github.com/sponsors/supabase) diff --git a/apps/www/_blog/2020-10-03-supabase-alpha-september-2020.mdx b/apps/www/_blog/2020-10-03-supabase-alpha-september-2020.mdx index f5af4a662ae..f24e466253c 100644 --- a/apps/www/_blog/2020-10-03-supabase-alpha-september-2020.mdx +++ b/apps/www/_blog/2020-10-03-supabase-alpha-september-2020.mdx @@ -99,7 +99,7 @@ Our focus now is to move from Alpha to Beta and we'll be improving stability, re ### Get started -- Start using Supabase today: [app.supabase.com](https://app.supabase.com/) +- Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard/) - Make sure to [star us on GitHub](https://github.com/supabase/supabase) - Follow us [on Twitter](https://twitter.com/supabase) - Become a [sponsor](https://github.com/sponsors/supabase) diff --git a/apps/www/_blog/2020-10-30-improved-dx.mdx b/apps/www/_blog/2020-10-30-improved-dx.mdx index d13ca01f614..786a45c585d 100644 --- a/apps/www/_blog/2020-10-30-improved-dx.mdx +++ b/apps/www/_blog/2020-10-30-improved-dx.mdx @@ -111,7 +111,7 @@ To summarise the steps: ### Get started -- Start using Supabase today: [app.supabase.com](https://app.supabase.com/) +- Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard/) - Make sure to [star us on GitHub](https://github.com/supabase/supabase) - Follow us [on Twitter](https://twitter.com/supabase) - Become a [sponsor](https://github.com/sponsors/supabase) diff --git a/apps/www/_blog/2020-11-02-supabase-alpha-october-2020.mdx b/apps/www/_blog/2020-11-02-supabase-alpha-october-2020.mdx index 158b81d22d5..e3778d5ba34 100644 --- a/apps/www/_blog/2020-11-02-supabase-alpha-october-2020.mdx +++ b/apps/www/_blog/2020-11-02-supabase-alpha-october-2020.mdx @@ -79,7 +79,7 @@ Our focus is still moving from Alpha to Beta and we'll be improving stability, r ### Get started -- Start using Supabase today: [app.supabase.com](https://app.supabase.com/) +- Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard/) - Make sure to [star us on GitHub](https://github.com/supabase/supabase) - Follow us [on Twitter](https://twitter.com/supabase) - Become a [sponsor](https://github.com/sponsors/supabase) diff --git a/apps/www/_blog/2020-12-01-supabase-alpha-november-2020.mdx b/apps/www/_blog/2020-12-01-supabase-alpha-november-2020.mdx index a4bb7858a82..15fd74a13b0 100644 --- a/apps/www/_blog/2020-12-01-supabase-alpha-november-2020.mdx +++ b/apps/www/_blog/2020-12-01-supabase-alpha-november-2020.mdx @@ -76,7 +76,7 @@ Look out for a big announcement on December 3rd. We'll also be presenting in the ### Get started -- Start using Supabase today: [app.supabase.com](https://app.supabase.com/) +- Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard/) - Make sure to [star us on GitHub](https://github.com/supabase/supabase) - Follow us [on Twitter](https://twitter.com/supabase) - Become a [sponsor](https://github.com/sponsors/supabase) diff --git a/apps/www/_blog/2021-01-02-supabase-beta-december-2020.mdx b/apps/www/_blog/2021-01-02-supabase-beta-december-2020.mdx index 3b5f726509a..c78910380ec 100644 --- a/apps/www/_blog/2021-01-02-supabase-beta-december-2020.mdx +++ b/apps/www/_blog/2021-01-02-supabase-beta-december-2020.mdx @@ -102,7 +102,7 @@ We also have something exciting planned with Vercel and Stripe ... [stay tuned]( ### Get started -- Start using Supabase today: [app.supabase.com](https://app.supabase.com/) +- Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard/) - Make sure to [star us on GitHub](https://github.com/supabase/supabase) - Follow us [on Twitter](https://twitter.com/supabase) - Become a [sponsor](https://github.com/sponsors/supabase) diff --git a/apps/www/_blog/2021-02-02-supabase-beta-january-2021.mdx b/apps/www/_blog/2021-02-02-supabase-beta-january-2021.mdx index 976c96f08b6..7fce0b1eabf 100644 --- a/apps/www/_blog/2021-02-02-supabase-beta-january-2021.mdx +++ b/apps/www/_blog/2021-02-02-supabase-beta-january-2021.mdx @@ -123,7 +123,7 @@ We're ramping up to "Launch week" at the end of Q1, where we will be giving you ### Get started -- Start using Supabase today: [app.supabase.com](https://app.supabase.com/) +- Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard/) - Make sure to [star us on GitHub](https://github.com/supabase/supabase) - Follow us [on Twitter](https://twitter.com/supabase) - Subscribe to our [YouTube channel](https://www.youtube.com/c/supabase) diff --git a/apps/www/_blog/2021-02-27-cracking-postgres-interview.mdx b/apps/www/_blog/2021-02-27-cracking-postgres-interview.mdx index dbdc69fc6ee..f90e44dff41 100644 --- a/apps/www/_blog/2021-02-27-cracking-postgres-interview.mdx +++ b/apps/www/_blog/2021-02-27-cracking-postgres-interview.mdx @@ -155,7 +155,7 @@ where first_name like "S%"; If you can reason about most of the topics in this post then you'll be in a very strong position to impress with your answers to PostgreSQL interview questions. As with all programming topics however, the real learning starts when you put these things into practice. At Supabase we offer a very very fast (the fastest?) way to spin up a PostgreSQL database and start querying it, and our browser based SQL editor is getting more powerful every day. -[Get started on Supabase for free here](https://app.supabase.com) +[Get started on Supabase for free here](https://supabase.com/dashboard) Thanks Steve Chavez for providing all the good bits of this post :) diff --git a/apps/www/_blog/2021-03-02-supabase-beta-february-2021.mdx b/apps/www/_blog/2021-03-02-supabase-beta-february-2021.mdx index 750370d5c7a..1f327482d37 100644 --- a/apps/www/_blog/2021-03-02-supabase-beta-february-2021.mdx +++ b/apps/www/_blog/2021-03-02-supabase-beta-february-2021.mdx @@ -103,7 +103,7 @@ Waiting for Supabase Storage? Here's a sneak peek for the upcoming Launch Week a ### Get started -- Start using Supabase today: [app.supabase.com](https://app.supabase.com/) +- Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard/) - Make sure to [star us on GitHub](https://github.com/supabase/supabase) - Follow us [on Twitter](https://twitter.com/supabase) - Subscribe to our [YouTube channel](https://www.youtube.com/c/supabase) diff --git a/apps/www/_blog/2021-03-05-postgres-as-a-cron-server.mdx b/apps/www/_blog/2021-03-05-postgres-as-a-cron-server.mdx index 307339e3a02..f71abee8d97 100644 --- a/apps/www/_blog/2021-03-05-postgres-as-a-cron-server.mdx +++ b/apps/www/_blog/2021-03-05-postgres-as-a-cron-server.mdx @@ -211,7 +211,7 @@ If you're familiar with `C`, you could also help `@pramsey` to implement async f There are plenty of ways to run cron jobs these days. You can trigger them from your local machine. You can install them on a VPS. You can schedule Serverless functions. You can use a paid service. You can use GitHub Actions. -Is Postgres the best place to put your cron jobs? `¯\_(ツ)_/¯`. Postgres databases are free on Supabase and since it takes only one minute to [get started](https://app.supabase.com/), why not make your next cron server a Postgres database? +Is Postgres the best place to put your cron jobs? `¯\_(ツ)_/¯`. Postgres databases are free on Supabase and since it takes only one minute to [get started](https://supabase.com/dashboard/), why not make your next cron server a Postgres database? ## More Postgres resources diff --git a/apps/www/_blog/2021-03-11-using-supabase-replit.mdx b/apps/www/_blog/2021-03-11-using-supabase-replit.mdx index 49dca993283..f5ef05d1413 100644 --- a/apps/www/_blog/2021-03-11-using-supabase-replit.mdx +++ b/apps/www/_blog/2021-03-11-using-supabase-replit.mdx @@ -133,4 +133,4 @@ We look forward to showing off some more Supabase + Replit examples. You can find my example repl here: [https://repl.it/@awalias/supabase-test#index.js](https://repl.it/@awalias/supabase-test#index.js) -Supabase has a free plan, head over to [https://app.supabase.com](https://app.supabase.com) to get started. +Supabase has a free plan, head over to [https://supabase.com/dashboard](https://supabase.com/dashboard) to get started. diff --git a/apps/www/_blog/2021-03-29-pricing.mdx b/apps/www/_blog/2021-03-29-pricing.mdx index f8300653ca4..1b0ccc104be 100644 --- a/apps/www/_blog/2021-03-29-pricing.mdx +++ b/apps/www/_blog/2021-03-29-pricing.mdx @@ -77,7 +77,7 @@ In the next few days, you will see your usage appear in the dashboard with an up Check back throughout the week to see what else we're launching [here](/blog/launch-week). -Sign up for the Supabase Beta [here](https://app.supabase.com). +Sign up for the Supabase Beta [here](https://supabase.com/dashboard). And check out the full pricing details [here](/pricing). And we'd love to hear your opnions on our Pricing! You can let us know via support@supabase.io. diff --git a/apps/www/_blog/2021-03-30-supabase-storage.mdx b/apps/www/_blog/2021-03-30-supabase-storage.mdx index ad9b96c392d..72921f565af 100644 --- a/apps/www/_blog/2021-03-30-supabase-storage.mdx +++ b/apps/www/_blog/2021-03-30-supabase-storage.mdx @@ -169,4 +169,4 @@ You may be itching to get started tinkering around with our new Supabase storage - A better editor to make authoring policies easier and less error prone. - Reach out to us if you would like to help out with adding storage support in one of the [community maintained client libraries](/docs/reference/javascript/installing). -Take it for a spin on our [dashboard](https://app.supabase.com/) and let us know what you think! +Take it for a spin on our [dashboard](https://supabase.com/dashboard/) and let us know what you think! diff --git a/apps/www/_blog/2021-03-31-supabase-cli.mdx b/apps/www/_blog/2021-03-31-supabase-cli.mdx index ea8d4c94ed8..9b3236d738f 100644 --- a/apps/www/_blog/2021-03-31-supabase-cli.mdx +++ b/apps/www/_blog/2021-03-31-supabase-cli.mdx @@ -224,4 +224,4 @@ Head over to the [Self Hosting Docs](/docs/guides/self-hosting) for a more compl If you require any assistance feel free to reach out in our [github discussions](https://github.com/supabase/supabase/discussions) or at support@supabase.io. -Check out the CLI VI [launched Monday 15th August, 2022](/blog/supabase-cli-v1-and-admin-api-beta), contribute to the [CLI repo](https://github.com/supabase/cli), or go here for the [hosted version](https://app.supabase.com). +Check out the CLI VI [launched Monday 15th August, 2022](/blog/supabase-cli-v1-and-admin-api-beta), contribute to the [CLI repo](https://github.com/supabase/cli), or go here for the [hosted version](https://supabase.com/dashboard). diff --git a/apps/www/_blog/2021-04-02-supabase-pgbouncer.mdx b/apps/www/_blog/2021-04-02-supabase-pgbouncer.mdx index 474d9c485bc..df6aa688c0e 100644 --- a/apps/www/_blog/2021-04-02-supabase-pgbouncer.mdx +++ b/apps/www/_blog/2021-04-02-supabase-pgbouncer.mdx @@ -92,7 +92,7 @@ This is the most granular option. Connections are returned to the pool after eve ## What's next? -Try out connection pooling now with a new project in the [dashboard.](https://app.supabase.com) For now, we do not have any plans to port this over to older projects. +Try out connection pooling now with a new project in the [dashboard.](https://supabase.com/dashboard) For now, we do not have any plans to port this over to older projects. Eventually, we will expose more PgBouncer settings to the UI such as `Pool Size`. At the moment it is set to `15`. diff --git a/apps/www/_blog/2021-04-06-supabase-beta-march-2021.mdx b/apps/www/_blog/2021-04-06-supabase-beta-march-2021.mdx index 607625976b6..1d766dbf8dc 100644 --- a/apps/www/_blog/2021-04-06-supabase-beta-march-2021.mdx +++ b/apps/www/_blog/2021-04-06-supabase-beta-march-2021.mdx @@ -116,7 +116,7 @@ For this we are working on our own [Workflow engine](/blog/supabase-workflows), ### Get started -- Start using Supabase today: [app.supabase.com](https://app.supabase.com/) +- Start using Supabase today: [supabase.com/dashboard](https://supabase.com/dashboard/) - Make sure to [star us on GitHub](https://github.com/supabase/supabase) - Follow us [on Twitter](https://twitter.com/supabase) - Subscribe to our [YouTube channel](https://www.youtube.com/c/supabase) diff --git a/apps/www/_blog/2021-05-03-supabase-beta-april-2021.mdx b/apps/www/_blog/2021-05-03-supabase-beta-april-2021.mdx index 342404f552e..817491cccb4 100644 --- a/apps/www/_blog/2021-05-03-supabase-beta-april-2021.mdx +++ b/apps/www/_blog/2021-05-03-supabase-beta-april-2021.mdx @@ -39,7 +39,7 @@ We're a developer tool, which means that Dark Mode is [extremely popular](https: While Dark mode is great, for some people it's not an option. Dark Mode is difficult to use for developers with astigmatisms, or even just working in brightly-lit environments. -So today we're shipping Light Mode. Access it in the settings of your [Dashboard](https://app.supabase.com). +So today we're shipping Light Mode. Access it in the settings of your [Dashboard](https://supabase.com/dashboard).
diff --git a/apps/www/_blog/2022-08-24-building-a-realtime-trello-board-with-supabase-and-angular.mdx b/apps/www/_blog/2022-08-24-building-a-realtime-trello-board-with-supabase-and-angular.mdx index c63debb9185..f674ba663dc 100644 --- a/apps/www/_blog/2022-08-24-building-a-realtime-trello-board-with-supabase-and-angular.mdx +++ b/apps/www/_blog/2022-08-24-building-a-realtime-trello-board-with-supabase-and-angular.mdx @@ -46,7 +46,7 @@ Ready for a wild adventure? Then let's begin inside our Supabase account! ## Creating the Supabase Project -First of all we need a new Supabase project. If you don't have a Supabase account yet, you can [get started for free](https://app.supabase.com/)! +First of all we need a new Supabase project. If you don't have a Supabase account yet, you can [get started for free](https://supabase.com/dashboard/)! In your dashboard, click "New Project" and leave it to the default settings, but make sure you keep a copy o your Database password! diff --git a/apps/www/_blog/2022-09-07-supabase-beta-update-august-2022.mdx b/apps/www/_blog/2022-09-07-supabase-beta-update-august-2022.mdx index 31a6206daec..13ca18a5f0f 100644 --- a/apps/www/_blog/2022-09-07-supabase-beta-update-august-2022.mdx +++ b/apps/www/_blog/2022-09-07-supabase-beta-update-august-2022.mdx @@ -146,7 +146,7 @@ If you made it this far in the blog post you deserve a treat. [Follow us on Twit ## Get started -- Start using Supabase today: **[app.supabase.com](https://app.supabase.com/)** +- Start using Supabase today: **[supabase.com/dashboard](https://supabase.com/dashboard/)** - Make sure to **[star us on GitHub](https://github.com/supabase/supabase)** - Follow us **[on Twitter](https://twitter.com/supabase)** - Subscribe to our **[YouTube channel](https://www.youtube.com/c/supabase)** diff --git a/apps/www/_blog/2022-10-05-supabase-beta-update-september-2022.mdx b/apps/www/_blog/2022-10-05-supabase-beta-update-september-2022.mdx index 8c418b43f0f..f1b3add99a3 100644 --- a/apps/www/_blog/2022-10-05-supabase-beta-update-september-2022.mdx +++ b/apps/www/_blog/2022-10-05-supabase-beta-update-september-2022.mdx @@ -96,7 +96,7 @@ If you made it this far in the blog post you deserve a treat. [Follow us on Twit ## Get started -- Start using Supabase today: **[app.supabase.com](https://app.supabase.com/)** +- Start using Supabase today: **[supabase.com/dashboard](https://supabase.com/dashboard/)** - Make sure to **[star us on GitHub](https://github.com/supabase/supabase)** - Follow us **[on Twitter](https://twitter.com/supabase)** - Subscribe to our **[YouTube channel](https://www.youtube.com/c/supabase)** diff --git a/apps/www/_blog/2022-11-02-supabase-beta-update-october-2022.mdx b/apps/www/_blog/2022-11-02-supabase-beta-update-october-2022.mdx index 5d43f927826..4c2250b41d4 100644 --- a/apps/www/_blog/2022-11-02-supabase-beta-update-october-2022.mdx +++ b/apps/www/_blog/2022-11-02-supabase-beta-update-october-2022.mdx @@ -116,7 +116,7 @@ If you made it this far in the blog post you deserve a treat. [Follow us on Twit ## Get started -- Start using Supabase today: **[app.supabase.com](https://app.supabase.com/)** +- Start using Supabase today: **[supabase.com/dashboard](https://supabase.com/dashboard/)** - Make sure to **[star us on GitHub](https://github.com/supabase/supabase)** - Follow us **[on Twitter](https://twitter.com/supabase)** - Subscribe to our **[YouTube channel](https://www.youtube.com/c/supabase)** diff --git a/apps/www/_blog/2022-11-17-fetching-and-caching-supabase-data-in-next-js-server-components.mdx b/apps/www/_blog/2022-11-17-fetching-and-caching-supabase-data-in-next-js-server-components.mdx index 01c432a7212..9dac31c3ece 100644 --- a/apps/www/_blog/2022-11-17-fetching-and-caching-supabase-data-in-next-js-server-components.mdx +++ b/apps/www/_blog/2022-11-17-fetching-and-caching-supabase-data-in-next-js-server-components.mdx @@ -52,9 +52,9 @@ Each folder within the `app` directory represents a route in our application. Ea > Learn more about [Page](https://beta.nextjs.org/docs/api-reference/file-conventions/page), [Layout](https://beta.nextjs.org/docs/api-reference/file-conventions/layout), [Loading](https://beta.nextjs.org/docs/api-reference/file-conventions/loading) and [Error](https://beta.nextjs.org/docs/api-reference/file-conventions/error) components in the [Next.js beta docs](https://beta.nextjs.org/docs). -Before we jump into fetching data, we need some data to fetch. Let’s [create a new Supabase project](https://app.supabase.com). +Before we jump into fetching data, we need some data to fetch. Let’s [create a new Supabase project](https://supabase.com/dashboard). -Once your instance is up and running, head over to the [SQL Editor](https://app.supabase.com/project/_/sql), paste in the following snippet and click `RUN`. +Once your instance is up and running, head over to the [SQL Editor](https://supabase.com/dashboard/project/_/sql), paste in the following snippet and click `RUN`. ```sql create table if not exists posts ( @@ -85,7 +85,7 @@ NEXT_PUBLIC_SUPABASE_URL=your-supabase-url NEXT_PUBLIC_SUPABASE_ANON_KEY=your-supabase-anon-key ``` -> The values for these can be found in [your project’s API settings](https://app.supabase.com/project/_/settings/api). +> The values for these can be found in [your project’s API settings](https://supabase.com/dashboard/project/_/settings/api). Lastly, we need to create a Supabase client. Create a file at `utils/supabase.ts` with the following content: @@ -382,7 +382,7 @@ But now we have loading spinners! Yuck! # Realtime -Realtime allows us to subscribe to changes in Supabase — inserted, updated or deleted posts — and update our UI dynamically. In order to receive realtime events, we need to [enable replication](https://app.supabase.com/project/_/database/replication) on the posts table. +Realtime allows us to subscribe to changes in Supabase — inserted, updated or deleted posts — and update our UI dynamically. In order to receive realtime events, we need to [enable replication](https://supabase.com/dashboard/project/_/database/replication) on the posts table. Let’s merge the two previous concepts and fetch the initial state of our posts in a Server Component, and then render a Client Component to do client-y things — like subscribe to changes in the DB and update the UI dynamically: diff --git a/apps/www/_blog/2022-11-22-flutter-authentication-and-authorization-with-rls.mdx b/apps/www/_blog/2022-11-22-flutter-authorization-with-rls.mdx similarity index 94% rename from apps/www/_blog/2022-11-22-flutter-authentication-and-authorization-with-rls.mdx rename to apps/www/_blog/2022-11-22-flutter-authorization-with-rls.mdx index 93ed654d530..25cbf2b6caa 100644 --- a/apps/www/_blog/2022-11-22-flutter-authentication-and-authorization-with-rls.mdx +++ b/apps/www/_blog/2022-11-22-flutter-authorization-with-rls.mdx @@ -1,5 +1,5 @@ --- -title: 'Flutter Authentication and Authorization with RLS' +title: 'Flutter Authorization with RLS' description: Learn how you can secure your Flutter app using Supabase Row Level Security. author: tyler_shukert image: flutter-chat-auth/supabase-flutter-auth.jpeg @@ -7,17 +7,18 @@ thumb: flutter-chat-auth/supabase-flutter-auth.jpeg tags: - flutter - auth - - mobile date: '2022-11-22' toc_depth: 3 --- This article is the second part of the Flutter tutorial series. During the series, you will learn how to build cross-platform apps without worrying about the backend. -In this article, I will show you how you can make a secure chat application by introducing authentication and authorization to the basic chat app that we created [previously](https://supabase.com/blog/flutter-tutorial-building-a-chat-app). +In this article, I will show you how you can make a secure chat application by introducing authorization to the basic chat app that we created [previously](https://supabase.com/blog/flutter-tutorial-building-a-chat-app). -We will use [Supabase](https://supabase.com/) to store the chat data and will use its [auth feature](https://supabase.com/auth) to provide a secure chat room feature. -Supabase lets us build a secure database where we can control who can access what part of the database, so your users' data is secured without worrying about the backend. +We will store the chat data on [Supabase](https://supabase.com/). +Supabase utilizes the built in authorization mechanism of PostgreSQL called [Row Level Security](https://supabase.com/docs/guides/auth/row-level-security) or RLS to prevent unauthorized access from accessing or writing data to your database. +RLS allows developers to define row-by-row conditions that evaluate to either `true` or `false` to either allow the access or deny it. +We will take a look at more specific examples of authorization using RLS throughout this article. ## What we created in the previous article @@ -174,7 +175,7 @@ For Android we edit the AndroidManifest.xml to register the deep link. ``` -We also need to set the deep link in our Supabase dashboard. Go to Authentication > URL Configuration in your dashboard and add `io.supabase.chat://login` as one of the redirect URLs. +We also need to set the deep link in our Supabase dashboard. Go to `Authentication > URL Configuration` in your dashboard and add `io.supabase.chat://login` as one of the redirect URLs. ![Deep link URL Configuration](/images/blog/flutter-chat-auth/url-configuration.png) @@ -188,7 +189,62 @@ The rooms page will load two types of data, recently added users and a list of r Let's start out by creating states for the rooms page. The rooms page would have four different states, loading, loaded, empty, and error. We will display different UI on the rooms page depending on what state it is. -Create a `lib/cubit/rooms/rooms_state.dart` file and paste the following code. +Satrt by defining the `Room` model. Create a `lib/models/room.dart` file and add the following code. + +```dart +import 'package:my_chat_app/models/message.dart'; + +class Room { + Room({ + required this.id, + required this.createdAt, + required this.otherUserId, + this.lastMessage, + }); + + /// ID of the room + final String id; + + /// Date and time when the room was created + final DateTime createdAt; + + /// ID of the user who the user is talking to + final String otherUserId; + + /// Latest message submitted in the room + final Message? lastMessage; + + Map toMap() { + return { + 'id': id, + 'createdAt': createdAt.millisecondsSinceEpoch, + }; + } + + /// Creates a room object from room_participants table + Room.fromRoomParticipants(Map map) + : id = map['room_id'], + otherUserId = map['profile_id'], + createdAt = DateTime.parse(map['created_at']), + lastMessage = null; + + Room copyWith({ + String? id, + DateTime? createdAt, + String? otherUserId, + Message? lastMessage, + }) { + return Room( + id: id ?? this.id, + createdAt: createdAt ?? this.createdAt, + otherUserId: otherUserId ?? this.otherUserId, + lastMessage: lastMessage ?? this.lastMessage, + ); + } +} +``` + +We will proceed with defining the states for the rooms page. Create `lib/cubit/rooms/rooms_state.dart` file and paste the following code. You may see some errors, but we will take care of them in the next step. ```dart title=lib/cubit/rooms/rooms_state.dart @@ -871,7 +927,7 @@ class _ChatBubble extends StatelessWidget { } ``` -### Step 3: Implementing Authentication in Flutter +### Step 3: Handle user sign-up/ sign-in Because we have modified the setting of our Supabase to send a confirmation email, we need to make some modifications to the register page and login page as well. @@ -1053,7 +1109,7 @@ class _RegisterPageState extends State { } ``` -Login page becomes more simple. +Login page becomes simpler. All it is doing is taking a user's email and password and logging them in. It is not doing any navigation whatsoever. This is because `LoginPage` is navigated on top of `RegisterPage`, the auth state listener on `RegisterPage` is still active, and therefore can take care of the navigation. @@ -1301,7 +1357,10 @@ class MyApp extends StatelessWidget { ### Step 4: Authorization with Row Level Security (RLS) -At this point, we seemingly have a complete app, except if we open the app right now, we will see every user's room with all the messages that have ever been sent within the app by any user. This is because we have not set up Row Level Security yet. [Row Level Security](https://supabase.com/docs/guides/auth/row-level-security) is a mechanism in PostgreSQL that allows developers to define who can perform what operation on a row-by-row basis. There are two ways we can define Row Level Security policies in Supabase, with the GUI or through SQL, but we will set them using SQL today. Let's run the following SQL to set the security policy. +At this point, we seemingly have a complete app. But if we open the app right now, we will see every users' room along with all the messages that have ever been sent. +This is because we have not set up Row Level Security to prevent users from accessing rooms that don't belong to them. +There are two ways we can define Row Level Security policies in Supabase: with the GUI or through SQL. Today we will use SQL. +Let's run the following SQL to set the security policy. ```sql -- Returns true if the signed in user is a participant of the room diff --git a/apps/www/_blog/2022-12-16-custom-domain-names.mdx b/apps/www/_blog/2022-12-16-custom-domain-names.mdx index 79ca54ad805..2578158b3c7 100644 --- a/apps/www/_blog/2022-12-16-custom-domain-names.mdx +++ b/apps/www/_blog/2022-12-16-custom-domain-names.mdx @@ -30,7 +30,7 @@ your users instead interact with Today, we're making Custom Domains generally available, and they're now accessible as a paid add-on through the Supabase dashboard. -Get your custom domain in the [Dashboard](https://app.supabase.com/project/_/settings/general) +Get your custom domain in the [Dashboard](https://supabase.com/dashboard/project/_/settings/general) # Vanity Subdomains diff --git a/apps/www/_blog/2022-12-16-launch-week-6-community-day.mdx b/apps/www/_blog/2022-12-16-launch-week-6-community-day.mdx index eb485c2bb11..07d0e9921fb 100644 --- a/apps/www/_blog/2022-12-16-launch-week-6-community-day.mdx +++ b/apps/www/_blog/2022-12-16-launch-week-6-community-day.mdx @@ -87,7 +87,7 @@ In [this community spotlight video](https://youtube.com/EdYQ9fF-hz4), [Thang Huu Over the past few years, we've had a number of people ask if we can add Full Text Search for other languages. PGroonga has been on our radar for a long time now, so when we reached out to them we were surprised to learn that _no_ Postgres platform currently supports them. Today we're fixing this by becoming the first. -PostgreSQL of course features excellent [Full Text Search](https://supabase.com/docs/guides/database/full-text-search) out-the-box, but it can be lacking if you need to search against languages with non-Roman characters such as Japanese, Chinese and so on. For this you can use the PGroonga extension! It's already installed on all new projects, just head to the [Database tab](https://app.supabase.com/project/_/database/extensions) on the dashboard and search or scroll for 'PGroonga' and hit enable to get started. Once enabled you can head to [their excellent documentation](https://pgroonga.github.io/tutorial/) on how to start making queries. +PostgreSQL of course features excellent [Full Text Search](https://supabase.com/docs/guides/database/full-text-search) out-the-box, but it can be lacking if you need to search against languages with non-Roman characters such as Japanese, Chinese and so on. For this you can use the PGroonga extension! It's already installed on all new projects, just head to the [Database tab](https://supabase.com/dashboard/project/_/database/extensions) on the dashboard and search or scroll for 'PGroonga' and hit enable to get started. Once enabled you can head to [their excellent documentation](https://pgroonga.github.io/tutorial/) on how to start making queries. PGroonga is backed by a collection of incredible maintainers, contributors, and a broad and diverse [community](https://pgroonga.github.io/community/). diff --git a/apps/www/_blog/2022-12-16-postgres-point-in-time-recovery.mdx b/apps/www/_blog/2022-12-16-postgres-point-in-time-recovery.mdx index dbce9c96b54..a566c13a3e0 100644 --- a/apps/www/_blog/2022-12-16-postgres-point-in-time-recovery.mdx +++ b/apps/www/_blog/2022-12-16-postgres-point-in-time-recovery.mdx @@ -17,7 +17,7 @@ When we announced Point-in-Time a few months ago, it was only available for Ente Pro-plan projects created from August 2022 onwards (excluding Northeast Asia / Seoul region), can now enable Point In Time Recovery (PITR) from the dashboard. Projects must have the "Small" compute add-on to ensure that PITR operates smoothly behind the scenes. -For older projects, don't worry - we're working on making it available for everybody. In the meantime, if you would like to have PITR enabled for your ineligible project, reach out directly [here](https://app.supabase.com/support/new), or stay tuned for further updates. +For older projects, don't worry - we're working on making it available for everybody. In the meantime, if you would like to have PITR enabled for your ineligible project, reach out directly [here](https://supabase.com/dashboard/support/new), or stay tuned for further updates. ## What is Point in Time Recovery? @@ -39,7 +39,7 @@ While all Pro-plan projects and above are backed up on a daily basis, this means ## Getting started -Enabling Point in Time Recovery can be done [in the Dashboard](https://app.supabase.com/project/_/settings/billing/subscription?panel=pitr). Retention for backups used by PITR is set to up to 7 days by default but could be increased to up to 28 days via self-serve. +Enabling Point in Time Recovery can be done [in the Dashboard](https://supabase.com/dashboard/project/_/settings/billing/subscription?panel=pitr). Retention for backups used by PITR is set to up to 7 days by default but could be increased to up to 28 days via self-serve. ## More Launch Week 6 diff --git a/apps/www/_blog/2022-12-16-vault-now-in-beta.mdx b/apps/www/_blog/2022-12-16-vault-now-in-beta.mdx index ef7a62d1640..fcc9bbec397 100644 --- a/apps/www/_blog/2022-12-16-vault-now-in-beta.mdx +++ b/apps/www/_blog/2022-12-16-vault-now-in-beta.mdx @@ -22,7 +22,7 @@ Vault is a new Postgres extension and accompanying Supabase UI that makes it saf ❇️ UPDATE JUNE 2023 ❇️ -Supabase Vault is now available on every Supabase project. [Check it out](https://app.supabase.com/project/_/settings/vault/secrets) +Supabase Vault is now available on every Supabase project. [Check it out](https://supabase.com/dashboard/project/_/settings/vault/secrets)
@@ -89,7 +89,7 @@ Privacy is becoming one of the most important features in a modern product. Supa ### Using the Vault -To learn how to use Supabase Vault, check out the [docs](https://supabase.com/docs/guides/database/vault). Supabase Vault is now available on all [Supabase projects](https://app.supabase.com/project/_/settings/vault/secrets) (some projects will have to enable via request). +To learn how to use Supabase Vault, check out the [docs](https://supabase.com/docs/guides/database/vault). Supabase Vault is now available on all [Supabase projects](https://supabase.com/dashboard/project/_/settings/vault/secrets) (some projects will have to enable via request). ## More Launch Week 6 diff --git a/apps/www/_blog/2023-03-09-supabase-beta-update-february-2023.mdx b/apps/www/_blog/2023-03-09-supabase-beta-update-february-2023.mdx index 6b43011f606..42d8126000c 100644 --- a/apps/www/_blog/2023-03-09-supabase-beta-update-february-2023.mdx +++ b/apps/www/_blog/2023-03-09-supabase-beta-update-february-2023.mdx @@ -18,7 +18,7 @@ There’s something for everybody this month: AI, Auth, Database, Edge Functions The most popular GraphQL IDE/API explorer is now built into the dashboard! You can now explore and query your GraphQL API produced by `pg_graphql`. -[Try it now](https://app.supabase.com/project/_/api/graphiql). +[Try it now](https://supabase.com/dashboard/project/_/api/graphiql). ## Supabase + OpenAI search @@ -52,7 +52,7 @@ We rewrote the Postgres Dockerfile with multi-stage builds so that each extensio We've improved database role management. You can create, update, and delete database roles through the dashboard. Just one small step towards column-level security -[Check it out.](https://app.supabase.com/project/_/editor) +[Check it out.](https://supabase.com/dashboard/project/_/editor) ## API docs in the table editor @@ -60,7 +60,7 @@ We've improved database role management. You can create, update, and delete data API docs got a light touchup and were moved to the table editor. You can now look up API methods and generate & download type files right there ✨ -[Check it out.](https://app.supabase.com/project/_/editor) +[Check it out.](https://supabase.com/dashboard/project/_/editor) ## Quick product updates @@ -70,9 +70,9 @@ API docs got a light touchup and were moved to the table editor. You can now loo - **Database**: supabase-js now infers the response type from your query. If the inferred type is incorrect, you can use `.returns()` to override it. [Doc](https://supabase.com/docs/reference/javascript/db-returns) -- **Dashboard**: Improved database roles management, you can now create, update and delete database roles through the dashboard. [Dashboard](https://app.supabase.com/project/_/database/roles) +- **Dashboard**: Improved database roles management, you can now create, update and delete database roles through the dashboard. [Dashboard](https://supabase.com/dashboard/project/_/database/roles) -- **Dashboard**: We've provided a reference panel showing all available paths that can be queried from each respective source that improves the Logs Explorer experience. [Dashboard](https://app.supabase.com/project/_/logs/explorer) +- **Dashboard**: We've provided a reference panel showing all available paths that can be queried from each respective source that improves the Logs Explorer experience. [Dashboard](https://supabase.com/dashboard/project/_/logs/explorer) - **Edge Functions**: upgraded to Deno 1.30.3, that supports TypeScript 4.9.x and introduces `satisfies`. Thanks to [Benjamin Dobell](https://github.com/Benjamin-Dobell) 🙏. [PR](https://github.com/supabase/functions-relay/pull/30) diff --git a/apps/www/_blog/2023-04-13-supabase-auth-sso-pkce.mdx b/apps/www/_blog/2023-04-13-supabase-auth-sso-pkce.mdx index e8783c245d3..ecf8951c8e1 100644 --- a/apps/www/_blog/2023-04-13-supabase-auth-sso-pkce.mdx +++ b/apps/www/_blog/2023-04-13-supabase-auth-sso-pkce.mdx @@ -39,7 +39,7 @@ Building SSO into your application isn't necessarily hard, but does come with so ### Getting Started with SAML 2.0 -To get started, enable the [“SAML 2.0“](https://app.supabase.com/project/phcnitosaawbzytgyznx/auth/providers) [authentication method in the dashboard](https://app.supabase.com/project/_/auth/providers). We've added new commands to the [Supabase CLI](https://supabase.com/docs/guides/cli) to help with the configuration process: +To get started, enable the [“SAML 2.0“](https://supabase.com/dashboard/project/phcnitosaawbzytgyznx/auth/providers) [authentication method in the dashboard](https://supabase.com/dashboard/project/_/auth/providers). We've added new commands to the [Supabase CLI](https://supabase.com/docs/guides/cli) to help with the configuration process: ```bash $ supabase sso --help diff --git a/apps/www/_blog/2023-05-04-flutter-multi-factor-authentication.mdx b/apps/www/_blog/2023-05-04-flutter-multi-factor-authentication.mdx index ad11ad53020..c160b6251d4 100644 --- a/apps/www/_blog/2023-05-04-flutter-multi-factor-authentication.mdx +++ b/apps/www/_blog/2023-05-04-flutter-multi-factor-authentication.mdx @@ -6,6 +6,7 @@ image: flutter-mfa/flutter-mfa-thumb-og.png thumb: flutter-mfa/flutter-mfa-thumb.jpg tags: - flutter + - auth date: '2023-05-04' toc_depth: 2 --- diff --git a/apps/www/_blog/2023-07-06-supabase-beta-update-june-2023.mdx b/apps/www/_blog/2023-07-06-supabase-beta-update-june-2023.mdx new file mode 100644 index 00000000000..6651b5bb101 --- /dev/null +++ b/apps/www/_blog/2023-07-06-supabase-beta-update-june-2023.mdx @@ -0,0 +1,107 @@ +--- +title: Supabase Beta June 2023 +description: A plethora of announcements... read till the end to find out when is the new Launch Week +author: ant_wilson +image: 2023-07-06-beta-update-june/beta-update-june-2023.png +thumb: 2023-07-06-beta-update-june/beta-update-june-2023.png +tags: + - release-notes +date: '2023-07-06' +toc_depth: 3 +--- + +Guess what? We've got some sizzling updates for you this month! Our partnership with Mozilla, Native mobile auth support, revamped billinx experience, real-time debugging magic, and great stuff from the community. Dive in now 🤿 + +## Mozilla uses Supabase to build AI Help. + +![Mozilla uses Supabase to build AI Help.](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/mdn_search.png) + +MDN is one of the richest sources of developer documentation on the internet, and it just received an upgrade. Mozilla built AI Help, an AI chatbot to help with search and discovery. Mozilla chose Supabase Vector and OpenAI to power their new tool which you can try for free. + +[Read the announcement](https://developer.mozilla.org/en-US/blog/introducing-ai-help/) + +## Native Mobile Auth Support for Google and Apple Sign in + +![Native Mobile Auth Support for Google and Apple Sign in](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/native-phone-support.png) + +Supabase Auth now has full native support for Sign in with Apple and Google, which means it can now be used with one-tap sign in methods like Sign in with Apple JS, Sign in with Google for Web, or even in Chrome extensions. + +[Learn more](https://supabase.com/blog/native-mobile-auth) + +## Supabase CLI: what is new? + +![Supabase CLI: what is new?](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/supabase-cli-cache-hi.png) + +It’s been a busy month for the Supabase CLI. We have added a tonne of new features: + +- **Migrations:** view all your migrations inside the Dashboard with the SQL [code that was executed](https://github.com/supabase/cli/pull/1181). +- **Functions:** the CLI now [serves all Functions](https://github.com/supabase/cli/pull/1171) when developing locally. +- **Database monitoring**: we’ve added a `usage` flag for [monitoring key Postgres statistics](https://github.com/supabase/cli/pull/1070). + +[See all updates](https://github.com/supabase/cli/releases) + +## Revamped billing experience + +![Revamped billing experience](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/billing.png) + +We have made huge improvements to the billing tooling inside Supabase Studio, including: + +- Easy monitoring of current usage, overage, and plan limits. +- Streamlined subscription management for upgrades or downgrades. +- Detailed usage billing breakdowns and compute instance specifications. +- And more! + +[New subscription page](https://app.supabase.com/project/_/settings/billing/subscription) | [New usage page](https://app.supabase.com/project/_/settings/billing/usage) + +## Login with Kakao + +![Login with Kakao](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/kakao-social-login.png?t=2023-07-06T13%3A26%3A11.108Z) + +Added the popular social platform Kakao as new social provider. Allow your users to effortlessly sign in using their Kakao accounts and make authentication a breeze while expanding your app's reach to a wider audience. + +[Login with Kakao](https://supabase.com/docs/guides/auth/social-login/auth-kakao) + +## Quick product updates + +- [**Postgres Tooling**] Implemented parallel Index build in regular and recovery state into OrioleDB. [[PR](https://github.com/orioledb/orioledb/commit/8c4a50175cf39a97ac0555ea3f969fe7e40dba21)] +- [**Edge Functions**] Edge Functions troubleshooting guide. [[Doc](https://supabase.com/docs/guides/functions/troubleshooting)] +- [**Storage**] Object id is now returned in the response when uploading an object. [[PR](https://github.com/supabase/storage-api/pull/332)] +- [**Realtime**] A new debugging tool to test your realtime endpoints together with your JWTs and Row Level Security policies. [[Realtime Inspector](https://realtime.supabase.com/inspector/new)] +- [**Docs**] A full guide on database partitions for developers looking to scale up. [[Guide](https://supabase.com/docs/guides/database/partitions)] + +## Made with Supabase + +![Chat Thing is Made with Supabase](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/chatting-ai.png) + +[Chat Thing](https://chatthing.ai/), is an innovative project that allows you to create AI chatbots using your existing data from Notion, uploaded files, websites and more. Built by [pixelhop](https://twitter.com/pixelhopio) using Vue, Nuxt, Railway, and Supabase for database, auth, and vector store. + +## Extended Community Highlights + +![Some of the faces from the community](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/flutter_auth.png) + +- Using Supabase with Cloudflare Workers. [Cloudflare TV](https://cloudflare.tv/event/using-supabase-with-cloudflare-workers/dgM90RgD) +- Build a Chatbot with Next.js, LangChain, OpenAI, and Supabase Vector. [Video Tutorial](https://www.youtube.com/watch?v=Tt45NrVIBn8) +- The refine open source Hackathon is in full swing. [Join now](https://discord.com/channels/@me/1118414473108148296/1123933930702262312) +- Flutter database and user authentication. [Video guide](https://www.youtube.com/watch?v=r7ysVtZ5Row) +- Google authentication with Expo & Supabase. [Tutorial](https://blog.spirokit.com/google-authentication-with-expo-supabase) +- Building Stripe integrations with Supabase. [Video](https://www.youtube.com/watch?v=D5kOnnB72WA) +- Build a Supabase + Drizzle-orm + Express backend. [Video Tutorial](https://www.youtube.com/watch?v=k0uC35J_xJ4) +- LogRocker blog: Authenticate React Applications: Supabase Auth. [Tutorial](https://blog.logrocket.com/authenticate-react-applications-supabase-auth/) +- Using Supabase Vault to store secrets. [Tutorial](https://makerkit.dev/blog/tutorials/supabase-vault) +- Nuxt + Supabase = Technology Stack of Dreams. [Blog post](https://dev.to/jacobandrewsky/nuxt-supabase-technology-stack-of-dreams-4dop) +- Build a to-do app with toddle and Supabase. [Video](https://www.youtube.com/watch?v=SHJ3EadcrgY) + +## We're Hiring + +Come join one of the fastest-growing open source projects ever: + +- [Front-End Developer (o11y focus)](https://boards.greenhouse.io/supabase/jobs/4910374004) +- [Rust developer](https://boards.greenhouse.io/supabase/jobs/4917893004) + +## ⚠️ Baking hot meme zone ⚠️ + +![Our favorite meme from June 2023](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/beta-update-june-2023-meme.png) + +## Launch Week alert: save the date + +![Launch Week 8 is announced - From Monday 07/08 till Friday 11/08](https://obuldanrptloktxcffvn.supabase.co/storage/v1/object/public/images/marketing-emails/lw8-teaser.jpg) diff --git a/apps/www/_blog/2023-07-12-postgrest-11-1-release.mdx b/apps/www/_blog/2023-07-12-postgrest-11-1-release.mdx new file mode 100644 index 00000000000..9637dedf858 --- /dev/null +++ b/apps/www/_blog/2023-07-12-postgrest-11-1-release.mdx @@ -0,0 +1,248 @@ +--- +title: 'What is new in PostgREST v11.1?' +description: 'Impersonated Role Settings, Configurable Isolation Level, improved Bulk Insert, and more' +author: steve_chavez +image: lw6-community/postgrest.png +thumb: lw6-community/postgrest.png +tags: + - postgres +date: '2023-07-12' +toc_depth: 3 +--- + +PostgREST 11.1 is now available on the Supabase platform. Besides the [pre-release](https://supabase.com/blog/postgrest-11-prerelease) features, we’ve added configuration and querying improvements. Here is what's new: + +## Impersonated Role Settings + +Every role that passes [PostgREST JWT Authentication](https://postgrest.org/en/stable/references/auth.html#jwt-based-user-impersonation) is an _impersonated role_. On the Supabase platform, these are the `anon`, `authenticated` and `service_role` roles. + +These roles can now have settings applied with a regular `ALTER ROLE .. SET`. This is useful, for example, to prevent web users from running expensive queries. + +Let’s try it by setting a statement timeout and cost limit. + +### Statement timeout + +`statement_timeout` aborts any statement that takes more than the specified amount of time. Let’s set it for the `anon`, `authenticated` and `service_role` roles: + +```sql +-- anonymous users can run queries that take 100 milliseconds max +alter + role anon +set + statement_timeout = '100ms'; + +-- authenticated users can run queries that take 5 seconds max +alter + role authenticated +set + statement_timeout = '5s'; + +-- backend-only users can run queries that take 15 seconds max +alter + role service_role +set + statement_timeout = '15s'; +``` + +You need to reload PostgREST config cache to apply these changes. + +```sql +NOTIFY pgrst, +'reload config'; +``` + +Now, suppose you do an expensive query with the `anon` role. Like filtering on a big table's unindexed column (this will cause a full table scan): + +```jsx +const { data, error } = await supabase.from('big_table').select().eq('unindexed_column', 'value') +``` + +Then, after 5 seconds, the request will be aborted with the response: + +```json +{ + "hint": null, + "details": null, + "code": "57014", + "message": "canceling statement due to statement timeout" +} +``` + +Which is what we wanted. Note that there's already a global `statement_timeout` set but you can be more fine-grained with this feature. See [timeouts](https://supabase.com/docs/guides/database/timeouts) for more details. + +### Statement Cost Limit + +With a statement timeout, expensive queries will still get executed for a length of time. They'll consume resources until they’re terminated. + +The [pg_plan_filter](https://github.com/pgexperts/pg_plan_filter) extension (available on the Supabase platform), brings a statement cost limit. This abort queries at the planning phase, before they get executed. + +You can use it like: + +```sql +-- anonymous users can only run cheap queries +ALTER + USER anon +SET + plan_filter.statement_cost_limit = 10000; + +-- authenticated users can run more expensive queries +ALTER + USER authenticated +SET + plan_filter.statement_cost_limit = 1e6; + +-- backend-only users can run any query +ALTER + USER service_role +SET + plan_filter.statement_cost_limit = 0; + +NOTIFY pgrst, +'reload config'; + +-- reload postgREST config cache to apply changes +``` + +Let’s repeat the previous expensive query with the `anon` role. + +```jsx +const { data, error } = await supabase.from('big_table').select().eq('unindexed_column', 'value') +``` + +Then, immediately, the request will be aborted and the response will be: + +```jsx +{ + "hint": null, + "details": null, + "code": "54001", + "message": "plan cost limit exceeded" +} +``` + +Note that tuning is required to get the cost limit right. You should use the `plan_filter.statement_cost_limit` with care as it can invalidate legitimate queries. + +## Configurable Transaction Isolation Level + +By default, all queries run in a transaction with the default _read committed_ isolation level. + +You can now modify this with the `default_transaction_isolation` setting. + +If you want a function to run with _repeatable read_ isolation level: + +```sql +create function hello() +returns text as $$ + select 'hello'; +$$ language sql +set default_transaction_isolation = 'repeatable read'; +``` + +Or if you want an impersonated role to run its queries with a _serializable_ isolation level: + +```sql +alter + role service_role +set + default_transaction_isolation = 'serializable'; + +NOTIFY pgrst, +'reload config'; + +-- reload postgREST config cache +``` + +Note that the default _read committed_ is good enough for almost all use cases. Higher isolation levels incur in overhead as they use more sophisticated locking. They're only needed in special cases. + +## Bulk insert JSON with default values + +A long wanted feature was bulk inserting JSON while considering columns' default values. + +Having the following sample table. + +```sql +create table + foo ( + id bigint generated by default as identity primary key, + bar text, + baz int default 100 + ); +``` + +You can now do it like this: + +```jsx +const { error } = await supabase + .from('foo') + .insert([ + { "bar": "val1" + } + , { "bar": "val2" + , "baz": 15 + } + ], defaultToNull: false) + .select() +``` + +And the response will be: + +```json +[ + { "id": 1, "bar": "val1", "baz": 100 }, + { "id": 2, "bar": "val2", "baz": 15 } +] +``` + +As you can see, `id` and `baz` took their default values. + +## ANY/ALL filter modifiers + +As a shortcut to `OR` filters, you can now use `any` modifiers on various filters. Take the `like` filter as an example: + +{/* prettier-ignore */} +```jsx +const res = await postgrest + .from('users') + .select() + .likeAnyOf('username', ['%supa%', '%kiwi%']) +``` + +This is equivalent to the following in SQL. + +```sql +select * +from users +where username like ANY('{%supa%,%kiwi%}'); +``` + +`any` modifiers are available for the `eq,like,ilike,gt,gte,lt,lte,match,imatch` filters. + +For completeness, the `all` modifier is also included. + +## Minimal Breaking Changes from v10 + +If you only use PostgREST through Supabase client libraries (like [`supabase-js`](https://supabase.com/docs/reference/javascript/introduction)) then it's safe to upgrade to v11. If you use PostgREST with other HTTP clients (like `curl`), consider the breaking changes for this version: + +- The `Range` header is now only considered on GET requests and is ignored for any other method. Previously PostgREST responded with an error but [RFC 9110](https://www.rfc-editor.org/rfc/rfc9110.html#name-range) dictates that we should ignore the `Range` header instead. +- RPC requests no longer consider the `Prefer: params=multiple-objects` header. This header was already deprecated on [v10.1.0](https://github.com/PostgREST/postgrest/releases/tag/v10.1.0). + +By making use of [Logflare](https://logflare.app/), we detected that out of 20 thousands of projects: + +- Only 7 projects used `Range` for HTTP methods other than GET. In these cases all responses were errors so in fact this breaking change is a fix for those requests. +- None were using `Prefer: params=multiple-objects`. + +So overall the breaking changes are minimal. + +## Closing up + +There you have it, now you can make your API more secure with role settings and use higher isolation levels without resorting to direct PostgreSQL connections. + +PostgREST v11.1 is available for all Supabase projects created after 5 July 2023. Existing projects can upgrade by doing a pause/unpause. + +## More Postgres resources + +- [Storing OpenAI embeddings in Postgres with pgvector](https://supabase.com/blog/openai-embeddings-postgres-vector) +- [Choosing a Postgres Primary Key](https://supabase.com/blog/choosing-a-postgres-primary-key) +- [SQL or NoSQL? Why not use both (with PostgreSQL)?](https://supabase.com/blog/sql-or-nosql-both-with-postgresql) +- [pg_jsonschema: JSON Schema support for Postgres](https://supabase.com/blog/pg-jsonschema-a-postgres-extension-for-json-validation) +- [Implementing "seen by" functionality with Postgres](https://supabase.com/blog/seen-by-in-postgresql) diff --git a/apps/www/_blog/2023-07-13-pgvector-performance.mdx b/apps/www/_blog/2023-07-13-pgvector-performance.mdx new file mode 100644 index 00000000000..e0cd741f223 --- /dev/null +++ b/apps/www/_blog/2023-07-13-pgvector-performance.mdx @@ -0,0 +1,311 @@ +--- +title: 'pgvector 0.4.0 performance' +description: There's been lot of talk about pgvector performance lately, so we took some datasets and pushed pgvector to the limits to find out its strengths and limitations. +tags: + - AI + - performance + - postgres + - planetpg +date: '2023-07-13' +toc_depth: 2 +author: egor_romanov,pavel +image: 2023-07-13-pgvector-performance/vector-benchmarks-og.jpeg +thumb: 2023-07-13-pgvector-performance/vector-benchmarks-thumb.jpeg +--- + +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. + +Our goals in this article are: + +1. To show the strengths and limitations of the _current version_ of pgvector. +2. Highlight some improvements that are coming to pgvector. +3. Prove to you that it's completely viable for production workloads and give you some tips on using it at scale. We'll show you how to run 1 million Open AI embeddings at ~1800 requests per second with 91% precision, or 670 requests per second with 98% precision. + +## Benchmark Methodology + +We've used the [ANN Benchmarks](https://github.com/erikbern/ann-benchmarks) methodology, a standard for benchmarking vector databases. + +The key elements are: + +- **Helper scripts:** a Python test runner which is responsible for data upload, index creation, and query execution. This uses [qdrant's vector-db-benchmark](https://github.com/qdrant/vector-db-benchmark) repo. The “engine” in this repo uses [Vecs](https://github.com/supabase/vecs), a Python client for pgvector. +- **Runtime:** Each test runs for at least 30-40 minutes and included a series of experiments executed at various concurrency levels. This process allowed us to gauge the engine's performance under different load types. Subsequently, we averaged the results. +- **Pre-warming RAM:** We executed 10,000 to 50,000 “warm-up” queries before each benchmark, matching the number of probes as the benchmark. Additionally, we executed about 1,000 queries with probes ranging from three to ten times the benchmark's probes. Both of these help with RAM utilization. + +
+ multi database + multi database +
+ +## Hardware + +All compute add-ons available on Supabase were used to run our benchmarks. Each add-on variant has a different allocation of RAM and CPU cores, the details of which are available in our docs. Each Supabase compute add-on comes with a specific set of optimizations ([version 2023-07](https://gist.github.com/egor-romanov/323e2847851bbd758081511785573c08)). + +| Instance | CPU | Memory | +| -------- | ----------------------- | ------ | +| 2XL | 8-core ARM (dedicated) | 32 GB | +| 4XL | 16-core ARM (dedicated) | 64 GB | +| 8XL | 32-core ARM (dedicated) | 128 GB | +| 12XL | 48-core ARM (dedicated) | 192 GB | +| 16XL | 64-core ARM (dedicated) | 256 GB | + +## Dataset + +We tested using the same dataset as the Qdrant comparison: [dbpedia-entities-openai-1M](https://huggingface.co/datasets/KShivendu/dbpedia-entities-openai-1M). This dataset includes 1M embeddings with 1536 dimensions (created using OpenAI). The embeddings are created by Wikipedia articles. It's a great dataset! + +
+ +We also have some useful [benchmarks in our docs](https://supabase.com/docs/guides/ai/choosing-compute-addon#results) for [gist-960-angular](http://corpus-texmex.irisa.fr/) (1M image embeddings, 960 dimensions) and [GloVe Reddit comments](https://nlp.stanford.edu/projects/glove/) (1.6M text embeddings, 512 dimensions). + +
+ +## Baseline + +Let's start with NirantK's results as a baseline: + +
+ multi database + multi database +
+ +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. + +## Results + +Our tests mirrored NirantK's: but incorporated slight variations: + +Same: + +- We used the same dataset +- We used the same hardware: a 2XL instance on Supabase, which offers the same core and RAM count as NirantK's machine - 8 cores and 32 GB of RAM + +Changed: + +- We used the pre-warming technique described earlier. +- We used the `inner-product` distance function. +- We set `lists` constant for an index equal to 2000 instead of 1000. +- We adjusted the [Probes](https://github.com/pgvector/pgvector#query-options) in various runs to benchmark the difference (NirantK's tests used `probes = 1`). + +The resulting figures were significantly different after these changes. + +### PROBES = 10 + +With the changes above and probes set to 10, pgvector was faster and more accurate: + +- precision@10 of 0.91 +- RPS (requests per second) of 380 + +
+ multi database + multi database +
+ +### PROBES = 40 + +If we increase the probes from 10 to 40, pgvector was not just substantially faster but also boasted almost the same precision as Qdrant: + +- precision@10 of 0.98 +- RPS of 140 + +
+ multi database + multi database +
+ +### Scaling the database + +Another key takeaway is that the performance scales predictably with the size of the database. For instance, a 4XL instance achieves precision@10 of 0.98 and RPS of 270 with probes set to 40. Moreover, an 8XL compute add-on analogously obtains precision@10 of 0.98 and an RPS of 470, surpassing the results of Qdrant. + +
+ +The Qdrant benchmark uses “default” configuration and is in not indicative of its capabilities after modifying the configuration. + +
+ +
+ multi database + multi database +
+ +Although more compute is required to match Qdrant's precision and RPS levels concurrently, this is still a satisfying outcome. It means that it's not a _necessity_ to use another vector database. You can put everything in Postgres to lower your operational complexity. + +### Final results: pgvector performance + +Putting it all together, we find that we can predictably scale our database to match the performance we need. + +With a 64-core, 256 GB server we achieve ~1800 RPS and 0.91 precision. This is for pgvector 0.4.0, and we've heard that the latest version (0.4.4) already has significant improvements. We'll release those benchmarks as soon as we have them. + +
+ multi database + multi database +
+ +## Other performance factors + +It's been about 5 months since we [added](https://supabase.com/blog/openai-embeddings-postgres-vector) pgvector to the platform. Since then we've discovered a few other important things to keep in mind. + +### Increasing lists improves performance + +Another way to improve performance without throwing more compute would be to increase `lists`. + +We ran a test to measure the impact of list size: we uploaded 90,000 vectors from the Wikipedia dataset and then queried 10,000 vectors from the same dataset. The documentation recommends to use `lists` constant of `number of vectors / 1000`. In this case, it would be 90. + +But as our experiment shows, we can improve RPS if we increase `lists` (i.e. with more lists in the index we need to get less index data to get the same precision). So for 95% precision, we can take any of: + +- 3% of index data = 270 lists +- 6% of index data = 90 lists +- 13% of index data = 30 lists + +
+ multi database + multi database +
+ +This also has an important caveat: building the index takes longer with more lists. Here we measure the index build time for a dataset containing 900,000 vectors: + +So if you can afford an index build time of 1 hour or more, you can go with `lists=5000` (`number of vectors / 200`) or more! + +
+ multi database + multi database +
+ +
+ +You may need to increase `maintenance_work_mem` to be able to create an index with high values for `lists`. For example: + +```sql +SET maintenance_work_mem TO '7168 MB'; +``` + +
+ +Keeping in mind that the overall index size is almost the same, and only index build time increases, we can say that it's better to use more lists for better select queries speed. + +### Real data has higher precision than random data + +Embeddings created from “real” data are more likely to be clustered together, whereas random embeddings are more likely to be scattered. In other words, real embeddings are very far from being randomly distributed. This might seem obvious, but it's an important call-out for benchmarks. + +Embeddings generated for similarity search using “real world data” will be more correlated, so the precision will be higher as well. You can see the difference in this chart using 10,000 Wikipedia embeddings, vs 10,000 randomly-generated embeddings: + +
+ multi database + multi database +
+ +## Optimizing pgvector performance + +Armed with all this information, we can safely give you a few tips and strategies for optimizing your pgvector workloads. + +### Tips + +First, a few generic tips which you can pick and choose from: + +1. **Adjust your Postgres config.** It should be aligned with RAM & CPU cores. [Find more details here](https://gist.github.com/egor-romanov/323e2847851bbd758081511785573c08). +2. Prefer `inner-product` to `L2` or `Cosine` distances if your vectors are normalized (like `text-embedding-ada-002`). If embeddings are not normalized, `Cosine` distance should give the best results with an index. +3. **Pre-warm your database.** Implement the warm-up technique we described earlier before transitioning to production. +4. **Establish your workload.** Increasing the lists constant for the pgvector index can accelerate your queries (at the expense of a slower build). For instance, for benchmarks with OpenAI embeddings, we employed a `lists` constant of 2000 (`number of vectors / 500`) as opposed to the suggested 1000 (`number of vectors / 1000`). +5. **Benchmark your own specific workloads.** Doing this during cache warm-up helps gauge the best value for the `probes` constant, balancing precision with RPS. + +### Going into production + +Before running your pgvector workload in production, here are a few steps you can take to maximize performance. + +1. Over-provision RAM during preparation. You can scale down in step `5`, but it's better to start with a larger size to get the best results for RAM requirements. (We'd recommend at least 8XL if you're using Supabase.) +2. Upload your data to the database. If you use [`vecs`](https://supabase.com/docs/guides/ai/python/api) library, it will automatically generate an index with default parameters. +3. Run a benchmark using randomly generated queries and see the results. Again, you can use `vecs` library with the `ann-benchmarks` tool. Do it with probes set to 10 (default) and then with probes set to 100 or more, so RPS will be lower than 10. +4. Take a look at the RAM usage, and save it as a note for yourself. You would likely want to use compute add-on in the future that would have the same amount of RAM as used at the moment (both actual RAM usage and RAM used for cache and buffers). +5. Scale down your compute add-on to the one that would have the same amount of RAM as used at the moment. +6. Repeat step 3. to load the data into RAM. You should see that RPS is increased on subsequent runs, and stop when it no longer increases. Then repeat the benchmark with probes set to a higher value as well if you didn't do it before on that compute add-on size. +7. Run a benchmark using real queries and see the results. You can use `vecs` library for that as well with `ann-benchmarks` tool. Do it with probes set to 10 (default) and then gradually increase/decrease probes value until you see that both precision and RPS match your requirements. +8. If you want higher RPS and you don't expect to have frequent inserts and reindexing, you can increase `lists` constantly. You have to rebuild the index with higher lists value and repeat steps 6-7 to find the best combination of `lists` and `probes` constants to achieve the best RPS and precision values. Higher `lists` mean that index will build slower, but you can achieve better RPS and precision. Higher probes mean that select queries will be slower, but you can achieve better precision. + +## The pgvector roadmap + +pgvector is still early in development. As with any open source tool, it needs time and resources to make it better. Supabase plans to continue supporting Andrew with his development of pgvector. + +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) +- Product quantization: better storage for IVFFLAT, improving speed and recall +- Parallel index builds: building your IVFFLAT indexes will be much faster + +## More AI resources + +- [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) +- [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) diff --git a/apps/www/_blog/2023-07-18-flutter-authentication.mdx b/apps/www/_blog/2023-07-18-flutter-authentication.mdx new file mode 100644 index 00000000000..550a9e1d7f8 --- /dev/null +++ b/apps/www/_blog/2023-07-18-flutter-authentication.mdx @@ -0,0 +1,426 @@ +--- +title: 'Getting started with Flutter authentication' +description: Learn how authentication on Flutter works through Google sign in with Supabase auth. +tags: + - flutter + - auth +date: '2023-07-18' +toc_depth: 2 +author: tyler_shukert +image: flutter-authentication/flutter-authentication.png +thumb: flutter-authentication/flutter-authentication.png +--- + +Flutter is Google’s open-source framework to develop cross-platform applications. In this article, we will take a look at how we can implement authentication using Google sign-in to secure our application using the [Supabase SDK for Flutter](https://supabase.com/docs/reference/dart/introduction). + +We will also dive into the deep ends of Open ID Connect sign-in to better understand how third-party sign-ins are being performed. You can check out the code of the sample in this article [here](https://github.com/supabase/supabase/tree/master/examples/auth/flutter-native-google-auth). + +## Prerequisites + +This article assumes you are comfortable with writing a basic application in Flutter. No knowledge of Supabase is required. + +We will use the following tools + +- [Flutter](https://docs.flutter.dev/get-started/install) - we used v3.10.5 for this article +- Supabase - create your account [here](https://database.new/) if you do not have one +- IDE of your choosing + +## What is Open ID Connect? + +We will implement third-party login with Google utilizing the Open ID Connect functionality of Supabase Auth. Open ID Connect, or OIDC is a protocol built on top of OAuth 2.0 that allows third-party applications to request the users to provide some personal information, such as name or profile image, in the form of an identity token along with an access token. This identity token can then be verified and decoded by the application to obtain that personal information. + +Supabase auth provides `signInWithIdToken` method where we can sign in a user using their ID token obtained from third-party auth providers such as Google. Upon signing a user with the `signInWithIdToken` method, Supabase automatically populates the content of the ID token in the Supabase user metadata for easy access to the information. We will be utilizing this feature in this example to display the user profile upon the user signing in. + +In today’s example, our app will make a request to Google, obtain the identity token, and we will use it to sign the user in as well as obtain basic user information. + +## What we will build + +We will build a simple app with a login screen and a home screen. The user is first presented with the login screen, and only after they sign in, can they proceed to the home screen. The login screen presents a login button that will kick off a third-party authentication flow to complete the sign-in. The profile screen displays user information such as the profile image or their full name. + +![Flutter Google sign in](/images/blog/flutter-authentication/flutter-google-sign-in.png) + +## Setup the Flutter project + +Let’s start by creating a fresh Flutter project. + +```bash +flutter create myauthapp +``` + +then we can install the dependencies. Change the working directory to the newly created app directory and run the following command to install our dependencies. + +```dart +flutter pub add supabase_flutter flutter_appauth crypto +``` + +We will use [supabase_flutter](https://pub.dev/packages/supabase_flutter) to interact with our Supabase instance. [flutter_appauth](https://pub.dev/packages/flutter_appauth) will be used to implement Google login, and [crypto](https://pub.dev/packages/crypto) is a library that has utility functions for encryption that we will use when performing OIDC logins. + +We are done installing our dependencies. Let’s set up [authentication](https://supabase.com/docs/guides/auth) now. + +## Configure Google sign-in on Supabase Auth + +We will obtain client IDs for iOS and Android from the Google Cloud console, and register them to our Supabase project. + +First, create your Google Cloud project [here](https://cloud.google.com/) if you do not have one yet. Within your Google Cloud project, follow the [Configure a Google API Console project for Android](https://developers.google.com/identity/sign-in/android/start-integrating#configure_a_project) guide and [Get an OAuth client ID for the iOS](https://developers.google.com/identity/sign-in/ios/start-integrating#get_an_oauth_client_id) guide to obtain client IDs for Android and iOS respectively. + +Once you have the client IDs, let’s add them to our Supabase dashboard. If you don’t have a Supabase project created yet, you can create one at [database.new](https://database.new) for free. The name is just an internal name, so we can call it “Auth” for now. Database Password will not be used in this example and can be reconfigured later, so press the `Generate a password` button and let Supabase generate a secure random password. No need to copy it anywhere. The region should be anywhere close to where you live, or where your users live in an actual production app. + +Lastly, for the pricing plan choose the free plan that allows you to connect with all major social OAuth providers and supports up to 50,000 monthly active users. + +![Supabase project creation](/images/blog/flutter-authentication/supabase-project-creation.png) + +Your project should be ready in a minute or two. Once your project is ready, you can open `authentication -> Providers -> Google` to set up Google auth. Toggle the `Enable Sign in with Google` switch first. Then add the two client IDs you obtained in your Google Cloud console to `Authorized Client IDs` field with a comma in between the two client IDs like this: `ANDROID_CLIENT_ID,IOS_CLIENT_ID`. + +![Supabase auth Google auth provider](/images/blog/flutter-authentication/supabase-google-provider.png) + +We also need some Android specific settings to make [flutter_appauth](https://pub.dev/packages/flutter_appauth#android-setup) work. Open `android/app/build.gradle` and find the `defaultConfig`. We need to set the reversed DNS form of the Android Client ID as the`appAuthRedirectScheme` manifest placeholder value. + +```groovy +... +android { + ... + defaultConfig { + ... + manifestPlaceholders += [ + // *account_id* will be unique for every single app + 'appAuthRedirectScheme': 'com.googleusercontent.apps.*account_id*' + ] + } +} +``` + +That is it for setting up our [Supabase auth to prepare for Google sign-in](https://supabase.com/docs/guides/auth/social-login/auth-google#using-native-sign-in). + +Finally, we can initialize Supabase in our Flutter application with the credentials of our Supabase instance. Update your `main.dart` file and add `Supabase.initialize()` in the `main` function like the following. Note that you will see some errors since the home screen is set to the `LoginScreen`, which we will create later. + +```dart +import 'package:flutter/material.dart'; +import 'package:myauthapp/screens/login_screen.dart'; +import 'package:supabase_flutter/supabase_flutter.dart'; + +void main() async { + /// TODO: update Supabase credentials with your own + await Supabase.initialize( + url: 'YOUR_SUPABASE_URL', + anonKey: 'YOUR_ANON_KEY', + ); + runApp(const MyApp()); +} + +final supabase = Supabase.instance.client; + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + + @override + Widget build(BuildContext context) { + return MaterialApp( + debugShowCheckedModeBanner: false, + title: 'Flutter Auth', + theme: ThemeData( + colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple), + useMaterial3: true, + ), + home: const LoginScreen(), + ); + } +} +``` + +You can find your Supabase URL and Anon key in `Settings -> API` from your [Supabase dashboard](https://supabase.com/dashboard/project/_/settings/api). + +![Supabase credentials](/images/blog/flutter-authentication/supabase-credentials.png) + +## Create the Login Screen + +We will have two screens for this app, `LoginScreen` and `ProfileScreen`. `LoginScreen` presents a single sign-in button for the user to perform Google sign-in. Create a `lib/screens/login_screen.dart` file add add the following. + +```dart +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; + +import 'package:crypto/crypto.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_appauth/flutter_appauth.dart'; +import 'package:myauthapp/main.dart'; +import 'package:myauthapp/screens/profile_screen.dart'; +import 'package:supabase_flutter/supabase_flutter.dart'; + +class LoginScreen extends StatefulWidget { + const LoginScreen({super.key}); + + @override + State createState() => _LoginScreenState(); +} + +class _LoginScreenState extends State { + @override + void initState() { + _setupAuthListener(); + super.initState(); + } + + void _setupAuthListener() { + supabase.auth.onAuthStateChange.listen((data) { + final event = data.event; + if (event == AuthChangeEvent.signedIn) { + Navigator.of(context).pushReplacement( + MaterialPageRoute( + builder: (context) => const ProfileScreen(), + ), + ); + } + }); + } + + /// Function to generate a random 16 character string. + String _generateRandomString() { + final random = Random.secure(); + return base64Url.encode(List.generate(16, (_) => random.nextInt(256))); + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar( + title: const Text('Login'), + ), + body: Center( + child: ElevatedButton( + onPressed: () async { + const appAuth = FlutterAppAuth(); + + // Just a random string + final rawNonce = _generateRandomString(); + final hashedNonce = + sha256.convert(utf8.encode(rawNonce)).toString(); + + /// TODO: update the iOS and Android client ID with your own. + /// + /// Client ID that you registered with Google Cloud. + /// You will have two different values for iOS and Android. + final clientId = + Platform.isIOS ? 'IOS_CLIENT_ID' : 'ANDROID_CLIENT_ID'; + + /// Set as reversed DNS form of Google Client ID + `:/` for Google login + final redirectUrl = '${clientId.split('.').reversed.join('.')}:/'; + + /// Fixed value for google login + const discoveryUrl = + 'https://accounts.google.com/.well-known/openid-configuration'; + + // authorize the user by opening the concent page + final result = await appAuth.authorize( + AuthorizationRequest( + clientId, + redirectUrl, + discoveryUrl: discoveryUrl, + nonce: hashedNonce, + scopes: [ + 'openid', + 'email', + 'profile', + ], + ), + ); + + if (result == null) { + throw 'No result'; + } + + // Request the access and id token to google + final tokenResult = await appAuth.token( + TokenRequest( + clientId, + redirectUrl, + authorizationCode: result.authorizationCode, + discoveryUrl: discoveryUrl, + codeVerifier: result.codeVerifier, + nonce: result.nonce, + scopes: [ + 'openid', + 'email', + ], + ), + ); + + final idToken = tokenResult?.idToken; + + if (idToken == null) { + throw 'No idToken'; + } + + await supabase.auth.signInWithIdToken( + provider: Provider.google, + idToken: idToken, + nonce: rawNonce, + ); + }, + child: const Text('Google login'), + ), + ), + ); + } +} +``` + +In terms of UI, this page is very simple, it just has a basic `Scaffold` with an `AppBar`, and has a button right in the middle of the body. Upon pressing the button, Google sign in flow starts. The user is presented with a Google authentication screen where they will complete the consent to allow our application to sign the user in using a Google account, as well as allow us to view some personal information. + +![Google sign in](/images/blog/flutter-authentication/google-sign-in.png) + +Let’s break down what is going on within the `onPressed` callback of the sign in button. + +First, we are generating a [nonce](https://openid.net/specs/openid-connect-core-1_0.html#SelfIssuedDiscovery:~:text=auth_time%20response%20parameter.)-,nonce,-String%20value%20used), which is essentially just a random string. This string is later passed to Google after being hashed to verify that the ID token has not been tampered to prevent a man-in-the-middle attack. + +```dart +// Random string to verify the integrity of the ID Token +final rawNonce = _generateRandomString(); +final hashedNonce = sha256.convert(utf8.encode(rawNonce)).toString(); +``` + +`clientId` and `applicationId` are the app-specific values. These will be used to the authentication request to Google later on. + +```dart + /// Client ID that you registered with Google Cloud. + /// You will have two different values for iOS and Android. + final clientId = Platform.isIOS ? 'IOS_CLIENT_ID' : 'ANDROID_CLIENT_ID'; +``` + +`redirectUrl` is the URL at which the user will be redirected after a successful authentication request. For Google sign-in, we can set it to the reversed DNS form of the client ID followed by `:/`. `discoveryUrl` is a URL provided by Google that contains information about their Open ID configuration. + +```dart +/// Set as reversed DNS form of Google Client ID + `:/` for Google login +final redirectUrl = '${clientId.split('.').reversed.join('.')}:/'; + +/// Fixed value for google login +const discoveryUrl = 'https://accounts.google.com/.well-known/openid-configuration'; +``` + +Then we are sending an authorization request to Google. This is where the user is taken to Google’s page to perform sign in and consent our app to obtain some personal information. Note that we are requesting three scopes here. `openid` and `email` are required by Supabase auth to complete the sign-in process. `profile` is not required by Supabase auth, but we are requesting it to display some profile information on the profile screen later on. We do not actually obtain the requested information in this step though. All we are doing is requesting an access token that has permission to obtain the personal information we have requested. + +```dart +// Authorize the user by opening the concent page +final result = await appAuth.authorize( + AuthorizationRequest( + clientId, + redirectUrl, + discoveryUrl: discoveryUrl, + nonce: hashedNonce, + scopes: [ + 'openid', + 'email', + 'profile', + ], + ), +); +``` + +Using the authorization token obtained in the previous step, we make the final request to Google’s auth server to obtain the personal information we asked for earlier. We get an ID token in return, which contains the personal information. + +```dart +// Request the access and id token to google +final tokenResult = await appAuth.token( + TokenRequest( + clientId, + redirectUrl, + authorizationCode: result.authorizationCode, + discoveryUrl: discoveryUrl, + codeVerifier: result.codeVerifier, + nonce: result.nonce, + scopes: [ + 'openid', + 'email', + 'profile', + ], + ), +); +``` + +And lastly, we pass the ID token we obtained from Google to Supabase to complete the sign-in on Supabase auth. Once the user is signed in, the auth state listener in the `initState` fires and takes the user to the `ProfileScreen`. + +```dart +await supabase.auth.signInWithIdToken( + provider: Provider.google, + idToken: idToken, + nonce: rawNonce, +); +``` + +## Create the Profile Screen + +The `ProfileScreen` will be just a simple UI presenting some of the information we obtained in the `LoginPage`. We can access the user data with `supabase.auth.currentUser`, where Supabase has saved the personal information in a property called `userMetadata`. In this example, we are displaying the `avatar_url` and `full_name` to display a basic profile page. Create a `lib/screens/profile_screen.dart` file and add the following. + +```dart +import 'package:flutter/material.dart'; +import 'package:myauthapp/main.dart'; +import 'package:myauthapp/screens/login_screen.dart'; + +class ProfileScreen extends StatelessWidget { + const ProfileScreen({super.key}); + + @override + Widget build(BuildContext context) { + final user = supabase.auth.currentUser; + final profileImageUrl = user?.userMetadata?['avatar_url']; + final fullName = user?.userMetadata?['full_name']; + return Scaffold( + appBar: AppBar( + title: const Text('Profile'), + actions: [ + TextButton( + onPressed: () async { + await supabase.auth.signOut(); + if (context.mounted) { + Navigator.of(context).pushReplacement( + MaterialPageRoute(builder: (context) => const LoginScreen()), + ); + } + }, + child: const Text('Sign out'), + ) + ], + ), + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (profileImageUrl != null) + ClipOval( + child: Image.network( + profileImageUrl, + width: 100, + height: 100, + fit: BoxFit.cover, + ), + ), + const SizedBox(height: 16), + Text( + fullName ?? '', + style: Theme.of(context).textTheme.headlineMedium, + ), + const SizedBox(height: 32), + ], + ), + ), + ); + } +} +``` + +And with that, we now have a basic working personalized application that utilizes Google sign-in. + +![Flutter Google sign in app](/images/blog/flutter-authentication/flutter-google-sign-in.png) + +## Conclusion + +In this post, we learned how to implement authentication in a Flutter application using Google sign-in and the Supabase SDK for Flutter. We also delved into the Open ID Connect functionality, which allows third-party sign-ins and the retrieval of personal information through identity tokens. + +You can also check out the [Flutter reference documents](https://supabase.com/docs/reference/dart/installing) to see how you can use `supabase-flutter` to implement a Postgres database, Storage, Realtime, and more. + +## More Flutter and Supabase resources + +- [supabase_flutter package](https://pub.dev/packages/supabase_flutter) +- [Build a chat application using Flutter and Supabase](https://supabase.com/blog/flutter-tutorial-building-a-chat-app) +- [Securing your Flutter apps with Multi-Factor Authentication](https://supabase.com/blog/flutter-multi-factor-authentication) +- [How to build a real-time multiplayer game with Flutter Flame](https://supabase.com/blog/flutter-real-time-multiplayer-game) diff --git a/apps/www/_customers/mobbin.mdx b/apps/www/_customers/mobbin.mdx index 6a8345ed0c7..ae7c0334ee8 100644 --- a/apps/www/_customers/mobbin.mdx +++ b/apps/www/_customers/mobbin.mdx @@ -98,4 +98,4 @@ Migrating to Supabase helped the team at Mobbin instantly improve the end-user e They now add new features with confidence, and they continue to help creators all over the globe find inspiration for their next project. You can [check out Mobbin on their website](https://mobbin.design/browse/ios/apps). -[Sign up](https://app.supabase.com/) for Supabase's free plan and set up a scalable backend in less than 2 minutes. +[Sign up](https://supabase.com/dashboard/) for Supabase's free plan and set up a scalable backend in less than 2 minutes. diff --git a/apps/www/_customers/replenysh.mdx b/apps/www/_customers/replenysh.mdx index ca6aef5898f..4d70d4674b3 100644 --- a/apps/www/_customers/replenysh.mdx +++ b/apps/www/_customers/replenysh.mdx @@ -88,4 +88,4 @@ Replenysh clients include brands with global recognition and millions of custome ## Supabase help Replenysh continue to scale -Supabase turbo-charged Replenysh's development time with a seamless end-user mobile login experience. They are ready to help major brands engage with their users through participation in the circular economy. With Supabase, the team knows they have a slick auth experience, reduced DevOps overhead, and can continue to scale with Postgres. You can test out the Supabase developer experience today by [starting a new project on the free plan!.](https://app.supabase.com) +Supabase turbo-charged Replenysh's development time with a seamless end-user mobile login experience. They are ready to help major brands engage with their users through participation in the circular economy. With Supabase, the team knows they have a slick auth experience, reduced DevOps overhead, and can continue to scale with Postgres. You can test out the Supabase developer experience today by [starting a new project on the free plan!.](https://supabase.com/dashboard) diff --git a/apps/www/components/BackedBy.tsx b/apps/www/components/BackedBy.tsx index f796653e736..af93fc30156 100644 --- a/apps/www/components/BackedBy.tsx +++ b/apps/www/components/BackedBy.tsx @@ -1,5 +1,6 @@ import React from 'react' import { useRouter } from 'next/router' +import Image from 'next/image' const BackedBy = ({ className, @@ -23,26 +24,42 @@ const BackedBy = ({ backed by
- Y Combinator - Mozilla - Coatue - Felicis +
+ Y Combinator +
+
+ Mozilla +
+
+ Coatue +
+
+ Felicis +
diff --git a/apps/www/components/Carousels/ImageCarousel.tsx b/apps/www/components/Carousels/ImageCarousel.tsx index ef544266da7..802a1bf4ff5 100644 --- a/apps/www/components/Carousels/ImageCarousel.tsx +++ b/apps/www/components/Carousels/ImageCarousel.tsx @@ -1,6 +1,6 @@ import { Button, IconCornerRightUp, Tabs } from 'ui' import { useRouter } from 'next/router' -import { useState } from 'react' +import { useRef, useState } from 'react' // Import Swiper React components import { Swiper, SwiperSlide } from 'swiper/react' @@ -11,6 +11,7 @@ import 'swiper/swiper.min.css' import Image from 'next/image' import TextLink from '../TextLink' import ImageCarouselStyles from './ImageCarousel.module.css' +import { useInView } from 'framer-motion' interface Content { title: string @@ -29,6 +30,8 @@ interface ImageCarouselProps { } function ImageCarousel(props: ImageCarouselProps) { + const sectionRef = useRef(null) + const isInView = useInView(sectionRef, { margin: '75%', once: true }) // base path for images const { basePath } = useRouter() @@ -66,7 +69,7 @@ function ImageCarousel(props: ImageCarouselProps) { ) return ( -
+
@@ -116,7 +119,7 @@ function ImageCarousel(props: ImageCarouselProps) { height="960" /> )} - {content.youtube_id && ( + {isInView && content.youtube_id && (