# Joomla Market — cPanel deployment

Your PHP + SQLite + React + Tailwind marketplace is prebuilt. **No Node.js server, npm, Composer or build step is required on your hosting.**

## 1. Hosting requirements

- Apache/LiteSpeed cPanel hosting with PHP 8.2 or later.
- PHP extensions: PDO SQLite, sqlite3, GD, mbstring, fileinfo, cURL and OpenSSL.
- HTTPS enabled for the website, especially Google authentication.
- PHP must be able to write to `joomla-private/` and `public_html/uploads/`.
- The included `.user.ini` requests 8 MB per image, 55 MB total POST, six uploads and 256 MB PHP memory. Confirm these values in your host's PHP settings; some providers override `.user.ini`.

## 2. Upload the folders

In cPanel File Manager, open your account home directory (one level ABOVE `public_html`).

1. Back up an existing website before replacing its files.
2. Put the CONTENTS of this package's `public_html` folder into your domain's `public_html` folder. Include `.htaccess` and `.user.ini` — enable “Show Hidden Files” in File Manager.
3. Put the `joomla-private` folder NEXT TO `public_html`, not inside it.
4. Keep `src`, `tests`, `previews`, package files and this guide on your computer. They are not needed for hosting.

The resulting folders should be:

| Location | Contents |
|---|---|
| `/home/YOUR_ACCOUNT/public_html/` | index.html, api.php, google-auth.php, lib.php, .htaccess, .user.ini |
| `/home/YOUR_ACCOUNT/public_html/assets/` | Compiled JS/CSS and generated images |
| `/home/YOUR_ACCOUNT/public_html/uploads/` | Watermarked seller photographs |
| `/home/YOUR_ACCOUNT/joomla-private/` | config.php, demo.json, reset-password.php; SQLite database is created during setup |

The Google secret is already in **joomla-private/config.php**. Keep that folder and this delivery ZIP private. Do not place the ZIP in a publicly accessible website directory. Do not commit config.php to Git. If you change hosting layout, update the private config path in lib.php accordingly.

Typical cPanel permissions are 755 for public folders and 644 for public files. Start with 700 for the private folder and 600 for its config/database, owned by your account. Hosting PHP handlers differ: if writes fail, ask the host for owner-writable permissions rather than making everything 777.

## 3. Set the installation key

Edit `joomla-private/config.php` and replace only:

`CHANGE_THIS_TO_A_LONG_RANDOM_SECRET`

with a unique random secret of at least 24 characters. This protects first-admin setup from visitors. The installer will refuse the placeholder. Do not change the Google credential values unless you are replacing those credentials.

## 4. Create your administrator account

1. Visit your HTTPS domain in a browser.
2. The first-run setup page appears automatically.
3. Enter your installation key, full website URL (for example `https://yourdomain.com`, without a final slash), name, email and a password of at least 12 characters.
4. Submit. The app creates the SQLite database and eight AI-generated sample listings.
5. Open the menu → **Admin dashboard**, or visit `https://yourdomain.com/#admin`.

There is no shared or hard-coded administrator password. You choose your credentials. Setup locks after the first administrator is created. You can connect the admin account to Google later from My account, using the same email address.

## 5. Finish Google signup/login configuration

Your supplied client ID and secret are already connected on the PHP server. To activate real logins on your domain:

1. Open Google Cloud / Google Auth Platform and select the project containing your OAuth client.
2. Make sure the client is a **Web application**.
3. Add this **Authorized redirect URI**, replacing the example domain:

   `https://yourdomain.com/google-auth.php`

4. Use exactly the same domain, HTTPS scheme and path as your setup website URL. `www` and non-`www` count as different hosts.
5. Set up the consent screen, app name “Joomla Market”, homepage and privacy URLs. The app's privacy page is `https://yourdomain.com/#privacy`.
6. Confirm the app's audience/publishing configuration permits the accounts you want to use, and add test users if required by your Google project configuration.
7. In Joomla Market, choose Sign in → Continue with Google. New Google users create accounts automatically. They must add a phone number in My account before posting an ad.

The exact callback URL is also shown in **Admin → Settings**. No JavaScript client secret is exposed. The server uses authorization code flow, state verification, PKCE, Google's HTTPS userinfo endpoint and the stable Google account subject identifier.

Existing password accounts are NOT silently merged by email. Sign in with your password first and use **My account → Connect Google account**. Google-only accounts manage their Google password in Google.

**Google login has been implemented and its local redirect/security behavior tested. A complete live Google login cannot be verified until you register the actual domain callback and deploy it.**

Reference: https://developers.google.com/identity/openid-connect/openid-connect

## 6. Control demo listings

Open **Admin → Overview** or **Admin → Settings**.

- **Demo listings ON:** all visible demo listings remain alongside real seller listings. Real uploads do not remove them.
- **Demo listings OFF:** sample ads disappear from public browsing, search, saved listings and direct public listing links.
- Real active listings remain visible either way.
- Turning the switch back on restores the demo listings. It does not delete seller data.
- Demo listings are clearly labeled and cannot receive buyer messages. The admin can always inspect them.

All dashboard totals come from your database. “Real listings” excludes demo ads; no fake visitors, sales figures or reviews are added.

## 7. Moderate your marketplace

- **Review before publishing ON** (default): new and edited seller ads wait for admin approval.
- Open **Admin → Listings**, choose Pending review, then change a listing to Active or Rejected.
- With moderation OFF, future new/edited ads publish immediately. Existing pending ads still need a decision.
- Feature/unfeature an ad with its feature button in the admin table.
- Review user reports; resolve a report and separately reject/delete its listing if appropriate.
- Suspend/restore member accounts. Suspension blocks their account access immediately; review and hide any unsafe listings separately.

## 8. Seller and buyer features

- Email/password and Google accounts, profile editing and password changes for password accounts.
- Search, eight categories, Nigerian locations, price filter, price sorting and pagination.
- Saved ads, product gallery, seller contact number, copyable listing links and reports.
- Post/edit ads with up to six photos; delete an ad or mark it sold.
- Private buyer–seller messaging with inbox refresh every 15 seconds while open.
- Automatic permanent **Joomla Market** watermark on every uploaded image; originals are not kept publicly.
- Responsive desktop, tablet and phone layouts, mobile navigation and accessible form labels.

This is a Jiji-style classifieds marketplace: buyers and sellers arrange payment and collection directly. It does not include a checkout/payment gateway, escrow, shipping, SMS/email notifications, seller identity verification or email password-reset delivery. No paid ad billing is implemented; featuring is controlled by the administrator. These services need separate provider configuration if added later.

## 9. Backups and recovery

Back up `joomla-private/market.sqlite`, private configuration and the entire `public_html/uploads/` folder together. Take backups when no writes are in progress, or use SQLite's backup command/tool. Keep the backup outside the public website.

If a password account loses access, a server owner with PHP CLI can run from the account home directory:

`php joomla-private/reset-password.php user@example.com`

The CLI utility asks for a new password; it does not accept recovery requests over HTTP. It can also add password login to a Google-only account. This is owner-assisted recovery, not a public reset form.

For upgrades, preserve the database, config.php and uploads. Do not reinstall or replace them with empty copies.

## 10. Troubleshooting

- **Database/500 error:** confirm PDO SQLite is enabled and the private folder is writable. Check cPanel PHP error logs.
- **Blank page/assets fail:** copy all built assets and index.html together; do not upload src/app.jsx as the website.
- **Google redirect_uri_mismatch:** copy the exact Admin → Settings callback into Google Cloud.
- **Google returns to sign-in:** verify the website URL matches the host you're visiting, HTTPS is active, PHP sessions can persist, cURL is enabled and the host can access Google HTTPS endpoints.
- **Photos fail:** enable GD, fileinfo and mbstring; check upload limits and writable uploads folder. JPG, PNG and WebP only; images must be at least 200×200 and no more than 24 megapixels.
- **Ad missing after upload:** check My listings. Pending ads need admin approval. Sold/rejected/archived ads are not public.
- **Database/settings not found after moving domain:** use SQLite administration or your developer to update the `site_url` value in the settings table, then update Google Cloud's redirect URI.
- **403 on uploads:** ensure your host permits reading JPG files and honors the supplied uploads .htaccess.

## Development

React source: `src/app.jsx`.
Tailwind + custom responsive styles: `src/styles.css`.
PHP API: `public_html/api.php`; shared database/session/upload functions: `public_html/lib.php`.
Google flow: `public_html/google-auth.php`.

For local source edits, install Node.js, run `npm ci` then `npm run build`. Upload the regenerated `public_html/assets/app.js` and `app.css` along with any PHP changes. Build tools are not required on cPanel.

The application is optimized for an initial marketplace on ordinary shared hosting. SQLite serializes writes; high concurrent traffic, large media libraries, large message histories and more than 1,000 admin rows warrant pagination/storage/database upgrades and production load testing.
