diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
index 719c333152d81..c0e952b351b45 100644
--- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
+++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.constants.ts
@@ -349,6 +349,16 @@ export const gettingstarted: NavMenuConstant = {
},
],
},
+ {
+ name: 'AI Prompts',
+ url: undefined,
+ items: [
+ {
+ name: 'Overview',
+ url: '/guides/getting-started/ai-prompts',
+ },
+ ],
+ },
],
}
diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx
index d47562c92298a..ffb21177637b5 100644
--- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx
+++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenu.tsx
@@ -256,7 +256,7 @@ const NavigationMenu = ({
additionalNavItems,
}: {
menuId: MenuId
- additionalNavItems?: Partial[]
+ additionalNavItems?: Record[]>
}) => {
const level = menuId
const menu = getMenuById(level)
diff --git a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideList.tsx b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideList.tsx
index af40ab7e9e869..e9e211a826598 100644
--- a/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideList.tsx
+++ b/apps/docs/components/Navigation/NavigationMenu/NavigationMenuGuideList.tsx
@@ -6,20 +6,23 @@ import { type NavMenuSection } from '../Navigation.types'
import * as NavItems from './NavigationMenu.constants'
import NavigationMenuGuideListItems from './NavigationMenuGuideListItems'
import { usePathname } from 'next/navigation'
+import { PropsWithChildren } from 'react'
+import { MenuId } from './NavigationMenu'
const NavigationMenuGuideList = ({
id,
additionalNavItems,
}: {
id: string
- additionalNavItems?: Partial[]
+ additionalNavItems?: Record[]>
}) => {
const pathname = usePathname()
const firstLevelRoute = pathname?.split('/')?.slice(0, 4)?.join('/')
+ // eslint-disable-next-line import/namespace -- dynamic access, can't lint properly
let menu = NavItems[id]
- if (id === 'integrations' && additionalNavItems) {
+ if (id === MenuId.Integrations && additionalNavItems?.integrations) {
const integrationsListIndex = menu.items.findIndex((item) => item.name === 'Integrations')
if (integrationsListIndex !== -1) {
menu = {
@@ -28,7 +31,7 @@ const NavigationMenuGuideList = ({
...menu.items.slice(0, integrationsListIndex),
{
...menu.items[integrationsListIndex],
- items: [...menu.items[integrationsListIndex].items, ...additionalNavItems],
+ items: [...menu.items[integrationsListIndex].items, ...additionalNavItems.integrations],
},
...menu.items.slice(integrationsListIndex + 1),
],
@@ -36,6 +39,38 @@ const NavigationMenuGuideList = ({
}
}
+ if (id === MenuId.GettingStarted && additionalNavItems?.prompts) {
+ const promptsSectionIndex = menu.items.findIndex((item) => item.name === 'AI Prompts')
+ if (promptsSectionIndex !== -1) {
+ menu = {
+ ...menu,
+ items: [
+ ...menu.items.slice(0, promptsSectionIndex),
+ {
+ ...menu.items[promptsSectionIndex],
+ items: [...menu.items[promptsSectionIndex].items, ...additionalNavItems.prompts],
+ },
+ ...menu.items.slice(promptsSectionIndex + 1),
+ ],
+ }
+ }
+ }
+
+ return (
+
+
+
+ )
+}
+
+export function NavigationMenuGuideListWrapper({
+ id,
+ firstLevelRoute,
+ children,
+}: PropsWithChildren<{
+ id: string
+ firstLevelRoute?: string
+}>) {
return (
-
+ {children}
)
}
diff --git a/apps/docs/content/guides/ai/examples/semantic-image-search-amazon-titan.mdx b/apps/docs/content/guides/ai/examples/semantic-image-search-amazon-titan.mdx
index c2dd616366eaa..373720b7797aa 100644
--- a/apps/docs/content/guides/ai/examples/semantic-image-search-amazon-titan.mdx
+++ b/apps/docs/content/guides/ai/examples/semantic-image-search-amazon-titan.mdx
@@ -28,7 +28,7 @@ Then initialize a new project:
poetry new aws_bedrock_image_search
```
-## Spin up a Postgres Database with pgvector
+## Spin up a Postgres database with pgvector
If you haven't already, head over to [database.new](https://database.new) and create a new project. Every Supabase project comes with a full Postgres database and the [pgvector extension](/docs/guides/database/extensions/pgvector) preconfigured.
diff --git a/apps/docs/content/guides/ai/integrations/amazon-bedrock.mdx b/apps/docs/content/guides/ai/integrations/amazon-bedrock.mdx
index d18f9a6bc83dc..02699d3271de0 100644
--- a/apps/docs/content/guides/ai/integrations/amazon-bedrock.mdx
+++ b/apps/docs/content/guides/ai/integrations/amazon-bedrock.mdx
@@ -10,7 +10,7 @@ tocVideo: 'A3uND5sgiO0'
This guide will walk you through an example using Amazon Bedrock SDK with `vecs`. We will create embeddings using the Amazon Titan Embeddings G1 – Text v1.2 (amazon.titan-embed-text-v1) model, insert these embeddings into a PostgreSQL database using vecs, and then query the collection to find the most similar sentences to a given query sentence.
-## Create an Environment
+## Create an environment
First, you need to set up your environment. You will need Python 3.7+ with the `vecs` and `boto3` libraries installed.
@@ -25,7 +25,7 @@ You'll also need:
- [Credentials to your AWS account](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html)
- [A Postgres Database with the pgvector extension](hosting.md)
-## Create Embeddings
+## Create embeddings
Next, we will use Amazon’s Titan Embedding G1 - Text v1.2 model to create embeddings for a set of sentences.
@@ -67,7 +67,7 @@ for sentence in dataset:
```
-### Store the Embeddings with vecs
+### Store the embeddings with vecs
Now that we have our embeddings, we can insert them into a PostgreSQL database using vecs.
@@ -90,7 +90,7 @@ sentences.upsert(records=embeddings)
sentences.create_index()
```
-### Querying for Most Similar Sentences
+### Querying for most similar sentences
Now, we query the `sentences` collection to find the most similar sentences to a sample query sentence. First need to create an embedding for the query sentence. Next, we query the collection we created earlier to find the most similar sentences.
diff --git a/apps/docs/content/guides/getting-started/ai-prompts.mdx b/apps/docs/content/guides/getting-started/ai-prompts.mdx
new file mode 100644
index 0000000000000..412364c2bfb62
--- /dev/null
+++ b/apps/docs/content/guides/getting-started/ai-prompts.mdx
@@ -0,0 +1,16 @@
+---
+title: AI Prompts
+subtitle: Prompts for working with Supabase using AI-powered IDE tools
+---
+
+We've curated a selection of prompts to help you work with Supabase using your favorite AI-powered IDE tools, such as GitHub Copilot or Cursor.
+
+## How to use
+
+Copy the prompt to a file in your repo.
+
+Use the "include file" feature from your AI tool to include the prompt when chatting with your AI assistant. For example, with GitHub Copilot, use `#`, in Cursor, use `@Files`, and in Zed, use `/file`.
+
+## Prompts
+
+
diff --git a/apps/docs/features/docs/MdxBase.tsx b/apps/docs/features/docs/MdxBase.tsx
index 1bda6f1f0b1f4..20413a1cc7d0b 100644
--- a/apps/docs/features/docs/MdxBase.tsx
+++ b/apps/docs/features/docs/MdxBase.tsx
@@ -7,9 +7,14 @@ import remarkGfm from 'remark-gfm'
import rehypeKatex from 'rehype-katex'
import remarkMath from 'remark-math'
+import { AiPromptsIndex } from '~/app/guides/(with-sidebar)/getting-started/ai-prompts/[slug]/AiPromptsIndex'
import { preprocessMdxWithDefaults } from '~/features/directives/utils'
import { components } from '~/features/docs/MdxBase.shared'
+const serverOnlyComponents = {
+ AiPromptsIndex,
+}
+
const codeHikeOptions: CodeHikeConfig = {
theme: codeHikeTheme,
lineNumbers: true,
@@ -66,7 +71,7 @@ const MDXRemoteBase = async ({
return (
diff --git a/apps/docs/layouts/MainSkeleton.tsx b/apps/docs/layouts/MainSkeleton.tsx
index 62bf27160f8c2..9e116e883c9a7 100644
--- a/apps/docs/layouts/MainSkeleton.tsx
+++ b/apps/docs/layouts/MainSkeleton.tsx
@@ -336,7 +336,7 @@ interface SkeletonProps extends PropsWithChildren {
NavigationMenu?: ReactNode
hideFooter?: boolean
className?: string
- additionalNavItems?: Partial[]
+ additionalNavItems?: Record[]>
}
function TopNavSkeleton({ children }) {
diff --git a/apps/docs/layouts/guides/index.tsx b/apps/docs/layouts/guides/index.tsx
index 0a2695833c93a..c6ba38d293a22 100644
--- a/apps/docs/layouts/guides/index.tsx
+++ b/apps/docs/layouts/guides/index.tsx
@@ -1,5 +1,5 @@
import 'katex/dist/katex.min.css'
-import { type PropsWithChildren } from 'react'
+import type { ReactNode, PropsWithChildren } from 'react'
import { type NavMenuSection } from '~/components/Navigation/Navigation.types'
import { LayoutMainContent } from '~/layouts/DefaultLayout'
@@ -8,9 +8,13 @@ import { SidebarSkeleton } from '~/layouts/MainSkeleton'
const Layout = ({
children,
additionalNavItems,
-}: PropsWithChildren<{ additionalNavItems?: Partial[] }>) => {
+ NavigationMenu,
+}: PropsWithChildren<{
+ additionalNavItems?: Record[]>
+ NavigationMenu?: ReactNode
+}>) => {
return (
-
+ {children}
)
diff --git a/apps/docs/next-env.d.ts b/apps/docs/next-env.d.ts
index 725dd6f245153..40c3d68096c27 100644
--- a/apps/docs/next-env.d.ts
+++ b/apps/docs/next-env.d.ts
@@ -1,6 +1,5 @@
///
///
-///
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/building-your-application/configuring/typescript for more information.
diff --git a/apps/docs/package.json b/apps/docs/package.json
index 9cf9730847556..857ab7ba745c6 100644
--- a/apps/docs/package.json
+++ b/apps/docs/package.json
@@ -101,7 +101,6 @@
"unist-builder": "^3.0.1",
"unist-util-filter": "^4.0.1",
"unist-util-visit": "^4.1.2",
- "unist-util-visit-parents": "^5.0.0",
"uuid": "^9.0.1",
"valtio": "^1.12.0",
"yaml": "^2.4.5",
diff --git a/examples/prompts/code-format-sql.md b/examples/prompts/code-format-sql.md
index ed3cb254a30d2..45e55811dac3b 100644
--- a/examples/prompts/code-format-sql.md
+++ b/examples/prompts/code-format-sql.md
@@ -1,4 +1,4 @@
-# PostgreSQL SQL Style Guide
+# Postgres SQL Style Guide
## General
@@ -12,7 +12,7 @@
- Avoid SQL reserved words and ensure names are unique and under 63 characters.
- Use snake_case for tables and columns.
-- Prefer plurals for table names
+- Prefer plurals for table names
- Prefer singular names for columns.
## Tables
@@ -62,12 +62,12 @@ where employee_id = 1001;
Larger queries:
```sql
-select
- first_name,
+select
+ first_name,
last_name
-from
+from
employees
-where
+where
start_date between '2021-01-01' and '2021-12-31'
and
status = 'employed';
@@ -80,14 +80,14 @@ and
- Prefer full table names when referencing tables. This helps for readability.
```sql
-select
- employees.employee_name,
+select
+ employees.employee_name,
departments.department_name
-from
+from
employees
-join
+join
departments on employees.department_id = departments.department_id
-where
+where
employees.start_date > '2022-01-01';
```
@@ -104,7 +104,7 @@ where end_date is null;
## Complex queries and CTEs
-- If a query is extremely complex, prefer a CTE.
+- If a query is extremely complex, prefer a CTE.
- Make sure the CTE is clear and linear. Prefer readability over performance.
- Add comments to each block.
@@ -138,4 +138,4 @@ from
employee_counts
order by
department_name;
-```
\ No newline at end of file
+```
diff --git a/examples/prompts/nextjs-supabase-auth.md b/examples/prompts/nextjs-supabase-auth.md
new file mode 100644
index 0000000000000..b10a4d63c3d30
--- /dev/null
+++ b/examples/prompts/nextjs-supabase-auth.md
@@ -0,0 +1,108 @@
+# Bootstrap Next.js app with Supabase Auth
+
+Create a Next.js app that uses App Router with Supabase Auth.
+
+Follow Supabase's guidelines for using the `@supabase/ssr` package and Server-Side Auth. Specifically, there should be:
+
+- A utility function to create a client on the client side
+- A utility function create a client on the server side, using the Next.js `cookies` API to access the cookies. Use the latest version of the API, where `cookies` must be awaited.
+- A utility function to handle refreshing the user session in middleware.
+
+## Working with cookies
+
+Use the latest version of `@supabase/ssr`, where cookie options are defined with the `getAll` and `setAll` functions, like so:
+
+```
+const supabase = createServerClient(
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
+ {
+ cookies: {
+ getAll() {
+ return request.cookies.getAll()
+ },
+ setAll(cookiesToSet) {
+ cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))
+ supabaseResponse = NextResponse.next({
+ request,
+ })
+ cookiesToSet.forEach(({ name, value, options }) =>
+ supabaseResponse.cookies.set(name, value, options)
+ )
+ },
+ },
+ }
+ )
+```
+
+No other cookie options should be provided.
+
+## Middleware
+
+The middleware should use the following `updateSession` function:
+
+```
+import { createServerClient } from '@supabase/ssr'
+import { NextResponse, type NextRequest } from 'next/server'
+
+export async function updateSession(request: NextRequest) {
+ let supabaseResponse = NextResponse.next({
+ request,
+ })
+
+ const supabase = createServerClient(
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
+ process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
+ {
+ cookies: {
+ getAll() {
+ return request.cookies.getAll()
+ },
+ setAll(cookiesToSet) {
+ cookiesToSet.forEach(({ name, value, options }) => request.cookies.set(name, value))
+ supabaseResponse = NextResponse.next({
+ request,
+ })
+ cookiesToSet.forEach(({ name, value, options }) =>
+ supabaseResponse.cookies.set(name, value, options)
+ )
+ },
+ },
+ }
+ )
+
+ // IMPORTANT: Avoid writing any logic between createServerClient and
+ // supabase.auth.getUser(). A simple mistake could make it very hard to debug
+ // issues with users being randomly logged out.
+
+ const {
+ data: { user },
+ } = await supabase.auth.getUser()
+
+ if (
+ !user &&
+ !request.nextUrl.pathname.startsWith('/login') &&
+ !request.nextUrl.pathname.startsWith('/auth')
+ ) {
+ // no user, potentially respond by redirecting the user to the login page
+ const url = request.nextUrl.clone()
+ url.pathname = '/login'
+ return NextResponse.redirect(url)
+ }
+
+ // IMPORTANT: You *must* return the supabaseResponse object as it is. If you're
+ // creating a new response object with NextResponse.next() make sure to:
+ // 1. Pass the request in it, like so:
+ // const myNewResponse = NextResponse.next({ request })
+ // 2. Copy over the cookies, like so:
+ // myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())
+ // 3. Change the myNewResponse object to fit your needs, but avoid changing
+ // the cookies!
+ // 4. Finally:
+ // return myNewResponse
+ // If this is not done, you may be causing the browser and server to go out
+ // of sync and terminate the user's session prematurely!
+
+ return supabaseResponse
+}
+```
diff --git a/package-lock.json b/package-lock.json
index 8d9b9e74f34a7..2bdf6f2e7eab5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -931,7 +931,6 @@
"unist-builder": "^3.0.1",
"unist-util-filter": "^4.0.1",
"unist-util-visit": "^4.1.2",
- "unist-util-visit-parents": "^5.0.0",
"uuid": "^9.0.1",
"valtio": "^1.12.0",
"yaml": "^2.4.5",
diff --git a/supa-mdx-lint.config.toml b/supa-mdx-lint.config.toml
index 1eba0db28cce7..745fe5912332b 100644
--- a/supa-mdx-lint.config.toml
+++ b/supa-mdx-lint.config.toml
@@ -5,32 +5,42 @@ ignore_patterns = ["**/_*.mdx"]
# 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-Z]{3,5}",
+ "[A-Z0-9]{2,5}",
"Android",
"Angular",
"Apple",
"Auth",
+ "ChatGPT",
"Content Delivery Network",
"Dart",
- "Edge Functions",
+ "Edge Functions?",
"Flutter",
"GoTrue",
"Google",
"GraphQL",
+ "Hugging Face",
+ "I",
+ "IVFFlat",
"Ionic Angular",
"Ionic React",
"Ionic Vue",
"JavaScript",
"Kotlin",
+ "Navigable Small World",
"Next.js",
"Nuxt",
"OpenAI",
+ "Poetry",
"Postgres",
"PostgreSQL",
"PostgREST",
+ "Python",
"React",
"React Native",
+ "Reciprocal Ranked Fusion",
"RedwoodJS",
+ "Retrieval Plugin",
+ "Roboflow Inference",
"Row Level Security",
"Server-Side Auth",
"Single Sign-On",
@@ -40,8 +50,11 @@ may_uppercase = [
"SvelteKit",
"Swift",
"SwiftUI",
+ "TypeScript",
"Xcode",
+ "Vecs",
"Vue",
+ "Wrappers",
]
# 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/).