diff --git a/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx b/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx
index 5f957a2b7a710..906e4a5b0feb1 100644
--- a/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx
+++ b/apps/docs/components/Navigation/NavigationMenu/MenuIconPicker.tsx
@@ -1,4 +1,4 @@
-import { Heart, Server } from 'lucide-react'
+import { Clock, Heart, Server, SquareStack } from 'lucide-react'
import {
IconBranching,
@@ -93,6 +93,10 @@ function getMenuIcon(menuKey: string, width: number = 16, height: number = 16, c
return
case 'deployment':
return
+ case 'cron':
+ return
+ case 'queue':
+ return
default:
return
}
diff --git a/apps/docs/components/Navigation/NavigationMenu/MenuIcons.tsx b/apps/docs/components/Navigation/NavigationMenu/MenuIcons.tsx
index c9dfa87898017..353214ce46e93 100644
--- a/apps/docs/components/Navigation/NavigationMenu/MenuIcons.tsx
+++ b/apps/docs/components/Navigation/NavigationMenu/MenuIcons.tsx
@@ -1,4 +1,4 @@
-import { products } from 'shared-data'
+import { PRODUCT_MODULES, products } from 'shared-data'
type HomeMenuIcon = {
width?: number
@@ -450,7 +450,7 @@ export function IconMenuAI({ width = 16, height = 16, className }: HomeMenuIcon)
xmlns="http://www.w3.org/2000/svg"
>
{
return MenuId.Api
case pathname.startsWith('auth'):
return MenuId.Auth
- case pathname.startsWith('local-development'):
- return MenuId.LocalDevelopment
+ case pathname.startsWith('cron'):
+ return MenuId.Cron
case pathname.startsWith('database'):
return MenuId.Database
case pathname.startsWith('deployment'):
@@ -123,6 +123,8 @@ export const getMenuId = (pathname: string | null) => {
return MenuId.Graphql
case pathname.startsWith('integrations'):
return MenuId.Integrations
+ case pathname.startsWith('local-development'):
+ return MenuId.LocalDevelopment
case pathname.startsWith('monitoring-troubleshooting'):
return MenuId.MonitoringTroubleshooting
case pathname.startsWith('platform'):
diff --git a/apps/docs/content/guides/cron.mdx b/apps/docs/content/guides/cron.mdx
new file mode 100644
index 0000000000000..84182b0dd1460
--- /dev/null
+++ b/apps/docs/content/guides/cron.mdx
@@ -0,0 +1,34 @@
+---
+title: 'Cron'
+subtitle: 'Schedule Recurring Jobs with Cron Syntax in Postgres'
+---
+
+Supabase Cron is a Postgres Module that simplifies scheduling recurring Jobs with cron syntax and monitoring Job runs inside Postgres.
+
+Cron Jobs can be created via SQL or the Cron interface inside of Supabase Dashboard and can run anywhere from every second to once a year depending on your use case.
+
+Every Job can run SQL snippets or database functions with zero network latency or make an HTTP request, such as invoking a Supabase Edge Function, with ease.
+
+
+
+For best performance, we recommend no more than 8 Jobs run concurrently. Each Job should run no more than 10 minutes.
+
+
+
+## How does Cron work?
+
+Under the hood, Supabase Cron uses the [`pg_cron`](https://github.com/citusdata/pg_cron) Postgres database extension which is the scheduling and execution engine for your Jobs.
+
+
+
+`pg_cron` is not fully supported on Fly Postgres. Learn more about [Fly Postgres limitations](/docs/guides/platform/fly-postgres#limitations).
+
+
+
+The extension creates a `cron` schema in your database and all Jobs are stored on the `cron.job` table. Every Job's run and its status is recorded on the `cron.job_run_details` table.
+
+The Supabase Dashboard provides and interface for you to schedule Jobs and monitor Job runs. You can also do the same with SQL.
+
+## Resources
+
+- [`pg_cron` GitHub Repository](https://github.com/citusdata/pg_cron)
diff --git a/apps/docs/content/guides/cron/install.mdx b/apps/docs/content/guides/cron/install.mdx
new file mode 100644
index 0000000000000..736b8870c287e
--- /dev/null
+++ b/apps/docs/content/guides/cron/install.mdx
@@ -0,0 +1,44 @@
+---
+title: 'Install'
+---
+
+Install the Supabase Cron Postgres Module to begin scheduling recurring Jobs.
+
+
+
+
+1. Go to the [Cron Postgres Module](/dashboard/project/_/integrations/cron/overview) under Integrations in the Dashboard.
+2. Enable the `pg_cron` extension.
+
+
+
+
+```sql
+create extension pg_cron with schema pg_catalog;
+
+grant usage on schema cron to postgres;
+grant all privileges on all tables in schema cron to postgres;
+```
+
+
+
+
+## Uninstall
+
+Uninstall Supabase Cron by disabling the `pg_cron` extension:
+
+```sql
+drop extension if exists pg_cron;
+```
+
+
+
+Disabling the `pg_cron` extension will permanently delete all Jobs.
+
+
diff --git a/apps/docs/content/guides/cron/quickstart.mdx b/apps/docs/content/guides/cron/quickstart.mdx
new file mode 100644
index 0000000000000..874644001a493
--- /dev/null
+++ b/apps/docs/content/guides/cron/quickstart.mdx
@@ -0,0 +1,337 @@
+---
+title: 'Quickstart'
+---
+
+
+
+Job names are case sensitive and cannot be edited once created.
+
+Attempting to create a second Job with the same name (and case) will overwrite the first Job.
+
+
+
+## Schedule a Job
+
+
+
+
+1. Go to the [Jobs](/dashboard/project/_/integrations/cron/jobs) section to schedule your first Job.
+2. Click on `Create job` button or navigate to the new Cron Job form [here](/dashboard/project/_/integrations/cron/jobs?dialog-shown=true).
+3. Name your Cron Job.
+4. Choose a schedule for your Job by inputting cron syntax (refer to the syntax chart in the form) or natural language.
+5. Input SQL snippet or select a Database function, HTTP request, or Supabase Edge Function.
+
+
+
+
+
+
+```sql
+-- Cron Job name cannot be edited
+select cron.schedule('permanent-cron-job-name', '30 seconds', 'CALL do_something()');
+```
+
+
+
+
+
+
+
+
+ ```
+ ┌───────────── min (0 - 59)
+ │ ┌────────────── hour (0 - 23)
+ │ │ ┌─────────────── day of month (1 - 31)
+ │ │ │ ┌──────────────── month (1 - 12)
+ │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to
+ │ │ │ │ │ Saturday, or use names; 7 is also Sunday)
+ │ │ │ │ │
+ │ │ │ │ │
+ * * * * *
+ ```
+
+ You can use [1-59] seconds (e.g. `30 seconds`) as the cron syntax to schedule sub-minute Jobs.
+
+
+
+
+
+
+
+
+You can input seconds for your Job schedule interval as long as you're on Postgres version 15.1.1.61 or later.
+
+
+
+## Edit a Job
+
+
+
+
+1. Go to the [Jobs](/dashboard/project/_/integrations/cron/jobs) section and find the Job you'd like to edit.
+2. Click on the three vertical dots menu on the right side of the Job and click `Edit cron job`.
+3. Make your changes and then click `Save cron job`.
+
+
+
+
+
+
+```sql
+select cron.alter_job(
+ job_id := (select jobid from cron.job where jobname = 'permanent-cron-job-name'),
+ schedule := '*/5 * * * *'
+);
+```
+
+Full options for the `cron.alter_job()` function are:
+
+```sql
+cron.alter_job(
+ job_id bigint,
+ schedule text default null,
+ command text default null,
+ database text default null,
+ username text default null,
+ active boolean default null
+)
+```
+
+It is also possible to modify a job by using the `cron.schedule()` function by inputting the same job name. This will replace the existing job via upsert.
+
+
+
+
+## Activate/Deactivate a Job
+
+
+
+
+1. Go to the [Jobs](/dashboard/project/_/integrations/cron/jobs) section and find the Job you'd like to unschedule.
+2. Toggle the `Active`/`Inactive` switch next to Job name.
+
+
+
+
+
+
+```sql
+-- Activate Job
+select cron.alter_job(
+ job_id := (select jobid from cron.job where jobname = 'permanent-cron-job-name'),
+ active := true
+);
+
+-- Deactivate Job
+select cron.alter_job(
+ job_id := (select jobid from cron.job where jobname = 'permanent-cron-job-name'),
+ active := false
+);
+```
+
+
+
+
+## Unschedule a Job
+
+
+
+
+1. Go to the [Jobs](/dashboard/project/_/integrations/cron/jobs) section and find the Job you'd like to delete.
+2. Click on the three vertical dots menu on the right side of the Job and click `Delete cron job`.
+3. Confirm deletion by entering the Job name.
+
+
+
+
+
+
+```sql
+select cron.unschedule('permanent-cron-job-name');
+```
+
+
+
+Unscheduling a Job will permanently delete the Job from `cron.job` table but its run history remain in `cron.job_run_details` table.
+
+
+
+
+
+
+## Inspecting Job Runs
+
+
+
+
+1. Go to the [Jobs](/dashboard/project/_/integrations/cron/jobs) section and find the Job you want to see the runs of.
+2. Click on the `History` button next to the Job name.
+
+
+
+
+
+
+```sql
+select
+ *
+from cron.job_run_details
+where jobid = (select jobid from cron.job where jobname = 'permanent-cron-job-name')
+order by start_time desc
+limit 10;
+```
+
+
+
+The records in the `cron.job_run_details` table are not cleaned up automatically. They are also not removed when jobs are unscheduled, which will take up disk space in your database.
+
+
+
+
+
+
+## Examples
+
+### Delete data every week
+
+{/* */}
+
+Delete old data every Saturday at 3:30AM (GMT):
+
+{/* */}
+
+```sql
+select cron.schedule (
+ 'saturday-cleanup', -- name of the cron job
+ '30 3 * * 6', -- Saturday at 3:30AM (GMT)
+ $$ delete from events where event_time < now() - interval '1 week' $$
+);
+```
+
+### Run a vacuum every day
+
+{/* */}
+
+Vacuum every day at 3:00AM (GMT):
+
+{/* */}
+
+```sql
+select cron.schedule('nightly-vacuum', '0 3 * * *', 'VACUUM');
+```
+
+### Call a database function every 5 minutes
+
+Create a [`hello_world()`](/docs/guides/database/functions?language=sql#simple-functions) database function and then call it every 5 minutes:
+
+```sql
+select cron.schedule('call-db-function', '*/5 * * * *', 'SELECT hello_world()');
+```
+
+### Call a database stored procedure
+
+To use a stored procedure, you can call it like this:
+
+```sql
+select cron.schedule('call-db-procedure', '*/5 * * * *', 'CALL my_procedure()');
+```
+
+### Invoke Supabase Edge Function every 30 seconds
+
+Make a POST request to a Supabase Edge Function every 30 seconds:
+
+```sql
+select
+ cron.schedule(
+ 'invoke-function-every-half-minute',
+ '30 seconds',
+ $$
+ select
+ net.http_post(
+ url:='https://project-ref.supabase.co/functions/v1/function-name',
+ headers:=jsonb_build_object('Content-Type','application/json', 'Authorization', 'Bearer ' || 'YOUR_ANON_KEY'),
+ body:=jsonb_build_object('time', now() ),
+ timeout_milliseconds:=5000
+ ) as request_id;
+ $$
+ );
+```
+
+
+
+This requires the [`pg_net` extension](/docs/guides/database/extensions/pg_net) to be enabled.
+
+
+
+## Caution: Scheduling System Maintenance
+
+Be extremely careful when setting up Jobs for system maintenance tasks as they can have unintended consequences.
+
+For instance, scheduling a command to terminate idle connections with `pg_terminate_backend(pid)` can disrupt critical background processes like nightly backups. Often, there is an existing Postgres setting, such as `idle_session_timeout`, that can perform these common maintenance tasks without the risk.
+
+Reach out to [Supabase Support](https://supabase.com/support) if you're unsure if that applies to your use case.
diff --git a/apps/docs/content/guides/database/extensions/pg_cron.mdx b/apps/docs/content/guides/database/extensions/pg_cron.mdx
index 6b934fbbe97a2..680a7680351da 100644
--- a/apps/docs/content/guides/database/extensions/pg_cron.mdx
+++ b/apps/docs/content/guides/database/extensions/pg_cron.mdx
@@ -1,194 +1,7 @@
---
id: 'pg_cron'
-title: 'pg_cron: Job Scheduling'
-description: 'pgnet: a simple cron-based job scheduler for PostgreSQL that runs inside the database.'
+title: 'pg_cron: Schedule Recurring Jobs with Cron Syntax in Postgres'
+description: 'pg_cron: schedule recurring Jobs with cron syntax in Postgres.'
---
-The `pg_cron` extension is a simple cron-based job scheduler for PostgreSQL that runs inside the database.
-
-
-
-pg_cron is not fully supported on Fly Postgres. Read more about this [Fly Postgres limitation here](/docs/guides/platform/fly-postgres#limitations).
-
-
-
-## Usage
-
-### Enable the extension
-
-
-
-
-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 "pg_cron" and enable the extension.
-
-
-
-
-```sql
--- Example: enable the "pg_cron" extension
-create extension pg_cron with schema pg_catalog;
-
-grant usage on schema cron to postgres;
-grant all privileges on all tables in schema cron to postgres;
-
--- Example: disable the "pg_cron" extension
-drop extension if exists pg_cron;
-```
-
-
-
-
-### Syntax
-
-The schedule uses the standard cron syntax, in which \* means "run every time period", and a specific number means "but only at this time":
-
-```bash
- ┌───────────── min (0 - 59)
- │ ┌────────────── hour (0 - 23)
- │ │ ┌─────────────── day of month (1 - 31)
- │ │ │ ┌──────────────── month (1 - 12)
- │ │ │ │ ┌───────────────── day of week (0 - 6) (0 to 6 are Sunday to
- │ │ │ │ │ Saturday, or use names; 7 is also Sunday)
- │ │ │ │ │
- │ │ │ │ │
- * * * * *
-```
-
-You can use `[1-59] seconds` as the cron syntax to schedule sub-minute jobs. This is available on `pg_cron` v1.5.0+; upgrade your existing Supabase project to use this syntax.
-
-Head over to [crontab.guru](https://crontab.guru/) to validate your cron schedules.
-
-### Scheduling system maintenance
-
-Be extremely careful when setting up `pg_cron` jobs for system maintenance tasks as they can have unintended consequences. For instance, scheduling a command to terminate idle connections with `pg_terminate_backend(pid)` can disrupt critical background processes like nightly backups. Often, there is an existing Postgres setting e.g. `idle_session_timeout` that can perform these common maintenance tasks without the risk.
-
-Reach out to [Supabase Support](https://supabase.com/support) if you're unsure if that applies to your use case.
-
-## Examples
-
-### Delete data every week
-
-Delete old data every Saturday at 3:30am (GMT):
-
-```sql
-select cron.schedule (
- 'saturday-cleanup', -- name of the cron job
- '30 3 * * 6', -- Saturday at 3:30am (GMT)
- $$ delete from events where event_time < now() - interval '1 week' $$
-);
-```
-
-### Run a vacuum every day
-
-Vacuum every day at 3:00am (GMT):
-
-```sql
-select cron.schedule('nightly-vacuum', '0 3 * * *', 'VACUUM');
-```
-
-### Call a database function every 5 minutes
-
-Create a [`hello_world()`](https://supabase.com/docs/guides/database/functions?language=sql#simple-functions) database function and then call it every 5 minutes:
-
-```sql
-select cron.schedule('call-db-function', '*/5 * * * *', 'SELECT hello_world()');
-```
-
-### Call a database stored procedure
-
-To use a stored procedure, you can call it like this:
-
-```sql
-select cron.schedule('call-db-procedure', '*/5 * * * *', 'CALL my_procedure()');
-```
-
-### Invoke Supabase Edge Function every 30 seconds
-
-
-
-This requires `pg_cron` v1.5.0+ and the [`pg_net` extension](/docs/guides/database/extensions/pgnet) to be enabled.
-
-
-
-Make a POST request to a Supabase Edge Function every 30 seconds:
-
-```sql
-select
- cron.schedule(
- 'invoke-function-every-half-minute',
- '30 seconds',
- $$
- select
- net.http_post(
- url:='https://project-ref.supabase.co/functions/v1/function-name',
- headers:=jsonb_build_object('Content-Type','application/json', 'Authorization', 'Bearer ' || 'YOUR_ANON_KEY'),
- body:=jsonb_build_object('time', now() ),
- timeout_milliseconds:=5000
- ) as request_id;
- $$
- );
-```
-
-### Edit a job
-
-Changes the frequency of a job called `'vacuum'` to once every 5 minutes.
-
-```sql
-select cron.alter_job(
- job_id := (select jobid from cron.job where jobname = 'vacuum'),
- schedule := '*/5 * * * *'
-);
-```
-
-Full options for the `cron.alter_job()` function are:
-
-```sql
-cron.alter_job(
- job_id bigint,
- schedule text default null,
- command text default null,
- database text default null,
- username text default null,
- active boolean default null
-)
-```
-
-It is also possible to modify a job by using the `cron.schedule()` function, with the same job name. This will replace the existing job, in the manner of an upsert.
-
-### Unschedule a job
-
-Unschedules a job called `'nightly-vacuum'`
-
-```sql
-select cron.unschedule('nightly-vacuum');
-```
-
-### Viewing previously ran jobs
-
-View the last ten jobs that have ran
-
-```sql
-select
- *
-from cron.job_run_details
-order by start_time desc
-limit 10;
-```
-
-
-
-The records in cron.job_run_details are not cleaned automatically which will take up disk space in your database.
-
-
-
-## Resources
-
-- [`pg_cron` GitHub Repository](https://github.com/citusdata/pg_cron)
+See the [Supabase Cron docs](/docs/guides/cron).
diff --git a/apps/docs/content/guides/deployment/branching.mdx b/apps/docs/content/guides/deployment/branching.mdx
index aaeaf2cc54380..3402d053de0b0 100644
--- a/apps/docs/content/guides/deployment/branching.mdx
+++ b/apps/docs/content/guides/deployment/branching.mdx
@@ -582,7 +582,7 @@ With the Supabase branching integration, you can sync the Git branch used by the
- The Vercel Integration for Supabase branching is under development. To express your interest, [join the discussion on GitHub discussions](https://github.com/orgs/supabase/discussions/18938).
+ The Vercel Integration for Supabase branching is working only with Supabase managed projects. There is currently no support for Vercel Marketplace managed resources, however the support is planned in the future.
diff --git a/apps/docs/content/guides/functions/schedule-functions.mdx b/apps/docs/content/guides/functions/schedule-functions.mdx
index 1dd5fb88ed274..f0d64f319c633 100644
--- a/apps/docs/content/guides/functions/schedule-functions.mdx
+++ b/apps/docs/content/guides/functions/schedule-functions.mdx
@@ -13,7 +13,7 @@ description: 'Schedule Edge Functions with pg_cron.'
>
-The hosted Supabase Platform supports the [`pg_cron` extension](/docs/guides/database/extensions/pgcron), a simple cron-based job scheduler for PostgreSQL that runs inside the database.
+The hosted Supabase Platform supports the [`pg_cron` extension](/docs/guides/database/extensions/pgcron), a recurring job scheduler in Postgres.
In combination with the [`pg_net` extension](/docs/guides/database/extensions/pgnet), this allows us to invoke Edge Functions periodically on a set schedule.
diff --git a/apps/docs/content/guides/integrations/vercel-marketplace.mdx b/apps/docs/content/guides/integrations/vercel-marketplace.mdx
index be0ef42121c49..ec92cffa11c6c 100644
--- a/apps/docs/content/guides/integrations/vercel-marketplace.mdx
+++ b/apps/docs/content/guides/integrations/vercel-marketplace.mdx
@@ -10,7 +10,7 @@ The Vercel Marketplace is a feature that allows you to manage third-party resour
When you create an organization and projects through Vercel Marketplace, they function just like those created directly within Supabase. However, the billing is handled through your Vercel account, and you can manage your resources directly from the Vercel dashboard or CLI. Additionally, environment variables are automatically synchronized, making them immediately available for your connected projects.
-For more information, see [Introducing the Vercel Marketplace](https://vercel.com/blog/share/introducing-the-vercel-marketplace) blog post.
+For more information, see [Introducing the Vercel Marketplace](https://vercel.com/blog/introducing-the-vercel-marketplace) blog post.
diff --git a/apps/docs/features/docs/GuidesMdx.utils.tsx b/apps/docs/features/docs/GuidesMdx.utils.tsx
index d21e7fe6e9eb3..aaef7455e70e8 100644
--- a/apps/docs/features/docs/GuidesMdx.utils.tsx
+++ b/apps/docs/features/docs/GuidesMdx.utils.tsx
@@ -1,7 +1,6 @@
import matter from 'gray-matter'
import { fromMarkdown } from 'mdast-util-from-markdown'
-import { gfmFromMarkdown, gfmToMarkdown } from 'mdast-util-gfm'
-import { toMarkdown } from 'mdast-util-to-markdown'
+import { gfmFromMarkdown } from 'mdast-util-gfm'
import { gfm } from 'micromark-extension-gfm'
import { type Metadata, type ResolvingMetadata } from 'next'
import { notFound } from 'next/navigation'
@@ -26,6 +25,7 @@ const PUBLISHED_SECTIONS = [
'ai',
'api',
'auth',
+ 'cron',
'database',
'deployment',
'functions',
diff --git a/apps/docs/layouts/MainSkeleton.tsx b/apps/docs/layouts/MainSkeleton.tsx
index 9e116e883c9a7..dbee0c2a53808 100644
--- a/apps/docs/layouts/MainSkeleton.tsx
+++ b/apps/docs/layouts/MainSkeleton.tsx
@@ -30,6 +30,10 @@ const levelsData = {
icon: 'database',
name: 'Database',
},
+ cron: {
+ icon: 'cron',
+ name: 'Cron',
+ },
api: {
icon: 'rest',
name: 'REST API',
diff --git a/apps/docs/public/img/guides/database/cron/cron-create.png b/apps/docs/public/img/guides/database/cron/cron-create.png
new file mode 100644
index 0000000000000..0751b5c6186ac
Binary files /dev/null and b/apps/docs/public/img/guides/database/cron/cron-create.png differ
diff --git a/apps/docs/public/img/guides/database/cron/cron-edit.png b/apps/docs/public/img/guides/database/cron/cron-edit.png
new file mode 100644
index 0000000000000..632d4692a0e27
Binary files /dev/null and b/apps/docs/public/img/guides/database/cron/cron-edit.png differ
diff --git a/apps/docs/public/img/guides/database/cron/cron-history.png b/apps/docs/public/img/guides/database/cron/cron-history.png
new file mode 100644
index 0000000000000..d65ef1f9a78a5
Binary files /dev/null and b/apps/docs/public/img/guides/database/cron/cron-history.png differ
diff --git a/apps/docs/public/img/guides/database/cron/cron-toggle.png b/apps/docs/public/img/guides/database/cron/cron-toggle.png
new file mode 100644
index 0000000000000..54a7c4a4936bc
Binary files /dev/null and b/apps/docs/public/img/guides/database/cron/cron-toggle.png differ
diff --git a/apps/docs/public/img/guides/database/cron/cron-unschedule.png b/apps/docs/public/img/guides/database/cron/cron-unschedule.png
new file mode 100644
index 0000000000000..10c6bb7275bf6
Binary files /dev/null and b/apps/docs/public/img/guides/database/cron/cron-unschedule.png differ
diff --git a/apps/docs/spec/cli_v1_config.yaml b/apps/docs/spec/cli_v1_config.yaml
index d6c2cbb2d1a64..2fbdd858fab61 100644
--- a/apps/docs/spec/cli_v1_config.yaml
+++ b/apps/docs/spec/cli_v1_config.yaml
@@ -1142,6 +1142,39 @@ parameters:
- name: 'Auth Server configuration'
link: 'https://supabase.com/docs/reference/auth'
+ - id: 'auth.hook..enabled'
+ title: 'auth.hook..enabled'
+ tags: ['auth']
+ required: false
+ default: 'false'
+ description: |
+ Enable Auth Hook. Possible values for `hook_name` are: `custom_access_token`, `send_sms`, `send_email`, `mfa_verification_attempt`, and `password_verification_attempt`.
+ links:
+ - name: 'Auth Hooks'
+ link: 'https://supabase.com/docs/guides/auth/auth-hooks'
+
+ - id: 'auth.hook..uri'
+ title: 'auth.hook..uri'
+ tags: ['auth']
+ required: false
+ default: ''
+ description: |
+ URI of hook to invoke. Should be a http or https function or Postgres function taking the form: `pg-functions:////`. For example, `pg-functions://postgres/auth/custom-access-token-hook`.
+ links:
+ - name: 'Auth Hooks'
+ link: 'https://supabase.com/docs/guides/auth/auth-hooks'
+
+ - id: 'auth.hook..secrets'
+ title: 'auth.hook..secrets'
+ tags: ['auth']
+ required: false
+ default: ''
+ description: |
+ Configure when using a HTTP Hooks. Takes a list of base64 comma separated values to allow for secret rotation. Currently, Supabase Auth uses only the first value in the list.
+ links:
+ - name: 'Auth Hooks'
+ link: 'https://supabase.com/docs/guides/auth/auth-hooks?queryGroups=language&language=http'
+
- id: 'auth.mfa.totp.enroll_enabled'
title: 'auth.mfa.totp.enroll_enabled'
tags: ['auth']
@@ -1254,6 +1287,28 @@ parameters:
- name: 'Auth Multi-Factor Authentication'
link: 'https://supabase.com/docs/guides/auth/auth-mfa'
+ - id: 'auth.sessions.timebox'
+ title: 'auth.sessions.timebox'
+ tags: ['auth']
+ required: false
+ default: ''
+ description: |
+ Force log out after the specified duration. Sample values include: '50m', '20h'.
+ links:
+ - name: 'Auth Sessions'
+ link: 'https://supabase.com/docs/guides/auth/sessions'
+
+ - id: 'auth.sessions.inactivity_timeout'
+ title: 'auth.sessions.inactivity_timeout'
+ tags: ['auth']
+ required: false
+ default: ''
+ description: |
+ Force log out if the user has been inactive longer than the specified duration. Sample values include: '50m', '20h'.
+ links:
+ - name: 'Auth Sessions'
+ link: 'https://supabase.com/docs/guides/auth/sessions'
+
- id: 'auth.third_party.aws_cognito.enabled'
title: 'auth.third_party.aws_cognito.enabled'
tags: ['auth']
diff --git a/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx b/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx
index a81f971a346ef..eded06a85da43 100644
--- a/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx
+++ b/apps/studio/components/interfaces/App/RouteValidationWrapper.tsx
@@ -6,7 +6,6 @@ import { useIsLoggedIn, useParams } from 'common'
import { useOrganizationsQuery } from 'data/organizations/organizations-query'
import { useProjectsQuery } from 'data/projects/projects-query'
import useLatest from 'hooks/misc/useLatest'
-import { useFlag } from 'hooks/ui/useFlag'
import { DEFAULT_HOME, IS_PLATFORM, LOCAL_STORAGE_KEYS } from 'lib/constants'
import { useAppStateSnapshot } from 'state/app-state'
@@ -14,7 +13,6 @@ import { useAppStateSnapshot } from 'state/app-state'
const RouteValidationWrapper = ({ children }: PropsWithChildren<{}>) => {
const router = useRouter()
const { ref, slug, id } = useParams()
- const navLayoutV2 = useFlag('navigationLayoutV2')
const isLoggedIn = useIsLoggedIn()
const snap = useAppStateSnapshot()
@@ -56,7 +54,7 @@ const RouteValidationWrapper = ({ children }: PropsWithChildren<{}>) => {
if (!isValidOrg) {
toast.error('This organization does not exist')
- router.push(navLayoutV2 ? `/org/${organizations[0].slug}` : DEFAULT_HOME)
+ router.push(DEFAULT_HOME)
return
}
}
@@ -81,7 +79,7 @@ const RouteValidationWrapper = ({ children }: PropsWithChildren<{}>) => {
if (!isValidProject && !isValidBranch) {
toast.error('This project does not exist')
- router.push(navLayoutV2 ? `/org/${organizations?.[0].slug}` : DEFAULT_HOME)
+ router.push(DEFAULT_HOME)
return
}
}
diff --git a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyChat.tsx b/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyChat.tsx
deleted file mode 100644
index 29545a60c9242..0000000000000
--- a/apps/studio/components/interfaces/Auth/Policies/AIPolicyEditorPanel/AIPolicyChat.tsx
+++ /dev/null
@@ -1,214 +0,0 @@
-import { compact, last } from 'lodash'
-import { ChevronsUpDown, Lightbulb } from 'lucide-react'
-import Link from 'next/link'
-import { useEffect, useRef, useState } from 'react'
-
-import { ButtonTooltip } from 'components/ui/ButtonTooltip'
-import { SchemaComboBox } from 'components/ui/SchemaComboBox'
-import { useSendEventMutation } from 'data/telemetry/send-event-mutation'
-import { useOrgOptedIntoAi } from 'hooks/misc/useOrgOptedIntoAi'
-import { useSchemasForAi } from 'hooks/misc/useSchemasForAi'
-import { useSelectedOrganization } from 'hooks/misc/useSelectedOrganization'
-import { useSelectedProject } from 'hooks/misc/useSelectedProject'
-import { IS_PLATFORM } from 'lib/constants'
-import { useProfile } from 'lib/profile'
-import {
- AiIconAnimation,
- Button,
- Tooltip_Shadcn_,
- TooltipContent_Shadcn_,
- TooltipTrigger_Shadcn_,
-} from 'ui'
-import { AssistantChatForm } from 'ui-patterns/AssistantChat'
-import { MessageWithDebug } from './AIPolicyEditorPanel.utils'
-import Message from './Message'
-
-interface AIPolicyChatProps {
- selectedTable: string
- messages: MessageWithDebug[]
- selectedMessage?: string
- loading: boolean
- onSubmit: (s: string) => void
- onDiff: (message: { id: string; content: string }) => void
- clearHistory?: () => void
-}
-
-export const AIPolicyChat = ({
- selectedTable,
- messages,
- selectedMessage,
- loading,
- onSubmit,
- onDiff,
- clearHistory,
-}: AIPolicyChatProps) => {
- const { profile } = useProfile()
- const project = useSelectedProject()
- const selectedOrganization = useSelectedOrganization()
-
- const bottomRef = useRef(null)
- const [selectedSchemas, setSelectedSchemas] = useSchemasForAi(project?.ref!)
- const [value, setValue] = useState('')
- const [hasSuggested, setHasSuggested] = useState(false)
- const inputRef = useRef(null)
-
- const isOptedInToAI = useOrgOptedIntoAi()
- const includeSchemaMetadata = isOptedInToAI || !IS_PLATFORM
-
- const name = compact([profile?.first_name, profile?.last_name]).join(' ')
- const pendingReply = loading && last(messages)?.role === 'user'
-
- const { mutate: sendEvent } = useSendEventMutation()
-
- useEffect(() => {
- if (!loading) {
- setValue('')
- if (inputRef.current) inputRef.current.focus()
- }
-
- // Try to scroll on each rerender to the bottom
- setTimeout(
- () => {
- if (bottomRef.current) {
- bottomRef.current.scrollIntoView({ behavior: 'smooth' })
- }
- },
- loading ? 100 : 500
- )
- }, [loading])
-
- return (
-
-
-
- {messages.length > 0 && (
-
- )}
-
-
- {includeSchemaMetadata ? (
-
-
- Include these schemas in your prompts:
-
- 0
- ? `${selectedSchemas.length} schema${
- selectedSchemas.length > 1 ? 's' : ''
- } selected`
- : 'No schemas selected'
- }
- />
-
- ) : (
- }
- tooltip={{
- content: {
- side: 'bottom',
- className: 'w-72',
- text: (
- <>
- Opt in to sending anonymous data to OpenAI in your{' '}
-
- organization settings
- {' '}
- to share schemas with the Assistant for more accurate responses.
- >
- ),
- },
- }}
- >
- No schemas selected
-
- )}
-
- {messages.map((m) => (
- onDiff({ id: m.id, content })}
- />
- ))}
- {pendingReply && }
-
-
- {!hasSuggested && (
-
-
-
- }
- onClick={() => {
- onSubmit(
- `Suggest policies for ${selectedTable} table. Don't duplicate any of my existing policies.`
- )
- setHasSuggested(true)
- }}
- >
- Suggest
-
-
-
- Suggest policies for this table
-
-
-
- 0
- ? `${selectedSchemas.length} schema${
- selectedSchemas.length > 1 ? 's' : ''
- } selected`
- : 'No schemas selected'
- }
- />
-
-
-
-
-
- Select specific schemas to send with your queries. Supabase AI can use this
- data to improve the responses it shows you.
-
-
-
-
-
- ) : (
- <>
- {shouldShowNotOptimizedAlert ? (
-
-
- AI Assistant is not optimized
-
- You need to agree to share anonymous schema data with OpenAI for the best
- experience.
-
-
-
-
-
-
-
- ) : (
- <>>
- )}
- >
- )}
-
- {messages.map((m, index) => {
- const isFirstUserMessage =
- m.role === 'user' && messages.slice(0, index).every((msg) => msg.role !== 'user')
-
- return (
- onDiff({ id: m.id, diffType, sql })}
- >
- {isFirstUserMessage && !includeSchemaMetadata && !shouldShowNotOptimizedAlert && (
-
-
-
- Quick reminder that you're not sending project metadata with your queries. By
- opting into sending anonymous data, Supabase AI can improve the answers it
- shows you.
-
-
-
-
- )}
- {isFirstUserMessage && includeSchemaMetadata && selectedSchemas.length === 0 && (
-
-
-
- We recommend including the schemas for better answers by Supabase AI.
-
-
-
- )}
-
- )
- })}
- {pendingReply && }
-
-
- By opting into sending anonymous data, Supabase AI can improve the answers it shows you.
- This is an organization-wide setting, and affects all projects in your organization.
-
+
+
+
+Supabase Cron is built on the powerful [`pg_cron`](https://github.com/citusdata/pg_cron) extension by the team at [Citus Data](https://github.com/citusdata).
+
+It's a Supabase policy to [support existing tools](https://supabase.com/docs/guides/getting-started/architecture#support-existing-tools) wherever possible, and the Citus Data team have generously licensed their extension with the OSI-compatible [PostgreSQL license](https://github.com/citusdata/pg_cron?tab=PostgreSQL-1-ov-file).
+
+We're very thankful to all the contributors and we look forward to continue working with the community.
+
+
+
+### What's a Cron?
+
+[**Cron**](https://en.wikipedia.org/wiki/Cron) is a tool for scheduling recurring tasks that run at specified intervals. These periodic tasks are called “Cron Jobs”. Common use-cases include:
+
+- **Maintenance:** delete or archive old data.
+- **Reporting and analytics:** save daily or weekly reports for analysis.
+- **Automation:** send periodic emails, like newsletters or reminders.
+- **Monitoring**: perform health checks on your database and log the results.
+- **Performance:** automate vacuuming tables and rebuilding indexes.
+
+Supabase Cron stores the scheduling logic within Postgres and runs your Jobs accordingly while integrating with the rest of the Supabase primitives - Dashboard, Edge Functions, and AI Assistant.
+
+## How Do You Use Supabase Cron?
+
+You can create Jobs either via the Dashboard or SQL.
+
+
+
+For this post we'll focus on the Dashboard. You can refer to the [documentation](https://supabase.com/docs/guides/cron/quickstart) for SQL.
+
+
+
+Within the Dashboard you can define schedules using standard cron syntax and the special `pg_cron` seconds syntax for sub-minute schedules or use natural language.
+
+
+
+## Job Types
+
+You can choose between four types of Jobs based on what you need to execute:
+
+
+
+### SQL Snippets
+
+Create an inline SQL query or command to run on your database periodically. Use this for tasks like:
+
+- Generating reports.
+- Cleaning up stale data.
+- Refreshing [Materialized Views](https://supabase.com/docs/guides/database/tables?queryGroups=database-method&database-method=sql#materialized-views).
+
+### Database Functions
+
+Call a Postgres function. This is useful for workflows, such as:
+
+- Batch processing operations.
+- Running periodic maintenance tasks.
+- Performing multi-step updates using transactions.
+
+### HTTP Requests (webhooks)
+
+Trigger an external HTTP endpoint. Use this for:
+
+- Starting external workflows.
+- Syncing data with third-party APIs.
+- Sending notifications to external systems.
+
+### Supabase Edge Functions
+
+Run a serverless function to execute custom logic. Examples include:
+
+- Creating embeddings.
+- Sending automated email updates.
+- Fetching external data and storing it in your database.
+
+These options cover a wide range of use cases, helping with everything from database management to external integrations.
+
+### Observe and Debug Jobs
+
+Wondering why a Job failed? You can view the history of all Jobs and their logs in the Dashboard. You can see when a Job started, how long it took, and what the result was.
+
+
+
+
+For a deeper dive, you can view Jobs in the [Logs Explorer](https://supabase.com/dashboard/project/_zvmkyvanngopzqaabmvx_/logs/pgcron-logs).
+
+
+### Try Supabase Cron today
+
+Getting started is easy:
+
+1. Visit the [Integrations page](https://supabase.com/dashboard/project/_/integrations) in your project.
+2. Enable the **Cron** Postgres Module.
+3. Create your first scheduled Job.
+
+
+
+
+
+We're looking forward to seeing how you use Supabase Cron to help automate your workflows!
diff --git a/apps/www/components/BrowserFrame.tsx b/apps/www/components/BrowserFrame.tsx
index 39cca627f22e3..5b944026a4de6 100644
--- a/apps/www/components/BrowserFrame.tsx
+++ b/apps/www/components/BrowserFrame.tsx
@@ -4,21 +4,29 @@ import { cn } from 'ui'
interface Props extends PropsWithChildren {
className?: string
contentClassName?: string
+ hasFrameButtons?: boolean
}
-const BrowserFrame: React.FC = ({ children, className, contentClassName }) => {
+const BrowserFrame: React.FC = ({
+ children,
+ className,
+ contentClassName,
+ hasFrameButtons = true,
+}) => {
return (