# ONYX Setup Guide Step-by-step instructions to take this project from "downloaded zip" to "live website". Total time: ~15 minutes. --- ## Part 1 — Firebase (5 min) > ✅ **Steps 1.1 and 1.2 are already done.** Your `config.js` ships with > the `onyx-preownedcars` Firebase project configured. Skip ahead to > **1.3 Enable Authentication** below. > > If you ever need to swap Firebase projects, edit the `firebase: {}` > block in `config.js` with your new project's web app config object > (Project Settings → Your apps → Web app config). ### 1.3 Enable Authentication 1. In the Firebase console sidebar → **Build → Authentication** 2. Click **Get started** 3. On the **Sign-in method** tab, click **Email/Password** 4. Toggle **Enable** ON, then **Save** ### 1.4 Create your admin account 1. Still in Authentication → click the **Users** tab 2. Click **Add user** 3. Enter the email and password you want to use (e.g. `admin@onyxcars.in` and a strong password) 4. Click **Add user** These are the credentials you'll use at `admin/login.html`. ### 1.5 Enable Firestore Database 1. In the Firebase console sidebar → **Build → Firestore Database** 2. Click **Create database** 3. **Production mode** → Next 4. Choose a location closest to your customers (for India: `asia-south1` in Mumbai or `asia-south2` in Delhi) → Enable ### 1.6 Set Firestore security rules The default rules block everything. You need rules that: - Allow anyone to **read** cars (so the public site works) - Only allow signed-in admins to **write** cars 1. In Firestore → **Rules** tab 2. Replace the contents with: ``` rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { // Cars collection: public can read; only signed-in admins can write match /cars/{carId} { allow read: if true; allow write: if request.auth != null; } } } ``` 3. Click **Publish** > ✅ Firebase is now ready. Firestore is empty — the admin will seed it > with a demo car the first time you sign in. --- ## Part 2 — Hostinger (5 min) ### 2.1 Sign in to Hostinger 1. Log into your Hostinger account 2. Open the **File Manager** for your domain (or use FTP if you prefer) 3. Navigate to `public_html/` (the web root) ### 2.2 Upload the project You have two options: **Option A — Upload everything (recommended)** Upload the **contents** of the `onyx-preowned-cars/` folder directly into `public_html/`. The structure should look like: ``` public_html/ ├── index.html ├── config.js ├── api/ │ ├── upload.php │ ├── delete.php │ └── .htaccess ├── uploads/ │ ├── .htaccess │ └── cars/ ├── images/ ├── admin/ └── ... ``` **Option B — Subfolder install** If you want the site at `yourdomain.com/onyx/` instead, upload the whole `onyx-preowned-cars/` folder. Adjust paths in your config accordingly. ### 2.3 Set folder permissions Make sure the `uploads/cars/` folder is **writable** by PHP: - In File Manager, right-click `uploads/cars/` → Permissions - Set to `755` (rwxr-xr-x) — usually already correct ### 2.4 Generate an upload token Open a terminal or visit https://randomkeygen.com and grab a "Fort Knox Password" or any long random string. You'll need this in three places. Example token: `9k3Lp_aXq8Vn4Mw2Rt6Yz1Bj7Hd5Fc0Sg` ### 2.5 Edit the PHP files on Hostinger In the File Manager, open `api/upload.php` and update these lines near the top: ```php const UPLOAD_TOKEN = 'PASTE_YOUR_RANDOM_TOKEN_HERE'; const PUBLIC_BASE_URL = 'https://onyxcars.in/uploads/cars/'; // ← your real domain const ALLOWED_ORIGINS = [ 'https://onyxcars.in', // ← your real domain 'http://localhost:8000', // optional: for dev ]; ``` Then do the same for `api/delete.php`: ```php const UPLOAD_TOKEN = 'PASTE_YOUR_RANDOM_TOKEN_HERE'; // ← same value! const ALLOWED_ORIGINS = [ 'https://onyxcars.in', 'http://localhost:8000', ]; ``` > ⚠ **Important:** The `UPLOAD_TOKEN` value MUST be identical in > `upload.php`, `delete.php`, AND `config.js`. Three places, same value. ### 2.6 Test the upload endpoint In a browser, visit `https://yourdomain.com/api/upload.php` You should see: `{"error":"Method not allowed"}` That's correct — it only accepts POST. If you see a 404 or PHP source code, something is wrong with the upload location or PHP support. --- ## Part 3 — Connect everything (3 min) ### 3.1 Edit `config.js` (Hostinger half only) Open `config.js`. The Firebase half is already filled in. You only need to update the `hostinger.*` block: ```js window.OnyxConfig = { firebase: { // ✅ Already configured — leave as-is. }, hostinger: { uploadUrl: "https://yourdomain.com/api/upload.php", // ← your domain deleteUrl: "https://yourdomain.com/api/delete.php", // ← your domain uploadToken: "9k3Lp_aXq8Vn4Mw2Rt6Yz1Bj7Hd5Fc0Sg", // ← same as PHP }, site: { // edit your phone / email / address here }, }; ``` Save the file. ### 3.2 Authorize your domain in Firebase Firebase Auth blocks sign-ins from un-authorized domains. 1. Firebase console → **Authentication → Settings → Authorized domains** 2. Click **Add domain** 3. Enter your domain: `yourdomain.com` 4. Click **Add** (`localhost` is already in the list for development.) --- ## Part 4 — Verify it works (2 min) ### 4.1 Public site Visit `https://yourdomain.com/` - The page should load with the dark luxury design - You'll see "Loading featured car..." briefly, then the seeded Toyota Innova HyCross should appear (after first admin login) ### 4.2 Admin Visit `https://yourdomain.com/admin/login.html` - Sign in with the email + password you created in Step 1.4 - You should land on the dashboard - A demo car will be seeded automatically on first login ### 4.3 Upload a real photo 1. Click **+ Add Car** 2. Drop an image into the uploader — you should see the upload progress 3. Once complete, the thumbnail should display 4. Fill in title, year, price, km 5. Click **Save & Publish** 6. Go back to the public site — your car should appear If the upload progress shows but then fails, check: - The PHP file's `UPLOAD_TOKEN` matches `config.js` - The PHP file's `ALLOWED_ORIGINS` includes your domain - The `uploads/cars/` folder exists and is writable --- ## Troubleshooting ### "Setup Required" banner doesn't go away The `isConfigured()` check in `config.js` looks for the string `REPLACE` in the values. Make sure no placeholder values remain. ### Sign-in fails with "auth/configuration-not-found" Firebase Authentication wasn't enabled. Go back to Step 1.3. ### Sign-in fails with "auth/unauthorized-domain" Your domain isn't in Firebase's authorized list. Go back to Step 3.2. ### Image upload fails with "Unauthorized" The `UPLOAD_TOKEN` in `config.js` doesn't match the one in `api/upload.php`. They must be identical strings. ### Image upload fails with CORS error The `ALLOWED_ORIGINS` in `upload.php` doesn't include the origin you're calling from. Add your domain (and `http://localhost:8000` for dev). ### Image upload succeeds but the URL doesn't load Check the `PUBLIC_BASE_URL` in `upload.php` — it should be the exact URL where uploads are publicly accessible. Example: if your uploads are saved to `public_html/uploads/cars/`, the URL is `https://yourdomain.com/uploads/cars/`. ### Cars don't appear on the public site - Open browser dev tools → Console → look for Firestore errors - Make sure the cars have `status: "published"` - Check Firestore security rules from Step 1.6 ### Firestore permission-denied errors Your security rules are too strict. Make sure read is `if true` for the `cars` collection. --- ## Security Notes This project uses a **shared secret token** (`UPLOAD_TOKEN`) to protect the upload endpoint. This is good enough for most small dealerships but not state-of-the-art. For higher security, consider: 1. **Firebase Auth + ID tokens** — verify the user's Firebase Auth token in PHP using the Firebase Admin SDK for PHP. More setup, but means only signed-in admins can upload. 2. **IP allowlist** — restrict the upload endpoint to your office IP. 3. **Cloudflare in front of Hostinger** — adds WAF, rate-limiting, and bot protection. 4. **Move to Firebase Storage** — if you're already using Firebase, their Storage service has authentication built in. You'd skip the PHP files entirely. (We use Hostinger here because you asked for it.) The current `UPLOAD_TOKEN` approach is fine if: - You keep the token secret (don't commit `config.js` to a public repo) - You enforce HTTPS (Hostinger does this by default) - You don't share the token --- That's it. Total time: about 15 minutes for a working production site with admin panel, Firebase data, and your own image hosting.