@c15t/react 3.0.0-alpha.1 → 3.0.0-alpha.11

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 (413) hide show
  1. package/AGENTS.md +97 -70
  2. package/README.md +21 -17
  3. package/SKILL.md +34 -0
  4. package/dist/aggregate-components.js +1 -1
  5. package/dist/chunk-warming.js +1 -1
  6. package/dist/component-hooks/use-headless-consent-ui.js +1 -1
  7. package/dist/component-hooks/use-headless-iab-consent-ui.js +1 -1
  8. package/dist/component-hooks/use-panel-trigger.js +1 -1
  9. package/dist/components/consent-gate/atoms.js +1 -0
  10. package/dist/components/consent-gate/consent-gate.js +2 -0
  11. package/dist/components/consent-gate/frame.js +2 -0
  12. package/dist/components/consent-gate/index.js +2 -0
  13. package/dist/components/consent-preferences-link/consent-preferences-link.js +1 -1
  14. package/dist/components/iab-panel/atoms/card.js +1 -1
  15. package/dist/components/iab-panel/atoms/feature-item.js +2 -0
  16. package/dist/components/iab-panel/atoms/header.js +1 -1
  17. package/dist/components/iab-panel/atoms/purpose-item.js +1 -1
  18. package/dist/components/iab-panel/atoms/root.js +1 -1
  19. package/dist/components/iab-panel/atoms/stack-item.js +1 -1
  20. package/dist/components/iab-panel/atoms/vendor-list.js +1 -1
  21. package/dist/components/iab-panel/hooks/use-gvl-data.js +1 -1
  22. package/dist/components/iab-panel/iab-panel.js +1 -1
  23. package/dist/components/iab-panel/index.js +1 -1
  24. package/dist/components/iab-prompt/atoms/overlay.js +1 -1
  25. package/dist/components/iab-prompt/atoms/root.js +1 -1
  26. package/dist/components/iab-prompt/iab-prompt.js +1 -1
  27. package/dist/components/panel/atoms/card.js +1 -1
  28. package/dist/components/panel/atoms/overlay.js +1 -1
  29. package/dist/components/panel/atoms/root.js +1 -1
  30. package/dist/components/panel/panel.js +1 -1
  31. package/dist/components/panel-trigger/atoms/button.js +1 -1
  32. package/dist/components/panel-trigger/atoms/icon.js +1 -1
  33. package/dist/components/panel-trigger/atoms/root.js +1 -1
  34. package/dist/components/panel-trigger/atoms/toolbar.js +1 -1
  35. package/dist/components/panel-trigger/atoms/trigger-icons.js +1 -0
  36. package/dist/components/panel-trigger/panel-trigger-toolbar.js +1 -1
  37. package/dist/components/panel-trigger/panel-trigger.js +1 -1
  38. package/dist/components/panel-trigger/toolbar-loader.js +2 -0
  39. package/dist/components/preferences/atoms/accordion.js +1 -1
  40. package/dist/components/preferences/atoms/root.js +1 -1
  41. package/dist/components/preferences/atoms/vendor-list.js +1 -0
  42. package/dist/components/preferences/index.js +1 -1
  43. package/dist/components/prompt/atoms/early-tap-script.js +2 -0
  44. package/dist/components/prompt/atoms/overlay.js +1 -1
  45. package/dist/components/prompt/atoms/root.js +1 -1
  46. package/dist/components/prompt/components.js +1 -1
  47. package/dist/components/prompt/policy-actions.js +1 -1
  48. package/dist/components/prompt/prompt.js +1 -1
  49. package/dist/components/shared/dialog-sheets.js +1 -0
  50. package/dist/components/shared/first-paint-sheets.js +1 -0
  51. package/dist/components/shared/iab-dialog-sheets.js +1 -0
  52. package/dist/components/shared/iab-first-paint-sheets.js +1 -0
  53. package/dist/components/shared/libs/compose-refs.js +1 -0
  54. package/dist/components/shared/libs/slot.js +1 -1
  55. package/dist/components/shared/primitives/button.js +1 -1
  56. package/dist/components/shared/primitives/legal-links/index.js +1 -1
  57. package/dist/components/shared/streamed-surface.js +2 -0
  58. package/dist/components/shared/surface-styles.js +2 -0
  59. package/dist/components/shared/ui/dialog/dialog.js +1 -1
  60. package/dist/components/shared/ui/icon.js +1 -1
  61. package/dist/components/shared/ui/logo.js +1 -1
  62. package/dist/components/shared/ui/preference-item/preference-item.js +1 -1
  63. package/dist/consent-gate.js +2 -0
  64. package/dist/consent-theme.js +1 -0
  65. package/dist/context/consent-tracking-context.js +1 -1
  66. package/dist/context/index.js +1 -1
  67. package/dist/context.js +1 -1
  68. package/dist/devtools-launcher.js +2 -0
  69. package/dist/devtools.js +1 -1
  70. package/dist/draft-context.js +2 -0
  71. package/dist/draft.js +1 -1
  72. package/dist/external-iab-context.js +1 -1
  73. package/dist/gpp.js +2 -0
  74. package/dist/headless.js +1 -1
  75. package/dist/hooks/use-color-scheme.js +1 -1
  76. package/dist/hooks/use-committed-ref.js +2 -0
  77. package/dist/hooks/use-focus-trap.js +1 -1
  78. package/dist/hooks/use-headless-iab-consent-ui.js +1 -1
  79. package/dist/hooks/use-iab-policy-guard.js +1 -0
  80. package/dist/hooks/use-late-entry.js +2 -0
  81. package/dist/hooks.js +1 -1
  82. package/dist/iab/styles.tw3.css +5 -45
  83. package/dist/iab-context.js +1 -1
  84. package/dist/iab-dialog-deferred.js +2 -0
  85. package/dist/iab.js +1 -1
  86. package/dist/index-parts/consent-banner.js +1 -0
  87. package/dist/index-parts/consent-dialog-link.js +1 -0
  88. package/dist/index-parts/consent-dialog-trigger.js +1 -0
  89. package/dist/index-parts/consent-dialog.js +1 -0
  90. package/dist/index-parts/consent-gate.js +1 -0
  91. package/dist/index-parts/core.js +1 -0
  92. package/dist/index-parts/draft.js +1 -0
  93. package/dist/index-parts/frame.js +1 -0
  94. package/dist/index-parts/hooks.js +1 -0
  95. package/dist/index-parts/hosted.js +1 -0
  96. package/dist/index-parts/module-hooks.js +1 -0
  97. package/dist/index-parts/offline.js +1 -0
  98. package/dist/index-parts/presets.js +1 -0
  99. package/dist/index-parts/provider.js +1 -0
  100. package/dist/index-parts/theme.js +1 -0
  101. package/dist/index-parts/translations.js +1 -0
  102. package/dist/index.js +1 -1
  103. package/dist/kernel-selector.js +1 -0
  104. package/dist/modes.js +1 -0
  105. package/dist/module-hooks/iframe-blocker.js +1 -1
  106. package/dist/module-hooks/network-blocker.js +1 -1
  107. package/dist/module-hooks/network-hold.js +2 -0
  108. package/dist/module-hooks/persistence.js +1 -1
  109. package/dist/panel-link.js +1 -1
  110. package/dist/panel-trigger.js +1 -1
  111. package/dist/panel.js +1 -1
  112. package/dist/postcss-tailwind3.js +1 -0
  113. package/dist/preferences.js +1 -2
  114. package/dist/provider.js +1 -1
  115. package/dist/server/fetch-ssr-data.js +1 -1
  116. package/dist/server/headers.js +1 -1
  117. package/dist/server/normalize-url.js +1 -1
  118. package/dist/styles.tw3.css +33 -51
  119. package/dist/transports/hosted.js +1 -0
  120. package/dist/transports/manifest.js +1 -0
  121. package/dist/transports/offline.js +1 -1
  122. package/dist/utils/deferred-module.js +2 -0
  123. package/dist/utils/merge-slot-props.js +1 -1
  124. package/dist/utils/theme-utils.js +1 -1
  125. package/dist/version.js +1 -1
  126. package/dist-types/aggregate-components.d.ts +2 -2
  127. package/dist-types/chunk-warming.d.ts +42 -8
  128. package/dist-types/component-hooks/use-headless-consent-ui.d.ts +5 -5
  129. package/dist-types/component-hooks/use-headless-iab-consent-ui.d.ts +2 -2
  130. package/dist-types/components/consent-gate/atoms.d.ts +11 -0
  131. package/dist-types/components/consent-gate/consent-gate.d.ts +2 -0
  132. package/dist-types/components/consent-gate/frame.d.ts +19 -0
  133. package/dist-types/components/consent-gate/index.d.ts +25 -0
  134. package/dist-types/components/{frame → consent-gate}/types.d.ts +7 -7
  135. package/dist-types/components/consent-preferences-link/consent-preferences-link.d.ts +1 -1
  136. package/dist-types/components/consent-preferences-link/index.d.ts +1 -1
  137. package/dist-types/components/iab-panel/atoms/feature-item.d.ts +28 -0
  138. package/dist-types/components/iab-panel/atoms/purpose-item.d.ts +5 -2
  139. package/dist-types/components/iab-panel/atoms/stack-item.d.ts +7 -2
  140. package/dist-types/components/iab-panel/atoms/vendor-list.d.ts +1 -1
  141. package/dist-types/components/iab-panel/iab-panel.d.ts +3 -3
  142. package/dist-types/components/iab-panel/index.d.ts +29 -26
  143. package/dist-types/components/iab-panel/use-iab-translations.d.ts +4 -0
  144. package/dist-types/components/iab-prompt/iab-prompt.d.ts +3 -3
  145. package/dist-types/components/iab-prompt/index.d.ts +19 -19
  146. package/dist-types/components/panel/atoms/card.d.ts +5 -4
  147. package/dist-types/components/panel/atoms/overlay.d.ts +1 -1
  148. package/dist-types/components/panel/index.d.ts +8 -8
  149. package/dist-types/components/panel/panel.d.ts +3 -3
  150. package/dist-types/components/panel-link/index.d.ts +1 -1
  151. package/dist-types/components/panel-trigger/atoms/button.d.ts +1 -1
  152. package/dist-types/components/panel-trigger/atoms/icon.d.ts +1 -1
  153. package/dist-types/components/panel-trigger/atoms/root.d.ts +2 -2
  154. package/dist-types/components/panel-trigger/atoms/toolbar.d.ts +2 -2
  155. package/dist-types/components/panel-trigger/atoms/trigger-icons.d.ts +25 -0
  156. package/dist-types/components/panel-trigger/index.d.ts +4 -4
  157. package/dist-types/components/panel-trigger/panel-trigger-toolbar.d.ts +1 -1
  158. package/dist-types/components/panel-trigger/panel-trigger.d.ts +9 -17
  159. package/dist-types/components/panel-trigger/toolbar-loader.d.ts +34 -0
  160. package/dist-types/components/panel-trigger/types.d.ts +1 -1
  161. package/dist-types/components/preferences/atoms/accordion.d.ts +6 -4
  162. package/dist-types/components/preferences/atoms/button.d.ts +1 -1
  163. package/dist-types/components/preferences/atoms/footer.d.ts +1 -1
  164. package/dist-types/components/preferences/atoms/root.d.ts +1 -1
  165. package/dist-types/components/preferences/atoms/vendor-list.d.ts +23 -0
  166. package/dist-types/components/preferences/index.d.ts +14 -12
  167. package/dist-types/components/preferences/policy-actions.d.ts +2 -2
  168. package/dist-types/components/preferences/preferences.d.ts +1 -1
  169. package/dist-types/components/preferences/types.d.ts +1 -1
  170. package/dist-types/components/prompt/atoms/early-tap-script.d.ts +17 -0
  171. package/dist-types/components/prompt/atoms/root.d.ts +4 -0
  172. package/dist-types/components/prompt/components.d.ts +9 -3
  173. package/dist-types/components/prompt/index.d.ts +12 -12
  174. package/dist-types/components/prompt/policy-actions.d.ts +2 -2
  175. package/dist-types/components/prompt/prompt.d.ts +5 -1
  176. package/dist-types/components/shared/dialog-sheets.d.ts +9 -0
  177. package/dist-types/components/shared/first-paint-sheets.d.ts +8 -0
  178. package/dist-types/components/shared/iab-dialog-sheets.d.ts +3 -0
  179. package/dist-types/components/shared/iab-first-paint-sheets.d.ts +3 -0
  180. package/dist-types/components/shared/libs/compose-refs.d.ts +20 -0
  181. package/dist-types/components/shared/policy-actions.d.ts +2 -2
  182. package/dist-types/components/shared/primitives/box.d.ts +1 -1
  183. package/dist-types/components/shared/primitives/button.d.ts +2 -2
  184. package/dist-types/components/shared/primitives/button.types.d.ts +1 -1
  185. package/dist-types/components/shared/streamed-surface.d.ts +23 -0
  186. package/dist-types/components/shared/surface-styles.d.ts +60 -0
  187. package/dist-types/components/shared/ui/accordion/accordion.d.ts +2 -2
  188. package/dist-types/components/shared/ui/accordion/index.d.ts +2 -2
  189. package/dist-types/components/shared/ui/animated-collapse/index.d.ts +2 -2
  190. package/dist-types/components/shared/ui/branding.d.ts +1 -1
  191. package/dist-types/components/shared/ui/button/button.d.ts +1 -1
  192. package/dist-types/components/shared/ui/button/index.d.ts +2 -2
  193. package/dist-types/components/shared/ui/collapsible/index.d.ts +1 -1
  194. package/dist-types/components/shared/ui/dialog/index.d.ts +1 -1
  195. package/dist-types/components/shared/ui/icon.d.ts +2 -1
  196. package/dist-types/components/shared/ui/logo.d.ts +0 -10
  197. package/dist-types/components/shared/ui/preference-item/index.d.ts +1 -1
  198. package/dist-types/components/shared/ui/preference-item/preference-item.d.ts +13 -0
  199. package/dist-types/components/shared/ui/switch/index.d.ts +2 -2
  200. package/dist-types/components/shared/ui/switch/switch.d.ts +1 -1
  201. package/dist-types/components/shared/ui/tabs/index.d.ts +1 -1
  202. package/dist-types/consent-gate.d.ts +1 -0
  203. package/dist-types/consent-theme.d.ts +38 -0
  204. package/dist-types/context/consent-tracking-context.d.ts +10 -0
  205. package/dist-types/context/index.d.ts +3 -3
  206. package/dist-types/context/theme-context.d.ts +3 -3
  207. package/dist-types/context.d.ts +25 -1
  208. package/dist-types/devtools-launcher.d.ts +29 -0
  209. package/dist-types/devtools.d.ts +13 -2
  210. package/dist-types/draft-context.d.ts +31 -0
  211. package/dist-types/draft.d.ts +81 -9
  212. package/dist-types/gpp.d.ts +27 -0
  213. package/dist-types/headless.d.ts +6 -7
  214. package/dist-types/hooks/use-committed-ref.d.ts +24 -0
  215. package/dist-types/hooks/use-focus-trap.d.ts +3 -1
  216. package/dist-types/hooks/use-headless-iab-consent-ui.d.ts +1 -1
  217. package/dist-types/hooks/use-iab-manager.d.ts +5 -5
  218. package/dist-types/hooks/use-iab-policy-guard.d.ts +35 -0
  219. package/dist-types/hooks/use-late-entry.d.ts +14 -0
  220. package/dist-types/hooks/use-theme.d.ts +1 -1
  221. package/dist-types/hooks.d.ts +106 -11
  222. package/dist-types/iab-dialog-deferred.d.ts +36 -0
  223. package/dist-types/iab.d.ts +8 -7
  224. package/dist-types/index-parts/consent-banner.d.ts +7 -0
  225. package/dist-types/index-parts/consent-dialog-link.d.ts +7 -0
  226. package/dist-types/index-parts/consent-dialog-trigger.d.ts +7 -0
  227. package/dist-types/index-parts/consent-dialog.d.ts +7 -0
  228. package/dist-types/index-parts/consent-gate.d.ts +7 -0
  229. package/dist-types/index-parts/core.d.ts +7 -0
  230. package/dist-types/index-parts/draft.d.ts +7 -0
  231. package/dist-types/index-parts/frame.d.ts +7 -0
  232. package/dist-types/index-parts/hooks.d.ts +7 -0
  233. package/dist-types/index-parts/hosted.d.ts +7 -0
  234. package/dist-types/index-parts/module-hooks.d.ts +7 -0
  235. package/dist-types/index-parts/offline.d.ts +7 -0
  236. package/dist-types/index-parts/presets.d.ts +7 -0
  237. package/dist-types/index-parts/provider.d.ts +7 -0
  238. package/dist-types/index-parts/theme.d.ts +8 -0
  239. package/dist-types/index-parts/translations.d.ts +7 -0
  240. package/dist-types/index.d.ts +32 -28
  241. package/dist-types/kernel-selector.d.ts +68 -0
  242. package/dist-types/modes.d.ts +26 -0
  243. package/dist-types/module-hooks/iframe-blocker.d.ts +33 -1
  244. package/dist-types/module-hooks/network-blocker.d.ts +23 -0
  245. package/dist-types/module-hooks/network-hold.d.ts +47 -0
  246. package/dist-types/module-hooks.d.ts +4 -4
  247. package/dist-types/panel-link.d.ts +1 -1
  248. package/dist-types/panel-trigger.d.ts +1 -1
  249. package/dist-types/panel.d.ts +13 -1
  250. package/dist-types/postcss-tailwind3.d.ts +21 -0
  251. package/dist-types/preferences.d.ts +12 -1
  252. package/dist-types/primitives/accordion.d.ts +1 -1
  253. package/dist-types/primitives/button.d.ts +1 -1
  254. package/dist-types/primitives/collapsible.d.ts +1 -1
  255. package/dist-types/primitives/dialog.d.ts +1 -1
  256. package/dist-types/primitives/preference-item.d.ts +1 -1
  257. package/dist-types/primitives/switch.d.ts +1 -1
  258. package/dist-types/primitives/tabs.d.ts +1 -1
  259. package/dist-types/primitives.d.ts +7 -7
  260. package/dist-types/prompt.d.ts +1 -1
  261. package/dist-types/provider.d.ts +169 -28
  262. package/dist-types/server/fetch-ssr-data.d.ts +1 -1
  263. package/dist-types/server/headers.d.ts +14 -4
  264. package/dist-types/server/index.d.ts +5 -5
  265. package/dist-types/server/normalize-url.d.ts +14 -7
  266. package/dist-types/server/types.d.ts +12 -1
  267. package/dist-types/theme-provider.d.ts +2 -2
  268. package/dist-types/transports/hosted.d.ts +36 -0
  269. package/dist-types/transports/manifest.d.ts +48 -0
  270. package/dist-types/transports/offline.d.ts +7 -16
  271. package/dist-types/types/index.d.ts +3 -3
  272. package/dist-types/types/manager.d.ts +1 -1
  273. package/dist-types/types/theme/index.d.ts +1 -1
  274. package/dist-types/ui-config-context.d.ts +14 -2
  275. package/dist-types/utils/deferred-module.d.ts +13 -0
  276. package/dist-types/utils/index.d.ts +4 -4
  277. package/dist-types/utils/merge-slot-props.d.ts +17 -3
  278. package/dist-types/utils/merge-styles.d.ts +1 -1
  279. package/dist-types/utils/theme-utils.d.ts +18 -3
  280. package/dist-types/version.d.ts +1 -1
  281. package/docs/README.md +97 -70
  282. package/docs/assets/v3/bottom-bar.png +0 -0
  283. package/docs/assets/v3/brand-card.png +0 -0
  284. package/docs/assets/v3/brand-preferences.png +0 -0
  285. package/docs/assets/v3/choice-wall.png +0 -0
  286. package/docs/assets/v3/headless-bar-html.png +0 -0
  287. package/docs/assets/v3/headless-bar-mobile.png +0 -0
  288. package/docs/assets/v3/headless-bar.png +0 -0
  289. package/docs/assets/v3/slim-bar.png +0 -0
  290. package/docs/concepts/choose-your-setup.md +141 -0
  291. package/docs/concepts/consent-categories.md +84 -0
  292. package/docs/concepts/consent-state.md +421 -0
  293. package/docs/concepts/data-fetching.md +284 -0
  294. package/docs/concepts/how-consent-works.md +123 -0
  295. package/docs/concepts/modes.md +281 -0
  296. package/docs/{frameworks/react/concepts/policy-presets.md → concepts/policies.md} +8 -60
  297. package/docs/customization/class-names.md +202 -0
  298. package/docs/customization/dark-mode.md +157 -0
  299. package/docs/customization/motion.md +128 -0
  300. package/docs/customization/overview.md +68 -33
  301. package/docs/customization/recipes.md +838 -47
  302. package/docs/customization/slots.md +217 -35
  303. package/docs/customization/stylesheets.md +248 -0
  304. package/docs/customization/tailwind.md +863 -0
  305. package/docs/customization/tokens.md +167 -36
  306. package/docs/customization/translations.md +87 -3
  307. package/docs/frameworks/react/callbacks.md +118 -0
  308. package/docs/frameworks/react/clear-on-revocation.md +106 -0
  309. package/docs/frameworks/react/components/consent-banner.md +48 -27
  310. package/docs/frameworks/react/components/consent-dialog-link.md +13 -11
  311. package/docs/frameworks/react/components/consent-dialog-trigger.md +86 -76
  312. package/docs/frameworks/react/components/consent-dialog.md +111 -58
  313. package/docs/frameworks/react/components/{frame.md → consent-gate.md} +70 -49
  314. package/docs/frameworks/react/components/consent-provider.md +143 -0
  315. package/docs/frameworks/react/components/consent-widget.md +69 -24
  316. package/docs/frameworks/react/components/dev-tools.md +76 -85
  317. package/docs/frameworks/react/components.md +113 -0
  318. package/docs/frameworks/react/compose.md +354 -0
  319. package/docs/frameworks/react/content-security-policy.md +149 -0
  320. package/docs/frameworks/react/customize.md +258 -0
  321. package/docs/frameworks/react/embeds.md +89 -0
  322. package/docs/frameworks/react/gpp.md +163 -0
  323. package/docs/frameworks/react/headless.md +4 -4
  324. package/docs/frameworks/react/hooks.md +70 -0
  325. package/docs/frameworks/react/iab.md +278 -0
  326. package/docs/frameworks/react/network-blocker.md +140 -0
  327. package/docs/frameworks/react/quickstart.md +171 -107
  328. package/docs/frameworks/react/rendering.md +285 -0
  329. package/docs/frameworks/react/scripts.md +114 -0
  330. package/docs/frameworks/react/translations.md +155 -0
  331. package/docs/frameworks/react/troubleshooting.md +189 -61
  332. package/docs/frameworks/react/upgrade-v3.md +652 -0
  333. package/docs/frameworks/react/vendor-consent.md +188 -0
  334. package/docs/guides/banner-experiments.md +688 -0
  335. package/docs/guides/troubleshooting.md +192 -54
  336. package/docs/guides/verify-consent.md +96 -49
  337. package/docs/integrations/adobe-analytics.md +177 -183
  338. package/docs/integrations/ahrefs-analytics.md +162 -178
  339. package/docs/integrations/amplitude.md +172 -180
  340. package/docs/integrations/building-integrations.md +137 -33
  341. package/docs/integrations/clearbit.md +164 -178
  342. package/docs/integrations/cloudflare-web-analytics.md +166 -180
  343. package/docs/integrations/cloudflare-zaraz.md +333 -0
  344. package/docs/integrations/crisp.md +174 -182
  345. package/docs/integrations/databuddy.md +167 -197
  346. package/docs/integrations/fathom-analytics.md +168 -180
  347. package/docs/integrations/front-chat.md +308 -0
  348. package/docs/integrations/google-maps.md +142 -108
  349. package/docs/integrations/google-tag-manager.md +258 -185
  350. package/docs/integrations/google-tag.md +226 -182
  351. package/docs/integrations/heap.md +173 -179
  352. package/docs/integrations/hightouch.md +171 -181
  353. package/docs/integrations/hotjar.md +169 -179
  354. package/docs/integrations/intercom.md +193 -177
  355. package/docs/integrations/klaviyo.md +473 -0
  356. package/docs/integrations/linkedin-insights.md +184 -174
  357. package/docs/integrations/logrocket.md +170 -180
  358. package/docs/integrations/matomo-analytics.md +198 -202
  359. package/docs/integrations/meta-pixel.md +198 -174
  360. package/docs/integrations/microsoft-clarity.md +173 -179
  361. package/docs/integrations/microsoft-uet.md +158 -178
  362. package/docs/integrations/mixpanel-analytics.md +165 -184
  363. package/docs/integrations/one-dollar-stats.md +292 -0
  364. package/docs/integrations/openai-pixel.md +214 -325
  365. package/docs/integrations/overview.md +153 -83
  366. package/docs/integrations/pinterest-tag.md +315 -0
  367. package/docs/integrations/pirsch.md +179 -183
  368. package/docs/integrations/plausible-analytics.md +182 -182
  369. package/docs/integrations/posthog.md +323 -264
  370. package/docs/integrations/promptwatch.md +164 -178
  371. package/docs/integrations/reddit-pixel.md +195 -181
  372. package/docs/integrations/rudderstack.md +211 -210
  373. package/docs/integrations/rybbit-analytics.md +181 -184
  374. package/docs/integrations/segment.md +192 -178
  375. package/docs/integrations/sentry.md +402 -0
  376. package/docs/integrations/snapchat-pixel.md +196 -180
  377. package/docs/integrations/tiktok-pixel.md +181 -174
  378. package/docs/integrations/umami-analytics.md +173 -182
  379. package/docs/integrations/vercel-analytics.md +176 -181
  380. package/docs/integrations/vercel-speed-insights.md +306 -0
  381. package/docs/integrations/x-pixel.md +186 -174
  382. package/docs/integrations/youtube.md +150 -111
  383. package/package.json +48 -17
  384. package/dist/component-hooks/use-manager.js +0 -2
  385. package/dist/components/frame/atoms.js +0 -1
  386. package/dist/components/frame/frame.js +0 -2
  387. package/dist/components/frame/index.js +0 -2
  388. package/dist/frame.js +0 -2
  389. package/dist/ui-save.js +0 -1
  390. package/dist-types/component-hooks/use-manager.d.ts +0 -40
  391. package/dist-types/components/frame/atoms.d.ts +0 -11
  392. package/dist-types/components/frame/frame.d.ts +0 -2
  393. package/dist-types/components/frame/index.d.ts +0 -24
  394. package/dist-types/frame.d.ts +0 -1
  395. package/dist-types/ui-save.d.ts +0 -5
  396. package/docs/assets/v3/brand-bar.png +0 -0
  397. package/docs/assets/v3/mobile-card.png +0 -0
  398. package/docs/assets/v3/preferences.png +0 -0
  399. package/docs/frameworks/react/components/consent-manager-provider.md +0 -71
  400. package/docs/frameworks/react/concepts/consent-categories.md +0 -33
  401. package/docs/frameworks/react/hooks/use-consent-manager/overview.md +0 -58
  402. package/docs/frameworks/react/iab/overview.md +0 -53
  403. package/docs/frameworks/react/script-loader.md +0 -63
  404. package/docs/frameworks/react/styling/overview.md +0 -217
  405. package/docs/guides/consent-state.md +0 -60
  406. package/docs/guides/data-fetching.md +0 -163
  407. package/docs/guides/deployment-modes.md +0 -63
  408. package/docs/integrations/clear-on-revocation.md +0 -167
  409. package/docs/upgrade-v3.md +0 -334
  410. package/readme.json +0 -48
  411. package/src/iab/styles.css +0 -11
  412. package/src/styles.css +0 -10
  413. /package/dist/components/{frame → consent-gate}/types.js +0 -0
@@ -0,0 +1,284 @@
1
+ ---
2
+ title: Data fetching
3
+ description: Choose the recommended build-time policy snapshot or runtime
4
+ manifest fetching, backend /init, browser resolution or offline rules, and
5
+ understand where consent choices are saved.
6
+ group: concepts
7
+ ---
8
+
9
+ ## Compare the fetching paths
10
+
11
+ Where policy resolves and where choices are saved are separate from who runs
12
+ the backend. Inth and a [self-hosted backend](https://v3.c15t.com/docs/self-host/quickstart) speak
13
+ the same protocol, so every path below works with either. Only `offline()`
14
+ removes backend requests. For a recommendation by framework, start with
15
+ [choose your setup](./choose-your-setup.md).
16
+
17
+ | Fetching path | Where policy resolves | Where choices are submitted | Choose it when |
18
+ | --------------------------------------------------------- | -------------------------------------------------------------------------------------------- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
19
+ | Build-time manifest, recommended for server-rendered apps | Your server resolves a bundled policy snapshot with each visitor's inputs | Inth or your c15t backend | Your framework renders on the server, supports a build integration, and policy changes can ship with a rebuild |
20
+ | Cached manifest on your server | Your application resolves public policy data with each request's location and signals | Inth or your c15t backend | Policy changes must reach the app without rebuilding, or builds cannot access the backend |
21
+ | Regular backend `/init` | The consent backend | The same backend | You have no application server, as in a React, Vue or Svelte single-page app, want the fewest moving parts, or need backend-owned request resolution |
22
+ | Manifest in the browser | The browser, using a supplied location, or `/init` when the policy needs one it doesn't have | Inth or your c15t backend | The policy has no location rules or the page knows the visitor's location, and you accept about 3 KB more bundle and a rebuild for policy edits |
23
+ | Offline | The browser or local runtime, using bundled rules | No backend submission | Local development and tests. Not recommended for production environments. |
24
+ | Custom transport | Your implementation | Your implementation | An existing service cannot use the c15t backend protocol |
25
+
26
+ ## What is a consent manifest?
27
+
28
+ A manifest is a versioned policy document served by `GET /manifest`. It contains
29
+ policy rules, translation configuration and related consent configuration. It
30
+ is public configuration, not a visitor's saved choices. A resolver combines the
31
+ manifest with country, region, language and privacy signals to produce an init
32
+ result for one visitor.
33
+
34
+ Reusing the public document avoids asking the consent backend to resolve policy
35
+ for every application request. Cache misses and revalidation still fetch the
36
+ manifest, and consent writes still need the backend. Measure the deployed
37
+ request path before promising a latency improvement.
38
+
39
+ Do not put secrets, visitor identifiers or consent records into a manifest.
40
+ Keep personalized init responses out of shared caches. Changing a policy also
41
+ requires a refresh strategy for cached or build-time manifests.
42
+
43
+ ## Use a build-time manifest by default
44
+
45
+ The build fetches your public policy once and bundles it, so the server never
46
+ fetches it at runtime.
47
+
48
+ `manifest()` is the default mode in every server-rendered framework.
49
+ [Consent modes](./modes.md#download-the-manifest-at-build-time)
50
+ covers each framework's build integration and what happens when the
51
+ download fails.
52
+
53
+ The framework quickstarts include the build integration for supported
54
+ deployments. Server resolution uses the snapshot without an upstream manifest
55
+ request. Browser resolution includes the policy and resolver in the client
56
+ bundle, and still calls `/init` for a regional policy when the browser doesn't
57
+ know the visitor's location, so the React, Vue and Svelte quickstarts use
58
+ `hosted()` instead. Static Nuxt and
59
+ Astro sites and script-tag sites keep the runtime setup from their guides.
60
+
61
+ The snapshot is fixed at build time:
62
+
63
+ * Rebuild after changing policies, translations or vendors. If your CI caches
64
+ build output, force a fresh build.
65
+ * Consent choices still go to the backend.
66
+
67
+ The build reads the backend URL from your public backend URL variable when
68
+ the config doesn't pass one: `NEXT_PUBLIC_C15T_BACKEND_URL` in Next.js,
69
+ `NUXT_PUBLIC_C15T_BACKEND_URL` in Nuxt, `PUBLIC_C15T_BACKEND_URL` in Astro,
70
+ Svelte and SvelteKit, and `VITE_C15T_BACKEND_URL` in TanStack Start and other
71
+ Vite apps. Each also reads the matching Inth variable, such as
72
+ `NEXT_PUBLIC_INTH_PROJECT_URL`, when the c15t one is unset. See
73
+ [set the backend URL](./modes.md#set-the-backend-url).
74
+
75
+ The fetch waits at most 10 seconds. When it fails, or no backend URL is set,
76
+ every framework does the same thing:
77
+
78
+ | Command | Default when the fetch fails |
79
+ | ------------------------------------------------------------------------- | -------------------------------------------------------- |
80
+ | Production build: `next build`, `vite build`, `nuxt build`, `astro build` | The build stops with an error. |
81
+ | Dev: `next dev`, `vite dev`, `nuxt dev`, `astro dev` | A warning, and the server fetches the policy at runtime. |
82
+
83
+ Set `onBuildError` to use one behaviour for both. `'fail'` stops dev too.
84
+ `'runtime'` lets a production build finish, and the server fetches the policy
85
+ at runtime. The `C15T_ON_BUILD_ERROR` environment variable overrides the
86
+ option, so you can deploy during a backend outage without a code change:
87
+
88
+ ```sh
89
+ C15T_ON_BUILD_ERROR=runtime npm run build
90
+ ```
91
+
92
+ Turborepo's strict environment mode hides undeclared variables from tasks, so
93
+ list `C15T_ON_BUILD_ERROR` in the build task's `passThroughEnv` there.
94
+
95
+ The build skips the fetch, without an error, when it can't use a snapshot,
96
+ for example when the backend URL is relative. With `onBuildError: 'fail'`, a
97
+ relative URL stops the build. [Consent modes](./modes.md#what-happens-when-the-download-fails)
98
+ lists every case.
99
+
100
+ ## How manifest mode counts visitors
101
+
102
+ The backend counts visitors from `/init` requests, and manifest resolution
103
+ skips them. To keep the count, the server adapters send a session report after
104
+ each resolution: the host posts to the backend's `POST /sessions` from the
105
+ server, after the response. The browser sends nothing, and the report stores
106
+ no identity; the visitor's IP address and user agent are forwarded under the
107
+ backend's usual IP handling. Static output resolves in the browser and sends
108
+ no report. Set `reportSessions: false` on an adapter to turn it off.
109
+
110
+ ## Link an init to the save that follows
111
+
112
+ Each page load gets a journey id, a random UUID sent on requests c15t already
113
+ makes:
114
+
115
+ | Request | Query parameters |
116
+ | ---------------- | ------------------------------------------------------------------------------------ |
117
+ | `GET /init` | `journey`, `journeyScope`, `stored` (`1` if a choice or notice dismissal was stored) |
118
+ | `POST /subjects` | `journey`, `journeyScope` |
119
+
120
+ Session reports carry it as `journey: { id, scope, storedChoice, prompt, domain }`.
121
+ A report and a save with the same `id` belong to one page load. `prompt` is
122
+ `due`, `stored` or `not-required`; a page that falls back to the default opt-in
123
+ banner counts as `due` or `stored`. A stored answer counts as `stored` even if a
124
+ policy change makes c15t ask again.
125
+
126
+ The id is random, is never the subject id and is never written to a cookie.
127
+ Every save that carries one follows an `/init` or report with the same id.
128
+ Saves replayed after going offline carry none.
129
+
130
+ | `journey` | Behavior |
131
+ | ------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
132
+ | `'page'` (default) | One id per page load, in memory. |
133
+ | `'tab'` | Kept in `sessionStorage` while a prompt is due, and removed once the visitor chooses or no prompt is due. Only when the browser resolves init; server-rendered pages use `'page'`. |
134
+ | `false` | No journey. |
135
+
136
+ Set it on the runtime or provider. In Next.js use `defineConsentConfig({ journey })`;
137
+ in TanStack Start pass the same value to `resolveConsent` and `ConsentRoot`; with
138
+ the inline prefetch script, pass it to `buildPrefetchScript` or to
139
+ `consentManifest({ initPrefetch: { journey } })`. Left unset, the script
140
+ continues a `'tab'` journey the tab already holds. A tab's first page has
141
+ none, so its `/init` reports the scope as `'page'`. The id still links it to
142
+ the save. Pass `journey: 'tab'` to the script too if you report on scope. Vue, Svelte, Astro
143
+ and the script tag use `'page'`. A manifest that resolves locally in the
144
+ browser reports no init, so it sends no journey.
145
+
146
+ If you pass a transport `hosted()` a `fetch`, match on the path: URLs now carry a query string.
147
+
148
+ ## What does regular `/init` do?
149
+
150
+ `hosted()` uses `${backendURL}/init` for initialization and
151
+ `${backendURL}/subjects` for consent submissions. The name `hosted` describes
152
+ the protocol; the URL can belong to Inth or your own c15t backend.
153
+
154
+ ```ts title="c15t.config.ts"
155
+ import { defineConsentConfig, hosted } from 'c15t/next';
156
+
157
+ export default defineConsentConfig({ mode: hosted() });
158
+ ```
159
+
160
+ Each framework passes the mode in a different place, and server-rendered
161
+ frameworks take the data `hosted()` from their own package.
162
+ [Consent modes](./modes.md#import-the-factories-from-your-framework-package)
163
+ lists where each one goes.
164
+
165
+ A regular backend `/init` request lets the backend resolve the visitor context.
166
+ A same-origin URL named `/api/c15t/init` can instead resolve from a cached
167
+ manifest in your application. The URL name alone does not tell you which path
168
+ runs.
169
+
170
+ In the browser, an inline script in `<head>` can start `/init` while the
171
+ app's JavaScript downloads, and `hosted()` uses that response. Vite apps get
172
+ it from `consentManifest()` by default, Nuxt adds it to pages with
173
+ `ssr: false`, and TanStack Start has `consentPrefetchHead`. Elsewhere, render
174
+ `buildPrefetchScript({ backendURL })` from `c15t` yourself. If c15t assigns
175
+ a banner experiment's arm, give the script the same `experiment`, or
176
+ `hosted()` sends a second `/init` for visitors who have not chosen yet.
177
+
178
+ ## How do transports and proxies differ?
179
+
180
+ A transport implements initialization, saving and optional record operations.
181
+ A proxy changes where HTTP requests travel. It does not change the policy
182
+ resolver or make personalized responses safe to cache.
183
+
184
+ For a same-origin init route that resolves a manifest, the hosted transport can
185
+ separate policy reads and record writes. With a backend rewrite mounted at
186
+ `/api/c15t`, a single-page app can use the transport `hosted()` from
187
+ `c15t`:
188
+
189
+ ```ts title="src/consent-mode.ts"
190
+ import { hosted } from 'c15t';
191
+
192
+ export const mode = hosted({
193
+ backendURL: '/api/c15t',
194
+ initURL: '/api/c15t/init',
195
+ });
196
+ ```
197
+
198
+ The route must return the c15t init response contract. c15t adds its inputs to
199
+ `initURL` as query parameters, replacing any of your own with the same name.
200
+ See [query parameters and CORS](https://v3.c15t.com/docs/self-host/api/endpoints#query-parameters-and-cors)
201
+ for the names. Because `initURL` is set, `assertDecisionInputs` defaults to
202
+ `true`: saves carry the policy decision they were made against when init
203
+ returned no signed policy snapshot token, so the backend can reject a save
204
+ made against a stale policy. Server-rendered frameworks do this for you when
205
+ you set `routePrefix`: the browser re-inits through `${routePrefix}/init`.
206
+ Every framework rejects `routePrefix: '/'` when it sets up, because a
207
+ catch-all consent route at the site root would catch every page.
208
+
209
+ The init route resolves policy; the backend rewrite forwards `/api/c15t/subjects`
210
+ and other record endpoints. Configure both if you choose this optional proxy
211
+ variant. Server-rendered frameworks do both with one option: `proxy: true` in
212
+ Next.js `c15t.config.ts` or TanStack Start's `createConsentStateHandler`,
213
+ with a consent route created with `proxy: true`. The
214
+ [Next.js recipe](https://v3.c15t.com/docs/frameworks/next/optimization#keep-browser-consent-requests-on-your-origin)
215
+ shows the configuration. A direct absolute backend URL works
216
+ without a rewrite.
217
+
218
+ This optional optimization keeps c15t requests on the app's origin and avoids a separate browser DNS lookup
219
+ and TLS connection to the consent backend. The app server still connects to
220
+ the upstream backend for manifest refreshes and consent writes. Vendor scripts
221
+ and vendor requests keep their own origins.
222
+
223
+ The rewrite destination and the init route use the absolute upstream endpoint,
224
+ such as `https://your-project.inth.app`. The browser uses `/api/c15t` without
225
+ needing the upstream URL. A static export cannot serve a Next.js route or
226
+ rewrite at runtime; use the absolute Inth URL or a proxy provided by the static
227
+ host instead.
228
+
229
+ ## When should I use offline mode?
230
+
231
+ Not recommended for production environments. Use Inth or a self-hosted backend
232
+ for production policy and consent records.
233
+
234
+ `offline()` resolves bundled policy rules without an init request and acknowledges
235
+ saves locally. The runtime's persistence module stores the choice in browser
236
+ storage. There is no backend audit history, cross-device record service or IP
237
+ geolocation supplied by this transport.
238
+
239
+ Use your framework's `offline()` so its translations and provider context are
240
+ included. In a React app it replaces the mode passed to `ConsentProvider`:
241
+
242
+ ```ts title="src/consent-mode.ts"
243
+ import { offline } from 'c15t/react';
244
+
245
+ export const mode = offline();
246
+ ```
247
+
248
+ In Next.js, TanStack Start, Nuxt, Astro and SvelteKit, pass the data
249
+ `offline()` from the framework package where the config takes `mode`; see
250
+ [consent modes](./modes.md#import-the-factories-from-your-framework-package).
251
+
252
+ With no `policyRules`, the current offline transport uses the recommended rule
253
+ pack. Supplying `policyRules` replaces that pack. Unknown country and region are
254
+ real resolution inputs; offline mode does not discover a visitor's location.
255
+ Use [policy rules](./policies.md) to understand
256
+ matching and defaults, and test the missing-location case.
257
+
258
+ Offline mode is an explicit architecture choice, not an automatic fallback for
259
+ a failed Inth request. If hosted initialization fails before a policy resolves,
260
+ optional permissions remain denied and the stock prompt stays hidden. Observe
261
+ initialization failures instead of silently changing policy sources.
262
+
263
+ ## Can I provide my own transport?
264
+
265
+ `custom(transport)` accepts a `KernelTransport` with the v3 `init` and `save`
266
+ contract. It does not accept v2 endpoint handlers such as `setConsent`. Keep
267
+ policy resolution, record acknowledgments and failure behavior consistent with
268
+ the kernel contract. Prefer a built-in transport when your backend supports it.
269
+
270
+ ## Verify the selected path
271
+
272
+ Inspect browser and server requests separately. A server manifest fetch will
273
+ not appear in the browser's Network panel. With a build-time snapshot, start a
274
+ fresh production server and confirm it makes no upstream `/manifest` request.
275
+ After a policy edit, rebuild and confirm the new policy appears. On a runtime
276
+ manifest path, check that
277
+ page requests do not call the backend `/init`, a visitor's choice still reaches
278
+ the backend's `/subjects`, and policy changes become visible after the configured
279
+ refresh. With a same-origin consent proxy, the browser should call only
280
+ `/api/c15t` paths for consent HTTP traffic; inspect server logs to verify their
281
+ upstream destinations.
282
+
283
+ Test different locations, missing location headers, GPC, returning choices and
284
+ backend failure. See [verification](../guides/verify-consent.md).
@@ -0,0 +1,123 @@
1
+ ---
2
+ title: How consent works
3
+ description: What c15t decides on each page load, the difference between a
4
+ permission and a recorded choice, and what happens when a visitor saves.
5
+ group: concepts
6
+ ---
7
+
8
+ ## What c15t decides on each page load
9
+
10
+ On every page load c15t answers one question for each consent category: is
11
+ this allowed right now? To answer it, c15t:
12
+
13
+ 1. Selects a **policy** for the visitor, usually by country and region. The
14
+ policy says whether optional categories start denied (opt-in) or allowed
15
+ (opt-out), and whether to show a banner.
16
+ 2. Reads the visitor's **stored choice** from a cookie and localStorage, if
17
+ there is one that still matches the policy.
18
+ 3. Reads **privacy signals** such as Global Privacy Control (GPC).
19
+
20
+ The result is a set of **permissions**, one per category. Components, script
21
+ loaders, embeds and your own code read those permissions. Nothing optional
22
+ runs until the policy has resolved: while it loads, and if it fails, every
23
+ optional category is denied.
24
+
25
+ A banner is only the interface. It does not stop a script you load with a
26
+ plain `<script>` tag or a vendor SDK you initialize yourself. To gate that code,
27
+ register it with c15t. See [integrations](../integrations/overview.md).
28
+
29
+ ## Categories
30
+
31
+ | Category | Use it for |
32
+ | --------------- | -------------------------------------------------- |
33
+ | `necessary` | Code the site cannot work without. Always allowed. |
34
+ | `functionality` | Optional features such as support chat. |
35
+ | `measurement` | Analytics and usage measurement. |
36
+ | `experience` | Personalization. |
37
+ | `marketing` | Advertising, retargeting and pixels. |
38
+
39
+ Assign a category by what the code does, not by what would be convenient.
40
+ Calling analytics `necessary` does not make it necessary.
41
+ [Consent categories](./consent-categories.md) explains which
42
+ categories the preference dialog shows and how policy scope affects them.
43
+
44
+ ## Policies
45
+
46
+ A policy has a **model** and a **prompt**:
47
+
48
+ | Model | Optional categories before a choice |
49
+ | --------- | ----------------------------------------------------------------- |
50
+ | `opt-in` | Denied until the visitor allows them. |
51
+ | `opt-out` | Allowed until the visitor refuses them or sends a privacy signal. |
52
+ | `iab` | Controlled by an IAB TCF consent string. |
53
+ | `none` | Allowed, with no prompt. |
54
+
55
+ | Prompt | What the visitor sees |
56
+ | -------- | ------------------------------------------------------------------------------ |
57
+ | `choice` | A banner asking for a decision. |
58
+ | `notice` | A notice they can dismiss. Dismissing records an acknowledgement, not consent. |
59
+ | `none` | Nothing on load. The policy can still require a way to open preferences. |
60
+
61
+ With [Inth](https://inth.com) you manage policies in your project, and the app
62
+ receives them from the backend. Changing a stylesheet or importing a preset in
63
+ the browser does not override a hosted policy.
64
+ [Policies](./policies.md) covers presets, scope, and why a banner may
65
+ not appear.
66
+
67
+ ## A permission is not a recorded choice
68
+
69
+ These two values answer different questions, and mixing them up is the most
70
+ common integration bug:
71
+
72
+ * **Permission** (`effectivePermissions`, `useConsent('measurement')`) answers
73
+ "may this run now?" Under an opt-out policy it can be `true` before the
74
+ visitor has done anything.
75
+ * **Recorded choice** (`explicitChoice`) answers "what did the visitor decide?"
76
+ It only changes when the visitor accepts, rejects or saves preferences.
77
+
78
+ | Task | Read |
79
+ | ---------------------------------------------------- | ------------------- |
80
+ | Load a script or render an optional feature | Permission |
81
+ | Show what the visitor chose, or report consent rates | Recorded choice |
82
+ | Decide whether a prompt is needed | `promptRequirement` |
83
+ | Find out why a region behaves differently | `policyRule` |
84
+ | Check that the policy loaded | `resolution.status` |
85
+
86
+ Never turn a permission into a saved choice. Hydrating server state, reading a
87
+ cookie or rendering a component does not count as a visitor action.
88
+ `onChoiceRecorded` fires only for a visitor's action; `onPermissionsChanged`
89
+ also fires when a choice expires or a privacy signal changes.
90
+
91
+ ## Notices and privacy signals
92
+
93
+ Dismissing a notice acknowledges it. It grants nothing and leaves earlier
94
+ refusals in place.
95
+
96
+ GPC is a browser setting that asks sites not to sell or share data. c15t reads
97
+ it live on every evaluation and applies the restrictions your policy configures
98
+ for it. It never becomes a stored refusal: when the browser stops sending GPC,
99
+ the restriction ends. The backend also sees the current value.
100
+
101
+ ## What happens when a visitor saves
102
+
103
+ When a visitor clicks Accept, Reject or Save, c15t:
104
+
105
+ 1. Updates permissions and closes the banner or dialog in the same click.
106
+ Scripts, embeds and network rules follow the new permissions immediately.
107
+ 2. Writes the choice to the cookie and localStorage.
108
+ 3. Sends the choice to the consent backend. If the request fails, the choice
109
+ stays saved in the browser and the request is retried later.
110
+ 4. Reloads the page if the visitor turned off something they had allowed.
111
+ Code that already ran cannot be unloaded, so the reload starts a page with
112
+ only permitted code. Set `reloadOnConsentRevoked: false` to handle revocation
113
+ yourself.
114
+
115
+ The [consent state reference](./consent-state.md) documents the exact
116
+ ordering, retries, server hydration and how open tabs stay in step.
117
+
118
+ ## Where consent data comes from
119
+
120
+ A consent backend supplies policies and stores consent records. Use Inth, run
121
+ the [c15t backend](https://v3.c15t.com/docs/self-host/overview) yourself, or keep policies in the
122
+ browser for local development. [Choose your setup](./choose-your-setup.md)
123
+ walks through the options for your framework and hosting.