https://github.com/cedric-v/fluance-io
Fluance.io website: content, build and deployement workflow
https://github.com/cedric-v/fluance-io
11ty github-actions jamstack javascript markdown markdown-to-html mjml multilingual nodejs nunjucks responsive-design static-site-generator tailwindcss
Last synced: 2 months ago
JSON representation
Fluance.io website: content, build and deployement workflow
- Host: GitHub
- URL: https://github.com/cedric-v/fluance-io
- Owner: cedric-v
- License: other
- Created: 2025-12-01T08:11:24.000Z (7 months ago)
- Default Branch: main
- Last Pushed: 2026-03-09T18:09:14.000Z (3 months ago)
- Last Synced: 2026-03-09T18:33:44.741Z (3 months ago)
- Topics: 11ty, github-actions, jamstack, javascript, markdown, markdown-to-html, mjml, multilingual, nodejs, nunjucks, responsive-design, static-site-generator, tailwindcss
- Language: JavaScript
- Homepage: http://fluance.io
- Size: 24.5 MB
- Stars: 1
- Watchers: 0
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- Copyright: COPYRIGHT
Awesome Lists containing this project
README
## Fluance.io
Fluance.io is a multilingual (FR/EN) static website built with [Eleventy](https://www.11ty.dev/) and [Tailwind CSS](https://tailwindcss.com/).
It is designed to be simple to develop locally, deploy on static hosting (GitHub Pages, Netlify, etc.), and easy to maintain over time.
---
### Tech stack
- **Eleventy 3** as static site generator
- **Nunjucks** templates
- **Tailwind CSS 4** for styling (CSS-first configuration)
- **Node.js / npm** for tooling
---
### Performance optimizations
The site includes several performance optimizations to ensure fast loading and smooth user experience:
#### Image optimization
- **WebP support with automatic fallback**: Images are automatically served in WebP format when available, with fallback to original formats (JPG/PNG) for compatibility
- **Explicit dimensions**: All images include `width` and `height` attributes to prevent Cumulative Layout Shift (CLS)
- **Lazy loading**: Images below the fold use `loading="lazy"` for faster initial page load
- **Eager loading for LCP**: Hero images and critical images use `loading="eager"` and `fetchpriority="high"` for optimal Largest Contentful Paint (LCP)
- **Responsive positioning**: Hero images use responsive `object-position` (centered on mobile, right-aligned on desktop)
#### Navigation optimization
- **Link prefetching**: Menu links are prefetched on hover (with 100ms delay) to accelerate page transitions
- **Smooth transitions**: CSS transitions reduce visual flicker during navigation
- **Optimized event listeners**: Uses `passive: true` for better scroll performance
#### Font loading
- **Preconnect**: Early connection to Google Fonts and external resources
- **Preload**: Critical Inter font is preloaded for faster rendering
- **Font-display**: Uses `font-display: optional` to prevent layout shifts
#### CSS and resource loading
- **CSS preload**: Critical CSS is preloaded asynchronously
- **Minification**: Production builds include minified HTML, CSS, and JavaScript
- **Will-change optimization**: Applied only during active transitions to avoid unnecessary layer creation
#### Core Web Vitals
The site is optimized for Google's Core Web Vitals:
- **LCP (Largest Contentful Paint)**: Optimized with eager loading and preconnect hints
- **FID/INP (First Input Delay / Interaction to Next Paint)**: Reduced with passive event listeners and optimized JavaScript
- **CLS (Cumulative Layout Shift)**: Minimized with explicit image dimensions and stable font loading
---
### Prerequisites
- **Node.js** (recommended: latest LTS)
- **npm** (comes with Node)
- A **GitHub** account (for deployment with GitHub Pages or CI)
---
### Installation
Clone the repository and install dependencies:
```bash
git clone https://github.com/cedric-v/fluance-io.git
cd fluance-io
npm install
```
---
### Local development
Start the Eleventy dev server and Tailwind watcher:
```bash
npm start
```
This will:
- Run Eleventy in dev mode with live reload at `http://localhost:8080/`
- Build Tailwind CSS from `src/assets/css/styles.css` to `_site/assets/css/styles.css` in watch mode
The main pages are:
- Root (redirects to FR): `http://localhost:8080/`
- French homepage: `http://localhost:8080/fr/`
- English homepage: `http://localhost:8080/en/`
Stop the dev server with `Ctrl + C`.
---
### Project structure
- `src/` – source content and templates
- `_includes/` – base layout, header, footer
- `fr/` – French content (e.g. `index.md`, `a-propos/philosophie.md`)
- `en/` – English content (e.g. `index.md`)
- `index.njk` – root index, redirects to `/fr/`
- `sitemap.njk` – sitemap.xml generator template
- `robots.txt` – robots.txt file (copied to root)
- `llms.txt` – LLM-friendly site description (copied to root)
- `assets/css/styles.css` – Tailwind input CSS
- `_site/` – generated static site (ignored by git)
- `sitemap.xml` – automatically generated sitemap
- `robots.txt` – copied from src/
- `llms.txt` – copied from src/
- `eleventy.config.js` – Eleventy configuration (i18n, filters, transforms, shortcodes)
- `tailwind.config.js` – Tailwind configuration
---
### Available npm scripts
From `package.json`:
- **`npm start`**
Runs both dev servers:
```bash
npm-run-all --parallel dev:*
```
- **`npm run dev:11ty`**
Eleventy dev server with live reload:
```bash
cross-env ELEVENTY_ENV=dev eleventy --serve
```
- **`npm run dev:css`**
Tailwind CSS in watch mode:
```bash
npx tailwindcss -i ./src/assets/css/styles.css -o ./_site/assets/css/styles.css --watch
```
- **`npm run build`**
Production build for deployment:
```bash
cross-env ELEVENTY_ENV=prod npm-run-all build:css build:11ty
```
- **`npm run build:11ty`**
```bash
eleventy
```
- **`npm run build:css`**
```bash
npx tailwindcss -i ./src/assets/css/styles.css -o ./_site/assets/css/styles.css --minify
```
---
### Building for production
Generate a production build (minified HTML, CSS, JS):
```bash
npm run build
```
Output:
- Static files are written to the `_site/` directory.
- This folder can be served by any static hosting provider (GitHub Pages, Netlify, S3, etc.).
---
### Deployment
You can deploy the content of `_site/` **as a static website**. The project is configured to use **GitHub Pages** via GitHub Actions.
#### GitHub Pages (via GitHub Actions)
Recommended: automatically build and deploy the site on each push to `main` using GitHub Actions.
1. In your repo, create the directory `.github/workflows/` (if it does not exist).
2. Add a file `.github/workflows/deploy.yml` with this content:
```yaml
name: Deploy site to GitHub Pages
on:
push:
branches: [ main ]
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: "pages"
cancel-in-progress: true
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 'lts/*'
- name: Install dependencies
run: npm ci
- name: Build site
env:
ELEVENTY_ENV: prod
run: npm run build
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: _site
deploy:
needs: build
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
```
3. In GitHub → **Settings → Pages**:
- Set **Source** to “GitHub Actions”.
On each push to `main`, GitHub will:
- Install dependencies
- Run `npm run build`
- Deploy the `_site/` folder to GitHub Pages.
#### Manual or other hosts (Netlify, S3, etc.)
1. Build the site:
```bash
npm run build
```
2. Deploy the contents of `_site/` to your static host (e.g. connect Netlify to the repo with build command `npm run build` and publish directory `_site`, etc.).
---
### Quality assurance and validation
The project includes automated quality checks to ensure the site works correctly:
#### Automated smoke tests
**Smoke tests** run automatically after each build to validate that critical pages are accessible and render correctly. The testing process includes multiple validation stages:
**Stage 1: Build artifact verification**
- ✅ Verify that critical files are present in the build output (`_site/`)
- ✅ Check for required files: `index.html`, `fr/index.html`, `en/index.html`, `CNAME`, `.nojekyll`, `404.html`
- ✅ Verify artifact statistics (HTML file count, total size)
**Stage 2: Artifact download verification**
- ✅ Verify that the downloaded artifact contains all critical files
- ✅ Check file sizes to ensure files were not corrupted during download
- ✅ Validate artifact integrity
**Stage 3: Local smoke tests**
- ✅ Verify that critical pages return HTTP 200 status
- ✅ Check that pages contain valid HTML content (title and body tags)
- ✅ Verify CNAME file content (must be `fluance.io`)
- ✅ Verify `.nojekyll` file presence (disables Jekyll processing)
- ✅ Test custom 404 page handling
- ✅ **Block deployment** if any critical page fails
**Stage 4: Deployment verification**
- ✅ Verify deployment status and page URL generation
- ✅ Confirm successful deployment to GitHub Pages
**Stage 5: Production accessibility tests (post-deploy)**
- ✅ Wait for GitHub Pages propagation (30 seconds)
- ✅ Test critical pages on production URL (`https://fluance.io`)
- ✅ Verify production site accessibility and HTML validity
- ⚠️ Note: Some tests may fail during initial propagation (can take up to 10 minutes)
**Pages tested:**
- Homepage (root, FR, EN)
- Contact page
- Login page (`/connexion-membre/`)
- Online course pages (5 days, 21 days)
- Member area (`/membre/`)
- Custom 404 page (`/404.html`)
- 404 error handling (non-existent page)
**When smoke tests run:**
- Automatically after each build on push to `main`
- Before deployment (deployment is blocked if tests fail)
- After deployment (production accessibility tests)
**Viewing test results:**
1. Go to the **Actions** tab in GitHub
2. Click on the latest workflow run
3. View test results in:
- **"build"** job: Artifact verification
- **"smoke-test"** job: Local smoke tests
- **"deploy"** job: Deployment status
- **"post-deploy"** job: Production accessibility tests
#### Optional validation reports
The project also includes optional quality checks using **Google Lighthouse** and **W3C HTML Validator**. These reports are **not generated automatically** and can be triggered manually when needed (see [GENERER_RAPPORTS_VALIDATION.md](GENERER_RAPPORTS_VALIDATION.md) for instructions).
#### Generating validation reports
Validation reports are **not generated automatically** by default. To generate them:
1. Go to **Actions** tab in GitHub
2. Select **"Deploy site to GitHub Pages"** workflow
3. Click **"Run workflow"**
4. **Check the box** "Exécuter les rapports Lighthouse et W3C"
5. Click **"Run workflow"**
See [GENERER_RAPPORTS_VALIDATION.md](GENERER_RAPPORTS_VALIDATION.md) for detailed instructions.
#### Accessing the reports
After running the workflow with validation enabled, reports are uploaded as GitHub Actions artifacts:
1. Go to your repository on GitHub
2. Click on the **"Actions"** tab
3. Click on the latest workflow run **"Deploy site to GitHub Pages"**
4. Click on the **"validate"** job
5. Scroll down to the **"Artifacts"** section at the bottom of the page
6. Click on **"validation-reports"** to download the ZIP file
7. Extract the ZIP file to access the reports
**Note:** Artifacts are retained for 30 days. After this period, they are automatically deleted.
#### Report contents
The `validation-reports` artifact contains:
**Google Lighthouse reports:**
- `lighthouse-home.html` - Full Lighthouse report for the homepage (HTML format)
- `lighthouse-fr.html` - Full Lighthouse report for the French homepage (HTML format)
- `lighthouse-en.html` - Full Lighthouse report for the English homepage (HTML format, if available)
- `lighthouse-home.json` - Lighthouse data for the homepage (JSON format)
- `lighthouse-fr.json` - Lighthouse data for the French homepage (JSON format)
**W3C HTML Validation reports:**
- `w3c/` directory containing validation reports for up to 10 HTML pages
- Each page has both HTML and JSON format reports
- Files are named based on the page path (e.g., `index.html`, `fr_index.html`, `a-propos_philosophie_index.html`)
**Summary:**
- `summary.md` - Overview of available reports and how to use them
#### Using the reports
**Lighthouse reports:**
- Open the HTML files in your browser for a visual, interactive report
- Lighthouse evaluates:
- **Performance** - Page load speed and optimization
- **Accessibility** - WCAG compliance and screen reader support
- **Best Practices** - Security, modern web standards
- **SEO** - Search engine optimization
- Use the JSON files for programmatic analysis or integration with CI/CD tools
- Aim for scores above 90 in each category for optimal results
**W3C Validation reports:**
- Open the HTML reports to see detailed validation errors and warnings
- The JSON format is useful for automated parsing and error detection
- Fix any errors (marked in red) and review warnings (marked in yellow)
- Valid HTML ensures better browser compatibility and accessibility
#### Troubleshooting
If you don't see the "Artifacts" section:
- Wait a few seconds after the workflow completes (upload may take time)
- Refresh the page
- Check the "Upload validation reports" step logs to verify the upload succeeded
- Ensure the "validate" job completed (it may show warnings but should still generate reports)
If W3C reports are missing:
- Check the workflow logs for the "Validate HTML with W3C" step
- The reports use the local server URLs, so ensure the server started successfully
- Some validation errors won't prevent report generation
---
### Environment variables
This project uses environment variables for:
- **`ELEVENTY_ENV`**
- `dev` for local development (`npm start`)
- `prod` for production builds (`npm run build`)
---
### Maintenance
To keep the project healthy over time:
- **Automatic dependency security monitoring:**
The project uses **GitHub Dependabot** to automatically monitor dependencies for security vulnerabilities and version updates.
- **Security alerts**: Dependabot automatically scans dependencies and creates pull requests for security updates
- **Version updates**: Weekly checks for new versions of dependencies (minor and patch updates)
- **Configuration**: See `.github/dependabot.yml` for monitoring settings
- **Notifications**: You'll receive GitHub notifications and emails for:
- Security vulnerabilities (high priority)
- Available dependency updates (weekly summary)
- **Pull requests**: Dependabot creates PRs automatically with:
- Changelog information
- Labels: `dependencies`, `npm`, `functions`
- Grouped updates for minor/patch versions
**How to use Dependabot PRs:**
1. Review the PR description and changelog
2. Test locally if needed: `git checkout && npm install && npm test`
3. Merge the PR if everything looks good
4. Dependabot will automatically update `package-lock.json` and `package.json`
**Manual dependency checks:**
```bash
npm outdated # see what is out of date
npm update # safe minor/patch updates
```
- **Automated Bexio Token Monitoring:**
The project includes a weekly check for the Bexio API token expiration to prevent service interruptions.
- **Mechanism**: A GitHub Action (`.github/workflows/bexio-token-check.yml`) runs every Monday.
- **Logic**: It decodes the JWT token and exits with an error if it expires within 15 days.
- **Notification**: GitHub automatically sends an email notification if the Action fails.
- **Secret required**: Ensure the `BEXIO_API_TOKEN` is added to **GitHub Repository Secrets**.
- **Rebuild Tailwind and Eleventy after changes:**
- For dev: `npm start`
- For prod: `npm run build`
- **Add new content:**
- French pages under `src/fr/` (Markdown or Nunjucks).
- Shared layouts/partials under `src/_includes/`.
- **Internationalization (i18n):**
- The site supports **French (FR)** and **English (EN)** languages.
- Basic i18n is configured via `eleventy-plugin-i18n` in `eleventy.config.js`.
- French content is located in `src/fr/`, English content in `src/en/`.
- Language switching is handled in the header navigation.
- Each page includes `hreflang` tags for proper SEO and language targeting.
- You can extend the `translations` object and add new languages as needed.
- **Sitemap:**
- A `sitemap.xml` is automatically generated during the build process.
- The sitemap includes all pages (excluding JSON files and 404 pages).
- Pages are prioritized: homepage (1.0), "À propos" pages (0.8), others (0.6).
- Multilingual pages include `hreflang` tags for proper language targeting.
- The sitemap is accessible at `https://fluance.io/sitemap.xml` after deployment.
- You can submit it to Google Search Console for better indexing.
- **Open Graph (OG) Tags:**
- Open Graph meta tags are automatically generated for all pages to optimize social media sharing (Facebook, Twitter, LinkedIn, etc.).
- All OG tags are included in the base template (`src/_includes/base.njk`).
- **Default description**: If a page doesn't have a `description` in its frontmatter, it uses:
- **FR**: "Fluance : le mouvement qui éveille et apaise. Libérez votre corps des tensions grâce à une approche simple basée sur le mouvement, le souffle et le jeu."
- **EN**: "Fluance: the movement that awakens and soothes. Release tension from your body through a simple approach based on movement, breath and play."
- **Custom OG image**: To use a specific image for social media sharing, add `ogImage` to the page frontmatter:
```yaml
---
layout: base.njk
title: My Page
description: My page description
ogImage: assets/img/my-hero-image.jpg
---
```
- **Default OG image**: If `ogImage` is not specified, the default image `assets/img/fond-cedric.jpg` (homepage hero image) is used.
- **OG tags included**:
- `og:type` - Always set to "website"
- `og:url` - Canonical URL of the page
- `og:title` - Page title + "| Fluance"
- `og:description` - Page description (or default)
- `og:image` - Full URL to the OG image (1200x630 recommended)
- `og:image:width` and `og:image:height` - Image dimensions
- `og:locale` - Language locale (fr_FR or en_US)
- `og:locale:alternate` - Alternate language version
- `og:site_name` - "Fluance"
- **Twitter Card tags** are also included for optimal Twitter sharing:
- `twitter:card` - Set to "summary_large_image"
- `twitter:url`, `twitter:title`, `twitter:description`, `twitter:image`
- **Image URL generation**: The `buildOgImageUrl` filter automatically converts relative image paths to full URLs (`https://fluance.io/...`).
- **Testing**: Use Facebook's [Sharing Debugger](https://developers.facebook.com/tools/debug/) or Twitter's [Card Validator](https://cards-dev.twitter.com/validator) to preview how your pages appear when shared.
- **Schema.org JSON-LD:**
- Structured data markup is automatically generated for all pages to improve SEO and enable rich results in search engines.
- The `schemaOrg` shortcode in `eleventy.config.js` generates appropriate schemas based on page type.
- **Schemas included:**
- **Organization** (all pages): Information about Fluance / Instants Zen Sàrl, address, contact, social media
- **WebSite** (all pages): Site information with SearchAction for search functionality
- **Person** (all pages): Information about Cédric Vonlanthen (founder/instructor)
- **Service** (homepage only): Description of wellness services and offers
- **Course** (online course pages): Course information, pricing, descriptions, languages
- **LocalBusiness** (in-person class pages): Information about classes in Fribourg, address, coordinates, pricing
- **Multilingual support**: Schemas automatically adapt to page language (FR/EN).
- **Security**: Email is not included in schemas to prevent spam scraping (phone number is used instead).
- **Validation**: Test your structured data with Google's [Rich Results Test](https://search.google.com/test/rich-results).
- Schemas are included in the `` of every page via `src/_includes/base.njk`.
- **llms.txt:**
- A structured file (`llms.txt`) is available at the root of the site to help Large Language Models (LLMs) better understand and reference the site.
- **Purpose**: Improves how AI assistants (ChatGPT, Claude, Perplexity, etc.) understand and recommend Fluance in their responses.
- **Content**: Includes site description, main sections with links, services, pricing, contact information, and approach characteristics.
- **Location**: The file is located at `src/llms.txt` and is automatically copied to the site root during build.
- **Access**: Available at `https://fluance.io/llms.txt` after deployment.
- **Focus**: Content-oriented information for users, without technical implementation details.
- **Static assets:**
- Add images, icons, etc. under `src/assets/img/`.
- They are copied to `_site/assets/img/` via `eleventyConfig.addPassthroughCopy`.
- **WebP optimization**: For better performance, convert images to WebP format and place them alongside the original files (e.g., `image.jpg` and `image.webp`). The `image` shortcode automatically serves WebP when available, with fallback to the original format.
- **Image shortcode usage**: Use `{% image "assets/img/filename.jpg", "alt text", "classes", "loading", "fetchpriority", "width", "height" %}` in templates. Always provide width and height to prevent layout shifts.
---
### Security and secrets
- **Dependency security**: Automated monitoring via GitHub Dependabot (see [Maintenance](#maintenance) section)
- **Secrets management**: No API keys or secrets are committed to the repository.
- **Frontend Environment variables**: The site uses environment variables for Firebase and Stripe configuration. These are loaded from a local `.env` file during development and from **GitHub Repository Secrets** during deployment.
- **Backend Environment variables**: Firebase Functions use environment variables configured via the Firebase Console (see `CONFIGURATION_VARIABLES_ENV.md`).
- **Git ignore**: The `.gitignore` file correctly excludes `.env` and other sensitive files.
- **Security alerts**: Check the **Security** tab in GitHub for active security advisories.