create-snapify-app 0.0.0-stage → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +24 -0
- package/README.md +55 -2
- package/bin/create-snapify-app.mjs +174 -0
- package/lib/args.mjs +59 -0
- package/lib/copy.mjs +44 -0
- package/lib/env.mjs +84 -0
- package/lib/prompt.mjs +63 -0
- package/package.json +35 -4
- package/template/.env.example +79 -0
- package/template/.github/workflows/ci.yml +23 -0
- package/template/.github/workflows/deploy.yml +26 -0
- package/template/.github/workflows/ping.yml +8 -0
- package/template/.github/workflows/release.yml +67 -0
- package/template/.snapify-install.json +5 -0
- package/template/CHANGELOG.md +28 -0
- package/template/LICENSE +14 -0
- package/template/README.md +287 -0
- package/template/administrator.html +23 -0
- package/template/apps/client/src/App.tsx +765 -0
- package/template/apps/client/src/auth.css +400 -0
- package/template/apps/client/src/lib/api.ts +22 -0
- package/template/apps/client/src/main.tsx +20 -0
- package/template/apps/community/src/App.tsx +592 -0
- package/template/apps/community/src/main.tsx +20 -0
- package/template/apps/community/src/styles.css +24 -0
- package/template/apps/developers/src/App.tsx +643 -0
- package/template/apps/developers/src/main.tsx +17 -0
- package/template/apps/developers/src/pages.tsx +1587 -0
- package/template/apps/developers/src/styles.css +98 -0
- package/template/apps/developers/src/ui.tsx +179 -0
- package/template/apps/landing/src/App.tsx +598 -0
- package/template/apps/landing/src/LegalPages.tsx +158 -0
- package/template/apps/landing/src/OrderPage.tsx +381 -0
- package/template/apps/landing/src/SeoPages.tsx +923 -0
- package/template/apps/landing/src/copy.ts +195 -0
- package/template/apps/landing/src/main.tsx +20 -0
- package/template/apps/landing/src/styles.css +803 -0
- package/template/apps/landing/src/types.ts +19 -0
- package/template/apps/marketplace/src/App.tsx +1229 -0
- package/template/apps/marketplace/src/developer/DeveloperApp.tsx +1266 -0
- package/template/apps/marketplace/src/main.tsx +20 -0
- package/template/apps/marketplace/src/styles.css +1001 -0
- package/template/apps/shared/AuthContext.tsx +65 -0
- package/template/apps/shared/Logo.tsx +33 -0
- package/template/apps/shared/api.ts +47 -0
- package/template/apps/shared/ui.tsx +128 -0
- package/template/apps/superadmin/src/App.tsx +1264 -0
- package/template/apps/superadmin/src/lib/api.ts +20 -0
- package/template/apps/superadmin/src/lib/hooks.ts +20 -0
- package/template/apps/superadmin/src/main.tsx +16 -0
- package/template/apps/superadmin/src/pages/ClientsPage.tsx +185 -0
- package/template/apps/superadmin/src/pages/InvoicesPage.tsx +157 -0
- package/template/apps/superadmin/src/pages/NewsletterPage.tsx +212 -0
- package/template/apps/superadmin/src/pages/OrdersPage.tsx +195 -0
- package/template/apps/superadmin/src/pages/PaymentsPage.tsx +150 -0
- package/template/apps/superadmin/src/pages/PayoutsPage.tsx +133 -0
- package/template/apps/superadmin/src/pages/PublishersPage.tsx +151 -0
- package/template/apps/superadmin/src/pages/SeoControlPage.tsx +692 -0
- package/template/apps/superadmin/src/pages/SettingsPage.tsx +199 -0
- package/template/apps/superadmin/src/pages/SystemPage.tsx +109 -0
- package/template/apps/superadmin/src/pages/TicketsPage.tsx +201 -0
- package/template/apps/superadmin/src/pages/UsersPage.tsx +167 -0
- package/template/client.html +21 -0
- package/template/community/hamdiayari/akhbar/README.md +23 -0
- package/template/community/hamdiayari/akhbar/screenshot.jpg +0 -0
- package/template/community/hamdiayari/akhbar/snapify.theme.json +76 -0
- package/template/community/hamdiayari/akhbar/src/Brand.tsx +26 -0
- package/template/community/hamdiayari/akhbar/src/Footer.tsx +182 -0
- package/template/community/hamdiayari/akhbar/src/Header.tsx +191 -0
- package/template/community/hamdiayari/akhbar/src/Layout.tsx +49 -0
- package/template/community/hamdiayari/akhbar/src/Social.tsx +33 -0
- package/template/community/hamdiayari/akhbar/src/Ticker.tsx +86 -0
- package/template/community/hamdiayari/akhbar/src/Views.tsx +285 -0
- package/template/community/hamdiayari/akhbar/src/blocks/CollectionBlocks.tsx +672 -0
- package/template/community/hamdiayari/akhbar/src/blocks/ContentBlocks.tsx +305 -0
- package/template/community/hamdiayari/akhbar/src/blocks/ConversionBlocks.tsx +569 -0
- package/template/community/hamdiayari/akhbar/src/blocks/HeaderBlocks.tsx +287 -0
- package/template/community/hamdiayari/akhbar/src/index.tsx +51 -0
- package/template/community/hamdiayari/akhbar/src/kit.tsx +357 -0
- package/template/community/hamdiayari/akhbar/src/site.ts +96 -0
- package/template/community/hamdiayari/akhbar/src/styles.css +566 -0
- package/template/community/hamdiayari/akhbar-actualites/README.md +28 -0
- package/template/community/hamdiayari/akhbar-actualites/screenshot.jpg +0 -0
- package/template/community/hamdiayari/akhbar-actualites/snapify.module.json +107 -0
- package/template/community/hamdiayari/akhbar-actualites/src/admin/AudiencePage.tsx +185 -0
- package/template/community/hamdiayari/akhbar-actualites/src/admin/index.tsx +11 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/Archive.tsx +142 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/cards.tsx +152 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/index.tsx +71 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/posts.ts +103 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/styles.css +568 -0
- package/template/community/hamdiayari/akhbar-actualites/src/public/widgets.tsx +226 -0
- package/template/community/hamdiayari/akhbar-actualites/src/server.ts +119 -0
- package/template/community/hamdiayari/akhbar-actualites/src/types.ts +25 -0
- package/template/community/hamdiayari/akhbar-urgent/README.md +36 -0
- package/template/community/hamdiayari/akhbar-urgent/screenshot.jpg +0 -0
- package/template/community/hamdiayari/akhbar-urgent/snapify.module.json +64 -0
- package/template/community/hamdiayari/akhbar-urgent/src/admin/FlashesPage.tsx +229 -0
- package/template/community/hamdiayari/akhbar-urgent/src/admin/index.tsx +11 -0
- package/template/community/hamdiayari/akhbar-urgent/src/public/Ticker.tsx +81 -0
- package/template/community/hamdiayari/akhbar-urgent/src/public/index.tsx +63 -0
- package/template/community/hamdiayari/akhbar-urgent/src/public/styles.css +142 -0
- package/template/community/hamdiayari/akhbar-urgent/src/server.ts +101 -0
- package/template/community/hamdiayari/akhbar-urgent/src/types.ts +35 -0
- package/template/community.html +21 -0
- package/template/developers.html +24 -0
- package/template/docker-compose.db.yml +24 -0
- package/template/docs/BACKOFFICE_SNAPIFY.md +130 -0
- package/template/docs/CI_CD.md +66 -0
- package/template/docs/MODULES.md +346 -0
- package/template/docs/PLATFORM_DEPLOY.md +54 -0
- package/template/docs/logo.svg +10 -0
- package/template/drizzle/0000_init.sql +147 -0
- package/template/drizzle/0001_page_project.sql +5 -0
- package/template/drizzle/0002_modules.sql +23 -0
- package/template/drizzle/0003_themes.sql +4 -0
- package/template/drizzle/0004_security.sql +82 -0
- package/template/drizzle/0005_module_records.sql +16 -0
- package/template/drizzle/0006_avatars.sql +4 -0
- package/template/drizzle/0007_platform.sql +264 -0
- package/template/drizzle/0008_mp_validation.sql +3 -0
- package/template/drizzle/0009_saas_ops.sql +77 -0
- package/template/drizzle/0010_cms_chrome.sql +13 -0
- package/template/drizzle/0011_client_portal.sql +26 -0
- package/template/drizzle/meta/0000_snapshot.json +998 -0
- package/template/drizzle/meta/0001_snapshot.json +1004 -0
- package/template/drizzle/meta/_journal.json +90 -0
- package/template/drizzle.config.ts +16 -0
- package/template/ecosystem.snapify.cjs +24 -0
- package/template/for.html +1 -0
- package/template/index.html +29 -0
- package/template/landing.html +37 -0
- package/template/marketplace/catalog.json +373 -0
- package/template/marketplace/gallery/hamdiayari.preveris/01-home.jpg +0 -0
- package/template/marketplace/gallery/hamdiayari.recaptcha/01-reglages.jpg +0 -0
- package/template/marketplace/gallery/hamdiayari.recaptcha/02-logo.jpg +0 -0
- package/template/marketplace/gallery/novalabs.ai-articles/01-generer.jpg +0 -0
- package/template/marketplace/gallery/novalabs.ai-articles/02-fournisseur-ia.jpg +0 -0
- package/template/marketplace/gallery/novalabs.calendar/01-agenda-site.jpg +0 -0
- package/template/marketplace/gallery/novalabs.calendar/02-evenements-admin.jpg +0 -0
- package/template/marketplace/gallery/novalabs.calendar/03-reglages.jpg +0 -0
- package/template/marketplace/screenshots/hamdiayari.preveris-1.0.6.jpg +0 -0
- package/template/marketplace/screenshots/hamdiayari.recaptcha-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/hamdiayari.wp-seo-migrator-1.1.1.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.ai-articles-1.0.1.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.ai-chat-1.0.1.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.calendar-1.0.1.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.cart-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.checkout-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.customers-1.1.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.dogga-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.mahdia-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.shop-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.sidibou-1.0.0.jpg +0 -0
- package/template/marketplace/screenshots/novalabs.whatsapp-1.0.1.jpg +0 -0
- package/template/marketplace.html +21 -0
- package/template/metadata.json +7 -0
- package/template/modules/ai-articles/screenshot.jpg +0 -0
- package/template/modules/ai-articles/snapify.module.json +74 -0
- package/template/modules/ai-articles/src/admin/ArticlesPage.tsx +162 -0
- package/template/modules/ai-articles/src/admin/GeneratePage.tsx +118 -0
- package/template/modules/ai-articles/src/admin/index.tsx +12 -0
- package/template/modules/ai-articles/src/public/index.tsx +119 -0
- package/template/modules/ai-articles/src/server.ts +287 -0
- package/template/modules/ai-articles/src/types.ts +30 -0
- package/template/modules/ai-chat/screenshot.jpg +0 -0
- package/template/modules/ai-chat/snapify.module.json +217 -0
- package/template/modules/ai-chat/src/public.tsx +198 -0
- package/template/modules/ai-chat/src/server.ts +142 -0
- package/template/modules/ai-theme-studio/README.md +15 -0
- package/template/modules/ai-theme-studio/screenshot.jpg +0 -0
- package/template/modules/ai-theme-studio/snapify.module.json +175 -0
- package/template/modules/ai-theme-studio/src/admin/HistoryPage.tsx +91 -0
- package/template/modules/ai-theme-studio/src/admin/StudioPage.tsx +414 -0
- package/template/modules/ai-theme-studio/src/admin/index.tsx +11 -0
- package/template/modules/ai-theme-studio/src/lib/images.ts +240 -0
- package/template/modules/ai-theme-studio/src/lib/llm.ts +123 -0
- package/template/modules/ai-theme-studio/src/lib/normalize.ts +714 -0
- package/template/modules/ai-theme-studio/src/lib/prompts.ts +198 -0
- package/template/modules/ai-theme-studio/src/server.ts +137 -0
- package/template/modules/ai-theme-studio/src/types.ts +112 -0
- package/template/modules/calendar/screenshot.jpg +0 -0
- package/template/modules/calendar/snapify.module.json +45 -0
- package/template/modules/calendar/src/admin/EventsPage.tsx +217 -0
- package/template/modules/calendar/src/admin/index.tsx +11 -0
- package/template/modules/calendar/src/public/index.tsx +231 -0
- package/template/modules/calendar/src/server.ts +143 -0
- package/template/modules/calendar/src/types.ts +25 -0
- package/template/modules/cart/screenshot.jpg +0 -0
- package/template/modules/cart/snapify.module.json +90 -0
- package/template/modules/cart/src/admin/index.tsx +265 -0
- package/template/modules/cart/src/public/CartPage.tsx +198 -0
- package/template/modules/cart/src/public/index.tsx +261 -0
- package/template/modules/cart/src/public/useQuote.ts +67 -0
- package/template/modules/cart/src/server.ts +148 -0
- package/template/modules/cart/src/types.ts +31 -0
- package/template/modules/checkout/screenshot.jpg +0 -0
- package/template/modules/checkout/snapify.module.json +264 -0
- package/template/modules/checkout/src/admin/OrderDetailPage.tsx +304 -0
- package/template/modules/checkout/src/admin/badges.tsx +28 -0
- package/template/modules/checkout/src/admin/index.tsx +236 -0
- package/template/modules/checkout/src/public/CheckoutPage.tsx +461 -0
- package/template/modules/checkout/src/public/OrderPages.tsx +153 -0
- package/template/modules/checkout/src/public/index.tsx +23 -0
- package/template/modules/checkout/src/server.ts +383 -0
- package/template/modules/checkout/src/types.ts +70 -0
- package/template/modules/customers/screenshot.jpg +0 -0
- package/template/modules/customers/snapify.module.json +115 -0
- package/template/modules/customers/src/admin/CustomerDetailPage.tsx +274 -0
- package/template/modules/customers/src/admin/index.tsx +194 -0
- package/template/modules/customers/src/public/AccountPages.tsx +470 -0
- package/template/modules/customers/src/public/AddressForm.tsx +115 -0
- package/template/modules/customers/src/public/AuthPages.tsx +349 -0
- package/template/modules/customers/src/public/Avatar.tsx +29 -0
- package/template/modules/customers/src/public/ProfileSection.tsx +291 -0
- package/template/modules/customers/src/public/index.tsx +137 -0
- package/template/modules/customers/src/public/session.ts +51 -0
- package/template/modules/customers/src/server.ts +421 -0
- package/template/modules/customers/src/types.ts +53 -0
- package/template/modules/recaptcha/logo.jpg +0 -0
- package/template/modules/recaptcha/screenshot.jpg +0 -0
- package/template/modules/recaptcha/snapify.module.json +99 -0
- package/template/modules/recaptcha/src/public/index.tsx +94 -0
- package/template/modules/recaptcha/src/server.ts +65 -0
- package/template/modules/recaptcha/src/types.ts +18 -0
- package/template/modules/shop/screenshot.jpg +0 -0
- package/template/modules/shop/snapify.module.json +340 -0
- package/template/modules/shop/src/admin/CategoriesPage.tsx +224 -0
- package/template/modules/shop/src/admin/ProductEditor.tsx +313 -0
- package/template/modules/shop/src/admin/ProductsPage.tsx +307 -0
- package/template/modules/shop/src/admin/index.tsx +14 -0
- package/template/modules/shop/src/public/Catalog.tsx +244 -0
- package/template/modules/shop/src/public/NotFound.tsx +22 -0
- package/template/modules/shop/src/public/ProductPage.tsx +195 -0
- package/template/modules/shop/src/public/index.tsx +134 -0
- package/template/modules/shop/src/public/useFetch.ts +26 -0
- package/template/modules/shop/src/server.ts +493 -0
- package/template/modules/shop/src/shared.ts +41 -0
- package/template/modules/shop/src/types.ts +60 -0
- package/template/modules/whatsapp/screenshot.jpg +0 -0
- package/template/modules/whatsapp/snapify.module.json +121 -0
- package/template/modules/whatsapp/src/public.tsx +119 -0
- package/template/modules/wp-seo-migrator/ARCHITECTURE.md +113 -0
- package/template/modules/wp-seo-migrator/README.md +21 -0
- package/template/modules/wp-seo-migrator/fixtures/aioseo-sample.csv +3 -0
- package/template/modules/wp-seo-migrator/fixtures/sample-exporter.json +39 -0
- package/template/modules/wp-seo-migrator/fixtures/sample-page.html +12 -0
- package/template/modules/wp-seo-migrator/fixtures/sample.htaccess +3 -0
- package/template/modules/wp-seo-migrator/screenshot.jpg +0 -0
- package/template/modules/wp-seo-migrator/snapify.module.json +87 -0
- package/template/modules/wp-seo-migrator/src/admin/HistoryPage.tsx +64 -0
- package/template/modules/wp-seo-migrator/src/admin/WizardPage.tsx +788 -0
- package/template/modules/wp-seo-migrator/src/admin/i18n.ts +156 -0
- package/template/modules/wp-seo-migrator/src/admin/index.tsx +11 -0
- package/template/modules/wp-seo-migrator/src/connectors/CUSTOM_CONNECTOR.md +31 -0
- package/template/modules/wp-seo-migrator/src/connectors/csvSeoFactory.ts +106 -0
- package/template/modules/wp-seo-migrator/src/connectors/exporter.ts +96 -0
- package/template/modules/wp-seo-migrator/src/connectors/gscCsv.ts +53 -0
- package/template/modules/wp-seo-migrator/src/connectors/htaccess.ts +65 -0
- package/template/modules/wp-seo-migrator/src/connectors/htmlCrawler.ts +90 -0
- package/template/modules/wp-seo-migrator/src/connectors/index.ts +113 -0
- package/template/modules/wp-seo-migrator/src/connectors/pluginCsv.ts +77 -0
- package/template/modules/wp-seo-migrator/src/connectors/rankMathCsv.ts +77 -0
- package/template/modules/wp-seo-migrator/src/connectors/redirection.ts +62 -0
- package/template/modules/wp-seo-migrator/src/connectors/sitemap.ts +44 -0
- package/template/modules/wp-seo-migrator/src/connectors/utils.ts +111 -0
- package/template/modules/wp-seo-migrator/src/connectors/wxr.ts +103 -0
- package/template/modules/wp-seo-migrator/src/connectors/yoastCsv.ts +56 -0
- package/template/modules/wp-seo-migrator/src/pipeline/analyze.ts +158 -0
- package/template/modules/wp-seo-migrator/src/pipeline/htmlParse.ts +58 -0
- package/template/modules/wp-seo-migrator/src/pipeline/remoteAuto.ts +328 -0
- package/template/modules/wp-seo-migrator/src/server.ts +492 -0
- package/template/modules/wp-seo-migrator/src/types.ts +151 -0
- package/template/modules/wp-seo-migrator/tests/connectors-extra.test.ts +39 -0
- package/template/modules/wp-seo-migrator/tests/merge.test.ts +25 -0
- package/template/package-lock.json +6016 -0
- package/template/package.json +74 -0
- package/template/public/images/photos/caravane-chameaux-desert.webp +0 -0
- package/template/public/images/photos/hammamet-medina-plage.jpg +0 -0
- package/template/public/images/photos/maison-campagne-collines.webp +0 -0
- package/template/public/images/photos/maisons-troglodytes-desert.jpg +0 -0
- package/template/public/images/photos/panorama-ville.jpg +0 -0
- package/template/public/images/photos/preveris-accessibilite-erp.jpg +0 -0
- package/template/public/images/photos/preveris-collectivites.jpg +0 -0
- package/template/public/images/photos/preveris-etudes-plans.jpg +0 -0
- package/template/public/images/photos/preveris-hero-erp.jpg +0 -0
- package/template/public/images/photos/preveris-ssi-incendie.jpg +0 -0
- package/template/public/images/photos/preveris-suivi-hotel.jpg +0 -0
- package/template/public/images/photos/ruelle-bleue-medina.jpg +0 -0
- package/template/public/images/photos/sidi-bou-said-port.webp +0 -0
- package/template/public/images/photos/terrasse-blanche-mer-voilier.jpg +0 -0
- package/template/public/landing/hero-ai-cms.jpg +0 -0
- package/template/public/landing/shot-dogga.jpg +0 -0
- package/template/public/landing/shot-mahdia.jpg +0 -0
- package/template/public/landing/shot-sidibou.jpg +0 -0
- package/template/public/llms.txt +35 -0
- package/template/public/logo.svg +10 -0
- package/template/scripts/app-pack.ts +155 -0
- package/template/scripts/app-publish.ts +123 -0
- package/template/scripts/apply-ecommerce-home.ts +196 -0
- package/template/scripts/auto-deploy-poll.sh +13 -0
- package/template/scripts/db-backup.sh +16 -0
- package/template/scripts/db-restore.sh +11 -0
- package/template/scripts/deploy.sh +34 -0
- package/template/scripts/github-webhook-deploy.sh +7 -0
- package/template/scripts/install-new-modules.ts +96 -0
- package/template/scripts/refresh-demo-baseline.ts +9 -0
- package/template/scripts/reinstall-marketplace-packs.ts +51 -0
- package/template/scripts/restore-classic-home.ts +13 -0
- package/template/scripts/sdk-pack.ts +289 -0
- package/template/scripts/sdk-publish.ts +75 -0
- package/template/scripts/seed-demo-products.ts +120 -0
- package/template/scripts/seed-theme-content-packs.ts +42 -0
- package/template/scripts/snapify-module.ts +207 -0
- package/template/scripts/test-theme-switch.ts +24 -0
- package/template/sdk/admin.css +18 -0
- package/template/sdk/admin.ts +95 -0
- package/template/sdk/build.ts +249 -0
- package/template/sdk/commerce.ts +512 -0
- package/template/sdk/content.ts +76 -0
- package/template/sdk/icons.ts +101 -0
- package/template/sdk/image.ts +60 -0
- package/template/sdk/index.ts +500 -0
- package/template/sdk/package.ts +298 -0
- package/template/sdk/recaptcha.tsx +122 -0
- package/template/sdk/settings.ts +84 -0
- package/template/sdk/theme.css +29 -0
- package/template/sdk/theme.ts +100 -0
- package/template/sdk/ui/commerce.tsx +385 -0
- package/template/sdk/ui/orders.tsx +136 -0
- package/template/sdk-kit/CHANGELOG.md +17 -0
- package/template/sdk-kit/LICENSE.md +47 -0
- package/template/sdk-kit/README.md +81 -0
- package/template/sdk-kit/cli.ts +339 -0
- package/template/sdk-kit/create-snapify/README.md +28 -0
- package/template/sdk-kit/create-snapify/create-snapify.mjs +11 -0
- package/template/sdk-kit/create-snapify/package.template.json +16 -0
- package/template/sdk-kit/package.template.json +95 -0
- package/template/sdk-kit/templates/common/README.md.tpl +27 -0
- package/template/sdk-kit/templates/common/_gitignore +3 -0
- package/template/sdk-kit/templates/common/package.json.tpl +19 -0
- package/template/sdk-kit/templates/common/src/snapify-env.d.ts +2 -0
- package/template/sdk-kit/templates/common/tsconfig.json +15 -0
- package/template/sdk-kit/templates/module/snapify.module.json.tpl +33 -0
- package/template/sdk-kit/templates/module/src/admin.tsx +53 -0
- package/template/sdk-kit/templates/module/src/public.tsx +49 -0
- package/template/sdk-kit/templates/module/src/server.ts +30 -0
- package/template/sdk-kit/templates/module/src/types.ts +19 -0
- package/template/sdk-kit/templates/theme/snapify.theme.json.tpl +22 -0
- package/template/sdk-kit/templates/theme/src/Footer.tsx +40 -0
- package/template/sdk-kit/templates/theme/src/Header.tsx +47 -0
- package/template/sdk-kit/templates/theme/src/Views.tsx +36 -0
- package/template/sdk-kit/templates/theme/src/blocks.tsx +93 -0
- package/template/sdk-kit/templates/theme/src/index.tsx +30 -0
- package/template/sdk-kit/templates/theme/src/site.tsx +59 -0
- package/template/sdk-kit/templates/theme/src/styles.css +71 -0
- package/template/server/client/routes.ts +252 -0
- package/template/server/cms/analyticsStore.ts +180 -0
- package/template/server/cms/auth.ts +155 -0
- package/template/server/cms/blockCatalog.ts +342 -0
- package/template/server/cms/blocks.ts +521 -0
- package/template/server/cms/contentMigration.ts +1119 -0
- package/template/server/cms/defaults.ts +303 -0
- package/template/server/cms/permissions.ts +154 -0
- package/template/server/cms/restoreClassicHome.ts +183 -0
- package/template/server/cms/revisions.ts +99 -0
- package/template/server/cms/scheduler.ts +78 -0
- package/template/server/cms/seed.ts +72 -0
- package/template/server/cms/seoAnalyzer.ts +213 -0
- package/template/server/cms/store.ts +122 -0
- package/template/server/cms/themeContent.ts +1386 -0
- package/template/server/cms/themePacks/sidibou-branding.json +1 -0
- package/template/server/cms/themePacks/sidibou-home.json +1 -0
- package/template/server/cms/themePacks/sidibou-menus.json +1 -0
- package/template/server/cms/types.ts +432 -0
- package/template/server/community/routes.ts +410 -0
- package/template/server/db/client.ts +43 -0
- package/template/server/db/repository.ts +389 -0
- package/template/server/db/schema.ts +726 -0
- package/template/server/demo/cmsReset.ts +196 -0
- package/template/server/developers/sdk.ts +85 -0
- package/template/server/geoip.ts +15 -0
- package/template/server/http.ts +53 -0
- package/template/server/mail.ts +216 -0
- package/template/server/marketplace/catalog.ts +74 -0
- package/template/server/marketplace/packageValidate.ts +475 -0
- package/template/server/marketplace/payments.ts +193 -0
- package/template/server/marketplace/routes.ts +850 -0
- package/template/server/marketplace/signing.ts +116 -0
- package/template/server/marketplace/syncOfficial.ts +282 -0
- package/template/server/media/images.ts +63 -0
- package/template/server/middleware/adminAuth.ts +134 -0
- package/template/server/modules/legacy.ts +44 -0
- package/template/server/modules/manager.ts +1122 -0
- package/template/server/modules/marketplace.ts +178 -0
- package/template/server/modules/outbound.ts +178 -0
- package/template/server/modules/purchases.ts +149 -0
- package/template/server/modules/records.ts +168 -0
- package/template/server/modules/themeHtml.ts +32 -0
- package/template/server/modules/trust.ts +16 -0
- package/template/server/modules/types.ts +147 -0
- package/template/server/platform/auth.ts +223 -0
- package/template/server/platform/clientWelcome.ts +168 -0
- package/template/server/platform/clients.ts +139 -0
- package/template/server/platform/dailyImprove.ts +356 -0
- package/template/server/platform/flouci.ts +126 -0
- package/template/server/platform/host.ts +69 -0
- package/template/server/platform/hostingProviders.ts +143 -0
- package/template/server/platform/licenseOrders.ts +291 -0
- package/template/server/platform/money.ts +42 -0
- package/template/server/platform/passwords.ts +41 -0
- package/template/server/platform/region.ts +86 -0
- package/template/server/platform/routes.ts +225 -0
- package/template/server/platform/seed.ts +82 -0
- package/template/server/platform/settings.ts +72 -0
- package/template/server/routes/adminAccount.ts +403 -0
- package/template/server/routes/adminCms.ts +808 -0
- package/template/server/routes/adminSystem.ts +243 -0
- package/template/server/routes/adminUsers.ts +449 -0
- package/template/server/routes/googleOAuth.ts +327 -0
- package/template/server/routes/modules.ts +323 -0
- package/template/server/routes/publicCms.ts +313 -0
- package/template/server/routes/seoPublic.ts +158 -0
- package/template/server/security/accounts.ts +121 -0
- package/template/server/security/audit.ts +143 -0
- package/template/server/security/authTokens.ts +74 -0
- package/template/server/security/ip.ts +68 -0
- package/template/server/security/rateLimit.ts +85 -0
- package/template/server/security/retention.ts +46 -0
- package/template/server/security/secrets.ts +44 -0
- package/template/server/security/sessions.ts +140 -0
- package/template/server/security/totp.ts +101 -0
- package/template/server/superadmin/analytics.ts +109 -0
- package/template/server/superadmin/auth.ts +92 -0
- package/template/server/superadmin/backlinksCatalog.ts +210 -0
- package/template/server/superadmin/frSeoContent.ts +165 -0
- package/template/server/superadmin/landingSeo.ts +675 -0
- package/template/server/superadmin/ops.ts +238 -0
- package/template/server/superadmin/routes.ts +1095 -0
- package/template/server/superadmin/tnSeoContent.ts +130 -0
- package/template/server.ts +522 -0
- package/template/src/App.tsx +263 -0
- package/template/src/admin/AdminApp.tsx +162 -0
- package/template/src/admin/account/AuthLayout.tsx +57 -0
- package/template/src/admin/account/SecurityForms.tsx +276 -0
- package/template/src/admin/admin.css +127 -0
- package/template/src/admin/context/AuthContext.tsx +147 -0
- package/template/src/admin/context/SiteContext.tsx +50 -0
- package/template/src/admin/editor/BlockLibrary.tsx +173 -0
- package/template/src/admin/editor/BlocksPanel.tsx +396 -0
- package/template/src/admin/editor/EditorBits.tsx +106 -0
- package/template/src/admin/editor/PreviewFrame.tsx +145 -0
- package/template/src/admin/editor/RichTextEditor.tsx +276 -0
- package/template/src/admin/editor/SeoPanel.tsx +349 -0
- package/template/src/admin/editor/StyleEditor.tsx +114 -0
- package/template/src/admin/editor/blockSchemas.ts +699 -0
- package/template/src/admin/editor/fields.tsx +486 -0
- package/template/src/admin/layout/AdminShell.tsx +418 -0
- package/template/src/admin/layout/nav.ts +95 -0
- package/template/src/admin/lib/api.ts +408 -0
- package/template/src/admin/lib/audit.ts +141 -0
- package/template/src/admin/lib/format.ts +84 -0
- package/template/src/admin/lib/hooks.ts +125 -0
- package/template/src/admin/main.tsx +16 -0
- package/template/src/admin/modules/InstallDialog.tsx +160 -0
- package/template/src/admin/modules/SettingsForm.tsx +145 -0
- package/template/src/admin/modules/kit.tsx +127 -0
- package/template/src/admin/modules/labels.tsx +226 -0
- package/template/src/admin/pages/AccountSetupPage.tsx +62 -0
- package/template/src/admin/pages/AnalyticsPage.tsx +206 -0
- package/template/src/admin/pages/BrandingPage.tsx +154 -0
- package/template/src/admin/pages/DashboardPage.tsx +239 -0
- package/template/src/admin/pages/EngagementPage.tsx +168 -0
- package/template/src/admin/pages/FormsPage.tsx +435 -0
- package/template/src/admin/pages/GeneralPage.tsx +120 -0
- package/template/src/admin/pages/LoginPage.tsx +249 -0
- package/template/src/admin/pages/MaintenancePage.tsx +125 -0
- package/template/src/admin/pages/MarketplacePage.tsx +426 -0
- package/template/src/admin/pages/MediaPage.tsx +251 -0
- package/template/src/admin/pages/MenusPage.tsx +446 -0
- package/template/src/admin/pages/ModuleAdminPage.tsx +113 -0
- package/template/src/admin/pages/ModuleDetailPage.tsx +293 -0
- package/template/src/admin/pages/ModulesPage.tsx +135 -0
- package/template/src/admin/pages/NewsletterPage.tsx +193 -0
- package/template/src/admin/pages/PageEditorPage.tsx +322 -0
- package/template/src/admin/pages/PagesListPage.tsx +277 -0
- package/template/src/admin/pages/PostEditorPage.tsx +292 -0
- package/template/src/admin/pages/PostsListPage.tsx +187 -0
- package/template/src/admin/pages/ProfilePage.tsx +489 -0
- package/template/src/admin/pages/ResetPasswordPage.tsx +110 -0
- package/template/src/admin/pages/SeoPage.tsx +670 -0
- package/template/src/admin/pages/SettingsPage.tsx +189 -0
- package/template/src/admin/pages/ThemeCustomizePage.tsx +170 -0
- package/template/src/admin/pages/ThemesPage.tsx +292 -0
- package/template/src/admin/pages/UsersPage.tsx +57 -0
- package/template/src/admin/pages/WidgetsPage.tsx +200 -0
- package/template/src/admin/seo/GoogleSetup.tsx +529 -0
- package/template/src/admin/settings/EmailTab.tsx +293 -0
- package/template/src/admin/settings/OtherTabs.tsx +270 -0
- package/template/src/admin/settings/SecurityTab.tsx +172 -0
- package/template/src/admin/settings/controls.tsx +133 -0
- package/template/src/admin/ui/Pagination.tsx +170 -0
- package/template/src/admin/ui/SaveBar.tsx +77 -0
- package/template/src/admin/ui/TagInput.tsx +54 -0
- package/template/src/admin/ui/charts.tsx +108 -0
- package/template/src/admin/ui/media.tsx +265 -0
- package/template/src/admin/ui/overlays.tsx +239 -0
- package/template/src/admin/ui/primitives.tsx +544 -0
- package/template/src/admin/users/AuditTab.tsx +104 -0
- package/template/src/admin/users/RolesTab.tsx +368 -0
- package/template/src/admin/users/UsersTab.tsx +723 -0
- package/template/src/admin/users/shared.tsx +278 -0
- package/template/src/cms/icons.ts +7 -0
- package/template/src/components/CookieBanner.tsx +166 -0
- package/template/src/components/MaintenanceGate.tsx +66 -0
- package/template/src/components/SiteAnalytics.tsx +64 -0
- package/template/src/components/SnapifyLogo.tsx +44 -0
- package/template/src/components/cms/BlockRenderer.tsx +154 -0
- package/template/src/components/cms/WidgetArea.tsx +193 -0
- package/template/src/context/SiteConfigContext.tsx +130 -0
- package/template/src/demoBase.ts +23 -0
- package/template/src/index.css +90 -0
- package/template/src/main.tsx +16 -0
- package/template/src/modules/ModuleHost.tsx +197 -0
- package/template/src/preview.ts +63 -0
- package/template/src/runtime.ts +38 -0
- package/template/src/themes/ThemeHost.tsx +168 -0
- package/template/src/themes/fallback.tsx +71 -0
- package/template/src/types.ts +94 -0
- package/template/src/views/BlogPostView.tsx +68 -0
- package/template/src/views/CmsPageView.tsx +34 -0
- package/template/start-pm2.sh +3 -0
- package/template/superadmin.html +20 -0
- package/template/themes/ai-canvas/screenshot.jpg +0 -0
- package/template/themes/ai-canvas/snapify.theme.json +96 -0
- package/template/themes/ai-canvas/src/CeeSimulator.tsx +247 -0
- package/template/themes/ai-canvas/src/Footer.tsx +190 -0
- package/template/themes/ai-canvas/src/Header.tsx +324 -0
- package/template/themes/ai-canvas/src/Layout.tsx +56 -0
- package/template/themes/ai-canvas/src/NotFound.tsx +58 -0
- package/template/themes/ai-canvas/src/Post.tsx +26 -0
- package/template/themes/ai-canvas/src/SnapifyLogo.tsx +44 -0
- package/template/themes/ai-canvas/src/blocks/CollectionBlocks.tsx +711 -0
- package/template/themes/ai-canvas/src/blocks/ContentBlocks.tsx +318 -0
- package/template/themes/ai-canvas/src/blocks/ConversionBlocks.tsx +559 -0
- package/template/themes/ai-canvas/src/blocks/HeaderBlocks.tsx +341 -0
- package/template/themes/ai-canvas/src/index.tsx +54 -0
- package/template/themes/ai-canvas/src/kit.tsx +398 -0
- package/template/themes/ai-canvas/src/site.ts +29 -0
- package/template/themes/ai-canvas/src/styles.css +317 -0
- package/template/themes/dogga/screenshot.jpg +0 -0
- package/template/themes/dogga/snapify.theme.json +55 -0
- package/template/themes/dogga/src/Brand.tsx +41 -0
- package/template/themes/dogga/src/Footer.tsx +202 -0
- package/template/themes/dogga/src/Header.tsx +239 -0
- package/template/themes/dogga/src/Layout.tsx +43 -0
- package/template/themes/dogga/src/Views.tsx +71 -0
- package/template/themes/dogga/src/blocks/CollectionBlocks.tsx +674 -0
- package/template/themes/dogga/src/blocks/ContentBlocks.tsx +307 -0
- package/template/themes/dogga/src/blocks/ConversionBlocks.tsx +571 -0
- package/template/themes/dogga/src/blocks/HeaderBlocks.tsx +289 -0
- package/template/themes/dogga/src/index.tsx +53 -0
- package/template/themes/dogga/src/kit.tsx +362 -0
- package/template/themes/dogga/src/site.ts +56 -0
- package/template/themes/dogga/src/styles.css +396 -0
- package/template/themes/mahdia/screenshot.jpg +0 -0
- package/template/themes/mahdia/snapify.theme.json +65 -0
- package/template/themes/mahdia/src/Brand.tsx +39 -0
- package/template/themes/mahdia/src/Footer.tsx +210 -0
- package/template/themes/mahdia/src/Header.tsx +291 -0
- package/template/themes/mahdia/src/Layout.tsx +44 -0
- package/template/themes/mahdia/src/Views.tsx +79 -0
- package/template/themes/mahdia/src/blocks/CollectionBlocks.tsx +674 -0
- package/template/themes/mahdia/src/blocks/ContentBlocks.tsx +307 -0
- package/template/themes/mahdia/src/blocks/ConversionBlocks.tsx +571 -0
- package/template/themes/mahdia/src/blocks/HeaderBlocks.tsx +289 -0
- package/template/themes/mahdia/src/index.tsx +53 -0
- package/template/themes/mahdia/src/kit.tsx +362 -0
- package/template/themes/mahdia/src/site.ts +75 -0
- package/template/themes/mahdia/src/styles.css +446 -0
- package/template/themes/preveris/screenshot.jpg +0 -0
- package/template/themes/preveris/snapify.theme.json +126 -0
- package/template/themes/preveris/src/Brand.tsx +44 -0
- package/template/themes/preveris/src/Footer.tsx +202 -0
- package/template/themes/preveris/src/Header.tsx +239 -0
- package/template/themes/preveris/src/Layout.tsx +42 -0
- package/template/themes/preveris/src/Views.tsx +71 -0
- package/template/themes/preveris/src/blocks/CollectionBlocks.tsx +678 -0
- package/template/themes/preveris/src/blocks/ContentBlocks.tsx +307 -0
- package/template/themes/preveris/src/blocks/ConversionBlocks.tsx +571 -0
- package/template/themes/preveris/src/blocks/HeaderBlocks.tsx +299 -0
- package/template/themes/preveris/src/index.tsx +53 -0
- package/template/themes/preveris/src/kit.tsx +365 -0
- package/template/themes/preveris/src/site.ts +79 -0
- package/template/themes/preveris/src/styles.css +446 -0
- package/template/themes/sidibou/screenshot.jpg +0 -0
- package/template/themes/sidibou/snapify.theme.json +21 -0
- package/template/themes/sidibou/src/CeeSimulator.tsx +247 -0
- package/template/themes/sidibou/src/Footer.tsx +203 -0
- package/template/themes/sidibou/src/Header.tsx +324 -0
- package/template/themes/sidibou/src/Layout.tsx +53 -0
- package/template/themes/sidibou/src/NotFound.tsx +58 -0
- package/template/themes/sidibou/src/Post.tsx +26 -0
- package/template/themes/sidibou/src/SnapifyLogo.tsx +44 -0
- package/template/themes/sidibou/src/blocks/CollectionBlocks.tsx +711 -0
- package/template/themes/sidibou/src/blocks/ContentBlocks.tsx +318 -0
- package/template/themes/sidibou/src/blocks/ConversionBlocks.tsx +559 -0
- package/template/themes/sidibou/src/blocks/HeaderBlocks.tsx +341 -0
- package/template/themes/sidibou/src/index.tsx +54 -0
- package/template/themes/sidibou/src/kit.tsx +398 -0
- package/template/themes/sidibou/src/site.ts +28 -0
- package/template/themes/sidibou/src/styles.css +317 -0
- package/template/tsconfig.json +33 -0
- package/template/vite.config.ts +42 -0
|
@@ -0,0 +1,1386 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contenu lié au thème (accueil + menus + branding léger).
|
|
3
|
+
* Chaque thème a son pack : activer un thème restaure son contenu
|
|
4
|
+
* sans écraser celui des autres.
|
|
5
|
+
*/
|
|
6
|
+
import fs from 'fs/promises';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import { fileURLToPath } from 'url';
|
|
9
|
+
import { eq } from 'drizzle-orm';
|
|
10
|
+
import { db } from '../db/client';
|
|
11
|
+
import { siteSettings } from '../db/schema';
|
|
12
|
+
import { updateSnapshot, loadSnapshot } from './store';
|
|
13
|
+
import { button, uid } from './blocks';
|
|
14
|
+
import { BLOCK_CATALOG } from './blockCatalog';
|
|
15
|
+
import { defaultSeoForPath } from './defaults';
|
|
16
|
+
import type { CmsBlock, CmsPage, MenuConfig, MenuItem, SeoMeta, ThemeBranding } from './types';
|
|
17
|
+
|
|
18
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const PACKS_DIR = path.join(__dirname, 'themePacks');
|
|
20
|
+
|
|
21
|
+
const KEY = (themeId: string) => `theme.content.${themeId}`;
|
|
22
|
+
|
|
23
|
+
export interface ThemePageSeed {
|
|
24
|
+
path: string;
|
|
25
|
+
title: string;
|
|
26
|
+
blocks: CmsBlock[];
|
|
27
|
+
seo?: Partial<SeoMeta>;
|
|
28
|
+
template?: CmsPage['template'];
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ThemeContentPack {
|
|
32
|
+
version: 1;
|
|
33
|
+
themeId: string;
|
|
34
|
+
savedAt: string;
|
|
35
|
+
home: {
|
|
36
|
+
title: string;
|
|
37
|
+
blocks: CmsBlock[];
|
|
38
|
+
seo?: Partial<SeoMeta>;
|
|
39
|
+
};
|
|
40
|
+
pages?: ThemePageSeed[];
|
|
41
|
+
menus: MenuConfig[];
|
|
42
|
+
branding?: Partial<ThemeBranding>;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function block(type: CmsBlock['type'], data: Record<string, unknown>, style?: CmsBlock['style']): CmsBlock {
|
|
46
|
+
return { id: uid('b'), type, data, style: style || { paddingTop: 'md', paddingBottom: 'md' } };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function moduleBlock(widget: string, options: Record<string, unknown>): CmsBlock {
|
|
50
|
+
return block('module', { module: 'novalabs.shop', widget, options });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function classicMenus(labels: { primary: MenuItem[]; footer: MenuItem[] }): MenuConfig[] {
|
|
54
|
+
const primary: MenuConfig = { id: 'primary', label: 'Menu principal (desktop)', items: labels.primary };
|
|
55
|
+
const mobile: MenuConfig = {
|
|
56
|
+
id: 'mobile',
|
|
57
|
+
label: 'Menu mobile',
|
|
58
|
+
items: JSON.parse(JSON.stringify(labels.primary)) as MenuItem[],
|
|
59
|
+
};
|
|
60
|
+
const footer: MenuConfig = { id: 'footer', label: 'Pied de page', items: labels.footer };
|
|
61
|
+
return [primary, mobile, footer];
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Pack boutique Mahdia (widgets shop). */
|
|
65
|
+
export function buildMahdiaPack(): ThemeContentPack {
|
|
66
|
+
const shopChildren: MenuItem[] = [
|
|
67
|
+
{ id: 'm-shop-maison', label: 'Maison & déco', path: '/boutique/maison-deco/' },
|
|
68
|
+
{ id: 'm-shop-mode', label: 'Mode', path: '/boutique/mode/' },
|
|
69
|
+
{ id: 'm-shop-bienetre', label: 'Bien-être', path: '/boutique/bien-etre/' },
|
|
70
|
+
{ id: 'm-shop-gourmet', label: 'Gourmet', path: '/boutique/gourmet/' },
|
|
71
|
+
];
|
|
72
|
+
const homeBlocks: CmsBlock[] = [
|
|
73
|
+
block(
|
|
74
|
+
'hero',
|
|
75
|
+
{
|
|
76
|
+
...BLOCK_CATALOG.hero.defaults(),
|
|
77
|
+
layout: 'split',
|
|
78
|
+
badgeTag: 'Boutique',
|
|
79
|
+
badgeText: 'Mahdia',
|
|
80
|
+
title: 'L’esprit Méditerranée, chez vous',
|
|
81
|
+
subtitle: 'Découvrez une sélection démo : déco, mode, bien-être et gourmet — livrée partout en Tunisie.',
|
|
82
|
+
buttons: [button('Voir la boutique', '/boutique/'), button('Promotions', '/boutique/?promo=1', 'secondary', 'none')],
|
|
83
|
+
media: 'image',
|
|
84
|
+
mainImage: '/images/photos/terrasse-blanche-mer-voilier.jpg',
|
|
85
|
+
mainImageAlt: 'Terrasse face à la mer',
|
|
86
|
+
marquee: ['Maison & déco', 'Mode', 'Bien-être', 'Gourmet', 'Livraison Tunisie'],
|
|
87
|
+
},
|
|
88
|
+
{ ...BLOCK_CATALOG.hero.style, paddingTop: 'lg', paddingBottom: 'lg', background: 'soft' }
|
|
89
|
+
),
|
|
90
|
+
moduleBlock('categories', { eyebrow: 'Collections', title: 'Parcourir par catégorie', subtitle: '', limit: 4, style: 'tiles' }),
|
|
91
|
+
moduleBlock('products', {
|
|
92
|
+
eyebrow: 'Sélection',
|
|
93
|
+
title: 'Nos coups de cœur',
|
|
94
|
+
subtitle: 'Produits mis en avant pour la démo Snapify.',
|
|
95
|
+
source: 'featured',
|
|
96
|
+
category: '',
|
|
97
|
+
limit: 8,
|
|
98
|
+
columns: '4',
|
|
99
|
+
buttonLabel: 'Voir toute la boutique',
|
|
100
|
+
}),
|
|
101
|
+
block(
|
|
102
|
+
'cta',
|
|
103
|
+
{
|
|
104
|
+
...BLOCK_CATALOG.cta.defaults(),
|
|
105
|
+
title: 'Livraison partout en Tunisie',
|
|
106
|
+
text: 'Paiement à la livraison, retours sous 14 jours.',
|
|
107
|
+
buttons: [button('Commander maintenant', '/boutique/', 'dark')],
|
|
108
|
+
},
|
|
109
|
+
{ paddingTop: 'lg', paddingBottom: 'lg' }
|
|
110
|
+
),
|
|
111
|
+
moduleBlock('products', {
|
|
112
|
+
eyebrow: 'Promotions',
|
|
113
|
+
title: 'Bonnes affaires',
|
|
114
|
+
subtitle: '',
|
|
115
|
+
source: 'sale',
|
|
116
|
+
category: '',
|
|
117
|
+
limit: 4,
|
|
118
|
+
columns: '4',
|
|
119
|
+
buttonLabel: 'Toutes les promotions',
|
|
120
|
+
}),
|
|
121
|
+
block('steps', {
|
|
122
|
+
...BLOCK_CATALOG.steps.defaults(),
|
|
123
|
+
title: 'Commander en 3 étapes',
|
|
124
|
+
items: [
|
|
125
|
+
{ id: uid('k'), num: '01', title: 'Choisir', text: 'Parcourez la boutique et ajoutez au panier.' },
|
|
126
|
+
{ id: uid('k'), num: '02', title: 'Valider', text: 'Renseignez l’adresse et le mode de paiement.' },
|
|
127
|
+
{ id: uid('k'), num: '03', title: 'Recevoir', text: 'Livraison sous 24 à 72 h en Tunisie.' },
|
|
128
|
+
],
|
|
129
|
+
}),
|
|
130
|
+
moduleBlock('products', {
|
|
131
|
+
eyebrow: 'Nouveautés',
|
|
132
|
+
title: 'Derniers arrivages',
|
|
133
|
+
subtitle: '',
|
|
134
|
+
source: 'latest',
|
|
135
|
+
category: '',
|
|
136
|
+
limit: 4,
|
|
137
|
+
columns: '4',
|
|
138
|
+
buttonLabel: '',
|
|
139
|
+
}),
|
|
140
|
+
block('faq', {
|
|
141
|
+
...BLOCK_CATALOG.faq.defaults(),
|
|
142
|
+
title: 'Questions fréquentes',
|
|
143
|
+
items: [
|
|
144
|
+
{ id: uid('k'), question: 'Quels sont les délais de livraison ?', answer: '<p>En général 24 à 72 h partout en Tunisie.</p>' },
|
|
145
|
+
{ id: uid('k'), question: 'Puis-je payer à la livraison ?', answer: '<p>Oui, via le module Commande.</p>' },
|
|
146
|
+
],
|
|
147
|
+
}),
|
|
148
|
+
block(
|
|
149
|
+
'cta',
|
|
150
|
+
{
|
|
151
|
+
...BLOCK_CATALOG.cta.defaults(),
|
|
152
|
+
title: 'Prêt à explorer la boutique ?',
|
|
153
|
+
text: '12 produits démo vous attendent.',
|
|
154
|
+
buttons: [button('Ouvrir la boutique', '/boutique/', 'dark')],
|
|
155
|
+
},
|
|
156
|
+
{ paddingTop: 'lg', paddingBottom: 'lg' }
|
|
157
|
+
),
|
|
158
|
+
];
|
|
159
|
+
return {
|
|
160
|
+
version: 1,
|
|
161
|
+
themeId: 'novalabs.mahdia',
|
|
162
|
+
savedAt: new Date().toISOString(),
|
|
163
|
+
home: {
|
|
164
|
+
title: 'Accueil',
|
|
165
|
+
blocks: homeBlocks,
|
|
166
|
+
seo: {
|
|
167
|
+
seoTitle: 'Snapify Boutique — Mahdia',
|
|
168
|
+
metaDescription: 'Découvrez 12 produits démo et 4 catégories.',
|
|
169
|
+
ogTitle: 'Accueil — Boutique',
|
|
170
|
+
ogDescription: 'Boutique démo Snapify.',
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
menus: classicMenus({
|
|
174
|
+
primary: [
|
|
175
|
+
{ id: 'm-shop', label: 'Boutique', path: '/boutique/', children: shopChildren },
|
|
176
|
+
{ id: 'm-promo', label: 'Promotions', path: '/boutique/?promo=1' },
|
|
177
|
+
{ id: 'm-home', label: 'Accueil', path: '/' },
|
|
178
|
+
{ id: 'm-contact', label: 'Contact', path: '/contact/', highlight: true },
|
|
179
|
+
],
|
|
180
|
+
footer: [
|
|
181
|
+
{ id: 'f-shop', label: 'Boutique', path: '/boutique/' },
|
|
182
|
+
{ id: 'f-promo', label: 'Promotions', path: '/boutique/?promo=1' },
|
|
183
|
+
{ id: 'f-contact', label: 'Contact', path: '/contact/', highlight: true },
|
|
184
|
+
{ id: 'f-legal', label: 'Mentions légales', path: '/mentions-legales/' },
|
|
185
|
+
{ id: 'f-privacy', label: 'Confidentialité', path: '/politique-de-confidentialite/' },
|
|
186
|
+
{ id: 'f-cookies', label: 'Cookies', path: '/cookies/' },
|
|
187
|
+
],
|
|
188
|
+
}),
|
|
189
|
+
branding: {
|
|
190
|
+
tagline: 'Boutique démo — Tunisie',
|
|
191
|
+
colors: {
|
|
192
|
+
primary: '#0E7C86',
|
|
193
|
+
primaryHover: '#0A5E66',
|
|
194
|
+
accent: '#D97706',
|
|
195
|
+
navy: '#0F262B',
|
|
196
|
+
background: '#FAF6EF',
|
|
197
|
+
text: '#0F262B',
|
|
198
|
+
muted: '#66716F',
|
|
199
|
+
border: '#E5DCCD',
|
|
200
|
+
},
|
|
201
|
+
fonts: { heading: 'Plus Jakarta Sans', body: 'Plus Jakarta Sans' },
|
|
202
|
+
},
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/** Pack éditorial Dogga (vitrine, sans boutique). */
|
|
207
|
+
export function buildDoggaPack(): ThemeContentPack {
|
|
208
|
+
const homeBlocks: CmsBlock[] = [
|
|
209
|
+
block(
|
|
210
|
+
'hero',
|
|
211
|
+
{
|
|
212
|
+
...BLOCK_CATALOG.hero.defaults(),
|
|
213
|
+
layout: 'centered',
|
|
214
|
+
badgeTag: 'Dogga',
|
|
215
|
+
badgeText: 'Éditorial',
|
|
216
|
+
title: 'Une présence éditoriale, sobre et durable',
|
|
217
|
+
subtitle: 'Grands titres, images en arche et sections aérées — le thème Dogga pour une vitrine corporate.',
|
|
218
|
+
buttons: [button('Nos expertises', '/expertises/'), button('Nous contacter', '/contact/', 'secondary', 'none')],
|
|
219
|
+
media: 'none',
|
|
220
|
+
},
|
|
221
|
+
{ ...BLOCK_CATALOG.hero.style, paddingTop: 'lg', paddingBottom: 'lg', background: 'soft' }
|
|
222
|
+
),
|
|
223
|
+
block('stats', {
|
|
224
|
+
...BLOCK_CATALOG.stats.defaults(),
|
|
225
|
+
items: [
|
|
226
|
+
{ id: uid('k'), value: '25', suffix: '+', label: 'Blocs du constructeur' },
|
|
227
|
+
{ id: uid('k'), value: '100', suffix: ' %', label: 'Personnalisable' },
|
|
228
|
+
{ id: uid('k'), value: '48', suffix: ' h', label: 'Mise en ligne' },
|
|
229
|
+
],
|
|
230
|
+
}),
|
|
231
|
+
block('steps', {
|
|
232
|
+
...BLOCK_CATALOG.steps.defaults(),
|
|
233
|
+
title: 'Notre méthode',
|
|
234
|
+
items: [
|
|
235
|
+
{ id: uid('k'), num: '01', title: 'Comprendre', text: 'Cadrage du message et de l’identité.' },
|
|
236
|
+
{ id: uid('k'), num: '02', title: 'Composer', text: 'Pages et blocs dans le constructeur.' },
|
|
237
|
+
{ id: uid('k'), num: '03', title: 'Publier', text: 'SEO, menus et formulaires prêts.' },
|
|
238
|
+
],
|
|
239
|
+
}),
|
|
240
|
+
block('projects', { ...BLOCK_CATALOG.projects.defaults(), title: 'Réalisations' }),
|
|
241
|
+
block(
|
|
242
|
+
'cta',
|
|
243
|
+
{
|
|
244
|
+
...BLOCK_CATALOG.cta.defaults(),
|
|
245
|
+
title: 'Parlons de votre projet',
|
|
246
|
+
text: 'Une équipe Snapify vous répond rapidement.',
|
|
247
|
+
buttons: [button('Contact', '/contact/', 'dark')],
|
|
248
|
+
},
|
|
249
|
+
{ paddingTop: 'lg', paddingBottom: 'lg' }
|
|
250
|
+
),
|
|
251
|
+
];
|
|
252
|
+
return {
|
|
253
|
+
version: 1,
|
|
254
|
+
themeId: 'novalabs.dogga',
|
|
255
|
+
savedAt: new Date().toISOString(),
|
|
256
|
+
home: {
|
|
257
|
+
title: 'Accueil',
|
|
258
|
+
blocks: homeBlocks,
|
|
259
|
+
seo: {
|
|
260
|
+
seoTitle: 'Snapify — Dogga',
|
|
261
|
+
metaDescription: 'Vitrine éditoriale Snapify avec le thème Dogga.',
|
|
262
|
+
ogTitle: 'Accueil',
|
|
263
|
+
ogDescription: 'Thème éditorial Dogga.',
|
|
264
|
+
},
|
|
265
|
+
},
|
|
266
|
+
menus: classicMenus({
|
|
267
|
+
primary: [
|
|
268
|
+
{ id: 'm-exp', label: 'Expertises', path: '/expertises/' },
|
|
269
|
+
{ id: 'm-sec', label: 'Secteurs', path: '/secteurs/' },
|
|
270
|
+
{ id: 'm-real', label: 'Réalisations', path: '/realisations/' },
|
|
271
|
+
{ id: 'm-approche', label: 'Notre approche', path: '/notre-approche/' },
|
|
272
|
+
{ id: 'm-contact', label: 'Contact', path: '/contact/', highlight: true },
|
|
273
|
+
],
|
|
274
|
+
footer: [
|
|
275
|
+
{ id: 'f-real', label: 'Réalisations', path: '/realisations/' },
|
|
276
|
+
{ id: 'f-approche', label: 'Notre approche', path: '/notre-approche/' },
|
|
277
|
+
{ id: 'f-contact', label: 'Contact', path: '/contact/', highlight: true },
|
|
278
|
+
{ id: 'f-legal', label: 'Mentions légales', path: '/mentions-legales/' },
|
|
279
|
+
{ id: 'f-privacy', label: 'Confidentialité', path: '/politique-de-confidentialite/' },
|
|
280
|
+
{ id: 'f-cookies', label: 'Cookies', path: '/cookies/' },
|
|
281
|
+
],
|
|
282
|
+
}),
|
|
283
|
+
branding: {
|
|
284
|
+
tagline: 'Éditorial & corporate — Tunisie',
|
|
285
|
+
colors: {
|
|
286
|
+
primary: '#B4532A',
|
|
287
|
+
primaryHover: '#93401E',
|
|
288
|
+
accent: '#2D3D78',
|
|
289
|
+
navy: '#1A1612',
|
|
290
|
+
background: '#F5F1EA',
|
|
291
|
+
text: '#1A1612',
|
|
292
|
+
muted: '#6F665B',
|
|
293
|
+
border: '#DDD3C4',
|
|
294
|
+
},
|
|
295
|
+
fonts: { heading: 'Instrument Serif', body: 'Manrope' },
|
|
296
|
+
},
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
async function loadSidibouDefault(): Promise<ThemeContentPack> {
|
|
301
|
+
const home = JSON.parse(await fs.readFile(path.join(PACKS_DIR, 'sidibou-home.json'), 'utf8')) as {
|
|
302
|
+
blocks: CmsBlock[];
|
|
303
|
+
title: string;
|
|
304
|
+
seo?: Partial<SeoMeta>;
|
|
305
|
+
};
|
|
306
|
+
const menus = JSON.parse(await fs.readFile(path.join(PACKS_DIR, 'sidibou-menus.json'), 'utf8')) as MenuConfig[];
|
|
307
|
+
let branding: ThemeContentPack['branding'];
|
|
308
|
+
try {
|
|
309
|
+
const b = JSON.parse(await fs.readFile(path.join(PACKS_DIR, 'sidibou-branding.json'), 'utf8')) as ThemeBranding;
|
|
310
|
+
branding = { siteName: b.siteName, tagline: b.tagline, colors: b.colors, fonts: b.fonts };
|
|
311
|
+
} catch {
|
|
312
|
+
branding = { tagline: 'Ingénierie & performance énergétique' };
|
|
313
|
+
}
|
|
314
|
+
return {
|
|
315
|
+
version: 1,
|
|
316
|
+
themeId: 'novalabs.sidibou',
|
|
317
|
+
savedAt: new Date().toISOString(),
|
|
318
|
+
home: { title: home.title || 'Accueil', blocks: home.blocks, seo: home.seo },
|
|
319
|
+
menus,
|
|
320
|
+
branding,
|
|
321
|
+
};
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export async function readThemePack(themeId: string): Promise<ThemeContentPack | null> {
|
|
325
|
+
const [row] = await db.select().from(siteSettings).where(eq(siteSettings.key, KEY(themeId)));
|
|
326
|
+
if (!row?.value || typeof row.value !== 'object') return null;
|
|
327
|
+
const v = row.value as ThemeContentPack;
|
|
328
|
+
if (v.version !== 1 || !Array.isArray(v.home?.blocks) || !Array.isArray(v.menus)) return null;
|
|
329
|
+
return v;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export async function writeThemePack(pack: ThemeContentPack): Promise<void> {
|
|
333
|
+
await db
|
|
334
|
+
.insert(siteSettings)
|
|
335
|
+
.values({ key: KEY(pack.themeId), value: pack, updatedAt: new Date() })
|
|
336
|
+
.onConflictDoUpdate({ target: siteSettings.key, set: { value: pack, updatedAt: new Date() } });
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/** Capture l’accueil + menus actuels dans le pack du thème. */
|
|
340
|
+
export async function captureLiveThemeContent(themeId: string): Promise<ThemeContentPack> {
|
|
341
|
+
const s = await loadSnapshot();
|
|
342
|
+
const home = s.pages.find((p) => p.path === '/' || p.path === '');
|
|
343
|
+
const pack: ThemeContentPack = {
|
|
344
|
+
version: 1,
|
|
345
|
+
themeId,
|
|
346
|
+
savedAt: new Date().toISOString(),
|
|
347
|
+
home: {
|
|
348
|
+
title: home?.title || 'Accueil',
|
|
349
|
+
blocks: structuredClone(home?.blocks || []),
|
|
350
|
+
seo: home?.seo ? structuredClone(home.seo) : undefined,
|
|
351
|
+
},
|
|
352
|
+
menus: structuredClone(s.menus),
|
|
353
|
+
branding: {
|
|
354
|
+
siteName: s.branding.siteName,
|
|
355
|
+
tagline: s.branding.tagline,
|
|
356
|
+
logoUrl: s.branding.logoUrl,
|
|
357
|
+
logoDarkUrl: s.branding.logoDarkUrl,
|
|
358
|
+
faviconUrl: s.branding.faviconUrl,
|
|
359
|
+
colors: structuredClone(s.branding.colors),
|
|
360
|
+
fonts: structuredClone(s.branding.fonts),
|
|
361
|
+
},
|
|
362
|
+
};
|
|
363
|
+
await writeThemePack(pack);
|
|
364
|
+
return pack;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
/** Applique un pack sur le snapshot CMS (accueil + pages du thème + menus + identité visuelle). */
|
|
368
|
+
export async function applyThemePack(pack: ThemeContentPack): Promise<void> {
|
|
369
|
+
const t = new Date().toISOString();
|
|
370
|
+
await updateSnapshot((s) => {
|
|
371
|
+
const home = s.pages.find((p) => p.path === '/' || p.path === '');
|
|
372
|
+
if (home) {
|
|
373
|
+
home.blocks = structuredClone(pack.home.blocks);
|
|
374
|
+
home.title = pack.home.title || 'Accueil';
|
|
375
|
+
if (pack.home.seo) home.seo = { ...home.seo, ...pack.home.seo };
|
|
376
|
+
home.updatedAt = t;
|
|
377
|
+
}
|
|
378
|
+
if (Array.isArray(pack.pages)) {
|
|
379
|
+
for (const pg of pack.pages) {
|
|
380
|
+
const existing = s.pages.find((p) => p.path === pg.path);
|
|
381
|
+
if (existing) {
|
|
382
|
+
existing.title = pg.title || existing.title;
|
|
383
|
+
existing.blocks = structuredClone(pg.blocks);
|
|
384
|
+
existing.status = 'published';
|
|
385
|
+
existing.publishedAt = existing.publishedAt || t;
|
|
386
|
+
existing.contentSource = 'cms';
|
|
387
|
+
if (pg.template) existing.template = pg.template;
|
|
388
|
+
if (pg.seo) existing.seo = { ...existing.seo, ...pg.seo };
|
|
389
|
+
existing.updatedAt = t;
|
|
390
|
+
} else {
|
|
391
|
+
s.pages.push({
|
|
392
|
+
id: uid('page'),
|
|
393
|
+
path: pg.path,
|
|
394
|
+
title: pg.title,
|
|
395
|
+
status: 'published',
|
|
396
|
+
publishedAt: t,
|
|
397
|
+
contentSource: 'cms',
|
|
398
|
+
template: pg.template || 'default',
|
|
399
|
+
blocks: structuredClone(pg.blocks),
|
|
400
|
+
seo: { ...defaultSeoForPath(pg.path, pg.title), ...(pg.seo || {}) },
|
|
401
|
+
createdAt: t,
|
|
402
|
+
updatedAt: t,
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
const byId = new Map(s.menus.map((m) => [m.id, m]));
|
|
408
|
+
for (const m of pack.menus) {
|
|
409
|
+
const existing = byId.get(m.id);
|
|
410
|
+
if (existing) {
|
|
411
|
+
existing.items = structuredClone(m.items);
|
|
412
|
+
if (m.label) existing.label = m.label;
|
|
413
|
+
} else {
|
|
414
|
+
s.menus.push(structuredClone(m));
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (pack.branding?.tagline !== undefined) s.branding.tagline = pack.branding.tagline;
|
|
418
|
+
if (pack.branding?.siteName) s.branding.siteName = pack.branding.siteName;
|
|
419
|
+
if (pack.branding?.logoUrl !== undefined) s.branding.logoUrl = pack.branding.logoUrl;
|
|
420
|
+
if (pack.branding?.logoDarkUrl !== undefined) s.branding.logoDarkUrl = pack.branding.logoDarkUrl;
|
|
421
|
+
if (pack.branding?.faviconUrl !== undefined) s.branding.faviconUrl = pack.branding.faviconUrl;
|
|
422
|
+
if (pack.branding?.colors) s.branding.colors = { ...s.branding.colors, ...pack.branding.colors };
|
|
423
|
+
if (pack.branding?.fonts) s.branding.fonts = { ...s.branding.fonts, ...pack.branding.fonts };
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
/** Pack Preveris — bureau d’études sécurité incendie & accessibilité ERP (contenu PDF). */
|
|
428
|
+
export function buildPreverisPack(): ThemeContentPack {
|
|
429
|
+
const homeBlocks: CmsBlock[] = [
|
|
430
|
+
block(
|
|
431
|
+
'hero',
|
|
432
|
+
{
|
|
433
|
+
...BLOCK_CATALOG.hero.defaults(),
|
|
434
|
+
layout: 'split',
|
|
435
|
+
badgeTag: 'Bureau d’études',
|
|
436
|
+
badgeText: 'Sécurité incendie · Accessibilité ERP',
|
|
437
|
+
title: 'PRÉVÉRIS, votre bureau d’études en',
|
|
438
|
+
highlight: 'sécurité incendie et accessibilité',
|
|
439
|
+
subtitle:
|
|
440
|
+
'Garantir l’ouverture de votre ERP dans un temps et un budget maîtrisés. Études, suivi et assistance pour exploitants et collectivités.',
|
|
441
|
+
buttons: [
|
|
442
|
+
button('Parler de votre projet', '/contact/'),
|
|
443
|
+
button('Nos études', '/etudes/autorisation-travaux/', 'secondary', 'none'),
|
|
444
|
+
],
|
|
445
|
+
media: 'image',
|
|
446
|
+
mainImage: '/images/photos/preveris-hero-erp.jpg',
|
|
447
|
+
mainImageAlt: 'Préventionniste PRÉVÉRIS — inspection sécurité incendie et plans ERP',
|
|
448
|
+
marquee: ['Autorisation de travaux', 'Permis de construire', 'Coordination SSI', 'RUS', 'Collectivités', 'Audit accessibilité'],
|
|
449
|
+
liveText: 'Fondé en 2017 · France entière',
|
|
450
|
+
trustItems: ['Autorisation de travaux', 'Commissions de sécurité', 'Accompagnement A à Z'],
|
|
451
|
+
},
|
|
452
|
+
{ ...BLOCK_CATALOG.hero.style, paddingTop: 'lg', paddingBottom: 'lg', background: 'soft', decor: 'glow', animation: 'fade-up' }
|
|
453
|
+
),
|
|
454
|
+
block(
|
|
455
|
+
'stats',
|
|
456
|
+
{
|
|
457
|
+
...BLOCK_CATALOG.stats.defaults(),
|
|
458
|
+
eyebrow: 'Chiffres clés',
|
|
459
|
+
title: 'Une expertise de terrain,',
|
|
460
|
+
highlight: 'au service de vos ERP.',
|
|
461
|
+
style: 'cards',
|
|
462
|
+
countUp: true,
|
|
463
|
+
items: [
|
|
464
|
+
{ id: uid('k'), value: '2017', suffix: '', label: 'Année de création' },
|
|
465
|
+
{ id: uid('k'), value: '95', suffix: ' %', label: 'Dossiers validés au 1er dépôt' },
|
|
466
|
+
{ id: uid('k'), value: '48', suffix: ' h', label: 'Délai moyen de premier échange' },
|
|
467
|
+
{ id: uid('k'), value: '31', suffix: '+', label: 'Collectivités accompagnées' },
|
|
468
|
+
],
|
|
469
|
+
},
|
|
470
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'navy', decor: 'glow', animation: 'fade-up' }
|
|
471
|
+
),
|
|
472
|
+
block(
|
|
473
|
+
'cards',
|
|
474
|
+
{
|
|
475
|
+
...BLOCK_CATALOG.cards.defaults(),
|
|
476
|
+
eyebrow: 'Besoin d’une étude ?',
|
|
477
|
+
title: 'Dossiers conformes,',
|
|
478
|
+
highlight: 'ouverture sécurisée.',
|
|
479
|
+
intro: 'PRÉVÉRIS constitue les dossiers techniques complets pour vos autorisations de travaux, permis et systèmes SSI.',
|
|
480
|
+
style: 'hoverDark',
|
|
481
|
+
columns: 3,
|
|
482
|
+
items: [
|
|
483
|
+
{
|
|
484
|
+
id: uid('k'),
|
|
485
|
+
icon: 'file-check',
|
|
486
|
+
title: 'Autorisation de travaux',
|
|
487
|
+
text: 'Plans cotés, notices sécurité incendie et accessibilité, Cerfa : déposez en mairie un projet conforme dès le 1er passage.',
|
|
488
|
+
tags: ['AT ERP · 95 % validés'],
|
|
489
|
+
link: '/etudes/autorisation-travaux/',
|
|
490
|
+
linkLabel: 'En savoir plus',
|
|
491
|
+
},
|
|
492
|
+
{
|
|
493
|
+
id: uid('k'),
|
|
494
|
+
icon: 'building',
|
|
495
|
+
title: 'Permis de construire',
|
|
496
|
+
text: 'Accompagnement clé en main avec architectes HMONP partenaires, notices réglementaires et suivi d’instruction.',
|
|
497
|
+
tags: ['PC · Architecte HMONP'],
|
|
498
|
+
link: '/etudes/permis-construire/',
|
|
499
|
+
linkLabel: 'En savoir plus',
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
id: uid('k'),
|
|
503
|
+
icon: 'shield',
|
|
504
|
+
title: 'Coordination SSI',
|
|
505
|
+
text: 'Conception, cahier des charges fonctionnel, essais techniques et dossier d’identité SSI supervisés par d’anciens officiers.',
|
|
506
|
+
tags: ['CSSI · NF S 61-932'],
|
|
507
|
+
link: '/etudes/coordination-ssi/',
|
|
508
|
+
linkLabel: 'En savoir plus',
|
|
509
|
+
},
|
|
510
|
+
],
|
|
511
|
+
},
|
|
512
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'white', animation: 'fade-up' }
|
|
513
|
+
),
|
|
514
|
+
block(
|
|
515
|
+
'textMedia',
|
|
516
|
+
{
|
|
517
|
+
...BLOCK_CATALOG.textMedia.defaults(),
|
|
518
|
+
eyebrow: 'Expertise prévention incendie',
|
|
519
|
+
title: 'D’anciens officiers préventionnistes',
|
|
520
|
+
highlight: 'à vos côtés.',
|
|
521
|
+
html: '<p>Fondé en 2017, le bureau d’études <strong>PRÉVÉRIS</strong> réunit des préventionnistes issus des commissions de sécurité, des dessinateurs projeteurs et des coordinateurs SSI.</p><p>Notre mission : traduire une réglementation incendie et accessibilité complexe en solutions concrètes, économiques et défendables devant les autorités.</p>',
|
|
522
|
+
bullets: [
|
|
523
|
+
'Supervision par d’anciens officiers de sapeurs-pompiers préventionnistes',
|
|
524
|
+
'Solutions compensatoires et demandes de dérogation argumentées',
|
|
525
|
+
'Présence physique à vos côtés lors des commissions de sécurité',
|
|
526
|
+
'Intervention sur toute la France métropolitaine sous 48 h',
|
|
527
|
+
],
|
|
528
|
+
buttons: [
|
|
529
|
+
button('Découvrir nos études', '/etudes/'),
|
|
530
|
+
button('Parler à un préventionniste', '/contact/', 'secondary', 'none'),
|
|
531
|
+
],
|
|
532
|
+
mediaType: 'image',
|
|
533
|
+
image: '/images/photos/preveris-etudes-plans.jpg',
|
|
534
|
+
imageAlt: 'Ingénieurs préventionnistes analysant des plans d’évacuation et de sécurité incendie ERP',
|
|
535
|
+
caption: 'Étude sur plans, notices réglementaires et préparation des commissions de sécurité.',
|
|
536
|
+
mediaPosition: 'right',
|
|
537
|
+
mediaStyle: 'framed',
|
|
538
|
+
ratio: 'landscape',
|
|
539
|
+
},
|
|
540
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'soft', animation: 'fade-up' }
|
|
541
|
+
),
|
|
542
|
+
block(
|
|
543
|
+
'steps',
|
|
544
|
+
{
|
|
545
|
+
...BLOCK_CATALOG.steps.defaults(),
|
|
546
|
+
eyebrow: 'Notre méthodologie',
|
|
547
|
+
title: 'Votre conformité ERP',
|
|
548
|
+
highlight: 'en 4 étapes maîtrisées.',
|
|
549
|
+
style: 'timeline',
|
|
550
|
+
deliverableLabel: 'Livrable clé',
|
|
551
|
+
items: [
|
|
552
|
+
{
|
|
553
|
+
id: uid('st'),
|
|
554
|
+
num: '01',
|
|
555
|
+
title: 'Diagnostic & faisabilité',
|
|
556
|
+
text: 'Analyse du classement ERP (type et catégorie), visite sur site, relevés géométriques et identification des points bloquants.',
|
|
557
|
+
deliverable: 'Compte-rendu d’audit & chiffrage',
|
|
558
|
+
},
|
|
559
|
+
{
|
|
560
|
+
id: uid('st'),
|
|
561
|
+
num: '02',
|
|
562
|
+
title: 'Dossier réglementaire & SSI',
|
|
563
|
+
text: 'Rédaction des notices sécurité incendie et accessibilité, plans cotés, cahier des charges fonctionnel SSI et Cerfa.',
|
|
564
|
+
deliverable: 'Dossier AT / PC / CSSI complet',
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
id: uid('st'),
|
|
568
|
+
num: '03',
|
|
569
|
+
title: 'Instruction & suivi mairie',
|
|
570
|
+
text: 'Dépôt dématérialisé ou papier, échanges directs avec les services instructeurs et la sous-commission départementale.',
|
|
571
|
+
deliverable: 'Complétude sous 48 h & avis favorable',
|
|
572
|
+
},
|
|
573
|
+
{
|
|
574
|
+
id: uid('st'),
|
|
575
|
+
num: '04',
|
|
576
|
+
title: 'Commission & ouverture',
|
|
577
|
+
text: 'Réception technique, préparation du registre de sécurité et présence d’un préventionniste le jour de la visite.',
|
|
578
|
+
deliverable: 'Arrêté d’ouverture & suivi annuel',
|
|
579
|
+
},
|
|
580
|
+
],
|
|
581
|
+
},
|
|
582
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'white', animation: 'fade-up' }
|
|
583
|
+
),
|
|
584
|
+
block(
|
|
585
|
+
'panels',
|
|
586
|
+
{
|
|
587
|
+
...BLOCK_CATALOG.panels.defaults(),
|
|
588
|
+
eyebrow: 'Besoin d’un suivi ?',
|
|
589
|
+
title: 'Maintenir la conformité',
|
|
590
|
+
highlight: 'dans la durée.',
|
|
591
|
+
items: [
|
|
592
|
+
{
|
|
593
|
+
id: uid('k'),
|
|
594
|
+
image: '/images/photos/preveris-ssi-incendie.jpg',
|
|
595
|
+
icon: 'calendar',
|
|
596
|
+
title: 'Suivi annuel',
|
|
597
|
+
text: 'Accompagnement toute l’année pour maintenir la conformité incendie de vos établissements et préparer les visites périodiques.',
|
|
598
|
+
bullets: ['Tenue du registre de sécurité', 'Visite annuelle sur site', 'Présence en commission'],
|
|
599
|
+
link: '/suivi/annuel/',
|
|
600
|
+
linkLabel: 'Découvrir',
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
id: uid('k'),
|
|
604
|
+
image: '/images/photos/preveris-accessibilite-erp.jpg',
|
|
605
|
+
icon: 'users',
|
|
606
|
+
title: 'Responsable Unique de Sécurité',
|
|
607
|
+
text: 'Externalisation complète de la mission réglementaire de RUS pour centres commerciaux et groupements d’ERP.',
|
|
608
|
+
bullets: ['Plus de 50 groupements suivis', 'Visa des dossiers preneurs', 'Registre unique & SOGS'],
|
|
609
|
+
link: '/suivi/rus/',
|
|
610
|
+
linkLabel: 'Découvrir',
|
|
611
|
+
},
|
|
612
|
+
{
|
|
613
|
+
id: uid('k'),
|
|
614
|
+
image: '/images/photos/preveris-suivi-hotel.jpg',
|
|
615
|
+
icon: 'hotel',
|
|
616
|
+
title: 'Suivi hôtel (Type O)',
|
|
617
|
+
text: 'Veille renforcée pour les ERP avec locaux à sommeil face aux risques d’incendie et aux visites inopinées.',
|
|
618
|
+
bullets: ['Audit annuel Type O', 'Suivi SDI & désenfumage', 'Assistance commission'],
|
|
619
|
+
link: '/suivi/hotel/',
|
|
620
|
+
linkLabel: 'Découvrir',
|
|
621
|
+
},
|
|
622
|
+
],
|
|
623
|
+
},
|
|
624
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'soft', animation: 'fade-up' }
|
|
625
|
+
),
|
|
626
|
+
block(
|
|
627
|
+
'showcase',
|
|
628
|
+
{
|
|
629
|
+
...BLOCK_CATALOG.showcase.defaults(),
|
|
630
|
+
eyebrow: 'Assistance & Collectivités',
|
|
631
|
+
title: 'Des interventions ciblées',
|
|
632
|
+
highlight: 'pour chaque situation.',
|
|
633
|
+
interval: 6,
|
|
634
|
+
items: [
|
|
635
|
+
{
|
|
636
|
+
id: uid('sh'),
|
|
637
|
+
icon: 'check-circle',
|
|
638
|
+
title: 'Audit accessibilité & dérogations PMR',
|
|
639
|
+
text: 'Diagnostic complet de la chaîne du déplacement (stationnement, accès, circulations, sanitaires) et constitution des dossiers de dérogation motivés en CCDSA.',
|
|
640
|
+
image: '/images/photos/preveris-accessibilite-erp.jpg',
|
|
641
|
+
chips: ['Loi 2005', 'Dérogations motivées', 'Espaces d’Attente Sécurisés'],
|
|
642
|
+
link: '/assistance/audit-accessibilite/',
|
|
643
|
+
buttonLabel: 'Voir l’audit accessibilité',
|
|
644
|
+
},
|
|
645
|
+
{
|
|
646
|
+
id: uid('sh'),
|
|
647
|
+
icon: 'file-text',
|
|
648
|
+
title: 'Documents obligatoires : GN8, SOGS, GE5 & plans',
|
|
649
|
+
text: 'Rédaction sur mesure de vos procédures d’évacuation des personnes en situation de handicap (GN8), SOGS, plans d’intervention pompiers et registres.',
|
|
650
|
+
image: '/images/photos/preveris-etudes-plans.jpg',
|
|
651
|
+
chips: ['Procédure GN8', 'SOGS (art. M 31)', 'Plans d’évacuation NF X 08-070'],
|
|
652
|
+
link: '/assistance/documents/',
|
|
653
|
+
buttonLabel: 'Commander mes documents',
|
|
654
|
+
},
|
|
655
|
+
{
|
|
656
|
+
id: uid('sh'),
|
|
657
|
+
icon: 'wind',
|
|
658
|
+
title: 'Études de désenfumage (IT 246) & avis défavorables',
|
|
659
|
+
text: 'Dimensionnement au plus juste des installations de désenfumage naturel ou mécanique, levée de prescriptions et visio-conseil dès 100 € TTC.',
|
|
660
|
+
image: '/images/photos/preveris-ssi-incendie.jpg',
|
|
661
|
+
chips: ['Instruction Technique 246', 'Levée de réserves', 'Visio-conseil expert'],
|
|
662
|
+
link: '/assistance/missions-ponctuelles/',
|
|
663
|
+
buttonLabel: 'Nos missions ponctuelles',
|
|
664
|
+
},
|
|
665
|
+
{
|
|
666
|
+
id: uid('sh'),
|
|
667
|
+
icon: 'building',
|
|
668
|
+
title: 'Services aux collectivités — « Vous décidez, nous éclairons »',
|
|
669
|
+
text: 'Instruction externalisée des AT ERP 5e catégorie sous 30 jours (complétude 48 h), secrétariat CCSA, appui ADS et audit du patrimoine communal.',
|
|
670
|
+
image: '/images/photos/preveris-collectivites.jpg',
|
|
671
|
+
chips: ['31 communes partenaires', 'Près de 1 000 dossiers instruits', 'Chorus Pro sans engagement'],
|
|
672
|
+
link: '/collectivites/',
|
|
673
|
+
buttonLabel: 'Offre collectivités',
|
|
674
|
+
},
|
|
675
|
+
],
|
|
676
|
+
},
|
|
677
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'white', animation: 'fade-up' }
|
|
678
|
+
),
|
|
679
|
+
block(
|
|
680
|
+
'checklist',
|
|
681
|
+
{
|
|
682
|
+
...BLOCK_CATALOG.checklist.defaults(),
|
|
683
|
+
eyebrow: 'Les + de PRÉVÉRIS',
|
|
684
|
+
title: 'Pourquoi nous confier',
|
|
685
|
+
highlight: 'votre établissement.',
|
|
686
|
+
cards: [
|
|
687
|
+
{
|
|
688
|
+
id: uid('k'),
|
|
689
|
+
icon: 'shieldCheck',
|
|
690
|
+
tag: 'Expertise',
|
|
691
|
+
title: 'Rigueur réglementaire',
|
|
692
|
+
entries: [
|
|
693
|
+
{ id: uid('e'), title: '95 % de dossiers validés au 1er dépôt', text: 'Des notices complètes et argumentées qui évitent les demandes de pièces complémentaires.' },
|
|
694
|
+
{ id: uid('e'), title: 'Anciens officiers préventionnistes', text: 'Une maîtrise parfaite des attentes des commissions de sécurité et d’accessibilité.' },
|
|
695
|
+
{ id: uid('e'), title: 'Veille réglementaire continue', text: 'Code de la construction, règlement du 25 juin 1980, arrêtés spécifiques et IT 246.' },
|
|
696
|
+
],
|
|
697
|
+
},
|
|
698
|
+
{
|
|
699
|
+
id: uid('k'),
|
|
700
|
+
icon: 'clock',
|
|
701
|
+
tag: 'Réactivité',
|
|
702
|
+
title: 'Délais & budget maîtrisés',
|
|
703
|
+
entries: [
|
|
704
|
+
{ id: uid('e'), title: 'Premier échange sous 48 h', text: 'Qualification rapide de votre besoin et chiffrage transparent sans mauvaise surprise.' },
|
|
705
|
+
{ id: uid('e'), title: 'Solutions techniques pragmatiques', text: 'Priorité aux aménagements et mesures compensatoires qui préservent votre budget travaux.' },
|
|
706
|
+
{ id: uid('e'), title: 'Dossiers livrés en 10 à 30 jours', text: 'Planification serrée pour sécuriser votre date d’ouverture ou de livraison.' },
|
|
707
|
+
],
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
id: uid('k'),
|
|
711
|
+
icon: 'users',
|
|
712
|
+
tag: 'Proximité',
|
|
713
|
+
title: 'Accompagnement humain',
|
|
714
|
+
entries: [
|
|
715
|
+
{ id: uid('e'), title: 'Binôme référent dédié', text: 'Un préventionniste et un chargé de suivi qui connaissent votre établissement.' },
|
|
716
|
+
{ id: uid('e'), title: 'Présence le jour J en commission', text: 'Nous défendons votre dossier sur place face aux pompiers et aux instructeurs.' },
|
|
717
|
+
{ id: uid('e'), title: 'Intervention France entière', text: 'Exploitants privés, enseignes nationales, architectes et collectivités territoriales.' },
|
|
718
|
+
],
|
|
719
|
+
},
|
|
720
|
+
],
|
|
721
|
+
},
|
|
722
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'soft', animation: 'fade-up' }
|
|
723
|
+
),
|
|
724
|
+
block(
|
|
725
|
+
'testimonials',
|
|
726
|
+
{
|
|
727
|
+
...BLOCK_CATALOG.testimonials.defaults(),
|
|
728
|
+
eyebrow: 'Ils nous font confiance',
|
|
729
|
+
title: 'Retours de terrain',
|
|
730
|
+
highlight: 'exploitants & partenaires.',
|
|
731
|
+
items: [
|
|
732
|
+
{
|
|
733
|
+
id: uid('k'),
|
|
734
|
+
quote:
|
|
735
|
+
'PRÉVÉRIS ce n’est pas juste un passage ou deux par an. C’est un réel accompagnement. L’avantage est que PRÉVÉRIS sont là le jour de la commission de sécurité.',
|
|
736
|
+
author: 'Alain Salmeron',
|
|
737
|
+
role: 'Président, Les Cottages de France',
|
|
738
|
+
},
|
|
739
|
+
{
|
|
740
|
+
id: uid('k'),
|
|
741
|
+
quote: 'À chaque fois la société PRÉVÉRIS a été présente pour instruire de A à Z les dossiers dans un temps record.',
|
|
742
|
+
author: 'Michel Laskar',
|
|
743
|
+
role: 'Président & Conseiller, Immobilier Commercial',
|
|
744
|
+
},
|
|
745
|
+
{
|
|
746
|
+
id: uid('k'),
|
|
747
|
+
quote: 'Il y a vraiment de la proximité avec PRÉVÉRIS. Lorsque j’ai un souci, j’appelle et la personne au bout du fil est toujours disponible.',
|
|
748
|
+
author: 'Jonathan Tergemina',
|
|
749
|
+
role: 'Président & Restaurateur, La Côte et l’Arête',
|
|
750
|
+
},
|
|
751
|
+
],
|
|
752
|
+
},
|
|
753
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'navy', decor: 'glow', animation: 'fade-up' }
|
|
754
|
+
),
|
|
755
|
+
block(
|
|
756
|
+
'faq',
|
|
757
|
+
{
|
|
758
|
+
...BLOCK_CATALOG.faq.defaults(),
|
|
759
|
+
eyebrow: 'Questions fréquentes',
|
|
760
|
+
title: 'Vos questions sur la',
|
|
761
|
+
highlight: 'conformité incendie & ERP.',
|
|
762
|
+
layout: 'split',
|
|
763
|
+
showContactCard: true,
|
|
764
|
+
contactLabel: 'Besoin d’un avis immédiat ?',
|
|
765
|
+
items: [
|
|
766
|
+
{
|
|
767
|
+
id: uid('q'),
|
|
768
|
+
question: 'Quand faut-il déposer une Autorisation de Travaux (AT) en ERP ?',
|
|
769
|
+
answer:
|
|
770
|
+
'<p>Toute création, aménagement intérieur, modification des circulations ou changement de destination d’un Établissement Recevant du Public (même sans permis de construire) nécessite une Autorisation de Travaux au titre de l’article L. 122-3 du CCH avant le démarrage du chantier.</p>',
|
|
771
|
+
},
|
|
772
|
+
{
|
|
773
|
+
id: uid('q'),
|
|
774
|
+
question: 'Que faire après un avis défavorable de la commission de sécurité ?',
|
|
775
|
+
answer:
|
|
776
|
+
'<p>Ne restez pas seul : nos préventionnistes analysent le procès-verbal, hiérarchisent les prescriptions, proposent un échéancier réaliste au maire et vous accompagnent jusqu’à la contre-visite de levée de réserves.</p>',
|
|
777
|
+
},
|
|
778
|
+
{
|
|
779
|
+
id: uid('q'),
|
|
780
|
+
question: 'Quels établissements ont l’obligation de désigner un RUS ?',
|
|
781
|
+
answer:
|
|
782
|
+
'<p>Les groupements d’établissements non isolés entre eux (centres commerciaux, galeries, bâtiments tertiaires multi-locataires en ERP) doivent obligatoirement désigner un Responsable Unique de Sécurité (art. R. 143-21 du CCH).</p>',
|
|
783
|
+
},
|
|
784
|
+
{
|
|
785
|
+
id: uid('q'),
|
|
786
|
+
question: 'Dans quels délais intervenez-vous et sur quelle zone géographique ?',
|
|
787
|
+
answer:
|
|
788
|
+
'<p>Nous organisons un premier échange sous 48 h ouvrées et livrons vos dossiers d’études sous 10 à 30 jours en moyenne, partout en France métropolitaine.</p>',
|
|
789
|
+
},
|
|
790
|
+
],
|
|
791
|
+
},
|
|
792
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'white', animation: 'fade-up' }
|
|
793
|
+
),
|
|
794
|
+
block(
|
|
795
|
+
'marquee',
|
|
796
|
+
{
|
|
797
|
+
...BLOCK_CATALOG.marquee.defaults(),
|
|
798
|
+
speed: 'slow',
|
|
799
|
+
items: [
|
|
800
|
+
'Ville de Bondy',
|
|
801
|
+
'Cottages de France',
|
|
802
|
+
'Intermarché',
|
|
803
|
+
'Leclerc',
|
|
804
|
+
'Meaux',
|
|
805
|
+
'Frey',
|
|
806
|
+
'Halles Market',
|
|
807
|
+
'Romainville',
|
|
808
|
+
'Super U',
|
|
809
|
+
'Parrot World',
|
|
810
|
+
].map((text) => ({ id: uid('m'), text })),
|
|
811
|
+
},
|
|
812
|
+
{ paddingTop: 'sm', paddingBottom: 'sm', background: 'soft' }
|
|
813
|
+
),
|
|
814
|
+
block(
|
|
815
|
+
'cta',
|
|
816
|
+
{
|
|
817
|
+
...BLOCK_CATALOG.cta.defaults(),
|
|
818
|
+
variant: 'gradient',
|
|
819
|
+
layout: 'centered',
|
|
820
|
+
eyebrow: 'Parlons de votre projet',
|
|
821
|
+
title: 'Mettez votre ERP',
|
|
822
|
+
highlight: 'en conformité.',
|
|
823
|
+
text: 'PRÉVÉRIS met à votre service son réseau de spécialistes pour la sécurité et l’accessibilité de votre établissement.',
|
|
824
|
+
buttons: [
|
|
825
|
+
button('Demander un échange', '/contact/', 'primary'),
|
|
826
|
+
button('07 44 84 45 19', 'tel:+33744844519', 'secondary', 'none'),
|
|
827
|
+
],
|
|
828
|
+
},
|
|
829
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'soft', animation: 'fade-up' }
|
|
830
|
+
),
|
|
831
|
+
];
|
|
832
|
+
|
|
833
|
+
const pvPage = (opts: {
|
|
834
|
+
path: string;
|
|
835
|
+
title: string;
|
|
836
|
+
eyebrow: string;
|
|
837
|
+
highlight?: string;
|
|
838
|
+
intro: string;
|
|
839
|
+
parentLabel?: string;
|
|
840
|
+
parentLink?: string;
|
|
841
|
+
image?: string;
|
|
842
|
+
cardsTitle?: string;
|
|
843
|
+
cardsHighlight?: string;
|
|
844
|
+
cards?: { icon: string; title: string; text: string; tags?: string[]; link?: string; linkLabel?: string }[];
|
|
845
|
+
stepsTitle?: string;
|
|
846
|
+
steps?: { num: string; title: string; text: string }[];
|
|
847
|
+
faq?: { question: string; answer: string }[];
|
|
848
|
+
html?: string;
|
|
849
|
+
}): ThemePageSeed => {
|
|
850
|
+
const blocks: CmsBlock[] = [
|
|
851
|
+
block(
|
|
852
|
+
'pageHeader',
|
|
853
|
+
{
|
|
854
|
+
...BLOCK_CATALOG.pageHeader.defaults(),
|
|
855
|
+
breadcrumb: true,
|
|
856
|
+
parentLabel: opts.parentLabel || '',
|
|
857
|
+
parentLink: opts.parentLink || '',
|
|
858
|
+
eyebrow: opts.eyebrow,
|
|
859
|
+
title: opts.title,
|
|
860
|
+
highlight: opts.highlight || '',
|
|
861
|
+
intro: opts.intro,
|
|
862
|
+
image: opts.image || '/images/photos/preveris-hero-erp.jpg',
|
|
863
|
+
imageAlt: opts.title,
|
|
864
|
+
buttons: [
|
|
865
|
+
button('Demander un devis', '/contact/'),
|
|
866
|
+
button('07 44 84 45 19', 'tel:+33744844519', 'secondary', 'none'),
|
|
867
|
+
],
|
|
868
|
+
},
|
|
869
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'soft', decor: 'glow', animation: 'fade-up' }
|
|
870
|
+
),
|
|
871
|
+
];
|
|
872
|
+
|
|
873
|
+
if (opts.html) {
|
|
874
|
+
blocks.push(
|
|
875
|
+
block(
|
|
876
|
+
'richText',
|
|
877
|
+
{ ...BLOCK_CATALOG.richText.defaults(), html: opts.html, size: 'normal' },
|
|
878
|
+
{ width: 'narrow', paddingTop: 'md', paddingBottom: 'md', background: 'white' }
|
|
879
|
+
)
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
|
|
883
|
+
if (opts.cards?.length) {
|
|
884
|
+
blocks.push(
|
|
885
|
+
block(
|
|
886
|
+
'cards',
|
|
887
|
+
{
|
|
888
|
+
...BLOCK_CATALOG.cards.defaults(),
|
|
889
|
+
eyebrow: opts.eyebrow,
|
|
890
|
+
title: opts.cardsTitle || 'Nos prestations',
|
|
891
|
+
highlight: opts.cardsHighlight || 'sur mesure.',
|
|
892
|
+
style: 'hoverDark',
|
|
893
|
+
columns: opts.cards.length === 2 ? 2 : 3,
|
|
894
|
+
items: opts.cards.map((c) => ({
|
|
895
|
+
id: uid('k'),
|
|
896
|
+
icon: c.icon,
|
|
897
|
+
title: c.title,
|
|
898
|
+
text: c.text,
|
|
899
|
+
tags: c.tags || [],
|
|
900
|
+
link: c.link || '/contact/',
|
|
901
|
+
linkLabel: c.linkLabel || 'Demander un échange',
|
|
902
|
+
})),
|
|
903
|
+
},
|
|
904
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'white', animation: 'fade-up' }
|
|
905
|
+
)
|
|
906
|
+
);
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
if (opts.steps?.length) {
|
|
910
|
+
blocks.push(
|
|
911
|
+
block(
|
|
912
|
+
'steps',
|
|
913
|
+
{
|
|
914
|
+
...BLOCK_CATALOG.steps.defaults(),
|
|
915
|
+
eyebrow: 'Méthodologie',
|
|
916
|
+
title: opts.stepsTitle || 'Les étapes de votre dossier',
|
|
917
|
+
style: 'timeline',
|
|
918
|
+
deliverableLabel: 'Étape',
|
|
919
|
+
items: opts.steps.map((s) => ({ id: uid('st'), num: s.num, title: s.title, text: s.text })),
|
|
920
|
+
},
|
|
921
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'soft', animation: 'fade-up' }
|
|
922
|
+
)
|
|
923
|
+
);
|
|
924
|
+
}
|
|
925
|
+
|
|
926
|
+
if (opts.faq?.length) {
|
|
927
|
+
blocks.push(
|
|
928
|
+
block(
|
|
929
|
+
'faq',
|
|
930
|
+
{
|
|
931
|
+
...BLOCK_CATALOG.faq.defaults(),
|
|
932
|
+
eyebrow: 'Questions fréquentes',
|
|
933
|
+
title: 'Tout comprendre',
|
|
934
|
+
highlight: 'avant de démarrer.',
|
|
935
|
+
layout: 'split',
|
|
936
|
+
showContactCard: true,
|
|
937
|
+
items: opts.faq.map((q) => ({ id: uid('q'), question: q.question, answer: q.answer })),
|
|
938
|
+
},
|
|
939
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'white', animation: 'fade-up' }
|
|
940
|
+
)
|
|
941
|
+
);
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
blocks.push(
|
|
945
|
+
block(
|
|
946
|
+
'cta',
|
|
947
|
+
{
|
|
948
|
+
...BLOCK_CATALOG.cta.defaults(),
|
|
949
|
+
variant: 'gradient',
|
|
950
|
+
layout: 'centered',
|
|
951
|
+
eyebrow: 'PRÉVÉRIS · France entière',
|
|
952
|
+
title: 'Parlons de votre',
|
|
953
|
+
highlight: 'établissement.',
|
|
954
|
+
text: 'Un préventionniste dédié analyse votre besoin et vous répond sous 48 h.',
|
|
955
|
+
buttons: [
|
|
956
|
+
button('Prendre contact', '/contact/', 'primary'),
|
|
957
|
+
button('07 44 84 45 19', 'tel:+33744844519', 'secondary', 'none'),
|
|
958
|
+
],
|
|
959
|
+
},
|
|
960
|
+
{ paddingTop: 'lg', paddingBottom: 'lg', background: 'soft', animation: 'fade-up' }
|
|
961
|
+
)
|
|
962
|
+
);
|
|
963
|
+
|
|
964
|
+
return {
|
|
965
|
+
path: opts.path,
|
|
966
|
+
title: `${opts.title} ${opts.highlight || ''}`.trim(),
|
|
967
|
+
blocks,
|
|
968
|
+
seo: {
|
|
969
|
+
seoTitle: `${opts.title} ${opts.highlight || ''} — PRÉVÉRIS`.trim(),
|
|
970
|
+
metaDescription: opts.intro,
|
|
971
|
+
},
|
|
972
|
+
};
|
|
973
|
+
};
|
|
974
|
+
|
|
975
|
+
const pages: ThemePageSeed[] = [
|
|
976
|
+
pvPage({
|
|
977
|
+
path: '/etudes/',
|
|
978
|
+
title: 'Études réglementaires',
|
|
979
|
+
highlight: 'ERP & incendie',
|
|
980
|
+
eyebrow: 'Études',
|
|
981
|
+
image: '/images/photos/preveris-etudes-plans.jpg',
|
|
982
|
+
intro: 'Autorisation de travaux, permis de construire et coordination SSI : des dossiers complets et conformes dès le premier dépôt.',
|
|
983
|
+
cardsTitle: 'Trois pôles d’études',
|
|
984
|
+
cardsHighlight: 'complémentaires.',
|
|
985
|
+
cards: [
|
|
986
|
+
{ icon: 'file-check', title: 'Autorisation de travaux', text: 'Notices sécurité et accessibilité, plans et Cerfa pour déposer en mairie sans stress.', tags: ['AT ERP'], link: '/etudes/autorisation-travaux/', linkLabel: 'Découvrir' },
|
|
987
|
+
{ icon: 'building', title: 'Permis de construire', text: 'Accompagnement de A à Z avec architecte HMONP partenaire et notices réglementaires.', tags: ['PC'], link: '/etudes/permis-construire/', linkLabel: 'Découvrir' },
|
|
988
|
+
{ icon: 'shield', title: 'Coordination SSI', text: 'Conception, cahier des charges fonctionnel, réception technique et dossier d’identité SSI.', tags: ['CSSI'], link: '/etudes/coordination-ssi/', linkLabel: 'Découvrir' },
|
|
989
|
+
],
|
|
990
|
+
}),
|
|
991
|
+
pvPage({
|
|
992
|
+
path: '/etudes/autorisation-travaux/',
|
|
993
|
+
title: 'Autorisation de travaux',
|
|
994
|
+
highlight: 'ERP sans retard',
|
|
995
|
+
eyebrow: 'Études · AT ERP',
|
|
996
|
+
parentLabel: 'Études',
|
|
997
|
+
parentLink: '/etudes/',
|
|
998
|
+
image: '/images/photos/preveris-etudes-plans.jpg',
|
|
999
|
+
intro: 'Nous constituons pour vous un dossier complet (plans, notices sécurité et accessibilité, Cerfa) pour déposer en mairie un projet conforme. 95 % des dossiers validés dès le premier dépôt.',
|
|
1000
|
+
cardsTitle: 'Quand déposer',
|
|
1001
|
+
cardsHighlight: 'une AT ERP ?',
|
|
1002
|
+
cards: [
|
|
1003
|
+
{ icon: 'building', title: 'Construction ou aménagement', text: 'Tout réaménagement des circulations, cloisonnements, dégagements ou création d’ERP.', tags: ['Neuf & aménagement'] },
|
|
1004
|
+
{ icon: 'sparkles', title: 'Changement de destination', text: 'Local transformé en restaurant, commerce, cabinet ou établissement recevant du public.', tags: ['Transformation'] },
|
|
1005
|
+
{ icon: 'shieldCheck', title: 'Mise en conformité', text: 'Travaux correctifs après prescriptions de la commission de sécurité ou d’accessibilité.', tags: ['Prescriptions'] },
|
|
1006
|
+
],
|
|
1007
|
+
stepsTitle: 'Les 5 étapes de votre autorisation de travaux',
|
|
1008
|
+
steps: [
|
|
1009
|
+
{ num: '01', title: 'Analyse réglementaire préalable', text: 'Classement (type et catégorie), textes applicables et diagnostic de l’existant.' },
|
|
1010
|
+
{ num: '02', title: 'Constitution du dossier technique', text: 'Plans cotés, notices sécurité incendie et accessibilité, calculs d’effectifs et Cerfa.' },
|
|
1011
|
+
{ num: '03', title: 'Dépôt en mairie', text: 'Transmission en mairie et suivi de la complétude auprès de la sous-commission.' },
|
|
1012
|
+
{ num: '04', title: 'Commission de sécurité', text: 'Instruction (4 mois max) et avis des commissions sécurité et accessibilité.' },
|
|
1013
|
+
{ num: '05', title: 'Réception & ouverture', text: 'Assistance à la visite d’ouverture et obtention de l’arrêté municipal.' },
|
|
1014
|
+
],
|
|
1015
|
+
faq: [
|
|
1016
|
+
{ question: 'Quel est le coût d’un dossier d’autorisation de travaux ?', answer: '<p>À partir de 1 000 € HT selon la complexité et la catégorie de l’ERP (jusqu’à 3 000–4 000 € HT pour les projets complexes). Devis gratuit après un premier échange.</p>' },
|
|
1017
|
+
{ question: 'Quel est le délai de réalisation ?', answer: '<p>10 à 30 jours calendaires (environ 20 jours en moyenne) pour constituer le dossier complet.</p>' },
|
|
1018
|
+
{ question: 'Peut-on ouvrir sans attendre l’autorisation ?', answer: '<p>Non : ouvrir sans autorisation constitue une infraction pénale (art. L. 122-5 du CCH) et expose à une fermeture administrative immédiate.</p>' },
|
|
1019
|
+
{ question: 'Et si je n’ai pas de plans ?', answer: '<p>Un dessinateur se déplace pour effectuer les relevés géométriques ou nous travaillons à partir des plans de votre architecte.</p>' },
|
|
1020
|
+
],
|
|
1021
|
+
}),
|
|
1022
|
+
pvPage({
|
|
1023
|
+
path: '/etudes/permis-construire/',
|
|
1024
|
+
title: 'Permis de construire',
|
|
1025
|
+
highlight: 'ERP clé en main',
|
|
1026
|
+
eyebrow: 'Études · Urbanisme & ERP',
|
|
1027
|
+
parentLabel: 'Études',
|
|
1028
|
+
parentLink: '/etudes/',
|
|
1029
|
+
image: '/images/photos/preveris-etudes-plans.jpg',
|
|
1030
|
+
intro: 'Un accompagnement de A à Z pour les maîtres d’ouvrage et les architectes : plans d’architecture HMONP, notices sécurité incendie et accessibilité, formulaires Cerfa.',
|
|
1031
|
+
cardsTitle: 'Contenu du pack',
|
|
1032
|
+
cardsHighlight: 'permis de construire.',
|
|
1033
|
+
cards: [
|
|
1034
|
+
{ icon: 'layers', title: 'Plans d’architecture', text: 'Relevés géométriques sur site et plans de l’existant et du projet par nos architectes HMONP partenaires.', tags: ['Architecte HMONP'] },
|
|
1035
|
+
{ icon: 'shield', title: 'Notice de sécurité incendie', text: 'Classement, nouvel effectif, dégagements, désenfumage et conformité de l’alarme.', tags: ['Sécurité'] },
|
|
1036
|
+
{ icon: 'check-circle', title: 'Notice d’accessibilité & Cerfa', text: 'Chaîne du déplacement PMR, dérogations éventuelles et formulaires administratifs complets.', tags: ['Accessibilité'] },
|
|
1037
|
+
],
|
|
1038
|
+
stepsTitle: 'Préparer votre permis avec PRÉVÉRIS',
|
|
1039
|
+
steps: [
|
|
1040
|
+
{ num: '01', title: 'Étude de faisabilité & relevés', text: 'Déplacement sur site, relevés géométriques et analyse des contraintes financières et techniques.' },
|
|
1041
|
+
{ num: '02', title: 'Conception concertée', text: 'Échanges continus entre architecte et préventionniste ; validation des plans aménagés.' },
|
|
1042
|
+
{ num: '03', title: 'Dépôt & suivi (5 mois max)', text: 'Dépôt en mairie du dossier complet et suivi jusqu’à l’arrêté de permis.' },
|
|
1043
|
+
],
|
|
1044
|
+
}),
|
|
1045
|
+
pvPage({
|
|
1046
|
+
path: '/etudes/coordination-ssi/',
|
|
1047
|
+
title: 'Coordination SSI',
|
|
1048
|
+
highlight: '(CSSI)',
|
|
1049
|
+
eyebrow: 'Études · Système de Sécurité Incendie',
|
|
1050
|
+
parentLabel: 'Études',
|
|
1051
|
+
parentLink: '/etudes/',
|
|
1052
|
+
image: '/images/photos/preveris-ssi-incendie.jpg',
|
|
1053
|
+
intro: 'Concevoir le système d’alarme et de mise en sécurité incendie adapté à votre ERP. Tous nos dossiers sont supervisés par un préventionniste expert, ancien officier de sapeurs-pompiers.',
|
|
1054
|
+
cardsTitle: 'Mission complète',
|
|
1055
|
+
cardsHighlight: 'de coordination SSI.',
|
|
1056
|
+
cards: [
|
|
1057
|
+
{ icon: 'file-text', title: 'Cahier des charges fonctionnel', text: 'Analyse du projet, définition des zones de détection/mise en sécurité et cahier des charges pour l’installateur.', tags: ['Phase conception'] },
|
|
1058
|
+
{ icon: 'check-square', title: 'Réception & essais techniques', text: 'Contrôle point par point de toute la chaîne de sécurité incendie et rapport de réception technique.', tags: ['Phase réalisation'] },
|
|
1059
|
+
{ icon: 'book-open', title: 'Dossier d’identité SSI', text: 'Constitution de la carte d’identité du SSI (consignes, plans, schémas, notices) et assistance en commission.', tags: ['Livraison'] },
|
|
1060
|
+
],
|
|
1061
|
+
}),
|
|
1062
|
+
pvPage({
|
|
1063
|
+
path: '/suivi/',
|
|
1064
|
+
title: 'Suivi réglementaire',
|
|
1065
|
+
highlight: 'de vos établissements',
|
|
1066
|
+
eyebrow: 'Suivi',
|
|
1067
|
+
image: '/images/photos/preveris-ssi-incendie.jpg',
|
|
1068
|
+
intro: 'Maintenez la conformité de vos ERP toute l’année : suivi technique annuel, mission de Responsable Unique de Sécurité (RUS) et veille dédiée aux hôtels.',
|
|
1069
|
+
cardsTitle: 'Trois formules',
|
|
1070
|
+
cardsHighlight: 'de suivi.',
|
|
1071
|
+
cards: [
|
|
1072
|
+
{ icon: 'calendar', title: 'Suivi annuel', text: 'Visites annuelles, tenue du registre de sécurité et présence lors des commissions.', tags: ['ERP'], link: '/suivi/annuel/', linkLabel: 'Découvrir' },
|
|
1073
|
+
{ icon: 'users', title: 'Responsable Unique de Sécurité', text: 'Externalisation complète de la mission RUS pour centres commerciaux et groupements.', tags: ['RUS'], link: '/suivi/rus/', linkLabel: 'Découvrir' },
|
|
1074
|
+
{ icon: 'building', title: 'Suivi hôtel (type O)', text: 'Veille renforcée pour les établissements avec locaux à sommeil.', tags: ['Hôtellerie'], link: '/suivi/hotel/', linkLabel: 'Découvrir' },
|
|
1075
|
+
],
|
|
1076
|
+
}),
|
|
1077
|
+
pvPage({
|
|
1078
|
+
path: '/suivi/annuel/',
|
|
1079
|
+
title: 'Suivi technique annuel',
|
|
1080
|
+
highlight: 'incendie & ERP',
|
|
1081
|
+
eyebrow: 'Suivi · Accompagnement annuel',
|
|
1082
|
+
parentLabel: 'Suivi',
|
|
1083
|
+
parentLink: '/suivi/',
|
|
1084
|
+
image: '/images/photos/preveris-hero-erp.jpg',
|
|
1085
|
+
intro: 'Ne craignez plus les commissions de sécurité. Un binôme référent (agent administratif + préventionniste) suit votre registre, prépare vos contrôles et vous assiste le jour J.',
|
|
1086
|
+
cardsTitle: 'Votre protection',
|
|
1087
|
+
cardsHighlight: 'au quotidien.',
|
|
1088
|
+
cards: [
|
|
1089
|
+
{ icon: 'shield', title: 'Préparation des commissions', text: 'Suivi constant du registre, présence pendant la visite et proposition de solutions alternatives maîtrisant les coûts.', tags: ['Commission'] },
|
|
1090
|
+
{ icon: 'file-check', title: 'Protection juridique', text: 'Traçabilité des opérations de maintenance et de formation pour vous prémunir de toute mise en cause.', tags: ['Traçabilité'] },
|
|
1091
|
+
{ icon: 'users', title: 'Binôme référent dédié', text: 'Visite annuelle par un préventionniste avec rapport détaillé et suivi administratif régulier.', tags: ['Proximité'] },
|
|
1092
|
+
],
|
|
1093
|
+
}),
|
|
1094
|
+
pvPage({
|
|
1095
|
+
path: '/suivi/rus/',
|
|
1096
|
+
title: 'Responsable Unique de Sécurité',
|
|
1097
|
+
highlight: '(RUS externalisé)',
|
|
1098
|
+
eyebrow: 'Suivi · Groupements d’ERP',
|
|
1099
|
+
parentLabel: 'Suivi',
|
|
1100
|
+
parentLink: '/suivi/',
|
|
1101
|
+
image: '/images/photos/preveris-accessibilite-erp.jpg',
|
|
1102
|
+
intro: 'Plus de 50 groupements et centres commerciaux suivis en France. PRÉVÉRIS assume la mission réglementaire de RUS avec neutralité, expertise d’officiers préventionnistes et pérennité.',
|
|
1103
|
+
cardsTitle: 'Missions réglementaires',
|
|
1104
|
+
cardsHighlight: 'du RUS.',
|
|
1105
|
+
cards: [
|
|
1106
|
+
{ icon: 'shieldCheck', title: 'Commissions & registre unique', text: 'Accueil de la commission de sécurité, ouverture et mise à jour du registre (art. R 143-44 CCH) et rédaction du SOGS.', tags: ['R 143-44 CCH'] },
|
|
1107
|
+
{ icon: 'file-text', title: 'Visa des dossiers preneurs', text: 'Examen et visa des dossiers d’AT/PC des cellules, suivi des RVRAT et transmission au maire.', tags: ['Cellules'] },
|
|
1108
|
+
{ icon: 'check-circle', title: 'Contrôles & vérifications', text: 'Vérification des contrats de maintenance, permanence SSIAP, exercices d’évacuation et levée des prescriptions.', tags: ['Terrain'] },
|
|
1109
|
+
],
|
|
1110
|
+
}),
|
|
1111
|
+
pvPage({
|
|
1112
|
+
path: '/suivi/hotel/',
|
|
1113
|
+
title: 'Suivi sécurité incendie',
|
|
1114
|
+
highlight: 'des hôtels (type O)',
|
|
1115
|
+
eyebrow: 'Suivi · Locaux à sommeil',
|
|
1116
|
+
parentLabel: 'Suivi',
|
|
1117
|
+
parentLink: '/suivi/',
|
|
1118
|
+
image: '/images/photos/preveris-suivi-hotel.jpg',
|
|
1119
|
+
intro: '« Dormez sur vos deux oreilles » : PRÉVÉRIS veille sur la conformité de vos hôtels face aux risques d’incendie et de fermeture administrative (visites périodiques tous les 3 ou 5 ans et visites inopinées).',
|
|
1120
|
+
cardsTitle: 'Nos missions',
|
|
1121
|
+
cardsHighlight: 'auprès des hôteliers.',
|
|
1122
|
+
cards: [
|
|
1123
|
+
{ icon: 'calendar', title: 'Visites annuelles sur site', text: 'Inspection complète de chaque hôtel par un préventionniste et remise d’un rapport d’audit détaillé.', tags: ['Type O'] },
|
|
1124
|
+
{ icon: 'clipboard', title: 'Suivi externalisé de la maintenance', text: 'Tenue administrative du registre de sécurité, suivi du système de détection incendie et des vérifications périodiques.', tags: ['SDI / Alarme'] },
|
|
1125
|
+
{ icon: 'shield', title: 'Soutien en commission', text: 'Préparation du passage de la commission de sécurité et présence à vos côtés le jour de la visite.', tags: ['Sérénité'] },
|
|
1126
|
+
],
|
|
1127
|
+
}),
|
|
1128
|
+
pvPage({
|
|
1129
|
+
path: '/assistance/',
|
|
1130
|
+
title: 'Assistance & audits',
|
|
1131
|
+
highlight: 'réglementaires ERP',
|
|
1132
|
+
eyebrow: 'Assistance',
|
|
1133
|
+
image: '/images/photos/preveris-accessibilite-erp.jpg',
|
|
1134
|
+
intro: 'Audit d’accessibilité, rédaction de documents obligatoires, missions ponctuelles et consultations d’experts en visioconférence.',
|
|
1135
|
+
cardsTitle: 'Nos prestations',
|
|
1136
|
+
cardsHighlight: 'd’assistance.',
|
|
1137
|
+
cards: [
|
|
1138
|
+
{ icon: 'check-circle', title: 'Audit accessibilité', text: 'Diagnostic complet de conformité PMR et demandes de dérogations motivées.', link: '/assistance/audit-accessibilite/', linkLabel: 'Découvrir' },
|
|
1139
|
+
{ icon: 'file-text', title: 'Documents administratifs', text: 'GE5, procédure GN8, SOGS, plans d’évacuation/intervention, registre et main courante SSI.', link: '/assistance/documents/', linkLabel: 'Découvrir' },
|
|
1140
|
+
{ icon: 'zap', title: 'Missions ponctuelles & Conseil', text: 'Assistance en commission, étude de désenfumage, AMO et visio-conseil dès 100 € TTC.', link: '/assistance/missions-ponctuelles/', linkLabel: 'Découvrir' },
|
|
1141
|
+
],
|
|
1142
|
+
}),
|
|
1143
|
+
pvPage({
|
|
1144
|
+
path: '/assistance/audit-accessibilite/',
|
|
1145
|
+
title: 'Audit accessibilité',
|
|
1146
|
+
highlight: 'rendre vos ERP accessibles',
|
|
1147
|
+
eyebrow: 'Assistance · Accessibilité PMR',
|
|
1148
|
+
parentLabel: 'Assistance',
|
|
1149
|
+
parentLink: '/assistance/',
|
|
1150
|
+
image: '/images/photos/preveris-accessibilite-erp.jpg',
|
|
1151
|
+
intro: 'Rendre les ERP accessibles est une obligation légale (jusqu’à 45 000 € d’amende) qui couvre tous les types de handicap, visibles ou invisibles. PRÉVÉRIS réalise votre diagnostic et instruit vos demandes de dérogation.',
|
|
1152
|
+
cardsTitle: 'Les + de PRÉVÉRIS',
|
|
1153
|
+
cardsHighlight: 'en accessibilité.',
|
|
1154
|
+
cards: [
|
|
1155
|
+
{ icon: 'search', title: 'Diagnostic complet sur site', text: 'Cheminements extérieurs, stationnement, accès, circulations, sanitaires et équipements analysés point par point.', tags: ['Loi 2005'] },
|
|
1156
|
+
{ icon: 'file-check', title: 'Dérogations argumentées', text: 'Dossiers de dérogation pour impossibilité technique, disproportion manifeste ou préservation du patrimoine.', tags: ['CCDSA'] },
|
|
1157
|
+
{ icon: 'users', title: 'Approche globale & coûts maîtrisés', text: 'Prise en compte simultanée de la sécurité incendie et du code du travail, avec présence en commission.', tags: ['Économie'] },
|
|
1158
|
+
],
|
|
1159
|
+
}),
|
|
1160
|
+
pvPage({
|
|
1161
|
+
path: '/assistance/documents/',
|
|
1162
|
+
title: 'Documents administratifs',
|
|
1163
|
+
highlight: 'obligatoires en ERP',
|
|
1164
|
+
eyebrow: 'Assistance · Conformité documentaire',
|
|
1165
|
+
parentLabel: 'Assistance',
|
|
1166
|
+
parentLink: '/assistance/',
|
|
1167
|
+
image: '/images/photos/preveris-etudes-plans.jpg',
|
|
1168
|
+
intro: 'Affichage GE5, procédure d’évacuation GN8, SOGS, plans d’évacuation et d’intervention, registre de sécurité et main courante SSI : nous rédigeons vos documents réglementaires sur mesure.',
|
|
1169
|
+
cardsTitle: 'Documents réalisés',
|
|
1170
|
+
cardsHighlight: 'par nos experts.',
|
|
1171
|
+
cards: [
|
|
1172
|
+
{ icon: 'file-text', title: 'Procédure GN8 & SOGS', text: 'Organisation de l’évacuation des personnes en situation de handicap (GN8) et Schéma d’Organisation Globale de la Sécurité (art. M 31).', tags: ['GN8 · SOGS'] },
|
|
1173
|
+
{ icon: 'map', title: 'Plans d’évacuation & d’intervention', text: 'Plans réglementaires pour les occupants et plans d’intervention détaillant zones à risques et coupures pour les secours.', tags: ['Plans'] },
|
|
1174
|
+
{ icon: 'book', title: 'Registre & main courante SSI', text: 'Classeur registre de sécurité personnalisé, affichage GE5 d’entrée et main courante annuelle SSI (catégories A et B).', tags: ['Registres'] },
|
|
1175
|
+
],
|
|
1176
|
+
}),
|
|
1177
|
+
pvPage({
|
|
1178
|
+
path: '/assistance/missions-ponctuelles/',
|
|
1179
|
+
title: 'Missions ponctuelles',
|
|
1180
|
+
highlight: 'études, audits & commissions',
|
|
1181
|
+
eyebrow: 'Assistance · Interventions ciblées',
|
|
1182
|
+
parentLabel: 'Assistance',
|
|
1183
|
+
parentLink: '/assistance/',
|
|
1184
|
+
image: '/images/photos/preveris-ssi-incendie.jpg',
|
|
1185
|
+
intro: 'Nos préventionnistes accompagnent les exploitants avant, pendant et après la visite de la commission de sécurité, ou sur des problématiques techniques ciblées.',
|
|
1186
|
+
cardsTitle: 'Interventions',
|
|
1187
|
+
cardsHighlight: 'à la carte.',
|
|
1188
|
+
cards: [
|
|
1189
|
+
{ icon: 'shield', title: 'Assistance commission de sécurité', text: 'Audit préalable, recommandations et présence aux côtés du chef d’établissement lors des visites d’ouverture, périodiques ou inopinées.', tags: ['Visite'] },
|
|
1190
|
+
{ icon: 'wind', title: 'Étude de désenfumage (IT 246)', text: 'Dimensionnement au plus juste des extracteurs de fumées et amenées d’air par nos préventionnistes spécialisés.', tags: ['Désenfumage'] },
|
|
1191
|
+
{ icon: 'compass', title: 'Audit avant acquisition & AMO', text: 'Rapport d’écarts réglementaires avant bail ou rachat, suivi de chantier et interface avec le bureau de contrôle.', tags: ['AMO'] },
|
|
1192
|
+
],
|
|
1193
|
+
}),
|
|
1194
|
+
pvPage({
|
|
1195
|
+
path: '/assistance/conseil-erp/',
|
|
1196
|
+
title: 'Conseil en réglementation ERP',
|
|
1197
|
+
highlight: 'en visioconférence',
|
|
1198
|
+
eyebrow: 'Assistance · Visio expert',
|
|
1199
|
+
parentLabel: 'Assistance',
|
|
1200
|
+
parentLink: '/assistance/',
|
|
1201
|
+
image: '/images/photos/preveris-hero-erp.jpg',
|
|
1202
|
+
intro: 'Réponses claires et rapides : un préventionniste expert vous reçoit en visio pour analyser votre cas précis, lever un avis défavorable ou valider la faisabilité d’un projet. Montant déduit si vous nous confiez la mission.',
|
|
1203
|
+
cardsTitle: 'Trois formats',
|
|
1204
|
+
cardsHighlight: 'réservables en ligne.',
|
|
1205
|
+
cards: [
|
|
1206
|
+
{ icon: 'clock', title: '30 min — 100 € TTC', text: 'Traitement d’un avis défavorable, lecture de prescriptions ou question réglementaire ciblée.', tags: ['Avis défavorable'] },
|
|
1207
|
+
{ icon: 'message-circle', title: '45 min — 180 € TTC', text: 'Consultation générale ERP : ouverture d’un commerce, classement, obligations incendie et accessibilité.', tags: ['Faisabilité'] },
|
|
1208
|
+
{ icon: 'shieldCheck', title: '1h30 — 360 € TTC', text: 'Préparation approfondie à une commission de sécurité ou analyse d’une mise en demeure.', tags: ['Commission'] },
|
|
1209
|
+
],
|
|
1210
|
+
}),
|
|
1211
|
+
pvPage({
|
|
1212
|
+
path: '/collectivites/',
|
|
1213
|
+
title: 'Services aux collectivités',
|
|
1214
|
+
highlight: '« Vous décidez, nous éclairons »',
|
|
1215
|
+
eyebrow: 'Collectivités · 31 communes accompagnées',
|
|
1216
|
+
image: '/images/photos/preveris-collectivites.jpg',
|
|
1217
|
+
intro: 'Service externalisé d’expertise réglementaire pour mairies et EPCI : instruction des AT ERP de 5e catégorie sous 30 jours (complétude 48 h), appui ADS, secrétariat de commissions CCSA, audits du patrimoine, PPMS et PCS.',
|
|
1218
|
+
cardsTitle: 'Quatre piliers',
|
|
1219
|
+
cardsHighlight: 'pour vos services.',
|
|
1220
|
+
cards: [
|
|
1221
|
+
{ icon: 'file-check', title: 'Instruction AT ERP 5e catégorie', text: 'Près de 1 000 dossiers instruits. Rapport motivé par volet (sécurité incendie & accessibilité) sous 30 jours, sans engagement de volume.', tags: ['Complétude 48 h'] },
|
|
1222
|
+
{ icon: 'users', title: 'Appui ADS & Commissions CCSA', text: 'Expert ERP aux côtés de vos instructeurs, secrétariat complet des commissions communales et visites préparatoires.', tags: ['Mairies & EPCI'] },
|
|
1223
|
+
{ icon: 'building', title: 'Patrimoine, AMO, PPMS & PCS', text: 'Audit et régularisation des ERP communaux, AMO préventionniste, Plan Communal de Sauvegarde et formation des agents.', tags: ['Patrimoine public'] },
|
|
1224
|
+
],
|
|
1225
|
+
stepsTitle: 'Instruction d’un dossier AT 5e catégorie',
|
|
1226
|
+
steps: [
|
|
1227
|
+
{ num: '01', title: 'Réception & complétude (48 h)', text: 'Vérification des pièces obligatoires sous 48 h ouvrées et qualification réglementaire.' },
|
|
1228
|
+
{ num: '02', title: 'Analyse incendie & accessibilité', text: 'Instruction technique indépendante par des préventionnistes issus des commissions de sécurité.' },
|
|
1229
|
+
{ num: '03', title: 'Rapport motivé & décision du Maire', text: 'Remise d’un rapport opposable avec avis proposé et prescriptions ; la collectivité reste seule décisionnaire.' },
|
|
1230
|
+
],
|
|
1231
|
+
faq: [
|
|
1232
|
+
{ question: 'Faut-il passer un marché public formalisé ?', answer: '<p>Les prestations sont facturées au forfait par dossier via une convention-cadre de 3 ans et des bons de commande Chorus Pro, sans abonnement ni engagement de volume.</p>' },
|
|
1233
|
+
{ question: 'Qui signe l’autorisation ou l’arrêté ?', answer: '<p>Toujours l’autorité compétente (le Maire). PRÉVÉRIS éclaire la décision par un rapport motivé mais ne se substitue jamais à la collectivité.</p>' },
|
|
1234
|
+
{ question: 'Quelles collectivités nous font confiance ?', answer: '<p>31 collectivités dont Meaux, Bondy, Sèvres, Conflans-Sainte-Honorine, Montereau-Fault-Yonne, Romainville, Serris, ainsi que des institutions publiques et culturelles de premier plan.</p>' },
|
|
1235
|
+
],
|
|
1236
|
+
}),
|
|
1237
|
+
pvPage({
|
|
1238
|
+
path: '/blog/',
|
|
1239
|
+
title: 'Ressources & guides',
|
|
1240
|
+
highlight: 'sécurité incendie et ERP',
|
|
1241
|
+
eyebrow: 'Blog PRÉVÉRIS',
|
|
1242
|
+
image: '/images/photos/preveris-etudes-plans.jpg',
|
|
1243
|
+
intro: 'Décryptages réglementaires, retours d’expérience et guides pratiques rédigés par nos préventionnistes pour les exploitants d’ERP et les collectivités.',
|
|
1244
|
+
cardsTitle: 'Guides essentiels',
|
|
1245
|
+
cardsHighlight: 'à consulter.',
|
|
1246
|
+
cards: [
|
|
1247
|
+
{ icon: 'alert-triangle', title: 'Avis défavorable de la commission : que faire ?', text: 'Comprendre les prescriptions, organiser la levée des réserves et éviter la fermeture administrative.', tags: ['Commission'], link: '/assistance/conseil-erp/', linkLabel: 'Consulter un expert' },
|
|
1248
|
+
{ icon: 'wind', title: 'Comprendre le désenfumage dans un ERP', text: 'Naturel ou mécanique, IT 246, seuils d’obligation et erreurs de dimensionnement à éviter.', tags: ['Technique'], link: '/assistance/missions-ponctuelles/', linkLabel: 'Étude désenfumage' },
|
|
1249
|
+
{ icon: 'file-check', title: 'Autorisation de travaux ERP : guide complet', text: 'Procédure, délais d’instruction, pièces obligatoires et différences entre 1er et 2e groupe.', tags: ['Dossier AT'], link: '/etudes/autorisation-travaux/', linkLabel: 'Monter mon dossier' },
|
|
1250
|
+
{ icon: 'building', title: 'ADS mutualisé & instruction AT 5e catégorie', text: 'Comment sécuriser l’instruction des dossiers ERP des communes membres sans alourdir les équipes.', tags: ['Collectivités'], link: '/collectivites/', linkLabel: 'Offre collectivités' },
|
|
1251
|
+
{ icon: 'check-circle', title: 'Obligations d’accessibilité ERP & EAS', text: 'Normes PMR, espaces d’attente sécurisés (EAS), attestations et cas de dérogation.', tags: ['Accessibilité'], link: '/assistance/audit-accessibilite/', linkLabel: 'Audit PMR' },
|
|
1252
|
+
{ icon: 'shield', title: 'Externaliser la mission de RUS', text: 'Responsabilités en centre commercial et groupement d’ERP, registre unique et SOGS.', tags: ['RUS'], link: '/suivi/rus/', linkLabel: 'Mission RUS' },
|
|
1253
|
+
],
|
|
1254
|
+
}),
|
|
1255
|
+
];
|
|
1256
|
+
|
|
1257
|
+
return {
|
|
1258
|
+
version: 1,
|
|
1259
|
+
themeId: 'hamdiayari.preveris',
|
|
1260
|
+
savedAt: new Date().toISOString(),
|
|
1261
|
+
home: {
|
|
1262
|
+
title: 'Accueil',
|
|
1263
|
+
blocks: homeBlocks,
|
|
1264
|
+
seo: {
|
|
1265
|
+
seoTitle: 'PRÉVÉRIS — Bureau d’études sécurité incendie et accessibilité ERP',
|
|
1266
|
+
metaDescription:
|
|
1267
|
+
'Bureau d’études spécialisé sécurité incendie et accessibilité des ERP. Autorisation de travaux, SSI, RUS, suivi annuel et appui aux collectivités.',
|
|
1268
|
+
ogTitle: 'PRÉVÉRIS — Sécurité incendie & accessibilité ERP',
|
|
1269
|
+
ogDescription: 'Garantir l’ouverture de votre ERP dans un temps et un budget maîtrisés.',
|
|
1270
|
+
},
|
|
1271
|
+
},
|
|
1272
|
+
pages,
|
|
1273
|
+
menus: classicMenus({
|
|
1274
|
+
primary: [
|
|
1275
|
+
{
|
|
1276
|
+
id: 'm-etudes',
|
|
1277
|
+
label: 'Études',
|
|
1278
|
+
path: '/etudes/',
|
|
1279
|
+
children: [
|
|
1280
|
+
{ id: 'm-at', label: 'Autorisation de travaux', path: '/etudes/autorisation-travaux/' },
|
|
1281
|
+
{ id: 'm-pc', label: 'Permis de construire', path: '/etudes/permis-construire/' },
|
|
1282
|
+
{ id: 'm-ssi', label: 'Coordination SSI', path: '/etudes/coordination-ssi/' },
|
|
1283
|
+
],
|
|
1284
|
+
},
|
|
1285
|
+
{
|
|
1286
|
+
id: 'm-suivi',
|
|
1287
|
+
label: 'Suivi',
|
|
1288
|
+
path: '/suivi/',
|
|
1289
|
+
children: [
|
|
1290
|
+
{ id: 'm-annuel', label: 'Suivi annuel', path: '/suivi/annuel/' },
|
|
1291
|
+
{ id: 'm-rus', label: 'Responsable Unique de Sécurité', path: '/suivi/rus/' },
|
|
1292
|
+
{ id: 'm-hotel', label: 'Suivi hôtel', path: '/suivi/hotel/' },
|
|
1293
|
+
],
|
|
1294
|
+
},
|
|
1295
|
+
{
|
|
1296
|
+
id: 'm-assist',
|
|
1297
|
+
label: 'Assistance',
|
|
1298
|
+
path: '/assistance/',
|
|
1299
|
+
children: [
|
|
1300
|
+
{ id: 'm-audit', label: 'Audit accessibilité', path: '/assistance/audit-accessibilite/' },
|
|
1301
|
+
{ id: 'm-docs', label: 'Documents administratifs', path: '/assistance/documents/' },
|
|
1302
|
+
{ id: 'm-ponct', label: 'Missions ponctuelles', path: '/assistance/missions-ponctuelles/' },
|
|
1303
|
+
{ id: 'm-conseil', label: 'Conseil ERP', path: '/assistance/conseil-erp/' },
|
|
1304
|
+
],
|
|
1305
|
+
},
|
|
1306
|
+
{ id: 'm-coll', label: 'Collectivités', path: '/collectivites/' },
|
|
1307
|
+
{ id: 'm-blog', label: 'Blog', path: '/blog/' },
|
|
1308
|
+
{ id: 'm-contact', label: 'Contact', path: '/contact/', highlight: true },
|
|
1309
|
+
],
|
|
1310
|
+
footer: [
|
|
1311
|
+
{ id: 'f-etudes', label: 'Études', path: '/etudes/' },
|
|
1312
|
+
{ id: 'f-suivi', label: 'Suivi', path: '/suivi/' },
|
|
1313
|
+
{ id: 'f-assist', label: 'Assistance', path: '/assistance/' },
|
|
1314
|
+
{ id: 'f-coll', label: 'Collectivités', path: '/collectivites/' },
|
|
1315
|
+
{ id: 'f-blog', label: 'Blog', path: '/blog/' },
|
|
1316
|
+
{ id: 'f-contact', label: 'Contact', path: '/contact/', highlight: true },
|
|
1317
|
+
{ id: 'f-legal', label: 'Mentions légales', path: '/mentions-legales/' },
|
|
1318
|
+
{ id: 'f-privacy', label: 'Confidentialité', path: '/politique-de-confidentialite/' },
|
|
1319
|
+
{ id: 'f-cookies', label: 'Cookies', path: '/cookies/' },
|
|
1320
|
+
],
|
|
1321
|
+
}),
|
|
1322
|
+
branding: {
|
|
1323
|
+
siteName: 'PRÉVÉRIS',
|
|
1324
|
+
tagline: 'Sécurité incendie & accessibilité ERP',
|
|
1325
|
+
colors: {
|
|
1326
|
+
primary: '#E85D04',
|
|
1327
|
+
primaryHover: '#C2410C',
|
|
1328
|
+
accent: '#F48C06',
|
|
1329
|
+
navy: '#0A101D',
|
|
1330
|
+
background: '#F8F9FC',
|
|
1331
|
+
text: '#0A101D',
|
|
1332
|
+
muted: '#556078',
|
|
1333
|
+
border: '#E2E6F0',
|
|
1334
|
+
},
|
|
1335
|
+
fonts: {
|
|
1336
|
+
heading: 'Poppins',
|
|
1337
|
+
body: 'Poppins',
|
|
1338
|
+
},
|
|
1339
|
+
},
|
|
1340
|
+
};
|
|
1341
|
+
}
|
|
1342
|
+
|
|
1343
|
+
async function defaultPackFor(themeId: string): Promise<ThemeContentPack | null> {
|
|
1344
|
+
if (themeId === 'novalabs.mahdia') return buildMahdiaPack();
|
|
1345
|
+
if (themeId === 'novalabs.dogga') return buildDoggaPack();
|
|
1346
|
+
if (themeId === 'novalabs.sidibou') return loadSidibouDefault();
|
|
1347
|
+
if (themeId === 'hamdiayari.preveris') return buildPreverisPack();
|
|
1348
|
+
return null;
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
/** Installe les packs par défaut s’ils n’existent pas encore. */
|
|
1352
|
+
export async function ensureDefaultThemePacks(): Promise<void> {
|
|
1353
|
+
for (const id of ['novalabs.sidibou', 'novalabs.dogga', 'novalabs.mahdia', 'hamdiayari.preveris'] as const) {
|
|
1354
|
+
const existing = await readThemePack(id);
|
|
1355
|
+
if (existing) continue;
|
|
1356
|
+
const pack = await defaultPackFor(id);
|
|
1357
|
+
if (pack) {
|
|
1358
|
+
await writeThemePack(pack);
|
|
1359
|
+
console.log(`[themes] pack contenu par défaut : ${id}`);
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
}
|
|
1363
|
+
|
|
1364
|
+
/**
|
|
1365
|
+
* Avant d’activer `nextId` : sauvegarde le contenu du thème courant,
|
|
1366
|
+
* puis restaure le pack du thème cible.
|
|
1367
|
+
*/
|
|
1368
|
+
export async function switchThemeContent(previousThemeId: string | null, nextThemeId: string): Promise<void> {
|
|
1369
|
+
await ensureDefaultThemePacks();
|
|
1370
|
+
if (previousThemeId && previousThemeId !== nextThemeId) {
|
|
1371
|
+
try {
|
|
1372
|
+
await captureLiveThemeContent(previousThemeId);
|
|
1373
|
+
console.log(`[themes] contenu sauvegardé pour ${previousThemeId}`);
|
|
1374
|
+
} catch (e) {
|
|
1375
|
+
console.error(`[themes] sauvegarde contenu ${previousThemeId} impossible`, e);
|
|
1376
|
+
}
|
|
1377
|
+
}
|
|
1378
|
+
const pack = (await readThemePack(nextThemeId)) || (await defaultPackFor(nextThemeId));
|
|
1379
|
+
if (!pack) {
|
|
1380
|
+
console.warn(`[themes] pas de pack contenu pour ${nextThemeId} — contenu laissé tel quel`);
|
|
1381
|
+
return;
|
|
1382
|
+
}
|
|
1383
|
+
if (!(await readThemePack(nextThemeId))) await writeThemePack(pack);
|
|
1384
|
+
await applyThemePack(pack);
|
|
1385
|
+
console.log(`[themes] contenu restauré pour ${nextThemeId} (${pack.home.blocks.length} blocs)`);
|
|
1386
|
+
}
|