From ee1eb5dbcaed943f98538f9348d16a4ee1df2a69 Mon Sep 17 00:00:00 2001 From: Illia Basalaiev <44750366+Ellba@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:03:37 +0200 Subject: [PATCH] docs: standardize quickstart guides (#48950) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## I have read the [CONTRIBUTING.md](https://github.com/supabase/supabase/blob/master/CONTRIBUTING.md) file. YES ## What kind of change does this PR introduce? Docs update ## What is the new behavior? - All 19 guides follow one step order: create project → set up database → create app → AI tooling → add keys → create client → query data → run it → go to production. Added _template.mdx with structure requirements; it is not enforced with a lint check for now - this will be a separate PR before adding new guides. - 4 new partials replace copy-pasted blocks (AI tooling, connection strings, mobile env vars, going to production). - Error handling: return a message instead of a blank page when a query fails. - All guides verified and tested separately - all work as described. What was fixed: wrong env var names in the Hono sample, a Next.js page that redirected to login, missing database permissions in Refine and Hono, and stale file paths and APIs in SvelteKit, Refine, and TanStack. - Astro, Expo, Python, Laravel, and Rails were live but missing from the quickstart grid or listing page. Added, with two new icons. ## Quick links for review Base preview: https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs **Quickstart discovery**: new Astro/Expo/Python/Laravel/Rails entries and icons - [Docs homepage grid](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs) CleanShot 2026-08-12 at 12 06 31@2x - [Getting started overview](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started) CleanShot 2026-08-12 at 12 13 30@2x ### New shared files: **[apps/docs/content/guides/getting-started/quickstarts/_template.mdx](https://github.com/supabase/supabase/blob/e311542913cf8da07f322a7586339d6f5de30c61/apps/docs/content/guides/getting-started/quickstarts/_template.mdx?plain=1)** A reference contract the other 19 quickstart guides are checked against. Documents the required frontmatter, the canonical 10-step section order, every guide's deviation from that order (and why), the direct-Postgres exception (Laravel/Rails/RedwoodJS/Spring Boot), and the discovery-surface/icon requirements for adding a new guide. No lint rule enforces it yet; that's a follow-up PR. **[apps/docs/content/_partials/quickstart_ai_tooling.mdx](https://github.com/supabase/supabase/blob/e311542913cf8da07f322a7586339d6f5de30c61/apps/docs/content/_partials/quickstart_ai_tooling.mdx?plain=1)** Example: [Next.js](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/nextjs#4-set-up-ai-tooling-optional) → "Set up AI tooling" section Shared by all 19 guides: astrojs, expo-react-native, flask, flutter, hono, ios-swiftui, kotlin, laravel, nextjs, nuxtjs, reactjs, redwoodjs, refine, ruby-on-rails, solidjs, spring-boot, sveltekit, tanstack, vue **[apps/docs/content/_partials/quickstart_going_to_production.mdx](https://github.com/supabase/supabase/blob/e311542913cf8da07f322a7586339d6f5de30c61/apps/docs/content/_partials/quickstart_going_to_production.mdx?plain=1)** Example: [Next.js](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/nextjs#going-to-production) → "Going to production" section Shared by all 19 guides: same full list as above **[apps/docs/content/_partials/quickstart_connection_string.mdx](https://github.com/supabase/supabase/blob/e311542913cf8da07f322a7586339d6f5de30c61/apps/docs/content/_partials/quickstart_connection_string.mdx?plain=1)** Example: [Laravel](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/laravel#5-set-up-the-postgres-connection-details) → connection string setup step Shared by 3 guides: laravel, ruby-on-rails, spring-boot – the ORM/backend frameworks that connect directly to Postgres rather than through the Data API **[apps/docs/content/_partials/quickstart_mobile_env_note.mdx](https://github.com/supabase/supabase/blob/e311542913cf8da07f322a7586339d6f5de30c61/apps/docs/content/_partials/quickstart_mobile_env_note.mdx?plain=1)** Example: [iOS SwiftUI](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/ios-swiftui#get-api-details:~:text=This%20guide%20substitutes%20your%20project%20URL%20and%20key%20directly) → environment variables step Shared by 3 guides: ios-swiftui, flutter, kotlin – note Expo React Native is mobile too but doesn't use this partial, since it has its own `EXPO_PUBLIC_` prefix convention inline instead. ## Per guide changes **[Astro](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/astrojs#9-query-supabase-data-from-astro)** Typed query error in the server client sample. **[Expo React Native](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/expo-react-native#8-query-data-from-the-app)** Added an `error` state alongside instruments. Also removed the broken [`--web` verification path](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/expo-react-native#9-start-the-app): expo-sqlite needs Metro wasm + COEP/COOP config the guide never had (CodeRabbit finding). **[Flask](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/flask#7-create-the-supabase-client)** Split "Create the Supabase client" and ["Query data"](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/flask#8-query-data-from-the-app) into their own steps. **[Flutter](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/flutter#9-setup-deep-links-optional)** Reworded the deep-links section; keeps the framework-specific [Android `INTERNET` permission subsection](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/flutter#android) under "Going to production." **[Hono](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/hono#6-declare-supabase-environment-variables)** Split into "Install dependencies," "Declare environment variables," "Set up anonymous sign-ins," and "Query data" as separate steps. Fixes wrong env var names from the previous sample. **[iOS SwiftUI](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/ios-swiftui#8-query-data-from-the-app)** Added an `isLoading` state so the loading overlay doesn't hang forever on a successful empty result (CodeRabbit fix). **[Kotlin](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/kotlin#5-install-dependencies)** Fixed the Compose compiler plugin declaration: `apply false` was missing from the app module (CodeRabbit finding). **[Laravel](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/laravel#5-set-up-the-postgres-connection-details)** Now uses the shared `quickstart_connection_string.mdx` partial for the session-pooler/SSL guidance instead of inline copy. **[Next.js](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/nextjs#6-allow-public-access-to-the-instruments-page)** New step fixing the page that previously redirected to login. Its middleware path check is also now segment-aware so it doesn't over-match paths like `/instruments-private` (CodeRabbit finding). **[Nuxt](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/nuxtjs#7-create-the-supabase-client)** "Create the Supabase client" and ["Query data"](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/nuxtjs#8-query-data-from-the-app) split out as their own steps. **[React](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/reactjs#7-create-the-supabase-client)** Same client-creation/[query-data](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/reactjs#8-query-data-from-the-app) split as the other Vite-based guides. **[RedwoodJS](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/redwoodjs#2-gather-database-connection-strings)** Expanded into explicit transaction-mode/session-mode connection strings, Prisma schema, migration, seed, and scaffold steps; fixes stale file paths and APIs from the previous version. **[Refine](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/refine#8-allow-writes-to-the-instruments-table)** New step fixing the missing RLS grants that made the scaffolded create/edit pages fail. **[Ruby on Rails](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/ruby-on-rails#4-set-up-the-postgres-connection-details)** Now uses `quickstart_connection_string.mdx`; added a [reminder to save the database password](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/ruby-on-rails#1-create-a-supabase-project) before it's needed for the connection string. **[SolidJS](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/solidjs#7-create-the-supabase-client)** Same client-creation/[query-data](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/solidjs#8-query-data-from-the-app) split, adapted to Solid's `resource.error`. **[Spring Boot](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/spring-boot#4-set-up-the-postgres-connection-details)** Connection-string section now uses the shared partial instead of a duplicated inline caution. **[SvelteKit](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/sveltekit#8-query-data-from-the-app)** Updated `load` functions (both `+page.js` and `+page.server.ts` variants) with explicit query-error typing; fixes stale file paths and APIs from the previous version. **[TanStack](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/tanstack#8-query-supabase-data-from-tanstack-start)** `fetchInstruments` now returns and renders the query error instead of silently returning an empty list (CodeRabbit finding); fixes stale file paths and APIs from the previous version. **[Vue](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/vue#7-create-the-supabase-client)** Same client-creation/[query-data](https://docs-git-docs-standardize-framework-quickstarts-supabase.vercel.app/docs/guides/getting-started/quickstarts/vue#8-query-data-from-the-app) split as the other Vite-based guides. ## Summary by CodeRabbit * **New Features** * Added SolidJS, RedwoodJS, Refine, Laravel, and Ruby on Rails quickstarts. * Added framework discovery entries for Astro, Expo React Native, Python, Laravel, and Rails. * Added optional AI tooling, MCP setup, connection-string, mobile configuration, and production-readiness guidance. * Added a Hono authentication example with anonymous sign-in, user details, and instrument data. * **Documentation** * Expanded setup, environment, authentication, RLS, migration, SSL, and deployment guidance. * **Bug Fixes** * Improved sample error handling for failed data requests. --------- Co-authored-by: Miranda Limonczenko --- apps/docs/components/FrameworkQuickstarts.tsx | 25 +++ .../_partials/quickstart_ai_tooling.mdx | 19 +++ .../quickstart_connection_string.mdx | 13 ++ .../quickstart_going_to_production.mdx | 9 + .../_partials/quickstart_mobile_env_note.mdx | 5 + .../getting-started/quickstarts/_template.mdx | 154 ++++++++++++++++++ .../getting-started/quickstarts/astrojs.mdx | 31 ++-- .../quickstarts/expo-react-native.mdx | 44 +++-- .../getting-started/quickstarts/flask.mdx | 39 +++-- .../getting-started/quickstarts/flutter.mdx | 19 +-- .../getting-started/quickstarts/hono.mdx | 61 +++++-- .../quickstarts/ios-swiftui.mdx | 28 ++-- .../getting-started/quickstarts/kotlin.mdx | 79 ++++++--- .../getting-started/quickstarts/laravel.mdx | 66 ++++---- .../getting-started/quickstarts/nextjs.mdx | 58 +++++-- .../getting-started/quickstarts/nuxtjs.mdx | 62 +++++-- .../getting-started/quickstarts/reactjs.mdx | 43 ++--- .../getting-started/quickstarts/redwoodjs.mdx | 64 ++++---- .../getting-started/quickstarts/refine.mdx | 92 +++++++---- .../quickstarts/ruby-on-rails.mdx | 48 ++---- .../getting-started/quickstarts/solidjs.mdx | 65 +++++--- .../quickstarts/spring-boot.mdx | 50 +++--- .../getting-started/quickstarts/sveltekit.mdx | 44 ++--- .../getting-started/quickstarts/tanstack.mdx | 61 ++++--- .../getting-started/quickstarts/vue.mdx | 47 ++++-- .../content-listings/getting-started.data.ts | 69 ++++++-- apps/docs/public/img/icons/laravel-icon.svg | 1 + apps/docs/public/img/icons/rails-icon.svg | 1 + examples/auth/hono/package.json | 1 + examples/auth/hono/src/client.tsx | 109 +++++++++++++ examples/auth/hono/src/index.tsx | 47 +++++- .../hono/src/middleware/auth.middleware.ts | 21 ++- examples/auth/hono/tsconfig.json | 12 ++ examples/auth/hono/vite.config.ts | 33 ++++ 34 files changed, 1089 insertions(+), 431 deletions(-) create mode 100644 apps/docs/content/_partials/quickstart_ai_tooling.mdx create mode 100644 apps/docs/content/_partials/quickstart_connection_string.mdx create mode 100644 apps/docs/content/_partials/quickstart_going_to_production.mdx create mode 100644 apps/docs/content/_partials/quickstart_mobile_env_note.mdx create mode 100644 apps/docs/content/guides/getting-started/quickstarts/_template.mdx create mode 100644 apps/docs/public/img/icons/laravel-icon.svg create mode 100644 apps/docs/public/img/icons/rails-icon.svg create mode 100644 examples/auth/hono/src/client.tsx create mode 100644 examples/auth/hono/tsconfig.json create mode 100644 examples/auth/hono/vite.config.ts diff --git a/apps/docs/components/FrameworkQuickstarts.tsx b/apps/docs/components/FrameworkQuickstarts.tsx index d4939b72455..398b099f5de 100644 --- a/apps/docs/components/FrameworkQuickstarts.tsx +++ b/apps/docs/components/FrameworkQuickstarts.tsx @@ -47,6 +47,21 @@ const frameworks = [ icon: '/docs/img/icons/svelte-icon', href: '/guides/getting-started/quickstarts/sveltekit', }, + { + name: 'SolidJS', + icon: '/docs/img/icons/solidjs-icon', + href: '/guides/getting-started/quickstarts/solidjs', + }, + { + name: 'RedwoodJS', + icon: '/docs/img/icons/redwood-icon', + href: '/guides/getting-started/quickstarts/redwoodjs', + }, + { + name: 'Refine', + icon: '/docs/img/icons/refine-icon', + href: '/guides/getting-started/quickstarts/refine', + }, { name: 'Hono', icon: '/docs/img/icons/hono-icon', @@ -81,6 +96,16 @@ const frameworks = [ icon: '/docs/img/icons/python-icon', href: '/guides/getting-started/quickstarts/flask', }, + { + name: 'Laravel', + icon: '/docs/img/icons/laravel-icon', + href: '/guides/getting-started/quickstarts/laravel', + }, + { + name: 'Ruby on Rails', + icon: '/docs/img/icons/rails-icon', + href: '/guides/getting-started/quickstarts/ruby-on-rails', + }, ] export function FrameworkQuickstarts({ labelledBy }: { labelledBy?: string }) { diff --git a/apps/docs/content/_partials/quickstart_ai_tooling.mdx b/apps/docs/content/_partials/quickstart_ai_tooling.mdx new file mode 100644 index 00000000000..2a66a6d3f72 --- /dev/null +++ b/apps/docs/content/_partials/quickstart_ai_tooling.mdx @@ -0,0 +1,19 @@ +Supabase provides two ways to give AI tools context about your project: Agent Skills, which give your AI coding agent procedural knowledge, and the MCP server, which connects AI assistants to your Supabase project directly. + +### Agent Skills + +[Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. + +Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. + +#### Installing Agent Skills + +To install, run the following command in the root of your project: + +```bash +npx skills add supabase/agent-skills +``` + +### Supabase MCP server + +The Supabase MCP server connects AI assistants to Supabase, so they can inspect your schema and act on your projects on your behalf. Find out how to add it to your client in [the MCP docs](/docs/guides/ai-tools/mcp). diff --git a/apps/docs/content/_partials/quickstart_connection_string.mdx b/apps/docs/content/_partials/quickstart_connection_string.mdx new file mode 100644 index 00000000000..48422f629c2 --- /dev/null +++ b/apps/docs/content/_partials/quickstart_connection_string.mdx @@ -0,0 +1,13 @@ +1. Navigate to your project dashboard and click on [Connect](/dashboard/project/_?showConnect=true&connectTab=direct&method=session). + + + + Don't use the Transaction pooler (port `6543`) as your app's main data source. Most ORMs rely on server-side prepared statements, which the Transaction pooler doesn't support. Use the Session pooler (port `5432`), or the direct connection string if you're in an [IPv6 environment](/docs/guides/troubleshooting/supabase--your-network-ipv4-and-ipv6-compatibility-cHe3BP) or have the [IPv4 Add-On](/docs/guides/platform/ipv4-address). + + + +1. Look for the **Session pooler** connection string and copy it. Replace the password placeholder with your saved database password, and [percent-encode](https://en.wikipedia.org/wiki/Percent-encoding) any reserved characters it contains, such as `&`, `#`, `?`, or a space. If you don't have your database password, you can reset it in your [Database Settings](/dashboard/project/_/database/settings). + +1. Set `sslmode=require` either on the connection string itself or as an explicit config option if your framework sets it separately. Most drivers default to `prefer`, which falls back to sending your data in plaintext if the encrypted attempt fails. You can also [enforce SSL](/docs/guides/platform/ssl-enforcement) on the database side. + +The connection strings below show the format only. Take the host, port, and username from the string you copied rather than typing the bracketed placeholders literally. diff --git a/apps/docs/content/_partials/quickstart_going_to_production.mdx b/apps/docs/content/_partials/quickstart_going_to_production.mdx new file mode 100644 index 00000000000..a3df5218846 --- /dev/null +++ b/apps/docs/content/_partials/quickstart_going_to_production.mdx @@ -0,0 +1,9 @@ +## Production requirements + +The quickstart procedure in this guide optimizes for getting you to a working app, not for production. + +Before you deploy: + +- If your app reads or writes through the Data API, review your [Row Level Security](/docs/guides/database/postgres/row-level-security) policies. Any policy you added here is scoped to this quickstart's sample data, not to real user data. +- Set your Supabase credentials as environment variables on whatever platform you deploy to, rather than committing them to source control. +- Configure a [custom domain](/docs/guides/platform/custom-domains) for your Supabase project once you're ready to go live. diff --git a/apps/docs/content/_partials/quickstart_mobile_env_note.mdx b/apps/docs/content/_partials/quickstart_mobile_env_note.mdx new file mode 100644 index 00000000000..7aee6d8e073 --- /dev/null +++ b/apps/docs/content/_partials/quickstart_mobile_env_note.mdx @@ -0,0 +1,5 @@ + + +This guide substitutes your project URL and key directly into the code above, rather than reading them from a `.env` file. Mobile apps don't get environment variables injected at runtime the way a bundler-based web app does. You'd need a build-time mechanism specific to your toolchain, such as `--dart-define-from-file` for Flutter, an `.xcconfig` file for iOS, or a `Gradle` `BuildConfig` field for Android. That's a good next step once you're past this quickstart, so your keys aren't committed to source control. + + diff --git a/apps/docs/content/guides/getting-started/quickstarts/_template.mdx b/apps/docs/content/guides/getting-started/quickstarts/_template.mdx new file mode 100644 index 00000000000..5a448263a53 --- /dev/null +++ b/apps/docs/content/guides/getting-started/quickstarts/_template.mdx @@ -0,0 +1,154 @@ +This file is a reference contract for framework quickstarts in this directory. It is +not a rendered page (filenames starting with `_` are excluded from the docs build +and from `supa-mdx-lint`) — it exists so every quickstart conforms to the same shape, +and so Phase 3's lint rule has a single source to check against. + +## Required frontmatter + +```yaml +--- +title: 'Use Supabase with ' +subtitle: '' +breadcrumb: 'Framework Quickstarts' +--- +``` + +## Required section order + +Before the numbered steps, and before any heading: + +- `` — always first. Every id must exist as a key in + `apps/docs/data/ai-prompts.data.ts`. +- An optional `## Prerequisites` section, for guides whose toolchain isn't implied + by the framework itself. `spring-boot.mdx` is the current example: Java 17, + `curl`, `unzip`. Don't add one to restate the obvious. + +The list below is the canonical order, not the literal heading numbers. +`quickstart_db_setup.mdx` supplies headings 1 and 2, so guides that use it start +their own headings at 3. Guides that use `quickstart_create_project.mdx` alone get +heading 1 from the partial and start at 2. A guide may also insert a +framework-specific step — `astrojs.mdx` adds **Configure Astro for SSR** between the +client library and the environment variables — so number each guide's headings +sequentially from where its partial leaves off rather than copying numbers from here. + +1. **Create a Supabase project** — via `<$Partial path="quickstart_create_project.mdx" />`, + either directly or nested inside `quickstart_db_setup.mdx` (see below). + - **Set up your database** (also numbered step 2, replacing the above) — only + for guides that query the shared `instruments` sample table through a + Supabase client library. Use `<$Partial path="quickstart_db_setup.mdx" />` + instead (it nests the project-creation partial). Guides that connect + directly to Postgres with their own ORM (Laravel, Rails, RedwoodJS, Spring + Boot) skip this and use `quickstart_create_project.mdx` alone — add a + one-line note stating the guide uses the framework's own tables instead, so + the omission reads as deliberate rather than a gap. +2. **Create a `` app** +3. **Set up AI tooling (optional)** — `<$Partial path="quickstart_ai_tooling.mdx" />`. + Covers both Agent Skills and the MCP server in one step. Keep them together: + two adjacent optional AI steps push the first real Supabase code further down + the page for no reader benefit, and the prose is identical across all 19 guides, + so it lives in the partial rather than being copied per guide. +4. **Install the Supabase client library** + - Guides that start from a scaffold which already depends on `supabase-js` + keep the step but retitle it to what the reader actually does. `hono.mdx` + uses **Install dependencies**, because `npx supabase bootstrap hono` already + lists the packages in `package.json` and the reader only runs `npm install`. + `nextjs.mdx` drops the step entirely, because the `with-supabase` template + installs them as part of step 3. +5. **Declare Supabase environment variables** — env vars only, never literal + credentials in code. Mobile guides (Flutter, iOS SwiftUI, Kotlin) are the + documented exception — they use `YOUR_SUPABASE_URL` / `YOUR_SUPABASE_PUBLISHABLE_KEY` + placeholder substitution instead of a `.env` file, with + `<$Partial path="quickstart_mobile_env_note.mdx" />` explaining why. Include the + ` <$Partial path="api_settings.mdx" variables={{ "framework": "", "tab": "" }} /> -## 7. Start the app +## 7. Set up anonymous sign-ins -Start the app, go to http://localhost:5173. +This app signs users in anonymously, so [enable anonymous sign-ins](/dashboard/project/_/auth/providers) in the Auth settings. -Learn how [server side auth](/docs/guides/auth/server-side/creating-a-client?queryGroups=framework&framework=hono) works with Hono. +Anonymous sign-ins use the `authenticated` role, but the database setup in step 2 grants read access to the `anon` role only. Without the privilege and a matching policy for `authenticated`, the instruments query returns no rows. Run the following in the [SQL Editor](/dashboard/project/_/sql/new) to grant the privilege and add the policy: + +```sql SQL_EDITOR +grant select on public.instruments to authenticated; + +create policy "authenticated can read instruments" +on public.instruments +for select to authenticated +using (true); +``` + +## 8. Query data from the app + +The bootstrapped app already includes the route that reads your `instruments` table, in `src/index.tsx`. The middleware in `src/middleware/auth.middleware.ts` creates a request-scoped Supabase client, so `getSupabase(c)` returns a client that already carries the signed-in user's auth token. Your RLS policies apply to the query. + +```tsx name=src/index.tsx +app.get('/instruments', async (c) => { + const supabase = getSupabase(c) + const { data, error } = await supabase.from('instruments').select('*') + + if (error) { + console.error(error) + return c.json({ error: error.message }, 500) + } + + return c.json(data) +}) +``` + +## 9. Start the app + +Start the app, go to http://localhost:5173, sign in anonymously, then open the instruments list. ```bash npm run dev ``` +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps - Learn how [server side auth](/docs/guides/auth/server-side/creating-a-client?queryGroups=framework&framework=hono) works with Hono. diff --git a/apps/docs/content/guides/getting-started/quickstarts/ios-swiftui.mdx b/apps/docs/content/guides/getting-started/quickstarts/ios-swiftui.mdx index 99ed3f1d351..ab5adf65d3d 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/ios-swiftui.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/ios-swiftui.mdx @@ -12,17 +12,9 @@ breadcrumb: 'Framework Quickstarts' Select the **Xcode > New Project > iOS > App** menu item. -## 4. Install Supabase's Agent Skills (optional) +## 4. Set up AI tooling (optional) -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. - -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. - -To install, run the following command in the root of your project: - -```bash -npx skills add supabase/agent-skills -``` +<$Partial path="quickstart_ai_tooling.mdx" /> ## 5. Install the Supabase client library @@ -34,7 +26,7 @@ Make sure to add `Supabase` product package as a dependency to your application ## 6. Initialize the Supabase client -Create a new `Supabase.swift` file add a new Supabase instance using your project URL and publishable key, which you can get from the helper below, or [from the project **Connect** panel](/dashboard/project/_?showConnect=true&framework=swift&connectTab=mobiles): +Create a new `Supabase.swift` file and initialize a Supabase client using your project URL and publishable key, which you can get from the helper below, or [from the project **Connect** panel](/dashboard/project/_?showConnect=true&framework=swift&connectTab=mobiles): ```kotlin +import io.github.jan.supabase.postgrest.from import ... val supabase = createSupabaseClient( - supabaseUrl = "https://xyzcompany.supabase.co", - supabaseKey = "your_publishable_key" + supabaseUrl = "YOUR_SUPABASE_URL", + supabaseKey = "YOUR_SUPABASE_PUBLISHABLE_KEY" ) { install(Postgrest) } @@ -88,6 +97,8 @@ val supabase = createSupabaseClient( <$Partial path="api_settings.mdx" variables={{ "framework": "androidkotlin", "tab": "mobiles" }} /> +<$Partial path="quickstart_mobile_env_note.mdx" /> + ## 8. Create a data model for instruments Create a serializable data class to represent the data from the database. @@ -95,6 +106,8 @@ Create a serializable data class to represent the data from the database. Add the following below the `createSupabaseClient` function in the `MainActivity.kt` file. ```kotlin +import kotlinx.serialization.Serializable + @Serializable data class Instrument( val id: Int, @@ -114,19 +127,23 @@ This example application makes a network request from the UI code. In production + + +This snippet omits the app-specific theme wrapper that Android Studio generates (named after your project, e.g. `Theme`), so it compiles regardless of what you named your project. Wrap the `Surface` in your generated theme composable from `ui/theme/Theme.kt` if you want your project's Material theme applied. + + + ```kotlin class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { - SupabaseTutorialTheme { - // A surface container using the 'background' color from the theme - Surface( - modifier = Modifier.fillMaxSize(), - color = MaterialTheme.colorScheme.background - ) { - InstrumentsList() - } + // A surface container using the 'background' color from the theme + Surface( + modifier = Modifier.fillMaxSize(), + color = MaterialTheme.colorScheme.background + ) { + InstrumentsList() } } } @@ -135,12 +152,24 @@ class MainActivity : ComponentActivity() { @Composable fun InstrumentsList() { var instruments by remember { mutableStateOf>(listOf()) } + var error by remember { mutableStateOf(null) } LaunchedEffect(Unit) { withContext(Dispatchers.IO) { - instruments = supabase.from("instruments") - .select().decodeList() + try { + instruments = supabase.from("instruments") + .select().decodeList() + } catch (e: Exception) { + error = e.message + } } } + if (error != null) { + Text( + "Error loading instruments: $error", + modifier = Modifier.padding(8.dp), + ) + return + } LazyColumn { items( instruments, @@ -159,6 +188,8 @@ fun InstrumentsList() { Run the app on an emulator or a physical device by clicking the `Run app` button in Android Studio. +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps - Learn how to build a complete user management app with authentication in the [Kotlin tutorial](/docs/guides/getting-started/tutorials/with-kotlin) diff --git a/apps/docs/content/guides/getting-started/quickstarts/laravel.mdx b/apps/docs/content/guides/getting-started/quickstarts/laravel.mdx index 9e4d868bc29..cce73dd2790 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/laravel.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/laravel.mdx @@ -6,65 +6,61 @@ breadcrumb: 'Framework Quickstarts' -<$Partial path="quickstart_db_setup.mdx" /> +<$Partial path="quickstart_create_project.mdx" /> -## 3. Create a Laravel project +Save your database password securely. You need it for the connection string. + + + +This guide uses Laravel's own database tables (via Breeze and Eloquent), not the shared `instruments` sample table used by other quickstarts. + + + +## 2. Create a Laravel project Make sure your PHP and Composer versions are up to date, then use `composer create-project` to scaffold a new Laravel project. -See the [Laravel docs](https://laravel.com/docs/10.x/installation#creating-a-laravel-project) for more details. +See the [Laravel docs](https://laravel.com/docs/12.x/installation#creating-a-laravel-project) for more details. ```bash composer create-project laravel/laravel example-app ``` -## 4. Install Supabase's Agent Skills (optional) +## 3. Set up AI tooling (optional) -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. +<$Partial path="quickstart_ai_tooling.mdx" /> -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. +## 4. Install the authentication template -To install, run the following command in the root of your project: - -```bash -npx skills add supabase/agent-skills -``` - -## 5. Install the authentication template - -Install [Laravel Breeze](https://laravel.com/docs/10.x/starter-kits#laravel-breeze), a basic implementation of all of Laravel's [authentication features](https://laravel.com/docs/10.x/authentication). +Install [Laravel Breeze](https://github.com/laravel/breeze), a basic implementation of all of Laravel's [authentication features](https://laravel.com/docs/12.x/authentication). It ships the migrations that the next step runs against your Supabase database. ```bash composer require laravel/breeze --dev -php artisan breeze:install +php artisan breeze:install blade ``` -## 6. Set up the Postgres connection details +Pass a stack name such as `blade`, `react`, or `vue` when prompted. The example above uses Blade templates. -Navigate to your project dashboard and click on [Connect](/dashboard/project/_?showConnect=true&connectTab=direct&method=session). +## 5. Set up the Postgres connection details -Look for the Session Pooler connection string and copy the string. You will need to replace the Password with your saved database password. You can reset your database password in your [Database Settings](/dashboard/project/_/database/settings) if you do not have it. - - - -If you're in an [IPv6 environment](https://github.com/orgs/supabase/discussions/27034) or have the IPv4 Add-On, you can use the direct connection string instead of Supavisor in Session mode. - - +<$Partial path="quickstart_connection_string.mdx" /> ```bash name=.env DB_CONNECTION=pgsql -DB_URL=postgres://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@aws-[REGION].pooler.supabase.com:5432/postgres +DB_URL=postgres://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@[POOLER-HOST]:5432/postgres ``` -## 7. Change the default schema +Laravel sets `sslmode` as an explicit `config/database.php` option rather than a URL parameter. The next step covers this. + +## 6. Change the default schema By default Laravel uses the `public` schema. We recommend changing this as Supabase exposes the `public` schema as a [data API](/docs/guides/api). -You can change the schema of your Laravel application by modifying the `search_path` variable `app/config/database.php`. +You can change the schema of your Laravel application by modifying the `search_path` variable in `config/database.php`. The schema you specify in `search_path` has to exist on Supabase. You can create a new schema from the [Table Editor](/dashboard/project/_/editor). -```php name=app/config/database.php +```php name=config/database.php 'pgsql' => [ 'driver' => 'pgsql', 'url' => env('DB_URL'), @@ -83,17 +79,21 @@ The schema you specify in `search_path` has to exist on Supabase. You can create Laravel ships with `sslmode` set to `prefer`, which sends your data in plaintext if the encrypted attempt fails. Set it to `require` so the connection fails instead. You can also [enforce SSL](/docs/guides/platform/ssl-enforcement) on the database side. -## 8. Run the database migrations +## 7. Run the database migrations Laravel ships with database migration files that set up the required tables for Laravel Authentication and User Management. -Note: Laravel does not use Supabase Auth but rather implements its own authentication system! + + +Laravel implements its own authentication system rather than using Supabase Auth. Your users are stored in Laravel's `users` table, not in Supabase Auth. + + ```bash php artisan migrate ``` -## 9. Start the app +## 8. Start the app Run the development server. Go to http://127.0.0.1:8000 in a browser to see your application. You can also navigate to http://127.0.0.1:8000/register and http://127.0.0.1:8000/login to register and log in users. @@ -101,6 +101,8 @@ Run the development server. Go to http://127.0.0.1:8000 in a browser to see your php artisan serve ``` +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps - Learn more about [Supabase Auth](/docs/guides/auth) if you want to replace Laravel's built-in authentication diff --git a/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx b/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx index af16da8b6cb..9ca784530e1 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/nextjs.mdx @@ -13,20 +13,12 @@ breadcrumb: 'Framework Quickstarts' Use the `create-next-app` command and the `with-supabase` template, to create a Next.js app pre-configured with [Cookie-based Auth](/docs/guides/auth/server-side/creating-a-client?queryGroups=package-manager&package-manager=npm&queryGroups=framework&framework=nextjs&queryGroups=environment&environment=server), [TypeScript](https://www.typescriptlang.org/), and [Tailwind CSS](https://tailwindcss.com/). ```bash -npx create-next-app -e with-supabase +npx create-next-app@latest my-app -e with-supabase ``` -## 4. Install Supabase's Agent Skills (optional) +## 4. Set up AI tooling (optional) -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. - -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. - -To install, run the following command in the root of your project: - -```bash -npx skills add supabase/agent-skills -``` +<$Partial path="quickstart_ai_tooling.mdx" /> ## 5. Declare Supabase environment variables @@ -45,7 +37,37 @@ NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY= <$Partial path="api_settings.mdx" variables={{ "framework": "nextjs", "tab": "frameworks" }} /> -## 6. Query Supabase data from Next.js +## 6. Allow public access to the instruments page + +The `with-supabase` template redirects unauthenticated visitors to the login page for most routes. The `instruments` table is publicly readable, so update `lib/supabase/proxy.ts` to skip that redirect for `/instruments`. + +Find this `if` statement: + +```ts name=lib/supabase/proxy.ts + if ( + request.nextUrl.pathname !== "/" && + !user && + !request.nextUrl.pathname.startsWith("/login") && + !request.nextUrl.pathname.startsWith("/auth") + ) { +``` + +Add a condition for `/instruments`: + +```ts name=lib/supabase/proxy.ts + if ( + request.nextUrl.pathname !== "/" && + !user && + !request.nextUrl.pathname.startsWith("/login") && + !request.nextUrl.pathname.startsWith("/auth") && + request.nextUrl.pathname !== "/instruments" && + !request.nextUrl.pathname.startsWith("/instruments/") + ) { +``` + +## 7. Query Supabase data from Next.js + +The `with-supabase` template already installs `@supabase/supabase-js` and `@supabase/ssr` and creates the clients for you, in `lib/supabase/client.ts` for the browser and `lib/supabase/server.ts` for Server Components. The code below imports the server client from there. Create a new file at `app/instruments/page.tsx` and populate with the following. @@ -59,7 +81,11 @@ import { Suspense } from "react"; async function InstrumentsData() { const supabase = await createClient(); - const { data: instruments } = await supabase.from("instruments").select(); + const { data: instruments, error } = await supabase.from("instruments").select(); + + if (error) { + return

Error loading instruments: {error.message}

; + } return
{JSON.stringify(instruments, null, 2)}
; } @@ -75,7 +101,7 @@ export default function Instruments() { -## 7. Start the app +## 8. Start the app Run the development server, go to http://localhost:3000/instruments in a browser and you should see the list of instruments. @@ -83,9 +109,11 @@ Run the development server, go to http://localhost:3000/instruments in a browser npm run dev ``` +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps -- Explore [drop-in UI components](/ui) for your Supabase app - Set up [Auth](/docs/guides/auth) for your app - [Insert more data](/docs/guides/database/import-data) into your database - Upload and serve static files using [Storage](/docs/guides/storage) +- Explore [drop-in UI components](/ui) for your Supabase app diff --git a/apps/docs/content/guides/getting-started/quickstarts/nuxtjs.mdx b/apps/docs/content/guides/getting-started/quickstarts/nuxtjs.mdx index f8db14935c5..3d282e492b9 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/nuxtjs.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/nuxtjs.mdx @@ -16,18 +16,20 @@ Create a Nuxt app using the `npx nuxi` command. npx nuxi@latest init my-app ``` -## 4. Install Supabase's Agent Skills (optional) + -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. - -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. - -To install, run the following command in the root of your project: +The CLI prompts for a template, a package manager, and whether to initialize a git repository. Choose a minimal template, or pass flags to skip the prompts (required in non-interactive shells): ```bash -npx skills add supabase/agent-skills +npx nuxi@latest init my-app --template minimal --no-gitInit --packageManager npm ``` + + +## 4. Set up AI tooling (optional) + +<$Partial path="quickstart_ai_tooling.mdx" /> + ## 5. Install the Supabase client library The fastest way to get started is to use the `supabase-js` client library which provides a convenient interface for working with Supabase from a Nuxt app. @@ -70,20 +72,37 @@ export default defineNuxtConfig({ <$Partial path="api_settings.mdx" variables={{ "framework": "nuxt", "tab": "frameworks" }} /> -## 7. Query data from the app +## 7. Create the Supabase client -In `app.vue`, create a Supabase client using your config values and replace the existing content with the following code. +Create a composable at `app/composables/useSupabase.ts` that builds the client from your config values. `useRuntimeConfig()` is only available inside a Nuxt context, such as a composable or a component's `setup`, so the client is created there rather than at the top level of a module. Nuxt auto-imports anything in `app/composables/`, so you don't need to import `useSupabase` where you use it. -```vue name=app.vue - ``` -## 8. Start the app + + +This example fetches data in `onMounted`, so the instrument list appears after the page loads in the browser. + + + +## 9. Start the app Start the app, navigate to http://localhost:3000 in the browser, and you should see the list of instruments. @@ -113,9 +139,11 @@ The community-maintained [@nuxtjs/supabase](https://supabase.nuxtjs.org/) module +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps -- Explore [drop-in UI components](/ui) for your Supabase app - Set up [Auth](/docs/guides/auth) for your app - [Insert more data](/docs/guides/database/import-data) into your database - Upload and serve static files using [Storage](/docs/guides/storage) +- Explore [drop-in UI components](/ui) for your Supabase app diff --git a/apps/docs/content/guides/getting-started/quickstarts/reactjs.mdx b/apps/docs/content/guides/getting-started/quickstarts/reactjs.mdx index 03ba4f2da3f..804bf92b434 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/reactjs.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/reactjs.mdx @@ -16,17 +16,9 @@ Create a React app using a [Vite](https://vitejs.dev/guide/) template. npm create vite@latest my-app -- --template react ``` -## 4. Install Supabase's Agent Skills (optional) +## 4. Set up AI tooling (optional) -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. - -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. - -To install, run the following command in the root of your project: - -```bash -npx skills add supabase/agent-skills -``` +<$Partial path="quickstart_ai_tooling.mdx" /> ## 5. Install the Supabase client library @@ -55,18 +47,27 @@ VITE_SUPABASE_PUBLISHABLE_KEY= <$Partial path="api_settings.mdx" variables={{ "framework": "react", "tab": "frameworks" }} /> -## 7. Query data from the app +## 7. Create the Supabase client -Replace the contents of `App.jsx` with a `getInstruments` function that fetches the data and displays the query result on the page using a Supabase client. +Create a `src/lib` directory in your React app, create a file called `supabaseClient.js`, and add the following code to initialize the Supabase client: + +```js name=src/lib/supabaseClient.js +import { createClient } from '@supabase/supabase-js' + +const supabaseUrl = import.meta.env.VITE_SUPABASE_URL +const supabasePublishableKey = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY + +export const supabase = createClient(supabaseUrl, supabasePublishableKey) +``` + +## 8. Query data from the app + +Replace the contents of `App.jsx` with a `getInstruments` function that fetches the data and displays the query result on the page. ```js name=src/App.jsx -import { createClient } from '@supabase/supabase-js' import { useEffect, useState } from 'react' -const supabase = createClient( - import.meta.env.VITE_SUPABASE_URL, - import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY -) +import { supabase } from './lib/supabaseClient' function App() { const [instruments, setInstruments] = useState([]) @@ -89,7 +90,7 @@ function App() { return (
    {instruments.map((instrument) => ( -
  • {instrument.name}
  • +
  • {instrument.name}
  • ))}
) @@ -98,7 +99,7 @@ function App() { export default App ``` -## 8. Start the app +## 9. Start the app Run the development server, go to http://localhost:5173 in a browser, and you should see the list of instruments. @@ -106,9 +107,11 @@ Run the development server, go to http://localhost:5173 in a browser, and you sh npm run dev ``` +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps -- Explore [drop-in UI components](/ui) for your Supabase app - Set up [Auth](/docs/guides/auth) for your app - [Insert more data](/docs/guides/database/import-data) into your database - Upload and serve static files using [Storage](/docs/guides/storage) +- Explore [drop-in UI components](/ui) for your Supabase app diff --git a/apps/docs/content/guides/getting-started/quickstarts/redwoodjs.mdx b/apps/docs/content/guides/getting-started/quickstarts/redwoodjs.mdx index 4de86295730..5ece18913c9 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/redwoodjs.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/redwoodjs.mdx @@ -10,6 +10,12 @@ breadcrumb: 'Framework Quickstarts' Save your database password securely. You need it for the connection string. + + +This quickstart uses Prisma migrations against your Postgres database. Use a **dedicated Supabase project** (or an empty database) so Prisma does not try to reconcile tables created by other apps or quickstarts. + + + ## 2. Gather database connection strings Open the project [**Connect** panel](/dashboard/project/_?showConnect=true&connectTab=direct). This quickstart connects using the [**Transaction pooler**](/dashboard/project/_?showConnect=true&connectTab=direct&method=transaction) and [**Session pooler**](/dashboard/project/_?showConnect=true&connectTab=direct&method=session) mode. Transaction mode is used for application queries and Session mode is used for running migrations with Prisma. @@ -18,7 +24,7 @@ To do this, set the connection mode to `Transaction` in the [Database Settings p To get the Session mode connection pooler string, change the port of the connection string from the dashboard to 5432. -You will need the Transaction mode connection string and the Session mode connection string to set up environment variables in Step 6. +You will need the Transaction mode connection string and the Session mode connection string to set up environment variables in Step 5. @@ -34,31 +40,21 @@ Create a RedwoodJS app with TypeScript. The [`yarn` package manager](https://yarnpkg.com) is required to create a RedwoodJS app. You will use it to run RedwoodJS commands later. -While TypeScript is recommended, If you want a JavaScript app, omit the `--ts` flag. +While TypeScript is recommended, if you want a JavaScript app, omit the `--ts` flag. + +RedwoodJS 8.x officially supports Node `20.x`. On Node 22 or later, `create-redwood-app` may prompt you to override the version check. Select **Override error and continue install**, or switch to Node 20 with a version manager such as [`nvm`](https://github.com/nvm-sh/nvm). ```bash -yarn create redwood-app my-app --ts +yarn create redwood-app my-app --ts --git-init false ``` -## 4. Install Supabase's Agent Skills (optional) +## 4. Set up AI tooling (optional) -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. +<$Partial path="quickstart_ai_tooling.mdx" /> -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. - -To install, run the following command in the root of your project: - -```bash -npx skills add supabase/agent-skills -``` - -## 5. Install MCP server (optional) - -The Supabase MCP server connects AI assistants to Supabase, allowing you to interact with your projects on your behalf. Find out more on how to add it to your client in [the MCP docs](/docs/guides/ai-tools/mcp). - -## 6. Configure environment variables +## 5. Configure environment variables In your `.env` file, add the following environment variables for your database connection: @@ -67,18 +63,18 @@ In your `.env` file, add the following environment variables for your database c - The `DIRECT_URL` should use the Session mode connection string you copied in Step 2. ```bash name=.env -# Transaction mode connection string — used by Prisma Client for app queries -DATABASE_URL="postgres://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@aws-[REGION].pooler.supabase.com:6543/postgres?pgbouncer=true&connection_limit=1" +# Transaction mode connection string for Prisma Client app queries +DATABASE_URL="postgres://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@[POOLER-HOST]:6543/postgres?pgbouncer=true&connection_limit=1" -# Session mode connection string — used by Prisma Migrate -DIRECT_URL="postgres://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@aws-[REGION].pooler.supabase.com:5432/postgres" +# Session mode connection string for Prisma Migrate +DIRECT_URL="postgres://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@[POOLER-HOST]:5432/postgres" ``` -## 7. Update your Prisma schema +## 6. Update your Prisma schema By default, RedwoodJS ships with a SQLite database, but we want to use Postgres. -Update your Prisma schema file `api/db/schema.prisma` to use your Supabase Postgres database connection environment variables you set up in Step 6. +Update your Prisma schema file `api/db/schema.prisma` to use your Supabase Postgres database connection environment variables you set up in Step 5. ```prisma name=api/db/schema.prisma datasource db { @@ -88,10 +84,16 @@ datasource db { } ``` -## 8. Create the instrument model and apply a schema migration +## 7. Create the instrument model and apply a schema migration Create the Instrument model in `api/db/schema.prisma` and then run `yarn rw prisma migrate dev` from your terminal to apply the migration. + + +`yarn rw prisma migrate dev` requires an interactive terminal. It prompts for a migration name and cannot run in fully non-interactive CI shells. + + + ```prisma name=api/db/schema.prisma model Instrument { id Int @id @default(autoincrement()) @@ -99,7 +101,7 @@ model Instrument { } ``` -## 9. Update seed script +## 8. Update seed script Seed the database with a few instruments. @@ -128,7 +130,7 @@ export default async () => { } ``` -## 10. Seed your database +## 9. Seed your database Run the seed database command to populate the `Instrument` table with the instruments you created. @@ -142,7 +144,7 @@ The reset database command `yarn rw prisma db reset` recreates the tables and al yarn rw prisma db seed ``` -## 11. Scaffold the instrument UI +## 10. Scaffold the instrument UI Use RedwoodJS generators to scaffold a CRUD UI for the `Instrument` model. @@ -150,16 +152,18 @@ Use RedwoodJS generators to scaffold a CRUD UI for the `Instrument` model. yarn rw g scaffold instrument ``` -## 12. Start the app +## 11. Start the app Start the app via `yarn rw dev`. A browser will open to the RedwoodJS Splash page. -## 13. View instruments UI +## 12. View instruments UI Click on `/instruments` to visit http://localhost:8910/instruments where should see the list of instruments. You may now edit, delete, and add new instruments using the scaffolded UI. +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps - Set up [Auth](/docs/guides/auth) for your app diff --git a/apps/docs/content/guides/getting-started/quickstarts/refine.mdx b/apps/docs/content/guides/getting-started/quickstarts/refine.mdx index d36cd46a83c..1d6921561d5 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/refine.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/refine.mdx @@ -18,18 +18,22 @@ The `refine-supabase` preset adds `@refinedev/supabase` supplementary package th npm create refine-app@latest -- --preset refine-supabase my-app ``` -## 4. Install Supabase's Agent Skills (optional) + -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. +The CLI may prompt for an email address. The `refine-supabase` preset also ships with demo Supabase credentials. Replace them in step 5 with your own project. -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. - -To install, run the following command in the root of your project: +To skip the email prompt in a non-interactive shell, pipe a blank line: ```bash -npx skills add supabase/agent-skills +printf '\n' | npm create refine-app@latest -- --preset refine-supabase my-app ``` + + +## 4. Set up AI tooling (optional) + +<$Partial path="quickstart_ai_tooling.mdx" /> + ## 5. Update `supabaseClient` with environment variables Create a `.env` file and populate it with your Supabase URL and publishable key, which you can get from the helper below, or [from the project **Connect** panel](/dashboard/project/_?showConnect=true&framework=refine&connectTab=frameworks). @@ -45,24 +49,15 @@ VITE_SUPABASE_URL= VITE_SUPABASE_PUBLISHABLE_KEY= ``` -Update `src/utility/supabaseClient.ts` to read the URL and publishable key from these environment variables. The `supabaseClient` is used in auth provider and data provider methods that allow the Refine app to connect to your Supabase backend. +The `refine-supabase` preset hardcodes Refine's own demo Supabase project in `src/providers/constants.ts`, and initializes the client from it in `src/providers/supabase-client.ts`. Replace the hardcoded values so the client reads your project credentials from the environment variables above instead: -```ts name=src/utility/supabaseClient.ts -import { createClient } from '@refinedev/supabase' - -const SUPABASE_URL = import.meta.env.VITE_SUPABASE_URL -const SUPABASE_KEY = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY - -export const supabaseClient = createClient(SUPABASE_URL, SUPABASE_KEY, { - db: { - schema: 'public', - }, - auth: { - persistSession: true, - }, -}) +```ts name=src/providers/constants.ts +export const SUPABASE_URL = import.meta.env.VITE_SUPABASE_URL +export const SUPABASE_KEY = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY ``` +The `supabaseClient` is used by the auth and data providers to connect your Refine app to Supabase. + <$Partial path="api_settings.mdx" variables={{ "framework": "refine", "tab": "frameworks" }} /> ## 6. Add instruments resource and pages @@ -71,7 +66,11 @@ Use the following code to automatically add resources and generate code for the This defines pages for `list`, `create`, `show` and `edit` actions inside the `src/pages/instruments/` directory with a `` component. -The `` component depends on `@refinedev/react-table` and `@refinedev/react-hook-form` packages. To avoid errors, you should install them as dependencies with `npm install @refinedev/react-table @refinedev/react-hook-form`. +The `` component depends on `@refinedev/react-table`, `@refinedev/react-hook-form`, and `react-live` packages. To avoid errors, install them as dependencies: + +```bash +npm install @refinedev/react-table @refinedev/react-hook-form react-live +``` @@ -103,26 +102,27 @@ import routerProvider, { NavigateToResource, UnsavedChangesNotifier, } from '@refinedev/react-router' -import { dataProvider, liveProvider } from '@refinedev/supabase' -import { BrowserRouter, Route, Routes } from 'react-router-dom' +import { liveProvider } from '@refinedev/supabase' +import { BrowserRouter, Route, Routes } from 'react-router' import './App.css' -import authProvider from './authProvider' +import authProvider from './providers/auth' +import { dataProvider } from './providers/data' +import { supabaseClient } from './providers/supabase-client' import { InstrumentsCreate, InstrumentsEdit, InstrumentsList, InstrumentsShow, } from './pages/instruments' -import { supabaseClient } from './utility' function App() { return ( + +These policies let anyone with your publishable key modify the `instruments` table. They exist so you can try the scaffolded UI against sample data. Scope writes to authenticated users before you put real data in this table. + + + +## 9. Start the app + +Run the development server, then open `/instruments` in your browser (Vite defaults to http://localhost:5173). You should see the instruments pages along the `/instruments` routes. You can edit and add new instruments using the Inferencer-generated UI. ```bash npm run dev @@ -171,6 +203,8 @@ npm run dev The Inferencer auto-generated code gives you a good starting point on which to keep building your `list`, `create`, `show` and `edit` pages. You can get these by clicking the `Show the auto-generated code` buttons in their respective pages. +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps - Set up [Auth](/docs/guides/auth) for your app diff --git a/apps/docs/content/guides/getting-started/quickstarts/ruby-on-rails.mdx b/apps/docs/content/guides/getting-started/quickstarts/ruby-on-rails.mdx index dc79d96a58e..15d7a9122fc 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/ruby-on-rails.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/ruby-on-rails.mdx @@ -10,6 +10,12 @@ breadcrumb: 'Framework Quickstarts' Save your database password securely. You need it for the connection string. + + +This guide uses Rails' own Active Record models and migrations, not the shared `instruments` sample table used by other quickstarts. + + + ## 2. Create a Rails project With your Ruby and Rails versions up to date, run `rails new` on your terminal to scaffold a new project. @@ -23,41 +29,21 @@ rails new blog -d=postgresql cd blog ``` -## 3. Install Supabase's Agent Skills (optional) +## 3. Set up AI tooling (optional) -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. +<$Partial path="quickstart_ai_tooling.mdx" /> -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. +## 4. Set up the Postgres connection details -To install, run the following command in the root of your project: +<$Partial path="quickstart_connection_string.mdx" /> + +Set the connection string as an environment variable. Rails reads `DATABASE_URL` from the environment and connects with it, so you don't need to edit `config/database.yml`. The export applies to the current shell session, so run it in the same shell as the Rails commands in the following steps. ```bash -npx skills add supabase/agent-skills +export DATABASE_URL=postgres://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@[POOLER-HOST]:5432/postgres?sslmode=require ``` -## 4. Install MCP server (optional) - -The Supabase MCP server connects AI assistants to Supabase, allowing you to interact with your projects on your behalf. Find out more on how to add it to your client in [the MCP docs](/docs/guides/ai-tools/mcp). - -## 5. Set up the Postgres connection details - -Navigate to your project dashboard and click on [Connect](/dashboard/project/_?showConnect=true&connectTab=direct&method=session). - -Look for the Session Pooler connection string and copy the string. You will need to replace the Password with your saved database password, and [percent-encode](https://en.wikipedia.org/wiki/Percent-encoding) any reserved characters it contains, such as `&`, `#`, `?`, or a space. You can reset your database password in your [Database Settings](/dashboard/project/_/database/settings) if you do not have it. - - - -If you're in an [IPv6 environment](https://github.com/orgs/supabase/discussions/27034) or have the IPv4 Add-On, you can use the direct connection string instead of Supavisor in Session mode. - - - -Set the connection string as an environment variable. Rails reads `DATABASE_URL` from the environment and connects with it, so you don't need to edit `config/database.yml`. The export applies to the current shell session, so run it in the same shell as the Rails commands in the following steps. `sslmode=require` stops the driver from falling back to sending your data in plaintext. - -```bash -export DATABASE_URL=postgres://postgres.[PROJECT-REF]:[YOUR-PASSWORD]@aws-[REGION].pooler.supabase.com:5432/postgres?sslmode=require -``` - -## 6. Create and run a database migration +## 5. Create and run a database migration Rails includes Active Record as the ORM as well as database migration tooling which generates the SQL migration files for you. @@ -68,7 +54,7 @@ bin/rails generate model Article title:string body:text bin/rails db:migrate ``` -## 7. Use the model to interact with the database +## 6. Use the model to interact with the database You can use the included Rails console to interact with the database. For example, you can create new entries or list all entries in a Model's table. @@ -83,7 +69,7 @@ article.save # Saves the entry to the database Article.all ``` -## 8. Start the app +## 7. Start the app Run the development server. Go to http://127.0.0.1:3000 in a browser to see your application running. @@ -91,6 +77,8 @@ Run the development server. Go to http://127.0.0.1:3000 in a browser to see your bin/rails server ``` +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps - Set up [Auth](/docs/guides/auth) for your app diff --git a/apps/docs/content/guides/getting-started/quickstarts/solidjs.mdx b/apps/docs/content/guides/getting-started/quickstarts/solidjs.mdx index 5b6b9662471..be6fc3f1eca 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/solidjs.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/solidjs.mdx @@ -13,21 +13,19 @@ breadcrumb: 'Framework Quickstarts' Create a SolidJS app using the `degit` command. ```bash -npx degit solidjs/templates/js my-app +npx degit solidjs/templates/vanilla/basic my-app ``` -## 4. Install Supabase's Agent Skills (optional) - -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. - -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. - -To install, run the following command in the root of your project: +The template ships with a `pnpm-lock.yaml`. Remove it so `npm install` in the next steps doesn't create a second, conflicting lockfile: ```bash -npx skills add supabase/agent-skills +rm my-app/pnpm-lock.yaml ``` +## 4. Set up AI tooling (optional) + +<$Partial path="quickstart_ai_tooling.mdx" /> + ## 5. Install the Supabase client library The fastest way to get started is to use the `supabase-js` client library which provides a convenient interface for working with Supabase from a SolidJS app. @@ -55,23 +53,35 @@ VITE_SUPABASE_PUBLISHABLE_KEY= <$Partial path="api_settings.mdx" variables={{ "framework": "solidjs", "tab": "frameworks" }} /> -## 7. Query data from the app +## 7. Create the Supabase client -In `App.jsx`, create a Supabase client to fetch the instruments data. +Create a `src/lib` directory in your SolidJS app, create a file called `supabaseClient.ts`, and add the following code to initialize the Supabase client: -Add a `getInstruments` function to fetch the data and display the query result to the page. - -```jsx name=src/App.jsx +```ts name=src/lib/supabaseClient.ts import { createClient } from '@supabase/supabase-js' -import { createResource, For } from 'solid-js' -const supabase = createClient( - import.meta.env.VITE_SUPABASE_URL, - import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY -) +const supabaseUrl = import.meta.env.VITE_SUPABASE_URL +const supabasePublishableKey = import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY + +export const supabase = createClient(supabaseUrl, supabasePublishableKey) +``` + +## 8. Query data from the app + +In `src/App.tsx`, add a `getInstruments` function to fetch the data and display the query result to the page. + +```tsx name=src/App.tsx +import { createResource, For, Show } from 'solid-js' + +import { supabase } from './lib/supabaseClient' async function getInstruments() { - const { data } = await supabase.from('instruments').select() + const { data, error } = await supabase.from('instruments').select() + + if (error) { + throw error + } + return data } @@ -79,16 +89,21 @@ function App() { const [instruments] = createResource(getInstruments) return ( -
    - {(instrument) =>
  • {instrument.name}
  • }
    -
+ Error loading instruments: {instruments.error?.message}

} + > +
    + {(instrument) =>
  • {instrument.name}
  • }
    +
+
) } export default App ``` -## 8. Start the app +## 9. Start the app Start the app and go to http://localhost:3000 in a browser and you should see the list of instruments. @@ -96,6 +111,8 @@ Start the app and go to http://localhost:3000 in a browser and you should see th npm run dev ``` +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps - Set up [Auth](/docs/guides/auth) for your app diff --git a/apps/docs/content/guides/getting-started/quickstarts/spring-boot.mdx b/apps/docs/content/guides/getting-started/quickstarts/spring-boot.mdx index 6093d91292a..84e57cdec81 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/spring-boot.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/spring-boot.mdx @@ -17,6 +17,12 @@ Before you begin, make sure you have: Save your database password securely. You need it for the connection string. + + +This guide uses Spring Boot's own JPA entities and generated schema, not the shared `instruments` sample table used by other quickstarts. + + + ## 2. Create a Spring Boot project Use [Spring Initializr](https://start.spring.io) to scaffold a new project with the Web, Spring Data JPA, and Postgres Driver dependencies. Run the following from the directory where you keep your projects. @@ -33,44 +39,22 @@ curl https://start.spring.io/starter.zip \ unzip instruments.zip -d instruments && cd instruments ``` -## 3. Install Supabase's Agent Skills (optional) +## 3. Set up AI tooling (optional) -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. - -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. - -To install, run the following command in the root of your project: - -```bash -npx skills add supabase/agent-skills -``` +<$Partial path="quickstart_ai_tooling.mdx" /> ## 4. Set up the Postgres connection details -Navigate to your project dashboard and click on [Connect](/dashboard/project/_?showConnect=true&connectTab=direct&method=session). +<$Partial path="quickstart_connection_string.mdx" /> - - -The Transaction pooler (port `6543`) doesn't work as your app's main data source, because Spring Data JPA uses Hibernate, which relies on server-side prepared statements. Use the Session pooler, or the direct connection string if you're in an [IPv6 environment](/docs/guides/troubleshooting/supabase--your-network-ipv4-and-ipv6-compatibility-cHe3BP) or have the [IPv4 Add-On](/docs/guides/platform/ipv4-address). - - - -Under the **Session pooler** (port `5432`), select the **JDBC** tab and copy the connection string. Replace the password placeholder with your saved database password, and [percent-encode](https://en.wikipedia.org/wiki/Percent-encoding) any reserved characters it contains, such as `&`, `#`, `?`, or a space. - - - -You can reset your database password in your [Database Settings](/dashboard/project/_/database/settings) if you do not have it. - - +Select the **JDBC** tab to copy the connection string in the right format for Spring Boot. The connection string contains your database password, and `application.properties` is committed with your project. Set the string as an environment variable instead, and set it the same way on whatever platform you deploy to. ```bash -export SUPABASE_DB_URL='jdbc:postgresql://aws-[REGION].pooler.supabase.com:5432/postgres?user=postgres.[PROJECT-REF]&password=[YOUR-PASSWORD]&sslmode=require' +export SUPABASE_DB_URL='jdbc:postgresql://[POOLER-HOST]:5432/postgres?user=postgres.[PROJECT-REF]&password=[YOUR-PASSWORD]&sslmode=require' ``` -The string you copied doesn't set `sslmode`, so add it. The driver defaults to `prefer`, which falls back to sending your data in plaintext if the encrypted attempt fails. You can also [enforce SSL](/docs/guides/platform/ssl-enforcement) on the database side. - Then reference the variable, along with the driver, in `src/main/resources/application.properties`. ```text name=src/main/resources/application.properties @@ -85,7 +69,13 @@ If the app fails to start with `Unable to determine Dialect without JDBC metadat By default Hibernate creates tables in the `public` schema. We recommend changing this as Supabase exposes the `public` schema as a [data API](/docs/guides/api). -Create the schema from the [Table Editor](/dashboard/project/_/editor) as your app will need it before start. Then point **Hibernate** at it in `application.properties`. +Create the `app` schema before you start the app. Hibernate creates tables in that schema on startup, but it does not create the schema itself. Run the following in the [SQL Editor](/dashboard/project/_/sql/new): + +```sql SQL_EDITOR +create schema if not exists app; +``` + +Then point Hibernate at the schema in `application.properties`. ```text name=src/main/resources/application.properties spring.jpa.properties.hibernate.default_schema=app @@ -212,9 +202,11 @@ Run the Spring Boot app, and go to http://localhost:8080/instruments in your bro ./mvnw spring-boot:run ``` +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps - Set up [Auth](/docs/guides/auth) for your app -- Replace `ddl-auto` with [database migrations](/docs/guides/deployment/database-migrations) before going to production - [Insert more data](/docs/guides/database/import-data) into your database - Upload and serve static files using [Storage](/docs/guides/storage) +- Replace `ddl-auto` with [database migrations](/docs/guides/deployment/database-migrations) before going to production diff --git a/apps/docs/content/guides/getting-started/quickstarts/sveltekit.mdx b/apps/docs/content/guides/getting-started/quickstarts/sveltekit.mdx index adc04d1e0c3..d512f518dc0 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/sveltekit.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/sveltekit.mdx @@ -10,23 +10,15 @@ breadcrumb: 'Framework Quickstarts' ## 3. Create a SvelteKit app -Create a SvelteKit app using the `npm create` command. +Create a SvelteKit app using the `sv` CLI. ```bash npx sv create my-app ``` -## 4. Install Supabase's Agent Skills (optional) +## 4. Set up AI tooling (optional) -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. - -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. - -To install, run the following command in the root of your project: - -```bash -npx skills add supabase/agent-skills -``` +<$Partial path="quickstart_ai_tooling.mdx" /> ## 5. Install the Supabase client library @@ -89,9 +81,16 @@ Create `+page.server.js` file in the `src/routes` directory with the following c import { supabase } from '$lib/supabaseClient' export async function load() { - const { data } = await supabase.from('instruments').select() + const { data, error } = await supabase.from('instruments').select() + + if (error) { + console.error('Error loading instruments:', error.message) + return { instruments: [], error: error.message } + } + return { instruments: data ?? [], + error: null, } } ``` @@ -107,15 +106,16 @@ type Instrument = { } export const load: PageServerLoad = async () => { - const { data, error } = await supabase.from('instruments').select<'instruments', Instrument>() + const { data, error } = await supabase.from('instruments').select<'*', Instrument>() if (error) { console.error('Error loading instruments:', error.message) - return { instruments: [] } + return { instruments: [], error: error.message } } return { instruments: data ?? [], + error: null, } } ``` @@ -129,11 +129,15 @@ Replace the existing content in your `+page.svelte` file in the `src/routes` dir let { data } = $props(); -
    - {#each data.instruments as instrument} -
  • {instrument.name}
  • - {/each} -
+{#if data.error} +

Error loading instruments: {data.error}

+{:else} +
    + {#each data.instruments as instrument} +
  • {instrument.name}
  • + {/each} +
+{/if} ``` ## 9. Start the app @@ -144,6 +148,8 @@ Start the app and go to http://localhost:5173 in a browser and you should see th npm run dev ``` +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps - Set up [Auth](/docs/guides/auth) for your app diff --git a/apps/docs/content/guides/getting-started/quickstarts/tanstack.mdx b/apps/docs/content/guides/getting-started/quickstarts/tanstack.mdx index ff9a466be80..9d0f220885f 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/tanstack.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/tanstack.mdx @@ -16,17 +16,9 @@ Create a TanStack Start app using the official CLI. npx @tanstack/cli@latest create my-app ``` -## 4. Install Supabase's Agent Skills (optional) +## 4. Set up AI tooling (optional) -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. - -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. - -To install, run the following command in the root of your project: - -```bash -npx skills add supabase/agent-skills -``` +<$Partial path="quickstart_ai_tooling.mdx" /> ## 5. Install the Supabase client libraries @@ -57,8 +49,10 @@ VITE_SUPABASE_PUBLISHABLE_KEY= TanStack Start needs two Supabase clients: a browser client for components that run in the browser, and a server client for loaders and server functions. Create a `src/lib/supabase` folder with a file for each client. +Both clients read the same two variables, through the API available in each environment. The browser client uses `import.meta.env`, which Vite replaces at build time. The server client uses `process.env`, which the server runtime populates from your `.env.local` file. + ```ts name=src/lib/supabase/client.ts -/// +/// import { createBrowserClient } from '@supabase/ssr' export function createClient() { @@ -99,29 +93,49 @@ export function createClient() { ## 8. Query Supabase data from TanStack Start -Replace the contents of `src/routes/index.tsx` with the following to add a loader that queries the `instruments` table through the server client. The loader runs on the server, so the data is part of the initial server-rendered response. +Create a server function that queries the `instruments` table through the server client. TanStack Start's import protection blocks direct server imports in route files, so wrap the Supabase call in `createServerFn`. + +```ts name=src/lib/supabase/fetch-instruments-server-fn.ts +import { createServerFn } from '@tanstack/react-start' + +import { createClient } from '@/lib/supabase/server' + +export const fetchInstruments = createServerFn({ method: 'GET' }).handler(async () => { + const supabase = createClient() + const { data: instruments, error } = await supabase.from('instruments').select() + + if (error) { + console.error(error) + return { instruments: [], error: error.message } + } + + return { instruments, error: null } +}) +``` + +Replace the contents of `src/routes/index.tsx` with the following to call the server function from a route loader. The loader runs on the server, so the data is part of the initial server-rendered response. ```tsx name=src/routes/index.tsx import { createFileRoute } from '@tanstack/react-router' -import { createClient } from '@/lib/supabase/server' +import { fetchInstruments } from '@/lib/supabase/fetch-instruments-server-fn' export const Route = createFileRoute('/')({ - loader: async () => { - const supabase = createClient() - const { data: instruments } = await supabase.from('instruments').select() - return { instruments } - }, + loader: async () => fetchInstruments(), component: Home, }) function Home() { - const { instruments } = Route.useLoaderData() + const { instruments, error } = Route.useLoaderData() + + if (error) { + return

Error loading instruments: {error}

+ } return (
    {instruments?.map((instrument) => ( -
  • {instrument.name}
  • +
  • {instrument.name}
  • ))}
) @@ -136,10 +150,11 @@ Run the development server, go to http://localhost:3000 in a browser and you sho npm run dev ``` +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps -- Learn how to [protect routes and check sessions](/docs/guides/auth/server-side/creating-a-client?queryGroups=framework&framework=tanstack) with the server client -- Set up a complete [login and sign-up flow](/library/docs/tanstack/password-based-auth) from Supabase Library -- Explore [drop-in UI components](/ui) for your Supabase app +- Learn how to [protect routes and check sessions](/docs/guides/auth/server-side/creating-a-client?queryGroups=framework&framework=tanstack) with the server client, or drop in a complete [login and sign-up flow](/library/docs/tanstack/password-based-auth) from Supabase Library - [Insert more data](/docs/guides/database/import-data) into your database - Upload and serve static files using [Storage](/docs/guides/storage) +- Explore [drop-in UI components](/ui) for your Supabase app diff --git a/apps/docs/content/guides/getting-started/quickstarts/vue.mdx b/apps/docs/content/guides/getting-started/quickstarts/vue.mdx index ff3b4c06480..3de10fe7e21 100644 --- a/apps/docs/content/guides/getting-started/quickstarts/vue.mdx +++ b/apps/docs/content/guides/getting-started/quickstarts/vue.mdx @@ -16,17 +16,9 @@ Create a Vue app using the `npm init` command. npm init vue@latest my-app ``` -## 4. Install Supabase's Agent Skills (optional) +## 4. Set up AI tooling (optional) -Supabase's [Agent Skills](/docs/guides/ai-tools/ai-skills) is a curated set of instructions that give your AI agent procedural knowledge about working with Supabase. - -Install them so your AI coding agent can produce more accurate, reliable code using current Supabase patterns, such as authentication, server-side rendering, and database migrations, rather than relying solely on training data. - -To install, run the following command in the root of your project: - -```bash -npx skills add supabase/agent-skills -``` +<$Partial path="quickstart_ai_tooling.mdx" /> ## 5. Install the Supabase client library @@ -57,9 +49,15 @@ VITE_SUPABASE_PUBLISHABLE_KEY= ## 7. Create the Supabase client -Create a `/src/lib` directory in your Vue app, create a file called `supabaseClient.js` and add the following code to initialize the Supabase client: +Create a `/src/lib` directory in your Vue app, create a file called `supabaseClient.ts` and add the following code to initialize the Supabase client: -```js name=src/lib/supabaseClient.js + + +`npm init vue@latest` scaffolds a TypeScript project by default. If you chose a JavaScript-only project, use a `.js` extension instead and drop the type import. + + + +```ts name=src/lib/supabaseClient.ts import { createClient } from '@supabase/supabase-js' const supabaseUrl = import.meta.env.VITE_SUPABASE_URL @@ -73,15 +71,27 @@ export const supabase = createClient(supabaseUrl, supabasePublishableKey) Replace the existing content in your `App.vue` file with the following code. ```vue name=src/App.vue - @@ -105,9 +116,11 @@ Start the app and go to http://localhost:5173 in a browser and you should see th npm run dev ``` +<$Partial path="quickstart_going_to_production.mdx" /> + ## Next steps -- Explore [drop-in UI components](/ui) for your Supabase app - Set up [Auth](/docs/guides/auth) for your app - [Insert more data](/docs/guides/database/import-data) into your database - Upload and serve static files using [Storage](/docs/guides/storage) +- Explore [drop-in UI components](/ui) for your Supabase app diff --git a/apps/docs/data/content-listings/getting-started.data.ts b/apps/docs/data/content-listings/getting-started.data.ts index 2d5ae192dce..07e7320a1df 100644 --- a/apps/docs/data/content-listings/getting-started.data.ts +++ b/apps/docs/data/content-listings/getting-started.data.ts @@ -65,7 +65,7 @@ export const gettingStartedFrameworkQuickstarts: ContentListingGroup = { icon: '/docs/img/icons/react-icon', hasLightIcon: false, description: - 'Learn how to create a Supabase project, add some sample data to your database, and query the data from a React app.', + 'Build single-page apps from reusable components, and query Supabase Postgres from the browser.', }, { title: 'Next.js', @@ -73,7 +73,7 @@ export const gettingStartedFrameworkQuickstarts: ContentListingGroup = { icon: '/docs/img/icons/nextjs-icon', hasLightIcon: true, description: - 'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Next.js app.', + 'Full-stack React with server rendering, wired to Supabase Postgres and cookie-based auth.', }, { title: 'Nuxt', @@ -81,7 +81,15 @@ export const gettingStartedFrameworkQuickstarts: ContentListingGroup = { icon: '/docs/img/icons/nuxt-icon', hasLightIcon: false, description: - 'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Nuxt app.', + 'Full-stack Vue with server rendering, reading Postgres through a Supabase composable.', + }, + { + title: 'Astro', + href: '/guides/getting-started/quickstarts/astrojs', + icon: '/docs/img/icons/astro-icon', + hasLightIcon: true, + description: + 'Content-driven sites that render on the server and pull Supabase Postgres data per request.', }, { title: 'Hono', @@ -89,7 +97,7 @@ export const gettingStartedFrameworkQuickstarts: ContentListingGroup = { icon: '/docs/img/icons/hono-icon', hasLightIcon: false, description: - 'Learn how to create a Supabase project, add some sample data to your database, secure it with auth, and query the data from a Hono app.', + 'Lightweight web APIs with Supabase Auth anonymous sign-in and RLS-protected reads.', }, { title: 'RedwoodJS', @@ -97,7 +105,15 @@ export const gettingStartedFrameworkQuickstarts: ContentListingGroup = { icon: '/docs/img/icons/redwood-icon', hasLightIcon: false, description: - 'Learn how to create a Supabase project, add some sample data to your database using Prisma migration and seeds, and query the data from a RedwoodJS app.', + 'Full-stack React and GraphQL, with Prisma migrations against your Supabase Postgres database.', + }, + { + title: 'Expo React Native', + href: '/guides/getting-started/quickstarts/expo-react-native', + icon: '/docs/img/icons/expo-icon', + hasLightIcon: true, + description: + 'Ship iOS and Android from one React Native codebase, backed by Supabase Postgres.', }, { title: 'Flutter', @@ -105,8 +121,7 @@ export const gettingStartedFrameworkQuickstarts: ContentListingGroup = { icon: '/docs/img/icons/flutter-icon', hasLightIcon: false, feature: 'sdk:dart', - description: - 'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Flutter app.', + description: 'Ship iOS and Android from one Dart codebase, backed by Supabase Postgres.', }, { title: 'iOS SwiftUI', @@ -114,8 +129,7 @@ export const gettingStartedFrameworkQuickstarts: ContentListingGroup = { icon: '/docs/img/icons/swift-icon', hasLightIcon: false, feature: 'sdk:swift', - description: - 'Learn how to create a Supabase project, add some sample data to your database, and query the data from an iOS app.', + description: 'Native iOS apps in Swift, reading Postgres through the Supabase Swift SDK.', }, { title: 'Android Kotlin', @@ -124,15 +138,14 @@ export const gettingStartedFrameworkQuickstarts: ContentListingGroup = { hasLightIcon: false, feature: 'sdk:kotlin', description: - 'Learn how to create a Supabase project, add some sample data to your database, and query the data from an Android Kotlin app.', + 'Native Android apps in Kotlin and Jetpack Compose, using the Supabase Kotlin SDK.', }, { title: 'SvelteKit', href: '/guides/getting-started/quickstarts/sveltekit', icon: '/docs/img/icons/svelte-icon', hasLightIcon: false, - description: - 'Learn how to create a Supabase project, add some sample data to your database, and query the data from a SvelteKit app.', + description: 'Full-stack Svelte that loads Supabase Postgres data in server load functions.', }, { title: 'SolidJS', @@ -140,7 +153,7 @@ export const gettingStartedFrameworkQuickstarts: ContentListingGroup = { icon: '/docs/img/icons/solidjs-icon', hasLightIcon: false, description: - 'Learn how to create a Supabase project, add some sample data to your database, and query the data from a SolidJS app.', + 'Fine-grained reactive UIs that load Supabase Postgres data with Solid resources.', }, { title: 'Vue', @@ -148,15 +161,14 @@ export const gettingStartedFrameworkQuickstarts: ContentListingGroup = { icon: '/docs/img/icons/vuejs-icon', hasLightIcon: false, description: - 'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Vue app.', + 'Build single-page apps with the Vue composition API, backed by Supabase Postgres.', }, { title: 'TanStack Start', href: '/guides/getting-started/quickstarts/tanstack', icon: '/docs/img/icons/tanstack-icon', hasLightIcon: true, - description: - 'Learn how to create a Supabase project, add some sample data to your database, and query the data from a TanStack Start app.', + description: 'Type-safe full-stack React that queries Supabase Postgres in server functions.', }, { title: 'Refine', @@ -164,7 +176,30 @@ export const gettingStartedFrameworkQuickstarts: ContentListingGroup = { icon: '/docs/img/icons/refine-icon', hasLightIcon: false, description: - 'Learn how to create a Supabase project, add some sample data to your database, and query the data from a Refine app.', + 'Scaffold CRUD dashboards and admin panels straight from your Supabase Postgres tables.', + }, + { + title: 'Python', + href: '/guides/getting-started/quickstarts/flask', + icon: '/docs/img/icons/python-icon', + hasLightIcon: false, + description: 'Serve Flask web apps that query Postgres with the Supabase Python client.', + }, + { + title: 'Laravel', + href: '/guides/getting-started/quickstarts/laravel', + icon: '/docs/img/icons/laravel-icon', + hasLightIcon: false, + description: + 'Full-stack PHP with Eloquent ORM connected directly to your Supabase Postgres database.', + }, + { + title: 'Ruby on Rails', + href: '/guides/getting-started/quickstarts/ruby-on-rails', + icon: '/docs/img/icons/rails-icon', + hasLightIcon: false, + description: + 'Convention-driven Ruby apps with Active Record connected directly to your Supabase Postgres database.', }, ], } diff --git a/apps/docs/public/img/icons/laravel-icon.svg b/apps/docs/public/img/icons/laravel-icon.svg new file mode 100644 index 00000000000..7b6ba90d83f --- /dev/null +++ b/apps/docs/public/img/icons/laravel-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/apps/docs/public/img/icons/rails-icon.svg b/apps/docs/public/img/icons/rails-icon.svg new file mode 100644 index 00000000000..ca2756f86f3 --- /dev/null +++ b/apps/docs/public/img/icons/rails-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/examples/auth/hono/package.json b/examples/auth/hono/package.json index b22cd49e2c9..3038a234fa2 100644 --- a/examples/auth/hono/package.json +++ b/examples/auth/hono/package.json @@ -15,6 +15,7 @@ "@hono/vite-build": "^1.1.0", "@hono/vite-dev-server": "^0.17.0", "@types/node": "^20.11.17", + "typescript": "^5.6.2", "vite": "^5.4.2" } } diff --git a/examples/auth/hono/src/client.tsx b/examples/auth/hono/src/client.tsx new file mode 100644 index 00000000000..a8ccf01c1bb --- /dev/null +++ b/examples/auth/hono/src/client.tsx @@ -0,0 +1,109 @@ +import type { AppType } from '.' +import { createBrowserClient } from '@supabase/ssr' +import { hc } from 'hono/client' +import { useEffect, useState } from 'hono/jsx' +import { render } from 'hono/jsx/dom' + +const client = hc('/') + +const supabase = createBrowserClient( + import.meta.env.VITE_SUPABASE_URL!, + import.meta.env.VITE_SUPABASE_PUBLISHABLE_KEY! +) + +function App() { + const [user, setUser] = useState(null) + // Check client-side if user is logged in: + useEffect(() => { + const { + data: { subscription }, + } = supabase.auth.onAuthStateChange((event, session) => { + console.log('Auth event:', event) + if (event === 'SIGNED_OUT') { + setUser(null) + } else { + setUser(session?.user!) + } + }) + + return () => subscription.unsubscribe() + }, []) + + return ( + <> +

Hono Supabase Auth Example!

+

Sign in

+ {!user ? ( + + ) : ( +
+ +
+ )} +

Example of API fetch()

+ +

Example of database read

+

Sign in anonymously, then open the instruments list.

+
Get instruments + + ) +} + +function SignIn() { + return ( + <> +

+ Read about and enable{' '} + + anonymous sign-ins here! + +

+ + + ) +} + +const UserDetailsButton = () => { + const [response, setResponse] = useState(null) + + const handleClick = async () => { + const response = await client.api.user.$get() + const data = await response.json() + const headers = Array.from(response.headers.entries()).reduce>( + (acc, [key, value]) => { + acc[key] = value + return acc + }, + {} + ) + const fullResponse = { + url: response.url, + status: response.status, + headers, + body: data, + } + setResponse(JSON.stringify(fullResponse, null, 2)) + } + + return ( +
+ + {response &&
{response}
} +
+ ) +} + +const root = document.getElementById('root')! +render(, root) diff --git a/examples/auth/hono/src/index.tsx b/examples/auth/hono/src/index.tsx index 9a97606c35a..584a57dda76 100644 --- a/examples/auth/hono/src/index.tsx +++ b/examples/auth/hono/src/index.tsx @@ -1,16 +1,19 @@ import { Hono } from 'hono' +import { csrf } from 'hono/csrf' + import { getSupabase, supabaseMiddleware } from './middleware/auth.middleware' const app = new Hono() +app.use('*', csrf()) app.use('*', supabaseMiddleware()) -app.get('/api/user', async (c) => { +const routes = app.get('/api/user', async (c) => { const supabase = getSupabase(c) const { data, error } = await supabase.auth.getClaims() if (error) console.log('error', error) - if (!data?.user) { + if (!data?.claims) { return c.json({ message: 'You are not logged in.', }) @@ -18,23 +21,49 @@ app.get('/api/user', async (c) => { return c.json({ message: 'You are logged in!', - userId: data.user, + userId: data.claims.sub, }) }) -app.get('/signout', async (c) => { +app.post('/signout', async (c) => { const supabase = getSupabase(c) await supabase.auth.signOut() console.log('Signed out server-side!') - return c.redirect('/') + return c.redirect('/', 303) }) -// Retrieve data with RLS enabled. The signed in user's auth token is automatically sent. -app.get('/countries', async (c) => { +app.get('/instruments', async (c) => { const supabase = getSupabase(c) - const { data, error } = await supabase.from('countries').select('*') - if (error) console.log(error) + const { data, error } = await supabase.from('instruments').select('*') + + if (error) { + console.error(error) + return c.json({ error: error.message }, 500) + } + return c.json(data) }) +export type AppType = typeof routes + +app.get('/', (c) => { + return c.html( + + + + + + {import.meta.env.PROD ? ( +