diff --git a/.github/workflows/docs-lint-v2.yml b/.github/workflows/docs-lint-v2.yml
index 0aabb9ce7fa..f967f56e943 100644
--- a/.github/workflows/docs-lint-v2.yml
+++ b/.github/workflows/docs-lint-v2.yml
@@ -16,8 +16,10 @@ jobs:
steps:
- uses: actions/checkout@v3
with:
+ fetch-depth: 0
sparse-checkout: |
supa-mdx-lint.config.toml
+ supa-mdx-lint
apps/docs/content
- name: cache cargo
id: cache-cargo
@@ -28,17 +30,21 @@ jobs:
~/.cargo/registry/index/
~/.cargo/registry/cache/
~/.cargo/git/db/
- key: 2d535367b06fe62354035464cf8334929bafca85
+ key: 6435a4cd1eeea7c2bbd343731de7e8a5127cb2d1
- name: install linter
if: steps.cache-cargo.outputs.cache-hit != 'true'
- run: cargo install --locked --git https://github.com/supabase-community/supa-mdx-lint --rev 2d535367b06fe62354035464cf8334929bafca85
+ run: cargo install --locked --git https://github.com/supabase-community/supa-mdx-lint --rev 6435a4cd1eeea7c2bbd343731de7e8a5127cb2d1
- name: install reviewdog
uses: reviewdog/action-setup@3f401fe1d58fe77e10d665ab713057375e39b887 # v1.3.0
with:
reviewdog_version: v0.20.2
- name: run linter
env:
+ BASE_REF: ${{ github.base_ref }}
REVIEWDOG_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -o pipefail
- supa-mdx-lint apps/docs/content/guides/getting-started apps/docs/content/guides/ai apps/docs/content/guides/auth --format rdf | tee >(cat) | reviewdog -f=rdjsonl -reporter=github-pr-review
+ git diff --name-only origin/$BASE_REF HEAD \
+ | grep -E "^apps/docs/content/guides/(getting-started|ai|api|auth|database|deployment|functions)/" \
+ | xargs -r supa-mdx-lint --format rdf \
+ | reviewdog -f=rdjsonl -reporter=github-pr-review
diff --git a/apps/docs/content/guides/auth/auth-captcha.mdx b/apps/docs/content/guides/auth/auth-captcha.mdx
index 127640ae192..a55b4e46ab2 100644
--- a/apps/docs/content/guides/auth/auth-captcha.mdx
+++ b/apps/docs/content/guides/auth/auth-captcha.mdx
@@ -1,13 +1,13 @@
---
id: 'auth-captcha'
-title: 'Enable Captcha Protection'
-description: 'Add Captcha Protection to your Supabase project'
+title: 'Enable CAPTCHA Protection'
+description: 'Add CAPTCHA Protection to your Supabase project'
tocVideo: 'em1cpOAXknM'
---
-Supabase provides you with the option of adding captcha to your sign-in, sign-up, and password reset forms. This keeps your website safe from bots and malicious scripts. Supabase authentication has support for [hCaptcha](https://www.hcaptcha.com/) and [Cloudflare Turnstile](https://www.cloudflare.com/products/turnstile/).
+Supabase provides you with the option of adding CAPTCHA to your sign-in, sign-up, and password reset forms. This keeps your website safe from bots and malicious scripts. Supabase authentication has support for [hCaptcha](https://www.hcaptcha.com/) and [Cloudflare Turnstile](https://www.cloudflare.com/products/turnstile/).
-## Sign up for Captcha
+## Sign up for CAPTCHA
-## Enable Captcha protection for your Supabase project
+## Enable CAPTCHA protection for your Supabase project
Navigate to the **[Auth](https://supabase.com/dashboard/project/_/settings/auth)** section of your Project Settings in the Supabase Dashboard and find the **Enable Captcha protection** toggle under Settings > Authentication > Bot and Abuse Protection > Enable Captcha protection.
Select your CAPTCHA provider from the dropdown, enter your Captcha **Secret key**, and click **Save**.
-## Add the Captcha frontend component
+## Add the CAPTCHA frontend component
The frontend requires some changes to provide the captcha on-screen for the user. This example uses React and the corresponding Captcha React component, but both Captcha providers can be used with any JavaScript framework.
diff --git a/apps/docs/content/guides/database/extensions.mdx b/apps/docs/content/guides/database/extensions.mdx
index d5fb2834e26..3bdbb3db71f 100644
--- a/apps/docs/content/guides/database/extensions.mdx
+++ b/apps/docs/content/guides/database/extensions.mdx
@@ -54,7 +54,7 @@ In addition to the pre-configured extensions, you can also install your own SQL
-### Upgrade Extensions
+### Upgrade extensions
If a new version of an extension becomes available on Supabase, you need to initiate a software upgrade in the [Infrastructure Settings](https://supabase.com/dashboard/project/_/settings/infrastructure) to access it. Software upgrades can also be initiated by restarting your server in the [General Settings](https://supabase.com/dashboard/project/_/settings/general).
diff --git a/apps/docs/content/guides/database/extensions/rum.mdx b/apps/docs/content/guides/database/extensions/rum.mdx
index e6fbe850a61..c95943e0202 100644
--- a/apps/docs/content/guides/database/extensions/rum.mdx
+++ b/apps/docs/content/guides/database/extensions/rum.mdx
@@ -58,7 +58,7 @@ drop extension if exists rum;
### Syntax
-#### For type: tsvector
+#### For type: `tsvector`
To understand the following you may need first to see [Official PostgreSQL documentation on text
search](https://www.postgresql.org/docs/current/functions-textsearch.html)
@@ -116,7 +116,7 @@ SELECT id, d, d `<=>` '2016-05-16 14:21:25' FROM tsts WHERE t @@ 'wr&qh' ORDER B
(5 rows)
```
-#### For type: anyarray
+#### For type: `anyarray`
`rum_anyarray_ops`
diff --git a/apps/docs/content/guides/database/postgres/column-level-security.mdx b/apps/docs/content/guides/database/postgres/column-level-security.mdx
index 6ed691e326c..a6731d1a281 100644
--- a/apps/docs/content/guides/database/postgres/column-level-security.mdx
+++ b/apps/docs/content/guides/database/postgres/column-level-security.mdx
@@ -12,7 +12,7 @@ PostgreSQL's [Row Level Security (RLS)](https://www.postgresql.org/docs/current/
roles.
-## Policies at the Row Level
+## Policies at the row level
Policies in Row Level Security (RLS) are used to restrict access to rows in a table. Think of them like adding a `WHERE` clause to every query.
@@ -35,7 +35,7 @@ update
However, this gives the post owner full access to update the row, including all of the columns.
-## Privileges at the Column Level
+## Privileges at the column level
To restrict access to columns, you can use [Privileges](https://www.postgresql.org/docs/current/ddl-priv.html).
@@ -80,7 +80,7 @@ You can view and edit the privileges in the [Supabase Studio](https://supabase.c

-## Manage column privileges in Migrations
+## Manage column privileges in migrations
While you can manage privileges directly from the Dashboard, as your project grows you may want to manage them in your migrations. Read about database migrations in the [Local Development](https://supabase.com/docs/guides/getting-started/local-development#database-migrations) guide.
diff --git a/apps/docs/content/guides/database/postgres/roles.mdx b/apps/docs/content/guides/database/postgres/roles.mdx
index b72ab8c1ad2..7a36f2761d7 100644
--- a/apps/docs/content/guides/database/postgres/roles.mdx
+++ b/apps/docs/content/guides/database/postgres/roles.mdx
@@ -46,7 +46,7 @@ When you created your project you were also asked to enter a password. This is a
Changing the password does not result in any downtime. All connected services, such as postgrest, pgbouncer, and other Supabase managed services, are automatically updated to use the latest password to ensure availability. However, if you have any external services connecting to the Supabase database using hardcoded username/password credentials, a manual update will be required.
-## Granting Permissions
+## Granting permissions
Roles can be granted various permissions on database objects using the `GRANT` command. Permissions include `SELECT`, `INSERT`, `UPDATE`, and `DELETE`. You can configure access to almost any object inside your database - including tables, views, functions, and triggers.
diff --git a/apps/docs/content/guides/database/postgres/timeouts.mdx b/apps/docs/content/guides/database/postgres/timeouts.mdx
index 8a735c9d7c1..c89c3def47a 100644
--- a/apps/docs/content/guides/database/postgres/timeouts.mdx
+++ b/apps/docs/content/guides/database/postgres/timeouts.mdx
@@ -124,9 +124,9 @@ language sql;
The Supabase Dashboard contains tools to help you identify timed-out and long-running queries.
-### Using the Log Explorer
+### Using the Logs Explorer
-Go to the [Log Explorer](/dashboard/project/_/logs/explorer), and run the following query to identify timed-out events (`statement timeout`) and queries that successfully run for longer than 10 seconds (`duration`).
+Go to the [Logs Explorer](/dashboard/project/_/logs/explorer), and run the following query to identify timed-out events (`statement timeout`) and queries that successfully run for longer than 10 seconds (`duration`).
```sql
select
diff --git a/apps/docs/content/guides/database/prisma/prisma-troubleshooting.mdx b/apps/docs/content/guides/database/prisma/prisma-troubleshooting.mdx
index 851ea07ef6c..974528af322 100644
--- a/apps/docs/content/guides/database/prisma/prisma-troubleshooting.mdx
+++ b/apps/docs/content/guides/database/prisma/prisma-troubleshooting.mdx
@@ -27,6 +27,8 @@ connection_string.../postgres?KEY1=VALUE&KEY2=VALUE&KEY3=VALUE
# Errors
+{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
+
## ... prepared statement already exists
Supavisor in transaction mode (port 6543) does not support [prepared statements](https://www.postgresql.org/docs/current/sql-prepare.html), which Prisma will try to create in the background.
@@ -162,7 +164,7 @@ An alternative strategy to reference these tables is to duplicate values into Pr
Show/Hide Details
-
+
```sql table_in_public
-- Create the 'profiles' table in the 'public' schema
create table public.profiles (
diff --git a/apps/docs/content/guides/database/query-optimization.mdx b/apps/docs/content/guides/database/query-optimization.mdx
index d1e2d88690d..f34e8ebf2bd 100644
--- a/apps/docs/content/guides/database/query-optimization.mdx
+++ b/apps/docs/content/guides/database/query-optimization.mdx
@@ -34,7 +34,7 @@ limit 10;
In this query, there are several parts that indexes could likely help in optimizing the performance:
-### `where` Clause:
+### `where` clause:
The `where` clause filters rows based on certain conditions, and indexing the columns involved can improve this process:
@@ -47,7 +47,7 @@ create index idx_customers_sign_up_date on customers (sign_up_date);
create index idx_orders_status on orders (status);
```
-### `join` Columns
+### `join` columns
Indexes on the columns used for joining tables can help Postgres avoid scanning tables in their entirety when connecting tables.
@@ -58,7 +58,7 @@ Indexes on the columns used for joining tables can help Postgres avoid scanning
create index idx_orders_customer_id on orders (customer_id);
```
-### `order by` Clause
+### `order by` clause
Sorting can also be optimized by indexing:
diff --git a/apps/docs/content/guides/functions/examples/auth-send-email-hook-react-email-resend.mdx b/apps/docs/content/guides/functions/examples/auth-send-email-hook-react-email-resend.mdx
index 908d9808ee7..f7c7ef537bf 100644
--- a/apps/docs/content/guides/functions/examples/auth-send-email-hook-react-email-resend.mdx
+++ b/apps/docs/content/guides/functions/examples/auth-send-email-hook-react-email-resend.mdx
@@ -114,7 +114,7 @@ Deno.serve(async (req) => {
})
```
-### 3. Create React Email Templates
+### 3. Create React Email templates
Create a new folder `_templates` and create a new file `magic-link.tsx` with the following code:
@@ -296,7 +296,7 @@ supabase secrets set --env-file supabase/functions/.env
That's it, now your Supabase Edge Function will be triggered anytime an Auth Email needs to be send to the user!
-## More Resources
+## More resources
- [Send Email Hooks](/docs/guides/auth/auth-hooks/send-email-hook)
- [Auth Hooks](/docs/guides/auth/auth-hooks)
diff --git a/apps/docs/content/guides/functions/examples/discord-bot.mdx b/apps/docs/content/guides/functions/examples/discord-bot.mdx
index bfe4a4e5114..48b0481bbc3 100644
--- a/apps/docs/content/guides/functions/examples/discord-bot.mdx
+++ b/apps/docs/content/guides/functions/examples/discord-bot.mdx
@@ -138,7 +138,7 @@ function hexToUint8Array(hex: string) {
}
```
-## Deploy the Slash Command handler
+## Deploy the slash command handler
```bash
supabase functions deploy discord-bot --no-verify-jwt
@@ -154,7 +154,7 @@ Navigate to your Function details in the Supabase Dashboard to get your Endpoint
The application is now ready. Let's proceed to the next section to install it.
-## Install the Slash Command on your Discord server
+## Install the slash command on your Discord server
So to use the `hello` Slash Command, we need to install our Greeter application on our Discord server. Here are the steps:
diff --git a/apps/docs/content/guides/functions/examples/push-notifications.mdx b/apps/docs/content/guides/functions/examples/push-notifications.mdx
index b59ad8879a9..994c7e4267d 100644
--- a/apps/docs/content/guides/functions/examples/push-notifications.mdx
+++ b/apps/docs/content/guides/functions/examples/push-notifications.mdx
@@ -18,14 +18,14 @@ Push notifications are an important part of any mobile app. They allow you to se
Find the example code on [GitHub](https://github.com/supabase/supabase/blob/master/examples/user-management/expo-push-notifications/).
- ## Supabase Setup
+ ## Supabase setup
- [Create a new Supabase project](https://database.new).
- Link your project: `supabase link --project-ref your-supabase-project-ref`
- Start supabase locally: `supabase start`
- Push up the schema: `supabase db push` (schema is defined in [supabase/migrations](https://github.com/supabase/supabase/blob/master/examples/user-management/expo-push-notifications/supabase/migrations/))
- ## Expo Setup
+ ## Expo setup
To utilize Expo's push notification service, you must configure your app by installing a set of libraries, implementing functions to handle notifications, and setting up credentials for Android and iOS. Follow the official [Expo Push Notifications Setup Guide](https://docs.expo.dev/push-notifications/push-notifications-setup/) to get the credentials for Android and iOS. This project uses [Expo's EAS build](https://docs.expo.dev/build/introduction/) service to simplify this part.
@@ -126,7 +126,7 @@ Push notifications are an important part of any mobile app. They allow you to se
This guide will show you how to send push notifications to your app when a new row is inserted into a table using FCM, Supabase Edge Functions, and database web hooks.
- ## Supabase Setup
+ ## Supabase setup
We will create two tables. One to store the user's FCM token and a `notifications` table. The edge function will be triggered when a new row is inserted into the `notifications` table and sends a push notification to the user.
@@ -258,7 +258,7 @@ Push notifications are an important part of any mobile app. They allow you to se
}
```
- ## FCM Setup
+ ## FCM setup
1. Follow the official [FCM Setup Guide](https://firebase.google.com/docs/cloud-messaging) to set up FCM for your client side application.
1. Generate a new service account private key from the Firebase console `Project Settings > Service Accounts > Generate new private key`.
diff --git a/apps/docs/content/guides/functions/examples/semantic-search.mdx b/apps/docs/content/guides/functions/examples/semantic-search.mdx
index b42077dd395..7534d6bafae 100644
--- a/apps/docs/content/guides/functions/examples/semantic-search.mdx
+++ b/apps/docs/content/guides/functions/examples/semantic-search.mdx
@@ -61,7 +61,7 @@ Deno.serve(async (req) => {
})
```
-## Create a Postgres Function and RPC
+## Create a Database Function and RPC
With the embeddings now stored in your Postgres database table, you can query them from Supabase Edge Functions by utilizing [Remote Procedure Calls (RPC)](/docs/guides/database/functions?language=js).
diff --git a/apps/docs/content/guides/functions/examples/sentry-monitoring.mdx b/apps/docs/content/guides/functions/examples/sentry-monitoring.mdx
index ec522e0a892..29bf2516193 100644
--- a/apps/docs/content/guides/functions/examples/sentry-monitoring.mdx
+++ b/apps/docs/content/guides/functions/examples/sentry-monitoring.mdx
@@ -79,7 +79,7 @@ supabase functions deploy sentryfied --no-verify-jwt
Find the complete example on [GitHub](https://github.com/supabase/supabase/tree/master/examples/edge-functions/supabase/functions/sentryfied/index.ts).
-## Working With Scopes
+## Working with scopes
Sentry Deno SDK currently do not support `Deno.serve` instrumentation, which means that there is no scope separation between requests.
Because of that, when the Edge Functions runtime is reused between multiple requests, all globally captured breadcrumbs and contextual data
diff --git a/apps/docs/content/guides/functions/import-maps.mdx b/apps/docs/content/guides/functions/import-maps.mdx
index 15e7bfdc9ab..176aa73d4f2 100644
--- a/apps/docs/content/guides/functions/import-maps.mdx
+++ b/apps/docs/content/guides/functions/import-maps.mdx
@@ -12,7 +12,7 @@ Developing with Edge Functions is similar to developing with Node.js, but with a
There are two ways to manage your dependencies in Supabase Edge Functions:
-### Using deno.json (Recommended)
+### Using deno.json (recommended)
@@ -50,7 +50,7 @@ The recommended file structure when using `deno.json`:
└── config.toml
```
-### Using Import Maps (Legacy)
+### Using import maps (legacy)
Import Maps are a legacy way to manage dependencies, similar to a `package.json` file. While still supported, we recommend using `deno.json`. If both exist, `deno.json` takes precedence.
@@ -112,7 +112,7 @@ Supabase Edge Functions support several ways to import dependencies:
- Built-in [Node APIs](https://docs.deno.com/runtime/manual/node/compatibility)
- Third party modules published to [JSR](https://jsr.io/) or [deno.land/x](https://deno.land/x)
-### NPM Modules
+### NPM modules
You can import npm modules using the `npm:` specifier:
@@ -120,7 +120,7 @@ You can import npm modules using the `npm:` specifier:
import { createClient } from 'npm:@supabase/supabase-js@2'
```
-### Node.js Built-ins
+### Node.js built-ins
For Node.js built-in APIs, use the `node:` specifier:
@@ -130,7 +130,7 @@ import process from 'node:process'
Learn more about npm specifiers and Node built-in APIs in [Deno's documentation](https://docs.deno.com/runtime/manual/node/npm_specifiers).
-### Importing from Private Registries
+### Importing from private registries
diff --git a/apps/docs/content/guides/functions/logging.mdx b/apps/docs/content/guides/functions/logging.mdx
index 4f0e66879cf..62a5cc3cd70 100644
--- a/apps/docs/content/guides/functions/logging.mdx
+++ b/apps/docs/content/guides/functions/logging.mdx
@@ -61,9 +61,9 @@ Deno.serve(async (req) => {
})
```
-## Logging Tips
+## Logging tips
-### Logging Request Headers
+### Logging request headers
When debugging Edge Functions, a common mistake is to try to log headers to the developer console via code like this:
@@ -88,7 +88,7 @@ The reason behind this behavior is that [Headers](https://developer.mozilla.org/
However, `Headers` objects are iterable. You can utilize this feature to craft a couple of succinct one-liners for debugging and printing headers.
-### Convert headers into an object with Object.fromEntries:
+### Convert headers into an object with `Object.fromEntries`:
You can use `Object.fromEntries` which is a call to convert the headers into an object:
diff --git a/apps/docs/content/guides/functions/routing.mdx b/apps/docs/content/guides/functions/routing.mdx
index f13eb21eeed..2944dacf500 100644
--- a/apps/docs/content/guides/functions/routing.mdx
+++ b/apps/docs/content/guides/functions/routing.mdx
@@ -15,7 +15,7 @@ To combine multiple endpoints into a single Edge Function, you can use web appli
Let's dive into some examples.
-## Routing with Frameworks
+## Routing with frameworks
Here's a simple hello world example using some popular web frameworks.
@@ -158,7 +158,7 @@ curl --request POST 'https://.supabase.co/functions/v1/hello-world'
We should see a response printing `Hello Foo!`.
-## Using Route Parameters
+## Using route parameters
We can use route parameters to capture values at specific URL segments (eg: `/tasks/:taskId/notes/:noteId`).
@@ -415,7 +415,7 @@ Deno.serve(async (req) => {
-## URL Patterns API
+## URL patterns API
If you prefer not to use a web framework, you can directly use [URLPattern API](https://developer.mozilla.org/en-US/docs/Web/API/URL_Pattern_API) within your Edge Functions to implement routing.
This is ideal for small apps with only couple of routes and you want to have a custom matching algorithm.
diff --git a/apps/docs/content/guides/functions/status-codes.mdx b/apps/docs/content/guides/functions/status-codes.mdx
index 29f7a4307f6..5925a2ad3bb 100644
--- a/apps/docs/content/guides/functions/status-codes.mdx
+++ b/apps/docs/content/guides/functions/status-codes.mdx
@@ -5,6 +5,8 @@ description: 'Edge Functions can return following status codes.'
subtitle: 'Edge Functions can return following status codes.'
---
+{/* supa-mdx-lint-disable Rule001HeadingCase */}
+
## 2XX Success
A successful Edge Function Response
diff --git a/apps/docs/content/guides/functions/troubleshooting.mdx b/apps/docs/content/guides/functions/troubleshooting.mdx
index cdeddcbe9c6..2d69c1e0867 100644
--- a/apps/docs/content/guides/functions/troubleshooting.mdx
+++ b/apps/docs/content/guides/functions/troubleshooting.mdx
@@ -30,6 +30,8 @@ If your Edge Function takes too long to respond or times out:
- If the boot times are similar, it’s likely an issue with your function’s code, such as a large dependency, a slow API call, or a complex computation. You can try to optimize your code, reduce the size of your dependencies, or use caching techniques to improve the performance of your function.
- If only some of the `booted` events are slow, find the affected `region` in the metadata and submit a support request via the "Help" button at the top.
+{/* supa-mdx-lint-disable-next-line Rule001HeadingCase */}
+
### Receiving 546 Error Response
The 546 error response might occur because:
@@ -47,7 +49,7 @@ The 546 error response might occur because:
## Advanced techniques
-### Monitoring Edge Function Resource Usage
+### Monitoring Edge Function resource usage
To determine how much memory and CPU your Edge Function consumes, follow these steps:
@@ -62,7 +64,7 @@ To determine how much memory and CPU your Edge Function consumes, follow these s
resources.
-### Understanding CPU soft and hard Limits
+### Understanding CPU soft and hard limits
An isolate is like a worker that can handle multiple requests for a function. It works until a time limit of 400 seconds is reached. Now, there are two types of limits for the CPU.
@@ -89,7 +91,7 @@ When analyzing dependencies for your Supabase Edge Functions, it's essential to
By selectively importing only the required submodules, you can effectively reduce the size of your function's dependencies and optimize its performance.
Before finalizing your imports, ensure to review both Deno and NPM dependencies, checking for any unnecessary or redundant dependencies that can be removed. Additionally, check for outdated dependencies and update to the latest versions if possible.
-#### Deno Dependencies
+#### Deno dependencies
Run `deno info`, providing the path to your input map if you use one.
Review the dependencies listed in the output. Pay attention to any significantly large dependencies, as they can contribute to increased bundle size and potential boot time issues.
@@ -99,7 +101,7 @@ Examine if there are any unnecessary or redundant dependencies that can be remov
deno info --import-map=/path/to/import_map.json /path/to/function/index.ts
```
-#### NPM Dependencies
+#### NPM dependencies
Additionally, if you utilize NPM modules in your Edge Functions, it's crucial to be mindful of their size and impact on the overall bundle size. While importing NPM modules, consider using the notation `import { submodule } from 'npm:package/submodule'` to selectively import specific submodules rather than importing the entire package. This approach can help minimize unnecessary overhead and streamline the execution of your function.
diff --git a/apps/docs/content/guides/functions/websockets.mdx b/apps/docs/content/guides/functions/websockets.mdx
index 48fd6fff028..0c0c82201e8 100644
--- a/apps/docs/content/guides/functions/websockets.mdx
+++ b/apps/docs/content/guides/functions/websockets.mdx
@@ -88,7 +88,7 @@ server.listen(8080);
-### Outbound Websockets
+### Outbound WebSockets
You can also establish an outbound WebSocket connection to another server from an Edge Function.
diff --git a/supa-mdx-lint.config.toml b/supa-mdx-lint.config.toml
index b85581f17a6..fc3403b3048 100644
--- a/supa-mdx-lint.config.toml
+++ b/supa-mdx-lint.config.toml
@@ -1,115 +1,14 @@
ignore_patterns = ["**/_*.mdx"]
# Heading should be sentence case
-[Rule001HeadingCase]
-# Words that may be uppercased even if they are not the first word in the sentence.
-# Can also specify a regex that is compatible with the [Rust regex crate](https://docs.rs/regex/latest/regex/).
-may_uppercase = [
- "[A-Z0-9]{2,5}",
- "APIs",
- "Android",
- "Angular",
- "Apple",
- "Auth",
- "Auth0",
- "Auth0 Actions?",
- "Azure",
- "Azure Developers?",
- "Bitbucket",
- "Boolean",
- "Captcha",
- "ChatGPT",
- "Chrome",
- "Code Exchange",
- "Content Delivery Network",
- "Dart",
- "Discord",
- "Edge Functions?",
- "Expo",
- "Facebook",
- "Facebook Developers?",
- "Figma",
- "Figma Developers?",
- "Firebase",
- "Firebase Authentication",
- "Flutter",
- "GitHub",
- "GitHub Actions",
- "GitLab",
- "GoTrue",
- "Google",
- "GraphQL",
- "Hooks?",
- "Hugging Face",
- "I",
- "IVFFlat",
- "Inbucket",
- "Ionic Angular",
- "Ionic React",
- "Ionic Vue",
- "JavaScript",
- "JWTs",
- "Kakao",
- "Kakao Developers?",
- "Kakao Login",
- "Keycloak",
- "Kotlin",
- "Kotlin Multiplatform",
- "LinkedIn",
- "LinkedIn Developers?",
- "Linux",
- "Magic Link",
- "Navigable Small World",
- "Next.js",
- "Notion",
- "Nuxt",
- "OAuth",
- "OpenAI",
- "Open ID Connect",
- "Poetry",
- "Postgres",
- "PostgreSQL",
- "PostgREST",
- "Python",
- "React",
- "React Native",
- "Reciprocal Ranked Fusion",
- "RedwoodJS",
- "Remix",
- "Retrieval Plugin",
- "Roboflow Inference",
- "Row Level Security",
- "Server-Side Auth",
- "Server-Side Rendering",
- "Single Sign-On",
- "Slack",
- "Slack Developers?",
- "SolidJS",
- "Spotify",
- "Spotify Developers?",
- "Supabase",
- "Svelte",
- "SvelteKit",
- "Swift",
- "SwiftUI",
- "Third-Party Auth",
- "Twitch",
- "Twitch Developers?",
- "Twitter",
- "Twitter Developers?",
- "TypeScript",
- "URIs",
- "URLs",
- "Xcode",
- "Vecs",
- "Vue",
- "Web",
- "Windows",
- "WorkOS",
- "Wrappers",
- "Zoom",
- "Zoom Developers?",
-]
-# Words that may be lowercased even if they are the first word in the sentence.
-# Can also specify a regex that is compatible with the [Rust regex crate](https://docs.rs/regex/latest/regex/).
-may_lowercase = ["iOS"]
+Rule001HeadingCase = "include('supa-mdx-lint/Rule001HeadingCase.toml')"
+
+Rule003Spelling = false
+# Check spelling
+# Error message: "Word not found in dictionary"
+# Rule003Spelling = "include('supa-mdx-lint/Rule003Spelling.toml')"
+
+Rule002AdmonitionTypes = false
+# [Rule002AdmonitionTypes]
+# Allowed admonition types are:
+# admonition_types = ["note", "tip", "caution", "deprecation", "danger"]
diff --git a/supa-mdx-lint/Rule001HeadingCase.toml b/supa-mdx-lint/Rule001HeadingCase.toml
new file mode 100644
index 00000000000..48d7b7a0193
--- /dev/null
+++ b/supa-mdx-lint/Rule001HeadingCase.toml
@@ -0,0 +1,200 @@
+# Heading should be sentence case
+
+# Words that may be uppercased even if they are not the first word in the sentence.
+# Can also specify a regex that is compatible with the [Rust regex crate](https://docs.rs/regex/latest/regex/).
+may_uppercase = [
+ "[A-Z0-9]{2,5}s?",
+ "Amazon RDS",
+ "APIs",
+ "Analytics",
+ "Android",
+ "Angular",
+ "Apple",
+ "Audit Logs?",
+ "Auth",
+ "Auth0",
+ "Auth0 Actions?",
+ "Azure",
+ "Azure Developers?",
+ "BigQuery",
+ "Bitbucket",
+ "Bitbucket Pipelines",
+ "Boolean",
+ "Broadcast",
+ "CAPTCHA",
+ "Channel",
+ "ChatGPT",
+ "Chrome",
+ "Chrome Developer Tools",
+ "Cloudflare",
+ "Cloudflare Workers?",
+ "Code Exchange",
+ "Colab",
+ "Content Delivery Network",
+ "Cron Jobs?",
+ "Data API",
+ "DataDog",
+ "Dart",
+ "Dashboard",
+ "Database Functions?",
+ "Deno",
+ "DigitalOcean",
+ "Discord",
+ "Discord Developers?",
+ "Django",
+ "Docker",
+ "Drizzle",
+ "Edge Functions?",
+ "Enterprise Plan",
+ "Expo",
+ "Facebook",
+ "Facebook Developers?",
+ "Figma",
+ "Figma Developers?",
+ "Firebase",
+ "Firebase Authentication",
+ "Firestore",
+ "Flutter",
+ "Functions?",
+ "Free Plan",
+ "Git",
+ "GitHub",
+ "GitHub Actions",
+ "GitLab",
+ "GoTrue",
+ "Google",
+ "Grafana",
+ "GraphQL",
+ "Heroku",
+ "Homebrew",
+ "Hooks?",
+ "Hugging Face",
+ "I",
+ "IPv4",
+ "IPv6",
+ "IVFFlat",
+ "IdP",
+ "Inbucket",
+ "Index Advisor",
+ "IntelliJ",
+ "Ionic Angular",
+ "Ionic React",
+ "Ionic Vue",
+ "JavaScript",
+ "JSON Web Tokens?",
+ "JWTs",
+ "Kakao",
+ "Kakao Developers?",
+ "Kakao Login",
+ "Keycloak",
+ "Kotlin",
+ "Kotlin Multiplatform",
+ "Kysely",
+ "Large Language Models?",
+ "LinkedIn",
+ "LinkedIn Developers?",
+ "Linux",
+ "LlamaIndex",
+ "Llamafile",
+ "Logs Explorer",
+ "Magic Link",
+ "Mixpeek",
+ "Mixpeek Embed",
+ "MySQL",
+ "Navigable Small World",
+ "Neon",
+ "Next.js",
+ "Node.js",
+ "Notion",
+ "Nuxt",
+ "OAuth",
+ "Okta",
+ "Ollama",
+ "OpenAI",
+ "Open ID Connect",
+ "OrbStack",
+ "OrioleDB",
+ "PGAudit",
+ "Phoenix",
+ "Pro Plan",
+ "Podman",
+ "Poetry",
+ "Postgres",
+ "Postgres Changes",
+ "PostgreSQL",
+ "PostgREST",
+ "Presence",
+ "Prometheus",
+ "Python",
+ "Query Performance",
+ "React",
+ "React Email",
+ "React Native",
+ "Reciprocal Ranked Fusion",
+ "Redis",
+ "RedwoodJS",
+ "Remix",
+ "Render",
+ "Retrieval Plugin",
+ "Roboflow Inference",
+ "Row Level Security",
+ "Send Email Hook",
+ "SendGrid",
+ "Sentry",
+ "Server-Side Auth",
+ "Server-Side Rendering",
+ "Single Sign-On",
+ "Slack",
+ "Slack Developers?",
+ "SolidJS",
+ "Spotify",
+ "Spotify Developers?",
+ "Sqitch",
+ "Storage",
+ "Studio",
+ "Supabase",
+ "Supabase Marketplace",
+ "Supavisor('s)?",
+ "Svelte",
+ "SvelteKit",
+ "Swift",
+ "SwiftUI",
+ "Team Plan",
+ "Third-Party Auth",
+ "TimescaleDB",
+ "Transformers.js",
+ "Twilio",
+ "Twitch",
+ "Twitch Developers?",
+ "Twitter",
+ "Twitter Developers?",
+ "TypeScript",
+ "Uppy",
+ "Upstash",
+ "URIs",
+ "URLs",
+ "Unsplash",
+ "Xcode",
+ "Vault",
+ "VSCode",
+ "Vecs",
+ "Vercel",
+ "Vercel Marketplace",
+ "Visual Studio Code",
+ "Vue",
+ "Web",
+ "WebAssembly",
+ "WebP",
+ "WebSockets?",
+ "WebStorm",
+ "Windows",
+ "WorkOS",
+ "Wrappers",
+ "Write-Ahead Log(s|ging)?",
+ "Zoom",
+ "Zoom Developers?",
+]
+
+# Words that may be lowercased even if they are the first word in the sentence.
+# Can also specify a regex that is compatible with the [Rust regex crate](https://docs.rs/regex/latest/regex/).
+may_lowercase = ["iOS"]
diff --git a/supa-mdx-lint/Rule003Spelling.toml b/supa-mdx-lint/Rule003Spelling.toml
new file mode 100644
index 00000000000..1eeb1ed2ffe
--- /dev/null
+++ b/supa-mdx-lint/Rule003Spelling.toml
@@ -0,0 +1,191 @@
+# Check spelling
+# Error message: "Word not found in dictionary"
+#
+# Allow list: Spellings that are actually correct, though they aren't in the
+# dictionary.
+#
+# Prefixes: Strings that are not standalone words, but that can be used in a
+# prefix before a hyphen, such as "pre" or "bi".
+#
+# Before adding a new word to the allow list, double check that it is in fact
+# the correct casing for the word! Especially for styling of company and product
+# names, the "official" casing might not be what you think.
+
+allow_list = [
+ "[A-Za-z0-9_-]+(\\.[A-Z-a-z0-9_-]+)+(\\/[A-Za-z0-9_-]+)*",
+ "[KMG]iB",
+ "\\[#[A-Za-z0-9-]+\\]",
+ "\\$\\$.+?\\$\\$",
+ "\\S+\\.json",
+ "\\S+\\.toml",
+ "\\S+\\.yaml",
+ "[A-Z]{2,5}s?",
+ "[Aa]utovacuum(s|ing|ed)?",
+ "[Bb]ackend",
+ "[Bb]uilt-ins?",
+ "[Cc]onfigs?",
+ "[Cc]ooldowns?",
+ "[Cc]ron",
+ "[Dd]atasets?",
+ "[Dd]evs?",
+ "[Dd]ropdown",
+ "[Ee]nums?",
+ "[Ee]nv",
+ "[Ff]rontend",
+ "[Gg]zip(s|ed)?",
+ "[Mm]iddlewares?",
+ "[Mm]ultimodal",
+ "[Mm]ultipart",
+ "[Mm]ultithreading",
+ "[Nn]onces?",
+ "[Nn]ullable",
+ "[Pp]arams?",
+ "[Pp]laintext",
+ "[Pp]olyfill(s|ed)?",
+ "[Pp]ooler",
+ "[Qq]uickstarts?",
+ "[Rr]ealtime",
+ "[Rr]ebas(e|ed|es|ing)",
+ "[Rr]epos?",
+ "[Rr]untimes?",
+ "[Ss]erverless",
+ "[Ss]ubcommands?",
+ "[Ss]ubdomains?",
+ "[Ss]ubfolders?",
+ "[Ss]ubmodules?",
+ "[Tt]odos?",
+ "[Tt]radeoffs?",
+ "[Uu]pserts?",
+ "[Uu]ptime",
+ "[Ww]aitlists?",
+ "[Ww]ebhooks?",
+ "AndroidX",
+ "AsyncStorage",
+ "BigQuery",
+ "Bitbucket",
+ "CAPTCHA",
+ "ChatGPT",
+ "Clippy",
+ "Cloudflare",
+ "Colab",
+ "Database Functions?",
+ "DataDog",
+ "DevTools",
+ "DDoS",
+ "Deno",
+ "Django",
+ "Docker",
+ "Drizzle",
+ "Erlang",
+ "Firestore",
+ "GDScript",
+ "Git",
+ "GitHub",
+ "GitLab",
+ "GoTrue",
+ "Grafana",
+ "GraphQL",
+ "Heroku",
+ "Homebrew",
+ "Hono",
+ "IdP",
+ "ImageMagick",
+ "Inbucket",
+ "IntelliJ",
+ "IVFFlat",
+ "Jupyter",
+ "JWTs",
+ "Kotlin",
+ "Ktor",
+ "Kysely",
+ "LangChain",
+ "Laravel",
+ "LlamaIndex",
+ "Llamafile",
+ "Lua",
+ "Mixpeek",
+ "MySQL",
+ "Nano",
+ "Netlify",
+ "Next.js",
+ "NoSQL",
+ "Node.js",
+ "Nuxt",
+ "OAuth",
+ "Okta",
+ "Ollama",
+ "OpenAI",
+ "OrbStack",
+ "PascalCase",
+ "Podman",
+ "PostgREST",
+ "Postgres",
+ # We prefer Postgres, but check for vocabulary preference in a separate rule
+ "PostgreSQL",
+ "PubSub",
+ "Prisma",
+ "Redis",
+ "RedwoodJS",
+ "Roboflow",
+ "SDKs",
+ "SQLAlchemy",
+ "SQLite",
+ "SendGrid",
+ "Snaplet",
+ "SolidJS",
+ "Supavisor",
+ "SvelteKit",
+ "SwiftUI",
+ "Supabase",
+ "TimescaleDB",
+ "Transformers.js",
+ "Twilio",
+ "Undici",
+ "Unsplash",
+ "Uppy",
+ "Upstash",
+ "VSCode",
+ "Vecs",
+ "Vercel",
+ "Vite",
+ "Vue",
+ "WebAssembly",
+ "WebP",
+ "WebSockets?",
+ "WebStorm",
+ "Xcode",
+ "bcrypt",
+ "camelCase",
+ "deno-postgres",
+ "e.g.",
+ "gte-small",
+ "https?:\\/\\/\\S+",
+ "i.e.",
+ "iOS",
+ "localhost",
+ "macOS",
+ "npm",
+ "npmrc",
+ "pgAudit",
+ "pgsodium",
+ "pgvector",
+ "psql",
+ "scrypt",
+ "stdin",
+ "stdout",
+ "supabase-auth-ui",
+ "supabase-csharp",
+ "supabase-flutter",
+ "supabase-gdscript",
+ "supabase-go",
+ "supabase-js",
+ "supabase-kt",
+ "supabase-management-js",
+ "supabase-py",
+ "supabase-rb",
+ "supabase-swift",
+ "supautils",
+ "vecs",
+]
+
+prefixes = ["bi", "pre"]