create-snapify-app 0.0.0-stage → 1.1.0
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 +33 -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 +100 -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,74 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "snapify",
|
|
3
|
+
"private": true,
|
|
4
|
+
"version": "1.1.0",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"author": "NOVALABS WEB DESIGN <contact@novalabs.tn>",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"scripts": {
|
|
9
|
+
"dev": "tsx server.ts",
|
|
10
|
+
"start": "node server.ts",
|
|
11
|
+
"build": "vite build",
|
|
12
|
+
"preview": "vite preview",
|
|
13
|
+
"clean": "rm -rf dist server.js",
|
|
14
|
+
"lint": "tsc --noEmit --pretty false",
|
|
15
|
+
"db:up": "docker compose -f docker-compose.db.yml --env-file .env up -d",
|
|
16
|
+
"db:generate": "drizzle-kit generate",
|
|
17
|
+
"db:studio": "drizzle-kit studio",
|
|
18
|
+
"db:backup": "scripts/db-backup.sh",
|
|
19
|
+
"db:restore": "scripts/db-restore.sh",
|
|
20
|
+
"module": "tsx scripts/snapify-module.ts",
|
|
21
|
+
"sdk:pack": "tsx scripts/sdk-pack.ts",
|
|
22
|
+
"sdk:publish": "tsx scripts/sdk-publish.ts",
|
|
23
|
+
"app:pack": "tsx scripts/app-pack.ts",
|
|
24
|
+
"app:publish": "tsx scripts/app-publish.ts"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"@dnd-kit/core": "^6.3.1",
|
|
28
|
+
"@dnd-kit/sortable": "^10.0.0",
|
|
29
|
+
"@dnd-kit/utilities": "^3.2.2",
|
|
30
|
+
"@tailwindcss/vite": "^4.3.3",
|
|
31
|
+
"@tiptap/extension-image": "^3.31.4",
|
|
32
|
+
"@tiptap/extension-link": "^3.31.4",
|
|
33
|
+
"@tiptap/extension-placeholder": "^3.31.4",
|
|
34
|
+
"@tiptap/extension-text-align": "^3.31.4",
|
|
35
|
+
"@tiptap/pm": "^3.31.4",
|
|
36
|
+
"@tiptap/react": "^3.31.4",
|
|
37
|
+
"@tiptap/starter-kit": "^3.31.4",
|
|
38
|
+
"@types/geoip-lite": "^1.4.4",
|
|
39
|
+
"@types/nodemailer": "^8.0.2",
|
|
40
|
+
"@types/qrcode": "^1.5.6",
|
|
41
|
+
"@vitejs/plugin-react": "^6.1.1",
|
|
42
|
+
"basic-ftp": "^5.3.1",
|
|
43
|
+
"dotenv": "^17.2.3",
|
|
44
|
+
"drizzle-orm": "^0.45.4",
|
|
45
|
+
"esbuild": "^0.25.12",
|
|
46
|
+
"express": "^4.21.2",
|
|
47
|
+
"geoip-lite": "^2.0.3",
|
|
48
|
+
"lucide-react": "^0.546.0",
|
|
49
|
+
"motion": "^12.23.24",
|
|
50
|
+
"nodemailer": "^10.1.0",
|
|
51
|
+
"pg": "^8.23.1",
|
|
52
|
+
"qrcode": "^1.5.4",
|
|
53
|
+
"react": "^19.0.1",
|
|
54
|
+
"react-dom": "^19.0.1",
|
|
55
|
+
"react-is": "^19.3.0",
|
|
56
|
+
"react-router-dom": "^7.18.4",
|
|
57
|
+
"recharts": "^3.10.1",
|
|
58
|
+
"sonner": "^2.0.8",
|
|
59
|
+
"tsx": "^4.23.15",
|
|
60
|
+
"vite": "^8.3.0"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@types/express": "^4.17.21",
|
|
64
|
+
"@types/node": "^22.14.0",
|
|
65
|
+
"@types/pg": "^8.23.1",
|
|
66
|
+
"@types/react": "^19.3.0",
|
|
67
|
+
"@types/react-dom": "^19.3.0",
|
|
68
|
+
"autoprefixer": "^10.4.21",
|
|
69
|
+
"drizzle-kit": "^0.31.11",
|
|
70
|
+
"postcss": "^8.5.29",
|
|
71
|
+
"tailwindcss": "^4.3.3",
|
|
72
|
+
"typescript": "^7.0.2"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# Snapify CMS
|
|
2
|
+
> CMS moderne (Node, sans PHP) pour créer sites vitrine, blogs et boutiques en ligne — Tunisie & France.
|
|
3
|
+
> Éditeur : NOVALABS WEB DESIGN · contact@novalabs.tn · +216 24 734 647
|
|
4
|
+
|
|
5
|
+
## Produit
|
|
6
|
+
- Nom : Snapify CMS
|
|
7
|
+
- Stack : Node.js (hors stack PHP / CVE classiques)
|
|
8
|
+
- Fonctions : constructeur par blocs, génération IA, e-commerce, multi-domaines, marketplace modules/thèmes, communauté
|
|
9
|
+
- Migration : WordPress, Prestashop, sites maison
|
|
10
|
+
- Installation : 48 h sur l’hébergement client
|
|
11
|
+
|
|
12
|
+
## Tarifs
|
|
13
|
+
- Tunisie (snapify.tn) : 699 DT / an · paiement Flouci
|
|
14
|
+
- France & international (snapify.fr) : 99 € / an
|
|
15
|
+
|
|
16
|
+
## Domaines
|
|
17
|
+
- https://snapify.tn/ — marché Tunisie
|
|
18
|
+
- https://snapify.fr/ — marché France / international
|
|
19
|
+
- https://marketplace.snapify.tn/ — modules & thèmes
|
|
20
|
+
- https://community.snapify.tn/ — forum
|
|
21
|
+
|
|
22
|
+
## Pages clés
|
|
23
|
+
- https://snapify.tn/seo-tunisie — CMS Tunisie, villes, e-commerce
|
|
24
|
+
- https://snapify.fr/seo-france — CMS France, alternative WordPress
|
|
25
|
+
- https://snapify.fr/alternative-wordpress — Comparatif vs WordPress
|
|
26
|
+
- https://snapify.tn/commander · https://snapify.fr/commander — commande
|
|
27
|
+
- https://snapify.tn/demo/ — démo publique
|
|
28
|
+
|
|
29
|
+
## Mots-clés cibles
|
|
30
|
+
CMS Tunisie, créer site web Tunis, boutique en ligne Tunisie, Flouci,
|
|
31
|
+
CMS France, alternative WordPress, CMS sans PHP, site web IA, migration WordPress,
|
|
32
|
+
CMS e-commerce, créer boutique en ligne Paris Lyon Marseille
|
|
33
|
+
|
|
34
|
+
## Contact
|
|
35
|
+
contact@novalabs.tn
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 96 96" width="96" height="96" role="img" aria-label="Snapify">
|
|
2
|
+
<rect width="96" height="96" rx="22" fill="#00a89d"/>
|
|
3
|
+
<g transform="translate(14 14) scale(1.7)">
|
|
4
|
+
<rect x="7" y="9" width="26" height="22" rx="4" fill="none" stroke="#FFFFFF" stroke-width="2.4"/>
|
|
5
|
+
<path d="M7 15.5 H33" stroke="#FFFFFF" stroke-width="2.4"/>
|
|
6
|
+
<circle cx="11" cy="12.3" r="1.1" fill="#FFFFFF"/>
|
|
7
|
+
<circle cx="14.4" cy="12.3" r="1.1" fill="#FFFFFF"/>
|
|
8
|
+
<path d="M20 18.2 L21.6 22 L25.4 23.6 L21.6 25.2 L20 29 L18.4 25.2 L14.6 23.6 L18.4 22 Z" fill="#FFFFFF"/>
|
|
9
|
+
</g>
|
|
10
|
+
</svg>
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapify
|
|
3
|
+
* © 2026 NOVALABS WEB DESIGN — Tunisie
|
|
4
|
+
* Contact : contact@novalabs.tn · +216 24 734 647
|
|
5
|
+
* Tous droits réservés. Toute reproduction, modification ou diffusion sans autorisation écrite est interdite.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Prépare le paquet npm `create-snapify-app` (CMS complet) :
|
|
9
|
+
*
|
|
10
|
+
* npm run app:pack [-- --force]
|
|
11
|
+
*
|
|
12
|
+
* Copie les sources filtrées dans create-snapify-app/template/, puis produit
|
|
13
|
+
* releases/npm/create-snapify-app-<version>.tgz
|
|
14
|
+
*/
|
|
15
|
+
import { execFileSync } from 'child_process';
|
|
16
|
+
import fs from 'fs/promises';
|
|
17
|
+
import path from 'path';
|
|
18
|
+
import { fileURLToPath } from 'url';
|
|
19
|
+
|
|
20
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
21
|
+
const PKG_DIR = path.join(ROOT, 'create-snapify-app');
|
|
22
|
+
const TEMPLATE = path.join(PKG_DIR, 'template');
|
|
23
|
+
const NPM_OUT = path.join(ROOT, 'releases', 'npm');
|
|
24
|
+
const force = process.argv.includes('--force');
|
|
25
|
+
|
|
26
|
+
const EXCLUDE_DIRS = new Set([
|
|
27
|
+
'node_modules',
|
|
28
|
+
'.git',
|
|
29
|
+
'.cursor',
|
|
30
|
+
'dist',
|
|
31
|
+
'build',
|
|
32
|
+
'coverage',
|
|
33
|
+
'backups',
|
|
34
|
+
'releases',
|
|
35
|
+
'data',
|
|
36
|
+
'database', // dumps locaux — jamais sur npm
|
|
37
|
+
'create-snapify-app',
|
|
38
|
+
'.snapify-build',
|
|
39
|
+
'.snapify',
|
|
40
|
+
]);
|
|
41
|
+
|
|
42
|
+
const EXCLUDE_FILES = new Set([
|
|
43
|
+
'.env',
|
|
44
|
+
'.pm2.env',
|
|
45
|
+
'landing-analytics.jsonl',
|
|
46
|
+
'ecosystem.config.json', // chemins / secrets machine
|
|
47
|
+
]);
|
|
48
|
+
|
|
49
|
+
const EXCLUDE_PREFIXES = [
|
|
50
|
+
'public/uploads/',
|
|
51
|
+
'create-snapify-app/template/',
|
|
52
|
+
'marketplace/packages/', // .snapmod lourds — sync marketplace à l’install
|
|
53
|
+
];
|
|
54
|
+
|
|
55
|
+
const EXCLUDE_SUFFIXES = ['.dump', '.pem', '.log', '.sql.gz'];
|
|
56
|
+
|
|
57
|
+
async function walk(dir: string): Promise<string[]> {
|
|
58
|
+
const out: string[] = [];
|
|
59
|
+
for (const e of await fs.readdir(dir, { withFileTypes: true })) {
|
|
60
|
+
if (EXCLUDE_DIRS.has(e.name)) continue;
|
|
61
|
+
const full = path.join(dir, e.name);
|
|
62
|
+
if (e.isDirectory()) out.push(...(await walk(full)));
|
|
63
|
+
else out.push(full);
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function rel(p: string) {
|
|
69
|
+
return path.relative(ROOT, p).split(path.sep).join('/');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function shouldInclude(file: string): boolean {
|
|
73
|
+
const r = rel(file);
|
|
74
|
+
if (EXCLUDE_FILES.has(path.basename(file))) return false;
|
|
75
|
+
if (EXCLUDE_PREFIXES.some((p) => r === p.slice(0, -1) || r.startsWith(p))) return false;
|
|
76
|
+
if (EXCLUDE_SUFFIXES.some((s) => r.endsWith(s))) return false;
|
|
77
|
+
if (r.startsWith('docs/screenshots/')) return false;
|
|
78
|
+
return true;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
async function rmrf(p: string) {
|
|
82
|
+
await fs.rm(p, { recursive: true, force: true });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
async function main() {
|
|
86
|
+
const pkg = JSON.parse(await fs.readFile(path.join(PKG_DIR, 'package.json'), 'utf8')) as {
|
|
87
|
+
name: string;
|
|
88
|
+
version: string;
|
|
89
|
+
};
|
|
90
|
+
const outTgz = path.join(NPM_OUT, `${pkg.name}-${pkg.version}.tgz`);
|
|
91
|
+
await fs.mkdir(NPM_OUT, { recursive: true });
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
await fs.access(outTgz);
|
|
95
|
+
if (!force) throw new Error(`${path.relative(ROOT, outTgz)} existe déjà — utilisez --force pour régénérer`);
|
|
96
|
+
} catch (e) {
|
|
97
|
+
if (e && typeof e === 'object' && 'code' in e && (e as NodeJS.ErrnoException).code === 'ENOENT') {
|
|
98
|
+
/* ok */
|
|
99
|
+
} else if (e instanceof Error && e.message.includes('existe déjà')) {
|
|
100
|
+
throw e;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
console.log('• Nettoyage template/');
|
|
105
|
+
await rmrf(TEMPLATE);
|
|
106
|
+
await fs.mkdir(TEMPLATE, { recursive: true });
|
|
107
|
+
|
|
108
|
+
const files = (await walk(ROOT)).filter(shouldInclude);
|
|
109
|
+
console.log(`• Copie de ${files.length} fichiers vers create-snapify-app/template/`);
|
|
110
|
+
for (const file of files) {
|
|
111
|
+
const target = path.join(TEMPLATE, rel(file));
|
|
112
|
+
await fs.mkdir(path.dirname(target), { recursive: true });
|
|
113
|
+
await fs.copyFile(file, target);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// .env.example enrichi pour le template (DATABASE_URL / PUBLIC_URL)
|
|
117
|
+
const examplePath = path.join(TEMPLATE, '.env.example');
|
|
118
|
+
let example = await fs.readFile(examplePath, 'utf8').catch(() => '');
|
|
119
|
+
if (!example.includes('DATABASE_URL=')) {
|
|
120
|
+
example = `DATABASE_URL=postgres://snapify:changez-moi@127.0.0.1:5432/snapify\nPUBLIC_URL=https://exemple.tn\nSNAPIFY_DB_PASSWORD=changez-moi\nSNAPIFY_DB_PORT=5433\n\n${example}`;
|
|
121
|
+
await fs.writeFile(examplePath, example);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// package.json du site dans le template : garder private, version alignée
|
|
125
|
+
const sitePkgPath = path.join(TEMPLATE, 'package.json');
|
|
126
|
+
const sitePkg = JSON.parse(await fs.readFile(sitePkgPath, 'utf8')) as Record<string, unknown>;
|
|
127
|
+
sitePkg.version = pkg.version;
|
|
128
|
+
sitePkg.private = true;
|
|
129
|
+
await fs.writeFile(sitePkgPath, `${JSON.stringify(sitePkg, null, 2)}\n`);
|
|
130
|
+
|
|
131
|
+
// Marqueur de provenance
|
|
132
|
+
await fs.writeFile(
|
|
133
|
+
path.join(TEMPLATE, '.snapify-install.json'),
|
|
134
|
+
`${JSON.stringify({ package: pkg.name, version: pkg.version, packedAt: new Date().toISOString() }, null, 2)}\n`,
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
console.log(`• npm pack → ${path.relative(ROOT, outTgz)}`);
|
|
138
|
+
const packed = execFileSync('npm', ['pack', '--pack-destination', NPM_OUT], {
|
|
139
|
+
cwd: PKG_DIR,
|
|
140
|
+
encoding: 'utf8',
|
|
141
|
+
}).trim();
|
|
142
|
+
const produced = path.join(NPM_OUT, packed.split('\n').pop()!.trim());
|
|
143
|
+
if (path.resolve(produced) !== path.resolve(outTgz)) {
|
|
144
|
+
await fs.rename(produced, outTgz);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
const stat = await fs.stat(outTgz);
|
|
148
|
+
console.log(`✔ ${path.relative(ROOT, outTgz)} (${(stat.size / 1024 / 1024).toFixed(1)} Mo)`);
|
|
149
|
+
console.log(' Publication : npm run app:publish -- --dry-run');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
main().catch((e) => {
|
|
153
|
+
console.error(`✖ ${e instanceof Error ? e.message : String(e)}`);
|
|
154
|
+
process.exit(1);
|
|
155
|
+
});
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Snapify
|
|
3
|
+
* © 2026 NOVALABS WEB DESIGN — Tunisie
|
|
4
|
+
* Contact : contact@novalabs.tn · +216 24 734 647
|
|
5
|
+
* Tous droits réservés. Toute reproduction, modification ou diffusion sans autorisation écrite est interdite.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Publie create-snapify-app sur npm :
|
|
9
|
+
*
|
|
10
|
+
* npm run app:publish -- --dry-run
|
|
11
|
+
* npm run app:publish -- --otp 123456
|
|
12
|
+
*/
|
|
13
|
+
import { execFileSync } from 'child_process';
|
|
14
|
+
import fs from 'fs/promises';
|
|
15
|
+
import path from 'path';
|
|
16
|
+
import { fileURLToPath } from 'url';
|
|
17
|
+
|
|
18
|
+
const ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
19
|
+
const argv = process.argv.slice(2);
|
|
20
|
+
const dryRun = argv.includes('--dry-run');
|
|
21
|
+
const otpIndex = argv.indexOf('--otp');
|
|
22
|
+
const otp = otpIndex >= 0 ? argv[otpIndex + 1] : undefined;
|
|
23
|
+
|
|
24
|
+
async function main() {
|
|
25
|
+
const pkg = JSON.parse(await fs.readFile(path.join(ROOT, 'create-snapify-app/package.json'), 'utf8')) as {
|
|
26
|
+
name: string;
|
|
27
|
+
version: string;
|
|
28
|
+
};
|
|
29
|
+
const file = path.join(ROOT, 'releases/npm', `${pkg.name}-${pkg.version}.tgz`);
|
|
30
|
+
await fs.access(file).catch(() => {
|
|
31
|
+
throw new Error(`${path.relative(ROOT, file)} absent : lancez npm run app:pack`);
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const token = (process.env.NPM_TOKEN || process.env.NODE_AUTH_TOKEN || '').trim();
|
|
35
|
+
const npmEnv = { ...process.env };
|
|
36
|
+
if (token) {
|
|
37
|
+
// Auth non interactive (CI / serveur) — ne pas écrire .npmrc disque
|
|
38
|
+
npmEnv.NPM_CONFIG_USERCONFIG = path.join(ROOT, 'releases/npm/.npmrc.publish');
|
|
39
|
+
await fs.mkdir(path.dirname(npmEnv.NPM_CONFIG_USERCONFIG), { recursive: true });
|
|
40
|
+
await fs.writeFile(
|
|
41
|
+
npmEnv.NPM_CONFIG_USERCONFIG,
|
|
42
|
+
`//registry.npmjs.org/:_authToken=${token}\nalways-auth=true\n`,
|
|
43
|
+
{ mode: 0o600 },
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
if (!dryRun) {
|
|
48
|
+
let user = '';
|
|
49
|
+
try {
|
|
50
|
+
user = execFileSync('npm', ['whoami'], {
|
|
51
|
+
cwd: ROOT,
|
|
52
|
+
encoding: 'utf8',
|
|
53
|
+
env: npmEnv,
|
|
54
|
+
}).trim();
|
|
55
|
+
} catch {
|
|
56
|
+
throw new Error(
|
|
57
|
+
'Aucun compte npm connecté : lancez `npm login` ou exportez NPM_TOKEN (automation token novalabsweb)',
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
console.log(`• Compte npm : ${user}`);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
let published = '';
|
|
64
|
+
try {
|
|
65
|
+
published = execFileSync('npm', ['view', `${pkg.name}@${pkg.version}`, 'version'], {
|
|
66
|
+
cwd: ROOT,
|
|
67
|
+
encoding: 'utf8',
|
|
68
|
+
stdio: ['ignore', 'pipe', 'ignore'],
|
|
69
|
+
}).trim();
|
|
70
|
+
} catch {
|
|
71
|
+
published = '';
|
|
72
|
+
}
|
|
73
|
+
if (published === pkg.version) {
|
|
74
|
+
console.log(`• ${pkg.name}@${pkg.version} déjà publié : ignoré`);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
console.log(`• ${dryRun ? 'Contrôle' : 'Publication'} de ${pkg.name}@${pkg.version}`);
|
|
79
|
+
try {
|
|
80
|
+
execFileSync(
|
|
81
|
+
'npm',
|
|
82
|
+
['publish', file, '--access', 'public', ...(dryRun ? ['--dry-run'] : []), ...(otp ? ['--otp', otp] : [])],
|
|
83
|
+
{ cwd: ROOT, stdio: 'inherit', env: npmEnv },
|
|
84
|
+
);
|
|
85
|
+
} finally {
|
|
86
|
+
if (token && npmEnv.NPM_CONFIG_USERCONFIG) {
|
|
87
|
+
await fs.rm(npmEnv.NPM_CONFIG_USERCONFIG, { force: true }).catch(() => undefined);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
console.log(
|
|
91
|
+
dryRun
|
|
92
|
+
? '✔ Contrôle terminé : rien n’a été publié'
|
|
93
|
+
: `✔ Publié : https://www.npmjs.com/package/${pkg.name}\n Install : npx create-snapify-app@latest`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
main().catch((e) => {
|
|
98
|
+
console.error(`✖ ${e instanceof Error ? e.message : String(e)}`);
|
|
99
|
+
process.exit(1);
|
|
100
|
+
});
|
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Branche menus + accueil sur la boutique (widgets shop) pour le thème Mahdia.
|
|
3
|
+
* Ne change pas le thème actif.
|
|
4
|
+
*/
|
|
5
|
+
import 'dotenv/config';
|
|
6
|
+
import crypto from 'crypto';
|
|
7
|
+
import { runMigrations } from '../server/db/client';
|
|
8
|
+
import { loadSnapshot, updateSnapshot } from '../server/cms/store';
|
|
9
|
+
import { button, uid } from '../server/cms/blocks';
|
|
10
|
+
import { BLOCK_CATALOG } from '../server/cms/blockCatalog';
|
|
11
|
+
import type { CmsBlock, MenuConfig, MenuItem } from '../server/cms/types';
|
|
12
|
+
|
|
13
|
+
function block(type: CmsBlock['type'], data: Record<string, unknown>, style?: CmsBlock['style']): CmsBlock {
|
|
14
|
+
return { id: uid('b'), type, data, style: style || { paddingTop: 'md', paddingBottom: 'md' } };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function moduleBlock(widget: string, options: Record<string, unknown>): CmsBlock {
|
|
18
|
+
return block('module', { module: 'novalabs.shop', widget, options });
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const HOME: CmsBlock[] = [
|
|
22
|
+
block(
|
|
23
|
+
'hero',
|
|
24
|
+
{
|
|
25
|
+
...BLOCK_CATALOG.hero.defaults(),
|
|
26
|
+
layout: 'split',
|
|
27
|
+
badgeTag: 'Boutique',
|
|
28
|
+
badgeText: 'Mahdia',
|
|
29
|
+
title: 'L’esprit Méditerranée, chez vous',
|
|
30
|
+
subtitle: 'Découvrez une sélection démo : déco, mode, bien-être et gourmet — livrée partout en Tunisie.',
|
|
31
|
+
buttons: [
|
|
32
|
+
button('Voir la boutique', '/boutique/'),
|
|
33
|
+
button('Promotions', '/boutique/?promo=1', 'secondary', 'none'),
|
|
34
|
+
],
|
|
35
|
+
media: 'image',
|
|
36
|
+
mainImage: '/images/photos/terrasse-blanche-mer-voilier.jpg',
|
|
37
|
+
mainImageAlt: 'Terrasse face à la mer',
|
|
38
|
+
marquee: ['Maison & déco', 'Mode', 'Bien-être', 'Gourmet', 'Livraison Tunisie', 'Paiement à la livraison'],
|
|
39
|
+
},
|
|
40
|
+
{ ...BLOCK_CATALOG.hero.style, paddingTop: 'lg', paddingBottom: 'lg', background: 'soft' }
|
|
41
|
+
),
|
|
42
|
+
moduleBlock('categories', {
|
|
43
|
+
eyebrow: 'Collections',
|
|
44
|
+
title: 'Parcourir par catégorie',
|
|
45
|
+
subtitle: '',
|
|
46
|
+
limit: 4,
|
|
47
|
+
style: 'tiles',
|
|
48
|
+
}),
|
|
49
|
+
moduleBlock('products', {
|
|
50
|
+
eyebrow: 'Sélection',
|
|
51
|
+
title: 'Nos coups de cœur',
|
|
52
|
+
subtitle: 'Produits mis en avant pour la démo Snapify.',
|
|
53
|
+
source: 'featured',
|
|
54
|
+
category: '',
|
|
55
|
+
limit: 8,
|
|
56
|
+
columns: '4',
|
|
57
|
+
buttonLabel: 'Voir toute la boutique',
|
|
58
|
+
}),
|
|
59
|
+
block(
|
|
60
|
+
'cta',
|
|
61
|
+
{
|
|
62
|
+
...BLOCK_CATALOG.cta.defaults(),
|
|
63
|
+
title: 'Livraison partout en Tunisie',
|
|
64
|
+
text: 'Paiement à la livraison, retours sous 14 jours.',
|
|
65
|
+
buttons: [button('Commander maintenant', '/boutique/', 'dark')],
|
|
66
|
+
},
|
|
67
|
+
{ paddingTop: 'lg', paddingBottom: 'lg' }
|
|
68
|
+
),
|
|
69
|
+
moduleBlock('products', {
|
|
70
|
+
eyebrow: 'Promotions',
|
|
71
|
+
title: 'Bonnes affaires',
|
|
72
|
+
subtitle: '',
|
|
73
|
+
source: 'sale',
|
|
74
|
+
category: '',
|
|
75
|
+
limit: 4,
|
|
76
|
+
columns: '4',
|
|
77
|
+
buttonLabel: 'Toutes les promotions',
|
|
78
|
+
}),
|
|
79
|
+
block('steps', {
|
|
80
|
+
...BLOCK_CATALOG.steps.defaults(),
|
|
81
|
+
title: 'Commander en 3 étapes',
|
|
82
|
+
items: [
|
|
83
|
+
{ id: uid('k'), num: '01', title: 'Choisir', text: 'Parcourez la boutique et ajoutez au panier.' },
|
|
84
|
+
{ id: uid('k'), num: '02', title: 'Valider', text: 'Renseignez l’adresse et le mode de paiement.' },
|
|
85
|
+
{ id: uid('k'), num: '03', title: 'Recevoir', text: 'Livraison sous 24 à 72 h en Tunisie.' },
|
|
86
|
+
],
|
|
87
|
+
}),
|
|
88
|
+
moduleBlock('products', {
|
|
89
|
+
eyebrow: 'Nouveautés',
|
|
90
|
+
title: 'Derniers arrivages',
|
|
91
|
+
subtitle: '',
|
|
92
|
+
source: 'latest',
|
|
93
|
+
category: '',
|
|
94
|
+
limit: 4,
|
|
95
|
+
columns: '4',
|
|
96
|
+
buttonLabel: '',
|
|
97
|
+
}),
|
|
98
|
+
block('faq', {
|
|
99
|
+
...BLOCK_CATALOG.faq.defaults(),
|
|
100
|
+
title: 'Questions fréquentes',
|
|
101
|
+
items: [
|
|
102
|
+
{
|
|
103
|
+
id: uid('k'),
|
|
104
|
+
question: 'Quels sont les délais de livraison ?',
|
|
105
|
+
answer: '<p>En général 24 à 72 h partout en Tunisie (démo illustrative).</p>',
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
id: uid('k'),
|
|
109
|
+
question: 'Puis-je payer à la livraison ?',
|
|
110
|
+
answer: '<p>Oui, le paiement à la livraison est proposé dans le module Commande.</p>',
|
|
111
|
+
},
|
|
112
|
+
],
|
|
113
|
+
}),
|
|
114
|
+
block(
|
|
115
|
+
'cta',
|
|
116
|
+
{
|
|
117
|
+
...BLOCK_CATALOG.cta.defaults(),
|
|
118
|
+
title: 'Prêt à explorer la boutique ?',
|
|
119
|
+
text: '12 produits démo vous attendent.',
|
|
120
|
+
buttons: [button('Ouvrir la boutique', '/boutique/', 'dark')],
|
|
121
|
+
},
|
|
122
|
+
{ paddingTop: 'lg', paddingBottom: 'lg' }
|
|
123
|
+
),
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
function menus(): MenuConfig[] {
|
|
127
|
+
const shopChildren: MenuItem[] = [
|
|
128
|
+
{ id: 'm-shop-maison', label: 'Maison & déco', path: '/boutique/maison-deco/' },
|
|
129
|
+
{ id: 'm-shop-mode', label: 'Mode', path: '/boutique/mode/' },
|
|
130
|
+
{ id: 'm-shop-bienetre', label: 'Bien-être', path: '/boutique/bien-etre/' },
|
|
131
|
+
{ id: 'm-shop-gourmet', label: 'Gourmet', path: '/boutique/gourmet/' },
|
|
132
|
+
];
|
|
133
|
+
const primary: MenuConfig = {
|
|
134
|
+
id: 'primary',
|
|
135
|
+
label: 'Menu principal (desktop)',
|
|
136
|
+
items: [
|
|
137
|
+
{ id: 'm-shop', label: 'Boutique', path: '/boutique/', children: shopChildren },
|
|
138
|
+
{ id: 'm-promo', label: 'Promotions', path: '/boutique/?promo=1' },
|
|
139
|
+
{ id: 'm-home', label: 'Accueil', path: '/' },
|
|
140
|
+
{ id: 'm-contact', label: 'Contact', path: '/contact/', highlight: true },
|
|
141
|
+
],
|
|
142
|
+
};
|
|
143
|
+
const mobile: MenuConfig = {
|
|
144
|
+
id: 'mobile',
|
|
145
|
+
label: 'Menu mobile',
|
|
146
|
+
items: JSON.parse(JSON.stringify(primary.items)) as MenuItem[],
|
|
147
|
+
};
|
|
148
|
+
const footer: MenuConfig = {
|
|
149
|
+
id: 'footer',
|
|
150
|
+
label: 'Pied de page',
|
|
151
|
+
items: [
|
|
152
|
+
{ id: 'f-shop', label: 'Boutique', path: '/boutique/' },
|
|
153
|
+
{ id: 'f-promo', label: 'Promotions', path: '/boutique/?promo=1' },
|
|
154
|
+
{ id: 'f-contact', label: 'Contact', path: '/contact/', highlight: true },
|
|
155
|
+
{ id: 'f-legal', label: 'Mentions légales', path: '/mentions-legales/' },
|
|
156
|
+
{ id: 'f-privacy', label: 'Confidentialité', path: '/politique-de-confidentialite/' },
|
|
157
|
+
{ id: 'f-cookies', label: 'Cookies', path: '/cookies/' },
|
|
158
|
+
],
|
|
159
|
+
};
|
|
160
|
+
return [primary, mobile, footer];
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
await runMigrations();
|
|
164
|
+
await loadSnapshot();
|
|
165
|
+
|
|
166
|
+
await updateSnapshot((s) => {
|
|
167
|
+
const home = s.pages.find((p) => p.path === '/' || p.path === '');
|
|
168
|
+
if (home) {
|
|
169
|
+
home.blocks = HOME;
|
|
170
|
+
home.title = 'Accueil';
|
|
171
|
+
home.seo = {
|
|
172
|
+
...home.seo,
|
|
173
|
+
seoTitle: 'Snapify Boutique — Mahdia',
|
|
174
|
+
metaDescription: 'Découvrez 12 produits démo et 4 catégories sur Snapify.',
|
|
175
|
+
ogTitle: 'Accueil — Boutique',
|
|
176
|
+
ogDescription: 'Boutique démo Snapify : déco, mode, bien-être et gourmet.',
|
|
177
|
+
};
|
|
178
|
+
home.updatedAt = new Date().toISOString();
|
|
179
|
+
}
|
|
180
|
+
const byId = new Map(s.menus.map((m) => [m.id, m]));
|
|
181
|
+
for (const m of menus()) {
|
|
182
|
+
const existing = byId.get(m.id);
|
|
183
|
+
if (existing) {
|
|
184
|
+
existing.items = m.items;
|
|
185
|
+
existing.label = m.label;
|
|
186
|
+
} else {
|
|
187
|
+
s.menus.push(m);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
s.branding.siteName = s.branding.siteName || 'Snapify';
|
|
191
|
+
s.branding.tagline = 'Boutique démo — Tunisie';
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
console.log('[ecom-home] accueil + menus boutique appliqués');
|
|
195
|
+
void crypto;
|
|
196
|
+
process.exit(0);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# CD de secours si GitHub Actions est indisponible (startup_failure sur le compte).
|
|
3
|
+
# Installe : crontab -e → */5 * * * * /home/snapify/scripts/auto-deploy-poll.sh >> /var/log/snapify-deploy.log 2>&1
|
|
4
|
+
set -euo pipefail
|
|
5
|
+
ROOT=/home/snapify
|
|
6
|
+
cd "$ROOT"
|
|
7
|
+
git fetch --quiet origin main
|
|
8
|
+
LOCAL=$(git rev-parse HEAD)
|
|
9
|
+
REMOTE=$(git rev-parse origin/main)
|
|
10
|
+
if [[ "$LOCAL" != "$REMOTE" ]]; then
|
|
11
|
+
echo "$(date -Is) deploy $LOCAL → $REMOTE"
|
|
12
|
+
bash "$ROOT/scripts/deploy.sh" origin/main
|
|
13
|
+
fi
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Snapify
|
|
3
|
+
# © 2026 NOVALABS WEB DESIGN — Tunisie
|
|
4
|
+
# Contact : contact@novalabs.tn · +216 24 734 647
|
|
5
|
+
# Tous droits réservés. Toute reproduction, modification ou diffusion sans autorisation écrite est interdite.
|
|
6
|
+
# Sauvegarde quotidienne de la base Snapify (format custom pg_dump, restaurable avec pg_restore).
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
DIR="$(cd "$(dirname "$0")/.." && pwd)/backups/db"
|
|
9
|
+
KEEP_DAYS="${KEEP_DAYS:-14}"
|
|
10
|
+
mkdir -p "$DIR"
|
|
11
|
+
FILE="$DIR/snapify-$(date +%Y%m%d-%H%M%S).dump"
|
|
12
|
+
docker exec snapify-postgres pg_dump -U snapify -d snapify -Fc > "$FILE.tmp"
|
|
13
|
+
mv "$FILE.tmp" "$FILE"
|
|
14
|
+
chmod 600 "$FILE"
|
|
15
|
+
find "$DIR" -name 'snapify-*.dump' -mtime +"$KEEP_DAYS" -delete
|
|
16
|
+
echo "Sauvegarde : $FILE"
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Snapify
|
|
3
|
+
# © 2026 NOVALABS WEB DESIGN — Tunisie
|
|
4
|
+
# Contact : contact@novalabs.tn · +216 24 734 647
|
|
5
|
+
# Tous droits réservés. Toute reproduction, modification ou diffusion sans autorisation écrite est interdite.
|
|
6
|
+
# Restaure une sauvegarde : scripts/db-restore.sh backups/db/snapify-AAAAMMJJ-HHMMSS.dump
|
|
7
|
+
set -euo pipefail
|
|
8
|
+
FILE="${1:?Usage : scripts/db-restore.sh <fichier.dump>}"
|
|
9
|
+
docker exec -i snapify-postgres pg_restore -U snapify -d snapify --clean --if-exists --no-owner < "$FILE"
|
|
10
|
+
pm2 restart snapify
|
|
11
|
+
echo "Base restaurée depuis $FILE"
|