# Start here

Four documents, in the order you need them.

| Read this | When |
|---|---|
| **`UPLOAD-TO-GODADDY.md`** | Now. Step by step: upload, two migrations, add three API keys, connect each site's CMS. About fifteen minutes. |
| **`UI-UX-REVIEW.md`** | After it is running. Every screen, why it is shaped the way it is, and a ranked list of what to do next. |
| **`CHANGELOG.md`** | The same thing in commit-note form, including what was found and fixed before release, and what everything costs. |
| **`MANIFEST.md`** | Only if the folder structure is unclear. Every path in the package, each marked FOLDER or file. |

---

## The one-paragraph version

This build does what you asked for: **competitor analysis per country**, then
**article recommendations for SEO and AI SEO**, laid out on **a calendar of two
articles a week per site**. You review each draft, and one click publishes it —
with a generated image — straight to that site's WordPress, Shopify, Wix or your
own custom site. Generated images carry no logo, brand name or product name.

Nothing reaches a live website until a person presses **Approve**. Editing the
text after approval withdraws the approval, because approval means a human read
*exactly that text*.

---

## The three-minute version of the upload

1. Back up `public_html/aiseo` in cPanel File Manager (Compress → zip).
2. Upload and extract `aiseo-3.0.zip` into `public_html/aiseo`, overwriting.
   `.env` is not in the zip, so your credentials survive — **do not delete the
   folder first.**
3. Open `https://www.dghanalytics.com/aiseo/` → "Open migrate-web.php" → tick →
   **Run migrations**. `007` and `008` are new; everything else is skipped.
4. Delete `setup-env.php`, `migrate-web.php` and `preflight.php`. The app shows
   an orange banner until you do.
5. Add three keys to `.env`: `DATAFORSEO_*` (you have these), `ANTHROPIC_API_KEY`
   and `OPENAI_API_KEY`. Each has its own hard daily cap right beneath it.
6. **Publishing** in the sidebar → for each site, pick the platform, fill in the
   credentials, press **Save and test the connection**. An untested connection
   cannot publish; that is enforced.
7. **Analyze** → tick your markets → **Save markets** → **Analyze**.

Then wait five minutes for the worker cron, and look at **Opportunities** and
**Calendar**.

---

## What it costs

| Action | Cost |
|---|---|
| One country analysed | roughly **$1** |
| One 1,500-word article | a few cents |
| One hero image | **$0.041** |
| Two articles a week, one site | under **$1 a month** in text and images |

The three caps in `.env` are hard stops. A run that hits one says so, rather than
reporting an empty result and leaving you to guess.

---

## The one thing that will stop everything

**The worker cron.** Every button that costs money queues a job; the worker is
what runs it. Without it, "Analyze", "Write the draft", "Generate the image" and
"Publish" all accept the click and nothing ever happens.

cPanel → Cron Jobs, every 5 minutes:

```
cd ~/public_html/aiseo && /usr/local/bin/php bin/worker.php --max-jobs=20 >> var/logs/cron.log 2>&1
```

The dashboard says when this is missing, and any article left mid-job for ten
minutes shows a banner saying the same thing with a button to get it unstuck.

---

## Also still worth doing

**`APP_URL` in `.env`** should read:

```
APP_URL=https://www.dghanalytics.com/aiseo
```

Pages work regardless — the app derives its path from the filesystem — but the
Google OAuth redirect URI is built from `APP_URL` and cannot self-correct.

---

## If something goes wrong

Open `preflight.php` (it is in this zip). It reports the PHP version, missing
extensions, resolved folders, whether every source file parses, whether `.env` is
readable *by PHP specifically*, and the tail of the error log — then gives a
ranked verdict. Delete it again afterwards.

Locked out of every account? There is no back door by design. In phpMyAdmin, run
`DELETE FROM app_user;` and reload the app — with the table empty it offers the
"create the first administrator" screen again. Sites, runs, findings and articles
live in other tables and are untouched.
