ultimate-jekyll-manager 0.0.60 → 0.0.62

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 (241) hide show
  1. package/.claude/settings.local.json +7 -1
  2. package/_notes/NOTES-app.md +92 -0
  3. package/_notes/NOTES-sub-2.md +42 -0
  4. package/_notes/NOTES-sub-ai.md +165 -0
  5. package/_notes/NOTES-sub-endpoints.md +44 -0
  6. package/_notes/NOTES-sub-example.md +92 -0
  7. package/_notes/NOTES-sub-plan.md +36 -0
  8. package/_notes/NOTES-sub-status.md +123 -0
  9. package/_notes/TODO-frontend.md +61 -0
  10. package/assets/logos/brandmarks/original/apple-app-store.svg +1 -0
  11. package/assets/logos/brandmarks/original/apple.svg +1 -0
  12. package/assets/logos/brandmarks/original/bitcoin.svg +1 -0
  13. package/assets/logos/brandmarks/original/bootstrap.svg +43 -0
  14. package/assets/logos/brandmarks/original/discord.svg +1 -0
  15. package/assets/logos/brandmarks/original/facebook-f.svg +1 -0
  16. package/assets/logos/brandmarks/original/facebook.svg +1 -0
  17. package/assets/logos/brandmarks/original/github.svg +6 -0
  18. package/assets/logos/brandmarks/original/gitlab.svg +17 -0
  19. package/assets/logos/brandmarks/original/google-a-s.svg +1 -0
  20. package/assets/logos/brandmarks/original/google-chrome-webstore.svg +49 -0
  21. package/assets/logos/brandmarks/original/google-play-store.svg +1 -0
  22. package/assets/logos/brandmarks/original/google-web-search.svg +1 -0
  23. package/assets/logos/brandmarks/original/google.svg +1 -0
  24. package/assets/logos/brandmarks/original/gulp.svg +4 -0
  25. package/assets/logos/brandmarks/original/html-5.svg +1 -0
  26. package/assets/logos/brandmarks/original/instagram.svg +1 -0
  27. package/assets/logos/brandmarks/original/javascript.svg +1 -0
  28. package/assets/logos/brandmarks/original/jira.svg +23 -0
  29. package/assets/logos/brandmarks/original/linkedin.svg +1 -0
  30. package/assets/logos/brandmarks/original/linux.svg +28 -0
  31. package/assets/logos/brandmarks/original/microsoft.svg +1 -0
  32. package/assets/logos/brandmarks/original/npm.svg +8 -0
  33. package/assets/logos/brandmarks/original/pinterest.svg +1 -0
  34. package/assets/logos/brandmarks/original/reddit.svg +1 -0
  35. package/assets/logos/brandmarks/original/sass.svg +3 -0
  36. package/assets/logos/brandmarks/original/slack.svg +33 -0
  37. package/assets/logos/brandmarks/original/soundcloud.svg +1 -0
  38. package/assets/logos/brandmarks/original/spotify.svg +5 -0
  39. package/assets/logos/brandmarks/original/tiktok.svg +1 -0
  40. package/assets/logos/brandmarks/original/tumblr.svg +1 -0
  41. package/assets/logos/brandmarks/original/twitter.svg +1 -0
  42. package/assets/logos/brandmarks/original/yahoo-y.svg +1 -0
  43. package/assets/logos/brandmarks/original/youtube-square.svg +1 -0
  44. package/assets/logos/brandmarks/original/youtube.svg +1 -0
  45. package/assets/logos/combomarks/dark/airbnb.svg +30 -0
  46. package/assets/logos/combomarks/dark/slack.svg +38 -0
  47. package/assets/logos/combomarks/dark/spotify.svg +35 -0
  48. package/assets/logos/combomarks/dark/twilio.svg +26 -0
  49. package/assets/logos/combomarks/dark/weebly.svg +35 -0
  50. package/assets/logos/combomarks/gray/airbnb.svg +33 -0
  51. package/assets/logos/combomarks/gray/alphabet.svg +23 -0
  52. package/assets/logos/combomarks/gray/amazon.svg +38 -0
  53. package/assets/logos/combomarks/gray/boring-company.svg +91 -0
  54. package/assets/logos/combomarks/gray/burberry.svg +239 -0
  55. package/assets/logos/combomarks/gray/embark.svg +21 -0
  56. package/assets/logos/combomarks/gray/fitbit.svg +61 -0
  57. package/assets/logos/combomarks/gray/fred-perry.svg +94 -0
  58. package/assets/logos/combomarks/gray/google.svg +27 -0
  59. package/assets/logos/combomarks/gray/hollister.svg +34 -0
  60. package/assets/logos/combomarks/gray/hubspot.svg +27 -0
  61. package/assets/logos/combomarks/gray/kaplan.svg +33 -0
  62. package/assets/logos/combomarks/gray/lenovo.svg +27 -0
  63. package/assets/logos/combomarks/gray/levis.svg +25 -0
  64. package/assets/logos/combomarks/gray/mapbox.svg +37 -0
  65. package/assets/logos/combomarks/gray/netflix.svg +15 -0
  66. package/assets/logos/combomarks/gray/new-balance.svg +32 -0
  67. package/assets/logos/combomarks/gray/nike.svg +17 -0
  68. package/assets/logos/combomarks/gray/paypal.svg +41 -0
  69. package/assets/logos/combomarks/gray/puma.svg +82 -0
  70. package/assets/logos/combomarks/gray/samsung.svg +26 -0
  71. package/assets/logos/combomarks/gray/shopify.svg +36 -0
  72. package/assets/logos/combomarks/gray/slack.svg +42 -0
  73. package/assets/logos/combomarks/gray/spotify.svg +38 -0
  74. package/assets/logos/combomarks/gray/stripe.svg +24 -0
  75. package/assets/logos/combomarks/gray/tnf.svg +30 -0
  76. package/assets/logos/combomarks/gray/twilio.svg +29 -0
  77. package/assets/logos/combomarks/gray/uber.svg +24 -0
  78. package/assets/logos/combomarks/gray/weebly.svg +38 -0
  79. package/assets/logos/combomarks/original/airbnb.svg +33 -0
  80. package/assets/logos/combomarks/original/alphabet.svg +23 -0
  81. package/assets/logos/combomarks/original/amazon.svg +38 -0
  82. package/assets/logos/combomarks/original/boring-company.svg +91 -0
  83. package/assets/logos/combomarks/original/embark.svg +24 -0
  84. package/assets/logos/combomarks/original/fitbit.svg +60 -0
  85. package/assets/logos/combomarks/original/google.svg +28 -0
  86. package/assets/logos/combomarks/original/hubspot.svg +29 -0
  87. package/assets/logos/combomarks/original/lenovo.svg +24 -0
  88. package/assets/logos/combomarks/original/mapbox.svg +39 -0
  89. package/assets/logos/combomarks/original/netflix.svg +15 -0
  90. package/assets/logos/combomarks/original/paypal.svg +41 -0
  91. package/assets/logos/combomarks/original/samsung.svg +25 -0
  92. package/assets/logos/combomarks/original/shopify.svg +35 -0
  93. package/assets/logos/combomarks/original/slack.svg +47 -0
  94. package/assets/logos/combomarks/original/spotify.svg +37 -0
  95. package/assets/logos/combomarks/original/stripe.svg +24 -0
  96. package/assets/logos/combomarks/original/uber.svg +24 -0
  97. package/assets/logos/combomarks/original/weebly.svg +34 -0
  98. package/assets/logos/combomarks/white/airbnb.svg +33 -0
  99. package/assets/logos/combomarks/white/alphabet.svg +23 -0
  100. package/assets/logos/combomarks/white/amazon.svg +38 -0
  101. package/assets/logos/combomarks/white/boring-company.svg +91 -0
  102. package/assets/logos/combomarks/white/embark.svg +21 -0
  103. package/assets/logos/combomarks/white/fitbit.svg +61 -0
  104. package/assets/logos/combomarks/white/google.svg +27 -0
  105. package/assets/logos/combomarks/white/hubspot.svg +27 -0
  106. package/assets/logos/combomarks/white/kaplan.svg +33 -0
  107. package/assets/logos/combomarks/white/lenovo.svg +27 -0
  108. package/assets/logos/combomarks/white/mapbox.svg +37 -0
  109. package/assets/logos/combomarks/white/netflix.svg +15 -0
  110. package/assets/logos/combomarks/white/paypal.svg +40 -0
  111. package/assets/logos/combomarks/white/samsung.svg +26 -0
  112. package/assets/logos/combomarks/white/shopify.svg +36 -0
  113. package/assets/logos/combomarks/white/slack.svg +42 -0
  114. package/assets/logos/combomarks/white/spotify.svg +38 -0
  115. package/assets/logos/combomarks/white/stripe.svg +24 -0
  116. package/assets/logos/combomarks/white/twilio.svg +29 -0
  117. package/assets/logos/combomarks/white/uber.svg +24 -0
  118. package/assets/logos/combomarks/white/weebly.svg +38 -0
  119. package/dist/assets/css/core/alert.scss +32 -16
  120. package/dist/assets/css/core/animations.scss +212 -188
  121. package/dist/assets/css/core/buttons.scss +22 -23
  122. package/dist/assets/css/core/chatsy.scss +36 -21
  123. package/dist/assets/css/core/cookieconsent.scss +49 -74
  124. package/dist/assets/css/core/custom-font-awesome.scss +21 -9
  125. package/dist/assets/css/core/initialize.scss +16 -5
  126. package/dist/assets/css/core/lazy-loading.scss +25 -31
  127. package/dist/assets/css/core/social-sharing.scss +7 -2
  128. package/dist/assets/css/core/utilities.scss +39 -16
  129. package/dist/assets/css/pages/download/index.scss +250 -0
  130. package/dist/assets/css/pages/payment/confirmation/index.scss +1 -51
  131. package/dist/assets/css/ultimate-jekyll-manager.scss +0 -3
  132. package/dist/assets/js/core/chatsy.js +5 -5
  133. package/dist/assets/js/core/lazy-loading.js +72 -12
  134. package/dist/assets/js/core/page-loader.js +3 -1
  135. package/dist/assets/js/core/query-strings.js +4 -2
  136. package/dist/assets/js/libs/dev.js +25 -25
  137. package/dist/assets/js/modules/vert.js +283 -0
  138. package/dist/assets/js/pages/account/sections/api-keys.js +5 -3
  139. package/dist/assets/js/pages/account/sections/billing.js +36 -42
  140. package/dist/assets/js/pages/account/sections/profile.js +5 -3
  141. package/dist/assets/js/pages/account/sections/referrals.js +5 -3
  142. package/dist/assets/js/pages/blog/post.js +114 -0
  143. package/dist/assets/js/pages/download/index.js +352 -0
  144. package/dist/assets/js/pages/payment/checkout/modules/session.js +19 -10
  145. package/dist/assets/js/pages/payment/checkout/modules/ui.js +8 -8
  146. package/dist/assets/js/pages/pricing/index.js +83 -0
  147. package/dist/assets/js/ultimate-jekyll-manager.js +3 -0
  148. package/dist/assets/themes/bootstrap/_theme.scss +3 -3
  149. package/dist/assets/themes/classy/_theme.js +7 -1
  150. package/dist/assets/themes/classy/_theme.scss +23 -15
  151. package/dist/assets/themes/classy/css/base/_backgrounds.scss +105 -0
  152. package/dist/assets/themes/classy/css/base/_borders.scss +56 -0
  153. package/dist/assets/themes/classy/css/{_soft-colors.scss → base/_soft-colors.scss} +12 -4
  154. package/dist/assets/themes/classy/css/{_spacing.scss → base/_spacing.scss} +14 -2
  155. package/dist/assets/themes/classy/css/{_typography.scss → base/_typography.scss} +55 -17
  156. package/dist/assets/themes/classy/css/base/_utilities.scss +77 -0
  157. package/dist/assets/themes/classy/css/{_variables.scss → base/_variables.scss} +32 -9
  158. package/dist/assets/themes/classy/css/{_avatars.scss → components/_avatars.scss} +15 -5
  159. package/dist/assets/themes/classy/css/components/_badges.scss +25 -0
  160. package/dist/assets/themes/classy/css/{_buttons.scss → components/_buttons.scss} +82 -149
  161. package/dist/assets/themes/classy/css/components/_cards.scss +33 -0
  162. package/dist/assets/themes/classy/css/{_forms.scss → components/_forms.scss} +12 -4
  163. package/dist/assets/themes/classy/css/{_links.scss → components/_links.scss} +6 -1
  164. package/dist/assets/themes/classy/css/components/_logo-scroll.scss +57 -0
  165. package/dist/assets/themes/classy/css/components/_spinners.scss +19 -0
  166. package/dist/assets/themes/classy/css/layout/_blog.scss +42 -0
  167. package/dist/assets/themes/classy/css/layout/_general.scss +43 -0
  168. package/dist/assets/themes/classy/css/{_navigation.scss → layout/_navigation.scss} +39 -45
  169. package/dist/assets/themes/classy/css/layout/_team.scss +18 -0
  170. package/dist/assets/themes/classy/js/logo-scroll.js +83 -0
  171. package/dist/assets/themes/classy/js/navbar-scroll.js +48 -13
  172. package/dist/defaults/dist/_includes/core/foot.html +3 -0
  173. package/dist/defaults/dist/_includes/modules/adunits/adsense.html +57 -60
  174. package/dist/defaults/dist/_includes/themes/classy/backend/sections/nav.html +1 -1
  175. package/dist/defaults/dist/_includes/themes/classy/frontend/sections/nav.html +23 -21
  176. package/dist/defaults/dist/_layouts/blueprint/about.html +12 -0
  177. package/dist/defaults/dist/_layouts/blueprint/download.html +12 -0
  178. package/dist/defaults/dist/_layouts/core/root.html +3 -1
  179. package/dist/defaults/dist/_layouts/modules/utilities/redirect.html +8 -4
  180. package/dist/defaults/dist/_layouts/themes/classy/frontend/core/base.html +36 -1
  181. package/dist/defaults/dist/_layouts/themes/classy/frontend/core/minimal.html +3 -3
  182. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/404.html +8 -33
  183. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/about.html +265 -0
  184. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/account/index.html +636 -688
  185. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/oauth2.html +15 -15
  186. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/reset.html +8 -17
  187. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signin.html +26 -15
  188. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/auth/signup.html +21 -12
  189. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/blog/index.html +132 -114
  190. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/blog/post.html +75 -57
  191. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/contact.html +51 -47
  192. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/download.html +748 -0
  193. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/index.html +289 -141
  194. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/payment/checkout.html +14 -14
  195. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/payment/confirmation.html +28 -19
  196. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/pricing.html +226 -83
  197. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/team/index.html +127 -190
  198. package/dist/defaults/dist/_layouts/themes/classy/frontend/pages/team/member.html +162 -1
  199. package/dist/defaults/dist/_team/alex.md +3 -1
  200. package/dist/defaults/dist/_team/ian.md +5 -1
  201. package/dist/defaults/dist/ads.txt +1 -1
  202. package/dist/defaults/dist/pages/about.md +7 -0
  203. package/dist/defaults/dist/pages/team/index.md +7 -0
  204. package/dist/defaults/dist/pages/test/libraries/adsense.html +68 -0
  205. package/dist/defaults/dist/pages/test/libraries/bootstrap-components.html +136 -93
  206. package/dist/defaults/dist/pages/test/libraries/lazy-loading.html +47 -29
  207. package/dist/defaults/dist/redirects/authentication/helpers/forgot.html +9 -0
  208. package/dist/defaults/dist/redirects/download/{linux-debian.html → helpers/linux-debian.html} +1 -1
  209. package/dist/defaults/dist/redirects/download/{linux-snap.html → helpers/linux-snap.html} +1 -1
  210. package/dist/defaults/dist/redirects/download/linux/debian.html +9 -0
  211. package/dist/defaults/dist/redirects/download/linux/index.html +9 -0
  212. package/dist/defaults/dist/redirects/download/linux/snap.html +9 -0
  213. package/dist/defaults/dist/redirects/download/{mac.html → mac/index.html} +1 -1
  214. package/dist/defaults/dist/redirects/download/mac/universal.html +9 -0
  215. package/dist/defaults/dist/redirects/download/{windows.html → windows/index.html} +1 -1
  216. package/dist/defaults/dist/redirects/download/windows/universal.html +9 -0
  217. package/dist/defaults/src/_config.yml +11 -6
  218. package/dist/defaults/src/_includes/frontend/sections/footer.json +64 -3
  219. package/dist/defaults/src/_includes/frontend/sections/nav.json +61 -27
  220. package/dist/gulp/tasks/distribute.js +3 -0
  221. package/dist/gulp/tasks/sass.js +14 -13
  222. package/dist/gulp/tasks/webpack.js +15 -0
  223. package/dist/index.js +13 -3
  224. package/dist/service-worker.js +65 -24
  225. package/package.json +4 -4
  226. package/dist/assets/css/core/temp-custom.scss +0 -2
  227. package/dist/assets/themes/classy/css/_badges.scss +0 -170
  228. package/dist/assets/themes/classy/css/_blog.scss +0 -35
  229. package/dist/assets/themes/classy/css/_cards.scss +0 -387
  230. package/dist/assets/themes/classy/css/_utilities.scss +0 -397
  231. package/dist/defaults/dist/_includes/modules/adunits/fallback.html +0 -164
  232. package/dist/defaults/dist/_layouts/blueprint/about.md +0 -48
  233. package/dist/defaults/dist/_layouts/blueprint/download.md +0 -49
  234. /package/{CLAUDE-pages.md → _notes/CLAUDE-pages.md} +0 -0
  235. /package/{CLAUDE-pages2.md → _notes/CLAUDE-pages2.md} +0 -0
  236. /package/{TODO-Claude.rtf → _notes/TODO-Claude.rtf} +0 -0
  237. /package/{TODO-FileStructure.md → _notes/TODO-FileStructure.md} +0 -0
  238. /package/{TODO-checkout.md → _notes/TODO-checkout.md} +0 -0
  239. /package/{TODO-legacy.md → _notes/TODO-legacy.md} +0 -0
  240. /package/{TODO-template-system.md → _notes/TODO-template-system.md} +0 -0
  241. /package/{TODO-theme.md → _notes/TODO-theme.md} +0 -0
@@ -34,7 +34,13 @@
34
34
  "Read(/Users/ian/Developer/Repositories/ITW-Creative-Works/jekyll-uj-powertools/**)",
35
35
  "Read(/Users/ian/Developer/Repositories/ITW-Creative-Works/jekyll-uj-powertools/**)",
36
36
  "Read(/Users/ian/Developer/Repositories/ITW-Creative-Works/jekyll-uj-powertools/**)",
37
- "Read(/Users/ian/Developer/Repositories/ITW-Creative-Works/jekyll-uj-powertools/**)"
37
+ "Read(/Users/ian/Developer/Repositories/ITW-Creative-Works/jekyll-uj-powertools/**)",
38
+ "Bash(for:*)",
39
+ "Bash(do if [[ \"$file\" != *\"-\"* ]])",
40
+ "Bash(then [ -f \"$file\" ])",
41
+ "Bash(fi)",
42
+ "Bash(done)",
43
+ "Bash(do [ -f \"$file\" ])"
38
44
  ],
39
45
  "deny": []
40
46
  }
@@ -0,0 +1,92 @@
1
+ {
2
+ "server": "https://us-central1-studymonkey-ai.cloudfunctions.net",
3
+ "images": {
4
+ "combomark": "https://cdn.itwcreativeworks.com/assets/studymonkey/images/logo/studymonkey-combomark-black-1024x.png",
5
+ "brandmark": "https://cdn.itwcreativeworks.com/assets/studymonkey/images/logo/studymonkey-brandmark-black-1024x1024.png",
6
+ "wordmark": "https://cdn.itwcreativeworks.com/assets/studymonkey/images/logo/studymonkey-wordmark-black-1024x.png"
7
+ },
8
+ "github": {
9
+ "repo": "studymonkey-website",
10
+ "user": "ianwieds"
11
+ },
12
+ "apiKeys": {
13
+ "stripe": {
14
+ "publishableKey": "pk_live_51Mirn8HGybgi7uQGuE5IcaED0VByYRfVXGUmBDqnUyldcf2BJrpiFCDmwu4NoSDv34LMBw5mfCNdB3pmRki0jhmx00jFgW4akz"
15
+ },
16
+ "chatsy": {
17
+ "accountId": "EG6j4wzyykSrHluANgIVTvyjzyu1",
18
+ "chatId": "LP8IKB0sRjARSO"
19
+ },
20
+ "paypal": {
21
+ "clientId": "AQSXMAqVuJYriyKEpaEc9xhS4hkm7iSlLjNRXSBdkM234figh599SMQbc0VMfYrm2Vh74J3u4jdeFYH9"
22
+ },
23
+ "chargebee": {
24
+ "siteKey": ""
25
+ }
26
+ },
27
+ "oauth2": {
28
+ "discord": {
29
+ "scope": ["identify", "guilds", "guilds.join"],
30
+ "enabled": true
31
+ },
32
+ "google": {
33
+ "enabled": false
34
+ }
35
+ },
36
+ "url": "https://studymonkey.ai",
37
+ "products": {
38
+ "studymonkey-homework-helper": {
39
+ "successURLText": "Start Studying!",
40
+ "name": "StudyMonkey Homework Helper",
41
+ "monthly": {
42
+ "stripeProductId": "prod_NTqQASoK03O5fP",
43
+ "price": 8,
44
+ "chargebeePlanId": "",
45
+ "paypalPlanId": "plan.id",
46
+ "stripePriceId": "price_1MisjzHGybgi7uQGw5MH7VZx"
47
+ },
48
+ "successURL": "https://studymonkey.ai/dashboard",
49
+ "planId": "homework-helper",
50
+ "spreadsheetId": "1d0elQATs7mpur6IwlyWy_7s2vWvUZYT0nfF2WtTiKjQ",
51
+ "type": "subscription",
52
+ "limits": {
53
+ "devices": 3,
54
+ "requests": 50
55
+ },
56
+ "trial": 14,
57
+ "annually": {
58
+ "stripeProductId": "prod_NTqYLkXCOhAwa5",
59
+ "price": 72,
60
+ "chargebeePlanId": "",
61
+ "paypalPlanId": "plan.id",
62
+ "stripePriceId": "price_1MisrnHGybgi7uQGn0XOVjRo"
63
+ }
64
+ }
65
+ },
66
+ "reviews": {
67
+ "sites": ["https://www.trustpilot.com/review/studymonkey.ai"]
68
+ },
69
+ "name": "StudyMonkey",
70
+ "id": "studymonkey",
71
+ "brand": {
72
+ "description": "StudyMonkey is an AI-powered tutor that helps you with your homework and studying."
73
+ },
74
+ "dashboard": true,
75
+ "email": "support@studymonkey.ai",
76
+ "sponsorships": {
77
+ "acceptable": ["education", "academic"],
78
+ "unacceptable": ["online homework services", "essay writing service", "online writing services"],
79
+ "prices": {
80
+ "guest-post": 40,
81
+ "link-insertion": 30
82
+ }
83
+ },
84
+ "authentication": {
85
+ "password": {
86
+ "enabled": true
87
+ },
88
+ "google.com": {
89
+ "enabled": true
90
+ }
91
+ }
92
+ }
@@ -0,0 +1,42 @@
1
+ // Flags for special conditions
2
+ flags: {
3
+ hasDispute: false,
4
+ hasRefund: false,
5
+ isDelinquent: false,
6
+ requiresAction: false,
7
+ autoRenewEnabled: true,
8
+ cancellationRequested: false,
9
+ },
10
+
11
+ // Dispute information (if applicable)
12
+ dispute: {
13
+ active: false,
14
+ createdAt: timestamp,
15
+ amount: 99.99,
16
+ reason: "fraudulent",
17
+ status: "warning_needs_response",
18
+ dueBy: timestamp,
19
+ evidence: {
20
+ submitted: false,
21
+ documents: []
22
+ }
23
+ },
24
+
25
+ // Refund information (if applicable)
26
+ refunds: [
27
+ {
28
+ id: "refund-xxx",
29
+ amount: 99.99,
30
+ reason: "customer_request",
31
+ createdAt: timestamp,
32
+ metadata: {}
33
+ }
34
+ ],
35
+
36
+ // Cancellation details (if cancelled)
37
+ cancellation: {
38
+ requestedAt: timestamp,
39
+ effectiveAt: timestamp, // When it actually ends
40
+ reason: "too_expensive",
41
+ feedback: "Price increased too much",
42
+ },
@@ -0,0 +1,165 @@
1
+ ⏺ I'll help you design a comprehensive storage architecture for your payment system. Let me create a detailed plan
2
+ using the TodoWrite tool to track our implementation.
3
+
4
+ ⏺ Update Todos
5
+ ⎿ ☐ Design Firestore collections structure for payment system
6
+ ☐ Implement active subscription checking before payment intent
7
+ ☐ Enhance trial eligibility to check both UID and IP address
8
+ ☐ Create abandoned cart tracking system
9
+ ☐ Design unified subscription object structure
10
+ ☐ Create webhook endpoints for Stripe, PayPal, Chargebee
11
+ ☐ Implement app notification system for subscription events
12
+
13
+ ⏺ Recommended Firestore Collections Structure
14
+
15
+ Based on your requirements, I recommend using multiple collections for better scalability and query efficiency:
16
+
17
+ 1. payment-intents (Abandoned Cart Tracking)
18
+
19
+ {
20
+ id: "CHK-xxx", // checkout session ID
21
+ app: "app-id",
22
+ productId: "product-id",
23
+ userId: "uid", // optional, may be guest
24
+ email: "email@example.com",
25
+ ipAddress: "192.168.1.1",
26
+ status: "pending" | "completed" | "abandoned",
27
+ createdAt: timestamp,
28
+ updatedAt: timestamp,
29
+ lastVisitedAt: timestamp,
30
+ abandonedEmailsSent: {
31
+ day1: false,
32
+ day3: false,
33
+ day7: false
34
+ },
35
+ cartData: {
36
+ total: 99.99,
37
+ frequency: "monthly",
38
+ discount: "CODE20"
39
+ }
40
+ }
41
+
42
+ 2. payment-trials (Trial Eligibility)
43
+
44
+ {
45
+ id: auto,
46
+ app: "app-id",
47
+ productId: "product-id",
48
+ uid: "user-id",
49
+ ipAddress: "192.168.1.1",
50
+ startedAt: timestamp,
51
+ endedAt: timestamp,
52
+ trialDays: 7
53
+ }
54
+
55
+ 3. payment-subscriptions (Unified Subscription Records)
56
+
57
+ {
58
+ id: "sub-xxx",
59
+ app: "app-id",
60
+ productId: "product-id",
61
+ userId: "uid",
62
+ email: "email@example.com",
63
+ processor: "stripe" | "paypal" | "chargebee",
64
+ processorSubscriptionId: "stripe_sub_xxx",
65
+ status: "active" | "cancelled" | "suspended" | "expired",
66
+ frequency: "monthly" | "annually",
67
+ amount: 99.99,
68
+ currency: "USD",
69
+ trialEnd: timestamp, // optional
70
+ currentPeriodStart: timestamp,
71
+ currentPeriodEnd: timestamp,
72
+ cancelledAt: timestamp, // optional
73
+ cancelReason: "string", // optional
74
+ createdAt: timestamp,
75
+ updatedAt: timestamp,
76
+ metadata: {
77
+ checkoutSessionId: "CHK-xxx",
78
+ webhookEvents: ["created", "updated", "cancelled"]
79
+ }
80
+ }
81
+
82
+ 4. payment-orders (One-time Payments)
83
+
84
+ {
85
+ id: "order-xxx",
86
+ app: "app-id",
87
+ productId: "product-id",
88
+ userId: "uid",
89
+ email: "email@example.com",
90
+ processor: "stripe" | "paypal" | "chargebee",
91
+ processorOrderId: "stripe_pi_xxx",
92
+ status: "pending" | "completed" | "failed" | "refunded",
93
+ amount: 299.99,
94
+ currency: "USD",
95
+ createdAt: timestamp,
96
+ completedAt: timestamp,
97
+ metadata: {
98
+ checkoutSessionId: "CHK-xxx"
99
+ }
100
+ }
101
+
102
+ Implementation Flow
103
+
104
+ 1. On Checkout Page Load (Client)
105
+
106
+ - Generate/retrieve checkout session ID
107
+ - Send cart data to /payment-v2/cart endpoint
108
+ - This creates/updates payment-intents document
109
+
110
+ 2. Before Creating Payment Intent (/payment-v2/intent)
111
+
112
+ Check these in parallel:
113
+ - Active subscription check: Query payment-subscriptions where userId == uid && productId == productId && status
114
+ == 'active'
115
+ - Trial eligibility: Query payment-trials where (uid == userId || ipAddress == ip) && productId == productId &&
116
+ app == appId
117
+ - ReCAPTCHA verification: Already implemented
118
+
119
+ 3. After Successful Payment Intent
120
+
121
+ - Update payment-intents with processor response data
122
+ - Store intent as "pending" until webhook confirmation
123
+
124
+ 4. Webhook Processing (/payment-v2/webhook/[processor])
125
+
126
+ - Verify webhook signature
127
+ - Map processor event to unified status
128
+ - Update/create payment-subscriptions or payment-orders
129
+ - Update payment-intents status to "completed"
130
+ - Send notification to app's webhook endpoint
131
+
132
+ 5. Abandoned Cart Cron Job
133
+
134
+ - Query payment-intents where status == 'pending'
135
+ - Check age and send appropriate emails
136
+ - Update abandonedEmailsSent flags
137
+
138
+ Endpoints Structure
139
+
140
+ /payment-v2/
141
+ ├── cart/ # Track abandoned carts
142
+ ├── intent/ # Create payment intent (existing)
143
+ ├── webhook/
144
+ │ ├── stripe/
145
+ │ ├── paypal/
146
+ │ └── chargebee/
147
+ ├── subscription/
148
+ │ └── check/ # Check active subscriptions
149
+ └── cron/
150
+ └── abandoned-carts/ # Daily cron for emails
151
+
152
+ Key Implementation Points
153
+
154
+ 1. IP Address Tracking: Add to schema and capture in /payment-v2/intent
155
+ 2. Composite Indexes: Create for efficient queries:
156
+ - payment-subscriptions: userId + productId + status
157
+ - payment-trials: uid + productId + app, ipAddress + productId + app
158
+ 3. Unified Status Mapping: Create processor-agnostic status values
159
+ 4. Webhook Security: Verify signatures for each processor
160
+ 5. App Notifications: Implement retry logic with exponential backoff
161
+
162
+ Would you like me to start implementing any of these components? I'd suggest starting with:
163
+ 1. Updating the intent endpoint to check active subscriptions
164
+ 2. Enhancing trial eligibility to include IP checking
165
+ 3. Creating the abandoned cart tracking endpoint
@@ -0,0 +1,44 @@
1
+
2
+ 1. Unified Endpoint Structure
3
+
4
+ All processors now use the same endpoint:
5
+ - Production: https://api.itwcreativeworks.com/payment/intent?processor={PROCESSOR}
6
+ - Development: http://localhost:5001/your-project-id/us-central1/api/payment/intent?processor={PROCESSOR}
7
+
8
+ The endpoint automatically switches based on webManager.isDevelopment().
9
+
10
+ 2. Standardized Request Body
11
+
12
+ All processors send the same request structure:
13
+ {
14
+ processor: 'stripe' | 'paypal' | 'chargebee',
15
+ recaptcha_token: 'token_from_google',
16
+ processor_data: { /* processor-specific data */ },
17
+ api_key: 'processor_api_key',
18
+ is_subscription: true/false // for PayPal
19
+ }
20
+
21
+ 3. Backend Architecture (Firebase Functions)
22
+
23
+ Your backend can now have a clean structure:
24
+ /functions
25
+ /payment
26
+ - intent.js // Main handler
27
+ /modules
28
+ - recaptcha.js // Shared reCAPTCHA verification
29
+ - stripe.js // Stripe-specific logic
30
+ - paypal.js // PayPal-specific logic
31
+ - chargebee.js // Chargebee-specific logic
32
+
33
+ The main handler can:
34
+ 1. Verify reCAPTCHA token (common for all)
35
+ 2. Extract processor from query param
36
+ 3. Validate request body
37
+ 4. Delegate to appropriate processor module
38
+ 5. Return standardized response: { url: "checkout_url" }
39
+
40
+ This architecture makes it easy to:
41
+ - Add new payment processors
42
+ - Share common logic (reCAPTCHA, logging, error handling)
43
+ - Test locally with Firebase emulator
44
+ - Maintain consistent API structure
@@ -0,0 +1,92 @@
1
+ /// SUBSCRIPTION
2
+
3
+ {
4
+ // Core identification
5
+ id: "sub-xxx", // Or "ORD-xxx" for orders
6
+ app: "app-id",
7
+ product: "product-id",
8
+ checkout: "chk-xxx", // Links back to payment-intents
9
+
10
+ // Auth
11
+ auth: {
12
+ uid: "user-uid",
13
+ email: "user@example.com"
14
+ },
15
+
16
+ // Processor information
17
+ processor: {
18
+ id: "stripe", // stripe, paypal, chargebee
19
+ lastWebhookEvent: "customer.subscription.updated" // Useful for debugging
20
+ },
21
+
22
+ // Type identifier
23
+ type: "subscription", // or "order" for one-time
24
+
25
+ // Status information
26
+ status: "active", // Same statuses work for orders too
27
+ access: true, // Computed based on current status and rules
28
+ frequency: "monthly", // null for one-time orders
29
+
30
+ // Customer information
31
+ customer: {
32
+ id: "cus-xxx", // Customer ID in the processor
33
+ name: "John Doe",
34
+ email: "john.doe@example.com"
35
+ },
36
+
37
+ // Billing information
38
+ billing: {
39
+ amount: 99.99,
40
+ lastPayment: {
41
+ amount: 99.99,
42
+ date: {
43
+ timestamp: "2023-10-01T12:00:00Z",
44
+ timestampUNIX: 1696156800
45
+ }
46
+ },
47
+ totalRevenue: 299.97, // Lifetime value
48
+ paymentCount: 3 // Number of successful payments
49
+ },
50
+
51
+ // Trial information (if applicable)
52
+ trial: {
53
+ active: true, // Is the trial currently active?
54
+ claimed: true, // Actually used the trial
55
+ days: 14,
56
+ started: {
57
+ timestamp: "2023-09-15T12:00:00Z",
58
+ timestampUNIX: 1694745600 // UNIX timestamp
59
+ }
60
+ },
61
+
62
+ // Supplemental information from the checkout form
63
+ supplemental: {
64
+ // Custom form fields
65
+ },
66
+
67
+ // Analytics and tracking
68
+ utm: {
69
+ source: "google",
70
+ medium: "cpc",
71
+ campaign: "summer_sale",
72
+ content: "ad_1",
73
+ term: "keyword"
74
+ },
75
+
76
+ // Original processor data (for debugging)
77
+ raw: {
78
+ // Complete webhook payload or API response
79
+ },
80
+
81
+ // Metadata and timestamps
82
+ meta: {
83
+ created: {
84
+ timestamp: "2023-10-01T12:00:00Z",
85
+ timestampUNIX: 1696156800
86
+ },
87
+ updated: {
88
+ timestamp: "2023-10-02T12:00:00Z",
89
+ timestampUNIX: 1696243200
90
+ },
91
+ },
92
+ }
@@ -0,0 +1,36 @@
1
+ ok so i need help planning the storage, trial eligibility, and webhooks. im not exactly sure WHAT to store and WHEN to store it. But heres what i know so far
2
+
3
+ * This system we are building is a centralized checkout system for multiple apps that offer multiple products
4
+ * This is why we store and keep track of the "app" and "product id" in the database and http calls.
5
+
6
+ * Prevent users who HAVE A SUBSCRIPTION from buying another one
7
+ * We will need to check our database to see if the user has an active subscription, as in one that is not cancelled.
8
+ * If the user has an active subscription, they should NOT be able to buy another one.
9
+
10
+ * We need to keep track of which users have had a trial already.
11
+ * There is TRIAL OFFERING and TRIAL ELIGIBILITY. TRIAL OFFERING means a product offers the possibility of a trial (stored in the app.products.[product-id].trial as either 0 or a number of days), and TRIAL ELIGIBILITY means the user is eligible for a trial, which is TRUE if the user has never used a trial for THAT PRODUCT in THAT APP .
12
+ * For this we need to store the "app", the "product.id", the "auth.uid", and the "geolocation.ip". In other words, for every product in a given app, we cant let a person use the trial more than once. So we should search for a product id of an app and if EITHER the UID or the IP address is found, then we should not allow the user to use the trial. A user can take a trial for a DIFFERNT product in the same app, or a different app entirely. Its only for the same product in the same app that we should not allow a trial more than once.
13
+ * This is because we dont want people to abuse the trial system.
14
+ * If the product DOES NOT OFFER A TRIAL, then we should not even check for a trial and assume they are not eligible for one.
15
+
16
+ * I want to implement a custom "abandoned cart" system
17
+ * The moment a user lands on the checkout page, we will store the cart somewhere in our database by sending an HTTP request to our server with the cart data.
18
+ * This way, we can loop through every day and if the user has not completed their checkout, we can send them an email reminding them to complete their purchase, one at 1 day, 3 days, and 7 days after they first landed on the checkout page. The link to go back will have their unique checkout ID in the URL.
19
+ * When they go to the checkout and send the request to our server, we will check if there is a cart with that ID, and if so, we will reset that cart's timer so we can send more abandoned cart emails if they still do not complete their purchase.
20
+ * Essentially, every time they visit checkout we will check if they have an abandoned cart, and if so, we will reset the timer for that cart.
21
+
22
+ * We need to set up webhook listener for stripe, paypal, etc
23
+ * Update the database with subscription events like when it becomes active, cancelled, etc.
24
+ * When we receive an event for say, subscription cancelled, we will need to find the record and update the status
25
+ * Without getting too ahead of ourselves, I would like to DESIGN A PROPRIETARY and UNIFIED object that we can use to store the subscription data and status. This way, no matter what payment provider we use, we can ensure the user has access to their paid features etc without having to consider all the different payment providers own data structures. In this sense, we will create a "resolved" subscription object that contains data regarding when the subscription started, whether it is active/cancelled/suspended (meaning unpaid), the payment provider, the product id, the app id, and any other relevant data we need to store. This way, we can use this object to check if a user has an active subscription or not, regardless of the payment provider.
26
+ * Also without getting too ahead of ourselves, we will need to send our own HTTP requests to the individual APP that is usinng our unified checkout system. So essentialy we will send a request with the subscription data AND THE RESOLVED SUBSCRIPTION OBJECT to the app that is using our checkout system. This way, the app can update its own database with the subscription data and status, and we can ensure that the user has access to their paid features in THAT SPECIFIC APP.
27
+
28
+ SO... ALL OF THE ABOVE CONSIDERED... Where should all of these checks happen and where should we store the data? By that I mean, which server functions do we perform these checks and what collections in firestore do we need?
29
+ * Do we store the entire lifecycle of an order in one collection? Or do we store parts of it in different collections?
30
+ * Storing in ONE COLLECTION
31
+ * we would store all the trial related data, the app, product, user, and geolocation data in one collection
32
+ * We would have a status field that indicates at what stage the order is in such as if its just a payment intent or if it was completed
33
+ * Storing in multiple collections
34
+ * We would only store what we need for the specific operation, like we could habe a "payment-trials" collection that keeps track of app, product, user, and IP address, and a "payment-orders" collection that keeps track of the order status, payment provider, etc. and then a "payment-subscriptions" collection that keeps track of the subscription status, start date, end date, etc.
35
+
36
+ SO... What is the best way to store this data and what endpoints should we set up?
@@ -0,0 +1,123 @@
1
+ Core Subscription Statuses
2
+
3
+ pending
4
+ - Initial state after checkout
5
+ - Access = false
6
+ - Waiting for first payment confirmation
7
+ - Becomes active or expired
8
+ - Requires additional user action (3D Secure, bank approval)
9
+
10
+ active
11
+ - Subscription is paid and current
12
+ - Access = true
13
+ - Payment method is valid
14
+ - Next billing date is in the future
15
+
16
+ trialing
17
+ - User is in free trial period
18
+ - Access = true
19
+ - No charges yet
20
+ - Will convert to active or cancelled when trial ends
21
+
22
+ paused
23
+ - Temporarily halted by user/admin
24
+ - Access = ?
25
+ - No charges during pause
26
+ - Can be resumed
27
+ - Access may be retained or revoked (configurable)
28
+ - ??? How do we determine access?
29
+
30
+ suspended
31
+ - One or more payments failed
32
+ - Access = false
33
+ - Access revoked
34
+ - Can be reactivated if payment succeeds
35
+ - Not permanently cancelled
36
+
37
+ cancelled
38
+ - User intentionally cancelled
39
+ - Access = true
40
+ - Will have access until period end
41
+ - No future charges
42
+ - Transitions to expired at period end
43
+
44
+ expired
45
+ - Subscription period ended after cancellation
46
+ - Access = false
47
+ - Cannot be reactivated (must create new subscription)
48
+ - Terminal state
49
+
50
+
51
+ Stripe → Unified
52
+
53
+ {
54
+ 'trialing': 'trialing',
55
+ 'active': 'active',
56
+ 'incomplete': 'incomplete',
57
+ 'incomplete_expired': 'expired',
58
+ 'past_due': 'past_due',
59
+ 'canceled': 'cancelled',
60
+ 'unpaid': 'suspended',
61
+ 'paused': 'paused'
62
+ }
63
+
64
+ PayPal → Unified
65
+
66
+ {
67
+ 'APPROVAL_PENDING': 'pending',
68
+ 'APPROVED': 'pending',
69
+ 'ACTIVE': 'active',
70
+ 'SUSPENDED': 'suspended',
71
+ 'CANCELLED': 'cancelled',
72
+ 'EXPIRED': 'expired'
73
+ }
74
+
75
+ Chargebee → Unified
76
+
77
+ {
78
+ 'future': 'pending',
79
+ 'in_trial': 'trialing',
80
+ 'active': 'active',
81
+ 'non_renewing': 'cancelled',
82
+ 'paused': 'paused',
83
+ 'cancelled': 'expired',
84
+ 'transferred': 'expired'
85
+ }
86
+
87
+ Status Transition Rules
88
+
89
+ const validTransitions = {
90
+ 'pending': ['active', 'trialing', 'incomplete', 'expired'],
91
+ 'trialing': ['active', 'cancelled', 'suspended'],
92
+ 'active': ['cancelled', 'suspended', 'paused'],
93
+ 'suspended': ['active', 'cancelled', 'expired'],
94
+ 'cancelled': ['expired'], // Can only expire after cancellation
95
+ 'paused': ['active', 'cancelled', 'expired'],
96
+ 'incomplete': ['active', 'expired'],
97
+ 'expired': [] // Terminal state
98
+ };
99
+
100
+
101
+ function computeAccess(subscription) {
102
+ switch (subscription.status) {
103
+ case 'active':
104
+ case 'trialing':
105
+ return true;
106
+
107
+ case 'cancelled':
108
+ // Has access until current period ends
109
+ return subscription.billing.currentPeriodEnd > Date.now();
110
+
111
+ case 'paused':
112
+ // Use stored decision from when pause was created
113
+ return subscription.pause?.accessRetained ?? false;
114
+
115
+ case 'pending':
116
+ case 'suspended':
117
+ case 'expired':
118
+ return false;
119
+
120
+ default:
121
+ return false;
122
+ }
123
+ }
@@ -0,0 +1,61 @@
1
+ Frontend TODO
2
+ - sentry in WM
3
+ - chatsy
4
+ - remake chatsy into a module that we can install here and then users can load it via cdnjs instead of our website
5
+ - contact form with tracking and form-manager and slapform
6
+
7
+ - save utm tags, send during checkout, signup, etc
8
+
9
+ - token redirect for auth system (for auth with desktop apps, etc)
10
+
11
+ ensure blog, article, posts, etc all use proper HTML semantics tags, aria, etc
12
+
13
+ js refactor
14
+ - make all fns await asyn operations
15
+ - order the fn definitions in the order they are called (most import/toplevel first then the rest. put all tracking fns at the bottom)
16
+ - move export to top and do not use init() fn, just call all fns inside dom.ready OR the main export (depends on the structure)
17
+ - track errors w sentry, not ga4/fb/tiktok
18
+ - add Manager, options back to each index.js for standardization
19
+ - for stanndardization, also ALWAYS set webManager = Manager.webManager in the index.js
20
+
21
+ pages
22
+ - blog + post
23
+ - about
24
+ - contact
25
+ - team + member
26
+ - extension and download
27
+
28
+ MAKE OUR CUSTOM THEME CLASSY!!
29
+
30
+ for pages like pricing, home, about etc
31
+ - put default frontmatter in the default pages so user can override
32
+
33
+ NEW PLAN NAME STANDARD
34
+ 1. Basic, Starter, Pro, Max
35
+ 1. Basic, Starter, Plus, Pro
36
+
37
+ Implement account resolver
38
+
39
+ https://docs.stripe.com/payments/link/express-checkout-element-link
40
+
41
+ // // Load page specific scripts
42
+ // if (url.includes('/pricing')) {
43
+ // dom.loadScript({src: 'https://cdn.itwcreativeworks.com/assets/general/js/pricing-page-handler/index.js'})
44
+ // } else if (url.includes('/download')) {
45
+ // dom.loadScript({src: 'https://cdn.itwcreativeworks.com/assets/general/js/download-page-handler/index.js'})
46
+ // } else if (url.includes('/browser-extension') || url.includes('/extension')) {
47
+ // dom.loadScript({src: 'https://cdn.itwcreativeworks.com/assets/general/js/browser-extension-page-handler/index.js'})
48
+ // } else if (window.location.pathname.endsWith('.html')) {
49
+ // // Redirect and remove .html
50
+ // window.location.pathname = window.location.pathname.replace('.html', '');
51
+ // }
52
+
53
+
54
+
55
+ // // Save user auth data
56
+ // Manager.auth().ready(function (user) {
57
+ // setupTracking(user);
58
+
59
+ // storage.set('user.auth.uid', user.uid);
60
+ // storage.set('user.auth.email', user.email);
61
+ // })
@@ -0,0 +1 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" height="800" width="1200" viewBox="-120.015 -200 1040.13 1200"><linearGradient y2="800" x2="400" y1="0" x1="400" gradientUnits="userSpaceOnUse" id="a"><stop offset="0" stop-color="#0ed4fc"/><stop offset="1" stop-color="#0c57ef"/></linearGradient><path d="M638.4 0H161.6C72.3 0 0 72.3 0 161.6v476.9C0 727.7 72.3 800 161.6 800h476.9c89.2 0 161.6-72.3 161.6-161.6V161.6C800 72.3 727.7 0 638.4 0z" fill="url(#a)"/><path d="M396.6 183.8l16.2-28c10-17.5 32.3-23.4 49.8-13.4 17.5 10 23.4 32.3 13.4 49.8L319.9 462.4h112.9c36.6 0 57.1 43 41.2 72.8H143c-20.2 0-36.4-16.2-36.4-36.4s16.2-36.4 36.4-36.4h92.8l118.8-205.9-37.1-64.4c-10-17.5-4.1-39.6 13.4-49.8 17.5-10 39.6-4.1 49.8 13.4zM256.2 572.7l-35 60.7c-10 17.5-32.3 23.4-49.8 13.4-17.5-10-23.4-32.3-13.4-49.8l26-45c29.4-9.1 53.3-2.1 72.2 20.7zm301.4-110.1h94.7c20.2 0 36.4 16.2 36.4 36.4s-16.2 36.4-36.4 36.4h-52.6l35.5 61.6c10 17.5 4.1 39.6-13.4 49.8-17.5 10-39.6 4.1-49.8-13.4-59.8-103.7-104.7-181.3-134.5-233-30.5-52.6-8.7-105.4 12.8-123.3 23.9 41 59.6 102.9 107.3 185.5z" fill="#fff"/></svg>