---
title: "Files, folders and URLs"
description: "Éclair's files and folders explained: data/, cache/, media/, eclair-config.php, .htaccess, Nginx, permissions, backups and generated URLs."
url: "https://eclair.academy/en/docs/files"
lang: "en"
author: "Thierry Gustin"
published: "2026-11-02"
updated: "2026-11-02"
---

# Files, folders and URLs

> **Key takeaways** — Éclair fits in one folder. index.php serves the pages, app/ and assets/ hold the code, data/ keeps content, settings and accounts, cache/ the generated pages and media/ the images. Only data/ and media/ need backing up. The .htaccess file protects the internal folders, and Éclair generates sitemap.xml, robots.txt, llms.txt, the feeds and the Markdown versions on its own.

Éclair has no database: everything that makes up your site lives in files and folders you can see over FTP. This reference describes the file tree, the role of each file in `data/`, the settings in `eclair-config.php`, the `.htaccess` and Nginx rules, the permissions to set, what to back up and every URL the site generates on its own.

## The eclair folder tree

The files and folders below are what you upload to your hosting's public folder (`public_html`, `www`…).

```text
eclair/
├── index.php                  front controller: serves the cache without loading the application
├── .htaccess                  rewriting, protections, compression, browser caching
├── eclair-config.exemple.php  template for the optional advanced settings
├── app/                       Éclair's code (never reachable from the web)
│   ├── bootstrap.php          startup: PHP version, eclair-config.php, loading
│   ├── manifest.php           original fingerprints for the integrity check
│   ├── lib/                   classes: Content, Blocks, Seo, Analyzer, Media, Auth, Mcp…
│   ├── admin/views/           admin screens (.php.gz in the archive)
│   ├── install/               setup wizard and “Installation locked” screen
│   ├── lang/                  admin translations (6 languages, compressed JSON)
│   └── theme/                 public site templates, theme.css, themes/, directions.css
├── assets/
│   ├── admin/                 admin CSS and JavaScript
│   └── site/site.js           the public site's only script (1.2 KB compressed)
├── data/                      content, settings, accounts: never public
├── cache/                     generated pages: never public
└── media/                     uploaded images, site icons, heading font
```

`app/` and `assets/` contain the code: an update replaces them. Your data is in `data/` and `media/`, which updates never touch. Next to the `eclair` folder, the official archive also contains the `LISEZ-MOI.txt`, `LICENSE.txt` and `THIRD-PARTY-NOTICES.txt` files: there's no need to upload them to your hosting.

## How is a page served?

![Request cycle: a page served from the static cache or generated by the application](https://eclair.academy/media/2026/11/eclair-academy-architecture-en.png)
*The static cache fast path*

1. Every page request arrives at `index.php`; images, CSS and scripts are served directly by the server. For a read (`GET` or `HEAD`), `index.php` reads `cache/runtime.php`: whether the cache is on, its expiry date, and the required domain and HTTPS.
2. If the page exists in `cache/pages/`, it's sent as is, with its ETag; a browser that already has it gets a `304 Not Modified` response.
3. Otherwise, `app/bootstrap.php` starts the application: it checks the PHP version, reads `eclair-config.php` if it exists, then routes the request to the installer, the admin, the form, the MCP connector or the site. The generated page is cached for the next visits.

The code is covered in detail in [Éclair's architecture](https://eclair.academy/en/paths/expert/architecture).

## What does the data folder contain?

Each file in `data/` is a `.php` file that starts with the line `<?php exit; ?>`, followed by JSON data. Even if a server ignored `.htaccess` files, opening one in a browser would display nothing. Writes are atomic (a temporary file, then a rename) and the files are private.

| File or folder | Contents | In the ZIP backup |
| --- | --- | --- |
| `site.php` | All the settings from the Settings tabs | Yes |
| `users.php` | Accounts, password hashes, two-factor authentication | Yes |
| `keys.php` | Secret keys created at installation (site secret, IndexNow key) | Yes |
| `vault.php` | The AI assistant's API keys, encrypted | No |
| `index.php` | A summary of all content, to list it and find a URL quickly | Yes |
| `content/` | One file per page, post or product | Yes |
| `revisions/` | The 20 latest versions of each piece of content | Yes |
| `search.php` | The text of your content, for site search | Yes |
| `media.php` | The media library register: files, dimensions, alt texts | Yes |
| `categories.php`, `menus.php`, `redirects.php` | Categories, menus and redirects | Yes |
| `custom-css.php` | Your custom CSS | Yes |
| `inbox.php` and `messages/` | The contact form inbox, 500 messages at most | Yes |
| `indexnow.php` | Date and result of the last IndexNow submission | Yes |
| `logs/` | Security log and technical errors, 1 MB at most each | Yes |
| `sessions/` | Open sessions, stored under a hashed name | No |
| `limits/` | Brute-force and anti-spam counters | No |
| `ai/` | Spending, conversations (30 per person), suggestions, undo data, MCP connections | No |
| `install-window.php` | Start of the 2-hour installation window, deleted when installation is complete | Not applicable |
| `reset.php` | “Forgot password” recovery file, created by you, deleted automatically | No |

> **Don't edit these files by hand** — Corrupted JSON makes the data unreadable. In `data/`, the only file meant to be created via FTP is `reset.php`: the steps are in [Troubleshooting](https://eclair.academy/en/docs/troubleshooting).

## The cache and media folders

### cache/

| Item | Role |
| --- | --- |
| `runtime.php` | Fast-path settings: cache on or off, expiry at the next scheduled post, required domain and HTTPS |
| `pages/` | One generated page per URL, named after the md5 hash of its path: a line of headers and ETag, then the HTML |
| `backup-….zip` | A backup being downloaded, deleted afterwards; if the download was interrupted, it's erased when the cache is cleared, at least an hour later |

The cache clears itself on every change, and at the scheduled time for a scheduled post. To clear it by hand: **Settings › Advanced › Clear cache**.

### media/

| Item | Role |
| --- | --- |
| `2026/11/…` | Uploaded images, sorted by year and month |
| `photo.jpg`, `.png`, `.webp` or `.gif` | The re-encoded image, 2,000 px wide at most, with no EXIF or GPS data (with the GD extension) |
| `photo-480.webp` to `photo-1600.webp` | WebP versions at 480, 800, 1200 and 1600 px (only those smaller than the original), plus a WebP version at the image's own size |
| `photo-og.jpg` | 1200 × 630 share image, created the first time it's needed |
| `site/icon-32.png`, `icon-180.png`, `icon-192.png`, `icon-512.png` | Site icons: favicon and mobile home screen |
| `fonts/` | Your art direction's heading font (`.woff2`), downloaded once |

The `media/.htaccess` file only allows images: no scripts, HTML pages, SVG or file listings, with a security policy that forbids any active content. Uploads are covered in detail in [Images and the media library](https://eclair.academy/en/paths/beginner/images-media-library).

## What goes in eclair-config.php?

This optional file sits next to `index.php`. Copy `eclair-config.exemple.php` under the name `eclair-config.php`, then uncomment what you need. It's read when the application starts, before anything else, and the integrity check doesn't flag it as an unknown file.

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

// Error details, while you solve a problem:
// define('ECLAIR_DEBUG', true);

// Data outside the public folder (move the data folder first):
// define('ECLAIR_DATA', '/home/myaccount/eclair-data');

// Stronger protection for API keys, to set before saving them:
// define('ECLAIR_SECRET', 'a-long-secret-phrase');
```

| Constant | Effect | Precaution |
| --- | --- | --- |
| `ECLAIR_DEBUG` | Shows error details | Also turns off the static cache: delete the line once the problem is solved |
| `ECLAIR_DATA` | Stores the data in another location (absolute path) | Move `data/` first, and remember to back up the new location |
| `ECLAIR_SECRET` | Adds a secret phrase to the encryption of API keys | Set it before saving your keys; if you add or change it later, you have to paste them again |

The code also recognizes two technical constants that aren't in the official guide: `ECLAIR_AI_ENDPOINTS` (a replacement URL for an AI service, for a gateway or for tests) and `ECLAIR_FONTS_URL` (the font source, Fontsource via `cdn.jsdelivr.net` by default). Only use them if you know why. `ECLAIR_VERSION` and `ECLAIR_ROOT` are set by `index.php`.

## The .htaccess rules explained

Éclair's `.htaccess` file works at the root of a domain as well as in a subfolder. It only uses directives allowed on shared hosting: no `Options`, no `php_flag`. Here is its rewriting section:

```apache
RewriteEngine On
# RewriteBase /
RewriteCond %{HTTP:Authorization} .
RewriteRule ^ - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]
RewriteRule ^(app|data|cache)(/|$) - [R=404,L]
RewriteRule (^|/)\.(?!well-known/) - [R=404,L]
RewriteRule ^(?!index\.php$).*\.(php\d?|phtml|phar|inc)$ - [R=404,NC,L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^ index.php [L,QSA]
```

1. `RewriteBase /` stays commented out: uncomment it only if your host requires it, which is rare.
2. The two `Authorization` lines pass PHP the authorization header that some hosts strip. The MCP connector needs it.
3. `app/`, `data/` and `cache/` return a 404 from the web.
4. Hidden files (`.git`, `.env`…) return a 404, except for the `.well-known` folder.
5. No PHP script runs except `index.php`.
6. Everything that isn't an existing file goes through `index.php`, even a folder: no file listing is ever shown.

The rest of the file turns on Brotli or Gzip compression for HTML pages, CSS stylesheets, JavaScript, JSON and XML data, RSS feeds, SVG images and Markdown, sets one-year browser caching for images, CSS, scripts and fonts (`Cache-Control: public, max-age=31536000, immutable`), and declares the WebP, AVIF and WOFF2 types. The `app/`, `data/` and `cache/` folders also have their own `.htaccess` that denies all access, so the protection is doubled.

> **Hidden files don't upload by themselves** — Names that start with a dot are hidden by default in many FTP clients and file managers. Turn on the display of hidden files before uploading, otherwise every page except the home page returns a 404. The full syntax is described in the [Apache documentation on .htaccess files](https://httpd.apache.org/docs/current/howto/htaccess.html).

## The Nginx configuration

Nginx ignores `.htaccess` files: reproduce these rules in your site's `server` block. This is the configuration given in the official guide.

```nginx
location ~ ^/(app|data|cache)(/|$) { return 404; }
location ~ /\.(?!well-known/) { return 404; }
location ^~ /media/ {
    location ~* \.(php\d?|phtml|phar|s?html?|svgz?|xml|js)$ { return 404; }
    add_header X-Content-Type-Options nosniff;
    expires 1y;
}
location ~* \.(webp|avif|jpe?g|png|gif|ico|css|js|woff2)$ { expires 1y; add_header Cache-Control "public, immutable"; }
location / { try_files $uri /index.php$is_args$args; }
location = /index.php {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root/index.php;
    fastcgi_pass unix:/run/php/php-fpm.sock;
}
location ~ \.php$ { return 404; }
```

- The first two rules close off the internal folders and hidden files, except `.well-known`.
- The `/media/` block refuses scripts, HTML pages, SVG and XML, and caches files for a year.
- `try_files` sends everything that isn't an existing file to `index.php`.
- Only `index.php` is handed to PHP-FPM: adapt `fastcgi_pass` to your server's socket.
- For the AI assistant to stream its answers as they're written, add `fastcgi_buffering off;` to the PHP block.

HTTPS, proxies and CDNs are covered in [Nginx, VPS, proxy and CDN](https://eclair.academy/en/paths/expert/nginx-vps).

## What permissions should files and folders have?

- PHP must be able to write to `data/`, `cache/` and `media/`. The setup wizard checks each of them (**Folder “data” is writable**) and, if a check fails, advises giving write permission (755) via FTP.
- Éclair then creates its data files with 0600 permissions (readable only by the account that runs PHP), its subfolders of `data/` and `cache/` with 0700, and those of `media/` with 0755.
- Avoid 777 permissions, which let any account on the server write. If 755 isn't enough, ask your host which account PHP runs under.

## Which files and folders should you back up?

| What to back up | Why | How |
| --- | --- | --- |
| `data/` | Content, settings, accounts, custom CSS | Security › **Download a backup**, or FTP |
| `media/` | Images, icons, heading font | Same ZIP backup, or FTP |
| `eclair-config.php` | If you created one | FTP |
| Modified templates in `app/theme/` | An update replaces them | FTP, before every update |
| Folder set by `ECLAIR_DATA` | If you moved your data | FTP |

The ZIP backup contains neither the API keys, nor the conversations and MCP connections, nor the sessions. After restoring to another server, paste your API keys again and reconnect Claude or ChatGPT. To restore, replace `data/` and `media/` with the ones from the backup (via FTP), then clear the cache from the admin.

![Updating: app and assets are replaced, data and media are kept](https://eclair.academy/media/2026/11/eclair-academy-update-en.png)
*What an update replaces and what it keeps*

The complete update procedure is in [Advanced security and maintenance](https://eclair.academy/en/paths/expert/advanced-security).

## The URLs generated by Éclair

| URL | Content | When it exists |
| --- | --- | --- |
| `/sitemap.xml` | Site map with images and language versions | Always; empty if the site is hidden from search engines |
| `/robots.txt` | Bot rules, including 30 AI bots, and the sitemap link | Always |
| `/llms.txt` | Site map for AI | **Publish /llms.txt** option |
| `/llms-full.txt` | All the content in Markdown | `/llms.txt` and `/llms-full.txt` options |
| `/feed.xml` | RSS feed of the 20 latest posts, full text | Blog enabled |
| `/products.xml` | Product feed for Google Merchant Center | Shop open |
| `/my-page.md`, `/index.md` | Markdown version of a page, `noindex`, with its canonical URL | **Markdown version of every page** option, except for `noindex` pages |
| `/favicon.ico` | 32 px icon | As soon as the site icon exists |
| `/search?q=…` | Search results, `noindex` | **Site search** option |
| `/<key>.txt` | IndexNow ownership proof | IndexNow enabled |
| `/_eclair/mcp` | MCP connector | **Allow MCP connections** |
| `/_eclair/oauth/authorize`, `/token`, `/register` | OAuth authorization for the connector | Same condition |
| `/.well-known/oauth-protected-resource`, `/.well-known/oauth-authorization-server`, `/.well-known/openid-configuration` | OAuth discovery | Same condition |
| `/_eclair/contact` | Receives the contact form | Always |
| `/_eclair/edit/<id>` | The site's **✏️ Edit** button, leading to the editor | Logged-in users |
| `/__eclair/ping` | Rewriting test and site address verification | Always |

### Content URLs

| Content | URL on an English-language site |
| --- | --- |
| Page | `/my-page`, or `/parent/child` for a subpage (4 levels at most) |
| Home page | `/`; the home page's own URL redirects to `/` |
| Post | `/blog/my-post` |
| Further blog pages | `/blog/page/2` |
| Post category | `/blog/my-category` |
| Author page | `/blog/author/first-last` |
| Catalog | `/shop`, then `/shop/page/2` |
| Product category, product | `/shop/my-category`, `/shop/my-product` |
| Admin | The URL chosen during installation |

The words in URLs follow the site's language: `page` in French and English, `pagina` in Spanish, Italian and Portuguese, `seite` in German; `auteur`, `autor`, `author` or `autore`; `recherche`, `buscar`, `search`, `suche`, `cerca` or `pesquisa`; `boutique`, `tienda`, `shop`, `negozio` or `loja`.

One URL per piece of content: Éclair 301-redirects variants with capital letters, a trailing slash, double slashes or `index.php`, as well as `http` to `https` when HTTPS is forced, and `www` or non-`www` once the official URL is verified.

Some words are reserved and can't be used as a page URL: `app`, `data`, `cache`, `assets`, `media`, `index`, `admin`, `_eclair`, `__eclair`, `sitemap`, `robots`, `feed`, `llms`, `llms-full`, `favicon`, `wp-admin`, `wp-login`, plus your admin URL, the blog URL, the search word and the shop URL once it's set up. The SEO side of these URLs is covered in [SEO with Éclair](https://eclair.academy/en/paths/intermediate/seo).

## Frequently asked questions about files

### Can I delete the cache folder?

Don't delete the folder itself: it contains its own `.htaccess` protection. Use **Settings › Advanced › Clear cache**, which only erases the generated pages; they're recreated on the next visit.

### Where are my posts stored?

In `data/content/`, one file per piece of content, with their 20 latest versions in `data/revisions/`. Images are in `media/`, sorted by year and month.

### Can you put the data folder outside the public folder?

Yes, if your host allows it: move the `data` folder, then give its absolute path with `ECLAIR_DATA` in `eclair-config.php`. Add the new location to your backups.
