What inside?
https://23-store.vercel.app/
Performance - 65 mobile / 99 desktop (15.07.2024)
git clone https://github.com/nicitaacom/23_store
cd 23_store
pnpm i
Commands (also available with video guide on YouTube - https://www.youtube.com/watch?v=O2D6rPJI2oM)
sudo apt update
sudo apt intall -y docker.io
sudo systemctl enable docker --now
sudo usermod -aG docker $USER
sudo reboot
docker build -t 23_store .
docker run -dp 3000:3000 23_store
To stop docker use - docker stop <container_id_or_name>
Login in supabase - https://app.supabase.com/sign-in
1. messages
create table
public.messages (
id uuid not null default gen_random_uuid (),
created_at timestamp with time zone not null default now(),
ticket_id text not null,
sender_id text not null,
sender_username text not null,
body text not null,
images text[] null,
seen boolean not null default false,
sender_avatar_url text null,
constraint messages_pkey primary key (id),
constraint messages_ticket_id_fkey foreign key (ticket_id) references tickets (id)
) tablespace pg_default;
Allow select for SUPPORT and ADMIN roles
((( SELECT users.role
FROM users
WHERE (users.id = auth.uid())) = 'SUPPORT'::text) OR (( SELECT users.role
FROM users
WHERE (users.id = auth.uid())) = 'ADMIN'::text))
2. products
create table
public.products (
price_id character varying not null,
title character varying not null,
sub_title character varying not null,
price numeric not null,
img_url character varying[] not null,
on_stock integer not null,
owner_id uuid not null,
id character varying not null,
constraint products_pkey primary key (price_id, owner_id, id),
constraint products_owner_id_fkey foreign key (owner_id) references auth.users (id) on update cascade on delete cascade
) tablespace pg_default;
Allow delete for owner_id
(owner_id = auth.uid())
insert for authenticated users
Target roles - authenticated
true
select for all users
true
update for product owners
(owner_id = auth.uid())
3. tickets
create table
public.tickets (
created_at timestamp with time zone not null default now(),
is_open boolean not null default true,
owner_username text not null,
owner_id text not null,
id text not null,
last_message_body text not null default ''::text,
owner_avatar_url text null,
rate integer null,
constraint tickets_pkey primary key (id)
) tablespace pg_default;
allow close ticket for SUPPORT and ADMIN roles
((( SELECT users.role
FROM users
WHERE (users.id = auth.uid())) = 'SUPPORT'::text) OR (( SELECT users.role
FROM users
WHERE (users.id = auth.uid())) = 'ADMIN'::text))
allow select for SUPPORT and ADMIN
((( SELECT users.role
FROM users
WHERE (users.id = auth.uid())) = 'SUPPORT'::text) OR (( SELECT users.role
FROM users
WHERE (users.id = auth.uid())) = 'ADMIN'::text))
4. users
create table
public.users (
id uuid not null,
created_at timestamp with time zone not null default now(),
username text not null,
email text not null,
avatar_url text null,
role text not null default 'USER'::text,
email_confirmed_at timestamp with time zone null,
providers text[] null default '{}'::text[],
constraint users_pkey primary key (id),
constraint users_id_fkey foreign key (id) references auth.users (id) on update cascade on delete cascade
) tablespace pg_default;
allow select for users based on their ids
(id = auth.uid())
5. users_cart
create table
public.users_cart (
id uuid not null,
created_at timestamp with time zone not null default now(),
cart_products jsonb not null default '{}'::jsonb,
constraint users_cart1_pkey primary key (id),
constraint users_cart_id_fkey foreign key (id) references auth.users (id) on update cascade on delete cascade
) tablespace pg_default;
allow select based on their id
(id = auth.uid())
allow user to update their carts
(id = auth.uid())
Authentication - Providers
Email - enabled
- Confirm email - ON
- Secure email change - ON
- Secure password change - OFF
- Mailer OTP Expiration - 86400
- Min password length - 6
Google - enabled
- Client ID (for OAuth) -
paste from .env
- Client Secret (for OAuth) -
paste from .env
Twitter - enabled
API key - paste from .env
API Secret Key - paste from .env
Authentication - Email templates
Adjust another emails for Invite user
Magic link
Change email address
Reset password
if needed
Confirm signup
<table style="max-width: 640px; width: 100%;background-color:rgb(32,32,32)" align="center">
<td style="min-width:100%;margin:0rem;padding:1rem 0rem;text-align:center"></td>
<tr>
<td style="text-align:center">
<img src="https://i.imgur.com/KmMEBux.png" alt="" style="width: 40%;" />
</td>
</tr>
<tr>
<td style="font-weight: bold; text-align:center;font-size: 18px; color: #666666; padding: 10px 0;">
Verify your email on 23_store
</td>
</tr>
<tr>
<td style="text-align: center;">
<a
href="{{ .ConfirmationURL }}"
style="display: inline-block; background-color: #4CAF50; color: #1f1f1f; padding: 10px 20px; text-align: center; text-decoration: none; border-radius: 4px; cursor: pointer; font-weight: bold;">
Verify email
</a>
</td>
</tr>
<table style="border-top:1px solid #999999;min-width:100%;margin:1rem 0rem;padding:1rem 0rem;text-align:center">
<tbody>
<tr>
<td>
<a
href="{{ .SiteURL }}/support"
style="color:rgb(64,125,237);text-decoration:none;margin:0px;font-size:0.875rem;line-height:1.25rem;text-align:center;margin-right:1rem"
target="_blank"
data-saferedirecturl="https://www.google.com/url?q={{ .SiteURL }}/support&source=gmail&ust=1696683582414000&usg=AOvVaw1cLGx1tiGtSp3MUWJAOiih"
>Support</a
>
<a
href="{{ .SiteURL }}/feedback"
style="color:rgb(64,125,237);text-decoration:none;margin:0px;font-size:0.875rem;line-height:1.25rem;text-align:center;margin-right:1rem"
target="_blank"
data-saferedirecturl="https://www.google.com/url?q={{ .SiteURL }}/feedback&source=gmail&ust=1696683582414000&usg=AOvVaw2J2syDW1hX-6J6kkisMOBZ"
>Feedback</a
>
</td>
</tr>
</tbody>
</table>
</table>
Authentication - URL Configuration
Site URL - https://23-store.vercel.app
Redirect URLs: (note that its better to don't use ** - use path without ** instead)
http://localhost:3023/\*\* (I hate prettier)
https://23-store.vercel.app/auth/callback/credentials
https://23-store.vercel.app/?modal=AuthModal&variant=resetPassword&code=**
https://23-store.vercel.app/error?error_description=**
https://23-store.vercel.app/auth/completed?code=**
https://23-store.vercel.app/**
https://23-store.vercel.app/auth/callback/oauth?provider=**
Storage
-
Create new bucked called 'public' and make 'public bucket' - ON
-
Create RLS policy for that bucket
Allow select and instert for all users
(bucket_id = 'public'::text)
I noticed only here that only authenticated users may instert so you may adjust this RLS policy if you want
stripe - https://app.supabase.com/sign-in
Alternativaly if you have problems on this step you may check guide on YouTube
how to setup resend
or how to send email using react
NEXT_PUBLIC_SUPPORT_EMAIL='your_email_where_you_send_messages_from'
It may be your email based on your domain like [email protected]
- Google - paypal developer - login/register
- Use this guide - https://developer.paypal.com/api/rest/
- Click 'Create App' - in case you haven't one
- Click on your app name in my case 'Platform Partner App - 5321855133911008505'
- login/register in coinmarketcap developer (google - coinmarketcap developer - login - etc)
pnpm dev
If you found some bug/issue - just go ahead and open a new issue