# CLAUDE.md — Projet TCA Industries

## 1. Project overview

You are working on the website redesign for **TCA Industries**, a French SME based in Clermont-Ferrand specialized in the sale, repair, and on-site servicing of industrial equipment (electric motors, pumps, reducers, mechanical transmissions, industrial supplies).

The site is being built on Vultek's custom Symfony "moule" (template). The goal is a custom, lightweight, SEO-optimized website that targets a Lighthouse score of 100/100 across all categories.

**Current website**: https://www.tca-industries.fr/ (reference only — full rewrite, no migration)
**Target domain**: tca-industries.fr
**Site language**: French (all visible copy)
**Code language**: English (all variables, methods, classes, comments, commit messages, branch names)

---

## 2. How to use this repository

### 2.1 Reading order — read these files in this exact order before any work

1. `CLAUDE.md` (this file) — general rules and conventions
2. `docs/client.md` — TCA business info, services, brands, team, contacts, geographical coverage
3. `docs/seo-strategy.md` — complete SEO strategy, topic clusters, pillar pages, editorial calendar
4. `docs/pages.md` — page-by-page breakdown with primary and secondary keywords, target URLs, intent
5. `docs/technical.md` — Symfony conventions, project structure, technical rules
6. `docs/design.md` — Figma link, brand guidelines, design system usage
7. `docs/seo-audit.md` — historical audit of the existing domain (context only)
8. `docs/faq.md` — Google "People Also Ask" questions per page, used for FAQ sections (filled by Gabin in parallel)

### 2.2 Source of truth hierarchy

When information conflicts between sources, follow this priority order:
1. This `CLAUDE.md` file — highest priority
2. The `docs/*.md` files
3. The Figma mockup
4. The current TCA website (lowest priority — reference only)

**Never invent information.** If you cannot find a fact (price, delay, exact service offering, brand) in the `.md` files or on the current TCA site, ask Gabin. Do not write speculative content.

---

## 3. Hard rules — non-negotiable

### 3.1 Database migrations

**Absolute rule**: You NEVER run database migrations. This applies to:
- `make:migration`
- `doctrine:migrations:migrate`
- `doctrine:migrations:diff`
- `doctrine:schema:update`
- Any command that touches the database schema

If schema changes are needed, document them in a `MIGRATIONS_NEEDED.md` file at the project root, describe each change clearly, and let Gabin run the migrations himself.

### 3.2 Dirty form gate — required pattern on all CRUD updates

Every edit form (CRUD update) must prevent submission when nothing has changed — both on UI side (UX) and server side (defense in depth, no unnecessary flush). Reproduce this pattern systematically, no exceptions.

**Three locations to wire together**:

**1. Server — snapshot before `handleRequest`**
- Simple entities: `ProfileChangeDetector::snapshot($entity, ['fieldA', 'fieldB'])`
- Complex structures (e.g. `SiteParameter`): private method `takeSnapshot(): array` in the controller

**2. Server — comparison after `isValid()`**
- `$detector->hasChanged($entity, $snapshot)` or manual comparison from the snapshot
- If unchanged: do not call `$em->flush()`. Return `{success: true, changed: false, message: 'Aucune modification détectée.'}` (AJAX) or flash `warning`
- If changed: `flush()` then return `{success: true, changed: true, ...}` or flash `success`
- This protection is non-negotiable — it avoids useless DB writes + `updatedAt` mutations for nothing

**3. Front — visual gate on the submit button**
- Public / customer space pattern: `FormAjax.guardButton(btn, isReady, eventTargets)` — replaces the real `<button>` with a greyed-out `<div>` while `isReady()` returns false. Reference: `public/js/profile.js`, `public/js/settings.js`
- Admin pattern: add a CSS class (e.g. `adm-btn--unchanged`) on the button + intercept the `submit` event in `capture` mode to `e.preventDefault()` when nothing has changed. Reference: `public/js/admin-parameters.js`
- Original values are exposed to JS via `data-original-<field>` on the `<form>` element (rendered by Twig from the controller snapshot)

**Note for TCA**: The TCA site is mostly a showcase site. The only public form is the contact form (a create, not an update). The dirty form gate becomes relevant if a back-office is added later. Keep the rule visible here for future development.

### 3.3 Never invent content

You never invent:
- Phone numbers, addresses, opening hours
- Prices, delays, response times
- Service offerings or technical specifications
- Brand partnerships
- Team member names, roles, biographies
- Customer testimonials
- Numbers and statistics

All of these must come from `docs/client.md` or be explicitly requested from Gabin.

### 3.4 Never delete files without permission

Do not delete files, even ones that look unused. Ask Gabin first.

### 3.5 Never add heavy external libraries without permission

The site must hit Lighthouse 100/100. Before adding any npm package, ask Gabin and justify the value vs the bundle size cost.

---

## 4. Git workflow

### 4.1 Branch naming

All work happens on branches named `gabin/feature-name` (English, kebab-case).
Examples:
- `gabin/homepage-template`
- `gabin/service-pages-base`
- `gabin/seo-meta-implementation`
- `gabin/contact-form`

### 4.2 Commits

- Commit messages in English
- Imperative mood: "Add hero section to homepage", not "Added" or "Adding"
- Conventional Commits prefix when applicable: `feat:`, `fix:`, `refactor:`, `docs:`, `style:`, `chore:`
- Group related changes into logical commits — do not commit everything in one massive commit

### 4.3 Code review

Bart will review the code. Make sure your work is reviewable:
- Clean diffs
- No commented-out dead code
- No `console.log`, `dd()`, `dump()` left in the code
- No unused imports
- Format Twig templates consistently

---

## 5. Technical stack and conventions

### 5.1 Stack expected (Vultek moule)

Read the moule first to confirm versions. The general stack should be:
- **Symfony** (current major version)
- **Twig** for templating
- **Asset bundler**: as defined in the moule (Encore/Webpack or Vite)
- **Doctrine ORM** for the database
- **Stimulus** or vanilla JS for interactivity — no heavy front frameworks
- **CSS approach**: as defined in the moule

If the moule uses a specific component library or design system, follow it. Do not introduce new patterns without alignment.

### 5.2 Naming conventions

- **Code (variables, methods, classes, files)**: English
- **Routes (paths in the browser)**: French, matching the URLs in `docs/pages.md`
- **Twig blocks and templates**: English file names (`base.html.twig`, `service-page.html.twig`)
- **Database tables and columns**: English (snake_case)
- **CSS classes**: BEM or as defined in the moule, English

### 5.3 File structure

Respect the existing moule structure. Common Symfony locations:
- Controllers: `src/Controller/`
- Entities: `src/Entity/`
- Twig templates: `templates/`
- Public assets: `public/`
- Translations: `translations/` (French primary)

If creating new directories, follow the existing pattern.

---

## 6. SEO — exhaustive copywriting and technical rules

These rules are **mandatory** on every page. The goal is for the site to rank organically on Google for the keywords defined in `docs/pages.md`.

### 6.1 Title tag (the `<title>` HTML element)

- Length: **50 to 60 characters** (hard limit: 60)
- Format: `Primary Keyword Variation — Brand Name`
- Primary keyword in the first 30 characters
- Separator: ` · ` (middle dot with spaces). This is the convention already applied to every page of the site. Do not use the em dash, `docs/redaction-articles.md` section 5 bans it and the standard prevails.
- Brand `TCA Industries` at the end, shortened to `TCA` when the 60-character budget requires it
- Unique on every page, no duplicates anywhere
- Example for `/reparation-moteur-electrique/`:
  `Réparation Moteur Électrique Clermont · TCA Industries`

### 6.2 Meta description

- Length: **140 to 160 characters** (hard limit: 160)
- Includes: an action verb, the main differentiator, a call to action
- Primary keyword present at least once, naturally
- Unique on every page
- Not just a copy of the H1
- Example:
  `Nous réparons et rebobinons vos moteurs électriques en atelier ou sur site à Clermont-Ferrand. Toutes marques. Devis gratuit — 04 73 28 74 74.`

### 6.3 H1 (page heading)

- **One single H1 per page** — strictly enforced
- Contains the page's primary keyword
- Different wording from the title tag (do not repeat it identically)
- Length: ideally 40 to 70 characters
- Reflects what the user will get on this page
- Example for `/reparation-moteur-electrique/`:
  `Réparation et remise en état de moteurs électriques`

### 6.4 H2 / H3 / H4 hierarchy

- Section length is set by `docs/redaction-articles.md` section 7: **at least 150 words per H2**, and each H2 covers one single idea. The former "H2 every 200 to 300 words" ceiling is superseded, it conflicted with that floor.
- H2 contain secondary keywords from `docs/pages.md` for that specific page
- H3 used for sub-sections of an H2
- Do not skip levels (no H2 directly followed by H4)
- Maximum 3 heading levels (H1, H2, H3) for service pages; H4 acceptable in long blog articles
- Each H2 introduces a clear topic — no decorative or vague H2

### 6.5 Keyword strategy per page

For every page:

**Primary keyword**:
- Present in H1 (mandatory)
- Present in the title tag (mandatory)
- Present in the meta description (mandatory)
- Present in the first 100 words of body copy (mandatory)
- Present in the URL slug (mandatory)
- Repeated 2 to 3 times in the body, naturally
- Total keyword density: between **0.5% and 2%** of total page words — never higher (keyword stuffing penalty)

**Secondary keywords** (from `docs/pages.md` for that page):
- Each secondary keyword appears at least once
- Distributed across H2 and body
- Integrated naturally — no forced or awkward placement
- Variations and synonyms are encouraged

### 6.6 Content length

**Do not look for length rules here.** `docs/redaction-articles.md` is the single source of truth for the editorial standard, target lengths included. Section 7 of that file gives the figures for blog articles and pillar pages. It overrides every other file in the repository, this one included, whenever they diverge.

The pages that `docs/redaction-articles.md` does not cover (homepage, about, contact) follow the indications given page by page in `docs/pages.md`.

### 6.7 Writing style — mandatory rules

- **Sentences**: short, average 15 to 20 words, never above 25 words
- **Paragraphs**: 3 to 4 sentences maximum
- **Tone**: professional but approachable. Direct. Concrete. No jargon for the sake of jargon.
- **No marketing superlatives**: never use "the best", "leader", "number one", "the most reliable". TCA is not a luxury brand — it is a credible, reliable, human-scale business.
- **No filler phrases**: avoid "in today's world", "in our modern economy", "as you know"
- **Active voice preferred over passive voice**
- **Address the reader directly** ("vous") in service pages
- **First person plural** ("nous") for TCA Industries
- **Use the real technical vocabulary** of the industry: rebobinage, stator, induit, roulement, triphasé, monophasé, étuvage, palier, accouplement, variateur de fréquence, etc.

### 6.8 Internal linking

- Every service page links to at least **3 related blog articles** (in the "Articles liés" section)
- Every service page links to at least **3 other service pages** (in the "Autres services" section)
- Every blog article links to **its corresponding pillar service page** (contextually within the text)
- Every blog article links to **2 to 3 related blog articles**
- **Anchor text rule**: descriptive, never "cliquez ici" or "en savoir plus" alone. The anchor must describe the destination.
  - ❌ Bad: "Pour en savoir plus, cliquez ici"
  - ✅ Good: "Découvrez notre service de réparation de moteur électrique"

### 6.9 Image rules

- All images in **WebP format** (with PNG/JPG fallback via `<picture>` element)
- All images have `width` and `height` attributes set in HTML to prevent CLS
- All images have a descriptive `alt` attribute, max 125 characters
- Alt text contains the page keyword **when relevant** (do not force it)
- File naming: kebab-case, descriptive, includes context
  - ✅ `reparation-moteur-electrique-atelier-tca-clermont.webp`
  - ❌ `IMG_4523.webp`
- Lazy loading (`loading="lazy"`) on all images except the hero LCP image
- The hero LCP image of each page has `fetchpriority="high"` and is preloaded
- Maximum weight per image: 150 KB; hero image: 300 KB max
- Photos are provided by Gabin in `/public/images/` (organized by page or theme)

### 6.10 URLs

- Lowercase only
- Kebab-case (dash separator, never underscore)
- No accents (use "reparation" not "réparation")
- No query parameters in indexable URLs
- Trailing slash: consistent across the site (preferred: with trailing slash for pages, without for files)
- Maximum 3 levels of depth
- URLs are defined in `docs/pages.md` and must not be changed without alignment with Gabin

### 6.11 Schema.org / JSON-LD — mandatory implementations

Every page outputs structured data in JSON-LD format in the `<head>` section.

| Schema | Where | Required fields |
|---|---|---|
| `LocalBusiness` | Every page | name, address, telephone, openingHours, geo, areaServed |
| `Organization` | Homepage, About page | name, logo, url, sameAs (LinkedIn) |
| `Service` | Each service page | name, description, provider, areaServed, serviceType |
| `BreadcrumbList` | Every page except homepage | itemListElement with position, name, item URL |
| `FAQPage` | Service pages + blog articles only | mainEntity array with Question/Answer pairs |
| `Article` | Blog articles only | headline, author, datePublished, dateModified, image |
| `WebSite` | Homepage only | name, url, potentialAction (SearchAction if site search exists) |

All structured data must validate cleanly in Google's Rich Results Test.

### 6.12 FAQ sections — placement and rules

**Where to place FAQ sections** (NOT on every page):

| Page type | FAQ accordion? | FAQPage schema? |
|---|---|---|
| Homepage | No | No |
| Service pages (T2) | **Yes — mandatory** | **Yes** |
| Blog articles (T6) | **Yes — mandatory** | **Yes** |
| About page | No | No |
| Contact page | No | No |
| Blog listing page | No | No |

**FAQ rules**:
- Use **only** the questions from `docs/faq.md` — do not invent FAQ questions
- 4 to 6 Q/A pairs per service page
- 3 to 5 Q/A pairs per blog article
- Each answer: **2 to 4 sentences**, complete and self-contained (`docs/redaction-articles.md` section 3). The former "40 to 80 words" figure is superseded, the sentence count is the rule that applies.
- Blog article FAQ questions must not repeat the H2 of the article, they cover the peripheral questions that had no place in the body
- Answers contain natural keyword variations
- Accordion behavior: one open at a time, smooth animation, accessible (ARIA attributes)

### 6.13 Canonical, robots, Open Graph

- `<link rel="canonical">` on every page, pointing to the absolute URL of the page itself
- `<meta name="robots" content="index, follow">` on indexable pages
- `<meta name="robots" content="noindex, follow">` on: search results, confirmation pages, legal pages (CGV, mentions légales, politique de confidentialité), 404 page
- Open Graph tags on every page: `og:title`, `og:description`, `og:image`, `og:url`, `og:type`, `og:locale` (fr_FR), `og:site_name`
- Twitter cards: `twitter:card` (summary_large_image), `twitter:title`, `twitter:description`, `twitter:image`

### 6.14 Sitemap and robots.txt

- `sitemap.xml` generated dynamically via a Symfony route, updated automatically on page/article creation
- Located at `/sitemap.xml`
- Only contains indexable URLs (excludes noindex pages)
- Each URL has `lastmod`, `changefreq`, `priority`
- `robots.txt` at `/robots.txt`:
  - `User-agent: *`
  - `Allow: /`
  - `Disallow: /admin/` (if admin exists)
  - `Sitemap: https://tca-industries.fr/sitemap.xml`

### 6.15 Performance — Lighthouse 100/100 target

Non-negotiable thresholds for the launch:
- **Performance**: ≥ 95 (target 100)
- **Accessibility**: 100
- **Best Practices**: 100
- **SEO**: 100

Core Web Vitals targets:
- **LCP** (Largest Contentful Paint): ≤ 2.5 s on mobile 4G
- **INP** (Interaction to Next Paint): ≤ 200 ms
- **CLS** (Cumulative Layout Shift): ≤ 0.1
- **TTFB** (Time to First Byte): ≤ 800 ms

Implementation requirements:
- CSS minified, critical CSS inlined for above-the-fold content
- JavaScript minified, deferred or async where possible
- No render-blocking resources
- Compression (gzip or brotli) enabled at the server level
- HTTP/2 enabled
- Browser cache headers configured for static assets (long max-age)
- Fonts preloaded with `font-display: swap`
- Subset fonts to French character range
- No unused CSS or JS in production
- Images served in WebP with `<picture>` fallback
- Lazy loading on non-critical images
- `width` and `height` set on all images and iframes

### 6.16 Accessibility — required for Lighthouse 100

- Semantic HTML (use `<header>`, `<nav>`, `<main>`, `<article>`, `<section>`, `<footer>`)
- Single `<main>` element per page
- `<h1>` always present
- All form fields have a visible `<label>` (not just placeholders)
- All form fields have associated error messages
- Color contrast ratio: minimum 4.5:1 for body text, 3:1 for large text
- Focus visible on all interactive elements
- Keyboard navigation works on every interactive element
- `<html lang="fr">` on every page
- `alt` attribute on every `<img>` (empty `alt=""` for decorative images)
- ARIA attributes used correctly (not abused)
- Skip-to-content link at the top of the page

---

## 7. Page-specific copywriting guidance

For each page type, refer to `docs/pages.md` for the primary and secondary keywords, then write the content following these patterns.

### 7.1 Homepage (`/`)

- H1 includes "Clermont-Ferrand" and a strong service keyword
- First paragraph: positioning of TCA + main value proposition (same-day response, 30 years, all brands)
- Do not try to cover every service in detail on the homepage — orient and direct toward service pages
- Lead with the 3 core activities (sale, repair, troubleshooting) prominently
- Real numbers and trust signals visible (30 years, 8 departments, thousands of references)
- 2 to 3 visible CTAs to the phone number
- Bottom of page: 3 latest blog articles to signal activity

### 7.2 Service pages (`/reparation-moteur-electrique/`, etc.)

Pattern for the body content of every service page:

1. **First paragraph (introduction)**: rephrase the visitor's problem and announce TCA's solution. Primary keyword in the first 100 words.
2. **What we do** (H2): list of concrete services offered for this specific service
3. **Our process** (H2): how TCA handles a request from start to finish (call → diagnosis → quote → intervention → follow-up)
4. **Brands and equipment** (H2 — optional): brands handled, types of equipment serviced
5. **Coverage area** (H2): list of cities and departments covered
6. **Why choose TCA** (H2): trust signals specific to this service (experience, equipment, certifications)
7. **FAQ** (H2 mandatory): 4 to 6 Q/A from `docs/faq.md`
8. **CTA section**: contact form or phone CTA

Length target: see `docs/redaction-articles.md` section 7, which sets pillar pages at 2 000 to 2 800 words. The 600 to 900 words previously written here and still present in `docs/pages.md` are below that standard, arbitration pending.

### 7.3 Blog articles (`/blog/article-slug/`)

Pattern:

The structure is the one imposed by `docs/redaction-articles.md` section 3. Summary:

1. **H1** phrased as the query is actually typed, no two-part construction split by punctuation
2. **Direct answer**, 2 to 4 sentences (40 to 80 words) right under the H1, before anything else, self-contained
3. **Table of contents**: clickable list of H2 sections
4. **Body**: H2 phrased as reader questions or clear steps, one idea per H2, at least 150 words each, at least two real explanatory paragraphs per section. A bullet list is never the explanation, it recaps after it. A table as soon as several options or cases are compared.
5. **Closing paragraph** that answers the title question a second time, differently worded
6. **Contextual link to the cluster pillar page** with a descriptive anchor, plus 2 to 3 links to articles of the same cluster placed in the body where they are relevant, not stacked at the bottom
7. **FAQ**: 3 to 5 Q/A entered in the `faq` field of the `Article` entity, not repeating the H2

Length target: see `docs/redaction-articles.md` section 7. Standard satellite article 1 100 to 1 600 words, article on a commercially loaded query (price, comparison) 1 400 to 2 000 words.

**Author block**: not applicable for now. `docs/client.md` section 8 forbids attributing an article to a named author until TCA validates the org chart and the individual consents.

### 7.4 About page (`/a-propos/`)

- History of TCA (30 years)
- The team (names, roles, photos)
- Values: Disponibilité, Conseil, Proximité, Réactivité
- Brand partners
- Numbers (years in business, departments covered, references in stock)
- Closing CTA: visit or call

### 7.5 Contact page (`/contact/`)

- Emergency banner at the top
- Two-column layout: form on one side, info on the other
- Form fields: Nom, Prénom, Email, Téléphone, Sujet (dropdown), Message
- Google Maps embed at the bottom
- Mention "Free quote" and "Same-day response" prominently

---

## 8. Design system — using the Figma mockup

### 8.1 The mockup as reference, not as cage

The Figma mockup provided by Waqas is a **visual reference**, not a rigid blueprint. The mockup shows a sample of pages and sections; the real site has more pages and may need more or different sections.

**Rules**:
- Reuse the design system from the mockup (colors, typography, spacing, button styles, card styles)
- If a page needs sections that are not in the mockup, **create new sections by reusing existing components and styles**
- If a section in the mockup has 3 cards but the real content has 6 items, adapt the section to fit 6
- Maintain visual consistency across the whole site
- The brand guidelines in `docs/design.md` and the assets in the drive are the source of truth

### 8.2 Mobile-first

Mobile rendering is as important as desktop. Specifically:
- Phone CTA always accessible on mobile (sticky header or floating button)
- Touch targets minimum 44×44 px
- Readable typography on mobile (minimum 16 px body)
- No horizontal scroll
- Tested on iPhone SE width (320 px) up to iPad Pro (1024 px) and desktop (1440 px+)

---

## 9. What you can do autonomously vs what to ask first

### 9.1 You can do autonomously

- Create new Twig templates, controllers, services, repositories
- Write copywriting based on `docs/*.md` files
- Generate JSON-LD schemas
- Generate sitemap and robots.txt
- Implement page templates from the Figma mockup
- Refactor your own code
- Add small utility libraries (if lightweight and justified)
- Write meta tags, alt text, structured data
- Create blog post templates and structure
- Implement the contact form
- Set up Google Analytics 4 and Google Search Console verification

### 9.2 Ask Gabin first before

- Running any database migration (forbidden — see rule 3.1)
- Modifying the `composer.json` to add a new dependency
- Adding any npm package above 50 KB minified
- Deleting files
- Changing URLs defined in `docs/pages.md`
- Changing the structure of the database schema
- Modifying the existing Vultek moule conventions
- Changing the visual identity (colors, fonts) from `docs/design.md`
- Publishing or pushing to a remote branch other than `gabin/*`

---

## 10. Pre-commit checklist

Before considering work complete on a page or feature, verify:

**SEO**:
- [ ] Single H1 on the page
- [ ] H1 contains the primary keyword
- [ ] Title tag 50-60 characters, unique
- [ ] Meta description 140-160 characters, unique
- [ ] Primary keyword in the first 100 words of body
- [ ] Secondary keywords distributed in H2 and body
- [ ] Canonical link present
- [ ] Open Graph tags complete
- [ ] JSON-LD structured data present and valid
- [ ] All images have alt text
- [ ] All images in WebP with proper fallback
- [ ] Internal links to related pages present
- [ ] FAQ section present (if applicable to page type)

**Technical**:
- [ ] Page renders without console errors
- [ ] Page passes HTML validation
- [ ] Responsive on mobile (320px) and desktop (1440px+)
- [ ] Lighthouse score: Performance ≥ 95, Accessibility 100, Best Practices 100, SEO 100
- [ ] No `console.log`, `dd()`, `dump()` left in code
- [ ] No unused imports
- [ ] No hardcoded strings that should be translations (if i18n is used)

**Content**:
- [ ] Word count within the range set by `docs/redaction-articles.md` section 7
- [ ] Sentences average 15-20 words
- [ ] Paragraphs 3-4 sentences max
- [ ] No marketing superlatives
- [ ] All numbers and facts sourced from `docs/client.md`
- [ ] Technical vocabulary accurate

---

## 11. Common mistakes to avoid

- ❌ Writing "Nous sommes les meilleurs / leader / numéro 1 / experts incontournables"
- ❌ Inventing prices, delays, response times, certifications
- ❌ Creating FAQ questions yourself instead of pulling from `docs/faq.md`
- ❌ Using stock photos instead of the real TCA photos
- ❌ Skipping the canonical link
- ❌ Multiple H1 on the same page
- ❌ Title tag exceeding 60 characters
- ❌ Meta description exceeding 160 characters
- ❌ Running a database migration
- ❌ Adding a heavy npm package without asking
- ❌ Hardcoding the phone number or address in 20 places — use a config or service
- ❌ Forgetting `width` and `height` on images
- ❌ Loading Google Fonts via `@import` (use `<link rel="preload">` instead)
- ❌ Inline CSS on every page (use external CSS with critical CSS inlined for hero only)
- ❌ Using `<div>` where semantic HTML applies (`<nav>`, `<article>`, `<section>`)

---

## 12. Verification tools Gabin will use after delivery

You should write code that passes:
- **Google PageSpeed Insights** (Lighthouse)
- **Google Rich Results Test** (structured data)
- **Google Search Console** URL Inspection
- **Screaming Frog SEO Spider** (full crawl of titles, metas, H1, etc.)
- **WAVE Web Accessibility Evaluation Tool**
- **HTML W3C Validator**

If your code fails any of these for SEO/performance/accessibility reasons, that is a defect.

---

## 13. Communication with Gabin

- Be direct. No fluff.
- If you are uncertain about a fact, ask — do not guess.
- If a `docs/*.md` file is missing information you need, flag it before continuing.
- When delivering work, summarize what was done, what was not done, and why.
- Suggest improvements when relevant, but do not implement them without alignment.

---

## 14. Project state and progress tracking

Keep a `PROGRESS.md` file at the project root updated with:
- Pages completed (with URL)
- Pages in progress
- Blockers (missing assets, missing information)
- Next steps

Update it at the end of every working session.

---

**End of CLAUDE.md** — this file is the source of truth for all working conventions on the TCA Industries project. If anything is unclear, ask Gabin before proceeding.
