Share E-Book

Building Production-Grade Web Applications with Supabase A comprehensive guide to database design, security, real-time data,… (David Lorenz)(Z-Library)

Author

Database
Language English

Craft resilient web applications with Supabase by leveraging advanced features such as authentication, data and user management, and seamless AI integration using its powerful Postgres infrastructure Key Features • Learn how to integrate Supabase and Next.js to create powerful and scalable web apps • Explore real-world scenarios with a multi-tenant ticket system • Master real-time data handling, secure file storage, and application security enhancement, while discovering the full potential of the database beyond holding data Discover the powerful capabilities of Supabase, the cutting-edge, open-source platform flipping the script on backend architecture. Guided by David Lorenz, a battle-tested software architect with over two decades of development experience, this book will transform the way you approach your projects and make you a Supabase expert. In this comprehensive guide, you'll build a secure, production-grade multi-tenant ticket system, seamlessly integrated with Next.js. You’ll build essential skills for effective data manipulation, authentication, and file storage, as well as master Supabase's advanced capabilities including automating tasks with cron scheduling, performing similarity searches with artificial intelligence, testing your database, and leveraging real-time updates. By the end of the book, you'll have a deeper understanding of the platform and be able to confidently utilize Supabase in your own web applications, all thanks to David's excellent expertise. Who this book is for This book is for developers looking for a hassle-free, universal solution to building robust apps using Supabase and its integration libraries. While a basic understanding of JavaScript is useful, it’s not essential as the book focuses on Supabase for creating high-performance web apps using Next.js. Experienced professionals from non-JavaScript backgrounds will find this book useful. Familiarity with Postgres, although helpful, is not mandatory…

Format PDF
Size 7.5 MB
8
Views
0
Downloads
0.00
Total Donations
(First 20 pages)

Registered users can read the full content for free

Register as a Gaohf Library member to read the complete e-book online for free and enjoy a better reading experience.

Page 1
(This page has no text content)
Page 2
Building Production-Grade Web Applications with Supabase A comprehensive guide to database design, security, real-time data, storage, multi-tenancy, and more David Lorenz
Page 3
Building Production-Grade Web Applications with Supabase Copyright © 2024 Packt Publishing All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews. Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book. Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information. Group Product Manager: Kaustubh Manglurkar Publishing Product Manager: Chayan Majumdar Book Project Manager: Sonam Pandey Senior Editor: Hayden Edwards Technical Editor: K Bimala Singha Copy Editor: Safis Editing Indexer: Pratik Shirodkar Production Designer: Jyoti Kadam DevRel Marketing Coordinator: Anamika Singh and Nivedita Pandey First published: August 2024 Production reference: 1260724 Published by Packt Publishing Ltd. Grosvenor House 11 St Paul’s Square Birmingham B3 1RB, UK. ISBN 978-1-83763-068-4 www.packtpub.com
Page 4
To my spouse, Ella, for her endless support and love. To my mother and sister for their understanding. To Alexander Hachmann for the time provided. To Christoph Kolb for the support. To Kai Klostermann for being my best friend and supporter. To the Supabase team for providing me with their trust, help, and warm words. – David Lorenz
Page 5
Foreword Six years ago, I joined Mercedes-Benz.io, the company where David worked, and I had the privilege of collaborating with him for four years. It quickly became evident that he was a “beacon” developer—a professional others admired for his exceptional skills and leadership. David’s passion for knowledge is unparalleled. He eagerly explores the latest technological advancements, conducting thorough research on each topic to form well-founded conclusions. His dedication to understanding the intricacies of his craft sets him apart as a truly exceptional professional. As lead developers for our respective teams on the same project, we faced unique challenges. Our project had specific constraints, chief among them a commitment to the old-fashioned approach of vanilla JavaScript. “So what?”, you might ask. And it’s a fair question. In an industry where cutting-edge frontend frameworks reign supreme, our approach was akin to building a house with hand tools while others used power equipment. We often had to solve complex problems from the ground up, without the shortcuts and conveniences modern toolsets provide. This wasn’t just about writing code—it was about rediscovering and applying core principles that many developers had begun to take for granted. Moreover, our role extended beyond coding. We became mentors and educators, guiding our colleagues through the intricacies of framework-free development. This meant teaching not just how to solve problems, but why certain solutions worked, fostering a deeper understanding of fundamental concepts. It was in this challenging environment that David’s exceptional qualities truly shone. From the early days of my tenure, his ability to form and share strong, well-researched opinions on a wide range of topics became apparent. David didn’t just know the how; he understood the why, and he had a knack for explaining both clearly and concisely. His enthusiasm for sharing these insights is a core part of who he is—a trait you, dear reader, are about to experience firsthand through this book. In our fast-paced technological landscape, where the “flavor of the month” changes constantly and documentation often lags behind, individuals such as David are invaluable. They serve as anchors amidst the turbulent sea of evolving technologies, helping others navigate and understand the ever- changing currents. David’s ability to provide clarity and insight where it’s needed most isn’t just useful—it’s essential for staying ahead in our field.
Page 6
This book offers you a glimpse into the same level of insight and enthusiasm that David brought to our team every day, distilled into a format that’s accessible and practical for developers at all levels. Regardless of your current expertise with Supabase, this book promises to be a valuable resource. David provides the following: • Clear explanations covering essential aspects of Supabase • Practical guidance on integrating Supabase into your projects • Strategies for building performant and scalable applications • Insights on how Supabase can compete with more expensive solutions Throughout these pages, you’ll find David’s knowledge translated into actionable insights. Whether you’re new to Supabase or an experienced developer, this book aims to enhance your understanding and application of Supabase, empowering you to create robust, efficient, and cost-effective solutions. Jorge Varandas System Architect, Mercedes-Benz.io
Page 7
Contributors About the author David Lorenz is a web software architect and lecturer who began programming at age 11. Before completing university in 2014, he had built a CRM system that automated an entire company and worked with numerous agencies through his own company. In 2015, he secured his first employment as a senior web developer, where he played a pioneering role in using cutting-edge technology and was an early adopter of progressive web apps. In 2017, he became the leading frontend architect and team lead for one of the largest projects at Mercedes-Benz.io, involving massive-scale architecture. Today, David provides valuable insights and guidance to clients across various industries, using his extensive experience and exceptional problem-solving abilities. I want to thank the people who have been close to me and supported me, especially Ella and the team at Wahnsinn Design GmbH, as well as my mom and my sister.
Page 8
About the reviewers Kamil Pyrkosz is a multiplatform programmer who fell in love with Supabase the first time he used it, surprised by how easy and powerful it was. His passion for Supabase resulted in the creation of a YouTube channel, Kamil the Supabase enjoyer, where he makes Supabase tutorials and videos on other related topics. Thor (Thorsten) Schaeff is a software developer, startup advisor, and Angel investor. Having grown up around the SAP headquarters in Germany, he started building websites back in high school, later studied computer science and media, and interned with Google in London. He joined early Stripe in Dublin, building out various user-facing engineering teams across Europe and Southeast Asia, contributing to open source software, and mentoring and investing in early-stage startups along the way. Now settled in sunny Singapore, Thor works on DevRel and DX at Supabase, helping developers take advantage of the power of Postgres. We would also like to thank Jorge Varandas, Kai Klostermann, and Kushal Seth for their help in reviewing the book.
Page 9
(This page has no text content)
Page 10
Preface xvii Part 1: Creating the Foundations of the Ticket System App 1 Unveiling the Inner Workings of Supabase and Introducing the Book’s Project 3 Technical requirements (and some preamble) 4 Understanding why Supabase is the stack you want 5 Demystifying the inner workings of Supabase with Postgres 8 Access logic within a route 9 Access logic as a central service 10 How Supabase handles access control 13 How the access system works under the hood 14 Supabase Studio – the convenient web dashboard 17 Supabase Auth (GoTrue) – the authentication handler 18 PostgREST – a REST and GraphQL API for your database 19 Realtime – elevating the user experience 21 Storage – simple and scalable object storage 21 Image Proxy – helping to transform images on the fly 22 Edge Functions – completing the optimization stack 23 pg-meta – an internal helper service for the database 24 Kong – the overarching service orchestrator 25 Introducing the production-grade ticket system project 25 Summary 28 Table of Contents
Page 11
Table of Contentsx 2 Setting Up Supabase with Next.js 29 Technical requirements 30 Getting ready with Next.js 31 Installing the Supabase CLI 31 Running your first Supabase instance on your machine 32 Initializing a new local Supabase instance 32 Starting your first Supabase instance 32 Managing multiple local Supabase instances 34 Option 1 – the start-stop technique 35 Option 2 – change ports 35 Connecting to Supabase with the Supabase JavaScript client 35 Initializing and testing the base Supabase JavaScript client within Next.js 36 Understanding the base Supabase client 40 Using the Supabase client with Pages Router and App Router 40 Connecting directly to the database 54 Using Supabase with TypeScript 55 Connecting Supabase to other frameworks 57 Nuxt 3 57 Python 58 Summary 59 3 Creating the Ticket Management Pages, Layout, and Components 61 Technical requirements 62 Setting up Pico.css with Next.js 62 Building the login form 63 Visualizing the Ticket Management UI 68 Creating a shared UI layout with navigation elements 69 Designing the Ticket List page 72 Constructing the Ticket Details page 75 Adding the comments section to the ticket details 78 Implementing a page to create a new ticket 83 Implementing a user overview 84 Enhancing the navigation component 86 Summary 88
Page 12
Table of Contents xi Part 2: Adding Multi-Tenancy and Learning RLS 4 Adding Authentication and Application Protection 91 Technical requirements 92 Adding authentication protection with Supabase 92 Creating users 93 Preparing the middleware for authentication 95 Implementing the login functionality in our app 99 Protecting access to the Ticket Management system 101 Adding a log out button 103 Logging out using the frontend 104 Logging out using the backend 107 Understanding server authentication 109 Enhancing the password login 110 Authenticating with magic links 114 Sending magic links with signInWithOtp() on the frontend 114 Why I usually don’t use signInWithOtp() 119 Understanding a server-only magic link flow 121 Implementing a server-only magic link flow with custom email content 123 Adding password recovery 130 Learning about the Site URL and redirect URLs 132 How to configure site and redirect URLs 133 Optional knowledge: adapting built-in templates 134 Summary 136 5 Crafting Multi-Tenancy through Database and App Design 137 Technical requirements 137 What kind of multi-tenancy do we need? 138 Designing the database for multi-tenancy 139 Planning our database 139 Creating the tenants table 141 Designing the users table 146 Designing the permission structure 152 Committing your database state (if you don’t seed it, you lose it) 155 Making our Next.js application tenant-aware 158 Enhancing the middleware to safeguard dynamic routes 159 Fixing all static routes in the application 161 Making the login tenant-based 165 Summary 168
Page 13
Table of Contentsxii 6 Enforcing Tenant Permissions with RLS and Handling Tenant Domains 169 Technical requirements 170 Learning to work with RLS 170 Fetching tenant data with the restrictive Supabase client 171 Defining RLS policies to access tenants based on permissions 173 Creating a permission-based RLS policy 178 Understanding and solving RLS implications 185 Shrinking RLS policies based on the implications 187 Learning about RLS implications 189 Minimizing RLS complexity with custom claims 190 Extending app_metadata with tenant permissions 192 Keeping custom claims in sync with the table data 202 Making the authentication process tenant-based 203 Preventing password login on a foreign tenant 204 Preventing the magic link login for foreign tenants 205 Rejecting to visit invalid and forbidden tenant URLs when signed in 206 Matching a tenant per domain instead of per path 207 Adding custom domains via the hosts file 208 Mapping domains in our application 209 Bringing back localhost with mapped domains 219 Summary 220 7 Adding Tenant-Based Signups, including Google Login 221 Technical requirements 222 Understanding the impact of disabling signups 222 Disabling signups generally 223 Disabling specific signup methods 223 Implementing the registration page 224 Processing the registration with a Route Handler 228 Reading and validating the form data 228 Rejecting registration 230 Handling account creation 232 Adding the service user and permission rows 234 Sending the activation email 236 Redirecting the user to a success page 240 Enabling OAuth/Sign-in with Google 242 Obtaining Google OAuth credentials 242 Configuring our Supabase instance with the OAuth credentials 247
Page 14
Table of Contents xiii Adding a “Sign in with Google” option triggering the OAuth process 247 Solving the crypto/HTTPS security problem 249 Building a verification route to finalize the registration 250 Dealing with invalid user registration 254 Summary 255 Part 3: Managing Tickets and Interactions 8 Implementing Dynamic Ticket Management 259 Technical requirements 259 Creating the tickets table in the database 260 Creating tickets and using triggers 266 Implementing the ticket creation logic 267 Using triggers to derive and set the user ID 273 Improving loading behavior after adding a ticket 279 Enforcing checks on the database columns 279 Viewing the ticket details 281 Caching the author’s name with a trigger 284 Improving the date and status view 287 Listing and filtering tickets 288 Enabling paging 290 Sorting tickets 295 Creating a ticket filter 297 Deleting tickets 303 Summary 306 9 Creating a User List with RPCs and Setting Ticket Assignees 307 Technical requirements 307 Adding a user list with an RPC 308 Ensuring there are enough users to test 308 Enhancing the table structure 308 Fetching the users with an RPC 309 Using the function with an RPC 316 Allowing the setting and editing of an assignee to a ticket 317 Adding assignee columns in the tickets table 318 Creating the trigger function to cache the name 319 Adding an assignee at ticket creation 322 Showing the assignee in the details 324 Updating the assignee 326 Summary 329
Page 15
Table of Contentsxiv 10 Enhancing Interactivity with Realtime Comments 331 Technical requirements 332 Creating the comments table 332 Adding a trigger to set the tenant automatically 335 Adding and optimizing RLS policies 338 Creating RLS helper functions 338 Creating the policies 342 Implementing comment creation 344 Listing existing comments from the server 346 Implementing Realtime comments 350 Enabling Realtime and subscribing to it 350 Updating the UI with Realtime data 353 Triggering impersonated real-time updates with the Table Editor 354 Embracing additional Realtime insights and learning about potential pitfalls 359 Summary 361 11 Adding, Securing, and Serving File Uploads with Supabase Storage 363 Technical requirements 364 Creating and understanding Storage buckets 364 Examining public buckets 367 Exploring files within a bucket programmatically 369 Learning how a basic RLS policy can be added to your bucket 370 Understanding private buckets and revising our bucket choice 372 Choosing a private or a public bucket? 374 Enabling the addition of comments with file attachments 376 Preparing the UI with file upload possibility 376 Uploading files to storage 377 Connecting uploaded files with the written comment 382 Showing the connected files 385 Serving image attachments directly in the UI 390 Using Image Transformations 390 Building a pseudo-CDN for private buckets 391 Using the pseudo-CDN inside our UI 393 Writing RLS policies directly on buckets and objects table 395 Diving into advanced storage restrictions 396 Summary 399
Page 16
Table of Contents xv Part 4: Diving Deeper into Security and Advanced Features 12 Avoiding Unwanted Data Manipulation and Undisclosed Exposures 403 Technical requirements 404 Understanding PostgREST’s OpenAPI Schema exposure 404 Preventing schema exposure 407 Removing schemas from usage via API 408 Specifically exposing a schema to the API 409 Being careful with current_user usage and understanding auth.role() 409 Generating new Anonymous Keys, Service Role Keys, and database passwords 412 Benefiting from Supabase Vault 413 Creating secrets in the Vault and reading them 414 Using the secret in the business logic/within your application 415 Utilizing silent resets to avoid data manipulation 416 Enabling column-level security/working with roles 417 Understanding security on views and manually created tables 418 Changing the max_rows configuration 419 Understanding safe-guarded API updates or deletion 419 Adding middleware inside Postgres for each API request 420 Adding middleware for PostgREST 423 Using the Security Advisor 426 Allowing a listing of IPs for database connections 427 Enforcing SSL on direct database connections 429 Summary 429 13 Adding Supabase Superpowers and Reviewing Production Hardening Tips 431 Technical requirements 432 Making sense of search_path 432 Comprehending search path in Postgres 433 Grasping the importance of extra_search_path 436 Familiarizing yourself with database extensions 437
Page 17
Table of Contentsxvi Installing an extension in the default extensions schema 437 Installing extensions in their own schema 439 Using the programmatic installation of extensions versus using the UI 441 Adding an AI-based semantic ticket search 442 Deciding on an embeddings provider 443 Creating the embeddings column in the table 444 Creating embeddings with OpenAI 444 Comparing embeddings to find matching search results 446 Using anonymous sign-ins 449 Transforming external APIs into tables with foreign data wrappers 452 Using webhooks 457 Creating webhooks with dynamic URLs per environment 460 Understanding Edge Functions 463 Understanding when to use Edge Functions 463 Creating an Edge Function that runs for new rows 463 Triggering the Edge Function 465 Using cronjobs to notify about due tickets 471 Using pg_jsonschema for JSON data integrity 475 Testing the database with pgTAP 476 Setting the auth.storageKey to avoid migration problems 477 Extending supabase.ts with custom typings 478 Improving RLS and query performance 479 Identifying database performance problems and bloat 481 Working with complex table joins 483 Reviewing the underestimated benefit of using an external database client 485 Understanding migrations 485 Utilizing database branching 487 Disabling GraphQL or PostgREST (if you don’t need it) 488 Using a dead-end built-in mailing setup 489 Retrieving table data with the REST API and cURL 490 Summary 491 Index 493 Other Books You May Enjoy 504
Page 18
Preface Technology and web development have always fascinated me. Over the past 23 years, I’ve navigated the evolving landscape of coding, starting from my self-taught beginnings at the age of 11. Back then, the internet presented different challenges, such as achieving a proper box model in Internet Explorer or using border-radius and transparent PNGs. As a web app architect, I carefully choose technology stacks. While I stay at the cutting edge of web development and closely observe new hypes, I don’t like to adopt them immediately. Instead, I evaluate them meticulously. My extensive JavaScript experience has given me a broad, well-informed perspective and taught me to trust my gut feeling, developed over years of diverse projects and challenges. My journey with Supabase has been unique as it’s one of the rare stacks I can use for nearly any project, no matter which additional stack surrounds it, thanks to its superpowered Postgres database with an “all batteries included” approach. This book is a culmination of my experiences, insights, and countless hours spent exploring Supabase. My hope is that it will not only guide you through the technical aspects but also inspire you to see the potential and possibilities that Supabase offers. We are at an exciting juncture in web development, and together, we will explore how Supabase can transform your projects and reshape the way you think about web development. Welcome to the world of Supabase! Who this book is for This book is perfect for developers looking for a hassle-free, universally applicable solution to build robust apps. By using the open source Supabase backend and its simple integration libraries, you can significantly accelerate your development process. What this book covers Chapter 1, Unveiling the Inner Workings of Supabase and Introducing the Book’s Project, explains why Supabase is the stack you want for your next project, demystifies its inner workings, and explores its interconnected services. You will also be introduced to the Multi-Tenant Ticket System project that we will be working on throughout the book. Chapter 2, Setting Up Supabase with Next.js, covers setting up and connecting to Supabase, running local instances, managing multiple instances, and integrating Supabase with your Next.js application, laying the groundwork for your ticket system project.
Page 19
Prefacexviii Chapter 3, Creating the Ticket Management Pages, Layout, and Components, explains how to build the foundational design of your ticket system project using mock data, creating solid-looking pages and components with Next.js only. Chapter 4, Adding Authentication and Application Protection, integrates user authentication with Supabase, protecting your application, and you will also learn about sending customized authentication emails. Chapter 5, Crafting Multi-Tenancy through Database and App Design, covers how to design your database and the application to support multi-tenancy, including defining permissions and making the application tenant aware. Chapter 6, Enforcing Tenant Permissions with RLS and Handling Tenant Domains, focuses on implementing row-level security (RLS) to secure tenant-specific data, streamlining RLS with Custom Claims, and adapting your application to use domain-based tenant identification. Chapter 7, Adding Tenant-Based Signups, Including Google Login, takes you through implementing tenant-based user registration, enabling OAuth sign-in with Google, and handling invalid user registrations to enhance the onboarding process. Chapter 8, Implementing Dynamic Ticket Management, shows you how to create and manage tickets, implement ticket details and related data, and enhance the ticket list with paging, sorting, and searching features. Chapter 9, Creating a User List with RPCs and Setting Ticket Assignees, explores how to create a user list using remote procedure calls (RPCs), add assignees to tickets, and implement UPDATE RLS policies for enhanced security. Chapter 10, Enhancing Interactivity with Realtime Comments, guides you through creating a comments table, implementing real-time comment functionality, and optimizing RLS policies to enhance user interactivity and experience. Chapter 11, Adding, Securing, and Serving File Uploads with Supabase Storage, explains how to implement file uploads within ticket comments, secure files with RLS policies, and serve images using Supabase Storage and Image Transformations Chapter 12, Avoiding Unwanted Data Manipulation and Undisclosed Exposures, discusses advanced security techniques to protect your Supabase application, including managing roles, using Supabase Vault, implementing column-level security (CLS), and much more. Chapter 13, Adding Supabase Superpowers and Reviewing Production Hardening Tips, unleashes the full potential of your Supabase application with powerful techniques. You’ll discover how to integrate database extensions, optimize performance, implement AI-based features, and secure your workflows like never before.
Page 20
Preface xix To get the most out of this book To get the most out of this book, you should have a solid understanding of at least one programming language and be familiar with JavaScript, as we will be building a Next.js app to explore Supabase’s features. However, since the concepts of Supabase are framework independent, this book is also incredibly insightful for experienced developers from non-JavaScript backgrounds who want to enhance their development speed. While familiarity with Postgres is also a plus, all SQL statements used in the book are thoroughly explained. Software/hardware covered in the book Operating system requirements Docker Desktop or orbstack Windows, macOS, or Linux npm/node An account on supabase.com DBeaver (recommended, not necessary) If you are using the digital version of this book, we advise you to type the code yourself or access the code from the book’s GitHub repository (a link is available in the next section). Doing so will help you avoid any potential errors related to the copying and pasting of code. Also, take your time and read the book carefully - there's no rush! Download the example code files You can download the example code files for this book from GitHub at https://github.com/ PacktPublishing/Building-Production-Grade-Web-Applications-with- Supabase. If there’s an update to the code, it will be updated in the GitHub repository. Conventions used There are a number of text conventions used throughout this book. Code in text: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: “Change port to something unique, such as port=9100, and now, for this project, your Supabase Studio Service will run on localhost:9100.” A block of code is set as follows: document = createNewTextDocument(); userId = getUserIdFromLoginSession(); getFgaClient() .subject({userId}) .addPermissions({objectType: 'document', objectId: document.id}) .relations(['save', 'delete', 'share'])
The above is a preview of the first 20 pages. Register to read the complete e-book.

Recommended for You

Loading recommended books...
Failed to load, please try again later

Tip the Site

Scan the WeChat Pay or Alipay code to tip. No login required.

WeChat Pay
Alipay
Back to List