# Prompt Vault

A local Laravel build of a curated AI-video-prompt library, modelled on the structure of
soniprompts.com: a browsable prompt catalogue split into free and members-only tiers, user
accounts, membership gating, and an admin panel for managing content.

Styling and all prompt content are original to this build.

## Stack

| Layer | Choice |
| --- | --- |
| Framework | Laravel 13.26 (PHP 8.3) |
| Views | Blade + Tailwind CSS 4 (Vite) |
| Database | SQLite (`database/database.sqlite`) |
| Auth | Hand-rolled session auth (register / login / logout) |
| Tests | PHPUnit — 25 feature tests |

Livewire 4 and Volt are installed to match the other Laravel projects in `C:\laragon\www`,
but the current pages don't use them — browsing is query-string driven so results stay
linkable and crawlable. Remove them with `composer remove livewire/livewire livewire/volt`
if you'd rather not carry the dependency.

## Running it

```bash
php artisan serve --port=8123
```

Then in a second terminal, for asset watching:

```bash
npm run dev
```

`APP_URL` is set to `http://prompt.test`, so Laragon's auto-vhost will also serve it at that
hostname once Laragon reloads — the folder sits in `www/prompt` and points at `public/`.

## Demo accounts

Seeded by `DatabaseSeeder`. All use the password `password`.

| Email | Role |
| --- | --- |
| `admin@prompt.test` | Admin — full panel access, sees everything |
| `member@prompt.test` | Paying member — premium prompts unlocked |
| `free@prompt.test` | Free account — premium prompts locked |

Reset the data at any time:

```bash
php artisan migrate:fresh --seed
```

## What's in it

**Public**
- `/` — hero, stats, category chips, featured / free / premium rails
- `/prompts` — search, category filter, free-vs-premium filter, pagination
- `/prompts/{slug}` — detail page with copy-to-clipboard, related prompts, save-to-library
- `/social`, `/join` (pricing + FAQ), `/legal/{privacy,terms,refunds}`

**Members**
- Register / login / logout
- `/dashboard` — membership status and saved-prompt library
- Save prompts to a personal library

**Admin** (`/admin`, requires `is_admin`)
- Overview with content and membership stats
- Prompt CRUD — thumbnail upload or URL, premium / published / featured flags
- Category management (inline edit)
- User list — grant or revoke membership, promote to admin

## How gating works

`Prompt::isUnlockedFor(?User)` is the single decision point, backed by
`User::hasPremiumAccess()` (admins always pass; members pass while `premium_until` is null or
in the future).

Locked prompts never send the real prompt text to the browser — the blurred block on the
detail page is decorative filler. A CSS blur is not access control, and a short prompt would
otherwise be fully readable in the page source.

## Payments

There is no payment gateway. `MembershipController` flips `is_premium` directly so the gated
experience can be exercised end to end, and admins can grant or revoke membership by hand.
Swap that controller for Cashier/Stripe or Razorpay checkout when you wire up a real gateway
— nothing else needs to change, since everything reads through `hasPremiumAccess()`.

## Switching to MySQL

The build defaults to SQLite so it runs with no credentials. To match the other projects here,
create the database and user, then update `.env`:

```
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=soniprompts
DB_USERNAME=soniprompts
DB_PASSWORD=<your password>
```

Then re-run `php artisan migrate:fresh --seed`. The migrations are portable — no SQLite-only
column types are used.

## Tests

```bash
php artisan test
```

Covers premium gating (guest, free user, member, expired member), draft visibility, search and
filtering, view counting, registration and login, the mock checkout, favourites, and admin
authorisation and CRUD.
