# Rarity admin setup

The client’s panel is at `/admin/`. It has Overview, Orders, Products and Settings.
Without configuration it is an explicitly labelled, read-only preview using the existing seven jerseys. There are no demo customers, fake sales or working save buttons.

## 1. Create Supabase

Create a project in the client's Supabase account. Keep the database password private.
In SQL Editor, run `supabase/schema.sql` once, followed by `supabase/seed.sql`.
The seed imports the seven existing jerseys. All stock starts at zero: enter actual counts for S, M, L and XL before enabling checkout. Re-running the seed will not overwrite products.

## 2. Create the admin account

In Authentication → Users, create an email/password user for the client. Use a strong temporary password and have the client reset it before using the panel. Do not add a signup form; ordinary registered users have no admin permissions.
Copy that user's UUID and run this in SQL Editor, substituting the actual UUID:

```sql
insert into public.admin_users(user_id) values ('REPLACE_WITH_AUTH_USER_UUID');
```

Only a database owner can grant admin access. Signing up alone cannot grant access.
Disable public signups in the Supabase Authentication settings if this project is only for this store admin.

For password recovery, set the Site URL to `https://www.raritybyadel.com/admin/` and add that exact URL to the allowed redirect URLs. Add `http://127.0.0.1:8080/admin/` only for local testing. Configure custom SMTP before handing password resets to the client; Supabase's default email service has restrictions and is for testing.

## 3. Connect Vercel

Add the following environment variables to the Rarity Vercel project:

| Variable | Value |
| --- | --- |
| `SUPABASE_URL` | The project URL, such as `https://your-project.supabase.co` |
| `SUPABASE_PUBLISHABLE_KEY` | The project's **public publishable key** (or legacy public anon key) |

Do **not** use a secret key or service-role key. The public key is intended for the browser; row-level database policies control access.
Redeploy after changing environment variables. `vercel.json` builds the site into `dist/` and serves the config through `/api/store-config`.
Build command: `npm run build`. Output directory: `dist`. Framework: Other.

## 4. Run locally

```sh
npm ci
npm run build
python3 -m http.server 8080 --bind 127.0.0.1
```

Open `http://127.0.0.1:8080/admin/` for preview mode.
For a connected local test, set the public URL and publishable key in `store-config.js`; leave it blank in production when using Vercel variables. A Python static server does not execute `/api/store-config`, so a 404 there in local preview is expected.
After editing admin source, run `npm run build` again. The generated bundle and dist directory are ignored by Git; Vercel builds them on deployment.

## What works after connection

- Password login, session persistence, sign-out and password recovery.
- All-time verified paid sales, paid orders, orders to dispatch and low-stock products.
- Add/edit products, prices, collections, descriptions, images and stock for S, M, L and XL. Hide products without deleting historical records.
- Image uploads limited to JPG, PNG and WebP, up to 5 MB.
- Product updates appear on the storefront on the next page load. Sold-out sizes cannot be added; cart quantities are capped to available stock. The catalog fails closed if the connected database is unreachable and keeps the saved cart.
- Order search and pagination, delivery status and internal notes. Product/settings/order updates detect concurrent edits instead of overwriting them silently.
- Desktop/mobile homepage images, hero headline and Instagram profile settings.

## Still pending: Paystack and new-order email alerts

Checkout remains disabled while the client's Paystack account is pending. The Orders screen is ready to read real orders, but does not manufacture orders or payments. Email alerts are explicitly marked not connected.

The future trusted checkout backend must:

1. Calculate prices and shipping from the database, not browser totals.
2. Reserve/reduce inventory atomically so simultaneous purchases cannot oversell.
3. Insert pending orders using server-only access. `orders.items` must be a snapshot array of `{baseId, title, size, qty, price}`; `total` is in GHS, including shipping. Keep Paystack amounts in pesewas at the API boundary.
4. Verify signed Paystack webhooks, transaction reference, currency and expected amount, handling retries idempotently. Only this trusted backend can set `payment_status` to `paid`, `failed` or `refunded`.
5. Send the client one new-order email after verified payment, using a transactional email provider with retries and deduplication. Configure the recipient privately; never expose service credentials in the browser.

Delivery statuses progress from pending → processing → dispatched → delivered, only for paid orders. Unpaid pending orders can be cancelled. Refunds/payment changes are deliberately unavailable to browser clients.

## Verification before client handoff

- Sign in as the admin and test a product edit and photo upload.
- Open the shop signed out and confirm price, image, visibility and size stock updates.
- Test a non-admin user: no access to orders, editing or image uploads.
- Test a password reset email on the production domain with SMTP configured.
- Once Paystack is integrated, test paid/failed/retried transactions and simultaneous stock changes before opening checkout.

Run `npm test` for cart and admin validation tests. Run `npm run test:database` if local PostgreSQL tools are installed for isolated database permission and workflow tests.

Sources: [Supabase password auth](https://supabase.com/docs/guides/auth/passwords), [database access policies](https://supabase.com/docs/guides/database/postgres/row-level-security), [storage access control](https://supabase.com/docs/guides/storage/security/access-control).
