Headless Laravel API for searching automotive spare parts by year, make, model, and any other customer-defined fitment attribute. Product catalog data is synced from Shopify; fitment data (year/make/model + custom qualifiers) is synced from a Google Sheet or an uploaded CSV.
Note: this document describes the app as it stands today and will change as the project evolves. Treat it as a living reference, not a permanent spec.
- Catalog pipeline —
Product,Category,Variant,CustomField,Filterare synced from Shopify viaApp\Models\Source\Shopify\Adapter. - Fitment pipeline —
Fitment(mandatory qualifiers:sku,year,make,model) andQualifier(any other customer-defined column) are synced from either a Google Sheet (App\Models\Source\Google\Adapter) or an uploaded CSV (App\Models\Source\Csv\Adapter). - Public API — three read-only JSON endpoints power a cascading year → make → model → qualifier search widget.
- Sync endpoints — token-protected routes trigger a full resync from the configured data source.
- Docker and Docker Compose (the project ships a full stack — Apache, PHP-FPM 8.4, MySQL 8, Redis, Mailhog — no local PHP/MySQL install needed)
- A host entry pointing a local domain at the Apache container (see below)
-
Clone and configure environment
git clone https://github.com/tinchodev/autosearch.git cd autosearch cp .env.example .envFill in
.envwith real values where needed — at minimumAPP_KEY(see step 5), theDB_*credentials to matchdocker-compose.yml, andSYNC_ACCESS_TOKEN(any random string; used to authenticate the sync endpoints, see Triggering a sync below). -
Add a local host entry
The Apache vhost is configured for
autosearch.test. Add it to your machine's hosts file:127.0.0.1 autosearch.test -
Generate a local SSL certificate
The Apache vhost expects a cert/key pair at
httpd/certs/apache.crtandhttpd/certs/apache.key. Use mkcert to generate one that's trusted by your machine (no browser warning), instead of a plain self-signed cert:mkcert -install mkcert -cert-file httpd/certs/apache.crt -key-file httpd/certs/apache.key \ autosearch.test "*.autosearch.test" -
Start the stack
docker compose up -d --build
This brings up
apache,php-fpm,sqlserver(MySQL 8),redis, andmailhog. -
Install dependencies and generate an app key
docker compose exec php-fpm composer install docker compose exec php-fpm php artisan key:generate
-
Create the database
docker-compose.ymlonly auto-creates a database nameddatabaseon first boot. Create the one.env'sDB_DATABASEactually points at (defaults toautosearch):docker compose exec sqlserver mysql -uroot -proot -e \ "CREATE DATABASE IF NOT EXISTS \`autosearch\`; GRANT ALL PRIVILEGES ON \`autosearch\`.* TO 'user'@'%'; FLUSH PRIVILEGES;"
-
Run migrations and seed base settings
docker compose exec php-fpm php artisan migrate docker compose exec php-fpm php artisan db:seed --class=SettingSeeder
-
Visit the app
https://autosearch.test— no browser warning if you generated the cert with mkcert per step 3; otherwise expect one.
- Place a Google service account credentials file at
storage/app/private/google_sheets_credentials.json(already gitignored). - Share the target spreadsheet with that service account's email.
- The sheet must have a tab named
full_datawith a header row including at leastsku,year,make,model(any additional columns become searchable qualifiers). - Set the
google_spreadsheet_idrow in thesettingstable to the spreadsheet ID (the long ID in the sheet's URL). - Trigger a sync — see below.
Upload a CSV with the same required header columns (sku, year, make, model)
via POST /fitment-sync-csv (see below).
All three sync routes require a SYNC_ACCESS_TOKEN (set in .env), passed either as
a header or a query parameter:
# Catalog sync (Shopify)
curl -H "X-Sync-Token: $SYNC_ACCESS_TOKEN" https://autosearch.test/catalog-sync
# Fitment sync (Google Sheets)
curl -H "X-Sync-Token: $SYNC_ACCESS_TOKEN" https://autosearch.test/fitment-sync
# Fitment sync (CSV upload)
curl -H "X-Sync-Token: $SYNC_ACCESS_TOKEN" \
-F "fitment_csv=@/path/to/file.csv" \
https://autosearch.test/fitment-sync-csvEach sync truncates and repopulates the relevant tables, so treat it as a full replace, not an incremental update. Only one sync can run at a time (enforced via a cache lock).
| Endpoint | Method | Purpose |
|---|---|---|
/api/years |
GET | List of all available fitment years, plus public settings. |
/api/fitment |
GET | Cascading makes/models/qualifiers for a given year (required), make, model. |
/api/listing |
GET | Same shape as /api/fitment, without server-side validation. |
Example:
curl "https://autosearch.test/api/fitment?year=2016&make=toyota&model=camry"# Run the test suite
docker compose exec php-fpm composer test
# Rector (automated refactoring / upgrade rules)
docker compose exec php-fpm composer rector:check # dry-run
docker compose exec php-fpm composer rector # apply
# PHP-CS-Fixer (code style)
docker compose exec php-fpm composer cs-check # dry-run
docker compose exec php-fpm composer cs-fix # applyProprietary — all rights reserved unless stated otherwise.