Architecture page

This commit is contained in:
Terry Sutton committed 2025-11-04 17:39:10 -03:30
1 parent c1e0ca4f27
commit 697d457f1d
2 files changed
+274 -44

No files matched your search

+119 -8
View File
@@ -1,4 +1,8 @@
'use client'
import { Check } from 'lucide-react'
import { useEffect, useRef, useState } from 'react'
import { useLocalStorage } from './use-local-storage'
interface ChapterCompletionProps {
chapterNumber: number
@@ -6,28 +10,135 @@ interface ChapterCompletionProps {
}
export function ChapterCompletion({ chapterNumber, completionMessage }: ChapterCompletionProps) {
const [completedChapters, setCompletedChapters] = useLocalStorage<number[]>(
'completed-chapters',
[]
)
const [isCompleted, setIsCompleted] = useState(false)
const [isVisible, setIsVisible] = useState(false)
const containerRef = useRef<HTMLDivElement>(null)
const timerRef = useRef<NodeJS.Timeout | null>(null)
// Check if chapter is already completed on mount
useEffect(() => {
if (completedChapters.includes(chapterNumber)) {
setIsCompleted(true)
}
}, [chapterNumber, completedChapters])
useEffect(() => {
const container = containerRef.current
if (!container) return
const observer = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
setIsVisible(true)
} else {
setIsVisible(false)
// Reset timer if user scrolls away
if (timerRef.current) {
clearTimeout(timerRef.current)
timerRef.current = null
}
}
})
},
{
threshold: 0.5, // Trigger when 50% of the component is visible
rootMargin: '0px',
}
)
observer.observe(container)
return () => {
observer.disconnect()
if (timerRef.current) {
clearTimeout(timerRef.current)
}
}
}, [])
useEffect(() => {
if (isVisible && !isCompleted) {
// Start timer when component becomes visible
timerRef.current = setTimeout(() => {
setIsCompleted(true)
// Save to local storage
if (!completedChapters.includes(chapterNumber)) {
setCompletedChapters([...completedChapters, chapterNumber])
}
}, 5000) // 5 seconds
} else if (!isVisible && timerRef.current) {
// Clear timer if user scrolls away before completion
clearTimeout(timerRef.current)
timerRef.current = null
}
return () => {
if (timerRef.current) {
clearTimeout(timerRef.current)
}
}
}, [isVisible, isCompleted, chapterNumber, completedChapters, setCompletedChapters])
return (
<div className="mb-16 mt-8">
<div className="flex items-center gap-12">
<div ref={containerRef} className="mb-16 mt-8">
<div className="flex items-center gap-12">
{/* Large circle with chapter number */}
<div className="relative mb-6">
<div className="w-24 h-24 rounded-full bg-green-50 flex items-center justify-center">
<span className="text-4xl font-bold text-brand-500">{chapterNumber}</span>
<div
className={`w-24 h-24 rounded-full flex items-center justify-center transition-all duration-500 ${
isCompleted ? 'bg-green-50' : 'bg-muted'
}`}
>
<span
className={`text-4xl font-bold transition-all duration-500 ${
isCompleted ? 'text-brand-500' : 'text-foreground-muted'
}`}
>
{chapterNumber}
</span>
</div>
{/* Small checkmark circle overlapping bottom-right */}
<div className="absolute -bottom-1 -right-1 w-8 h-8 bg-brand-500 rounded-full flex items-center justify-center shadow-md">
<Check className="h-6 w-6 text-white" strokeWidth={3} />
<div
className={`absolute -bottom-1 -right-1 w-8 h-8 rounded-full flex items-center justify-center shadow-md transition-all duration-500 ${
isCompleted ? 'bg-brand-500 scale-100 opacity-100' : 'bg-muted scale-75 opacity-0'
}`}
>
<Check
className={`h-6 w-6 text-white transition-all duration-300 ${
isCompleted ? 'scale-100 opacity-100' : 'scale-0 opacity-0'
}`}
strokeWidth={3}
/>
</div>
</div>
<div>
{/* Completion text */}
<h3 className="text-2xl font-bold text-foreground mb-2">
<h3
className={`text-2xl font-bold mb-2 transition-all duration-500 ${
isCompleted
? 'text-foreground opacity-100 translate-y-0'
: 'text-foreground-muted opacity-60 translate-y-2'
}`}
>
You've completed Chapter {chapterNumber}
</h3>
{completionMessage && (
<p className="text-base text-foreground-light max-w-2xl">{completionMessage}</p>
<p
className={`text-base max-w-2xl transition-all duration-500 delay-100 ${
isCompleted
? 'text-foreground-light opacity-100 translate-y-0'
: 'text-foreground-light opacity-0 translate-y-2'
}`}
>
{completionMessage}
</p>
)}
</div>
</div>
+155 -36
View File
@@ -4,57 +4,176 @@ description: Learn how Supabase's core products work together.
chapterNumber: 1
---
In this short course, you'll explore how Supabase brings together **Database**, **Auth**, **Storage**, **Edge Functions**, and **Realtime** into a unified developer platform.
---
By the end, you'll understand how each piece of Supabase fits together, how to persist and protect your data, and how to start confidently building your own applications.
## What you'll learn
- **Architecture**: how Supabase's core products work together.
- **Data fundamentals**: create tables, insert and retrieve data, and explore our generated APIs.
- **Authentication**: create and sign in users, and make secure requests.
- **Security**: enable Row Level Security (RLS) and write policies to protect your data.
- **Storage**: upload and serve files using buckets.
- **Edge Functions**: run custom backend logic close to your users, using Deno and Supabase's serverless runtime.
- **Vector search**: store and query embeddings for AI-powered search and recommendations.
title: Architecture
description: A high-level view of how Supabase fits together: Postgres at the center,
with services for auth, APIs, storage, realtime, edge functions, and vector search.
---
## Prerequisites
This page explains how Supabase is structured and how its main services work
together. Supabase is built on top of a powerful open source database called
Postgres, but it includes much more than a database. Around Postgres,
Supabase adds services for authentication, serverless functions, file storage, realtime updates, AI-powered search, and easy APIs to access it — all designed to work easily together.
- A [Supabase account](https://supabase.com/) (free)
- Basic familiarity with a terminal to run queries.
The goal is to give you a complete backend that feels consistent and connected,
so you can focus on building your app instead of wiring together separate tools.
---
## Course outline
## The mental model
The course is split into 7 chapters, each approximately 10 minutes long.
At the center of Supabase is Postgres. Every other part connects to it.
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.
```text
Clients (web, mobile, scripts)
|
v
API layer (REST via PostgREST, GraphQL)
|
v
Postgres <---- Realtime (listens for changes)
| ^
| |
v |
Storage | Auth (manages users)
| | Edge Functions (runs code)
v | Vector Search (pgvector)
Files + URLs Studio, CLI, Policies (RLS)
```
You interact with Supabase mainly through the API layer or the client libraries.
The API talks to Postgres, and Postgres enforces security rules that you define.
All the other services stay in sync because they share the same database.
---
## Before you begin
## The main components
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.
### Database (Postgres)
Your data lives in Postgres tables. You can design tables, columns, and
relationships using SQL or the visual editor in Supabase Studio. Supabase
manages backups, scaling, and migrations for you.
**Why this matters:** Postgres is a full relational database with features like
foreign keys, indexes, and extensions. Supabase gives you these tools without
the usual setup.
---
## Duration
### API layer (REST and GraphQL)
Approx. **1 hour** — a fast, hands-on introduction to the Supabase platform.
Supabase automatically exposes your tables as APIs using PostgREST (for REST)
and PostGraphile (for GraphQL). You can read, insert, update, and delete rows
with simple HTTP requests. You can also expose your own SQL functions as custom
endpoints.
**Why this matters:** You can connect any frontend or script directly to your
database without building a separate API server.
---
### Auth (users and tokens)
Auth manages users and issues tokens that identify them. When someone signs in,
their token is sent with every request, and Postgres uses that identity to apply
the right access rules.
**Why this matters:** Authentication is built into your database layer, so you
don't need an external service to handle sign-ups or sessions.
---
### Row Level Security (RLS) and policies
RLS lets you write SQL rules that decide who can read or modify each row in your
tables. These policies apply everywhere — through REST, GraphQL, or Realtime.
**Why this matters:** Security lives directly in the database. You define it
once, and it's enforced across every API call.
---
### Storage (files and buckets)
Storage provides an S3-style interface for storing files such as images, videos,
and documents. File metadata lives in Postgres, so you can apply the same access
policies you use for your data.
**Why this matters:** File access and data access follow the same security rules,
which keeps your system consistent and simple.
---
### Realtime
Realtime listens to changes in Postgres and sends them to connected clients over
WebSocket. You can subscribe to table events and see updates as they happen.
**Why this matters:** You can build collaborative or live-updating interfaces
without managing your own socket server.
---
### Edge Functions
Edge Functions let you run server-side JavaScript or TypeScript using Deno.
They're good for webhooks, background tasks, and any logic that shouldn't run
on the client.
**Why this matters:** You can write custom backend logic without maintaining a
full server or worrying about scaling.
---
### Vector Search
The pgvector extension adds support for storing and searching **embeddings** —
numerical representations of text, images, or other data. This allows you to
search by meaning, not just by keywords.
**Why this matters:** You can add AI-style semantic search or recommendations
directly to your database.
---
### Studio and CLI
Supabase Studio is the web dashboard for managing your project: running SQL,
browsing data, editing policies, and managing users. The CLI is for local
development and migrations, so your schema can live alongside your code.
**Why this matters:** You can move smoothly between GUI and code, keeping your
database versioned and reproducible.
---
## How everything connects
When your app makes a request, it goes through a simple path:
1. The client calls a Supabase API endpoint, sending a project key and (usually)
a user token.
2. The API turns that request into a SQL query.
3. Postgres runs the query and applies any RLS policies.
4. The API returns the results as JSON.
5. If there are changes, Realtime broadcasts them to any connected clients that
are allowed to see them.
Edge Functions can follow the same pattern — they can call the APIs or connect
directly to Postgres when they need more control.
---
## Why this architecture helps
- **Everything shares one source of truth:** Postgres is at the center.
- **Security is consistent:** RLS policies apply across every service.
- **No separate backend required:** APIs are generated automatically from you database.
- **You can grow gradually:** Start with just a table, add realtime, storage, or functions later.
- **It's just Postgres:** You can use standard SQL, extensions, and tools.
Supabase gives you the power of Postgres with the convenience of a fully
integrated backend platform.