Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
8 changes: 6 additions & 2 deletions .slugignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
/.git
/.next/cache
.git
.gitignore
.next/cache
coverage
*.log
.env*
27 changes: 1 addition & 26 deletions app/(iframes)/iframes/[tool]/[equivalent]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,7 @@ import { categories } from 'data/categories'
import Equivalent from 'components/outils/equivalents/Equivalent'
import { equivalentsSimulators } from 'components/outils/equivalents/simulators/equivalentsSimulators'

export async function generateStaticParams() {
return categories.flatMap((category) =>
category.equivalents
? category.equivalents.flatMap((equivalent) =>
equivalent.withCarpool
? [
{
tool: category.slug,
equivalent: equivalent.slug,
},
...Array.from({ length: 4 }).map((value, index) => ({
tool: category.slug,
equivalent: `${equivalent.slug}+${index + 1}`,
carpool: index + 1,
})),
]
: [
{
tool: category.slug,
equivalent: equivalent.slug,
},
]
)
: []
)
}
export const dynamic = 'force-dynamic'
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same concern as above: making all iframe equivalent pages fully dynamic may be costly operationally. If the motivation is the combinatorial explosion of static params (especially with carpool variants), consider ISR (revalidate) or switching the carpool selection to a query param so the number of path variants stays manageable for static generation.

Suggested change
export const dynamic = 'force-dynamic'
export const revalidate = 3600

Copilot uses AI. Check for mistakes.

type Props = {
params: Promise<{ tool: string; equivalent: string }>
Expand Down
6 changes: 1 addition & 5 deletions app/(iframes)/iframes/[tool]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
import { notFound } from 'next/navigation'
import { categories } from 'data/categories'
import Category from 'components/outils/Category'
import { simulators } from 'components/outils/simulators'
import { getCategory } from 'utils/category'

type Props = { params: Promise<{ tool: string }> }

export async function generateStaticParams() {
return categories.map((category) => ({ tool: category.slug }))
}
export const dynamic = 'force-dynamic'
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same concern as the public pages: force-dynamic for all iframe tool pages moves rendering to runtime and can reduce cacheability. If the iframe endpoints are high-traffic, consider using revalidate (ISR) or a narrower dynamic scope to avoid unnecessary per-request rendering.

Suggested change
export const dynamic = 'force-dynamic'
export const revalidate = 3600

Copilot uses AI. Check for mistakes.

const page = async (props: Props) => {
const params = await props.params
Expand Down
2 changes: 1 addition & 1 deletion app/(iframes)/iframes/transport/itineraire/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { Category as CategoryType } from 'types/category'
import { categories } from 'data/categories'
import Category from 'components/outils/Category'
import TransportSimulator from 'components/outils/TransportSimulator'
import TransportSimulator from 'components/outils/transport/TransportSimulator'

const category = categories.find((category) => category.slug === 'transport') as CategoryType

Expand Down
27 changes: 1 addition & 26 deletions app/(public)/outils/[tool]/[equivalent]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,32 +6,7 @@ import { equivalentsSimulators } from 'components/outils/equivalents/simulators/
import { getName } from 'utils/Equivalent/equivalent'
import Suggestion from 'components/layout/Suggestion'

export async function generateStaticParams() {
return categories.flatMap((category) =>
category.equivalents
? category.equivalents.flatMap((equivalent) =>
equivalent.withCarpool
? [
{
tool: category.slug,
equivalent: equivalent.slug,
},
...Array.from({ length: 4 }).map((value, index) => ({
tool: category.slug,
equivalent: `${equivalent.slug}+${index + 1}`,
carpool: index + 1,
})),
]
: [
{
tool: category.slug,
equivalent: equivalent.slug,
},
]
)
: []
)
}
export const dynamic = 'force-dynamic'
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forcing full dynamic rendering for all tool/equivalent pages can significantly increase runtime load and latency (and may regress caching/SEO if these were previously statically generated). If the intent is to avoid enumerating a large generateStaticParams, consider alternatives like keeping the route dynamic only where needed (e.g., via dynamicParams = true + revalidate), or generating a limited subset of common params while allowing dynamic fallback for the long tail.

Suggested change
export const dynamic = 'force-dynamic'
export const dynamicParams = true
export const revalidate = 3600

Copilot uses AI. Check for mistakes.

type Props = {
params: Promise<{ tool: string; equivalent: string }>
Expand Down
2 changes: 1 addition & 1 deletion app/(public)/outils/transport/itineraire/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Metadata } from 'next'
import { Category as CategoryType } from 'types/category'
import { categories } from 'data/categories'
import Category from 'components/outils/CategoryPage'
import TransportSimulator from 'components/outils/TransportSimulator'
import TransportSimulator from 'components/outils/transport/TransportSimulator'
import { metaDescriptions, metaTitles } from 'utils/meta'
import Suggestion from 'components/layout/Suggestion'

Expand Down
7 changes: 4 additions & 3 deletions app/api/dynamics/equivalents/[slug]/route.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@ export async function GET(req: NextRequest, context: { params: Promise<{ slug: s
return NextResponse.json(`Please use ${process.env.NEXT_PUBLIC_IMAGE_URL}`, { status: 400 })
}

const [slug, carpool] = decodeURIComponent((await context.params).slug).split('+')
const slugParam = decodeURIComponent((await context.params).slug)
const [slug, carpool] = slugParam.split('+')
Comment on lines +24 to +25
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Splitting the route param on '+' makes the slug ambiguous now that equivalents slugs can themselves contain '+' (e.g., voitureelectrique+1 in public/equivalents.csv). This will mis-parse valid slugs, causing wrong equivalent lookup and incorrect quantity division. Use an unambiguous encoding for carpool (e.g., a dedicated query param like ?carpool=..., or a delimiter guaranteed not to appear in slugs), or only split on the last '+' when the suffix is strictly numeric and the remaining base slug is known to be a carpool-capable equivalent.

Copilot uses AI. Check for mistakes.
if (!slug) {
return NextResponse.json('No slug specified', { status: 400 })
}
Expand Down Expand Up @@ -52,9 +53,9 @@ export async function GET(req: NextRequest, context: { params: Promise<{ slug: s

return new ImageResponse(
<Equivalent
slug={equivalent.slug}
slug={slug}
carpool={!!carpool}
name={getName(language, { ...equivalent, category: 0, carpool: Number(carpool) })}
name={getName(language, { ...equivalent, slug: slugParam, carpool: Number(carpool) }, false, 1, false, true)}
quantity={equivalent.value / ((Number(carpool) || 0) + 1)}
unit={equivalent.unit || category.unit}
language={language}
Expand Down
4 changes: 2 additions & 2 deletions app/api/v1/alimentation/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ const names: Record<Language, Record<string, string>> = {
* properties:
* warning:
* type: string
* example: La requete n'est pas authentifée.
* example: La requete n'est pas authentifiée.
* data:
* type: array
* items:
Expand Down Expand Up @@ -171,7 +171,7 @@ export async function GET(req: NextRequest) {
})),
warning: hasAPIKey
? undefined
: `La requete n'est pas authentifée. Nous nous reservons le droit de couper cette API aux utilisateurs anonymes, veuillez nous contacter à ${process.env.NEXT_PUBLIC_CONTACT_EMAIL} pour obtenir une clé d'API gratuite.`,
: `La requete n'est pas authentifiée. Nous nous reservons le droit de couper cette API aux utilisateurs anonymes, veuillez nous contacter à ${process.env.NEXT_PUBLIC_CONTACT_EMAIL} pour obtenir une clé d'API gratuite.`,
},
{ status: 200 }
)
Expand Down
4 changes: 2 additions & 2 deletions app/api/v1/chauffage/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ const chauffageValidation = z.object({
* properties:
* warning:
* type: string
* example: La requete n'est pas authentifée.
* example: La requete n'est pas authentifiée.
* data:
* type: array
* items:
Expand Down Expand Up @@ -116,7 +116,7 @@ export async function GET(req: NextRequest) {
}),
warning: hasAPIKey
? undefined
: `La requete n'est pas authentifée. Nous nous reservons le droit de couper cette API aux utilisateurs anonymes, veuillez nous contacter à ${process.env.NEXT_PUBLIC_CONTACT_EMAIL} pour obtenir une clé d'API gratuite.`,
: `La requete n'est pas authentifiée. Nous nous reservons le droit de couper cette API aux utilisateurs anonymes, veuillez nous contacter à ${process.env.NEXT_PUBLIC_CONTACT_EMAIL} pour obtenir une clé d'API gratuite.`,
},
{ status: 200 }
)
Expand Down
4 changes: 2 additions & 2 deletions app/api/v1/fruitsetlegumes/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ const validation = z.object({
* properties:
* warning:
* type: string
* example: La requete n'est pas authentifée.
* example: La requete n'est pas authentifiée.
* data:
* type: array
* items:
Expand Down Expand Up @@ -131,7 +131,7 @@ export async function GET(req: NextRequest) {
.filter((value) => !inputs.data.categories || inputs.data.categories.includes(value.category)),
warning: hasAPIKey
? undefined
: `La requete n'est pas authentifée. Nous nous reservons le droit de couper cette API aux utilisateurs anonymes, veuillez nous contacter à ${process.env.NEXT_PUBLIC_CONTACT_EMAIL} pour obtenir une clé d'API gratuite.`,
: `La requete n'est pas authentifiée. Nous nous reservons le droit de couper cette API aux utilisateurs anonymes, veuillez nous contacter à ${process.env.NEXT_PUBLIC_CONTACT_EMAIL} pour obtenir une clé d'API gratuite.`,
},
{ status: 200 }
)
Expand Down
4 changes: 2 additions & 2 deletions app/api/v1/thematiques/ecv/[id]/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ const categoryValidation = z.object({
* properties:
* warning:
* type: string
* example: La requete n'est pas authentifée.
* example: La requete n'est pas authentifiée.
* data:
* type: array
* items:
Expand Down Expand Up @@ -203,7 +203,7 @@ export async function GET(req: NextRequest, context: { params: Promise<{ id: str
}),
warning: hasAPIKey
? undefined
: `La requete n'est pas authentifée. Nous nous reservons le droit de couper cette API aux utilisateurs anonymes, veuillez nous contacter à ${process.env.NEXT_PUBLIC_CONTACT_EMAIL} pour obtenir une clé d'API gratuite.`,
: `La requete n'est pas authentifiée. Nous nous reservons le droit de couper cette API aux utilisateurs anonymes, veuillez nous contacter à ${process.env.NEXT_PUBLIC_CONTACT_EMAIL} pour obtenir une clé d'API gratuite.`,
},
{ status: 200 }
)
Expand Down
4 changes: 2 additions & 2 deletions app/api/v1/thematiques/route.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ import { trackAPIRequest } from 'utils/middleware'
* properties:
* warning:
* type: string
* example: La requete n'est pas authentifée.
* example: La requete n'est pas authentifiée.
* data:
* type: array
* items:
Expand All @@ -71,7 +71,7 @@ export async function GET(req: NextRequest) {
.sort((a, b) => a.id - b.id),
warning: hasAPIKey
? undefined
: `La requete n'est pas authentifée. Nous nous reservons le droit de couper cette API aux utilisateurs anonymes, veuillez nous contacter à ${process.env.NEXT_PUBLIC_CONTACT_EMAIL} pour obtenir une clé d'API gratuite.`,
: `La requete n'est pas authentifiée. Nous nous reservons le droit de couper cette API aux utilisateurs anonymes, veuillez nous contacter à ${process.env.NEXT_PUBLIC_CONTACT_EMAIL} pour obtenir une clé d'API gratuite.`,
},
{ status: 200 }
)
Expand Down
Loading
Loading