Version 0.56 - July 6, 2025
Build on Laravel 12 using Inertia.js 2.x with Vue.js 3.x.
Table of contents
- Development environment: For local development via DDEV
- Production environment: How to deploy on Production
- Data Import: How to import Organisations
Maps rely on MapBox and therefore, a valid MapBox Access Token has to be used.
Important: The token will be included in the webpage and will be visible to anyone who makes an effort to look for it. MapBox recommends that you generate a separate access token with URL restrictions to help prevent abuse of billable API endpoints. See How to use Mapbox securely for detailed security guidance.
Geocoding services rely on OpenCage Data and therefore, a valid OpenCage API Key must be configured in your .env
file as OPENCAGE_API_KEY
.
- DDEV version 1.24 or newer.
- Access to this repository.
- Clone this project.
- Change to the directory of the project (i.e.
cd interactive-landscape-tool
). - The configuration of the DDEV project is included in the repository; therefore, you can start it:
ddev start &&
ddev composer install
If for some reason the .env
file has not been created on the root of this project, then please create it yourself by copying the provided example.
cp .env.example .env
Create the application key, required by Laravel, run the migrations, and do the initial seed of the database:
ddev artisan key:generate &&
ddev artisan migrate:fresh --seed
No organisations will be seeded. You should be able to import organisations using the provided CLI tool as described on Data Import.
Finally, install the required front-end dependencies:
ddev npm i
Start Vite to launch the development environment:
ddev npm run dev
You can visit https://interactive-landscape-tool.ddev.site on your browser to enjoy development with hot-reloading for both Laravel and Inertia/Vue.js.
Something wrong with the database? Want a fresh start? Do this whenever you feel the need to, and the database will be recreated from scratch (i.e. existing data will be erased).
ddev artisan migrate:fresh --seed
For your convenience, the project includes Laravel Pail, a package that allows you to easily dive into your Laravel application's log files directly from the command line.
ddev artisan pail
Laravel Pint — Automatically formats PHP code according to Laravel's coding standards using PHP-CS-Fixer rules:
ddev pint
Larastan — Static analysis tool that extends PHPStan for Laravel projects, configured at level 10 (strictest) to catch type errors, unused variables, and potential bugs:
ddev exec ./vendor/bin/phpstan analyse
ESLint with TypeScript ESLint — Lints JavaScript/TypeScript code in Vue components and scripts, automatically fixing issues where possible:
ddev npm run lint
Prettier — Code formatter for JavaScript, TypeScript, and Vue files with consistent styling across the project:
ddev npm run format
Vue TSC — TypeScript compiler for Vue 3 that type-checks all TypeScript code in Vue components and scripts:
ddev npm run type-check
The project uses PHPUnit for testing Laravel backend functionality. Tests are organised into core tests (business logic, models, controllers) and live API tests (external service integrations):
All tests — Run all tests including core tests and live API tests:
ddev php artisan test
Live API tests only — Test integration with OpenCage geocoding service using real API calls:
ddev php artisan test --group=live-api
Core tests only (recommended) — Test application logic, database operations, and API endpoints without external dependencies:
ddev php artisan test --exclude-group=live-api
- MySQL >= 8.0
- PHP >= 8.2 with required extensions:
- intl— ― for internationalisation
- imagick ― for image processing
- pdo ― for database connectivity
- Plus all Laravel 12 required extensions
Please note that this app is built for SSR, although this doesn't seem to be a requirement at the moment (hopefully).
For production, usually the following steps are enough for the first installation. Please make sure that you have properly configured the .env
file.
composer install &&
php artisan key:generate &&
php artisan migrate:fresh --seed &&
npm install &&
npm run build
artisan down --message="Scheduled maintenance in progress."
composer install &&
npm install &&
npm run build &&
php artisan config:cache
php artisan up
Please note that in both cases build assets will be created in two locations:
public/build
- Front-end CSS & JSbootstrap/ssr
- SSR
- A valid OpenCage Data API key, properly set on the
OPENCAGE_API_KEY
property of your.env
file. - Test geocoding availability at
/test/geocode
route with interactive country selection.
To import organisation data, use the provided CLI tool which processes Excel files directly.
The command syntax varies depending on your environment:
Production environment:
php artisan app:import-organisations
Local development (using DDEV):
ddev artisan app:import-organisations
All import files must be organised in a specific directory structure within /storage/app/private/organisations/import/
:
- Create a dedicated subfolder for each data provider (e.g.,
Data_Provider_Name
) - Place the Excel file (
.xlsx
format) inside this subfolder - the filename itself doesn't matter, only the extension - Include organisation logos (optional) in the same subfolder, as
.png
or.webp
files with appropriate names
Important:: Logo files must be named using a specific pattern derived from the organisation name in the Excel file:
- Naming pattern: Convert the organisation name to a slug format using underscores
- Names should be in lower-case
- Spaces and special characters should be replaced with underscores
- Supported formats:
.png
,.webp
For example, if the organisation name is "Example Tech Company", the logo should be named example_tech_company.png
(or example_tech_company.webp
).
storage/app/private/organisations/import/
└── Data_Provider_Name/
├── organisation_data.xlsx
├── example_tech_company.png
├── another_organisation.webp
└── third_company_ltd.png
- Organise your files according to the structure above
- Ensure logo filenames match the converted organisation names from your Excel file
- Run the appropriate artisan command for your environment
- Follow the interactive prompts to complete the import
- Consecutive imports are designed to be non-destructive (existing data should be preserved)
Logo Import Notes:
- Logo files are copied only if they don't exist or if the file size differs from existing ones
- Missing logos will generate warnings in the import logs but won't stop the import process
- Each logo gets a unique UUID when stored in the media storage
The subfolder structure is mandatory because logos must be co-located with their corresponding Excel data file for proper association during import.
The application maintains a 90-day geocoding cache for performance. You can manage this cache with:
# Clear expired geocoding cache (90+ days old)
ddev artisan app:clear-expired-geocoding-cache
# Test geocoding service availability
ddev artisan tinker --execute="echo Geocoder::isGeocodingAvailable() ? 'Available' : 'Unavailable';"
# Test geocoding with country bias
ddev artisan tinker --execute="print_r(Geocoder::getCoordinates('Address', 'country_code', 1));"