/opt/canhelp/apps/web/src/app
NameSizeModeActions
(auth)/-0755rm
admin/-0755rm
become-specialist/-0755rm
chat/-0755rm
dashboard/-0755rm
delete-account/-0755rm
favorites/-0755rm
maintenance/-0755rm
notifications/-0755rm
payment/-0755rm
pricing/-0755rm
privacy/-0755rm
profile/-0755rm
schedule/-0755rm
site/-0755rm
specialist-setup/-0755rm
specialist-tasks/-0755rm
specialists/-0755rm
support/-0755rm
tasks/-0755rm
users/-0755rm
apple-icon.png626050644editdlrm
globals.css95430644editdlrm
icon.png626050644editdlrm
icon.svg48820644editdlrm
layout.tsx43450644editdlrm
not-found.tsx5500644editdlrm
page.tsx243370644editdlrm
robots.ts7890644editdlrm
sitemap.ts36640644editdlrm
Edit: /opt/canhelp/apps/web/src/app/layout.tsx (4345B)
import type { Metadata } from 'next' import { cookies, headers } from 'next/headers' import { cache } from 'react' import './globals.css' import { Header } from '@/components/Header' import { Footer } from '@/components/Footer' import { LocaleProvider } from '@/context/locale' import { LocationProvider } from '@/context/location' import { ScrollToTopButton } from '@/components/ScrollToTopButton' import { AdminRolePreview } from '@/components/AdminRolePreview' import type { Locale } from '@/lib/translations' // React.cache() deduplicates identical calls within the same request render pass const fetchSeoSettings = cache(async (): Promise> => { try { const apiBase = process.env.INTERNAL_API_URL || 'http://localhost:4000' const res = await fetch(`${apiBase}/api/admin/seo-public`, { next: { revalidate: 60 } }) if (!res.ok) return {} return res.json() } catch { return {} } }) export async function generateMetadata(): Promise { const seo = await fetchSeoSettings() const cookieStore = await cookies() const rawLocale = cookieStore.get('canhelp_locale')?.value const locale = ['el', 'en', 'ru', 'uk'].includes(rawLocale ?? '') ? rawLocale! : 'el' const title = seo[`seo.siteTitle.${locale}`] || seo['seo.siteTitle.el'] || seo['seo.siteTitle'] || 'CanHelp — Βρες ειδικό για κάθε δουλειά' const description = seo[`seo.siteDescription.${locale}`] || seo['seo.siteDescription.el'] || seo['seo.siteDescription'] || 'Η ελληνική πλατφόρμα για online ανάθεση εργασιών. Βρες επαγγελματίες για καθαρισμό, υδραυλικά, μαθήματα και πολλά άλλα.' return { title, description, keywords: 'εργασίες, ειδικοί, Ελλάδα, freelance, καθαρισμός, υδραυλικά', robots: seo['seo.indexingEnabled'] === 'false' ? 'noindex, nofollow' : undefined, } } export default async function RootLayout({ children }: { children: React.ReactNode }) { const cookieStore = await cookies() const headerStore = await headers() const pathname = headerStore.get('x-pathname') ?? '' const isStandalone = pathname.startsWith('/site/') const rawLocale = cookieStore.get('canhelp_locale')?.value const locales: Locale[] = ['el', 'en', 'uk', 'ru'] const initialLocale: Locale = locales.includes(rawLocale as Locale) ? (rawLocale as Locale) : 'el' const initialLocation = decodeURIComponent(cookieStore.get('canhelp_location')?.value ?? '') const seo = await fetchSeoSettings() const headScripts = seo['seo.headScripts'] ?? '' // Parse each