Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4dfb97ad91 | |||
| 05818099e6 |
@ -72,9 +72,6 @@ function injectBrandStyles() {
|
||||
/* Hide Fleetbase-branded user menu links */
|
||||
.support-user-nav-item,.docs-user-nav-item{display:none!important}
|
||||
a[href*="discord.gg"]{display:none!important}
|
||||
|
||||
/* Hide "Launch app" link in Storefront sidebar (points to GitHub) */
|
||||
a.next-nav-item:has([data-icon="rocket"]){display:none!important}
|
||||
`;
|
||||
document.head.appendChild(style);
|
||||
}
|
||||
|
||||
443
fleetbase-source/AGENTS.md
Normal file
@ -0,0 +1,443 @@
|
||||
# AGENTS.md — Fleetbase
|
||||
|
||||
## Architecture
|
||||
|
||||
- **Dual-stack monorepo:** Laravel 10 (PHP) backend + Ember.js 5.4 frontend + 12 Git submodules
|
||||
- **Docker services:** `application` (FrankenPHP/Caddy :8000), `httpd` (:80→8000), `console` (Nginx :4200), `socket` (SocketCluster :38000), `database` (MySQL 8.0 :3306), `cache` (Redis), `queue`, `scheduler`
|
||||
- **Console port 4200**, **API port 8000** — both must be free or mapped differently
|
||||
- **Packages:** Each `packages/<name>/` is a Git submodule; contains PHP (`composer.json` + `server/`) and/or Ember code (`addon/`, `app/`, `extension.json`)
|
||||
- **Core packages:** `core-api`, `ember-core`, `ember-ui`, `dev-engine` — framework layers all extensions depend on
|
||||
|
||||
## Prerequisites & Constraints
|
||||
|
||||
- **PHP >= 8.0, <= 8.2.30** (strict upper bound — 8.3+ will break)
|
||||
- **Node.js >= 22**
|
||||
- **pnpm** is the JS package manager (not npm/yarn) — `pnpm@11.0.9`
|
||||
- **Composer** uses private registry at `https://registry.fleetbase.io` — authentication may be required for private packages
|
||||
- Git submodules must be initialized: `git submodule update --init --recursive`
|
||||
|
||||
## Commands
|
||||
|
||||
### Docker (most common)
|
||||
```bash
|
||||
docker compose up -d # Start all services
|
||||
docker compose exec application bash # Shell into API container
|
||||
docker compose exec application php artisan … # Run artisan commands
|
||||
docker compose exec application bash -c "./deploy.sh" # Run deployment script
|
||||
```
|
||||
|
||||
### Backend (api/)
|
||||
```bash
|
||||
cd api && composer install # Install PHP deps (uses fleetbase registry)
|
||||
cd api && php artisan … # Laravel artisan (run inside container or locally with DB access)
|
||||
cd api && php artisan test # Run PHPUnit tests
|
||||
cd api && ./vendor/bin/php-cs-fixer fix # Fix PHP style
|
||||
cd api && vendor/bin/phpstan analyse # Static analysis (in packages with phpstan.neon.dist)
|
||||
```
|
||||
|
||||
### Frontend (console/)
|
||||
```bash
|
||||
cd console && pnpm install # Install JS deps
|
||||
cd console && pnpm start # Ember dev server (requires API + socket running)
|
||||
cd console && pnpm lint # ESLint + stylelint + template-lint
|
||||
cd console && pnpm test # Lint + ember test (QUnit via Testem)
|
||||
cd console && pnpm build # Production build → dist/
|
||||
```
|
||||
|
||||
### Single test runs
|
||||
```bash
|
||||
cd api && php artisan test --filter=MyTest # PHP: single test class
|
||||
cd api && php artisan test --filter=MyTest::testFoo # PHP: single test method
|
||||
cd console && pnpm test --filter='My test name' # Ember: filter by test name
|
||||
cd console && pnpm test --server # Ember: watch mode
|
||||
```
|
||||
|
||||
## Extensions (Custom Packages)
|
||||
|
||||
Each extension is a Git submodule under `packages/<name>/` with this structure:
|
||||
```
|
||||
extension.json # Metadata (name, version, engine, api)
|
||||
composer.json # PHP dependencies (if has API)
|
||||
package.json # JS dependencies (if has Ember engine)
|
||||
server/ # PHP API code (PSR-4)
|
||||
addon/ # Ember engine files
|
||||
app/ # Ember app files
|
||||
```
|
||||
|
||||
### Scaffold a new extension
|
||||
```bash
|
||||
flb scaffold # CLI wizard
|
||||
# Or manually: create packages/<name>/ with extension.json, composer.json, package.json
|
||||
# Register it as submodule: git submodule add <repo-url> packages/<name>
|
||||
```
|
||||
|
||||
### Link local extensions for development
|
||||
```bash
|
||||
node scripts/package-linker.mjs # Symlink all packages/ into api/ and console/
|
||||
```
|
||||
|
||||
### Package registry flow
|
||||
```bash
|
||||
flb register # One-time: create registry account
|
||||
flb verify -e <email> -c <code> # Verify email
|
||||
flb generate-token -e <email> # Get auth token
|
||||
flb set-auth <token> # Save token for installs
|
||||
flb install fleetbase/<extension> # Install extension from registry
|
||||
```
|
||||
|
||||
## Production Deployment (VPS: 37.27.183.102)
|
||||
|
||||
```
|
||||
SSH key: Config/fleet_key (chmod 600, OpenSSH RSA private key)
|
||||
SSH command: ssh -i Config/fleet_key root@37.27.183.102
|
||||
```
|
||||
|
||||
### Key env vars for production (docker-compose.override.yml)
|
||||
- `ENVIRONMENT=production`, `APP_DEBUG=false`
|
||||
- `APP_KEY` — generate with `docker compose exec application bash -c "php artisan key:generate --show"`
|
||||
- `APP_URL`, `CONSOLE_HOST` — set to actual domain/IP
|
||||
- `SESSION_DOMAIN` — domain for session cookies
|
||||
- `SOCKETCLUSTER_OPTIONS` — restrict origins to production domains
|
||||
- `MAIL_*` — configure real mailer (not log driver)
|
||||
- `FILESYSTEM_DRIVER=s3` — S3 for file storage (not local disk)
|
||||
- `GOOGLE_MAPS_API_KEY`, `IPINFO_API_KEY`, `TWILIO_*` — for full feature set
|
||||
- `REGISTRY_HOST`, `REGISTRY_PREINSTALLED_EXTENSIONS` — extension registry config
|
||||
- `OSRM_HOST` — routing engine URL
|
||||
|
||||
### Production checklist
|
||||
1. Copy repo to server, run `docker compose up -d` (with correct override)
|
||||
2. Ensure ports 80/443/8000/4200/38000 are open in firewall
|
||||
3. Set up SSL/reverse proxy (Caddyfile for API, Nginx for console)
|
||||
4. Use external/managed MySQL in production (not bundled container)
|
||||
5. S3 for file storage (not local disk)
|
||||
6. Restrict `SOCKETCLUSTER_OPTIONS` origins
|
||||
|
||||
## Environment File Locations
|
||||
|
||||
| Env | Notes |
|
||||
|-----|-------|
|
||||
| `docker-compose.override.yml` | **Primary** — env vars injected into all Docker services |
|
||||
| `api/.env` | Only needed for local PHP runs outside Docker |
|
||||
| `api/.env.example` | Template reference |
|
||||
| `console/environments/.env.development` | Ember dev env |
|
||||
| `console/environments/.env.production` | Ember prod env |
|
||||
|
||||
## Git Submodule Gotchas
|
||||
|
||||
- Always `git submodule update --init --recursive` after clone
|
||||
- Submodules track specific commits — working on a package means committing inside `packages/<name>/` first, then updating the parent repo's submodule pointer
|
||||
- After `git pull` in parent, run `git submodule update --recursive` to sync submodules
|
||||
- Package linker script (`scripts/package-linker.mjs`) symlinks submodules into api/console/ for local dev — run it after changing module structure
|
||||
|
||||
## Linting (all layers)
|
||||
|
||||
| Layer | Tool | Command |
|
||||
|-------|------|---------|
|
||||
| PHP | php-cs-fixer | `./vendor/bin/php-cs-fixer fix` (in api/ or package) |
|
||||
| PHP | PHPStan | `vendor/bin/phpstan analyse` (in packages with neon config) |
|
||||
| JS | ESLint + Prettier | `pnpm lint` (in console/) |
|
||||
| CSS | Stylelint | `pnpm lint:css` |
|
||||
| Templates | ember-template-lint | `pnpm lint:hbs` |
|
||||
| i18n | fleetbase-intl-lint | `pnpm lint:intl` |
|
||||
|
||||
## Conventions
|
||||
|
||||
- Ember Octane edition — use Glimmer components (`@glimmer/component`), `<template>` tags, `@tracked`
|
||||
- Tailwind CSS 3.4 is the styling framework, `inter-ui` is the typeface
|
||||
- PHP controllers return API resources via `\App\Http\Resources\` namespace
|
||||
- Caddy replaces traditional Nginx/Apache for the API server (FrankenPHP)
|
||||
- SocketCluster handles real-time WebSocket connections
|
||||
- Prettier config: 4-space tabs, single quotes for JS, double quotes for HBS, 190 print width
|
||||
|
||||
---
|
||||
|
||||
## Session: 2026-05-24 — Biibaye Branding Extension
|
||||
|
||||
### Branch Strategy
|
||||
|
||||
- **main**: Clean upstream from `github.com:fleetbase/fleetbase`. Never commit here — only `git pull`.
|
||||
- **custom-production**: Working branch with custom branding + WhatsApp alterations. Created off `main` at v0.7.41.
|
||||
|
||||
### Private Git Repo
|
||||
|
||||
- **URL**: `ssh://git@git.1.warancloud.com:2222/Ali/biibaye.git`
|
||||
- **SSH Key**: `~/.ssh/deploy_key` (same key present on both local and VPS)
|
||||
- **SSH Config entry** (on VPS at `/root/.ssh/config`):
|
||||
```
|
||||
Host git.1.warancloud.com
|
||||
IdentityFile ~/.ssh/deploy_key
|
||||
IdentitiesOnly yes
|
||||
AddKeysToAgent yes
|
||||
port 2222
|
||||
user git
|
||||
```
|
||||
|
||||
### New Extension: `packages/biibaye-branding/`
|
||||
|
||||
Git submodule pointing at private repo. Provides all custom branding:
|
||||
|
||||
```
|
||||
packages/biibaye-branding/
|
||||
├── extension.json # "Biibaye Branding" v1.0.0
|
||||
├── package.json # @biibaye/branding, fleetbase-extension + ember-engine keywords
|
||||
├── index.js # Ember addon entry
|
||||
├── config/environment.js # Engine config
|
||||
├── addon/
|
||||
│ ├── engine.js # Minimal Ember Engine (required by Fleetbase build system)
|
||||
│ └── extension.js # Branding logic — runs at Ember boot
|
||||
└── public/
|
||||
├── favicon/ # 22 Biibaye-branded icon files (apple-icon-*, android-icon-*, ms-icon-*)
|
||||
└── images/ # logo SVGs, icon PNGs
|
||||
```
|
||||
|
||||
**extension.js** does 5 things on boot:
|
||||
1. `document.title = "Biibaye - Delivery System"` (in both setupExtension and onEngineLoaded)
|
||||
2. `intl.addTranslations('en-us', { 'app.name': 'Biibaye' })` — runtime translation injection
|
||||
3. Injects CSS: `--primary: #FF4500`, dark theme `background-color: #343538`
|
||||
4. Replaces all `<link rel="icon">` / `<link rel="apple-touch-icon">` with Biibaye files
|
||||
5. Updates meta tags: `msapplication-TileColor`, `theme-color`, `msapplication-TileImage`
|
||||
|
||||
**Why `translations/en-us.yaml` was removed:** ember-intl merges translations at build time with host app files taking HIGHEST priority. `console/translations/en-us.yaml` defines `app.name: Fleetbase`, which always wins over any addon's `app.name`. Other Fleetbase extensions avoid this by using namespaced keys (e.g., `fleet-ops.*`, `storefront.*`). Solution: in `overrideAppName()`, look up the intl service from `appInstance` and call `intl.addTranslations('en-us', { 'app.name': 'Biibaye' })` at runtime.
|
||||
|
||||
**Key implementation detail:** `setupExtension()` calls `universe.extensionManager.ensureEngineLoaded('@biibaye/branding')` to force the engine to boot. Without this, the engine never loads (root-mounted engines have no route to trigger boot). `onEngineLoaded` re-sets translation and title after boot, defeating any race with ember-page-title re-render.
|
||||
|
||||
### Deploy Script: `/opt/fleetbase/scripts/deploy-biibaye.sh`
|
||||
|
||||
Located on VPS. Handles the Docker build context issue (console build context is `./console/`, not repo root). Steps:
|
||||
|
||||
1. `git pull origin main` in extension submodule
|
||||
2. Copies extension into `console/packages/biibaye-branding/` (Docker build context)
|
||||
3. Copies `public/favicon/*` and `public/images/*` into `console/public/` (so files serve from root `/favicon/*` URLs)
|
||||
4. **NEW — Patch `console/app/index.html`:** Replace Fleetbase defaults to prevent branding flash during reload:
|
||||
```bash
|
||||
sed -i 's|<title>Fleetbase Console</title>|<title>Biibaye - Delivery System</title>|' console/app/index.html
|
||||
sed -i 's|content="#da532c"|content="#FF4500"|' console/app/index.html
|
||||
sed -i 's|content="#ffffff"|content="#FF4500"|' console/app/index.html
|
||||
sed -i 's|href="/favicon/apple-touch-icon.png"|href="/favicon/apple-icon-180x180.png"|' console/app/index.html
|
||||
sed -i 's|href="/favicon/android-chrome-192x192.png"|href="/favicon/android-icon-192x192.png"|' console/app/index.html
|
||||
sed -i 's|href="/favicon/android-chrome-256x256.png"|href="/favicon/android-icon-144x144.png"|' console/app/index.html
|
||||
sed -i 's|color="#5bbad5"|color="#FF4500"|' console/app/index.html
|
||||
```
|
||||
5. **NEW — Patch `console/tailwind.config.js`:** Replace sky-500 blue (#3485e2) palette with Biibaye orange (#FF4500). This is the PRIMARY fix for the color theme — without this, Fleetbase shows blue buttons/accents because all UI uses Tailwind `sky-*` classes directly:
|
||||
```bash
|
||||
sed -i "s/'#e6f0fb'/'#FFF0E6'/" console/tailwind.config.js
|
||||
sed -i "s/'#bad5f5'/'#FFD0B3'/" console/tailwind.config.js
|
||||
sed -i "s/'#8dbbef'/'#FFB380'/" console/tailwind.config.js
|
||||
sed -i "s/'#61a0e8'/'#FF7A33'/" console/tailwind.config.js
|
||||
sed -i "s/'#3485e2'/'#FF4500'/" console/tailwind.config.js
|
||||
sed -i "s/'#1c6cc7'/'#E03D00'/" console/tailwind.config.js
|
||||
sed -i "s/'#16539a'/'#B33100'/" console/tailwind.config.js
|
||||
sed -i "s/'#103b6d'/'#8A2600'/" console/tailwind.config.js
|
||||
sed -i "s/'#092341'/'#611A00'/" console/tailwind.config.js
|
||||
```
|
||||
6. Adjusts pnpm workspace paths for Docker (`../packages/` → `packages/`)
|
||||
7. Injects `COPY packages/ packages/` before `pnpm install` in Dockerfile (so pnpm resolve the link dependency)
|
||||
8. Removes `--frozen-lockfile` during build (new dep not in lockfile)
|
||||
9. Runs `docker compose build console --no-cache`
|
||||
10. Restores all original configs (Dockerfile, package.json, workspace, index.html, tailwind.config.js) — **restore is critical to keep the clean checkout intact**
|
||||
11. Restarts console, httpd, application containers
|
||||
|
||||
**Why both tailwind.config.js patching AND extension.js CSS injection?**
|
||||
|
||||
- **tailwind.config.js patching** (build-time): Changes primary color at the Tailwind compilation level. This prevents the blue flash because the compiled `@fleetbase/console.css` already contains orange colors. However, `ember-ui`'s pre-compiled CSS in `vendor.css` (like `.btn.btn-primary`) uses `#3485e2` at `@apply` compile time and is NOT affected by the console's tailwind config.
|
||||
- **extension.js CSS injection** (runtime): Acts as a safety net, overriding any blue that leaks through from `vendor.css` with `!important` rules. Covers the gap where ember-ui's pre-compiled CSS still references blue.
|
||||
|
||||
**To update branding assets in the future:**
|
||||
```bash
|
||||
# Locally: replace files in packages/biibaye-branding/public/ then:
|
||||
cd packages/biibaye-branding
|
||||
git add -A && git commit -m "Update assets" && git push origin main
|
||||
|
||||
# On VPS:
|
||||
ssh root@37.27.183.102
|
||||
/opt/fleetbase/scripts/deploy-biibaye.sh
|
||||
```
|
||||
|
||||
### VPS Changes Made (37.27.183.102)
|
||||
|
||||
| What | Where | Details |
|
||||
|------|-------|---------|
|
||||
| `custom-production` branch | `/opt/fleetbase/` | Created off `main`, committed submodule addition |
|
||||
| `packages/biibaye-branding` submodule | `/opt/fleetbase/.gitmodules` | Points at private repo |
|
||||
| `APP_NAME: "Biibaye"` | `docker-compose.override.yml` | Was "Fleetbase" |
|
||||
| `MAIL_FROM_NAME: "Biibaye"` | `docker-compose.override.yml` | Was "Fleetbase" |
|
||||
| `EXTENSIONS: "@biibaye/branding"` | `console/fleetbase.config.json` | Critical — without this extension.js never runs |
|
||||
| SSH config | `/root/.ssh/config` | Added git.1.warancloud.com entry |
|
||||
| SSH key | `/root/.ssh/deploy_key` | Copied for private repo access |
|
||||
| Deploy script | `/opt/fleetbase/scripts/deploy-biibaye.sh` | Rebuilds console with branding |
|
||||
|
||||
### VPS State (Pre-existing)
|
||||
|
||||
| What | Value |
|
||||
|------|-------|
|
||||
| Fleetbase version | v0.7.41 |
|
||||
| Domains | `api.biibaye.com`, `console.biibaye.com`, `socket.biibaye.com` |
|
||||
| `.env.development` | API: `http://37.27.183.102:8000` |
|
||||
| `.env.production` | API: `https://api.biibaye.com` |
|
||||
| `fleetbase.config.json` | API/Socket prod URLs |
|
||||
| Docker services | All running (scheduler unhealthy — pre-existing) |
|
||||
|
||||
### Branding Spec
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| App name | Biibaye |
|
||||
| Window title | Biibaye - Delivery System |
|
||||
| Primary color | #FF4500 |
|
||||
| Dark theme background | #343538 |
|
||||
| Favicon files | 22 Biibaye-branded icons (apple-icon-*, android-icon-*, ms-icon-*) |
|
||||
| Logo files | SVG-02.svg, icon.svg, icon.png, fleetbase-logo-svg.svg |
|
||||
|
||||
### Troubleshooting: app.name Translation
|
||||
|
||||
**Problem:** `{{t "app.name"}}` still shows "Fleetbase" after extension loaded.
|
||||
|
||||
**Root cause:** ember-intl v6.3.2 build-time merge gives host app (`console/translations/en-us.yaml`) priority over addon translations. Key `app.name: Fleetbase` at line 2 of console translations defeats any addon override.
|
||||
|
||||
**Fix:** Instead of relying on build-time `translations/en-us.yaml`, use runtime injection via `intl.addTranslations()`:
|
||||
```js
|
||||
// In setupExtension + onEngineLoaded:
|
||||
const intl = appInstance.lookup('service:intl');
|
||||
intl.addTranslations('en-us', { 'app.name': 'Biibaye' });
|
||||
```
|
||||
|
||||
**Verification:** Check that `appInstance.lookup('service:intl')` returns the intl service and `addTranslations` method exists. ember-intl 6.3.2 has this API confirmed via `addTranslations` in test-support.js.
|
||||
|
||||
### Troubleshooting: Primary Color Not Applied (CSS Variables Don't Work)
|
||||
|
||||
**Problem:** Extension injected `:root { --primary: #FF4500; }` but Fleetbase UI still shows blue (#3485e2).
|
||||
|
||||
**Root cause:** Fleetbase does NOT use CSS custom properties for theming. All colors are hardcoded via Tailwind's `sky-*` palette (e.g., `bg-sky-500`, `text-sky-500`). The `--primary` variable is never referenced by any Fleetbase component or CSS rule.
|
||||
|
||||
**Fix (two layers):**
|
||||
|
||||
1. **Build-time** — Patch `tailwind.config.js` to replace the sky palette with Biibaye orange before the Docker build. This changes all `sky-*` class definitions in the compiled `console.css`.
|
||||
|
||||
2. **Runtime** — extension.js injects `!important` CSS overrides targeting Tailwind utility classes (`.bg-sky-500`, `.text-sky-500`, etc.) and component classes (`.btn.btn-primary`). This catches any blue that leaks through from `ember-ui`'s pre-compiled `vendor.css`.
|
||||
|
||||
---
|
||||
|
||||
## Session: 2026-05-25 — CSS Color Fix + Fleetbase UI Removal
|
||||
|
||||
### Two critical fixes applied
|
||||
|
||||
#### 1. Post-build CSS color patching (the approach that finally worked)
|
||||
|
||||
**Problem:** Building tailwind.config.js patches into Docker failed repeatedly (host-side sed, Dockerfile-internal Node.js patching, post-build sed — none worked). The built CSS always retained Fleetbase blue `rgba(52, 133, 226, ...)`.
|
||||
|
||||
**Solution:** `console/patch-css-colors.js` — a Node.js script that runs AFTER `pnpm build` inside the Dockerfile. It walks the `dist/` directory tree, finds all `.css` files, and replaces Fleetbase blue hex/RGB values with Biibaye orange directly in the compiled output.
|
||||
|
||||
```dockerfile
|
||||
RUN pnpm build --environment $ENVIRONMENT
|
||||
RUN node patch-index-html.js && node patch-css-colors.js
|
||||
```
|
||||
|
||||
**Result:** 4 CSS files patched (console.css, vendor.css, fleetops-engine/engine.css, registry-bridge-engine/engine.css). Zero blue references remain — 11 orange refs in console.css, 16 in vendor.css.
|
||||
|
||||
#### 2. Extension loading fix
|
||||
|
||||
**Problem:** The @biibaye/branding extension never loaded because `extensions.json` (generated at build time by scanning node_modules) didn't include it. The deploy script's `sed` commands to modify pnpm workspace paths were no-ops because the source files never contained the biibaye entries to begin with.
|
||||
|
||||
**Solution:** Added `"@biibaye/branding": "link:../packages/biibaye-branding"` to `console/package.json` dependencies. Committed to `custom-production` branch. The deploy script converts the link path from `link:../packages/` (host) to `link:packages/` (Docker build context) via sed. This is the ONLY reliable sed in the deploy script — the workspace.yaml sed was removed.
|
||||
|
||||
**Result:** `extensions.json` now contains `@biibaye/branding`. The extension loads, all runtime features fire on boot.
|
||||
|
||||
### Extension.js Enhancements
|
||||
|
||||
**Added in this session:**
|
||||
|
||||
1. **CSS color overrides** — replaced non-functional `--primary: #FF4500` CSS variables with `!important` overrides for actual Tailwind classes (`.bg-sky-500`, `.text-sky-500`, `.border-sky-500`, `.btn.btn-primary`, etc.) and dark theme `body[data-theme="dark"]` background.
|
||||
|
||||
2. **Fleetbase UI removal:**
|
||||
- **Menu links** — CSS rules hide `.support-user-nav-item` (Help & Support), `.docs-user-nav-item` (Documentation), and `a[href*="discord.gg"]` (Discord).
|
||||
- **Default widgets** — `removeFleetbaseWidgets()` accesses the widget registry and removes `dashboard#fleetbase-blog` and `dashboard#fleetbase-github-card` from both `widget` and `default-widget` lists.
|
||||
|
||||
### Patch Scripts (in `console/` directory on VPS)
|
||||
|
||||
| Script | Purpose | When runs |
|
||||
|--------|---------|-----------|
|
||||
| `patch-index-html.js` | Replace Fleetbase title/favicon/meta in dist/index.html | Docker: after pnpm build |
|
||||
| `patch-css-colors.js` | Replace Fleetbase blue → Biibaye orange in all compiled CSS | Docker: after pnpm build |
|
||||
| `patch-index-html.py` | Same as .js version but in Python (used on host) | Deprecated — uses .js version now |
|
||||
| `patch-tailwind.js` | Replace sky palette in tailwind.config.js | Deprecated — didn't work reliably in Docker |
|
||||
|
||||
### Deploy Script (current version)
|
||||
|
||||
Located at `/opt/fleetbase/scripts/deploy-biibaye.sh` on VPS. Current steps:
|
||||
|
||||
1. `git pull origin main` in extension submodule
|
||||
2. Copy extension into `console/packages/biibaye-branding/`
|
||||
3. Copy public assets (favicon, images) into `console/public/`
|
||||
4. Run `python3 patch-index-html.py` on host (patches source `app/index.html`)
|
||||
5. Adjust Dockerfile: remove `--frozen-lockfile`, inject `COPY packages/ packages/`, inject `RUN node patch-index-html.js` before build
|
||||
6. Adjust package.json: convert `link:../packages/` → `link:packages/` for Docker context
|
||||
7. `docker compose build console --no-cache`
|
||||
8. Restore all modified files (index.html, package.json, Dockerfile)
|
||||
9. Restart containers
|
||||
|
||||
### Fleetbase Source Changes (custom-production branch)
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `console/package.json` | Added `"@biibaye/branding": "link:../packages/biibaye-branding"` in dependencies |
|
||||
| `AGENTS.md` | All session documentation |
|
||||
|
||||
These changes are mirrored in the `custom-pr` branch of the biibaye extension repo under `fleetbase-source/` for safekeeping.
|
||||
|
||||
---
|
||||
|
||||
## Session: 2026-05-25 — Email Template Rebrand
|
||||
|
||||
### Problem
|
||||
|
||||
OTP email showed "14411 is your fleetbase verification code" (lowercase fleetbase), Fleetbase logo in email header, and "2026 Fleetbase..." in footer. Other notification emails (password reset, user invite, etc.) had hardcoded "Fleetbase" in subject lines and body text.
|
||||
|
||||
### Root Cause
|
||||
|
||||
The application container had `APP_NAME=Fleetbase` despite `docker-compose.override.yml` setting `APP_NAME: "Biibaye"`. The container was created before the override was applied and `restart` doesn't pick up new env vars — only `--force-recreate` does.
|
||||
|
||||
### Fix Applied
|
||||
|
||||
1. **Environment fix:** Recreated application container with `--force-recreate` to pick up `APP_NAME=Biibaye` from override. This fixed all `config('app.name')` references:
|
||||
- OTP email subject: `"XXXX is your Biibaye verification code"` ✓
|
||||
- SMS code: `"Your Biibaye verification code is XXXX"` ✓
|
||||
- Email footer: `"© 2026 Biibaye"` ✓
|
||||
- Logo alt text: `"Biibaye Logo"` ✓
|
||||
- Password reset (forgot): `"Your password reset link for Biibaye"` ✓
|
||||
- User credentials: `"Your login credentials for ... on Biibaye"` ✓
|
||||
|
||||
2. **Hardcoded Fleetbase → `config('app.name')`:** Modified PHP source files to replace hardcoded "Fleetbase" strings. Applied via Docker volume mounts (overlay patched files over vendor directory):
|
||||
|
||||
| File | Change |
|
||||
|------|--------|
|
||||
| `PasswordReset.php` | `"Your password reset link for Fleetbase"` → `config('app.name')` |
|
||||
| `UserInvited.php` | `"...on Fleetbase!"` → `"...on " . config('app.name') . "!"` |
|
||||
| `UserAcceptedCompanyInvite.php` | `"...on Fleetbase!"` + `"Thank you for using Fleetbase!"` → `config('app.name')` |
|
||||
| `TestMail.php` | Subject set via `config('app.name')` in constructor |
|
||||
| `test.blade.php` | `"test email from Fleetbase"` → `{{ config('app.name') }}` |
|
||||
| `fleetbase.php` | Logo URL → `https://console.biibaye.com/images/icon.png` |
|
||||
| `mail.php` | From address default → `no-reply@biibaye.com`, name fallback → `Biibaye` |
|
||||
| `Utils.php` | `getDefaultMailFromAddress` default → `null` (uses CONSOLE_HOST) |
|
||||
| `StorefrontNetworkInvite.php` | `->from('hello@fleetbase.io',...)` → `config('mail.from.address')` |
|
||||
|
||||
3. **Volume mounts in docker-compose.override.yml:**
|
||||
```yaml
|
||||
application:
|
||||
volumes:
|
||||
- ./api/patches/core-api/src/Notifications/PasswordReset.php:/fleetbase/api/vendor/fleetbase/core-api/src/Notifications/PasswordReset.php
|
||||
# ... (8 mount points total)
|
||||
```
|
||||
|
||||
This overlays the patched files over the pre-built Docker image without requiring a custom image build.
|
||||
|
||||
### Email branding summary
|
||||
|
||||
| Element | Before | After |
|
||||
|---------|--------|-------|
|
||||
| OTP subject | "XXXX is your fleetbase verification code" | "XXXX is your Biibaye verification code" |
|
||||
| Email header logo | Fleetbase S3 logo | Biibaye icon (from admin setting, fallback: console.biibaye.com) |
|
||||
| Email footer | "© 2026 Fleetbase" | "© 2026 Biibaye" |
|
||||
| From address | hello@fleetbase.io (default) | no-reply@biibaye.com (default) |
|
||||
| From name | Fleetbase (default) | Biibaye (default) |
|
||||
| Password reset subject | "Your password reset link for Fleetbase" | "Your password reset link for Biibaye" |
|
||||
| User invite subject | "...invited to join Company on Fleetbase!" | "...invited to join Company on Biibaye!" |
|
||||
171
fleetbase-source/console-package.json
Normal file
@ -0,0 +1,171 @@
|
||||
{
|
||||
"name": "@fleetbase/console",
|
||||
"version": "0.7.41",
|
||||
"private": true,
|
||||
"description": "Modular logistics and supply chain operating system (LSOS)",
|
||||
"repository": "https://github.com/fleetbase/fleetbase",
|
||||
"license": "AGPL-3.0-or-later",
|
||||
"author": "Fleetbase Pte Ltd <hello@fleetbase.io>",
|
||||
"directories": {
|
||||
"doc": "doc",
|
||||
"test": "tests"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "ember build",
|
||||
"lint": "concurrently \"npm:lint:*(!fix)\" --names \"lint:\"",
|
||||
"lint:css": "stylelint \"**/*.css\"",
|
||||
"lint:css:fix": "concurrently \"npm:lint:css -- --fix\"",
|
||||
"lint:fix": "concurrently \"npm:lint:*:fix\" --names \"fix:\"",
|
||||
"lint:hbs": "ember-template-lint .",
|
||||
"lint:hbs:fix": "ember-template-lint . --fix",
|
||||
"lint:js": "eslint . --cache",
|
||||
"lint:js:fix": "eslint . --fix",
|
||||
"lint:intl": "fleetbase-intl-lint",
|
||||
"start": "ember serve",
|
||||
"start:dev": "ember serve --environment development",
|
||||
"test": "concurrently \"npm:lint\" \"npm:test:*\" --names \"lint,test:\"",
|
||||
"test:ember": "ember test"
|
||||
},
|
||||
"ember-addon": {
|
||||
"paths": [
|
||||
"lib/fleetbase-extensions-generator"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"@ember/legacy-built-in-components": "^0.4.2",
|
||||
"@biibaye/branding": "link:../packages/biibaye-branding",
|
||||
"@fleetbase/dev-engine": "^0.2.13",
|
||||
"@fleetbase/ember-core": "^0.3.19",
|
||||
"@fleetbase/ember-ui": "^0.3.31",
|
||||
"@fleetbase/fleetops-data": "^0.1.33",
|
||||
"@fleetbase/fleetops-engine": "^0.6.49",
|
||||
"@fleetbase/iam-engine": "^0.1.9",
|
||||
"@fleetbase/leaflet-routing-machine": "^3.2.17",
|
||||
"@fleetbase/ledger-engine": "^0.0.3",
|
||||
"@fleetbase/registry-bridge-engine": "^0.1.9",
|
||||
"@fleetbase/storefront-engine": "^0.4.14",
|
||||
"@fleetbase/valhalla-engine": "^0.0.4",
|
||||
"@fleetbase/vroom-engine": "^0.0.4",
|
||||
"@formatjs/intl-datetimeformat": "^6.18.2",
|
||||
"@formatjs/intl-numberformat": "^8.15.6",
|
||||
"@formatjs/intl-pluralrules": "^5.4.6",
|
||||
"@formatjs/intl-relativetimeformat": "^11.4.13",
|
||||
"@fortawesome/ember-fontawesome": "^2.0.0",
|
||||
"ember-changeset": "4.1.2",
|
||||
"ember-changeset-validations": "4.1.2",
|
||||
"ember-composable-helpers": "^5.0.0",
|
||||
"ember-concurrency": "^4.0.4",
|
||||
"ember-concurrency-decorators": "^2.0.3",
|
||||
"ember-intl": "6.3.2",
|
||||
"ember-math-helpers": "^2.18.2",
|
||||
"ember-maybe-in-element": "^2.1.0",
|
||||
"ember-prism": "^0.13.0",
|
||||
"ember-radio-button": "3.0.0-beta.1",
|
||||
"ember-tag-input": "^3.1.0",
|
||||
"fleetbase-extensions-indexer": "^0.0.5",
|
||||
"postcss-at-rules-variables": "^0.3.0",
|
||||
"postcss-custom-properties": "^12.1.11",
|
||||
"postcss-nth-list": "^1.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.25.2",
|
||||
"@babel/eslint-parser": "^7.25.1",
|
||||
"@babel/plugin-proposal-decorators": "^7.24.7",
|
||||
"@ember/optional-features": "^2.1.0",
|
||||
"@ember/string": "^3.1.1",
|
||||
"@ember/test-helpers": "^3.3.1",
|
||||
"@embroider/macros": "1.16.12",
|
||||
"@fleetbase/intl-lint": "^0.0.1",
|
||||
"@fortawesome/fontawesome-svg-core": "6.4.0",
|
||||
"@fortawesome/free-brands-svg-icons": "6.4.0",
|
||||
"@fortawesome/free-solid-svg-icons": "6.4.0",
|
||||
"@glimmer/component": "^1.1.2",
|
||||
"@glimmer/tracking": "^1.1.2",
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"autoprefixer": "^10.4.20",
|
||||
"broccoli-asset-rev": "^3.0.0",
|
||||
"broccoli-file-creator": "^2.1.1",
|
||||
"broccoli-funnel": "^3.0.8",
|
||||
"broccoli-merge-trees": "^4.2.0",
|
||||
"chokidar": "4.0.3",
|
||||
"concurrently": "^8.2.2",
|
||||
"date-fns": "^2.30.0",
|
||||
"dragula": "^3.7.3",
|
||||
"ember-auto-import": "^2.7.4",
|
||||
"ember-cli": "~5.4.2",
|
||||
"ember-cli-app-version": "^6.0.1",
|
||||
"ember-cli-babel": "^8.2.0",
|
||||
"ember-cli-clean-css": "^3.0.0",
|
||||
"ember-cli-dependency-checker": "^3.3.2",
|
||||
"ember-cli-deprecation-workflow": "^4.0.0",
|
||||
"ember-cli-dotenv": "^3.1.0",
|
||||
"ember-cli-htmlbars": "^6.3.0",
|
||||
"ember-cli-inject-live-reload": "^2.1.0",
|
||||
"ember-cli-postcss": "^8.2.0",
|
||||
"ember-cli-sri": "^2.1.1",
|
||||
"ember-cli-string-helpers": "^6.1.0",
|
||||
"ember-cli-terser": "^4.0.2",
|
||||
"ember-data": "^4.12.8",
|
||||
"ember-engines": "^0.9.0",
|
||||
"ember-fetch": "^8.1.2",
|
||||
"ember-load-initializers": "^2.1.2",
|
||||
"ember-modifier": "^4.2.0",
|
||||
"ember-page-title": "^8.2.3",
|
||||
"ember-qunit": "^8.1.0",
|
||||
"ember-resolver": "^11.0.1",
|
||||
"ember-responsive": "^5.0.0",
|
||||
"ember-source": "~5.4.1",
|
||||
"ember-template-lint": "^5.13.0",
|
||||
"ember-wormhole": "^0.6.0",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-plugin-ember": "^11.12.0",
|
||||
"eslint-plugin-n": "^16.6.2",
|
||||
"eslint-plugin-prettier": "^5.2.1",
|
||||
"eslint-plugin-qunit": "^8.1.2",
|
||||
"fast-glob": "^3.3.2",
|
||||
"fs": "0.0.1-security",
|
||||
"inter-ui": "^3.19.3",
|
||||
"loader.js": "^4.7.0",
|
||||
"normalize.css": "^8.0.1",
|
||||
"postcss": "^8.4.41",
|
||||
"postcss-conditionals-renewed": "^1.0.0",
|
||||
"postcss-each": "^1.1.0",
|
||||
"postcss-import": "14.1.0",
|
||||
"postcss-mixins": "^9.0.4",
|
||||
"postcss-preset-env": "^7.8.3",
|
||||
"postcss-simple-vars": "^7.0.1",
|
||||
"prettier": "^3.3.3",
|
||||
"qunit": "^2.22.0",
|
||||
"qunit-dom": "^2.0.0",
|
||||
"recast": "^0.23.9",
|
||||
"stylelint": "^15.11.0",
|
||||
"stylelint-config-standard": "^34.0.0",
|
||||
"stylelint-prettier": "^4.1.0",
|
||||
"tailwindcss": "^3.4.10",
|
||||
"tracked-built-ins": "^3.3.0",
|
||||
"webpack": "^5.98.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 22"
|
||||
},
|
||||
"ember": {
|
||||
"edition": "octane"
|
||||
},
|
||||
"prettier": {
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 4,
|
||||
"semi": true,
|
||||
"singleQuote": true,
|
||||
"printWidth": 190,
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.hbs",
|
||||
"options": {
|
||||
"singleQuote": false
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"packageManager": "pnpm@11.0.9"
|
||||
}
|
||||
42
fleetbase-source/deploy-biibaye.sh
Normal file
@ -0,0 +1,42 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
cd /opt/fleetbase
|
||||
|
||||
echo '=== Pull branding extension ==='
|
||||
cd packages/biibaye-branding && git pull origin main && cd /opt/fleetbase
|
||||
|
||||
echo '=== Copy extension + assets into console build context ==='
|
||||
rm -rf console/packages/biibaye-branding
|
||||
cp -r packages/biibaye-branding console/packages/biibaye-branding
|
||||
rm -rf console/packages/biibaye-branding/.git console/packages/biibaye-branding/.gitignore
|
||||
cp -r console/packages/biibaye-branding/public/favicon/* console/public/favicon/
|
||||
cp -r console/packages/biibaye-branding/public/images/* console/public/images/
|
||||
|
||||
echo '=== Patch index.html ==='
|
||||
cp console/app/index.html console/app/index.html.bak
|
||||
python3 /opt/fleetbase/scripts/patch-index-html.py
|
||||
|
||||
echo '=== Adjust for Docker build ==='
|
||||
cp console/package.json console/package.json.bak
|
||||
cp console/Dockerfile console/Dockerfile.bak
|
||||
|
||||
# Convert link path for Docker build context
|
||||
sed -i 's|link:../packages/biibaye-branding|link:packages/biibaye-branding|g' console/package.json
|
||||
|
||||
# Dockerfile: remove frozen-lockfile, copy packages/, inject patching
|
||||
sed -i 's|--frozen-lockfile||g' console/Dockerfile
|
||||
sed -i '/^RUN pnpm install/i COPY packages/ packages/' console/Dockerfile
|
||||
sed -i '/^RUN pnpm build/i RUN node patch-index-html.js' console/Dockerfile
|
||||
|
||||
echo '=== Build ==='
|
||||
docker compose -f docker-compose.yml -f docker-compose.override.yml build console --no-cache
|
||||
|
||||
echo '=== Restore ==='
|
||||
mv console/app/index.html.bak console/app/index.html
|
||||
mv console/package.json.bak console/package.json
|
||||
mv console/Dockerfile.bak console/Dockerfile
|
||||
|
||||
echo '=== Restart ==='
|
||||
docker compose -f docker-compose.yml -f docker-compose.override.yml up -d console && sleep 5 && docker compose -f docker-compose.yml -f docker-compose.override.yml restart httpd application
|
||||
|
||||
echo '=== Done ==='
|
||||
@ -1,25 +0,0 @@
|
||||
# Docker Compose Override Example
|
||||
# Copy this file to docker-compose.override.yml and customize for your environment
|
||||
|
||||
version: "3.8"
|
||||
services:
|
||||
application:
|
||||
environment:
|
||||
CONSOLE_HOST: http://localhost:4200
|
||||
# Add your environment-specific variables here
|
||||
MAIL_MAILER: smtp # or ses, mailgun, postmark, sendgrid
|
||||
OSRM_HOST: https://router.project-osrm.org
|
||||
# IPINFO_API_KEY: your_api_key
|
||||
# GOOGLE_MAPS_API_KEY: your_api_key
|
||||
# GOOGLE_MAPS_LOCALE: us
|
||||
# TWILIO_SID: your_twilio_sid
|
||||
# TWILIO_TOKEN: your_twilio_token
|
||||
# TWILIO_FROM: your_twilio_phone
|
||||
|
||||
socket:
|
||||
environment:
|
||||
# DEVELOPMENT: Allow localhost connections (HTTP, HTTPS, and WebSocket protocols)
|
||||
SOCKETCLUSTER_OPTIONS: '{"origins":"http://localhost:*,https://localhost:*,ws://localhost:*,wss://localhost:*"}'
|
||||
|
||||
# PRODUCTION: Replace with your actual domain(s) - include all protocols
|
||||
# SOCKETCLUSTER_OPTIONS: '{"origins":"https://yourdomain.com:*,wss://yourdomain.com:*,https://app.yourdomain.com:*,wss://app.yourdomain.com:*"}'
|
||||
54
fleetbase-source/patch-css-colors.js
Normal file
@ -0,0 +1,54 @@
|
||||
var fs = require('fs');
|
||||
var path = require('path');
|
||||
|
||||
function walkDir(dir, callback) {
|
||||
fs.readdirSync(dir).forEach(function(f) {
|
||||
var p = path.join(dir, f);
|
||||
if (fs.statSync(p).isDirectory()) walkDir(p, callback);
|
||||
else if (p.endsWith('.css')) callback(p);
|
||||
});
|
||||
}
|
||||
|
||||
var replacements = [
|
||||
[/230, 240, 251/g, '255, 240, 230'],
|
||||
[/186, 213, 245/g, '255, 208, 179'],
|
||||
[/141, 187, 239/g, '255, 179, 128'],
|
||||
[/97, 160, 232/g, '255, 122, 51'],
|
||||
[/52, 133, 226/g, '255, 69, 0'],
|
||||
[/28, 108, 199/g, '224, 61, 0'],
|
||||
[/22, 83, 154/g, '179, 49, 0'],
|
||||
[/16, 59, 109/g, '138, 38, 0'],
|
||||
[/9, 35, 65/g, '97, 26, 0'],
|
||||
[/#e6f0fb/gi, '#FFF0E6'],
|
||||
[/#bad5f5/gi, '#FFD0B3'],
|
||||
[/#8dbbef/gi, '#FFB380'],
|
||||
[/#61a0e8/gi, '#FF7A33'],
|
||||
[/#3485e2/gi, '#FF4500'],
|
||||
[/#1c6cc7/gi, '#E03D00'],
|
||||
[/#16539a/gi, '#B33100'],
|
||||
[/#103b6d/gi, '#8A2600'],
|
||||
[/#092341/gi, '#611A00'],
|
||||
[/31, 41, 55/g, '52, 53, 56'],
|
||||
[/#1f2937/gi, '#343538'],
|
||||
];
|
||||
|
||||
var distDir = 'dist';
|
||||
if (!fs.existsSync(distDir)) {
|
||||
distDir = '.';
|
||||
}
|
||||
|
||||
var count = 0;
|
||||
walkDir(distDir, function(filePath) {
|
||||
var content = fs.readFileSync(filePath, 'utf8');
|
||||
var original = content;
|
||||
replacements.forEach(function(r) {
|
||||
content = content.replace(r[0], r[1]);
|
||||
});
|
||||
if (content !== original) {
|
||||
fs.writeFileSync(filePath, content);
|
||||
console.log('Patched: ' + filePath);
|
||||
count++;
|
||||
}
|
||||
});
|
||||
|
||||
console.log('Patched ' + count + ' CSS files');
|
||||
15
fleetbase-source/patch-index-html.js
Normal file
@ -0,0 +1,15 @@
|
||||
var fs = require('fs');
|
||||
var p = 'dist/index.html';
|
||||
if (!fs.existsSync(p)) {
|
||||
p = 'app/index.html';
|
||||
}
|
||||
var c = fs.readFileSync(p, 'utf8');
|
||||
c = c.replace('<title>Fleetbase Console</title>', '<title>Biibaye - Delivery System</title>');
|
||||
c = c.replace(/content="#da532c"/g, 'content="#FF4500"');
|
||||
c = c.replace(/content="#ffffff"/g, 'content="#FF4500"');
|
||||
c = c.replace(/href="\/favicon\/apple-touch-icon.png"/g, 'href="/favicon/apple-icon-180x180.png"');
|
||||
c = c.replace(/href="\/favicon\/android-chrome-192x192.png"/g, 'href="/favicon/android-icon-192x192.png"');
|
||||
c = c.replace(/href="\/favicon\/android-chrome-256x256.png"/g, 'href="/favicon/android-icon-144x144.png"');
|
||||
c = c.replace(/color="#5bbad5"/g, 'color="#FF4500"');
|
||||
fs.writeFileSync(p, c);
|
||||
console.log('index.html patched: ' + p);
|
||||
20
fleetbase-source/patch-index-html.py
Normal file
@ -0,0 +1,20 @@
|
||||
import re
|
||||
path = '/opt/fleetbase/console/app/index.html'
|
||||
with open(path, 'r') as f:
|
||||
content = f.read()
|
||||
replacements = [
|
||||
('<title>Fleetbase Console</title>', '<title>Biibaye - Delivery System</title>'),
|
||||
('content="#da532c"', 'content="#FF4500"'),
|
||||
('content="#ffffff"', 'content="#FF4500"'),
|
||||
('href="/favicon/apple-touch-icon.png"', 'href="/favicon/apple-icon-180x180.png"'),
|
||||
('href="/favicon/android-chrome-192x192.png"', 'href="/favicon/android-icon-192x192.png"'),
|
||||
('href="/favicon/android-chrome-256x256.png"', 'href="/favicon/android-icon-144x144.png"'),
|
||||
('color="#5bbad5"', 'color="#FF4500"'),
|
||||
]
|
||||
for old, new in replacements:
|
||||
if old not in content:
|
||||
print(f'WARNING: pattern not found: {old}')
|
||||
content = content.replace(old, new)
|
||||
with open(path, 'w') as f:
|
||||
f.write(content)
|
||||
print('index.html patched successfully')
|
||||
|
Before Width: | Height: | Size: 4.3 KiB |
|
Before Width: | Height: | Size: 6.3 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 3.0 KiB |
|
Before Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.6 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 2.3 KiB |