diff --git a/web/docs/guides/with-angular.mdx b/web/docs/guides/with-angular.mdx
new file mode 100644
index 00000000000..c1fc84ef5bc
--- /dev/null
+++ b/web/docs/guides/with-angular.mdx
@@ -0,0 +1,582 @@
+---
+id: with-angular
+title: "Quickstart: Angular"
+description: Learn how to use Supabase in your Angular App.
+---
+
+import Tabs from '@theme/Tabs';
+import TabItem from '@theme/TabItem';
+
+## Intro
+
+This example provides the steps to build a simple user management app (from scratch!) using Supabase and Angular. It includes:
+
+- Supabase [Database](/docs/guides/database): a Postgres database for storing your user data.
+- Supabase [Auth](/docs/guides/auth): users can sign in with magic links (no passwords, only email).
+- Supabase [Storage](/docs/guides/storage): users can upload a photo.
+- [Row Level Security](/docs/guides/auth#row-level-security): data is protected so that individuals can only access their own data.
+- Instant [APIs](/docs/guides/api): APIs will be automatically generated when you create your database tables.
+
+By the end of this guide you'll have an app which allows users to login and update some basic profile details:
+
+
+
+Clicking this button the application will:
+
+- Launch and prepare the Postgres database in Supabase.
+- Launch the app in Vercel.
+- Fork the example into your own GitHub account.
+- Prepare the deployed application with all the necessary environment variables.
+
+If you want to do it yourself, let's get started!
+
+### Github
+
+Whenever you get stuck at any point, take a look at [this repo](https://github.com/angular-supa/supabase-angular-user-management).
+
+## Project set up
+
+Before we start building we're going to set up our Database and API. This is as simple as starting a new Project in Supabase
+and then creating a "schema" inside the database.
+
+### Create a project
+
+1. Go to [app.supabase.io](https://app.supabase.io).
+1. Click on "New Project".
+1. Enter your project details.
+1. Wait for the new database to launch.
+
+
+### Set up the database schema
+
+Now we are going to set up the database schema. We can use the "User Management Starter" quickstart in the SQL Editor,
+or you can just copy/paste the SQL from below and run it yourself.
+
+
+
+
+ ```sh
+ 1. Go to the "SQL" section.
+ 2. Click "User Management Starter".
+ 4. Click "Run".
+ ```
+
+
+
+
+
+
+ ```sql
+ -- Create a table for public "profiles"
+ create table profiles (
+ id uuid references auth.users not null,
+ updated_at timestamp with time zone,
+ username text unique,
+ avatar_url text,
+ website text,
+
+ primary key (id),
+ unique(username),
+ constraint username_length check (char_length(username) >= 3)
+ );
+
+ alter table profiles enable row level security;
+
+ create policy "Public profiles are viewable by everyone."
+ on profiles for select
+ using ( true );
+
+ create policy "Users can insert their own profile."
+ on profiles for insert
+ with check ( auth.uid() = id );
+
+ create policy "Users can update own profile."
+ on profiles for update
+ using ( auth.uid() = id );
+
+ -- Set up Realtime!
+ begin;
+ drop publication if exists supabase_realtime;
+ create publication supabase_realtime;
+ commit;
+ alter publication supabase_realtime add table profiles;
+
+ -- Set up Storage!
+ insert into storage.buckets (id, name)
+ values ('avatars', 'avatars');
+
+ create policy "Avatar images are publicly accessible."
+ on storage.objects for select
+ using ( bucket_id = 'avatars' );
+
+ create policy "Anyone can upload an avatar."
+ on storage.objects for insert
+ with check ( bucket_id = 'avatars' );
+
+ ```
+
+
+
+
+
+### Get the API Keys
+
+Now that you've created some database tables, you are ready to insert data using the auto-generated API.
+We just need to get the URL and `anon` key from the API settings.
+
+
+
+
+ ```sh
+ 1. Go to the "Settings" section.
+ 2. Click "API" in the sidebar.
+ 3. Find your API URL in this page.
+ 4. Find your "anon" and "service_role" keys on this page.
+ ```
+
+
+
+
+
+
+## Building the App
+
+Let's start building the Angular app from scratch.
+
+### Initialize a Angular app
+
+We can use the [Angular CLI](https://angular.io/cli) to initialize
+an app called `supabase-angular`:
+
+```bash
+npx ng new supabase-angular --routing false --style css
+cd supabase-angular
+```
+
+Then let's install the only additional dependency: [supabase-js](https://github.com/supabase/supabase-js)
+
+```bash
+npm install @supabase/supabase-js
+```
+
+And finally we want to save the environment variables in the `environment.ts` file.
+All we need are the API URL and the `anon` key that you copied [earlier](#get-the-api-keys).
+These variables will be exposed on the browser, and that's completely fine since we have [Row Level Security](/docs/guides/auth#row-level-security) enabled on our Database.
+
+
+```ts title="environment.ts"
+export const environment = {
+ production: false,
+ supabaseUrl: "YOUR_SUPABASE_URL",
+ supbaseKey: "YOUR_SUPABASE_KEY"
+};
+```
+
+Now that we have the API credentials in place, let's create a **SupabaseService** with `ng g s supabase` to initialize the Supabase client and implement functions to communicate with the Supabase API.
+
+```ts title="src/app/supabase.service.ts"
+import { Injectable } from '@angular/core';
+import {AuthChangeEvent, createClient, Session, SupabaseClient} from '@supabase/supabase-js';
+import {environment} from "../environments/environment";
+
+export interface Profile {
+ username: string;
+ website: string;
+ avatar_url: string;
+}
+
+@Injectable({
+ providedIn: 'root'
+})
+export class SupabaseService {
+ private supabase: SupabaseClient;
+
+ constructor() {
+ this.supabase = createClient(environment.supabaseUrl, environment.supbaseKey);
+ }
+
+ get user() {
+ return this.supabase.auth.user();
+ }
+
+ get session() {
+ return this.supabase.auth.session();
+ }
+
+ get profile() {
+ return this.supabase
+ .from('profiles')
+ .select(`username, website, avatar_url`)
+ .eq('id', this.user?.id)
+ .single();
+ }
+
+ authChanges(callback: (event: AuthChangeEvent, session: Session | null) => void) {
+ return this.supabase.auth.onAuthStateChange(callback);
+ }
+
+ signIn(email: string) {
+ return this.supabase.auth.signIn({email});
+ }
+
+ signOut() {
+ return this.supabase.auth.signOut();
+ }
+
+ updateProfile(profile: Profile) {
+ const update = {
+ ...profile,
+ id: this.user?.id,
+ updated_at: new Date()
+ }
+
+ return this.supabase.from('profiles').upsert(update, {
+ returning: 'minimal', // Don't return the value after inserting
+ });
+ }
+
+ downLoadImage(path: string) {
+ return this.supabase.storage.from('avatars').download(path);
+ }
+
+ uploadAvatar(filePath: string, file: File) {
+ return this.supabase.storage
+ .from('avatars')
+ .upload(filePath, file);
+ }
+}
+
+```
+
+And one optional step is to update the CSS file `src/index.css` to make the app look nice.
+You can find the full contents of this file [here](https://raw.githubusercontent.com/angular-supa/supabase-angular-user-management/main/src/styles.css).
+
+### Set up a Login component
+
+Let's set up a Angular component to manage logins and sign ups. We'll use Magic Links, so users can sign in with their email without using passwords.
+Create an **AuthComponent** with `ng g c auth` Angular CLI command.
+
+```ts title="src/app/auth.component.ts"
+import { Component } from '@angular/core';
+import {SupabaseService} from "./supabase.service";
+
+@Component({
+ selector: 'app-auth',
+ template: `
+
+
+
+ `,
+})
+export class AuthComponent {
+ loading = false;
+
+ constructor(private readonly supabase: SupabaseService) { }
+
+ async handleLogin(input: string) {
+ try {
+ this.loading = true;
+ await this.supabase.signIn(input);
+ alert('Check your email for the login link!');
+ } catch (error) {
+ alert(error.error_description || error.message)
+ } finally {
+ this.loading = false;
+ }
+ }
+}
+```
+
+### Account page
+
+After a user is signed in we can allow them to edit their profile details and manage their account.
+Create an **AccountComponent** with `ng g c account` Angular CLI command.
+
+```ts title="src/app/account.component.ts"
+import {Component, Input, OnInit} from '@angular/core';
+import {Profile, SupabaseService} from "./supabase.service";
+import {Session} from "@supabase/supabase-js";
+
+@Component({
+ selector: 'app-account',
+ template: `
+
+ `
+})
+export class AppComponent implements OnInit {
+ session = this.supabase.session;
+
+ constructor(private readonly supabase: SupabaseService) { }
+
+ ngOnInit() {
+ this.supabase.authChanges((_, session) => this.session = session);
+ }
+}
+```
+
+Once that's done, run this in a terminal window:
+
+```bash
+npm run start
+```
+
+And then open the browser to [localhost:4200](http://localhost:4200) and you should see the completed app.
+
+
+
+
+## Bonus: Profile photos
+
+Every Supabase project is configured with [Storage](/docs/guides/storage) for managing large files like photos and videos.
+
+### Create an upload widget
+
+Let's create an avatar for the user so that they can upload a profile photo.
+Create an **AvatarComponent** with `ng g c avatar` Angular CLI command.
+
+```ts title="src/app/avatar.component.ts"
+import {Component, EventEmitter, Input, Output} from '@angular/core';
+import {SupabaseService} from "./supabase.service";
+import {DomSanitizer, SafeResourceUrl} from "@angular/platform-browser";
+
+@Component({
+ selector: 'app-avatar',
+ template: `
+
+
+
+
+
+
+
+ `,
+})
+export class AvatarComponent {
+ _avatarUrl: SafeResourceUrl | undefined;
+ uploading = false;
+
+ @Input()
+ set avatarUrl(url: string | undefined) {
+ if (url) {
+ this.downloadImage(url);
+ }
+ };
+
+ @Output() upload = new EventEmitter();
+
+ constructor(
+ private readonly supabase: SupabaseService,
+ private readonly dom: DomSanitizer
+ ) { }
+
+ async downloadImage(path: string) {
+ try {
+ const {data} = await this.supabase.downLoadImage(path);
+ this._avatarUrl = this.dom.bypassSecurityTrustResourceUrl(URL.createObjectURL(data));
+ } catch (error) {
+ console.error('Error downloading image: ', error.message);
+ }
+ }
+
+ async uploadAvatar(event: any) {
+ try {
+ this.uploading = true;
+ if (!event.target.files || event.target.files.length === 0) {
+ throw new Error('You must select an image to upload.');
+ }
+
+ const file = event.target.files[0];
+ const fileExt = file.name.split('.').pop();
+ const fileName = `${Math.random()}.${fileExt}`;
+ const filePath = `${fileName}`;
+
+ await this.supabase.uploadAvatar(filePath, file);
+ this.upload.emit(filePath);
+ } catch (error) {
+ alert(error.message);
+ } finally {
+ this.uploading = false;
+ }
+ }
+}
+```
+
+
+### Add the new widget
+
+And then we can add the widget on top of the **AccountComponent** html template:
+
+```ts title="src/app/account.component.ts"
+template: `
+
+
+
+
+`
+```
+
+## Next steps
+
+At this stage you have a fully functional application!
+
+- Got a question? [Ask here](https://github.com/supabase/supabase/discussions).
+- Sign in: [app.supabase.io](https://app.supabase.io)
diff --git a/web/sidebars.js b/web/sidebars.js
index d34518e5098..3e4c4533af6 100755
--- a/web/sidebars.js
+++ b/web/sidebars.js
@@ -88,6 +88,7 @@ module.exports = {
'guides/with-react',
'guides/with-svelte',
'guides/with-vue-3',
+ 'guides/with-angular',
'guides/self-hosting',
],
},
diff --git a/web/static/img/supabase-angular-demo.png b/web/static/img/supabase-angular-demo.png
new file mode 100644
index 00000000000..7fbeaa64199
Binary files /dev/null and b/web/static/img/supabase-angular-demo.png differ