From b2497cefb86dc2377988955ef0a71cc6f7e810aa Mon Sep 17 00:00:00 2001 From: Terry Sutton Date: Wed, 5 Nov 2025 17:07:20 -0330 Subject: [PATCH] Add db and auth pages --- apps/learn/components/side-navigation.tsx | 6 +- apps/learn/config/docs.ts | 20 ++- .../content/foundations/authentication.mdx | 103 +++++++++++++ .../content/foundations/data-fundamentals.mdx | 142 ++++++++++++++---- .../content/foundations/edge-functions.mdx | 136 +++++++++++++++++ apps/learn/content/foundations/security.mdx | 136 +++++++++++++++++ apps/learn/content/foundations/storage.mdx | 136 +++++++++++++++++ apps/learn/content/foundations/vector.mdx | 136 +++++++++++++++++ apps/learn/lib/get-next-page.ts | 9 +- 9 files changed, 786 insertions(+), 38 deletions(-) create mode 100644 apps/learn/content/foundations/authentication.mdx create mode 100644 apps/learn/content/foundations/edge-functions.mdx create mode 100644 apps/learn/content/foundations/security.mdx create mode 100644 apps/learn/content/foundations/storage.mdx create mode 100644 apps/learn/content/foundations/vector.mdx diff --git a/apps/learn/components/side-navigation.tsx b/apps/learn/components/side-navigation.tsx index 644b91673af..770771f7e24 100644 --- a/apps/learn/components/side-navigation.tsx +++ b/apps/learn/components/side-navigation.tsx @@ -1,7 +1,7 @@ import Link from 'next/link' import NavigationItem from '@/components/side-navigation-item' -import { gettingStarted } from '@/config/docs' +import { courses } from '@/config/docs' import { CommandMenu } from './command-menu' import { ThemeSwitcherDropdown } from './theme-switcher-dropdown' @@ -68,10 +68,10 @@ function SideNavigation() {

- {gettingStarted.title} + {courses.title}

diff --git a/apps/learn/config/docs.ts b/apps/learn/config/docs.ts index 3b9b0173ac0..60c2586aeec 100644 --- a/apps/learn/config/docs.ts +++ b/apps/learn/config/docs.ts @@ -1,6 +1,6 @@ import { SidebarNavGroup } from 'types/nav' -export const gettingStarted: SidebarNavGroup = { +export const courses: SidebarNavGroup = { title: 'Courses', items: [ { @@ -23,6 +23,22 @@ export const gettingStarted: SidebarNavGroup = { title: 'Authentication', href: '/foundations/authentication', }, + { + title: 'Security', + href: '/foundations/security', + }, + { + title: 'Storage', + href: '/foundations/storage', + }, + { + title: 'Edge Functions', + href: '/foundations/edge-functions', + }, + { + title: 'Vector Search', + href: '/foundations/vector-search', + }, ], commandItemLabel: 'Foundations', }, @@ -45,7 +61,7 @@ export const gettingStarted: SidebarNavGroup = { } export const COMMAND_ITEMS = [ - ...gettingStarted.items.map((item) => ({ + ...courses.items.map((item) => ({ label: item.commandItemLabel, href: item.href, })), diff --git a/apps/learn/content/foundations/authentication.mdx b/apps/learn/content/foundations/authentication.mdx new file mode 100644 index 00000000000..f195be17b0b --- /dev/null +++ b/apps/learn/content/foundations/authentication.mdx @@ -0,0 +1,103 @@ +--- +title: Authentication +description: Learn how Supabase manages users and how signed-in requests connect to the database. +chapterNumber: 3 +--- + +Most applications need to know who is using them. Authentication is how we identify +a user and attach their actions to their own data. Supabase includes an +authentication system that works directly with the database, so user identity +flows naturally into queries and permissions. + +Authentication in Supabase is handled by Supabase Auth. It manages creating +accounts, signing in, and issuing tokens that represent the current user. + +--- + +## Users + +A user in Supabase has an id and some optional profile information (such as +email). When someone signs up, Supabase creates a new user record and assigns +them a unique identifier. + +You do not need to create or manage the users table yourself. Supabase stores it +internally and keeps it updated. + +Example of the kind of data Supabase stores for a user: + +```text +id: 74d2...af1 +email: maria@example.com +created: 2025-01-12 09:44:21 +``` + +You can reference this user id in your tables when you want to link data to a +specific user. + +--- + +## Tokens and identity + +When a user signs in, Supabase returns a token. This token proves who the user +is. Your application includes this token in each API request. + +Inside the database, this token becomes the value returned by `auth.uid()`. +This lets policies decide which data belongs to which user. + +For example: + +```text +select auth.uid(); +``` + +returns the id of the signed-in user who made the request. + +--- + +## Sign up and sign in + +Supabase Auth supports several sign-in methods: + +- Email and password +- Magic links (sign in by clicking a link in an email) +- OAuth providers (Google, GitHub, etc.) +- Phone number (SMS) + +For now, we will use email and password, since it is the simplest starting point. + +--- + +## Where authentication connects to data + +Authentication by itself only identifies a user. It does not control access. +The next step is **Row Level Security (RLS)**. RLS uses the user id from the +token to decide which rows the user can read or write. + +So the flow looks like this: + +```text +User signs in +↓ +Supabase gives the client a user token +↓ +Client sends token with API requests +↓ +Postgres receives token and sets auth.uid() +↓ +RLS policies use auth.uid() to enforce access rules +``` + +Authentication says who the user is. +RLS decides what they are allowed to do. + +--- + +## What we learned + +- Supabase Auth manages user accounts and sign-in. +- Each user has a unique id that you can reference in your tables. +- When a user signs in, Supabase provides a token. +- The token tells the database who the user is through `auth.uid()`. +- Authentication by itself does not control access. RLS does that part. + +Understanding this identity flow is important before we begin writing policies. diff --git a/apps/learn/content/foundations/data-fundamentals.mdx b/apps/learn/content/foundations/data-fundamentals.mdx index 185e7f93990..545efa958fa 100644 --- a/apps/learn/content/foundations/data-fundamentals.mdx +++ b/apps/learn/content/foundations/data-fundamentals.mdx @@ -1,52 +1,136 @@ --- title: Data Fundamentals -description: Learn the foundations of Supabase, the Postgres development platform. +description: 'Learn how data is structured in Postgres: tables, rows, columns, and keys.' chapterNumber: 2 --- -In this chapter, you'll learn how to create a table in Supabase, insert data into it, and query it using the REST API. +Before we store any information in Supabase, we need to understand how data is +organized in Postgres. Supabase uses Postgres as its database, which means data +is arranged in a structured and predictable way. This helps keep your app +organized, consistent, and easy to query. -## What you'll learn - -- **Data fundamentals**: create tables, insert and retrieve data, and explore our generated APIs. +The core ideas are simple: you create tables to hold related data, and each +table has rows (records) and columns (fields). Once you understand that pattern, +you can model almost anything. --- -## Prerequisites +## Tables, rows, and columns -- A [Supabase account](https://supabase.com/) (free) -- Basic familiarity with a terminal to run queries. +A table is like a spreadsheet. It has: + +- **Columns**: the fields that define what kind of data the table stores +- **Rows**: the individual entries in the table + +Imagine a table for storing notes: + +```text +| id | content | created_at | +|----|------------------|----------------------| +| 1 | Buy groceries | 2025-01-10 14:22:11 | +| 2 | Call the dentist | 2025-01-10 15:08:54 | +``` + +- Each **row** is a single note. +- Each **column** represents one piece of information about the note. --- -## Course outline +## Data types -The course is split into 7 chapters, each approximately 10 minutes long. +Every column has a data type. This describes the kind of value that can be +stored there. -1. **What is Supabase?** - Get an overview of Supabase's architecture and core products. Create your first project and make a simple API call. -2. **Your First Table** - Create a Postgres table in Supabase, insert data, and query it through the REST API. -3. **Authentication Basics** - Add users, sign them in, and understand how Supabase secures your APIs with JWTs. -4. **Secure Your Data with Row-Level Security** - Enable Row-Level Security and write policies to ensure users only access their own data. -5. **Storage** - Store files in Supabase Storage and upload and serve files from your buckets. -6. **Edge Functions** - Deploy simple functions to run backend logic close to your users using Deno. -7. **Vector Search** - Store and query embeddings for AI-powered search and recommendations using Supabase Vector. +Some common data types: + +```text +| Data type | Example value | Meaning | +| ----------- | ---------------- | ----------------------------- | +| text | Hello world | A string of characters | +| integer | 42 | A number without decimals | +| boolean | true | Yes/no or on/off values | +| timestamptz | 2025-01-10 14:22 | Date and time (with timezone) | +| json | {"name": "John"} | A JSON object | +``` + +Choosing correct types makes your data easier to work with and protects you from +unexpected values. --- -## Before you begin +## Primary keys -Create a new project at [supabase.com](https://supabase.com), open the **Supabase Dashboard**, and grab your **API URL** and **anon key** from the [Connect dialog](https://supabase.com/dashboard/project/_/settings/api?showConnect=true&connectTab=frameworks). -You'll use them throughout the course to send real requests to your database and APIs. +Most tables include a primary key. This is a column that uniquely identifies each +row. In many Supabase projects, this column is named `id` and uses a type called +`uuid`, which automatically generates a unique value. + +You create this column in the table definition like this: + +```text +id uuid primary key default gen_random_uuid() +``` + +You generally don't need to think about it after setting it up. It simply gives +each record a stable identity. --- -## Duration +## Relationships between tables -Approx. **1 hour** — a fast, hands-on introduction to the Supabase platform. +You can link tables together using foreign keys. This is how you express things +like: + +- A user has many notes +- A project has many tasks +- A team has many members + +For example: + +```text +| id | user_id | content | created_at | +|----|--------------------------------------|------------------|----------------------| +| 1 | 9f1b1c94-3e7b-4d6a-9fa7-1e2a3c4ba987 | Buy groceries | 2025-01-10 14:22:11 | +| 2 | 9f1b1c94-3e7b-4d6a-9fa7-1e2a3c4ba987 | Call the dentist | 2025-01-10 15:08:54 | +``` + +Here, `user_id` refers to a row in a `users` table. This means the note belongs +to that user, and we can see that this user has two notes. + +Relationships let you organize data without repeating information. + +--- + +## Why relational data is useful in practice + +Relational data is really useful in practice because it allows you to: + +- Keep data valid with constraints
+ _Example: no duplicate emails._ + +- Link records safely with foreign keys
+ _Example: delete a user and their notes in one action._ + +- Express real permissions with RLS
+ _Example: users can read their own notes; admins can read all._ + +- Query exactly what you need with table joins
+ _Example: fetch notes with the author's email._ + +--- + +## What we learned + +A database in Supabase is made up of tables. +Each table has: + +- columns (which describe the type of information stored) +- rows (the individual pieces of data in that table) + +You can relate tables to each other using foreign keys. +This lets you model real situations, such as: + +- a user has many notes +- a team has many members +- a project has many tasks + +Thinking in tables, rows, and relationships is the foundation of working with data in Supabase. diff --git a/apps/learn/content/foundations/edge-functions.mdx b/apps/learn/content/foundations/edge-functions.mdx new file mode 100644 index 00000000000..545efa958fa --- /dev/null +++ b/apps/learn/content/foundations/edge-functions.mdx @@ -0,0 +1,136 @@ +--- +title: Data Fundamentals +description: 'Learn how data is structured in Postgres: tables, rows, columns, and keys.' +chapterNumber: 2 +--- + +Before we store any information in Supabase, we need to understand how data is +organized in Postgres. Supabase uses Postgres as its database, which means data +is arranged in a structured and predictable way. This helps keep your app +organized, consistent, and easy to query. + +The core ideas are simple: you create tables to hold related data, and each +table has rows (records) and columns (fields). Once you understand that pattern, +you can model almost anything. + +--- + +## Tables, rows, and columns + +A table is like a spreadsheet. It has: + +- **Columns**: the fields that define what kind of data the table stores +- **Rows**: the individual entries in the table + +Imagine a table for storing notes: + +```text +| id | content | created_at | +|----|------------------|----------------------| +| 1 | Buy groceries | 2025-01-10 14:22:11 | +| 2 | Call the dentist | 2025-01-10 15:08:54 | +``` + +- Each **row** is a single note. +- Each **column** represents one piece of information about the note. + +--- + +## Data types + +Every column has a data type. This describes the kind of value that can be +stored there. + +Some common data types: + +```text +| Data type | Example value | Meaning | +| ----------- | ---------------- | ----------------------------- | +| text | Hello world | A string of characters | +| integer | 42 | A number without decimals | +| boolean | true | Yes/no or on/off values | +| timestamptz | 2025-01-10 14:22 | Date and time (with timezone) | +| json | {"name": "John"} | A JSON object | +``` + +Choosing correct types makes your data easier to work with and protects you from +unexpected values. + +--- + +## Primary keys + +Most tables include a primary key. This is a column that uniquely identifies each +row. In many Supabase projects, this column is named `id` and uses a type called +`uuid`, which automatically generates a unique value. + +You create this column in the table definition like this: + +```text +id uuid primary key default gen_random_uuid() +``` + +You generally don't need to think about it after setting it up. It simply gives +each record a stable identity. + +--- + +## Relationships between tables + +You can link tables together using foreign keys. This is how you express things +like: + +- A user has many notes +- A project has many tasks +- A team has many members + +For example: + +```text +| id | user_id | content | created_at | +|----|--------------------------------------|------------------|----------------------| +| 1 | 9f1b1c94-3e7b-4d6a-9fa7-1e2a3c4ba987 | Buy groceries | 2025-01-10 14:22:11 | +| 2 | 9f1b1c94-3e7b-4d6a-9fa7-1e2a3c4ba987 | Call the dentist | 2025-01-10 15:08:54 | +``` + +Here, `user_id` refers to a row in a `users` table. This means the note belongs +to that user, and we can see that this user has two notes. + +Relationships let you organize data without repeating information. + +--- + +## Why relational data is useful in practice + +Relational data is really useful in practice because it allows you to: + +- Keep data valid with constraints
+ _Example: no duplicate emails._ + +- Link records safely with foreign keys
+ _Example: delete a user and their notes in one action._ + +- Express real permissions with RLS
+ _Example: users can read their own notes; admins can read all._ + +- Query exactly what you need with table joins
+ _Example: fetch notes with the author's email._ + +--- + +## What we learned + +A database in Supabase is made up of tables. +Each table has: + +- columns (which describe the type of information stored) +- rows (the individual pieces of data in that table) + +You can relate tables to each other using foreign keys. +This lets you model real situations, such as: + +- a user has many notes +- a team has many members +- a project has many tasks + +Thinking in tables, rows, and relationships is the foundation of working with data in Supabase. diff --git a/apps/learn/content/foundations/security.mdx b/apps/learn/content/foundations/security.mdx new file mode 100644 index 00000000000..545efa958fa --- /dev/null +++ b/apps/learn/content/foundations/security.mdx @@ -0,0 +1,136 @@ +--- +title: Data Fundamentals +description: 'Learn how data is structured in Postgres: tables, rows, columns, and keys.' +chapterNumber: 2 +--- + +Before we store any information in Supabase, we need to understand how data is +organized in Postgres. Supabase uses Postgres as its database, which means data +is arranged in a structured and predictable way. This helps keep your app +organized, consistent, and easy to query. + +The core ideas are simple: you create tables to hold related data, and each +table has rows (records) and columns (fields). Once you understand that pattern, +you can model almost anything. + +--- + +## Tables, rows, and columns + +A table is like a spreadsheet. It has: + +- **Columns**: the fields that define what kind of data the table stores +- **Rows**: the individual entries in the table + +Imagine a table for storing notes: + +```text +| id | content | created_at | +|----|------------------|----------------------| +| 1 | Buy groceries | 2025-01-10 14:22:11 | +| 2 | Call the dentist | 2025-01-10 15:08:54 | +``` + +- Each **row** is a single note. +- Each **column** represents one piece of information about the note. + +--- + +## Data types + +Every column has a data type. This describes the kind of value that can be +stored there. + +Some common data types: + +```text +| Data type | Example value | Meaning | +| ----------- | ---------------- | ----------------------------- | +| text | Hello world | A string of characters | +| integer | 42 | A number without decimals | +| boolean | true | Yes/no or on/off values | +| timestamptz | 2025-01-10 14:22 | Date and time (with timezone) | +| json | {"name": "John"} | A JSON object | +``` + +Choosing correct types makes your data easier to work with and protects you from +unexpected values. + +--- + +## Primary keys + +Most tables include a primary key. This is a column that uniquely identifies each +row. In many Supabase projects, this column is named `id` and uses a type called +`uuid`, which automatically generates a unique value. + +You create this column in the table definition like this: + +```text +id uuid primary key default gen_random_uuid() +``` + +You generally don't need to think about it after setting it up. It simply gives +each record a stable identity. + +--- + +## Relationships between tables + +You can link tables together using foreign keys. This is how you express things +like: + +- A user has many notes +- A project has many tasks +- A team has many members + +For example: + +```text +| id | user_id | content | created_at | +|----|--------------------------------------|------------------|----------------------| +| 1 | 9f1b1c94-3e7b-4d6a-9fa7-1e2a3c4ba987 | Buy groceries | 2025-01-10 14:22:11 | +| 2 | 9f1b1c94-3e7b-4d6a-9fa7-1e2a3c4ba987 | Call the dentist | 2025-01-10 15:08:54 | +``` + +Here, `user_id` refers to a row in a `users` table. This means the note belongs +to that user, and we can see that this user has two notes. + +Relationships let you organize data without repeating information. + +--- + +## Why relational data is useful in practice + +Relational data is really useful in practice because it allows you to: + +- Keep data valid with constraints
+ _Example: no duplicate emails._ + +- Link records safely with foreign keys
+ _Example: delete a user and their notes in one action._ + +- Express real permissions with RLS
+ _Example: users can read their own notes; admins can read all._ + +- Query exactly what you need with table joins
+ _Example: fetch notes with the author's email._ + +--- + +## What we learned + +A database in Supabase is made up of tables. +Each table has: + +- columns (which describe the type of information stored) +- rows (the individual pieces of data in that table) + +You can relate tables to each other using foreign keys. +This lets you model real situations, such as: + +- a user has many notes +- a team has many members +- a project has many tasks + +Thinking in tables, rows, and relationships is the foundation of working with data in Supabase. diff --git a/apps/learn/content/foundations/storage.mdx b/apps/learn/content/foundations/storage.mdx new file mode 100644 index 00000000000..545efa958fa --- /dev/null +++ b/apps/learn/content/foundations/storage.mdx @@ -0,0 +1,136 @@ +--- +title: Data Fundamentals +description: 'Learn how data is structured in Postgres: tables, rows, columns, and keys.' +chapterNumber: 2 +--- + +Before we store any information in Supabase, we need to understand how data is +organized in Postgres. Supabase uses Postgres as its database, which means data +is arranged in a structured and predictable way. This helps keep your app +organized, consistent, and easy to query. + +The core ideas are simple: you create tables to hold related data, and each +table has rows (records) and columns (fields). Once you understand that pattern, +you can model almost anything. + +--- + +## Tables, rows, and columns + +A table is like a spreadsheet. It has: + +- **Columns**: the fields that define what kind of data the table stores +- **Rows**: the individual entries in the table + +Imagine a table for storing notes: + +```text +| id | content | created_at | +|----|------------------|----------------------| +| 1 | Buy groceries | 2025-01-10 14:22:11 | +| 2 | Call the dentist | 2025-01-10 15:08:54 | +``` + +- Each **row** is a single note. +- Each **column** represents one piece of information about the note. + +--- + +## Data types + +Every column has a data type. This describes the kind of value that can be +stored there. + +Some common data types: + +```text +| Data type | Example value | Meaning | +| ----------- | ---------------- | ----------------------------- | +| text | Hello world | A string of characters | +| integer | 42 | A number without decimals | +| boolean | true | Yes/no or on/off values | +| timestamptz | 2025-01-10 14:22 | Date and time (with timezone) | +| json | {"name": "John"} | A JSON object | +``` + +Choosing correct types makes your data easier to work with and protects you from +unexpected values. + +--- + +## Primary keys + +Most tables include a primary key. This is a column that uniquely identifies each +row. In many Supabase projects, this column is named `id` and uses a type called +`uuid`, which automatically generates a unique value. + +You create this column in the table definition like this: + +```text +id uuid primary key default gen_random_uuid() +``` + +You generally don't need to think about it after setting it up. It simply gives +each record a stable identity. + +--- + +## Relationships between tables + +You can link tables together using foreign keys. This is how you express things +like: + +- A user has many notes +- A project has many tasks +- A team has many members + +For example: + +```text +| id | user_id | content | created_at | +|----|--------------------------------------|------------------|----------------------| +| 1 | 9f1b1c94-3e7b-4d6a-9fa7-1e2a3c4ba987 | Buy groceries | 2025-01-10 14:22:11 | +| 2 | 9f1b1c94-3e7b-4d6a-9fa7-1e2a3c4ba987 | Call the dentist | 2025-01-10 15:08:54 | +``` + +Here, `user_id` refers to a row in a `users` table. This means the note belongs +to that user, and we can see that this user has two notes. + +Relationships let you organize data without repeating information. + +--- + +## Why relational data is useful in practice + +Relational data is really useful in practice because it allows you to: + +- Keep data valid with constraints
+ _Example: no duplicate emails._ + +- Link records safely with foreign keys
+ _Example: delete a user and their notes in one action._ + +- Express real permissions with RLS
+ _Example: users can read their own notes; admins can read all._ + +- Query exactly what you need with table joins
+ _Example: fetch notes with the author's email._ + +--- + +## What we learned + +A database in Supabase is made up of tables. +Each table has: + +- columns (which describe the type of information stored) +- rows (the individual pieces of data in that table) + +You can relate tables to each other using foreign keys. +This lets you model real situations, such as: + +- a user has many notes +- a team has many members +- a project has many tasks + +Thinking in tables, rows, and relationships is the foundation of working with data in Supabase. diff --git a/apps/learn/content/foundations/vector.mdx b/apps/learn/content/foundations/vector.mdx new file mode 100644 index 00000000000..545efa958fa --- /dev/null +++ b/apps/learn/content/foundations/vector.mdx @@ -0,0 +1,136 @@ +--- +title: Data Fundamentals +description: 'Learn how data is structured in Postgres: tables, rows, columns, and keys.' +chapterNumber: 2 +--- + +Before we store any information in Supabase, we need to understand how data is +organized in Postgres. Supabase uses Postgres as its database, which means data +is arranged in a structured and predictable way. This helps keep your app +organized, consistent, and easy to query. + +The core ideas are simple: you create tables to hold related data, and each +table has rows (records) and columns (fields). Once you understand that pattern, +you can model almost anything. + +--- + +## Tables, rows, and columns + +A table is like a spreadsheet. It has: + +- **Columns**: the fields that define what kind of data the table stores +- **Rows**: the individual entries in the table + +Imagine a table for storing notes: + +```text +| id | content | created_at | +|----|------------------|----------------------| +| 1 | Buy groceries | 2025-01-10 14:22:11 | +| 2 | Call the dentist | 2025-01-10 15:08:54 | +``` + +- Each **row** is a single note. +- Each **column** represents one piece of information about the note. + +--- + +## Data types + +Every column has a data type. This describes the kind of value that can be +stored there. + +Some common data types: + +```text +| Data type | Example value | Meaning | +| ----------- | ---------------- | ----------------------------- | +| text | Hello world | A string of characters | +| integer | 42 | A number without decimals | +| boolean | true | Yes/no or on/off values | +| timestamptz | 2025-01-10 14:22 | Date and time (with timezone) | +| json | {"name": "John"} | A JSON object | +``` + +Choosing correct types makes your data easier to work with and protects you from +unexpected values. + +--- + +## Primary keys + +Most tables include a primary key. This is a column that uniquely identifies each +row. In many Supabase projects, this column is named `id` and uses a type called +`uuid`, which automatically generates a unique value. + +You create this column in the table definition like this: + +```text +id uuid primary key default gen_random_uuid() +``` + +You generally don't need to think about it after setting it up. It simply gives +each record a stable identity. + +--- + +## Relationships between tables + +You can link tables together using foreign keys. This is how you express things +like: + +- A user has many notes +- A project has many tasks +- A team has many members + +For example: + +```text +| id | user_id | content | created_at | +|----|--------------------------------------|------------------|----------------------| +| 1 | 9f1b1c94-3e7b-4d6a-9fa7-1e2a3c4ba987 | Buy groceries | 2025-01-10 14:22:11 | +| 2 | 9f1b1c94-3e7b-4d6a-9fa7-1e2a3c4ba987 | Call the dentist | 2025-01-10 15:08:54 | +``` + +Here, `user_id` refers to a row in a `users` table. This means the note belongs +to that user, and we can see that this user has two notes. + +Relationships let you organize data without repeating information. + +--- + +## Why relational data is useful in practice + +Relational data is really useful in practice because it allows you to: + +- Keep data valid with constraints
+ _Example: no duplicate emails._ + +- Link records safely with foreign keys
+ _Example: delete a user and their notes in one action._ + +- Express real permissions with RLS
+ _Example: users can read their own notes; admins can read all._ + +- Query exactly what you need with table joins
+ _Example: fetch notes with the author's email._ + +--- + +## What we learned + +A database in Supabase is made up of tables. +Each table has: + +- columns (which describe the type of information stored) +- rows (the individual pieces of data in that table) + +You can relate tables to each other using foreign keys. +This lets you model real situations, such as: + +- a user has many notes +- a team has many members +- a project has many tasks + +Thinking in tables, rows, and relationships is the foundation of working with data in Supabase. diff --git a/apps/learn/lib/get-next-page.ts b/apps/learn/lib/get-next-page.ts index 306a4e377b4..4eda18f71cd 100644 --- a/apps/learn/lib/get-next-page.ts +++ b/apps/learn/lib/get-next-page.ts @@ -1,5 +1,5 @@ import { allDocs } from 'contentlayer/generated' -import { gettingStarted } from '@/config/docs' +import { courses } from '@/config/docs' import { SidebarNavItem } from '@/types/nav' /** @@ -32,9 +32,11 @@ export function normalizeSlug(slug: string): string { /** * Gets the next page in the navigation structure based on the current page slug */ -export function getNextPage(currentSlug: string): { title: string; href: string; description?: string; chapterNumber?: number } | null { +export function getNextPage( + currentSlug: string +): { title: string; href: string; description?: string; chapterNumber?: number } | null { // Flatten all navigation items - const allPages = flattenNavItems(gettingStarted.items) + const allPages = flattenNavItems(courses.items) // Normalize the current slug for comparison const normalizedCurrentSlug = normalizeSlug(currentSlug) @@ -78,4 +80,3 @@ export function getNextPage(currentSlug: string): { title: string; href: string; chapterNumber, } } -