---
title: "Local development and testing"
description: "Set up local development for Éclair: PHP's built-in server, 550 automated checks, the archive, Lighthouse, debug mode and MCP Inspector."
url: "https://eclair.academy/en/paths/expert/local-development"
lang: "en"
author: "Thierry Gustin"
published: "2026-11-02"
updated: "2026-11-02"
---

# Local development and testing

> **Key takeaways** — For local development on Éclair, clone the GitHub repository, then run PHP_CLI_SERVER_WORKERS=4 php -S localhost:8000 -t eclair tools/router.php. The php tests/run.php command runs 550 unit and HTTP checks, php tools/build.php produces the archive and its fingerprints, and eclair-config.php turns on debug mode.

Local development on Éclair needs no Composer, no database and no container: PHP 8.1 or later is enough. In this lesson, you run the site on your machine, run the 550 automated checks, build the distributable archive, measure with Lighthouse and test the MCP connector, all before you touch a live site.

> **Before you start** — Time: 45 minutes. Prerequisites: PHP 8.1 or later on the command line (8.3 recommended) with the extensions covered in [Prepare your installation](https://eclair.academy/en/paths/beginner/prepare-installation), plus curl for the HTTP tests and zip for the archive; Git; Node.js 22.19 or later for Lighthouse and MCP Inspector. Read [Éclair's architecture](https://eclair.academy/en/paths/expert/architecture) first.

## What you'll be able to do

### 🚀 Run Éclair locally

PHP's built-in server, with the repository's router.

### ✅ Test before you ship

Unit and HTTP checks, and a public rendering compared down to the byte.

### 🔧 Debug cleanly

eclair-config.php, the error log and MCP Inspector.

## Running Éclair for local development

```bash
git clone https://github.com/Jacckisback/eclair-cms.git
cd eclair-cms
PHP_CLI_SERVER_WORKERS=4 php -S localhost:8000 -t eclair tools/router.php
```

The `-t eclair` option makes the `eclair/` folder the site's root, like a host's public folder. The `tools/router.php` script reproduces the `.htaccess` rules: 404 for `app/`, `data/`, `cache/`, hidden files and any `.php` file other than `index.php`, and no scripts or pages in `media/`. It serves existing files as they are and sends everything else to `index.php`.

Why `PHP_CLI_SERVER_WORKERS=4`? To verify its address, the site calls itself on `/__eclair/ping`. With a single process, the built-in server is busy with the current request and can't answer: the check fails, and redirects to the official address stay off. PHP doesn't support multiple workers on Windows: use WSL, or accept an unverified address locally.

Then open `http://localhost:8000`: the setup wizard starts, with the same 2-hour window as online. Always use the same address (`localhost` or `127.0.0.1`), because it's the one the installation saves. Your local data goes into `eclair/data/`, which Git ignores, just like the cache, uploaded images and `eclair-config.php`.

| Repository folder | Contents |
| --- | --- |
| `eclair/` | the CMS, as it ships to a host |
| `i18n/` | human-readable sources of the admin translations |
| `tests/` | unit and HTTP tests, fake AI providers, reference sites |
| `tools/` | development router, build, capture, translations |
| `docs/` | official guide in 7 languages |
| `dist/` | distributable archives, one per version |

> **Start again from a blank site** — `git clean -fdX eclair/` deletes everything Git ignores in `eclair/`: data, cache, uploaded images and `eclair-config.php`. Tracked files, such as `data/.htaccess`, stay in place.

## How do you run Éclair's tests?

```bash
php tests/run.php                  # unit + HTTP integration
# ✅ 550 vérifications réussies

php tests/run.php --unit           # unit tests only, in a few seconds
# ✅ 241 vérifications réussies

# Same test suite on an unzipped archive
ECLAIR_TEST_ROOT=/tmp/archive/eclair php tests/run.php
```

The tests don't touch your local development site: unit test data goes into the system's temporary folder. Each HTTP test copies `eclair/` into that same folder, empties its data, starts `php -S` on a random port with four workers and `tools/router.php`, installs a site, then replays its scenarios with curl. The repository's tools report in French: in the output above, “vérifications réussies” means “checks passed”. If something fails, the list of failed checks is displayed and the command exits with code 1, so it fits as is into a continuous integration pipeline.

| File | What it checks |
| --- | --- |
| `tests/run.php` | XSS sanitization, slugs, two-factor authentication, blocks; installation, headers, cache and 304, redirects, brute-force protection, FTP recovery; public rendering identical to the reference |
| `tests/ai.php` | the AI assistant end to end, with fake providers |
| `tests/shop.php` | themes, custom CSS, shop, Stripe, PayPal and Revolut links, Merchant Center feed |
| `tests/mcp.php` | MCP connector: OAuth discovery, PKCE, tokens, tools, revocation |
| `tests/design.php` | art directions, contrast, fonts, Design score |
| `tests/fixtures/` | 4 reference sites and fingerprints of their public rendering |

### Developing the AI assistant with no key and no spending

`tests/fake-ai.php` mimics the Anthropic, OpenAI, FLUX and Ideogram APIs. The tests start it on a local port and write an `eclair-config.php` file into their copy that defines `ECLAIR_AI_ENDPOINTS`. You can reproduce this setup to work on the assistant's interface:

```bash
# Terminal 1: fake providers (request log in /tmp/fake-ai/log.jsonl)
mkdir -p /tmp/fake-ai
FAKE_AI_DIR=/tmp/fake-ai php -S 127.0.0.1:9999 tests/fake-ai.php
```

```php
<?php
// eclair/eclair-config.php: the assistant talks to the fake providers
defined('ECLAIR') || exit;
define('ECLAIR_AI_ENDPOINTS', ['anthropic' => 'http://127.0.0.1:9999', 'openai' => 'http://127.0.0.1:9999']);
```

The fake server only accepts its test keys, such as `sk-ant-test-0123456789`, and reacts to a keyword placed in your request: `ARTICLE` (an image, then a draft), `EQUIPE` (adding a team member) or `PIEGE` (malicious text), among others.

## Building the distributable archive

```bash
php tools/build.php
# ✓ Traductions : 6 langues compilées (eclair/app/lang)
# ✓ Empreintes : 126 fichiers (app/manifest.php)
# ✓ Archive : …/dist/eclair-cms-1.8.0.zip (479 Ko, 981 991 octets une fois décompressée)
```

The version comes from the `ECLAIR_VERSION` constant in `eclair/index.php`. The script recompiles the translations, computes each file's SHA-256 fingerprint (its first 128 bits) in `app/manifest.php`, the basis of the integrity check, then creates `dist/eclair-cms-<version>.zip`. In the archive, the PHP is compacted with `php -w`, the admin views are compressed (`.php.gz`, read through zlib) and the admin JavaScript and CSS are minified. The public rendering stays identical down to the byte. The contents of `data/`, `cache/` and `media/` and your `eclair-config.php` are excluded, while `LISEZ-MOI.txt` (a read-me in French), `LICENSE.txt` and `THIRD-PARTY-NOTICES.txt` are added. Without the zip extension, no archive is created.

> **The manifest changes** — The build rewrites `eclair/app/manifest.php` in your working copy, so Git will see it as modified. Run it deliberately, when you publish a release.

## Capturing the rendering and measuring with Lighthouse

```bash
npm install -g lighthouse              # Node.js 22 or later
php tools/capture.php                  # rendering fingerprints → tests/fixtures/public-<version>.json
php tools/capture.php --lighthouse     # mobile Lighthouse → tests/fixtures/lighthouse-<version>.json
```

`tools/capture.php` serves the four reference sites in `tests/fixtures/sites/` (blog, business, freelance, landing) and records the fingerprint of each page, for a visitor and then with an admin session, the HTML of each block and the public CSS and JS files. `tests/run.php` compares the current rendering with `public-1.6.0.json`: a new version must not change a single byte of the public site. The `--reinstall` option recreates the starter sites, and therefore new fingerprints: the existing references are then no longer valid.

With `--lighthouse`, the tool measures on mobile the home page and a post of the “business” site, the “landing” page, then the home page dressed in four art directions, keeping the median of three runs. The `LIGHTHOUSE` and `CHROME_PATH` variables set the command and the browser. For Éclair 1.8, every measured page scores 100 in all four categories, with an LCP of 779 to 885 ms, a CLS of 0 and a TBT of 0 to 17 ms.

## Debug mode and eclair-config.php

Copy `eclair/eclair-config.exemple.php` as `eclair-config.php`, next to `index.php`, and keep only the lines you need. Here is the template, with the `ECLAIR_SECRET` constant added:

```php
<?php
defined('ECLAIR') || exit;

// Detailed errors and static cache off: only while you fix a problem.
define('ECLAIR_DEBUG', true);

// Data outside the public folder (move the "data" folder first).
// define('ECLAIR_DATA', '/home/moncompte/eclair-data');

// Extra secret for the API key vault, set before saving the keys.
// define('ECLAIR_SECRET', 'une-longue-phrase-secrète');
```

| Constant | Effect |
| --- | --- |
| `ECLAIR_DEBUG` | shows errors, turns warnings into exceptions, details the error on the incident page, turns off the static cache |
| `ECLAIR_DATA` | location of the data, `eclair/data` by default |
| `ECLAIR_SECRET` | added to the site secret to encrypt the API keys |
| `ECLAIR_AI_ENDPOINTS` | replaces the AI providers' URLs: a gateway or fake servers |

Without debug mode, an error displays “Oups, un court-circuit” (always shown in French) with an 8-character reference. The details are logged in `data/logs/errors.php` and shown on the **Security** page, under **Recent technical errors**. That's the right method on a live site, where `ECLAIR_DEBUG` would show your errors to visitors.

## Testing the MCP connector with MCP Inspector

1. In the local admin, open **Settings › AI assistant**, turn on **Allow MCP connections** and save. A warning reminds you that Claude and ChatGPT require an https address; the Inspector, however, accepts your local address.
2. Check OAuth discovery and the refusal without a token with the first two commands below.
3. Start the Inspector with the connector URL (third command).
4. Connect from the Inspector: it reads the discovery document, registers itself (Éclair accepts return URLs on `http://localhost`, `127.0.0.1` or `[::1]`), then opens Éclair's consent page. Log in and click **Allow**.
5. List the tools: `get_site`, `search_content`, `get_content` and `find_media` for reading; `create_draft` and `update_content` for writing, limited to 60 per hour per connection.

```bash
# Discovery: protected resource and authorization server
curl -s http://localhost:8000/.well-known/oauth-protected-resource

# No token: 401 refusal pointing to the discovery document
curl -si -X POST http://localhost:8000/_eclair/mcp | grep -i www-authenticate
# WWW-Authenticate: Bearer resource_metadata="http://localhost:8000/.well-known/oauth-protected-resource"

# MCP Inspector, web interface
npx @modelcontextprotocol/inspector --server-url http://localhost:8000/_eclair/mcp --transport http
```

The Éclair 1.8 connector announces versions 2025-11-25, 2025-06-18 and 2025-03-26 of the protocol. For a scriptable test, the same command with `--cli` and `--method tools/list` lists the tools in the terminal.

## Key points

- Local development on Éclair comes down to one command: `PHP_CLI_SERVER_WORKERS=4 php -S localhost:8000 -t eclair tools/router.php`.
- `php tests/run.php` replays 550 checks on copies, without touching your site; `--unit` sticks to the 241 unit tests.
- `php tools/build.php` produces the archive and rewrites `app/manifest.php`, the basis of the integrity check.
- `eclair-config.php` holds the advanced settings; `ECLAIR_DEBUG` stays on only while you diagnose a problem.
- MCP Inspector tests the connector locally, OAuth included, before Claude or ChatGPT.

## Going further

- [Éclair's architecture](https://eclair.academy/en/paths/expert/architecture): what your tests exercise, request by request.
- [Customize the theme templates](https://eclair.academy/en/paths/expert/theme-customization): change the rendering, then check it with these tools.
- [Understanding the MCP connector](https://eclair.academy/en/paths/ai-mcp/understanding-mcp): the six tools and what the AI can't do.
- [Performance: staying at 100 out of 100](https://eclair.academy/en/paths/expert/performance): read and interpret a Lighthouse measurement.
- PHP: [the built-in web server and its router scripts](https://www.php.net/manual/en/features.commandline.webserver.php).
- Model Context Protocol: [MCP Inspector documentation](https://modelcontextprotocol.io/docs/tools/inspector).

## Frequently asked questions

### Do I need Composer, npm or Docker for local development?

No. PHP on the command line is enough for the site, the tests and the archive. Node.js is only used for Lighthouse and MCP Inspector.

### Why does the address stay unverified locally?

The built-in server is probably running with a single process: add `PHP_CLI_SERVER_WORKERS=4` before the command. On Windows, the check fails without affecting the rest of the site.

### Do the tests modify my eclair/ folder?

No. They write to the system's temporary folder and work on copies, which are deleted at the end of each run.

### How do I test the archive I just built?

Unzip it, then run `ECLAIR_TEST_ROOT=/path/to/eclair php tests/run.php`. The checks then cover the compacted files, exactly as they'll ship to your host.
