Skip to content

Commit

Permalink
wip: quickstarts
Browse files Browse the repository at this point in the history
  • Loading branch information
zoedsoupe committed Oct 25, 2024
1 parent 0a4d54c commit c017d33
Show file tree
Hide file tree
Showing 54 changed files with 291 additions and 19 deletions.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
# Supabase Phoenix LiveView User Management

This repo is a quick sample of how you can get started building apps using [Phoenix LiveView](https://phoenixframework.org) and Supabase. You can find a step by step guide of how to build out this app in the [Quickstart: Phoenix LiveView guide](./guides/quickstart.md).

This repo will demonstrate how to:

- sign users in with Supabase Auth using [magic link](https://supabase.io/docs/reference/dart/auth-signin#sign-in-with-magic-link)
- store and retrieve data with [Supabase database](https://supabase.io/docs/guides/database)
- store image files in [Supabase storage](https://supabase.io/docs/guides/storage)

## Getting Started

Before running this app, you need to create a Supabase project and copy [your credentials](./guides/quickstart.md#get-the-api-keys) to `.env` or you can safely use [supabase-cli](https://supabase.com/docs/guides/cli/getting-started) and use the already defined `.env.dev`.

Run the following command to launch it on `localhost:4000`

```bash
mix dev
```

> Note that this command `mix dev` is a custom alias defind on `mix.exs`.
## Database Schema

```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 ( (select auth.uid()) = id );

create policy "Users can update own profile."
on profiles for update
using ( (select 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' );
```

> [!INFO]
> You can find the SQL schema in the [migrations](./priv/repo/migrations) folder.
> Generally you would prefer to use direct connection between your app (with ecto) and the Supabase postgres intances instead of using PostgREST
Original file line number Diff line number Diff line change
@@ -0,0 +1,128 @@
# Build a User Management App with Phoenix LiveView

Learn how to use Supabase in your Phoenix LiveView App.

This tutorial demonstrates how to build a basic user management app. The app authenticates and identifies the user, stores their profile information in the database, and allows the user to log in, update their profile details, and upload a profile photo. The app uses:

- [Supabase Database](https://supabase.com/docs/guides/database) - a Postgres database for storing your user data and [Row Level Security](https://supabase.com/docs/guides/auth#row-level-security) so data is protected and users can only access their own information.
- [Supabase Auth](https://supabase.com/docs/guides/auth) - allow users to sign up and log in.
- [Supabase Storage](https://supabase.com/docs/guides/storage) - users can upload a profile photo.

![Supabase User Management example](https://supabase.com/docs/img/user-management-demo.png)

> [!INFO]
> If you get stuck while working through this guide, refer to the [full example on GitHub](https://github.com/zoedsoupe/supabase-ex/tree/main/examples/user_management/phoenix_live_view_user_management).
## Project Setup

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. [Create a new project](https://supabase.com/dashboard) in the Supabase Dashboard.
2. Enter your project details.
3. Wait for the new database to launch.

### Set up the database schema

I'll be doing that using the [Ecto migrations](https://hexdocs.pm/ecto_sql), but you can also do that manually in the Supabase Dashboard.

### 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 Project URL and `anon` key from the API settings.

1. Go to the [API Settings](https://supabase.com/dashboard/project/_/settings/api) page in the Dashboard.
2. Find your Project `URL`, `anon`, and `service_role` keys on this page.

## Building the app

Let's start building the Phoenix LiveView app from scratch.

### Initialize a Phoenix LiveView app

We can use [`mix phx.new`](https://hexdocs.pm/phoenix/Mix.Tasks.Phx.New.html) to create an app called `arcane`:

> Before issuing this command, ensure you have [elixir](https://elixir-lang.org) installed
> Also ensure that you have the [phoenix installer](https://hexdocs.pm/phoenix/installation.html) in your machine
```bash
mix phx.new --adapter bandit --no-tailwind --app arcane phoenix_live_view_user_management

cd phoenix_live_view_user_management
```

Then let's install the needed dependencies to integrate with supabase: [Supabase Potion](https://hexdocs.pm/supabase_potion). We only need to add these lines to your `deps` in `mix.exs`:

```elixir
defp deps do
[
{:supabase_potion, "~> 0.5"},
{:supabase_gotrue, "~> 0.3"},
{:supabase_storage, "~> 0.3"},
# other dependencies
]
end
```

Then install them with:

```sh
mix deps.get
```

And finally we want to save the environment variables in a `.env`.
All we need are the API URL and the `anon` key that you copied [earlier](#get-the-api-keys).

```bash .env
export SUPABASE_URL="YOUR_SUPABASE_URL"
export SUPABASE_KEY="YOUR_SUPABASE_ANON_KEY"
```

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.
Amazing thing about [NuxtSupabase](https://supabase.nuxtjs.org/) is that setting environment variables is all we need to do in order to start using Supabase.
No need to initialize Supabase. The library will take care of it automatically.

### App styling (optional)

An optional step is to update the CSS file `assets/main.css` to make the app look nice.
You can find the full contents of this file [here](https://github.com/zoedsoupe/supabase-ex/blob/main/examples/user_managment/phoenix_live_view_user_management/assets/css/app.css).

### Set up Auth component

TODO

### User state

TODO

### Account component

TODO

### Launch!

TODO

Once that's done, run this in a terminal window:

```bash
iex -S mix phx.server
```

And then open the browser to [localhost:4000](http://localhost:4000) and you should see the completed app.

![Supabase Phoenix LiveView](https://supabase.com/docs/img/supabase-vue-3-demo.png)

## Bonus: Profile photos

Every Supabase project is configured with [Storage](https://supabase.com//docs/guides/storage) for managing large files like photos and videos.

### Create an upload widget

TODO

### Add the new widget

TODO

That is it! You should now be able to upload a profile photo to Supabase Storage and you have a fully functional application.
87 changes: 87 additions & 0 deletions guides/quickstarts/phoenix_liveview.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Use Supabase with Phoenix LiveView

Learn how to create a LiveView project and connect it to your Supabase Postgres database.

## 1. Create a Phoenix LiveView Project

Make sure your Elixir and Phoenix installer versions are up to date, then use `mix phx.new` to scaffold a new LiveView project. Postgresql is the default database for Phoenix apps.

Go to the [Phoenix docs](https://phoenixframework.org) for more details.

```sh
mix phx.new blog
```

## 2. Set up the Postgres connection details

Go to [database.new](https://database.new/) and create a new Supabase project. Save your database password securely.

When your project is up and running, navigate to the [database settings](https://supabase.com/dashboard/project/_/settings/database) to find the URI connection string. Make sure **Use connection pooling** is checked and **Session mode** is selected. Then copy the URI. Replace the password placeholder with your saved database password.

> [!INFO]
> If your network supports IPv6 connections, you can also use the direct connection string. Uncheck **Use connection pooling** and copy the new URI.
For the production environment, you can set up this env var on your `config/runtime.exs`
```sh
export DATABASE_URL=ecto://postgres.xxxx:password@xxxx.pooler.supabase.com:5432/postgres
```

For your local dev environment your can modify the `config/dev.exs` file to look like this (replacing placeholders with your `supabase-cli` config):

```elixir
# config/dev.exs

import Config

config :blog, Blog.Repo,
hostname: "localhost",
port: 54322, # default supabase-cli postgres port
username: "postgres",
password: "postgres",
database: "postgres"

# other configs
```

## 3. Create and run a database migration

Phoenix LiveView includes [Ecto](https://hexdocs.pm/ecto) as the data mapping and database schema magement tool (aka ORM in other stacks) as well as database migration tooling which generates the SQL migration files for you.

Create an example `Article` model and generate the migration files.

```sh
mix phx.gen.schema Posts.Article articles title:string views:integer
mix ecto.migrate
```

The first argument is the schema module followed by its plural name (used as the table name).

The generated schema above will contain:
- a schema file in `lib/blog/posts/article.ex`, with a articles table
- a migration file for the repository

More information on the [mix phx.new.schema task documentation](https://hexdocs.pm/phoenix/Mix.Tasks.Phx.Gen.Schema.html)

## 4. Use the Model to interact with the database

You can use the included Phoenix console to interact with the database. For example, you can create new entries or list all entries in a Model's table.

```sh
iex -S mix
```

```iex
article = %Blog.Posts.Article{title: "Hello Phoenix", body: "I am on Phoenix!"}
Blog.Repo.insert!(article) # Saves the entry to the database
Blog.Repo.all(Blog.Posts.Article) # Lists all the entries of a model in the database
```

## 5. Start the app

Run the development server. Go to [http://127.0.0.1:4000](http://127.0.0.1:4000) in a browser to see your application running.

```sh
iex -S mix phx.server
```

> This command also starts an iex session (REPL) while staring the web server
2 changes: 1 addition & 1 deletion lib/supabase/client/behaviour.ex
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
defmodule Supabase.Client.Behaviour do
@doc """
@moduledoc """
The behaviour for the Supabase Client. This behaviour is used to define the API for a Supabase Client.
If you're implementing a [Self Managed Client](https://github.com/zoedsoupe/supabase-ex?tab=readme-ov-file#self-managed-clients) as the [Supabase.Client](https://hexdocs.pm/supabase_potion/Supabase.Client.html), this behaviour is already implemented for you.
Expand Down

0 comments on commit c017d33

Please sign in to comment.