> ## Documentation Index
> Fetch the complete documentation index at: https://constanza101-borrissol-28.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Performance optimization: Core Web Vitals and asset pipeline

> How Borrissol achieves Lighthouse Performance 99: Astro asset pipeline, AVIF/WebP images, self-hosted fonts, lazy loading, and Core Web Vitals targets.

Borrissol scores **Lighthouse Performance 99 on mobile** — the ceiling for a real-world multilingual marketing site with hero images, a carousel, a Maps embed, and Google Analytics. This page documents every technique that achieves that score, along with the hard rules that must be respected to keep it.

## Core Web Vitals targets

These are the measured values on mobile Lighthouse as of the last audit. Every production deploy should be checked against them.

| Metric                         | Target |
| ------------------------------ | ------ |
| First Contentful Paint (FCP)   | 1.5 s  |
| Largest Contentful Paint (LCP) | 1.8 s  |
| Total Blocking Time (TBT)      | 30 ms  |
| Cumulative Layout Shift (CLS)  | 0      |

<Tip>
  CLS of exactly 0 is a result of always providing explicit `width` and `height` attributes on every `<Picture>` and `<img>`. Never omit intrinsic dimensions from image elements.
</Tip>

## Image pipeline

All content images live in `src/assets/images/` and are processed at build time by Astro's `<Picture>` component. No image should be placed in `/public/` unless it cannot be processed (e.g., dynamically referenced OG images).

**Build-time output for every content image:**

* AVIF + WebP formats (`formats={['avif', 'webp']}`)
* Responsive `srcset` across configured breakpoints
* Intrinsic `width` and `height` retained from the source file

**Loading strategy:**

| Image              | Strategy                                   |
| ------------------ | ------------------------------------------ |
| Hero (LCP element) | `loading="eager"` + `fetchpriority="high"` |
| All other images   | `loading="lazy"`                           |

**Source file discipline:**

Source files should be no larger than approximately 2× the widest responsive variant served. A 6000×4000 px source file is wasteful when the largest responsive output is 1200 px wide. Keep source files proportionate.

### Pre-deploy asset audit

Before every production deploy, run the following command to spot any oversized files in `/public/`:

```bash theme={null}
find public -type f -exec ls -laS {} + | sort -k5 -n -r | head -10
```

Nothing in `/public/` should exceed **500 KB** without explicit justification documented in the PR.

## Fonts

Borrissol uses Roboto self-hosted as WOFF2. There is no Google Fonts CDN call — this eliminates a third-party DNS lookup and the associated render-blocking risk.

| Setting        | Value                                             |
| -------------- | ------------------------------------------------- |
| Family         | Roboto                                            |
| Format         | WOFF2 only                                        |
| Weights        | 400 (body/headings) and 500 (buttons, labels, UI) |
| `font-display` | `swap` on all `@font-face` declarations           |

<Warning>
  Never add a `<link>` to `fonts.googleapis.com`. The self-hosted WOFF2 setup is what eliminates the third-party DNS lookup from the critical path. Adding a Google Fonts CDN call would immediately degrade FCP on first visit.
</Warning>

## Scripts and runtime JavaScript

Borrissol ships **zero runtime JS framework bytes** to visitors. All interactive behaviour is implemented in vanilla JavaScript:

| Feature                  | Implementation                                 |
| ------------------------ | ---------------------------------------------- |
| Scroll reveal animations | `IntersectionObserver` — no library            |
| Testimonials carousel    | Vanilla JS arrow navigation                    |
| FAQ accordion            | Native `<details>` / `<summary>` — zero JS     |
| Google Maps embed        | CSS `filter: grayscale(1)` → color on `:hover` |
| Cookie consent           | Vanilla JS, persisted in `localStorage`        |

The `prefers-reduced-motion` media query is respected in the scroll reveal logic — users who have opted out of motion see content immediately without transitions.

## Preconnect hints

Preconnect resource hints are defined in the page `<head>` for third-party domains that Borrissol contacts at runtime (primarily Google Analytics / `gtag.js`). This moves the TCP handshake earlier in the waterfall and reduces the latency cost of the first GA request.

## OG image rules

The Open Graph image (`/public/og-default.jpg`) has strict constraints that exist because a previous version of the file was accidentally exported from Figma as PNG and reached **4 MB** in production, silently consuming bandwidth on every social share.

| Constraint       | Value               |
| ---------------- | ------------------- |
| Format           | **JPG** (never PNG) |
| Dimensions       | 1200 × 630 px       |
| File size target | \< 300 KB           |

<Warning>
  **Never export the OG image as PNG from Figma.** PNG exports of full-bleed artwork routinely produce files of 2–6 MB. JPG at quality 80–85 % hits the same visual result under 300 KB.
</Warning>

## UX additions with no performance cost

These features add meaningful UX without adding any JavaScript weight:

* **FAQ section** — uses native `<details>` / `<summary>` elements. Keyboard accessible, animated with CSS, requires no JS bundle.
* **Testimonials carousel** — a small vanilla JS file; no carousel library loaded.
* **Google Maps embed** — rendered as a standard `<iframe>`. The CSS `grayscale` → color hover effect is a pure CSS transition with no JS.
