Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
7403cac
fix(landing): use NuxtImg for reference logos to respect base URL
wazolab Mar 26, 2026
3264278
feat(ci): add Lighthouse audit to CI pipeline
wazolab Mar 26, 2026
3b4c3d6
fix(i18n): use global scope in app.vue to suppress intlify warning
wazolab Mar 26, 2026
e4f00e7
fix(ci): address Lighthouse CI review feedback
wazolab Mar 26, 2026
b1eab4e
docs: add mobile-first convention to project guidelines
wazolab Mar 26, 2026
c72beb5
feat(ci): auto-create GitHub issue on Lighthouse regression
wazolab Mar 26, 2026
d013175
feat(ci): attach Lighthouse report as PR comment
wazolab Mar 27, 2026
fae72b0
fix(ci): replace invalid githubToken with manual PR comment step
wazolab Mar 27, 2026
725a170
fix(ci): use manifest summary for Lighthouse PR comment scores
wazolab Mar 27, 2026
cb8e899
Merge pull request #83 from teritorio/feat/lighthouse-ci
wazolab Mar 30, 2026
75a70a9
docs(i18n): rename nav label from 'Documentation' to 'How it works?'
wazolab Mar 30, 2026
fc86fb3
Merge pull request #99 from teritorio/feat/rename-nav-label
wazolab Mar 30, 2026
b18dc86
docs: restructure page hierarchy for 'how-it-works' section
wazolab Mar 30, 2026
e2e03c7
Merge pull request #100 from teritorio/feat/restructure-docs
wazolab Mar 30, 2026
59f8336
docs(fr): write FR content for 'how-it-works' section
wazolab Mar 30, 2026
05bf75c
Merge pull request #101 from teritorio/feat/fr-content
wazolab Mar 30, 2026
6fc0dca
docs(en): translate 'how-it-works' section to English
wazolab Mar 30, 2026
6cef347
Merge pull request #102 from teritorio/feat/en-content
wazolab Mar 30, 2026
2f2eff4
docs(es): translate 'how-it-works' section to Spanish
wazolab Mar 30, 2026
c309b16
Merge pull request #103 from teritorio/feat/es-content
wazolab Mar 30, 2026
2445f56
docs: update cross-links in 'going-further' section
wazolab Mar 30, 2026
15e053f
Merge pull request #104 from teritorio/feat/fix-crosslinks
wazolab Mar 30, 2026
090d3fa
fix(i18n): use global scope in all useI18n() calls
wazolab Mar 30, 2026
0950072
revert: remove useScope global workaround for intlify warning
wazolab Mar 30, 2026
3f22389
feat(docs): replace See Also sections with prev/next navigation
wazolab Mar 30, 2026
d6b434e
fix(docs): filter redirect pages from prev/next navigation
wazolab Mar 31, 2026
21a642c
Merge pull request #106 from teritorio/feat/prev-next-navigation
wazolab Mar 31, 2026
8ac94d5
fix(docs): exclude non-docs pages from prev/next navigation
wazolab Mar 31, 2026
bf14ae4
chore: update reference logos with new versions
wazolab Mar 31, 2026
62cf7fb
feat: add custom 404 error page
wazolab Mar 31, 2026
be65063
fix: throw 404 error for missing pages instead of inline fallback
wazolab Mar 31, 2026
9320254
fix: add mobile navigation drawer to header (#108)
wazolab Mar 31, 2026
66361d9
fix(ci): remove stale slug tests and fix Lighthouse URL (#110)
wazolab Mar 31, 2026
9abd7cb
feat: remove going-further docs section (#112)
wazolab Apr 1, 2026
1edb277
feat: add CTA button in header nav linking to Clearance app (#115)
wazolab Apr 1, 2026
41cf3a2
fix(content): convert validators to bullet list on control rules page…
wazolab Apr 1, 2026
25e06a7
fix(content): replace "maîtrise" with "confiance" in references section
wazolab Apr 1, 2026
6dfd600
fix(content): add "touristique" to destination management organizatio…
wazolab Apr 1, 2026
e4c1378
fix(ui): responsive mobile fixes for footer, steps, cards, contact fo…
wazolab Apr 1, 2026
1d03f37
feat(ui): add mobile sidebar navigation for docs layout (#126)
wazolab Apr 1, 2026
e311893
fix(ui): add mobile fallback for SVG schema diagram (#127)
wazolab Apr 1, 2026
37ea68c
fix(ui): use Clearance logo in docs mobile nav and fix a11y warnings
wazolab Apr 1, 2026
e275dc6
fix(ui): make docs surround nav more compact on mobile and revert sub…
wazolab Apr 1, 2026
1001d13
fix(ui): right-align contact form submit button
wazolab Apr 1, 2026
74ec352
fix(ci): deduplicate CI runs with concurrency group
wazolab Apr 1, 2026
269abbd
fix(ci): use commit SHA for concurrency group
wazolab Apr 1, 2026
9610a2e
fix(ci): use PR head SHA for concurrency group
wazolab Apr 1, 2026
ae6f869
fix(ci): remove push trigger to prevent duplicate runs
wazolab Apr 1, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 93 additions & 2 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ name: CI
on:
pull_request:
branches: [develop, main]
push:
branches: [develop]

jobs:
ci:
Expand All @@ -30,3 +28,96 @@ jobs:

- name: Test
run: pnpm test:run

lighthouse:
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- uses: actions/checkout@v6

- uses: pnpm/action-setup@v5

- uses: actions/setup-node@v6
with:
node-version: 22
cache: pnpm

- name: Install dependencies
run: pnpm install --frozen-lockfile

# No NUXT_APP_BASE_URL here — Lighthouse audits the site at root,
# unlike deploy.yml which prefixes /clearance-website/ for GitHub Pages.
- name: Generate static site
run: pnpm generate

- name: Lighthouse CI
id: lhci
uses: treosh/lighthouse-ci-action@v12
if: always()
with:
configPath: ./lighthouserc.cjs

- name: Comment Lighthouse results on PR
if: always() && github.event_name == 'pull_request' && steps.lhci.outputs.resultsPath != ''
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RESULTS_PATH: ${{ steps.lhci.outputs.resultsPath }}
LINKS: ${{ steps.lhci.outputs.links }}
run: |
MANIFEST="$RESULTS_PATH/manifest.json"
if [ ! -f "$MANIFEST" ]; then exit 0; fi

COMMENT=$(jq -r '
"## Lighthouse Report\n\n| URL | Performance | Accessibility | Best Practices | SEO |\n|-----|:-----------:|:------------:|:--------------:|:---:|",
(
[ .[] | select(.isRepresentativeRun == true) ] |
.[] |
"| `\(.url | split("//")[1] | split("/")[1:] | "/" + join("/"))` | \((.summary.performance // 0) * 100 | round) | \((.summary.accessibility // 0) * 100 | round) | \((.summary["best-practices"] // 0) * 100 | round) | \((.summary.seo // 0) * 100 | round) |"
)
' "$MANIFEST")

if [ -n "$LINKS" ]; then
COMMENT+=$'\n\n'"**Report links:** ${LINKS}"
fi

echo "$COMMENT" | gh pr comment "${{ github.event.pull_request.number }}" --body-file -

- name: Create issue on Lighthouse regression
if: always() && steps.lhci.outcome == 'failure' && steps.lhci.outputs.resultsPath != ''
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RESULTS_PATH: ${{ steps.lhci.outputs.resultsPath }}
LINKS: ${{ steps.lhci.outputs.links }}
run: |
if [ ! -f "$RESULTS_PATH/assertion-results.json" ]; then
echo "No assertion results found — LHCI likely crashed during collection."
exit 0
fi

REPORT=$(jq -r '
.[] | select(.level == "error" or .level == "warn") |
"- **\(.level)**: \(.auditId // .name) — score \(.actual) (expected ≥ \(.expected))"
' "$RESULTS_PATH/assertion-results.json")

gh issue create \
--title "Lighthouse regression detected on $(date +%Y-%m-%d)" \
--label "lighthouse" \
--assignee wazolab \
--body "$(cat <<EOF
## Lighthouse CI failed

**Run:** ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
**Commit:** \`${{ github.sha }}\`
**Branch:** \`${{ github.ref_name }}\`

### Failures

${REPORT}

### Report links

${LINKS}
EOF
)"
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ Clearance Website — marketing/presentational site for Clearance, an open-sourc
- ESLint: `@antfu/eslint-config`
- Commits: conventional commits enforced by commitlint
- Git hooks: simple-git-hooks + lint-staged
- **Mobile-first**: Design and implement for mobile screens first, then enhance for larger breakpoints

## Tests

- **Keep tests in sync with the codebase.** Every time an issue is resolved, verify that existing tests still match the code and update or remove tests that no longer apply. Add new tests for new functionality.

## Git Commits

Expand Down
2 changes: 1 addition & 1 deletion components/AppFooter.vue
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ const footerColumns = computed(() => [
<UFooter :ui="{ top: 'border-b border-t border-default' }">
<template #top>
<UContainer>
<UFooterColumns :columns="footerColumns" :ui="{ root: 'block!', left: 'hidden!', center: 'grid! grid-cols-3! gap-8' }" />
<UFooterColumns :columns="footerColumns" :ui="{ root: 'block!', left: 'hidden!', center: 'grid! grid-cols-1! sm:grid-cols-3! gap-8' }" />
</UContainer>
</template>
<template #left>
Expand Down
46 changes: 27 additions & 19 deletions components/AppHeader.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
<script setup lang="ts">
const { t, locale, locales } = useI18n()
const switchLocalePath = useSwitchLocalePath()
const APP_URL = 'https://clearance.teritorio.xyz'

const { t } = useI18n()
const localePath = useLocalePath()
const drawerOpen = ref(false)

const navItems = computed(() => [
{
Expand All @@ -21,33 +23,39 @@ const navItems = computed(() => [
target: '_blank',
},
])

const localeItems = computed(() =>
(locales.value as Array<{ code: string, name: string }>).map(l => ({
label: l.name,
to: switchLocalePath(l.code as typeof locale.value),
})),
)
</script>

<template>
<UHeader :to="localePath('/')">
<UHeader v-model:open="drawerOpen" :to="localePath('/')" mode="drawer">
<template #title>
<div class="flex items-center gap-2">
<NuxtImg src="/logo.svg" alt="Clearance" width="28" height="28" />
<span>{{ t('nav.home') }}</span>
</div>
</template>
<template #right>
<UNavigationMenu :items="navItems" />
<UDropdownMenu :items="localeItems">
<UButton
variant="ghost"
icon="i-lucide-languages"
:label="locale.toUpperCase()"
:aria-label="t('nav.changeLanguage')"
/>
</UDropdownMenu>
<UNavigationMenu class="hidden md:flex" :items="navItems" />
<UButton
:label="t('nav.openApp')"
:to="APP_URL"
target="_blank"
rel="noopener"
icon="i-lucide-external-link"
class="hidden md:flex"
/>
<AppLanguageSwitcher />
</template>
<template #body>
<UNavigationMenu orientation="vertical" :items="navItems" />
<UButton
:label="t('nav.openApp')"
:to="APP_URL"
target="_blank"
rel="noopener"
icon="i-lucide-external-link"
class="mt-4 w-full justify-center"
@click="drawerOpen = false"
/>
</template>
</UHeader>
</template>
22 changes: 22 additions & 0 deletions components/AppLanguageSwitcher.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<script setup lang="ts">
const { t, locale, locales } = useI18n()
const switchLocalePath = useSwitchLocalePath()

const localeItems = computed(() =>
(locales.value as Array<{ code: string, name: string }>).map(l => ({
label: l.name,
to: switchLocalePath(l.code as typeof locale.value),
})),
)
</script>

<template>
<UDropdownMenu :items="localeItems">
<UButton
variant="ghost"
icon="i-lucide-languages"
:label="locale.toUpperCase()"
:aria-label="t('nav.changeLanguage')"
/>
</UDropdownMenu>
</template>
2 changes: 1 addition & 1 deletion components/content/LandingFeature.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defineProps<{
</script>

<template>
<div class="rounded-xl border border-zinc-200 bg-zinc-50 p-6">
<div class="rounded-xl border border-zinc-200 bg-zinc-50 p-4 sm:p-6">
<div v-if="icon" class="mb-4 flex size-10 items-center justify-center rounded-lg bg-primary/10">
<UIcon :name="icon" class="size-5 text-primary" />
</div>
Expand Down
2 changes: 1 addition & 1 deletion components/content/LandingProblemCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ defineProps<{
</script>

<template>
<div class="landing-problem-card rounded-xl border-2 border-primary/30 bg-zinc-50 p-6 text-center">
<div class="landing-problem-card rounded-xl border-2 border-primary/30 bg-zinc-50 p-4 sm:p-6 text-center">
<div v-if="icon" class="mb-4 mx-auto flex size-10 items-center justify-center rounded-lg bg-primary/10">
<UIcon :name="icon" class="size-5 text-primary" />
</div>
Expand Down
4 changes: 2 additions & 2 deletions components/content/LandingReference.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ defineProps<{
</script>

<template>
<div class="flex flex-col rounded-xl border border-zinc-200 bg-white p-6">
<div class="flex flex-col rounded-xl border border-zinc-200 bg-white p-4 sm:p-6">
<div class="mb-3 flex items-center gap-3">
<img v-if="logo" :src="logo" :alt="title" class="h-16 w-28 shrink-0 object-contain">
<NuxtImg v-if="logo" :src="logo" :alt="title" class="h-12 w-20 sm:h-16 sm:w-28 shrink-0 object-contain" />
<h3 class="text-base font-semibold">
{{ title }}
</h3>
Expand Down
38 changes: 37 additions & 1 deletion components/content/LandingSchema.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,45 @@ defineProps<{

<template>
<div class="mx-auto max-w-3xl">
<!-- Mobile: simplified vertical flow -->
<div class="flex flex-col items-center gap-3 sm:hidden" role="img" :aria-label="`${changesLabel} → ${osmLabel} → ${clearanceLabel} → ${extractLabel}`">
<div class="flex w-full max-w-xs items-center gap-3 rounded-xl border border-zinc-200 bg-zinc-50 px-4 py-3">
<div class="flex size-10 shrink-0 items-center justify-center rounded-full border-2 border-zinc-300 bg-white">
<svg viewBox="0 0 30 14" class="h-3.5 w-[30px]" aria-hidden="true"><path d="M 0,7 Q 5,0 10,7 Q 15,14 20,7 Q 25,0 30,7" fill="none" stroke="#3f3f46" stroke-width="2.2" stroke-linecap="round" /></svg>
</div>
<span class="text-sm text-muted">{{ changesLabel }}</span>
</div>
<UIcon name="i-lucide-chevron-down" class="size-5 text-primary" />
<div class="flex w-full max-w-xs items-center gap-3 rounded-xl border border-zinc-200 bg-zinc-50 px-4 py-3">
<div class="flex size-10 shrink-0 items-center justify-center rounded-full border-2 border-zinc-300 bg-white">
<NuxtImg src="/logos/openstreetmap.png" alt="OpenStreetMap" class="size-6 object-contain" />
</div>
<span class="text-sm text-muted">{{ osmLabel }}</span>
</div>
<UIcon name="i-lucide-chevron-down" class="size-5 text-primary" />
<div class="flex w-full max-w-xs items-center gap-3 rounded-xl border-2 border-primary/30 bg-primary/5 px-4 py-3">
<div class="flex size-10 shrink-0 items-center justify-center rounded-full border-2 border-primary bg-white">
<svg viewBox="0 0 24 24" class="size-6" aria-hidden="true"><circle cx="10" cy="10" r="8" fill="#ffbb00" stroke="#000" stroke-width="0.8" /><circle cx="15" cy="15" r="6.5" fill="#f00" stroke="#000" stroke-width="0.8" /></svg>
</div>
<span class="text-sm font-medium">{{ clearanceLabel }}</span>
</div>
<UIcon name="i-lucide-chevron-down" class="size-5 text-primary" />
<div class="flex w-full max-w-xs items-center gap-3 rounded-xl border border-zinc-200 bg-zinc-50 px-4 py-3">
<div class="flex size-10 shrink-0 items-center justify-center rounded-full border-2 border-zinc-300 bg-white">
<UIcon name="i-lucide-database" class="size-5 text-zinc-700" />
</div>
<span class="text-sm text-muted">{{ extractLabel }}</span>
</div>
<div class="mt-1 flex items-center gap-1 text-xs text-muted italic">
<UIcon name="i-lucide-rotate-ccw" class="size-3.5" />
<span>{{ feedbackLabel }}</span>
</div>
</div>

<!-- Desktop: full SVG diagram -->
<svg
viewBox="0 -15 560 170"
class="block w-full"
class="hidden w-full sm:block"
role="img"
:aria-label="`${changesLabel} → ${osmLabel} → ${clearanceLabel} → ${extractLabel}`"
>
Expand Down
6 changes: 3 additions & 3 deletions components/content/LandingStep.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ defineProps<{
</div>

<!-- Card -->
<div class="flex h-full flex-col items-center rounded-xl border border-zinc-200 bg-white px-6 pb-6 pt-8 text-center shadow-sm">
<div class="flex h-full flex-col items-center rounded-xl border border-zinc-200 bg-white px-4 pb-4 sm:px-6 sm:pb-6 pt-8 text-center shadow-sm">
<h3 class="text-lg font-semibold">
{{ title }}
</h3>
Expand All @@ -36,7 +36,7 @@ defineProps<{

<style scoped>
/* Horizontal chevron arrow between steps (desktop) */
@media (min-width: 640px) {
@media (min-width: 768px) {
.landing-step:not(:last-child)::after {
content: '';
position: absolute;
Expand All @@ -51,7 +51,7 @@ defineProps<{
}

/* Vertical chevron arrow between steps (mobile) */
@media (max-width: 639px) {
@media (max-width: 767px) {
.landing-step:not(:last-child)::after {
content: '';
position: absolute;
Expand Down
2 changes: 1 addition & 1 deletion components/content/LandingSteps.vue
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ defineProps<{
<section class="py-16 sm:py-24 bg-zinc-50">
<UContainer>
<LandingSectionHeader :headline="headline" :title="title" :description="description" />
<div class="mt-12 grid gap-y-10 pt-6 sm:grid-cols-3 sm:gap-x-12">
<div class="mt-12 grid gap-y-14 pt-6 md:grid-cols-3 md:gap-x-12">
<MDCSlot :use="$slots.default" />
</div>
</UContainer>
Expand Down
2 changes: 1 addition & 1 deletion components/content/LandingUseCase.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defineProps<{
</script>

<template>
<div class="rounded-xl border border-zinc-200 bg-zinc-50 p-6">
<div class="rounded-xl border border-zinc-200 bg-zinc-50 p-4 sm:p-6">
<div class="mb-4 flex items-center gap-3">
<div v-if="icon" class="flex size-12 shrink-0 items-center justify-center rounded-lg bg-primary/10">
<UIcon :name="icon" class="size-6 text-primary" />
Expand Down
54 changes: 0 additions & 54 deletions content/en/docs/1.getting-started/1.overview.md

This file was deleted.

Loading
Loading