Compare commits

..

39 Commits

Author SHA1 Message Date
b486c4f3fe cleanup
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 18s
2026-04-03 16:10:25 -04:00
mbcube
bc02da9d48 Update Navigation “main” 2026-04-03 16:06:41 -04:00
7e474a85a2 add gh auth config for decap 2026-04-03 15:49:23 -04:00
8f8fcb83c9 update decap 2026-04-03 15:20:39 -04:00
936000b32a add gh app 2026-04-03 15:17:00 -04:00
5315f1b188 fix decap config 2026-04-03 14:53:55 -04:00
d6d54df384 reset 2026-04-03 14:29:01 -04:00
f1c880690f top level env var 2026-04-03 14:26:58 -04:00
9fee97dea6 update cf content branch 2026-04-03 14:16:56 -04:00
789dc380c1 add log 2026-04-03 14:14:40 -04:00
fe94d4c543 fix apis 2026-04-03 14:09:06 -04:00
f8f59a5134 reomve wrangler 2026-04-03 13:55:17 -04:00
3d1336c3b2 fix some bugs 2026-04-03 13:52:13 -04:00
05eb117e4b audit 2026-04-03 13:30:12 -04:00
84728c9532 cloudflare deployment 2026-04-03 11:19:29 -04:00
5dc33897ce fix stroke
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 46s
2026-03-30 14:09:37 -04:00
067a151be1 1.01 audrey's edits
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 46s
2026-03-28 15:37:45 -04:00
539e537572 v-1.001
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 59s
2026-03-27 12:56:15 -04:00
60c295d731 fix stupid animation
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 47s
2026-03-26 23:43:47 -04:00
0e99cb4cd7 fix env keys
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 47s
2026-03-26 18:53:19 -04:00
212baf8efc add env
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 45s
2026-03-26 18:45:47 -04:00
148d664b44 fix logo for metatags
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 45s
2026-03-26 18:41:12 -04:00
d1ad6e0f09 fix build
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 50s
2026-03-26 18:20:25 -04:00
72f652eabe fix pipeline
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 33s
2026-03-26 18:01:12 -04:00
b23809eb47 fix build
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 45s
2026-03-26 17:58:04 -04:00
cd3cb704be switch up animation
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 27s
2026-03-26 16:43:22 -04:00
b0f2bf142b faster hero 2026-03-26 16:27:05 -04:00
d9dbb43926 fix footer casing
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 2m32s
2026-03-26 13:09:35 -04:00
50ad21bb42 fix pipeline
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 15s
2026-03-26 13:07:26 -04:00
4a64e90a47 1.0
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 11s
2026-03-26 13:04:18 -04:00
70d8d83691 0.95
Some checks failed
Build and Deploy / build-and-deploy (push) Failing after 2m56s
2026-03-25 16:25:19 -04:00
66495f7b17 cleaning up assets
Some checks are pending
Build and Deploy / build-and-deploy (push) Waiting to run
2026-03-25 10:42:18 -04:00
5be7d43446 0.0.9 2026-03-25 10:42:18 -04:00
mbcube
9d21f06d51 Upload “public/images/stylish-bedroom-interior-with-double-bed-and-emera-2023-11-27-05-08-37-utc.webp” 2026-03-25 10:42:18 -04:00
mbcube
e02e6bae43 Upload “public/images/empty-room-blue-wall-with-moulding-and-parquet-fl-2023-11-27-04-52-31-utc.webp” 2026-03-25 10:42:18 -04:00
mbcube
ed565cc5c7 Upload “public/images/logo-text.svg”
Some checks failed
Build and Deploy / build-and-deploy (push) Has been cancelled
2026-03-24 13:17:00 -04:00
mbcube
68f6a8088b Upload “public/images/logo-vignette.svg” 2026-03-24 13:17:00 -04:00
mbcube
485cf758ff Upload “public/images/cachetvignette3.svg” 2026-03-24 13:17:00 -04:00
mbcube
a2b5044326 Delete “public/images/logo.png” 2026-03-24 13:17:00 -04:00
167 changed files with 4030 additions and 6594 deletions

View File

@@ -12,7 +12,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-node@v4 - uses: actions/setup-node@v4
with: with:
node-version: '20' node-version: '24'
cache: 'npm' cache: 'npm'
- run: npm ci && npm run build - run: npm ci && npm run build
@@ -21,4 +21,6 @@ jobs:
docker build -t cachetdeco:latest . docker build -t cachetdeco:latest .
docker stop cachetdeco 2>/dev/null || true docker stop cachetdeco 2>/dev/null || true
docker rm cachetdeco 2>/dev/null || true docker rm cachetdeco 2>/dev/null || true
docker run -d --name cachetdeco -p 30001:80 --restart unless-stopped cachetdeco:latest docker run -d --name cachetdeco -p 30001:4321 --restart unless-stopped \
-e RESEND_API_KEY=${{ secrets.RESEND_API_KEY }} \
cachetdeco:latest

1
.gitignore vendored
View File

@@ -1,6 +1,7 @@
# Build output # Build output
dist/ dist/
.astro/ .astro/
.wrangler/
# Dependencies # Dependencies
node_modules/ node_modules/

View File

@@ -1,3 +1,13 @@
FROM nginx:alpine FROM node:24-alpine AS runtime
COPY dist/ /usr/share/nginx/html/ WORKDIR /app
EXPOSE 80
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
ENV NODE_ENV=production
ENV HOST=0.0.0.0
ENV PORT=4321
EXPOSE 4321
CMD ["node", "./dist/server/entry.mjs"]

View File

@@ -1,6 +1,6 @@
# Cachet Peintres Décorateurs — Site Web # Cachet Peintres Décorateurs — Site Web
Site vitrine statique pour **Cachet Peintres Décorateurs** (9500-5609 Québec Inc). Site vitrine statique pour **Cachet Peintres Décorateurs** (CACHETDECO).
Construit avec **Astro v5 + Tailwind v4 + Decap CMS**, déployé sur **Cloudflare Pages**. Construit avec **Astro v5 + Tailwind v4 + Decap CMS**, déployé sur **Cloudflare Pages**.
## Stack ## Stack
@@ -180,7 +180,6 @@ Aucune refactorisation structurelle n'est nécessaire — l'infrastructure est d
Conformément aux exigences légales québécoises, les informations suivantes doivent apparaître visiblement sur le site : Conformément aux exigences légales québécoises, les informations suivantes doivent apparaître visiblement sur le site :
- **Raison sociale :** 9500-5609 Québec Inc
- **Numéro RBQ :** 5839 8736 01 (obligatoire pour tout service nécessitant une modification d'un bâtiment) - **Numéro RBQ :** 5839 8736 01 (obligatoire pour tout service nécessitant une modification d'un bâtiment)
Ces informations sont affichées dans le footer de chaque page. Ces informations sont affichées dans le footer de chaque page.

View File

@@ -2,9 +2,11 @@ import { defineConfig } from 'astro/config';
import tailwindcss from '@tailwindcss/vite'; import tailwindcss from '@tailwindcss/vite';
import sitemap from '@astrojs/sitemap'; import sitemap from '@astrojs/sitemap';
import react from '@astrojs/react'; import react from '@astrojs/react';
import cloudflare from '@astrojs/cloudflare';
export default defineConfig({ export default defineConfig({
output: 'static', output: 'server',
adapter: cloudflare(),
site: 'https://cachetdeco.com', site: 'https://cachetdeco.com',
i18n: { i18n: {
defaultLocale: 'fr', defaultLocale: 'fr',
@@ -24,5 +26,8 @@ export default defineConfig({
], ],
vite: { vite: {
plugins: [tailwindcss()], plugins: [tailwindcss()],
ssr: {
noExternal: ['motion', 'motion/react'],
},
}, },
}); });

View File

@@ -0,0 +1,76 @@
# Cloudflare Workers + Astro v6 Deployment Notes
## Stack
- Astro v6 + `@astrojs/cloudflare` adapter (v13+)
- Deployed as **Cloudflare Worker** (not Pages)
- Build: `npm run build` → Deploy: `npx wrangler deploy`
---
## Issue 1 — `wrangler.json` with `pages_build_output_dir` breaks deploy
**Error:**
```
The name 'ASSETS' is reserved in Pages projects. Please use a different name for your Assets binding.
```
**Cause:** Having `pages_build_output_dir` in `wrangler.json` makes Wrangler treat the project as a Pages project. The adapter generates `dist/server/wrangler.json` with an `ASSETS` binding for static assets, which is reserved in Pages context.
**Fix:** Remove `pages_build_output_dir` from `wrangler.json`, or delete the file entirely. The adapter generates a complete `dist/server/wrangler.json` — Wrangler picks it up automatically via config redirect.
---
## Issue 2 — `locals.runtime.env` removed in Astro v6
**Error:**
```
Astro.locals.runtime.env has been removed in Astro v6.
Use 'import { env } from "cloudflare:workers"' instead.
```
**Cause:** Astro v6 dropped the `locals.runtime.env` pattern for accessing Cloudflare env vars/bindings.
**Fix:**
```ts
// ❌ Astro v5 (broken in v6)
const runtime = (locals as any).runtime;
const apiKey = runtime?.env?.RESEND_API_KEY;
// ✅ Astro v6
import { env } from 'cloudflare:workers';
const apiKey = (env as unknown as Record<string, string>).RESEND_API_KEY;
```
Install types and add to `tsconfig.json`:
```bash
npm install --save-dev @cloudflare/workers-types
```
```json
// tsconfig.json
{
"compilerOptions": {
"types": ["@cloudflare/workers-types"]
}
}
```
---
## Env vars in Cloudflare Workers dashboard
- Set vars under **Worker → Settings → Variables and Secrets**
- They are accessible via `env` from `cloudflare:workers` at runtime
- Do **not** rely on `process.env` or `import.meta.env` for server-side secrets in Workers
---
## Wrangler config redirect (how it works)
When `astro build` runs, `@astrojs/cloudflare` generates `dist/server/wrangler.json`. Wrangler detects this and logs:
```
Using redirected Wrangler configuration.
- Configuration being used: "dist/server/wrangler.json"
- Original user's configuration: "wrangler.json"
```
The generated config includes the worker `main` entry, `assets` binding, `compatibility_date`, and any adapter-detected bindings (e.g. `IMAGES`, `SESSION`).

View File

@@ -1,175 +0,0 @@
interface SoumissionBody {
nom: string;
courriel: string;
telephone: string;
type_service: string;
adresse?: string;
message: string;
}
interface Env {
RESEND_API_KEY: string;
CONTACT_EMAIL: string;
}
const serviceLabels: Record<string, string> = {
interieur: 'Peinture intérieure',
exterieur: 'Peinture extérieure',
commercial: 'Peinture commerciale',
decoration: 'Décoration intérieure',
autre: 'Autre',
};
function buildEmailHtml(data: SoumissionBody): string {
const serviceLabel = serviceLabels[data.type_service] ?? data.type_service;
const adresseLine = data.adresse
? `<tr><td style="padding:8px 12px;color:#666;font-size:14px;border-bottom:1px solid #eee">Adresse des travaux</td><td style="padding:8px 12px;font-size:14px;border-bottom:1px solid #eee">${data.adresse}</td></tr>`
: '';
return `<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body style="margin:0;padding:0;background:#f5f5f5;font-family:system-ui,sans-serif">
<div style="max-width:600px;margin:0 auto;padding:40px 20px">
<div style="background:#314732;padding:32px;border-radius:8px 8px 0 0;text-align:center">
<h1 style="margin:0;color:#ffffff;font-size:22px;font-weight:600">Nouvelle demande de soumission</h1>
<p style="margin:8px 0 0;color:rgba(255,255,255,0.7);font-size:14px">Cachet Peintres Décorateurs</p>
</div>
<div style="background:#ffffff;border-radius:0 0 8px 8px;overflow:hidden">
<div style="padding:24px;background:#f0f4ef;border-bottom:2px solid #d6e2d4">
<p style="margin:0;font-size:15px;color:#314732;font-weight:600">
Vous avez reçu une nouvelle demande de soumission de la part de <strong>${data.nom}</strong>.
</p>
</div>
<table style="width:100%;border-collapse:collapse">
<tbody>
<tr>
<td style="padding:8px 12px;color:#666;font-size:14px;border-bottom:1px solid #eee;width:40%">Nom</td>
<td style="padding:8px 12px;font-size:14px;border-bottom:1px solid #eee;font-weight:600">${data.nom}</td>
</tr>
<tr>
<td style="padding:8px 12px;color:#666;font-size:14px;border-bottom:1px solid #eee">Courriel</td>
<td style="padding:8px 12px;font-size:14px;border-bottom:1px solid #eee"><a href="mailto:${data.courriel}" style="color:#314732;font-weight:600">${data.courriel}</a></td>
</tr>
<tr>
<td style="padding:8px 12px;color:#666;font-size:14px;border-bottom:1px solid #eee">Téléphone</td>
<td style="padding:8px 12px;font-size:14px;border-bottom:1px solid #eee"><a href="tel:${data.telephone.replace(/\D/g, '')}" style="color:#314732;font-weight:600">${data.telephone}</a></td>
</tr>
<tr>
<td style="padding:8px 12px;color:#666;font-size:14px;border-bottom:1px solid #eee">Type de service</td>
<td style="padding:8px 12px;font-size:14px;border-bottom:1px solid #eee">${serviceLabel}</td>
</tr>
${adresseLine}
</tbody>
</table>
<div style="padding:20px">
<p style="margin:0 0 8px;font-size:13px;font-weight:700;color:#666;text-transform:uppercase;letter-spacing:0.05em">Message</p>
<div style="background:#f9fafb;border:1px solid #e5e7eb;border-radius:6px;padding:16px;font-size:14px;color:#374151;line-height:1.6;white-space:pre-wrap">${data.message}</div>
</div>
<div style="padding:16px 20px 24px">
<a href="mailto:${data.courriel}?subject=Re: Soumission — Cachet Peintres Décorateurs" style="display:inline-block;padding:10px 24px;background:#314732;color:#fff;text-decoration:none;border-radius:4px;font-size:14px;font-weight:700">Répondre à ${data.nom}</a>
</div>
</div>
<p style="margin:24px 0 0;text-align:center;font-size:11px;color:#999">
Cachet Peintres Décorateurs · 9500-5609 Québec Inc · RBQ 5839 8736 01
</p>
</div>
</body>
</html>`;
}
function validateBody(body: unknown): body is SoumissionBody {
if (typeof body !== 'object' || body === null) return false;
const b = body as Record<string, unknown>;
return (
typeof b.nom === 'string' && b.nom.trim().length > 0 &&
typeof b.courriel === 'string' && /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(b.courriel) &&
typeof b.telephone === 'string' && b.telephone.trim().length > 0 &&
typeof b.type_service === 'string' && b.type_service.length > 0 &&
typeof b.message === 'string' && b.message.trim().length > 0
);
}
export const onRequestPost: PagesFunction<Env> = async (context) => {
const corsHeaders = {
'Access-Control-Allow-Origin': 'https://cachetdeco.com',
'Content-Type': 'application/json',
};
// Rate limiting via CF headers (basic check)
const ip = context.request.headers.get('CF-Connecting-IP') ?? 'unknown';
let body: unknown;
try {
body = await context.request.json();
} catch {
return new Response(
JSON.stringify({ success: false, error: 'Corps de requête invalide.' }),
{ status: 400, headers: corsHeaders }
);
}
if (!validateBody(body)) {
return new Response(
JSON.stringify({ success: false, error: 'Données manquantes ou invalides.' }),
{ status: 422, headers: corsHeaders }
);
}
const apiKey = context.env.RESEND_API_KEY;
const contactEmail = context.env.CONTACT_EMAIL;
if (!apiKey || !contactEmail) {
console.error('Missing env vars: RESEND_API_KEY or CONTACT_EMAIL');
return new Response(
JSON.stringify({ success: false, error: 'Configuration serveur manquante.' }),
{ status: 500, headers: corsHeaders }
);
}
const emailPayload = {
from: 'Cachet Peintres Décorateurs <soumission@cachetdeco.com>',
to: [contactEmail],
reply_to: body.courriel,
subject: `Soumission — ${serviceLabels[body.type_service] ?? body.type_service}${body.nom}`,
html: buildEmailHtml(body),
};
const resendRes = await fetch('https://api.resend.com/emails', {
method: 'POST',
headers: {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(emailPayload),
});
if (!resendRes.ok) {
const resendError = await resendRes.text().catch(() => 'Unknown error');
console.error('Resend error:', resendError, 'IP:', ip);
return new Response(
JSON.stringify({ success: false, error: 'Erreur lors de l\'envoi du courriel.' }),
{ status: 502, headers: corsHeaders }
);
}
return new Response(
JSON.stringify({ success: true }),
{ status: 200, headers: corsHeaders }
);
};
// Handle preflight OPTIONS
export const onRequestOptions: PagesFunction = async () => {
return new Response(null, {
status: 204,
headers: {
'Access-Control-Allow-Origin': 'https://cachetdeco.com',
'Access-Control-Allow-Methods': 'POST, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
},
});
};

0
guidline Normal file
View File

2328
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -9,28 +9,33 @@
"astro": "astro" "astro": "astro"
}, },
"dependencies": { "dependencies": {
"@astrojs/react": "^5.0.0", "@astrojs/cloudflare": "^13.1.7",
"@astrojs/sitemap": "^3.2.1", "@astrojs/react": "^5.0.2",
"@astrojs/sitemap": "^3.7.2",
"@fontsource-variable/geist": "^5.2.8", "@fontsource-variable/geist": "^5.2.8",
"@headlessui/react": "^2.2.9", "@headlessui/react": "^2.2.9",
"@heroicons/react": "^2.2.0", "@heroicons/react": "^2.2.0",
"@tailwindcss/vite": "^4.0.0", "@tailwindcss/vite": "^4.0.0",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",
"astro": "^5.4.0", "astro": "^6.1.0",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"embla-carousel-autoplay": "^8.6.0", "embla-carousel-autoplay": "^8.6.0",
"embla-carousel-react": "^8.6.0", "embla-carousel-react": "^8.6.0",
"lucide-react": "^0.577.0", "lucide-react": "^0.577.0",
"motion": "^12.38.0",
"radix-ui": "^1.4.3", "radix-ui": "^1.4.3",
"react": "^19.2.4", "react": "^19.2.4",
"react-dom": "^19.2.4", "react-dom": "^19.2.4",
"react-hook-form": "^7.72.0",
"react-social-media-embed": "^2.5.18",
"shadcn": "^4.0.5", "shadcn": "^4.0.5",
"tailwind-merge": "^3.5.0", "tailwind-merge": "^3.5.0",
"tailwindcss": "^4.2.1", "tailwindcss": "^4.2.1",
"tw-animate-css": "^1.4.0" "tw-animate-css": "^1.4.0"
}, },
"devDependencies": { "devDependencies": {
"@cloudflare/workers-types": "^4.20260403.1",
"@types/react": "^19.2.14" "@types/react": "^19.2.14"
} }
} }

View File

@@ -1,10 +1,9 @@
backend: backend:
name: github name: github
repo: mbcube/cachetdeco # REPLACE with your GitHub org/repo repo: mbcube/cachetdeco
branch: main branch: cloudflare
# For Cloudflare Pages (no Netlify Identity), use PKCE flow: base_url: https://cachetdeco.br-mouad.workers.dev
auth_type: pkce auth_endpoint: /api/auth
app_id: YOUR_GITHUB_OAUTH_APP_CLIENT_ID # REPLACE with your GitHub OAuth App client ID
locale: fr locale: fr
media_folder: "public/images" media_folder: "public/images"
@@ -78,7 +77,7 @@ collections:
i18n: true i18n: true
fields: fields:
- { name: "services", label: "Page Services", widget: "string" } - { name: "services", label: "Page Services", widget: "string" }
- { name: "soumission", label: "Page Soumission", widget: "string" } - { name: "submission", label: "Page Soumission", widget: "string" }
- name: "hero" - name: "hero"
label: "Hero (accueil)" label: "Hero (accueil)"
@@ -172,10 +171,10 @@ collections:
- { name: "button", label: "Bouton", widget: "string" } - { name: "button", label: "Bouton", widget: "string" }
- { name: "breadcrumbHome", label: "Fil d'Ariane — Accueil", widget: "string", i18n: true } - { name: "breadcrumbHome", label: "Fil d'Ariane — Accueil", widget: "string", i18n: true }
- name: "soumission" - name: "submission"
label: "Page Soumission & formulaire" label: "Page Soumission & formulaire"
label_singular: "Soumission" label_singular: "Soumission"
folder: "src/content/soumission" folder: "src/content/submission"
format: json format: json
create: false create: false
delete: false delete: false
@@ -191,29 +190,33 @@ collections:
i18n: true i18n: true
fields: fields:
- { name: "ariaLabel", label: "Aria-label formulaire", widget: "string" } - { name: "ariaLabel", label: "Aria-label formulaire", widget: "string" }
- { name: "nom", label: "Libellé nom", widget: "string" } - { name: "fullNameLabel", label: "Libellé nom complet", widget: "string" }
- { name: "nomPlaceholder", label: "Placeholder nom", widget: "string" } - { name: "fullNamePlaceholder", label: "Placeholder nom", widget: "string" }
- { name: "courriel", label: "Libellé courriel", widget: "string" } - { name: "emailLabel", label: "Libellé courriel", widget: "string" }
- { name: "courrielPlaceholder", label: "Placeholder courriel", widget: "string" } - { name: "emailPlaceholder", label: "Placeholder courriel", widget: "string" }
- { name: "telephone", label: "Libellé téléphone", widget: "string" } - { name: "phoneLabel", label: "Libellé téléphone", widget: "string" }
- { name: "telephonePlaceholder", label: "Placeholder téléphone", widget: "string" } - { name: "phonePlaceholder", label: "Placeholder téléphone", widget: "string" }
- { name: "adresse", label: "Libellé adresse travaux", widget: "string" } - { name: "workAddressLabel", label: "Libellé adresse travaux", widget: "string" }
- { name: "adressePlaceholder", label: "Placeholder adresse", widget: "string" } - { name: "workAddressPlaceholder", label: "Placeholder adresse", widget: "string" }
- { name: "typeService", label: "Libellé type de service", widget: "string" } - { name: "serviceTypeLabel", label: "Libellé type de service", widget: "string" }
- { name: "typeServicePlaceholder", label: "Placeholder sélection", widget: "string" } - { name: "serviceTypePlaceholder", label: "Placeholder sélection", widget: "string" }
- name: "typeServiceOptions" - name: "serviceTypeOptions"
label: "Options type de service" label: "Options type de service"
widget: "object" widget: "object"
fields: fields:
- { name: "interieur", label: "Intérieur", widget: "string" } - { name: "interior", label: "Intérieur", widget: "string" }
- { name: "exterieur", label: "Extérieur", widget: "string" } - { name: "exterior", label: "Extérieur", widget: "string" }
- { name: "commercial", label: "Commercial", widget: "string" } - { name: "commercial", label: "Commercial", widget: "string" }
- { name: "decoration", label: "Décoration", widget: "string" } - { name: "decoration", label: "Décoration", widget: "string" }
- { name: "autre", label: "Autre", widget: "string" } - { name: "other", label: "Autre", widget: "string" }
- { name: "message", label: "Libellé message", widget: "string" } - { name: "messageLabel", label: "Libellé message", widget: "string" }
- { name: "messagePlaceholder", label: "Placeholder message", widget: "text" } - { name: "messagePlaceholder", label: "Placeholder message", widget: "text" }
- { name: "envoyer", label: "Bouton envoyer", widget: "string" } - { name: "attachmentsLabel", label: "Libellé pièces jointes", widget: "string" }
- { name: "sending", label: "État envoi", widget: "string" } - { name: "attachmentsHint", label: "Aide zone dépôt", widget: "string" }
- { name: "attachmentsAccepted", label: "Formats acceptés", widget: "string" }
- { name: "attachmentsRemove", label: "Retirer fichier (aria)", widget: "string" }
- { name: "submitLabel", label: "Bouton envoyer", widget: "string" }
- { name: "submittingLabel", label: "État envoi", widget: "string" }
- { name: "successTitle", label: "Succès — titre", widget: "string" } - { name: "successTitle", label: "Succès — titre", widget: "string" }
- { name: "successMessage", label: "Succès — message", widget: "text" } - { name: "successMessage", label: "Succès — message", widget: "text" }
- { name: "errorTitle", label: "Erreur — titre", widget: "string" } - { name: "errorTitle", label: "Erreur — titre", widget: "string" }
@@ -222,11 +225,13 @@ collections:
label: "Messages validation" label: "Messages validation"
widget: "object" widget: "object"
fields: fields:
- { name: "nom", label: "Nom", widget: "string" } - { name: "fullName", label: "Nom", widget: "string" }
- { name: "courriel", label: "Courriel", widget: "string" } - { name: "email", label: "Courriel", widget: "string" }
- { name: "telephone", label: "Téléphone", widget: "string" } - { name: "phone", label: "Téléphone", widget: "string" }
- { name: "typeService", label: "Type service", widget: "string" } - { name: "serviceType", label: "Type service", widget: "string" }
- { name: "message", label: "Message", widget: "string" } - { name: "message", label: "Message", widget: "string" }
- { name: "attachmentsType", label: "Type fichier", widget: "string" }
- { name: "attachmentsSize", label: "Taille fichiers", widget: "string" }
- name: "sidebar" - name: "sidebar"
label: "Barre latérale" label: "Barre latérale"
widget: "object" widget: "object"
@@ -258,6 +263,7 @@ collections:
- { name: "navTitle", label: "Titre colonne navigation", widget: "string", i18n: true } - { name: "navTitle", label: "Titre colonne navigation", widget: "string", i18n: true }
- { name: "servicesTitle", label: "Titre colonne services", widget: "string", i18n: true } - { name: "servicesTitle", label: "Titre colonne services", widget: "string", i18n: true }
- { name: "contactTitle", label: "Titre colonne contact", widget: "string", i18n: true } - { name: "contactTitle", label: "Titre colonne contact", widget: "string", i18n: true }
- { name: "serviceAreasTitle", label: "Titre colonne zones de service", widget: "string", i18n: true }
- { name: "legal", label: "Mention légale (utiliser {year})", widget: "string", i18n: true } - { name: "legal", label: "Mention légale (utiliser {year})", widget: "string", i18n: true }
- { name: "rbq", label: "Ligne RBQ", widget: "string", i18n: true } - { name: "rbq", label: "Ligne RBQ", widget: "string", i18n: true }
- { name: "neq", label: "Ligne NEQ", widget: "string", i18n: true } - { name: "neq", label: "Ligne NEQ", widget: "string", i18n: true }
@@ -269,6 +275,11 @@ collections:
fields: fields:
- { name: "label", label: "Libellé", widget: "string" } - { name: "label", label: "Libellé", widget: "string" }
- { name: "href", label: "URL", widget: "string" } - { name: "href", label: "URL", widget: "string" }
- name: "serviceAreas"
label: "Zones de service"
widget: "list"
i18n: true
field: { name: "item", label: "Ville / Secteur", widget: "string" }
- name: "not_found" - name: "not_found"
label: "Page 404" label: "Page 404"
@@ -316,6 +327,26 @@ collections:
- { name: "title", label: "Titre", widget: "string" } - { name: "title", label: "Titre", widget: "string" }
- { name: "description", label: "Description", widget: "text" } - { name: "description", label: "Description", widget: "text" }
- name: "testimonials"
label: "Témoignages"
label_singular: "Témoignage"
folder: "src/content/testimonials"
format: json
create: false
delete: false
i18n: true
slug: "{{slug}}"
fields:
- { name: "sectionLabel", label: "Libellé de section", widget: "string", i18n: true }
- { name: "title", label: "Titre de section", widget: "string", i18n: true }
- name: "items"
label: "Témoignages"
widget: "list"
i18n: true
fields:
- { name: "key", label: "Identifiant unique", widget: "string" }
- { name: "src", label: "URL du post Facebook (embed)", widget: "string" }
- name: "settings" - name: "settings"
label: "Paramètres du site" label: "Paramètres du site"
files: files:
@@ -329,10 +360,15 @@ collections:
- { name: "taglineHero", label: "Slogan hero", widget: "string" } - { name: "taglineHero", label: "Slogan hero", widget: "string" }
- { name: "phone", label: "Téléphone", widget: "string" } - { name: "phone", label: "Téléphone", widget: "string" }
- { name: "email", label: "Courriel", widget: "string" } - { name: "email", label: "Courriel", widget: "string" }
- { name: "emailFromContact", label: "Expéditeur courriel (formulaire contact, ex. Nom <adresse@domaine>)", widget: "string" }
- { name: "emailToContact", label: "Destinataire courriel (formulaire contact)", widget: "string" }
- { name: "fromAddressSubmission", label: "Expéditeur courriel (formulaire soumission, ex. Nom <adresse@domaine>)", widget: "string" }
- { name: "toAddressSubmission", label: "Destinataire courriel (formulaire soumission)", widget: "string" }
- { name: "address", label: "Adresse", widget: "string" } - { name: "address", label: "Adresse", widget: "string" }
- { name: "serviceArea", label: "Zone de service", widget: "string" } - { name: "serviceArea", label: "Zone de service", widget: "string" }
- { name: "facebook", label: "Lien Facebook", widget: "string" } - { name: "facebook", label: "Lien Facebook", widget: "string" }
- { name: "instagram", label: "Lien Instagram", widget: "string", required: false } - { name: "instagram", label: "Lien Instagram", widget: "string", required: false }
- { name: "linkedin", label: "Lien LinkedIn (vide = masqué)", widget: "string", required: false }
- { name: "rbq", label: "Numéro RBQ", widget: "string" } - { name: "rbq", label: "Numéro RBQ", widget: "string" }
- { name: "neq", label: "Numéro NEQ (Registraire)", widget: "string" } - { name: "neq", label: "Numéro NEQ (Registraire)", widget: "string" }

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by Pixelmator Pro 3.6.18 -->
<svg width="600" height="700" viewBox="0 0 600 700" xmlns="http://www.w3.org/2000/svg">
<path id="Path" fill="#74826e" stroke="none" d="M 212.013763 570.637939 L 209.280426 570.637939 C 201.072083 569.871216 194.230408 562.108765 194.230408 552.042114 L 194.230408 46.725403 C 194.230408 36.654541 201.759583 28.125427 210.647095 28.125427 L 212.705414 28.125427 L 300.24292 28.125427 C 432.24707 28.125427 539.630432 150.57959 539.630432 300.154602 C 539.630432 449.746246 432.24707 570.637939 300.24292 570.637939 Z"/>
<path id="path1" fill="#2e4030" stroke="none" d="M 299.743774 671.875 C 167.756256 671.875 60.368744 550.958374 60.368744 401.383331 C 60.368744 251.804138 167.756256 129.345825 299.743774 129.345825 L 387.289612 129.345825 L 389.34375 129.345825 C 398.231262 129.345825 405.760437 137.87085 405.760437 147.94165 L 405.760437 653.262512 C 405.760437 663.337524 398.922913 671.087524 390.7146 671.875 L 387.981262 671.875 Z"/>
<path id="path2" fill="none" stroke="#74826e" stroke-width="12.5" d="M 212.013763 570.637939 L 209.280426 570.637939 C 201.072083 569.871216 194.230408 562.108765 194.230408 552.042114 L 194.230408 46.729614 C 194.230408 36.654541 201.759583 28.129578 210.647095 28.129578 L 212.705414 28.129578 L 300.24707 28.129578 C 432.24707 28.129578 539.630432 150.57959 539.630432 300.154602 C 539.630432 449.746246 432.24707 570.637939 300.24707 570.637939 L 212.013763 570.637939 Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

Before

Width:  |  Height:  |  Size: 525 KiB

After

Width:  |  Height:  |  Size: 525 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 127 KiB

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by Pixelmator Pro 3.6.18 -->
<svg width="1390" height="500" viewBox="0 0 1390 500" xmlns="http://www.w3.org/2000/svg">
<text id="CACHET" xml:space="preserve" x="3" y="312" font-family="Cocogoose Classic Trial" font-size="350" font-weight="600" fill="#2d4030">CACHET</text>
<path id="Rectangle" fill="#b0b0ac" fill-rule="evenodd" stroke="none" d="M 228 360 L 1161 360 L 1161 334 L 228 334 Z"/>
<text id="PEINTRES-DECORATEURS" xml:space="preserve" x="228" y="435" font-family="Geoform" font-size="72" font-weight="700" fill="#3d3e3b">PEINTRES DECORATEURS</text>
</svg>

After

Width:  |  Height:  |  Size: 633 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

View File

@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by Pixelmator Pro 3.6.18 -->
<svg width="600" height="700" viewBox="0 0 600 700" xmlns="http://www.w3.org/2000/svg">
<path id="Path" fill="#74826e" stroke="none" d="M 212.013763 570.637939 L 209.280426 570.637939 C 201.072083 569.871216 194.230408 562.108765 194.230408 552.042114 L 194.230408 46.725403 C 194.230408 36.654541 201.759583 28.125427 210.647095 28.125427 L 212.705414 28.125427 L 300.24292 28.125427 C 432.24707 28.125427 539.630432 150.57959 539.630432 300.154602 C 539.630432 449.746246 432.24707 570.637939 300.24292 570.637939 Z"/>
<path id="path1" fill="#2e4030" stroke="none" d="M 299.743774 671.875 C 167.756256 671.875 60.368744 550.958374 60.368744 401.383331 C 60.368744 251.804138 167.756256 129.345825 299.743774 129.345825 L 387.289612 129.345825 L 389.34375 129.345825 C 398.231262 129.345825 405.760437 137.87085 405.760437 147.94165 L 405.760437 653.262512 C 405.760437 663.337524 398.922913 671.087524 390.7146 671.875 L 387.981262 671.875 Z"/>
<path id="path2" fill="none" stroke="#74826e" stroke-width="12.5" d="M 212.013763 570.637939 L 209.280426 570.637939 C 201.072083 569.871216 194.230408 562.108765 194.230408 552.042114 L 194.230408 46.729614 C 194.230408 36.654541 201.759583 28.129578 210.647095 28.129578 L 212.705414 28.129578 L 300.24707 28.129578 C 432.24707 28.129578 539.630432 150.57959 539.630432 300.154602 C 539.630432 449.746246 432.24707 570.637939 300.24707 570.637939 L 212.013763 570.637939 Z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 MiB

View File

Before

Width:  |  Height:  |  Size: 198 KiB

After

Width:  |  Height:  |  Size: 198 KiB

View File

Before

Width:  |  Height:  |  Size: 227 KiB

After

Width:  |  Height:  |  Size: 227 KiB

View File

Before

Width:  |  Height:  |  Size: 223 KiB

After

Width:  |  Height:  |  Size: 223 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 138 KiB

View File

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

View File

Before

Width:  |  Height:  |  Size: 65 KiB

After

Width:  |  Height:  |  Size: 65 KiB

View File

Before

Width:  |  Height:  |  Size: 83 KiB

After

Width:  |  Height:  |  Size: 83 KiB

View File

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 149 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 459 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 339 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 427 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 204 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 202 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 298 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 226 KiB

Some files were not shown because too many files have changed in this diff Show More