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.
Files changed (614) hide show
  1. package/LICENSE.md +24 -0
  2. package/README.md +55 -2
  3. package/bin/create-snapify-app.mjs +174 -0
  4. package/lib/args.mjs +59 -0
  5. package/lib/copy.mjs +44 -0
  6. package/lib/env.mjs +84 -0
  7. package/lib/prompt.mjs +63 -0
  8. package/package.json +35 -4
  9. package/template/.env.example +79 -0
  10. package/template/.github/workflows/ci.yml +23 -0
  11. package/template/.github/workflows/deploy.yml +26 -0
  12. package/template/.github/workflows/ping.yml +8 -0
  13. package/template/.github/workflows/release.yml +67 -0
  14. package/template/.snapify-install.json +5 -0
  15. package/template/CHANGELOG.md +28 -0
  16. package/template/LICENSE +14 -0
  17. package/template/README.md +287 -0
  18. package/template/administrator.html +23 -0
  19. package/template/apps/client/src/App.tsx +765 -0
  20. package/template/apps/client/src/auth.css +400 -0
  21. package/template/apps/client/src/lib/api.ts +22 -0
  22. package/template/apps/client/src/main.tsx +20 -0
  23. package/template/apps/community/src/App.tsx +592 -0
  24. package/template/apps/community/src/main.tsx +20 -0
  25. package/template/apps/community/src/styles.css +24 -0
  26. package/template/apps/developers/src/App.tsx +643 -0
  27. package/template/apps/developers/src/main.tsx +17 -0
  28. package/template/apps/developers/src/pages.tsx +1587 -0
  29. package/template/apps/developers/src/styles.css +98 -0
  30. package/template/apps/developers/src/ui.tsx +179 -0
  31. package/template/apps/landing/src/App.tsx +598 -0
  32. package/template/apps/landing/src/LegalPages.tsx +158 -0
  33. package/template/apps/landing/src/OrderPage.tsx +381 -0
  34. package/template/apps/landing/src/SeoPages.tsx +923 -0
  35. package/template/apps/landing/src/copy.ts +195 -0
  36. package/template/apps/landing/src/main.tsx +20 -0
  37. package/template/apps/landing/src/styles.css +803 -0
  38. package/template/apps/landing/src/types.ts +19 -0
  39. package/template/apps/marketplace/src/App.tsx +1229 -0
  40. package/template/apps/marketplace/src/developer/DeveloperApp.tsx +1266 -0
  41. package/template/apps/marketplace/src/main.tsx +20 -0
  42. package/template/apps/marketplace/src/styles.css +1001 -0
  43. package/template/apps/shared/AuthContext.tsx +65 -0
  44. package/template/apps/shared/Logo.tsx +33 -0
  45. package/template/apps/shared/api.ts +47 -0
  46. package/template/apps/shared/ui.tsx +128 -0
  47. package/template/apps/superadmin/src/App.tsx +1264 -0
  48. package/template/apps/superadmin/src/lib/api.ts +20 -0
  49. package/template/apps/superadmin/src/lib/hooks.ts +20 -0
  50. package/template/apps/superadmin/src/main.tsx +16 -0
  51. package/template/apps/superadmin/src/pages/ClientsPage.tsx +185 -0
  52. package/template/apps/superadmin/src/pages/InvoicesPage.tsx +157 -0
  53. package/template/apps/superadmin/src/pages/NewsletterPage.tsx +212 -0
  54. package/template/apps/superadmin/src/pages/OrdersPage.tsx +195 -0
  55. package/template/apps/superadmin/src/pages/PaymentsPage.tsx +150 -0
  56. package/template/apps/superadmin/src/pages/PayoutsPage.tsx +133 -0
  57. package/template/apps/superadmin/src/pages/PublishersPage.tsx +151 -0
  58. package/template/apps/superadmin/src/pages/SeoControlPage.tsx +692 -0
  59. package/template/apps/superadmin/src/pages/SettingsPage.tsx +199 -0
  60. package/template/apps/superadmin/src/pages/SystemPage.tsx +109 -0
  61. package/template/apps/superadmin/src/pages/TicketsPage.tsx +201 -0
  62. package/template/apps/superadmin/src/pages/UsersPage.tsx +167 -0
  63. package/template/client.html +21 -0
  64. package/template/community/hamdiayari/akhbar/README.md +23 -0
  65. package/template/community/hamdiayari/akhbar/screenshot.jpg +0 -0
  66. package/template/community/hamdiayari/akhbar/snapify.theme.json +76 -0
  67. package/template/community/hamdiayari/akhbar/src/Brand.tsx +26 -0
  68. package/template/community/hamdiayari/akhbar/src/Footer.tsx +182 -0
  69. package/template/community/hamdiayari/akhbar/src/Header.tsx +191 -0
  70. package/template/community/hamdiayari/akhbar/src/Layout.tsx +49 -0
  71. package/template/community/hamdiayari/akhbar/src/Social.tsx +33 -0
  72. package/template/community/hamdiayari/akhbar/src/Ticker.tsx +86 -0
  73. package/template/community/hamdiayari/akhbar/src/Views.tsx +285 -0
  74. package/template/community/hamdiayari/akhbar/src/blocks/CollectionBlocks.tsx +672 -0
  75. package/template/community/hamdiayari/akhbar/src/blocks/ContentBlocks.tsx +305 -0
  76. package/template/community/hamdiayari/akhbar/src/blocks/ConversionBlocks.tsx +569 -0
  77. package/template/community/hamdiayari/akhbar/src/blocks/HeaderBlocks.tsx +287 -0
  78. package/template/community/hamdiayari/akhbar/src/index.tsx +51 -0
  79. package/template/community/hamdiayari/akhbar/src/kit.tsx +357 -0
  80. package/template/community/hamdiayari/akhbar/src/site.ts +96 -0
  81. package/template/community/hamdiayari/akhbar/src/styles.css +566 -0
  82. package/template/community/hamdiayari/akhbar-actualites/README.md +28 -0
  83. package/template/community/hamdiayari/akhbar-actualites/screenshot.jpg +0 -0
  84. package/template/community/hamdiayari/akhbar-actualites/snapify.module.json +107 -0
  85. package/template/community/hamdiayari/akhbar-actualites/src/admin/AudiencePage.tsx +185 -0
  86. package/template/community/hamdiayari/akhbar-actualites/src/admin/index.tsx +11 -0
  87. package/template/community/hamdiayari/akhbar-actualites/src/public/Archive.tsx +142 -0
  88. package/template/community/hamdiayari/akhbar-actualites/src/public/cards.tsx +152 -0
  89. package/template/community/hamdiayari/akhbar-actualites/src/public/index.tsx +71 -0
  90. package/template/community/hamdiayari/akhbar-actualites/src/public/posts.ts +103 -0
  91. package/template/community/hamdiayari/akhbar-actualites/src/public/styles.css +568 -0
  92. package/template/community/hamdiayari/akhbar-actualites/src/public/widgets.tsx +226 -0
  93. package/template/community/hamdiayari/akhbar-actualites/src/server.ts +119 -0
  94. package/template/community/hamdiayari/akhbar-actualites/src/types.ts +25 -0
  95. package/template/community/hamdiayari/akhbar-urgent/README.md +36 -0
  96. package/template/community/hamdiayari/akhbar-urgent/screenshot.jpg +0 -0
  97. package/template/community/hamdiayari/akhbar-urgent/snapify.module.json +64 -0
  98. package/template/community/hamdiayari/akhbar-urgent/src/admin/FlashesPage.tsx +229 -0
  99. package/template/community/hamdiayari/akhbar-urgent/src/admin/index.tsx +11 -0
  100. package/template/community/hamdiayari/akhbar-urgent/src/public/Ticker.tsx +81 -0
  101. package/template/community/hamdiayari/akhbar-urgent/src/public/index.tsx +63 -0
  102. package/template/community/hamdiayari/akhbar-urgent/src/public/styles.css +142 -0
  103. package/template/community/hamdiayari/akhbar-urgent/src/server.ts +101 -0
  104. package/template/community/hamdiayari/akhbar-urgent/src/types.ts +35 -0
  105. package/template/community.html +21 -0
  106. package/template/developers.html +24 -0
  107. package/template/docker-compose.db.yml +24 -0
  108. package/template/docs/BACKOFFICE_SNAPIFY.md +130 -0
  109. package/template/docs/CI_CD.md +66 -0
  110. package/template/docs/MODULES.md +346 -0
  111. package/template/docs/PLATFORM_DEPLOY.md +54 -0
  112. package/template/docs/logo.svg +10 -0
  113. package/template/drizzle/0000_init.sql +147 -0
  114. package/template/drizzle/0001_page_project.sql +5 -0
  115. package/template/drizzle/0002_modules.sql +23 -0
  116. package/template/drizzle/0003_themes.sql +4 -0
  117. package/template/drizzle/0004_security.sql +82 -0
  118. package/template/drizzle/0005_module_records.sql +16 -0
  119. package/template/drizzle/0006_avatars.sql +4 -0
  120. package/template/drizzle/0007_platform.sql +264 -0
  121. package/template/drizzle/0008_mp_validation.sql +3 -0
  122. package/template/drizzle/0009_saas_ops.sql +77 -0
  123. package/template/drizzle/0010_cms_chrome.sql +13 -0
  124. package/template/drizzle/0011_client_portal.sql +26 -0
  125. package/template/drizzle/meta/0000_snapshot.json +998 -0
  126. package/template/drizzle/meta/0001_snapshot.json +1004 -0
  127. package/template/drizzle/meta/_journal.json +90 -0
  128. package/template/drizzle.config.ts +16 -0
  129. package/template/ecosystem.snapify.cjs +24 -0
  130. package/template/for.html +1 -0
  131. package/template/index.html +29 -0
  132. package/template/landing.html +37 -0
  133. package/template/marketplace/catalog.json +373 -0
  134. package/template/marketplace/gallery/hamdiayari.preveris/01-home.jpg +0 -0
  135. package/template/marketplace/gallery/hamdiayari.recaptcha/01-reglages.jpg +0 -0
  136. package/template/marketplace/gallery/hamdiayari.recaptcha/02-logo.jpg +0 -0
  137. package/template/marketplace/gallery/novalabs.ai-articles/01-generer.jpg +0 -0
  138. package/template/marketplace/gallery/novalabs.ai-articles/02-fournisseur-ia.jpg +0 -0
  139. package/template/marketplace/gallery/novalabs.calendar/01-agenda-site.jpg +0 -0
  140. package/template/marketplace/gallery/novalabs.calendar/02-evenements-admin.jpg +0 -0
  141. package/template/marketplace/gallery/novalabs.calendar/03-reglages.jpg +0 -0
  142. package/template/marketplace/screenshots/hamdiayari.preveris-1.0.6.jpg +0 -0
  143. package/template/marketplace/screenshots/hamdiayari.recaptcha-1.0.0.jpg +0 -0
  144. package/template/marketplace/screenshots/hamdiayari.wp-seo-migrator-1.1.1.jpg +0 -0
  145. package/template/marketplace/screenshots/novalabs.ai-articles-1.0.1.jpg +0 -0
  146. package/template/marketplace/screenshots/novalabs.ai-chat-1.0.1.jpg +0 -0
  147. package/template/marketplace/screenshots/novalabs.calendar-1.0.1.jpg +0 -0
  148. package/template/marketplace/screenshots/novalabs.cart-1.0.0.jpg +0 -0
  149. package/template/marketplace/screenshots/novalabs.checkout-1.0.0.jpg +0 -0
  150. package/template/marketplace/screenshots/novalabs.customers-1.1.0.jpg +0 -0
  151. package/template/marketplace/screenshots/novalabs.dogga-1.0.0.jpg +0 -0
  152. package/template/marketplace/screenshots/novalabs.mahdia-1.0.0.jpg +0 -0
  153. package/template/marketplace/screenshots/novalabs.shop-1.0.0.jpg +0 -0
  154. package/template/marketplace/screenshots/novalabs.sidibou-1.0.0.jpg +0 -0
  155. package/template/marketplace/screenshots/novalabs.whatsapp-1.0.1.jpg +0 -0
  156. package/template/marketplace.html +21 -0
  157. package/template/metadata.json +7 -0
  158. package/template/modules/ai-articles/screenshot.jpg +0 -0
  159. package/template/modules/ai-articles/snapify.module.json +74 -0
  160. package/template/modules/ai-articles/src/admin/ArticlesPage.tsx +162 -0
  161. package/template/modules/ai-articles/src/admin/GeneratePage.tsx +118 -0
  162. package/template/modules/ai-articles/src/admin/index.tsx +12 -0
  163. package/template/modules/ai-articles/src/public/index.tsx +119 -0
  164. package/template/modules/ai-articles/src/server.ts +287 -0
  165. package/template/modules/ai-articles/src/types.ts +30 -0
  166. package/template/modules/ai-chat/screenshot.jpg +0 -0
  167. package/template/modules/ai-chat/snapify.module.json +217 -0
  168. package/template/modules/ai-chat/src/public.tsx +198 -0
  169. package/template/modules/ai-chat/src/server.ts +142 -0
  170. package/template/modules/ai-theme-studio/README.md +15 -0
  171. package/template/modules/ai-theme-studio/screenshot.jpg +0 -0
  172. package/template/modules/ai-theme-studio/snapify.module.json +175 -0
  173. package/template/modules/ai-theme-studio/src/admin/HistoryPage.tsx +91 -0
  174. package/template/modules/ai-theme-studio/src/admin/StudioPage.tsx +414 -0
  175. package/template/modules/ai-theme-studio/src/admin/index.tsx +11 -0
  176. package/template/modules/ai-theme-studio/src/lib/images.ts +240 -0
  177. package/template/modules/ai-theme-studio/src/lib/llm.ts +123 -0
  178. package/template/modules/ai-theme-studio/src/lib/normalize.ts +714 -0
  179. package/template/modules/ai-theme-studio/src/lib/prompts.ts +198 -0
  180. package/template/modules/ai-theme-studio/src/server.ts +137 -0
  181. package/template/modules/ai-theme-studio/src/types.ts +112 -0
  182. package/template/modules/calendar/screenshot.jpg +0 -0
  183. package/template/modules/calendar/snapify.module.json +45 -0
  184. package/template/modules/calendar/src/admin/EventsPage.tsx +217 -0
  185. package/template/modules/calendar/src/admin/index.tsx +11 -0
  186. package/template/modules/calendar/src/public/index.tsx +231 -0
  187. package/template/modules/calendar/src/server.ts +143 -0
  188. package/template/modules/calendar/src/types.ts +25 -0
  189. package/template/modules/cart/screenshot.jpg +0 -0
  190. package/template/modules/cart/snapify.module.json +90 -0
  191. package/template/modules/cart/src/admin/index.tsx +265 -0
  192. package/template/modules/cart/src/public/CartPage.tsx +198 -0
  193. package/template/modules/cart/src/public/index.tsx +261 -0
  194. package/template/modules/cart/src/public/useQuote.ts +67 -0
  195. package/template/modules/cart/src/server.ts +148 -0
  196. package/template/modules/cart/src/types.ts +31 -0
  197. package/template/modules/checkout/screenshot.jpg +0 -0
  198. package/template/modules/checkout/snapify.module.json +264 -0
  199. package/template/modules/checkout/src/admin/OrderDetailPage.tsx +304 -0
  200. package/template/modules/checkout/src/admin/badges.tsx +28 -0
  201. package/template/modules/checkout/src/admin/index.tsx +236 -0
  202. package/template/modules/checkout/src/public/CheckoutPage.tsx +461 -0
  203. package/template/modules/checkout/src/public/OrderPages.tsx +153 -0
  204. package/template/modules/checkout/src/public/index.tsx +23 -0
  205. package/template/modules/checkout/src/server.ts +383 -0
  206. package/template/modules/checkout/src/types.ts +70 -0
  207. package/template/modules/customers/screenshot.jpg +0 -0
  208. package/template/modules/customers/snapify.module.json +115 -0
  209. package/template/modules/customers/src/admin/CustomerDetailPage.tsx +274 -0
  210. package/template/modules/customers/src/admin/index.tsx +194 -0
  211. package/template/modules/customers/src/public/AccountPages.tsx +470 -0
  212. package/template/modules/customers/src/public/AddressForm.tsx +115 -0
  213. package/template/modules/customers/src/public/AuthPages.tsx +349 -0
  214. package/template/modules/customers/src/public/Avatar.tsx +29 -0
  215. package/template/modules/customers/src/public/ProfileSection.tsx +291 -0
  216. package/template/modules/customers/src/public/index.tsx +137 -0
  217. package/template/modules/customers/src/public/session.ts +51 -0
  218. package/template/modules/customers/src/server.ts +421 -0
  219. package/template/modules/customers/src/types.ts +53 -0
  220. package/template/modules/recaptcha/logo.jpg +0 -0
  221. package/template/modules/recaptcha/screenshot.jpg +0 -0
  222. package/template/modules/recaptcha/snapify.module.json +99 -0
  223. package/template/modules/recaptcha/src/public/index.tsx +94 -0
  224. package/template/modules/recaptcha/src/server.ts +65 -0
  225. package/template/modules/recaptcha/src/types.ts +18 -0
  226. package/template/modules/shop/screenshot.jpg +0 -0
  227. package/template/modules/shop/snapify.module.json +340 -0
  228. package/template/modules/shop/src/admin/CategoriesPage.tsx +224 -0
  229. package/template/modules/shop/src/admin/ProductEditor.tsx +313 -0
  230. package/template/modules/shop/src/admin/ProductsPage.tsx +307 -0
  231. package/template/modules/shop/src/admin/index.tsx +14 -0
  232. package/template/modules/shop/src/public/Catalog.tsx +244 -0
  233. package/template/modules/shop/src/public/NotFound.tsx +22 -0
  234. package/template/modules/shop/src/public/ProductPage.tsx +195 -0
  235. package/template/modules/shop/src/public/index.tsx +134 -0
  236. package/template/modules/shop/src/public/useFetch.ts +26 -0
  237. package/template/modules/shop/src/server.ts +493 -0
  238. package/template/modules/shop/src/shared.ts +41 -0
  239. package/template/modules/shop/src/types.ts +60 -0
  240. package/template/modules/whatsapp/screenshot.jpg +0 -0
  241. package/template/modules/whatsapp/snapify.module.json +121 -0
  242. package/template/modules/whatsapp/src/public.tsx +119 -0
  243. package/template/modules/wp-seo-migrator/ARCHITECTURE.md +113 -0
  244. package/template/modules/wp-seo-migrator/README.md +21 -0
  245. package/template/modules/wp-seo-migrator/fixtures/aioseo-sample.csv +3 -0
  246. package/template/modules/wp-seo-migrator/fixtures/sample-exporter.json +39 -0
  247. package/template/modules/wp-seo-migrator/fixtures/sample-page.html +12 -0
  248. package/template/modules/wp-seo-migrator/fixtures/sample.htaccess +3 -0
  249. package/template/modules/wp-seo-migrator/screenshot.jpg +0 -0
  250. package/template/modules/wp-seo-migrator/snapify.module.json +87 -0
  251. package/template/modules/wp-seo-migrator/src/admin/HistoryPage.tsx +64 -0
  252. package/template/modules/wp-seo-migrator/src/admin/WizardPage.tsx +788 -0
  253. package/template/modules/wp-seo-migrator/src/admin/i18n.ts +156 -0
  254. package/template/modules/wp-seo-migrator/src/admin/index.tsx +11 -0
  255. package/template/modules/wp-seo-migrator/src/connectors/CUSTOM_CONNECTOR.md +31 -0
  256. package/template/modules/wp-seo-migrator/src/connectors/csvSeoFactory.ts +106 -0
  257. package/template/modules/wp-seo-migrator/src/connectors/exporter.ts +96 -0
  258. package/template/modules/wp-seo-migrator/src/connectors/gscCsv.ts +53 -0
  259. package/template/modules/wp-seo-migrator/src/connectors/htaccess.ts +65 -0
  260. package/template/modules/wp-seo-migrator/src/connectors/htmlCrawler.ts +90 -0
  261. package/template/modules/wp-seo-migrator/src/connectors/index.ts +113 -0
  262. package/template/modules/wp-seo-migrator/src/connectors/pluginCsv.ts +77 -0
  263. package/template/modules/wp-seo-migrator/src/connectors/rankMathCsv.ts +77 -0
  264. package/template/modules/wp-seo-migrator/src/connectors/redirection.ts +62 -0
  265. package/template/modules/wp-seo-migrator/src/connectors/sitemap.ts +44 -0
  266. package/template/modules/wp-seo-migrator/src/connectors/utils.ts +111 -0
  267. package/template/modules/wp-seo-migrator/src/connectors/wxr.ts +103 -0
  268. package/template/modules/wp-seo-migrator/src/connectors/yoastCsv.ts +56 -0
  269. package/template/modules/wp-seo-migrator/src/pipeline/analyze.ts +158 -0
  270. package/template/modules/wp-seo-migrator/src/pipeline/htmlParse.ts +58 -0
  271. package/template/modules/wp-seo-migrator/src/pipeline/remoteAuto.ts +328 -0
  272. package/template/modules/wp-seo-migrator/src/server.ts +492 -0
  273. package/template/modules/wp-seo-migrator/src/types.ts +151 -0
  274. package/template/modules/wp-seo-migrator/tests/connectors-extra.test.ts +39 -0
  275. package/template/modules/wp-seo-migrator/tests/merge.test.ts +25 -0
  276. package/template/package-lock.json +6016 -0
  277. package/template/package.json +74 -0
  278. package/template/public/images/photos/caravane-chameaux-desert.webp +0 -0
  279. package/template/public/images/photos/hammamet-medina-plage.jpg +0 -0
  280. package/template/public/images/photos/maison-campagne-collines.webp +0 -0
  281. package/template/public/images/photos/maisons-troglodytes-desert.jpg +0 -0
  282. package/template/public/images/photos/panorama-ville.jpg +0 -0
  283. package/template/public/images/photos/preveris-accessibilite-erp.jpg +0 -0
  284. package/template/public/images/photos/preveris-collectivites.jpg +0 -0
  285. package/template/public/images/photos/preveris-etudes-plans.jpg +0 -0
  286. package/template/public/images/photos/preveris-hero-erp.jpg +0 -0
  287. package/template/public/images/photos/preveris-ssi-incendie.jpg +0 -0
  288. package/template/public/images/photos/preveris-suivi-hotel.jpg +0 -0
  289. package/template/public/images/photos/ruelle-bleue-medina.jpg +0 -0
  290. package/template/public/images/photos/sidi-bou-said-port.webp +0 -0
  291. package/template/public/images/photos/terrasse-blanche-mer-voilier.jpg +0 -0
  292. package/template/public/landing/hero-ai-cms.jpg +0 -0
  293. package/template/public/landing/shot-dogga.jpg +0 -0
  294. package/template/public/landing/shot-mahdia.jpg +0 -0
  295. package/template/public/landing/shot-sidibou.jpg +0 -0
  296. package/template/public/llms.txt +35 -0
  297. package/template/public/logo.svg +10 -0
  298. package/template/scripts/app-pack.ts +155 -0
  299. package/template/scripts/app-publish.ts +123 -0
  300. package/template/scripts/apply-ecommerce-home.ts +196 -0
  301. package/template/scripts/auto-deploy-poll.sh +13 -0
  302. package/template/scripts/db-backup.sh +16 -0
  303. package/template/scripts/db-restore.sh +11 -0
  304. package/template/scripts/deploy.sh +34 -0
  305. package/template/scripts/github-webhook-deploy.sh +7 -0
  306. package/template/scripts/install-new-modules.ts +96 -0
  307. package/template/scripts/refresh-demo-baseline.ts +9 -0
  308. package/template/scripts/reinstall-marketplace-packs.ts +51 -0
  309. package/template/scripts/restore-classic-home.ts +13 -0
  310. package/template/scripts/sdk-pack.ts +289 -0
  311. package/template/scripts/sdk-publish.ts +75 -0
  312. package/template/scripts/seed-demo-products.ts +120 -0
  313. package/template/scripts/seed-theme-content-packs.ts +42 -0
  314. package/template/scripts/snapify-module.ts +207 -0
  315. package/template/scripts/test-theme-switch.ts +24 -0
  316. package/template/sdk/admin.css +18 -0
  317. package/template/sdk/admin.ts +95 -0
  318. package/template/sdk/build.ts +249 -0
  319. package/template/sdk/commerce.ts +512 -0
  320. package/template/sdk/content.ts +76 -0
  321. package/template/sdk/icons.ts +101 -0
  322. package/template/sdk/image.ts +60 -0
  323. package/template/sdk/index.ts +500 -0
  324. package/template/sdk/package.ts +298 -0
  325. package/template/sdk/recaptcha.tsx +122 -0
  326. package/template/sdk/settings.ts +84 -0
  327. package/template/sdk/theme.css +29 -0
  328. package/template/sdk/theme.ts +100 -0
  329. package/template/sdk/ui/commerce.tsx +385 -0
  330. package/template/sdk/ui/orders.tsx +136 -0
  331. package/template/sdk-kit/CHANGELOG.md +17 -0
  332. package/template/sdk-kit/LICENSE.md +47 -0
  333. package/template/sdk-kit/README.md +81 -0
  334. package/template/sdk-kit/cli.ts +339 -0
  335. package/template/sdk-kit/create-snapify/README.md +28 -0
  336. package/template/sdk-kit/create-snapify/create-snapify.mjs +11 -0
  337. package/template/sdk-kit/create-snapify/package.template.json +16 -0
  338. package/template/sdk-kit/package.template.json +95 -0
  339. package/template/sdk-kit/templates/common/README.md.tpl +27 -0
  340. package/template/sdk-kit/templates/common/_gitignore +3 -0
  341. package/template/sdk-kit/templates/common/package.json.tpl +19 -0
  342. package/template/sdk-kit/templates/common/src/snapify-env.d.ts +2 -0
  343. package/template/sdk-kit/templates/common/tsconfig.json +15 -0
  344. package/template/sdk-kit/templates/module/snapify.module.json.tpl +33 -0
  345. package/template/sdk-kit/templates/module/src/admin.tsx +53 -0
  346. package/template/sdk-kit/templates/module/src/public.tsx +49 -0
  347. package/template/sdk-kit/templates/module/src/server.ts +30 -0
  348. package/template/sdk-kit/templates/module/src/types.ts +19 -0
  349. package/template/sdk-kit/templates/theme/snapify.theme.json.tpl +22 -0
  350. package/template/sdk-kit/templates/theme/src/Footer.tsx +40 -0
  351. package/template/sdk-kit/templates/theme/src/Header.tsx +47 -0
  352. package/template/sdk-kit/templates/theme/src/Views.tsx +36 -0
  353. package/template/sdk-kit/templates/theme/src/blocks.tsx +93 -0
  354. package/template/sdk-kit/templates/theme/src/index.tsx +30 -0
  355. package/template/sdk-kit/templates/theme/src/site.tsx +59 -0
  356. package/template/sdk-kit/templates/theme/src/styles.css +71 -0
  357. package/template/server/client/routes.ts +252 -0
  358. package/template/server/cms/analyticsStore.ts +180 -0
  359. package/template/server/cms/auth.ts +155 -0
  360. package/template/server/cms/blockCatalog.ts +342 -0
  361. package/template/server/cms/blocks.ts +521 -0
  362. package/template/server/cms/contentMigration.ts +1119 -0
  363. package/template/server/cms/defaults.ts +303 -0
  364. package/template/server/cms/permissions.ts +154 -0
  365. package/template/server/cms/restoreClassicHome.ts +183 -0
  366. package/template/server/cms/revisions.ts +99 -0
  367. package/template/server/cms/scheduler.ts +78 -0
  368. package/template/server/cms/seed.ts +72 -0
  369. package/template/server/cms/seoAnalyzer.ts +213 -0
  370. package/template/server/cms/store.ts +122 -0
  371. package/template/server/cms/themeContent.ts +1386 -0
  372. package/template/server/cms/themePacks/sidibou-branding.json +1 -0
  373. package/template/server/cms/themePacks/sidibou-home.json +1 -0
  374. package/template/server/cms/themePacks/sidibou-menus.json +1 -0
  375. package/template/server/cms/types.ts +432 -0
  376. package/template/server/community/routes.ts +410 -0
  377. package/template/server/db/client.ts +43 -0
  378. package/template/server/db/repository.ts +389 -0
  379. package/template/server/db/schema.ts +726 -0
  380. package/template/server/demo/cmsReset.ts +196 -0
  381. package/template/server/developers/sdk.ts +85 -0
  382. package/template/server/geoip.ts +15 -0
  383. package/template/server/http.ts +53 -0
  384. package/template/server/mail.ts +216 -0
  385. package/template/server/marketplace/catalog.ts +74 -0
  386. package/template/server/marketplace/packageValidate.ts +475 -0
  387. package/template/server/marketplace/payments.ts +193 -0
  388. package/template/server/marketplace/routes.ts +850 -0
  389. package/template/server/marketplace/signing.ts +116 -0
  390. package/template/server/marketplace/syncOfficial.ts +282 -0
  391. package/template/server/media/images.ts +63 -0
  392. package/template/server/middleware/adminAuth.ts +134 -0
  393. package/template/server/modules/legacy.ts +44 -0
  394. package/template/server/modules/manager.ts +1122 -0
  395. package/template/server/modules/marketplace.ts +178 -0
  396. package/template/server/modules/outbound.ts +178 -0
  397. package/template/server/modules/purchases.ts +149 -0
  398. package/template/server/modules/records.ts +168 -0
  399. package/template/server/modules/themeHtml.ts +32 -0
  400. package/template/server/modules/trust.ts +16 -0
  401. package/template/server/modules/types.ts +147 -0
  402. package/template/server/platform/auth.ts +223 -0
  403. package/template/server/platform/clientWelcome.ts +168 -0
  404. package/template/server/platform/clients.ts +139 -0
  405. package/template/server/platform/dailyImprove.ts +356 -0
  406. package/template/server/platform/flouci.ts +126 -0
  407. package/template/server/platform/host.ts +69 -0
  408. package/template/server/platform/hostingProviders.ts +143 -0
  409. package/template/server/platform/licenseOrders.ts +291 -0
  410. package/template/server/platform/money.ts +42 -0
  411. package/template/server/platform/passwords.ts +41 -0
  412. package/template/server/platform/region.ts +86 -0
  413. package/template/server/platform/routes.ts +225 -0
  414. package/template/server/platform/seed.ts +82 -0
  415. package/template/server/platform/settings.ts +72 -0
  416. package/template/server/routes/adminAccount.ts +403 -0
  417. package/template/server/routes/adminCms.ts +808 -0
  418. package/template/server/routes/adminSystem.ts +243 -0
  419. package/template/server/routes/adminUsers.ts +449 -0
  420. package/template/server/routes/googleOAuth.ts +327 -0
  421. package/template/server/routes/modules.ts +323 -0
  422. package/template/server/routes/publicCms.ts +313 -0
  423. package/template/server/routes/seoPublic.ts +158 -0
  424. package/template/server/security/accounts.ts +121 -0
  425. package/template/server/security/audit.ts +143 -0
  426. package/template/server/security/authTokens.ts +74 -0
  427. package/template/server/security/ip.ts +68 -0
  428. package/template/server/security/rateLimit.ts +85 -0
  429. package/template/server/security/retention.ts +46 -0
  430. package/template/server/security/secrets.ts +44 -0
  431. package/template/server/security/sessions.ts +140 -0
  432. package/template/server/security/totp.ts +101 -0
  433. package/template/server/superadmin/analytics.ts +109 -0
  434. package/template/server/superadmin/auth.ts +92 -0
  435. package/template/server/superadmin/backlinksCatalog.ts +210 -0
  436. package/template/server/superadmin/frSeoContent.ts +165 -0
  437. package/template/server/superadmin/landingSeo.ts +675 -0
  438. package/template/server/superadmin/ops.ts +238 -0
  439. package/template/server/superadmin/routes.ts +1095 -0
  440. package/template/server/superadmin/tnSeoContent.ts +130 -0
  441. package/template/server.ts +522 -0
  442. package/template/src/App.tsx +263 -0
  443. package/template/src/admin/AdminApp.tsx +162 -0
  444. package/template/src/admin/account/AuthLayout.tsx +57 -0
  445. package/template/src/admin/account/SecurityForms.tsx +276 -0
  446. package/template/src/admin/admin.css +127 -0
  447. package/template/src/admin/context/AuthContext.tsx +147 -0
  448. package/template/src/admin/context/SiteContext.tsx +50 -0
  449. package/template/src/admin/editor/BlockLibrary.tsx +173 -0
  450. package/template/src/admin/editor/BlocksPanel.tsx +396 -0
  451. package/template/src/admin/editor/EditorBits.tsx +106 -0
  452. package/template/src/admin/editor/PreviewFrame.tsx +145 -0
  453. package/template/src/admin/editor/RichTextEditor.tsx +276 -0
  454. package/template/src/admin/editor/SeoPanel.tsx +349 -0
  455. package/template/src/admin/editor/StyleEditor.tsx +114 -0
  456. package/template/src/admin/editor/blockSchemas.ts +699 -0
  457. package/template/src/admin/editor/fields.tsx +486 -0
  458. package/template/src/admin/layout/AdminShell.tsx +418 -0
  459. package/template/src/admin/layout/nav.ts +95 -0
  460. package/template/src/admin/lib/api.ts +408 -0
  461. package/template/src/admin/lib/audit.ts +141 -0
  462. package/template/src/admin/lib/format.ts +84 -0
  463. package/template/src/admin/lib/hooks.ts +125 -0
  464. package/template/src/admin/main.tsx +16 -0
  465. package/template/src/admin/modules/InstallDialog.tsx +160 -0
  466. package/template/src/admin/modules/SettingsForm.tsx +145 -0
  467. package/template/src/admin/modules/kit.tsx +127 -0
  468. package/template/src/admin/modules/labels.tsx +226 -0
  469. package/template/src/admin/pages/AccountSetupPage.tsx +62 -0
  470. package/template/src/admin/pages/AnalyticsPage.tsx +206 -0
  471. package/template/src/admin/pages/BrandingPage.tsx +154 -0
  472. package/template/src/admin/pages/DashboardPage.tsx +239 -0
  473. package/template/src/admin/pages/EngagementPage.tsx +168 -0
  474. package/template/src/admin/pages/FormsPage.tsx +435 -0
  475. package/template/src/admin/pages/GeneralPage.tsx +120 -0
  476. package/template/src/admin/pages/LoginPage.tsx +249 -0
  477. package/template/src/admin/pages/MaintenancePage.tsx +125 -0
  478. package/template/src/admin/pages/MarketplacePage.tsx +426 -0
  479. package/template/src/admin/pages/MediaPage.tsx +251 -0
  480. package/template/src/admin/pages/MenusPage.tsx +446 -0
  481. package/template/src/admin/pages/ModuleAdminPage.tsx +113 -0
  482. package/template/src/admin/pages/ModuleDetailPage.tsx +293 -0
  483. package/template/src/admin/pages/ModulesPage.tsx +135 -0
  484. package/template/src/admin/pages/NewsletterPage.tsx +193 -0
  485. package/template/src/admin/pages/PageEditorPage.tsx +322 -0
  486. package/template/src/admin/pages/PagesListPage.tsx +277 -0
  487. package/template/src/admin/pages/PostEditorPage.tsx +292 -0
  488. package/template/src/admin/pages/PostsListPage.tsx +187 -0
  489. package/template/src/admin/pages/ProfilePage.tsx +489 -0
  490. package/template/src/admin/pages/ResetPasswordPage.tsx +110 -0
  491. package/template/src/admin/pages/SeoPage.tsx +670 -0
  492. package/template/src/admin/pages/SettingsPage.tsx +189 -0
  493. package/template/src/admin/pages/ThemeCustomizePage.tsx +170 -0
  494. package/template/src/admin/pages/ThemesPage.tsx +292 -0
  495. package/template/src/admin/pages/UsersPage.tsx +57 -0
  496. package/template/src/admin/pages/WidgetsPage.tsx +200 -0
  497. package/template/src/admin/seo/GoogleSetup.tsx +529 -0
  498. package/template/src/admin/settings/EmailTab.tsx +293 -0
  499. package/template/src/admin/settings/OtherTabs.tsx +270 -0
  500. package/template/src/admin/settings/SecurityTab.tsx +172 -0
  501. package/template/src/admin/settings/controls.tsx +133 -0
  502. package/template/src/admin/ui/Pagination.tsx +170 -0
  503. package/template/src/admin/ui/SaveBar.tsx +77 -0
  504. package/template/src/admin/ui/TagInput.tsx +54 -0
  505. package/template/src/admin/ui/charts.tsx +108 -0
  506. package/template/src/admin/ui/media.tsx +265 -0
  507. package/template/src/admin/ui/overlays.tsx +239 -0
  508. package/template/src/admin/ui/primitives.tsx +544 -0
  509. package/template/src/admin/users/AuditTab.tsx +104 -0
  510. package/template/src/admin/users/RolesTab.tsx +368 -0
  511. package/template/src/admin/users/UsersTab.tsx +723 -0
  512. package/template/src/admin/users/shared.tsx +278 -0
  513. package/template/src/cms/icons.ts +7 -0
  514. package/template/src/components/CookieBanner.tsx +166 -0
  515. package/template/src/components/MaintenanceGate.tsx +66 -0
  516. package/template/src/components/SiteAnalytics.tsx +64 -0
  517. package/template/src/components/SnapifyLogo.tsx +44 -0
  518. package/template/src/components/cms/BlockRenderer.tsx +154 -0
  519. package/template/src/components/cms/WidgetArea.tsx +193 -0
  520. package/template/src/context/SiteConfigContext.tsx +130 -0
  521. package/template/src/demoBase.ts +23 -0
  522. package/template/src/index.css +90 -0
  523. package/template/src/main.tsx +16 -0
  524. package/template/src/modules/ModuleHost.tsx +197 -0
  525. package/template/src/preview.ts +63 -0
  526. package/template/src/runtime.ts +38 -0
  527. package/template/src/themes/ThemeHost.tsx +168 -0
  528. package/template/src/themes/fallback.tsx +71 -0
  529. package/template/src/types.ts +94 -0
  530. package/template/src/views/BlogPostView.tsx +68 -0
  531. package/template/src/views/CmsPageView.tsx +34 -0
  532. package/template/start-pm2.sh +3 -0
  533. package/template/superadmin.html +20 -0
  534. package/template/themes/ai-canvas/screenshot.jpg +0 -0
  535. package/template/themes/ai-canvas/snapify.theme.json +96 -0
  536. package/template/themes/ai-canvas/src/CeeSimulator.tsx +247 -0
  537. package/template/themes/ai-canvas/src/Footer.tsx +190 -0
  538. package/template/themes/ai-canvas/src/Header.tsx +324 -0
  539. package/template/themes/ai-canvas/src/Layout.tsx +56 -0
  540. package/template/themes/ai-canvas/src/NotFound.tsx +58 -0
  541. package/template/themes/ai-canvas/src/Post.tsx +26 -0
  542. package/template/themes/ai-canvas/src/SnapifyLogo.tsx +44 -0
  543. package/template/themes/ai-canvas/src/blocks/CollectionBlocks.tsx +711 -0
  544. package/template/themes/ai-canvas/src/blocks/ContentBlocks.tsx +318 -0
  545. package/template/themes/ai-canvas/src/blocks/ConversionBlocks.tsx +559 -0
  546. package/template/themes/ai-canvas/src/blocks/HeaderBlocks.tsx +341 -0
  547. package/template/themes/ai-canvas/src/index.tsx +54 -0
  548. package/template/themes/ai-canvas/src/kit.tsx +398 -0
  549. package/template/themes/ai-canvas/src/site.ts +29 -0
  550. package/template/themes/ai-canvas/src/styles.css +317 -0
  551. package/template/themes/dogga/screenshot.jpg +0 -0
  552. package/template/themes/dogga/snapify.theme.json +55 -0
  553. package/template/themes/dogga/src/Brand.tsx +41 -0
  554. package/template/themes/dogga/src/Footer.tsx +202 -0
  555. package/template/themes/dogga/src/Header.tsx +239 -0
  556. package/template/themes/dogga/src/Layout.tsx +43 -0
  557. package/template/themes/dogga/src/Views.tsx +71 -0
  558. package/template/themes/dogga/src/blocks/CollectionBlocks.tsx +674 -0
  559. package/template/themes/dogga/src/blocks/ContentBlocks.tsx +307 -0
  560. package/template/themes/dogga/src/blocks/ConversionBlocks.tsx +571 -0
  561. package/template/themes/dogga/src/blocks/HeaderBlocks.tsx +289 -0
  562. package/template/themes/dogga/src/index.tsx +53 -0
  563. package/template/themes/dogga/src/kit.tsx +362 -0
  564. package/template/themes/dogga/src/site.ts +56 -0
  565. package/template/themes/dogga/src/styles.css +396 -0
  566. package/template/themes/mahdia/screenshot.jpg +0 -0
  567. package/template/themes/mahdia/snapify.theme.json +65 -0
  568. package/template/themes/mahdia/src/Brand.tsx +39 -0
  569. package/template/themes/mahdia/src/Footer.tsx +210 -0
  570. package/template/themes/mahdia/src/Header.tsx +291 -0
  571. package/template/themes/mahdia/src/Layout.tsx +44 -0
  572. package/template/themes/mahdia/src/Views.tsx +79 -0
  573. package/template/themes/mahdia/src/blocks/CollectionBlocks.tsx +674 -0
  574. package/template/themes/mahdia/src/blocks/ContentBlocks.tsx +307 -0
  575. package/template/themes/mahdia/src/blocks/ConversionBlocks.tsx +571 -0
  576. package/template/themes/mahdia/src/blocks/HeaderBlocks.tsx +289 -0
  577. package/template/themes/mahdia/src/index.tsx +53 -0
  578. package/template/themes/mahdia/src/kit.tsx +362 -0
  579. package/template/themes/mahdia/src/site.ts +75 -0
  580. package/template/themes/mahdia/src/styles.css +446 -0
  581. package/template/themes/preveris/screenshot.jpg +0 -0
  582. package/template/themes/preveris/snapify.theme.json +126 -0
  583. package/template/themes/preveris/src/Brand.tsx +44 -0
  584. package/template/themes/preveris/src/Footer.tsx +202 -0
  585. package/template/themes/preveris/src/Header.tsx +239 -0
  586. package/template/themes/preveris/src/Layout.tsx +42 -0
  587. package/template/themes/preveris/src/Views.tsx +71 -0
  588. package/template/themes/preveris/src/blocks/CollectionBlocks.tsx +678 -0
  589. package/template/themes/preveris/src/blocks/ContentBlocks.tsx +307 -0
  590. package/template/themes/preveris/src/blocks/ConversionBlocks.tsx +571 -0
  591. package/template/themes/preveris/src/blocks/HeaderBlocks.tsx +299 -0
  592. package/template/themes/preveris/src/index.tsx +53 -0
  593. package/template/themes/preveris/src/kit.tsx +365 -0
  594. package/template/themes/preveris/src/site.ts +79 -0
  595. package/template/themes/preveris/src/styles.css +446 -0
  596. package/template/themes/sidibou/screenshot.jpg +0 -0
  597. package/template/themes/sidibou/snapify.theme.json +21 -0
  598. package/template/themes/sidibou/src/CeeSimulator.tsx +247 -0
  599. package/template/themes/sidibou/src/Footer.tsx +203 -0
  600. package/template/themes/sidibou/src/Header.tsx +324 -0
  601. package/template/themes/sidibou/src/Layout.tsx +53 -0
  602. package/template/themes/sidibou/src/NotFound.tsx +58 -0
  603. package/template/themes/sidibou/src/Post.tsx +26 -0
  604. package/template/themes/sidibou/src/SnapifyLogo.tsx +44 -0
  605. package/template/themes/sidibou/src/blocks/CollectionBlocks.tsx +711 -0
  606. package/template/themes/sidibou/src/blocks/ContentBlocks.tsx +318 -0
  607. package/template/themes/sidibou/src/blocks/ConversionBlocks.tsx +559 -0
  608. package/template/themes/sidibou/src/blocks/HeaderBlocks.tsx +341 -0
  609. package/template/themes/sidibou/src/index.tsx +54 -0
  610. package/template/themes/sidibou/src/kit.tsx +398 -0
  611. package/template/themes/sidibou/src/site.ts +28 -0
  612. package/template/themes/sidibou/src/styles.css +317 -0
  613. package/template/tsconfig.json +33 -0
  614. package/template/vite.config.ts +42 -0
package/LICENSE.md ADDED
@@ -0,0 +1,24 @@
1
+ # Licence — create-snapify-app / Snapify
2
+
3
+ Copyright © 2026 NOVALABS WEB DESIGN — Tunisie
4
+ Contact : contact@novalabs.tn · +216 24 734 647
5
+
6
+ Tous droits réservés.
7
+
8
+ Ce paquet npm (`create-snapify-app`) et le code source Snapify qu’il embarque sont la propriété exclusive de
9
+ NOVALABS WEB DESIGN.
10
+
11
+ ## Autorisation d’installation
12
+
13
+ NOVALABS autorise l’utilisation de ce paquet **uniquement pour installer et exploiter une instance Snapify** sur
14
+ votre propre hébergement, sous réserve d’une licence Snapify valide lorsque celle-ci est requise.
15
+
16
+ ## Restrictions
17
+
18
+ Sauf accord écrit de NOVALABS WEB DESIGN, il est interdit de :
19
+
20
+ - redistribuer, republier ou revendre le code source, modifié ou non ;
21
+ - utiliser le code pour créer un produit concurrent ;
22
+ - retirer les mentions de copyright.
23
+
24
+ CE LOGICIEL EST FOURNI « EN L’ÉTAT », SANS GARANTIE D’AUCUNE SORTE.
package/README.md CHANGED
@@ -1,3 +1,56 @@
1
- # Temporary Holding Version
1
+ # create-snapify-app
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Installe **Snapify** (CMS + e-commerce : backend Express et frontends React) en une commande.
4
+
5
+ ```bash
6
+ npx create-snapify-app@latest mon-site
7
+ ```
8
+
9
+ Le wizard demande :
10
+
11
+ 1. **Domaine** (ex. `boutique.exemple.tn`) → URL publique HTTPS
12
+ 2. **PostgreSQL** (hôte, port, utilisateur, mot de passe, base) — ou une `DATABASE_URL` complète
13
+ 3. **Compte admin** (e-mail + mot de passe)
14
+
15
+ Puis le CLI copie le code source, écrit `.env`, lance `npm install` et `npm run build`.
16
+
17
+ ```bash
18
+ cd mon-site
19
+ NODE_ENV=production npm start
20
+ ```
21
+
22
+ Administration : `https://votre-domaine/administrator`
23
+
24
+ ## Prérequis
25
+
26
+ - **Node.js** 22+ (ou ≥ 20.19)
27
+ - **PostgreSQL** 17 (instance existante, ou `docker compose` fourni dans le projet)
28
+
29
+ ## Sans questions (CI / scripts)
30
+
31
+ ```bash
32
+ npx create-snapify-app@latest mon-site --yes \
33
+ --domain boutique.exemple.tn \
34
+ --database-url "postgres://user:pass@127.0.0.1:5432/snapify" \
35
+ --admin-email admin@exemple.tn \
36
+ --admin-password 'MotDePasseFort1'
37
+ ```
38
+
39
+ ## Publication (mainteneurs NOVALABS)
40
+
41
+ Depuis le dépôt Snapify :
42
+
43
+ ```bash
44
+ npm run app:pack
45
+ npm run app:publish -- --dry-run
46
+ npm run app:publish -- --otp 123456
47
+ ```
48
+
49
+ ## Différence avec `create-snapify`
50
+
51
+ | Paquet | Rôle |
52
+ | --- | --- |
53
+ | `create-snapify` | Projet **module / thème** (kit développeur) |
54
+ | `create-snapify-app` | **CMS Snapify complet** (site + admin) |
55
+
56
+ © 2026 NOVALABS WEB DESIGN — Tunisie. Licence : voir `LICENSE.md`.
@@ -0,0 +1,174 @@
1
+ #!/usr/bin/env node
2
+ /*! create-snapify-app — © 2026 NOVALABS WEB DESIGN — licence : LICENSE.md */
3
+ import { spawnSync } from 'node:child_process';
4
+ import fs from 'node:fs/promises';
5
+ import path from 'node:path';
6
+ import { parseArgs, printHelp } from '../lib/args.mjs';
7
+ import { copyTemplate } from '../lib/copy.mjs';
8
+ import {
9
+ buildDatabaseUrl,
10
+ buildEnvFile,
11
+ domainFromPublicUrl,
12
+ normalizePublicUrl,
13
+ } from '../lib/env.mjs';
14
+ import { ask, askSecret, askYesNo } from '../lib/prompt.mjs';
15
+
16
+ const { flags, positionals } = parseArgs(process.argv.slice(2));
17
+
18
+ if (flags.help) {
19
+ printHelp();
20
+ process.exit(0);
21
+ }
22
+
23
+ const nonInteractive = Boolean(flags.yes);
24
+ const skipInstall = Boolean(flags['skip-install']);
25
+
26
+ function fail(msg) {
27
+ console.error(`✖ ${msg}`);
28
+ process.exit(1);
29
+ }
30
+
31
+ function ok(msg) {
32
+ console.log(`✔ ${msg}`);
33
+ }
34
+
35
+ async function main() {
36
+ console.log('\n Snapify — installation complète (backend + frontend)\n');
37
+
38
+ const targetName = positionals[0] || (nonInteractive ? 'snapify' : await ask('Dossier du projet', 'snapify'));
39
+ const dest = path.resolve(process.cwd(), targetName);
40
+
41
+ let publicUrl;
42
+ if (flags.domain) {
43
+ publicUrl = normalizePublicUrl(String(flags.domain));
44
+ } else if (nonInteractive) {
45
+ fail('--domain est requis avec --yes');
46
+ } else {
47
+ publicUrl = normalizePublicUrl(await ask('Domaine public (ex. boutique.exemple.tn)', 'localhost:3000'));
48
+ if (publicUrl.includes('localhost')) {
49
+ publicUrl = publicUrl.replace(/^https:/, 'http:');
50
+ }
51
+ }
52
+ const domain = domainFromPublicUrl(publicUrl);
53
+
54
+ let databaseUrl = flags['database-url'] ? String(flags['database-url']) : '';
55
+ if (!databaseUrl) {
56
+ if (nonInteractive && !(flags['db-host'] && flags['db-user'] && flags['db-password'] && flags['db-name'])) {
57
+ fail('--database-url ou --db-* requis avec --yes');
58
+ }
59
+ if (!nonInteractive) {
60
+ console.log('\n PostgreSQL');
61
+ const paste = await askYesNo('Coller une DATABASE_URL complète', false);
62
+ if (paste) {
63
+ databaseUrl = await ask('DATABASE_URL');
64
+ }
65
+ }
66
+ if (!databaseUrl) {
67
+ const host = String(flags['db-host'] || (!nonInteractive ? await ask('Hôte', '127.0.0.1') : ''));
68
+ const port = String(flags['db-port'] || (!nonInteractive ? await ask('Port', '5432') : '5432'));
69
+ const user = String(flags['db-user'] || (!nonInteractive ? await ask('Utilisateur', 'snapify') : ''));
70
+ const password = String(
71
+ flags['db-password'] ||
72
+ (!nonInteractive ? (await askSecret('Mot de passe')) || (await ask('Mot de passe (visible)')) : ''),
73
+ );
74
+ const database = String(flags['db-name'] || (!nonInteractive ? await ask('Base', 'snapify') : ''));
75
+ if (!host || !user || !password || !database) fail('Identifiants PostgreSQL incomplets');
76
+ databaseUrl = buildDatabaseUrl({ host, port, user, password, database });
77
+ }
78
+ }
79
+
80
+ let adminEmail = flags['admin-email'] ? String(flags['admin-email']) : '';
81
+ let adminPassword = flags['admin-password'] ? String(flags['admin-password']) : '';
82
+ if (!adminEmail) {
83
+ if (nonInteractive) fail('--admin-email requis avec --yes');
84
+ adminEmail = await ask('E-mail administrateur', `admin@${domain === 'localhost' ? 'localhost' : domain}`);
85
+ }
86
+ if (!adminPassword) {
87
+ if (nonInteractive) fail('--admin-password requis avec --yes');
88
+ adminPassword = (await askSecret('Mot de passe administrateur')) || (await ask('Mot de passe administrateur'));
89
+ }
90
+ if (adminPassword.length < 8) fail('Mot de passe administrateur : 8 caractères minimum');
91
+
92
+ const port = String(flags.port || (!nonInteractive ? await ask('Port d’écoute', '3000') : '3000'));
93
+
94
+ console.log(`\n→ Copie des sources vers ${dest}`);
95
+ await copyTemplate(dest);
96
+ ok('Sources copiées');
97
+
98
+ const envBody = buildEnvFile({
99
+ databaseUrl,
100
+ domain,
101
+ publicUrl,
102
+ adminEmail,
103
+ adminPassword,
104
+ port,
105
+ });
106
+ await fs.writeFile(path.join(dest, '.env'), envBody, { mode: 0o600 });
107
+ ok('.env écrit');
108
+
109
+ // Alignement du package.json projet (nom local, plus private pour le site client)
110
+ try {
111
+ const pkgPath = path.join(dest, 'package.json');
112
+ const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf8'));
113
+ pkg.name = path.basename(dest).toLowerCase().replace(/[^a-z0-9-_]/g, '-') || 'snapify-site';
114
+ pkg.private = true;
115
+ delete pkg.publishConfig;
116
+ await fs.writeFile(pkgPath, `${JSON.stringify(pkg, null, 2)}\n`);
117
+ } catch {
118
+ /* ignore */
119
+ }
120
+
121
+ if (!skipInstall) {
122
+ console.log('\n→ npm install…');
123
+ const install = spawnSync('npm', ['install', '--no-audit', '--no-fund', '--legacy-peer-deps'], {
124
+ cwd: dest,
125
+ stdio: 'inherit',
126
+ env: { ...process.env, NODE_ENV: 'development' },
127
+ });
128
+ if (install.status !== 0) fail('npm install a échoué');
129
+ ok('Dépendances installées');
130
+
131
+ console.log('\n→ npm run build…');
132
+ const build = spawnSync('npm', ['run', 'build'], {
133
+ cwd: dest,
134
+ stdio: 'inherit',
135
+ env: { ...process.env, NODE_ENV: 'development' },
136
+ });
137
+ if (build.status !== 0) fail('npm run build a échoué');
138
+ ok('Frontend compilé');
139
+ }
140
+
141
+ const nginx = `
142
+ # Nginx — à adapter puis activer
143
+ server {
144
+ server_name ${domain};
145
+ location / {
146
+ proxy_pass http://127.0.0.1:${port};
147
+ proxy_set_header Host $host;
148
+ proxy_set_header X-Forwarded-Host $host;
149
+ proxy_set_header X-Forwarded-Proto $scheme;
150
+ proxy_set_header X-Real-IP $remote_addr;
151
+ }
152
+ }
153
+ `.trim();
154
+
155
+ await fs.writeFile(path.join(dest, 'deploy.nginx.example.conf'), `${nginx}\n`);
156
+
157
+ console.log(`
158
+ ✔ Snapify est prêt dans ${dest}
159
+
160
+ Prochaines étapes :
161
+ 1. Vérifiez que PostgreSQL accepte la connexion
162
+ 2. cd ${path.relative(process.cwd(), dest) || '.'}
163
+ 3. NODE_ENV=production npm start
164
+ 4. Pointez le DNS de ${domain} vers ce serveur
165
+ 5. Configurez le reverse-proxy (voir deploy.nginx.example.conf)
166
+ 6. Ouvrez ${publicUrl}/administrator
167
+ → ${adminEmail}
168
+
169
+ Astuce Docker Postgres locale :
170
+ SNAPIFY_DB_PASSWORD=... npm run db:up
171
+ `);
172
+ }
173
+
174
+ main().catch((e) => fail(e instanceof Error ? e.message : String(e)));
package/lib/args.mjs ADDED
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Parse les arguments CLI.
3
+ * @param {string[]} argv
4
+ */
5
+ export function parseArgs(argv) {
6
+ /** @type {Record<string, string | boolean>} */
7
+ const flags = {};
8
+ /** @type {string[]} */
9
+ const positionals = [];
10
+
11
+ for (let i = 0; i < argv.length; i++) {
12
+ const a = argv[i];
13
+ if (a === '--') {
14
+ positionals.push(...argv.slice(i + 1));
15
+ break;
16
+ }
17
+ if (a.startsWith('--')) {
18
+ const eq = a.indexOf('=');
19
+ if (eq > 0) {
20
+ flags[a.slice(2, eq)] = a.slice(eq + 1);
21
+ continue;
22
+ }
23
+ const key = a.slice(2);
24
+ const next = argv[i + 1];
25
+ if (next && !next.startsWith('-')) {
26
+ flags[key] = next;
27
+ i++;
28
+ } else {
29
+ flags[key] = true;
30
+ }
31
+ continue;
32
+ }
33
+ if (a.startsWith('-') && a.length === 2) {
34
+ const key = a.slice(1);
35
+ const map = { y: 'yes', h: 'help' };
36
+ flags[map[key] || key] = true;
37
+ continue;
38
+ }
39
+ positionals.push(a);
40
+ }
41
+
42
+ return { flags, positionals };
43
+ }
44
+
45
+ export function printHelp() {
46
+ console.log(`Usage: create-snapify-app [dossier] [options]
47
+
48
+ Options:
49
+ --domain <host> Domaine public (ex. boutique.exemple.tn)
50
+ --database-url <url> postgres://user:pass@host:port/db
51
+ --db-host --db-port --db-user --db-password --db-name
52
+ --admin-email <email>
53
+ --admin-password <password>
54
+ --port <n> Port d'écoute (défaut 3000)
55
+ --skip-install Ne pas lancer npm install / build
56
+ --yes, -y Mode non interactif (valeurs par défaut / flags)
57
+ --help, -h Aide
58
+ `);
59
+ }
package/lib/copy.mjs ADDED
@@ -0,0 +1,44 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+
5
+ const HERE = path.dirname(fileURLToPath(import.meta.url));
6
+ export const PACKAGE_ROOT = path.resolve(HERE, '..');
7
+ export const TEMPLATE_DIR = path.join(PACKAGE_ROOT, 'template');
8
+
9
+ async function exists(p) {
10
+ try {
11
+ await fs.access(p);
12
+ return true;
13
+ } catch {
14
+ return false;
15
+ }
16
+ }
17
+
18
+ /**
19
+ * Copie récursive du template vers la cible.
20
+ * @param {string} dest
21
+ */
22
+ export async function copyTemplate(dest) {
23
+ if (!(await exists(TEMPLATE_DIR))) {
24
+ throw new Error(
25
+ `Template absent (${TEMPLATE_DIR}). Ce paquet npm est incomplet : republiez avec « npm run app:pack ».`,
26
+ );
27
+ }
28
+ if (await exists(dest)) {
29
+ const entries = await fs.readdir(dest);
30
+ if (entries.length > 0) {
31
+ throw new Error(`Le dossier « ${dest} » n'est pas vide. Choisissez un autre chemin ou videz-le.`);
32
+ }
33
+ } else {
34
+ await fs.mkdir(dest, { recursive: true });
35
+ }
36
+ await fs.cp(TEMPLATE_DIR, dest, {
37
+ recursive: true,
38
+ filter: (src) => {
39
+ const base = path.basename(src);
40
+ if (base === 'node_modules' || base === '.git' || base === '.env') return false;
41
+ return true;
42
+ },
43
+ });
44
+ }
package/lib/env.mjs ADDED
@@ -0,0 +1,84 @@
1
+ import crypto from 'node:crypto';
2
+
3
+ /** @param {number} [bytes] */
4
+ export function randomSecret(bytes = 32) {
5
+ return crypto.randomBytes(bytes).toString('hex');
6
+ }
7
+
8
+ /**
9
+ * @param {object} opts
10
+ * @param {string} opts.databaseUrl
11
+ * @param {string} opts.domain
12
+ * @param {string} opts.publicUrl
13
+ * @param {string} opts.adminEmail
14
+ * @param {string} opts.adminPassword
15
+ * @param {number|string} opts.port
16
+ * @param {string} [opts.cookieDomain]
17
+ */
18
+ export function buildEnvFile(opts) {
19
+ const domain = opts.domain.replace(/^https?:\/\//, '').replace(/\/$/, '').toLowerCase();
20
+ const publicUrl = opts.publicUrl.replace(/\/$/, '');
21
+ const cookie =
22
+ opts.cookieDomain ||
23
+ (domain.includes('.') ? `.${domain.split('.').slice(-2).join('.')}` : undefined);
24
+
25
+ const lines = [
26
+ `# Généré par create-snapify-app — ${new Date().toISOString()}`,
27
+ `PORT=${opts.port}`,
28
+ `NODE_ENV=production`,
29
+ `DATABASE_URL=${opts.databaseUrl}`,
30
+ '',
31
+ `PUBLIC_URL=${publicUrl}`,
32
+ `SNAPIFY_PUBLIC_URL=${publicUrl}`,
33
+ `SNAPIFY_ADMIN_URL=${publicUrl}/administrator`,
34
+ cookie ? `PLATFORM_COOKIE_DOMAIN=${cookie}` : '# PLATFORM_COOKIE_DOMAIN=',
35
+ '',
36
+ `ADMIN_EMAIL=${opts.adminEmail}`,
37
+ `ADMIN_PASSWORD=${opts.adminPassword}`,
38
+ `ADMIN_JWT_SECRET=${randomSecret(32)}`,
39
+ `SNAPIFY_SECRET_KEY=${randomSecret(32)}`,
40
+ '',
41
+ '# Marketplace distante (recommandé en production)',
42
+ 'MARKETPLACE_URL=https://marketplace.snapify.tn/api/marketplace/catalog.json',
43
+ 'SNAPIFY_MODULES_DEV_MODE=false',
44
+ '',
45
+ 'FLOUCI_MOCK=false',
46
+ '',
47
+ '# Superadmin plateforme — changez immédiatement',
48
+ 'SUPERADMIN_USERNAME=admin',
49
+ `SUPERADMIN_PASSWORD=${randomSecret(12)}`,
50
+ `SUPERADMIN_SECRET=${randomSecret(24)}`,
51
+ '',
52
+ 'GEMINI_API_KEY=',
53
+ 'SMTP_HOST=',
54
+ 'SMTP_PORT=587',
55
+ 'SMTP_USER=',
56
+ 'SMTP_PASS=',
57
+ `SMTP_FROM=contact@${domain}`,
58
+ ];
59
+
60
+ return `${lines.join('\n')}\n`;
61
+ }
62
+
63
+ /**
64
+ * Construit une DATABASE_URL à partir des pièces.
65
+ * @param {{ host: string, port: string|number, user: string, password: string, database: string }} p
66
+ */
67
+ export function buildDatabaseUrl(p) {
68
+ const user = encodeURIComponent(p.user);
69
+ const password = encodeURIComponent(p.password);
70
+ return `postgres://${user}:${password}@${p.host}:${p.port}/${p.database}`;
71
+ }
72
+
73
+ /** @param {string} domainOrUrl */
74
+ export function normalizePublicUrl(domainOrUrl) {
75
+ const raw = domainOrUrl.trim();
76
+ if (!raw) throw new Error('Domaine requis');
77
+ if (/^https?:\/\//i.test(raw)) return raw.replace(/\/$/, '');
78
+ return `https://${raw.replace(/\/$/, '')}`;
79
+ }
80
+
81
+ /** @param {string} publicUrl */
82
+ export function domainFromPublicUrl(publicUrl) {
83
+ return new URL(publicUrl).hostname;
84
+ }
package/lib/prompt.mjs ADDED
@@ -0,0 +1,63 @@
1
+ import readline from 'node:readline/promises';
2
+ import { stdin as input, stdout as output } from 'node:process';
3
+
4
+ /** @param {string} question @param {string} [fallback] */
5
+ export async function ask(question, fallback = '') {
6
+ const rl = readline.createInterface({ input, output });
7
+ try {
8
+ const hint = fallback ? ` (${fallback})` : '';
9
+ const answer = (await rl.question(`${question}${hint} : `)).trim();
10
+ return answer || fallback;
11
+ } finally {
12
+ rl.close();
13
+ }
14
+ }
15
+
16
+ /** @param {string} question */
17
+ export async function askSecret(question) {
18
+ const rl = readline.createInterface({ input, output });
19
+ try {
20
+ output.write(`${question} : `);
21
+ const wasRaw = input.isRaw;
22
+ if (input.isTTY) input.setRawMode?.(true);
23
+ let value = '';
24
+ await new Promise((resolve) => {
25
+ const onData = (buf) => {
26
+ const s = buf.toString('utf8');
27
+ for (const ch of s) {
28
+ if (ch === '\n' || ch === '\r' || ch === '\u0004') {
29
+ input.off('data', onData);
30
+ if (input.isTTY) input.setRawMode?.(wasRaw ?? false);
31
+ output.write('\n');
32
+ resolve();
33
+ return;
34
+ }
35
+ if (ch === '\u0003') {
36
+ input.off('data', onData);
37
+ if (input.isTTY) input.setRawMode?.(wasRaw ?? false);
38
+ output.write('\n');
39
+ process.exit(130);
40
+ }
41
+ if (ch === '\u007f' || ch === '\b') {
42
+ value = value.slice(0, -1);
43
+ continue;
44
+ }
45
+ value += ch;
46
+ output.write('*');
47
+ }
48
+ };
49
+ input.on('data', onData);
50
+ });
51
+ return value;
52
+ } finally {
53
+ rl.close();
54
+ }
55
+ }
56
+
57
+ /** @param {string} question @param {boolean} [fallback] */
58
+ export async function askYesNo(question, fallback = true) {
59
+ const def = fallback ? 'O/n' : 'o/N';
60
+ const answer = (await ask(`${question} [${def}]`, '')).toLowerCase();
61
+ if (!answer) return fallback;
62
+ return answer === 'o' || answer === 'oui' || answer === 'y' || answer === 'yes';
63
+ }
package/package.json CHANGED
@@ -1,6 +1,37 @@
1
1
  {
2
2
  "name": "create-snapify-app",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.1.1",
4
+ "description": "Installe Snapify (CMS complet : backend + frontend) : npx create-snapify-app@latest",
5
+ "license": "SEE LICENSE IN LICENSE.md",
6
+ "author": "NOVALABS WEB DESIGN <contact@novalabs.tn> (https://novalabs.tn)",
7
+ "homepage": "https://snapify.tn",
8
+ "bugs": {
9
+ "email": "contact@novalabs.tn"
10
+ },
11
+ "keywords": [
12
+ "snapify",
13
+ "cms",
14
+ "create",
15
+ "installer",
16
+ "ecommerce",
17
+ "postgresql",
18
+ "novalabs"
19
+ ],
20
+ "type": "module",
21
+ "bin": {
22
+ "create-snapify-app": "bin/create-snapify-app.mjs"
23
+ },
24
+ "files": [
25
+ "bin",
26
+ "lib",
27
+ "template",
28
+ "README.md",
29
+ "LICENSE.md"
30
+ ],
31
+ "engines": {
32
+ "node": "^20.19.0 || >=22.12.0"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ }
37
+ }
@@ -0,0 +1,79 @@
1
+ PORT=3000
2
+
3
+ # PostgreSQL (obligatoire)
4
+ DATABASE_URL=postgres://snapify:changez-moi@127.0.0.1:5432/snapify
5
+ # Conteneur Docker local (npm run db:up)
6
+ SNAPIFY_DB_PASSWORD=changez-moi
7
+ SNAPIFY_DB_PORT=5433
8
+
9
+ # URL publique du site (utilisée au premier démarrage pour settings.publicUrl)
10
+ PUBLIC_URL=https://exemple.tn
11
+ SNAPIFY_PUBLIC_URL=https://exemple.tn
12
+
13
+ # Module « Assistant IA » (novalabs.ai-chat) — clé lue uniquement côté serveur
14
+ GEMINI_API_KEY=
15
+
16
+ # Community + Marketplace + portail développeurs (sous-domaines)
17
+ COMMUNITY_HOST=community.snapify.tn,community.snapify.fr,community.localhost
18
+ MARKETPLACE_HOST=marketplace.snapify.tn,marketplace.snapify.fr,marketplace.localhost
19
+ DEVELOPERS_HOST=developers.snapify.tn,developers.snapify.fr,developers.localhost
20
+ COMMUNITY_URL=https://community.snapify.tn
21
+ MARKETPLACE_PUBLIC_URL=https://marketplace.snapify.tn
22
+ PLATFORM_PUBLIC_URL=https://marketplace.snapify.tn
23
+ # Domaine cookie dérivé du Host (.snapify.tn / .snapify.fr) ; fallback :
24
+ PLATFORM_COOKIE_DOMAIN=.snapify.tn
25
+ PLATFORM_ADMIN_EMAIL=admin@snapify.tn
26
+ PLATFORM_ADMIN_PASSWORD=SnapifyAdmin1
27
+ MARKETPLACE_COMMISSION_BPS=3000
28
+ DEVELOPER_FEE_MILLIMES=100000
29
+ FLOUCI_PUBLIC_KEY=
30
+ FLOUCI_PRIVATE_KEY=
31
+ FLOUCI_WEBHOOK_SECRET=
32
+ # true = paiements simulés — ignoré / interdit si NODE_ENV=production
33
+ FLOUCI_MOCK=true
34
+
35
+ # Modules — catalogue distant HTTPS (vide = catalogue local marketplace/catalog.json)
36
+ # Pointer vers le catalogue généré par la plateforme :
37
+ # MARKETPLACE_URL=https://marketplace.snapify.tn/api/marketplace/catalog.json
38
+ MARKETPLACE_URL=
39
+ # true = autorise l'installation de modules non signés (développement uniquement)
40
+ SNAPIFY_MODULES_DEV_MODE=false
41
+
42
+ # Backoffice — changez impérativement en production
43
+ ADMIN_EMAIL=admin@snapify.fr
44
+ ADMIN_PASSWORD=changez-moi
45
+ ADMIN_JWT_SECRET=long-random-secret
46
+ # Clé de chiffrement des secrets en base (mot de passe SMTP, 2FA). Vide = dérivée d'ADMIN_JWT_SECRET.
47
+ # Ne plus la changer une fois définie : les secrets déjà chiffrés deviendraient illisibles.
48
+ SNAPIFY_SECRET_KEY=
49
+ # Adresse de l'administration utilisée dans les e-mails (invitation, mot de passe oublié). Vide = URL publique du site.
50
+ SNAPIFY_ADMIN_URL=
51
+ # Secours : true = ignore la liste d'IP autorisées de l'administration (à remettre à false après usage)
52
+ SNAPIFY_ADMIN_IP_BYPASS=false
53
+
54
+ # Google OAuth (Search Console) — facultatif : l'assistant SEO › Google Search Console
55
+ # permet de saisir ces identifiants dans l'admin (prioritaires, secret chiffré).
56
+ # GOOGLE_REDIRECT_URI n'est utilisé qu'avec les identifiants définis ici.
57
+ GOOGLE_CLIENT_ID=
58
+ GOOGLE_CLIENT_SECRET=
59
+ GOOGLE_REDIRECT_URI=https://snapify.fr/api/admin/google/callback
60
+
61
+ # E-mails (formulaires, newsletter double opt-in, invitations). Utilisé seulement si le SMTP
62
+ # n'est pas configuré dans Paramètres › E-mails, qui a priorité.
63
+ SMTP_HOST=
64
+ SMTP_PORT=587
65
+ SMTP_USER=
66
+ SMTP_PASS=
67
+ SMTP_FROM=contact@snapify.fr
68
+
69
+ # Démo publique snapify.tn/demo (credentials affichés + reset CMS 24h)
70
+ DEMO_ADMIN_EMAIL=admin@snapify.fr
71
+ DEMO_ADMIN_PASSWORD=SnapifyDemo1
72
+ DEMO_CMS_RESET=true
73
+ DEMO_CMS_RESET_HOURS=24
74
+ LICENSE_PRICE_MILLIMES=699000
75
+
76
+ # Superadmin (https://snapify.tn/hamdisup90) — SUPERADMIN_PASSWORD obligatoire (pas de défaut)
77
+ SUPERADMIN_USERNAME=hamdisup90
78
+ SUPERADMIN_PASSWORD=changez-moi
79
+ SUPERADMIN_SECRET=
@@ -0,0 +1,23 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+ workflow_dispatch:
9
+
10
+ concurrency:
11
+ group: ci-${{ github.ref }}
12
+ cancel-in-progress: true
13
+
14
+ jobs:
15
+ build:
16
+ name: Lint & build
17
+ runs-on: [self-hosted, linux, x64]
18
+ timeout-minutes: 25
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+ - run: npm ci --no-audit --no-fund --legacy-peer-deps
22
+ - run: npm run lint
23
+ - run: npm run build
@@ -0,0 +1,26 @@
1
+ name: Deploy
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ workflow_dispatch:
7
+ inputs:
8
+ ref:
9
+ description: 'Git ref (origin/main ou tags/v1.1.0)'
10
+ required: false
11
+ default: origin/main
12
+
13
+ concurrency:
14
+ group: deploy-production
15
+ cancel-in-progress: false
16
+
17
+ jobs:
18
+ deploy:
19
+ name: Production (hamdi)
20
+ runs-on: [self-hosted, linux, x64]
21
+ timeout-minutes: 30
22
+ steps:
23
+ - name: Deploy Snapify
24
+ env:
25
+ REF: ${{ github.event.inputs.ref || 'origin/main' }}
26
+ run: sudo -n bash /home/snapify/scripts/deploy.sh "$REF"
@@ -0,0 +1,8 @@
1
+ name: Ping
2
+ on:
3
+ workflow_dispatch:
4
+ jobs:
5
+ ping:
6
+ runs-on: self-hosted
7
+ steps:
8
+ - run: echo hello-from-hamdi && hostname