@hitch42/applet 0.1.0-beta.10

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 (193) hide show
  1. package/LICENSE +21 -0
  2. package/dist/_internal/client.d.ts +7 -0
  3. package/dist/_internal/client.js +169 -0
  4. package/dist/_internal/server.d.ts +92 -0
  5. package/dist/_internal/server.js +181 -0
  6. package/dist/applet.d.ts +1 -0
  7. package/dist/applet.js +184 -0
  8. package/dist/batch-Qa4B4-Yp.d.ts +30 -0
  9. package/dist/build-BlmLiKro.js +90 -0
  10. package/dist/build-CcT-wNN9.js +2 -0
  11. package/dist/ci-0Q2mUh53.js +68 -0
  12. package/dist/client.d.ts +48 -0
  13. package/dist/client.js +38 -0
  14. package/dist/contract-QUvEGiRI.d.ts +23 -0
  15. package/dist/deploy-BbL3GObV.js +2579 -0
  16. package/dist/email-DBTVhNB_.js +62 -0
  17. package/dist/generate-XB-72Fzj.js +537 -0
  18. package/dist/generate-wIN3IYqL.js +2 -0
  19. package/dist/index.d.ts +185 -0
  20. package/dist/index.js +251 -0
  21. package/dist/init-DwsXRUk-.js +244 -0
  22. package/dist/lazy-client-x0DCI98S.js +64 -0
  23. package/dist/load-config-OKZU3UKn.js +27 -0
  24. package/dist/login-BBO74hPC.js +12 -0
  25. package/dist/logs-XvK6Zs5Y.js +183 -0
  26. package/dist/manifest-4ZAc6HUk.js +191 -0
  27. package/dist/manifest-I-9s8R36.d.ts +88 -0
  28. package/dist/me-BW7Paary.js +32 -0
  29. package/dist/project-B0qNXnFu.js +536 -0
  30. package/dist/prompt-ChS-grYO.js +29 -0
  31. package/dist/query-cache-CXmAyLv3.js +82 -0
  32. package/dist/react.d.ts +37 -0
  33. package/dist/react.js +515 -0
  34. package/dist/schedules-BkWZsbSs.js +42 -0
  35. package/dist/server.d.ts +46 -0
  36. package/dist/server.js +104 -0
  37. package/dist/telephony-protocol-D-nf3Gca.d.ts +76 -0
  38. package/dist/telephony.d.ts +77 -0
  39. package/dist/telephony.js +607 -0
  40. package/dist/upload-DKZzz5kW.d.ts +112 -0
  41. package/dist/upload-DRbVhuDm.js +114 -0
  42. package/dist/variables-0tjnAeut.js +108 -0
  43. package/dist/vite.d.ts +63 -0
  44. package/dist/vite.js +816 -0
  45. package/dist/workflow-CTo2kZF1.js +51 -0
  46. package/dist/workflow-DurM6Fwx.d.ts +28 -0
  47. package/dist/workflow-engine-MogejNfF.js +117 -0
  48. package/dist/workspace-DruAZPmV.js +390 -0
  49. package/package.json +112 -0
  50. package/scaffold/.agents/skills/hitch-applets/SKILL.md +163 -0
  51. package/scaffold/.agents/skills/hitch-applets/references/client.md +73 -0
  52. package/scaffold/.agents/skills/hitch-applets/references/email-tracking.md +49 -0
  53. package/scaffold/.agents/skills/hitch-applets/references/files.md +109 -0
  54. package/scaffold/.agents/skills/hitch-applets/references/manifest.md +198 -0
  55. package/scaffold/.agents/skills/hitch-applets/references/markdown.md +37 -0
  56. package/scaffold/.agents/skills/hitch-applets/references/performance.md +74 -0
  57. package/scaffold/.agents/skills/hitch-applets/references/records.md +176 -0
  58. package/scaffold/.agents/skills/hitch-applets/references/schedules.md +91 -0
  59. package/scaffold/.agents/skills/hitch-applets/references/server.md +95 -0
  60. package/scaffold/.agents/skills/hitch-applets/references/workflows.md +81 -0
  61. package/scaffold/.agents/skills/hitch-cli/SKILL.md +129 -0
  62. package/scaffold/.agents/skills/hitch-data/SKILL.md +52 -0
  63. package/scaffold/.agents/skills/hitch-data/references/attributes.md +127 -0
  64. package/scaffold/.agents/skills/hitch-data/references/limits.md +64 -0
  65. package/scaffold/.agents/skills/hitch-theory/SKILL.md +151 -0
  66. package/scaffold/.agents/skills/react-best-practices/SKILL.md +127 -0
  67. package/scaffold/.agents/skills/react-best-practices/rules/advanced-effect-event-deps.md +50 -0
  68. package/scaffold/.agents/skills/react-best-practices/rules/advanced-event-handler-refs.md +55 -0
  69. package/scaffold/.agents/skills/react-best-practices/rules/advanced-init-once.md +42 -0
  70. package/scaffold/.agents/skills/react-best-practices/rules/advanced-use-latest.md +39 -0
  71. package/scaffold/.agents/skills/react-best-practices/rules/async-cheap-condition-before-await.md +37 -0
  72. package/scaffold/.agents/skills/react-best-practices/rules/async-defer-await.md +82 -0
  73. package/scaffold/.agents/skills/react-best-practices/rules/async-dependencies.md +48 -0
  74. package/scaffold/.agents/skills/react-best-practices/rules/async-parallel.md +24 -0
  75. package/scaffold/.agents/skills/react-best-practices/rules/bundle-analyzable-paths.md +42 -0
  76. package/scaffold/.agents/skills/react-best-practices/rules/bundle-barrel-imports.md +39 -0
  77. package/scaffold/.agents/skills/react-best-practices/rules/bundle-conditional.md +35 -0
  78. package/scaffold/.agents/skills/react-best-practices/rules/bundle-defer-third-party.md +46 -0
  79. package/scaffold/.agents/skills/react-best-practices/rules/bundle-dynamic-imports.md +38 -0
  80. package/scaffold/.agents/skills/react-best-practices/rules/bundle-preload.md +40 -0
  81. package/scaffold/.agents/skills/react-best-practices/rules/client-event-listeners.md +78 -0
  82. package/scaffold/.agents/skills/react-best-practices/rules/client-localstorage-schema.md +74 -0
  83. package/scaffold/.agents/skills/react-best-practices/rules/client-passive-event-listeners.md +48 -0
  84. package/scaffold/.agents/skills/react-best-practices/rules/js-batch-dom-css.md +110 -0
  85. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-function-results.md +58 -0
  86. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-property-access.md +28 -0
  87. package/scaffold/.agents/skills/react-best-practices/rules/js-cache-storage.md +56 -0
  88. package/scaffold/.agents/skills/react-best-practices/rules/js-combine-iterations.md +32 -0
  89. package/scaffold/.agents/skills/react-best-practices/rules/js-early-exit.md +50 -0
  90. package/scaffold/.agents/skills/react-best-practices/rules/js-flatmap-filter.md +51 -0
  91. package/scaffold/.agents/skills/react-best-practices/rules/js-hoist-regexp.md +45 -0
  92. package/scaffold/.agents/skills/react-best-practices/rules/js-index-maps.md +37 -0
  93. package/scaffold/.agents/skills/react-best-practices/rules/js-length-check-first.md +50 -0
  94. package/scaffold/.agents/skills/react-best-practices/rules/js-min-max-loop.md +82 -0
  95. package/scaffold/.agents/skills/react-best-practices/rules/js-request-idle-callback.md +104 -0
  96. package/scaffold/.agents/skills/react-best-practices/rules/js-set-map-lookups.md +24 -0
  97. package/scaffold/.agents/skills/react-best-practices/rules/js-tosorted-immutable.md +57 -0
  98. package/scaffold/.agents/skills/react-best-practices/rules/rendering-activity.md +26 -0
  99. package/scaffold/.agents/skills/react-best-practices/rules/rendering-animate-svg-wrapper.md +38 -0
  100. package/scaffold/.agents/skills/react-best-practices/rules/rendering-conditional-render.md +32 -0
  101. package/scaffold/.agents/skills/react-best-practices/rules/rendering-content-visibility.md +38 -0
  102. package/scaffold/.agents/skills/react-best-practices/rules/rendering-hoist-jsx.md +36 -0
  103. package/scaffold/.agents/skills/react-best-practices/rules/rendering-resource-hints.md +81 -0
  104. package/scaffold/.agents/skills/react-best-practices/rules/rendering-script-defer-async.md +36 -0
  105. package/scaffold/.agents/skills/react-best-practices/rules/rendering-svg-precision.md +28 -0
  106. package/scaffold/.agents/skills/react-best-practices/rules/rendering-usetransition-loading.md +43 -0
  107. package/scaffold/.agents/skills/react-best-practices/rules/rerender-defer-reads.md +39 -0
  108. package/scaffold/.agents/skills/react-best-practices/rules/rerender-dependencies.md +45 -0
  109. package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state-no-effect.md +40 -0
  110. package/scaffold/.agents/skills/react-best-practices/rules/rerender-derived-state.md +29 -0
  111. package/scaffold/.agents/skills/react-best-practices/rules/rerender-functional-setstate.md +77 -0
  112. package/scaffold/.agents/skills/react-best-practices/rules/rerender-lazy-state-init.md +56 -0
  113. package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo-with-default-value.md +36 -0
  114. package/scaffold/.agents/skills/react-best-practices/rules/rerender-memo.md +44 -0
  115. package/scaffold/.agents/skills/react-best-practices/rules/rerender-move-effect-to-event.md +45 -0
  116. package/scaffold/.agents/skills/react-best-practices/rules/rerender-no-inline-components.md +75 -0
  117. package/scaffold/.agents/skills/react-best-practices/rules/rerender-simple-expression-in-memo.md +35 -0
  118. package/scaffold/.agents/skills/react-best-practices/rules/rerender-split-combined-hooks.md +64 -0
  119. package/scaffold/.agents/skills/react-best-practices/rules/rerender-transitions.md +40 -0
  120. package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-deferred-value.md +59 -0
  121. package/scaffold/.agents/skills/react-best-practices/rules/rerender-use-ref-transient-values.md +73 -0
  122. package/scaffold/.agents/skills/tanstack-query/SKILL.md +136 -0
  123. package/scaffold/.agents/skills/tanstack-query/references/compositions/automatic-invalidation-after-mutations.md +124 -0
  124. package/scaffold/.agents/skills/tanstack-query/references/compositions/broadcast-realtime-and-multi-tab-synchronization.md +150 -0
  125. package/scaffold/.agents/skills/tanstack-query/references/compositions/compose-query-with-tanstack-router-and-start.md +248 -0
  126. package/scaffold/.agents/skills/tanstack-query/references/compositions/enforce-query-best-practices-with-eslint.md +167 -0
  127. package/scaffold/.agents/skills/tanstack-query/references/compositions/persist-offline-and-restore-caches.md +181 -0
  128. package/scaffold/.agents/skills/tanstack-query/references/compositions/query-data-and-forms.md +156 -0
  129. package/scaffold/.agents/skills/tanstack-query/references/core/build-query-abstractions.md +130 -0
  130. package/scaffold/.agents/skills/tanstack-query/references/core/cancel-queries-and-consume-abort-signals.md +176 -0
  131. package/scaffold/.agents/skills/tanstack-query/references/core/concurrent-optimistic-updates.md +135 -0
  132. package/scaffold/.agents/skills/tanstack-query/references/core/coordinate-query-execution.md +188 -0
  133. package/scaffold/.agents/skills/tanstack-query/references/core/design-query-keys-and-options.md +182 -0
  134. package/scaffold/.agents/skills/tanstack-query/references/core/fetch-and-observe-queries.md +193 -0
  135. package/scaffold/.agents/skills/tanstack-query/references/core/implement-optimistic-updates-and-cache-writes.md +168 -0
  136. package/scaffold/.agents/skills/tanstack-query/references/core/paginate-and-build-infinite-queries.md +188 -0
  137. package/scaffold/.agents/skills/tanstack-query/references/core/seed-placeholder-select-and-transform-data.md +188 -0
  138. package/scaffold/.agents/skills/tanstack-query/references/core/selectors-and-derived-state.md +145 -0
  139. package/scaffold/.agents/skills/tanstack-query/references/core/tune-defaults-freshness-retries-and-refetching.md +172 -0
  140. package/scaffold/.agents/skills/tanstack-query/references/core/understand-query-internals-and-observers.md +104 -0
  141. package/scaffold/.agents/skills/tanstack-query/references/core/write-mutations-and-invalidate-related-queries.md +183 -0
  142. package/scaffold/.agents/skills/tanstack-query/references/framework/debug-with-devtools.md +169 -0
  143. package/scaffold/.agents/skills/tanstack-query/references/framework/handle-status-and-errors.md +119 -0
  144. package/scaffold/.agents/skills/tanstack-query/references/framework/shape-data-and-render-efficiently.md +184 -0
  145. package/scaffold/.agents/skills/tanstack-query/references/framework/use-framework-adapter-reactivity.md +185 -0
  146. package/scaffold/.agents/skills/tanstack-query/references/framework/use-suspense-and-error-boundaries.md +208 -0
  147. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/migrate-major-versions-and-codemods.md +169 -0
  148. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/prefetch-and-remove-request-waterfalls.md +228 -0
  149. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/setup-query-client-and-providers.md +161 -0
  150. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/ssr-hydration-and-streaming.md +209 -0
  151. package/scaffold/.agents/skills/tanstack-query/references/lifecycle/test-query-code.md +160 -0
  152. package/scaffold/.agents/skills/tanstack-router/SKILL.md +134 -0
  153. package/scaffold/.agents/skills/tanstack-router/references/compositions/router-query.md +412 -0
  154. package/scaffold/.agents/skills/tanstack-router/references/react-router.md +495 -0
  155. package/scaffold/.agents/skills/tanstack-router/references/router-core/auth-and-guards.md +495 -0
  156. package/scaffold/.agents/skills/tanstack-router/references/router-core/code-splitting.md +318 -0
  157. package/scaffold/.agents/skills/tanstack-router/references/router-core/data-loading.md +490 -0
  158. package/scaffold/.agents/skills/tanstack-router/references/router-core/index.md +158 -0
  159. package/scaffold/.agents/skills/tanstack-router/references/router-core/navigation.md +433 -0
  160. package/scaffold/.agents/skills/tanstack-router/references/router-core/not-found-and-errors.md +436 -0
  161. package/scaffold/.agents/skills/tanstack-router/references/router-core/path-params.md +383 -0
  162. package/scaffold/.agents/skills/tanstack-router/references/router-core/search-params.md +343 -0
  163. package/scaffold/.agents/skills/tanstack-router/references/router-core/ssr.md +462 -0
  164. package/scaffold/.agents/skills/tanstack-router/references/router-core/type-safety.md +493 -0
  165. package/scaffold/.agents/skills/tanstack-router/references/router-plugin.md +250 -0
  166. package/scaffold/.agents/skills/tanstack-router/references/virtual-file-routes.md +215 -0
  167. package/scaffold/.agents/skills/web-design-guidelines/SKILL.md +184 -0
  168. package/scaffold/.github/workflows/hitch.yml +15 -0
  169. package/scaffold/AGENTS.md +38 -0
  170. package/scaffold/applet/components.json +25 -0
  171. package/scaffold/applet/src/client/components/ui/alert.tsx +73 -0
  172. package/scaffold/applet/src/client/components/ui/avatar.tsx +100 -0
  173. package/scaffold/applet/src/client/components/ui/badge.tsx +55 -0
  174. package/scaffold/applet/src/client/components/ui/button.tsx +90 -0
  175. package/scaffold/applet/src/client/components/ui/card.tsx +85 -0
  176. package/scaffold/applet/src/client/components/ui/checkbox.tsx +35 -0
  177. package/scaffold/applet/src/client/components/ui/dialog.tsx +164 -0
  178. package/scaffold/applet/src/client/components/ui/dropdown-menu.tsx +235 -0
  179. package/scaffold/applet/src/client/components/ui/input-group.tsx +144 -0
  180. package/scaffold/applet/src/client/components/ui/input.tsx +22 -0
  181. package/scaffold/applet/src/client/components/ui/label.tsx +29 -0
  182. package/scaffold/applet/src/client/components/ui/popover.tsx +74 -0
  183. package/scaffold/applet/src/client/components/ui/select.tsx +243 -0
  184. package/scaffold/applet/src/client/components/ui/separator.tsx +25 -0
  185. package/scaffold/applet/src/client/components/ui/sheet.tsx +177 -0
  186. package/scaffold/applet/src/client/components/ui/skeleton.tsx +13 -0
  187. package/scaffold/applet/src/client/components/ui/spinner.tsx +17 -0
  188. package/scaffold/applet/src/client/components/ui/switch.tsx +41 -0
  189. package/scaffold/applet/src/client/components/ui/table.tsx +114 -0
  190. package/scaffold/applet/src/client/components/ui/tabs.tsx +78 -0
  191. package/scaffold/applet/src/client/components/ui/textarea.tsx +23 -0
  192. package/scaffold/applet/src/client/lib/utils.ts +1 -0
  193. package/scaffold/applet/src/client/styles/globals.css +136 -0
package/package.json ADDED
@@ -0,0 +1,112 @@
1
+ {
2
+ "name": "@hitch42/applet",
3
+ "version": "0.1.0-beta.10",
4
+ "license": "MIT",
5
+ "bin": {
6
+ "applet": "./dist/applet.js"
7
+ },
8
+ "files": [
9
+ "dist",
10
+ "scaffold"
11
+ ],
12
+ "type": "module",
13
+ "exports": {
14
+ ".": {
15
+ "source": "./src/index.ts",
16
+ "default": "./dist/index.js"
17
+ },
18
+ "./server": {
19
+ "source": "./src/author/server.ts",
20
+ "default": "./dist/server.js"
21
+ },
22
+ "./client": {
23
+ "source": "./src/author/client.ts",
24
+ "default": "./dist/client.js"
25
+ },
26
+ "./react": {
27
+ "source": "./src/react/index.ts",
28
+ "default": "./dist/react.js"
29
+ },
30
+ "./telephony": {
31
+ "source": "./src/telephony/index.ts",
32
+ "default": "./dist/telephony.js"
33
+ },
34
+ "./vite": {
35
+ "source": "./src/vite.ts",
36
+ "default": "./dist/vite.js"
37
+ },
38
+ "./_internal/client": {
39
+ "source": "./src/internal/client.ts",
40
+ "default": "./dist/_internal/client.js"
41
+ },
42
+ "./_internal/server": {
43
+ "source": "./src/internal/server.ts",
44
+ "default": "./dist/_internal/server.js"
45
+ }
46
+ },
47
+ "dependencies": {
48
+ "@cloudflare/vite-plugin": "^1.51.1",
49
+ "@fontsource-variable/inter": "^5.3.0",
50
+ "@hey-api/openapi-ts": "0.0.0-next-20260824173136",
51
+ "@orpc/client": "^1.15.0",
52
+ "@orpc/contract": "^1.15.0",
53
+ "@orpc/openapi-client": "^1.15.0",
54
+ "@orpc/tanstack-query": "^1.15.0",
55
+ "@tailwindcss/vite": "^4.3.0",
56
+ "@tanstack/react-query-persist-client": "5.101.4",
57
+ "@tanstack/router-cli": "^1.167.24",
58
+ "@tanstack/router-plugin": "^1.168.23",
59
+ "@telnyx/webrtc": "^2.27.10",
60
+ "@tiptap/core": "^3.30.3",
61
+ "@tiptap/extension-image": "^3.30.3",
62
+ "@tiptap/extension-list": "^3.30.3",
63
+ "@tiptap/extension-table": "^3.30.3",
64
+ "@tiptap/extensions": "^3.30.3",
65
+ "@tiptap/markdown": "^3.30.3",
66
+ "@tiptap/react": "^3.30.3",
67
+ "@tiptap/starter-kit": "^3.30.3",
68
+ "@vitejs/plugin-react": "^6.0.3",
69
+ "class-variance-authority": "^0.7.1",
70
+ "cn": "^0.4.0",
71
+ "croner": "^10.0.1",
72
+ "lucide-react": "^1.33.0",
73
+ "oxc-transform-react": "^0.149.0",
74
+ "oxfmt": "^0.72.0",
75
+ "oxlint": "^1.87.0",
76
+ "oxlint-tsgolint": "^7.0.2003",
77
+ "react-aria-components": "^1.20.0",
78
+ "shadcn": "^4.16.1",
79
+ "smol-toml": "^1.9.0",
80
+ "streamdown": "^2.6.0",
81
+ "tailwindcss": "^4.3.0",
82
+ "tw-animate-css": "^1.4.0",
83
+ "vite": "8.3.0",
84
+ "vitest": "4.1.11",
85
+ "wrangler": "^4.120.0",
86
+ "zod": "^4.4.3"
87
+ },
88
+ "peerDependencies": {
89
+ "@orpc/server": "^1.15.0",
90
+ "@tanstack/react-query": "5.101.4",
91
+ "@tanstack/react-router": "^1.170.18",
92
+ "@types/node": "^24",
93
+ "@types/react": "^19.2.0",
94
+ "@types/react-dom": "^19.2.0",
95
+ "react": "^19.2.8",
96
+ "react-dom": "^19.2.8",
97
+ "typescript": "^7.0.2"
98
+ },
99
+ "engines": {
100
+ "node": ">=24"
101
+ },
102
+ "repository": {
103
+ "type": "git",
104
+ "url": "git+https://github.com/hitch-42/hitch.git",
105
+ "directory": "packages/applet"
106
+ },
107
+ "publishConfig": {
108
+ "access": "public",
109
+ "registry": "https://registry.npmjs.org",
110
+ "tag": "beta"
111
+ }
112
+ }
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: hitch-applets
3
+ description: Build, change, test, and debug Hitch applets. Use for applet routes, Hitch data access, applet servers, contract and theme generation, local development, deployment, and applet UI work.
4
+ ---
5
+
6
+ # Hitch Applets
7
+
8
+ Build small applets against an organization's Hitch data. Keep each applet focused on one related workflow.
9
+
10
+ Treat each applet as an isolated microfrontend. Keep it separate from the data storage layer, and access Hitch data through the SDK.
11
+
12
+ ## Go deeper
13
+
14
+ This file holds the common rules. Read each matching reference before you edit an applet. Paths are relative to this file.
15
+
16
+ | Read this | When the task involves |
17
+ | ------------------------------ | -------------------------------------------------------------------------------------------------------- |
18
+ | `references/client.md` | Client routes, navigation, page layout, forms, controls, or other user interface work |
19
+ | `references/records.md` | Listing, querying, creating, or updating records; filters, includes, aggregates; a missing record method |
20
+ | `references/files.md` | Uploading or reading files, attachment attributes, download links |
21
+ | `references/email-tracking.md` | Creating pixels and reading raw email hits |
22
+ | `references/markdown.md` | Rendering or editing markdown, image uploads, Hitch file links |
23
+ | `references/server.md` | The applet server: secrets, env variables, external services, the `api` client |
24
+ | `references/schedules.md` | Cron schedules and background runs |
25
+ | `references/workflows.md` | Multi-step server work: `createWorkflow`, `step.do`, `step.sleep`, starting, reading, and listing runs |
26
+ | `references/manifest.md` | The applet definition in `applet.manifest.ts`: objects, access, variables, and packages |
27
+ | `references/performance.md` | Data access design: client versus server, N+1 reads, includes, aggregates, pagination, batch writes |
28
+
29
+ For attribute types, filters, and API limits, read `../hitch-data/SKILL.md`. To inspect or change Hitch data and settings from the shell, read `../hitch-cli/SKILL.md`.
30
+
31
+ Read `../tanstack-router/SKILL.md` for route work and `../tanstack-query/SKILL.md` for query and cache work.
32
+ Read `../react-best-practices/SKILL.md` for React performance and `../web-design-guidelines/SKILL.md` for requested interface reviews.
33
+ Follow the Hitch applet rules for SDK-owned configuration, providers, and generated files.
34
+
35
+ ## Work with the workspace
36
+
37
+ - Run package commands with `pnpm`.
38
+ - Run `pnpm exec applet login` from the workspace root or an applet directory to sign in. It uses the organization in `hitch.config.ts` and shares credentials with `hitch login`. Add `--no-browser` to print the sign-in URL without opening a browser.
39
+ - A server permission error is not a login request.
40
+ - After a workspace is linked to a repository, deploy in two ways. Run `pnpm exec applet deploy` to release a change immediately. Push to the production branch to deploy through CI and keep releases in sync with the repository.
41
+ - Run `pnpm exec applet new <code>` from the workspace root to create a full applet.
42
+ - Add `--client-only` or `--server-only` when the applet needs only one part.
43
+ - Use `--client-only` for a user interface that uses the current user's Hitch access and needs no server.
44
+ - Use `--server-only` for an API or schedule that needs no user interface.
45
+ - The `new` command creates the applet before it installs packages and generates Hitch types.
46
+ - If installation or generation fails, inspect the created applet. Do not run `new` again.
47
+ - Run `pnpm install`, then rerun `pnpm exec applet generate` from the applet directory.
48
+ - If the user selects `--no-install`, do not run package scripts until applet dependencies are available.
49
+ - If generation cannot select a saved login, ask the user to fix the login or provide `HITCH_API_KEY`.
50
+ - Do not install or run a different Hitch CLI to repair applet generation.
51
+ - Run `pnpm --dir applets/<code> run generate` after a Hitch object, operation, or theme changes.
52
+ - Run generation at the start of a session when the task depends on current Hitch types.
53
+ - Run `pnpm --dir applets/<code> run dev` and `pnpm --dir applets/<code> run build` from the workspace root.
54
+ - The dev server runs as you in the production org. Reads and writes use real data.
55
+ - The dev server prints a preview link. Open the link to see the local applet inside Hitch.
56
+ - Chrome asks once to allow local network access for the Hitch site.
57
+ - The preview lasts until you select Exit or close the tab.
58
+ - A pending `requiresChangeset` schema is not available in dev. Deploy to test it.
59
+ - Run `pnpm --dir applets/<code> run deploy` only when the user requests a deployment.
60
+ - The CLI creates missing MCP files and adds missing Hitch and Chrome DevTools entries. Existing entries and other settings belong to the user.
61
+ - The applet CLI replaces its generated support files. It creates `.github/workflows/hitch.yml` only when the file is absent. To stop it, set `githubWorkflow: false` in `hitch.config.ts` and delete the file.
62
+ - Remember that generation refreshes the local theme copy. Deployed applets load the public org theme from its Hitch `.com` URL.
63
+
64
+ ## Use Vite and Vitest
65
+
66
+ - Import configuration APIs from `vite`.
67
+ - Import test APIs from `vitest`.
68
+ - Put tests in the applet's `test` folder and name them `*.test.ts` or `*.test.tsx`. Vitest does not run test files in other folders.
69
+ - Do not edit `vite.config.ts`. The applet CLI rewrites it. Do not add another Vite config.
70
+ - Add applet packages to `dependencies` or `devDependencies` in `applet.manifest.ts`.
71
+
72
+ ## Access Hitch data
73
+
74
+ Use the client SDK unless the task needs a secret or an external service:
75
+
76
+ ```ts
77
+ import { useQuery } from "@tanstack/react-query";
78
+ import { hitch } from "@hitch42/applet/client";
79
+
80
+ const deals = useQuery(
81
+ hitch.records.deals.list.queryOptions({
82
+ input: { query: {} },
83
+ }),
84
+ );
85
+ ```
86
+
87
+ The client SDK uses the current user's identity and access. Do not add a server proxy for filtering or access control.
88
+
89
+ Use the server SDK for secrets, external services, or imperative Hitch data access:
90
+
91
+ ```ts
92
+ import { env, hitch } from "@hitch42/applet/server";
93
+ ```
94
+
95
+ Define an applet server with an oRPC router:
96
+
97
+ ```ts
98
+ import { os } from "@orpc/server";
99
+
100
+ const router = {
101
+ hello: os.handler(() => ({ hello: "World!" })),
102
+ };
103
+
104
+ export default { router };
105
+ ```
106
+
107
+ Call applet server procedures through the generated client API:
108
+
109
+ ```ts
110
+ import { useQuery } from "@tanstack/react-query";
111
+ import { api } from "@hitch42/applet/client";
112
+
113
+ const greeting = useQuery(api.hello.queryOptions());
114
+ ```
115
+
116
+ Use generated types as the source of truth. Do not add casts or local copies that bypass them.
117
+
118
+ Do not invent fields or silence type errors with casts. Ask the user when generated types exclude a requested field or operation.
119
+
120
+ ## Work with files
121
+
122
+ Upload a file with one call. The SDK creates the file record and sends the bytes directly to storage:
123
+
124
+ ```ts
125
+ import { hitch } from "@hitch42/applet/client";
126
+
127
+ const uploaded = await hitch.files.upload(file); // file is a web File
128
+ ```
129
+
130
+ Read `references/files.md` before download links, attachment attributes, or server-side uploads.
131
+
132
+ ## Diagnose with logs
133
+
134
+ - Add useful `console.<level>` calls around important server work and failures. Deployed logs often provide the clearest evidence for applet issues.
135
+ - Choose `console.log`, `console.info`, `console.warn`, or `console.error` deliberately. The console method sets the entry level used by log filters.
136
+ - Run `pnpm --dir applets/<code> exec applet logs --filter '{"type":"applet"}'` from the workspace root to inspect applet code logs.
137
+ - Include the applet type filter during diagnosis. Without it, Cloudflare invocation entries can hide the useful applet entries. For a workflow run, use `--run <id>` or `--filter '{"type":"workflow"}'` instead.
138
+ - Do not log secrets, tokens, or personal data.
139
+
140
+ ## Verify changes
141
+
142
+ Run these commands from the workspace root before deployment:
143
+
144
+ ```sh
145
+ pnpm --dir applets/<code> run generate
146
+ pnpm --dir applets/<code> run typecheck
147
+ pnpm --dir applets/<code> run fmt
148
+ pnpm --dir applets/<code> run lint
149
+ pnpm --dir applets/<code> run test # Only when the applet contains tests.
150
+ pnpm --dir applets/<code> run build
151
+ ```
152
+
153
+ If missing packages block a check, stop package checks. Do not retry the check through another binary.
154
+
155
+ If a command fails, report the exact blocker. Do not deploy as a verification step.
156
+
157
+ ## Deploy from GitHub
158
+
159
+ - A push to the production branch runs `applet deploy` in the workspace root through GitHub Actions.
160
+ - An applet deploys when its own folder changed since its current CI release. Every applet deploys when a file outside `applets/` changed. An applet without a CI release always deploys. An applet also deploys when CI cannot load the commit of its current release.
161
+ - The deploy skips other applets and logs the reason. A skip is expected, not a failure.
162
+ - A schema change in Hitch alone does not trigger CI.
163
+ - Do not import from a sibling applet folder. The change check does not follow such imports.
@@ -0,0 +1,73 @@
1
+ # Client routes and interface
2
+
3
+ Read this file before you change client routes, navigation, page layout, forms, or controls.
4
+
5
+ ## Choose the client half
6
+
7
+ - Use a client-only applet for a user interface that uses the current user's Hitch access.
8
+ - Add a server only for secrets, external services, schedules, or imperative server work.
9
+ - Do not add a server proxy for normal Hitch data access.
10
+
11
+ ## Define routes
12
+
13
+ Hitch mounts each applet below `/<code>`. Include the applet code in every route path.
14
+
15
+ Use these file and path pairs:
16
+
17
+ | File | Route path |
18
+ | -------------------------------------- | ------------------- |
19
+ | `src/client/routes/index.tsx` | `/<code>/` |
20
+ | `src/client/routes/about.tsx` | `/<code>/about` |
21
+ | `src/client/routes/settings/index.tsx` | `/<code>/settings/` |
22
+
23
+ Define a page with `createFileRoute`:
24
+
25
+ ```tsx
26
+ import { createFileRoute } from "@tanstack/react-router";
27
+
28
+ export const Route = createFileRoute("/<code>/about")({
29
+ component: AboutPage,
30
+ });
31
+
32
+ function AboutPage() {
33
+ return <main>About</main>;
34
+ }
35
+ ```
36
+
37
+ - Keep the generated route path type as the source of truth.
38
+ - If TypeScript rejects a route, check its file name and `/<code>` prefix.
39
+ - Do not use a cast to bypass a route error.
40
+
41
+ ## Add navigation
42
+
43
+ Use TanStack Router's `Link` for a normal internal link:
44
+
45
+ ```tsx
46
+ import { Link } from "@tanstack/react-router";
47
+
48
+ <Link to="/<code>/about">About</Link>;
49
+ ```
50
+
51
+ Use the bundled `LinkButton` for a button-style link:
52
+
53
+ ```tsx
54
+ import { LinkButton } from "@/client/components/ui/button";
55
+
56
+ <LinkButton href="/<code>/about">About</LinkButton>;
57
+ ```
58
+
59
+ - Use a full path that starts with the applet code.
60
+ - Use `LinkButton` for button-style navigation. Use `Button` for an action.
61
+ - Do not add extra navigation that the user did not request.
62
+
63
+ ## Use the interface components
64
+
65
+ - Use components in `src/client/components/ui` before raw HTML controls.
66
+ - Inspect a component export before you use it.
67
+ - Browse the [shadcn component catalog](https://ui.shadcn.com/docs/components) before you create a control.
68
+ - Prefer a shadcn React Aria component when the catalog has a suitable component.
69
+ - Run `pnpm exec shadcn add <component>` from the applet directory to add a missing component.
70
+ - Keep installed components unchanged when possible.
71
+ - Copy a component outside the `ui` directory before a product-specific change.
72
+ - Use `cn` from `@/client/lib/utils` for class names.
73
+ - Keep global styles in `src/client/styles/globals.css`.
@@ -0,0 +1,49 @@
1
+ # Email tracking
2
+
3
+ Create one pixel for each email. Put its URL in the HTML before send.
4
+ Add the pixel next to CID images. A CID image cannot make a tracking request.
5
+
6
+ ```ts
7
+ const { id, url } = await hitch.email.tracking.createPixel({
8
+ tags: { campaignId: "fall", buyerId: "acme", version: "v2" },
9
+ });
10
+ const html = `<p>Hello</p><img src="${url}" width="1" height="1" alt="">`;
11
+ // Send the email with the applet's email provider.
12
+ await hitch.email.tracking.markSent({ id });
13
+ ```
14
+
15
+ `markSent({ id, sentAt })` accepts an ISO time. A later call replaces the sent time.
16
+ `get({ id })` returns one tracker. `list()` returns up to 100 trackers by default.
17
+ Use `filter`, `sentAt`, `cursor`, and `limit` to select a page.
18
+
19
+ ```ts
20
+ const tracker = await hitch.email.tracking.get({ id });
21
+ const query = {
22
+ filter: { buyerId: "acme" },
23
+ sentAt: { $gte: "2026-10-01T00:00:00Z" },
24
+ limit: 100,
25
+ };
26
+ const page = await hitch.email.tracking.list(query);
27
+ const next = page.nextCursor
28
+ ? await hitch.email.tracking.list({ ...query, cursor: page.nextCursor })
29
+ : null;
30
+ const opened =
31
+ tracker.lastHitAt !== null &&
32
+ new Date(tracker.lastHitAt).getTime() >
33
+ new Date(tracker.sentAt ?? tracker.createdAt).getTime() + 60_000;
34
+ ```
35
+
36
+ The example rule counts a tracker as opened when `lastHitAt` is more than 60 seconds after send or creation.
37
+ Hitch records `firstHitAt` and `lastHitAt`. It does not classify opens.
38
+ Each page must repeat the same filter, `sentAt`, and limit.
39
+
40
+ Tags stay fixed after creation. Use at most 10 tags. A key starts with an ASCII letter.
41
+ The rest contains ASCII letters, digits, or underscores, up to 64 characters total.
42
+ Each value has 1 to 200 characters. A filter matches every tag by exact equality.
43
+ Everyone with applet access sees all its trackers.
44
+
45
+ Gmail can fetch through `GoogleImageProxy` a few seconds after send.
46
+ A real Gmail open has the same user agent. A Gmail draft preview can fetch before send.
47
+ Apple Mail Privacy Protection fetches on delivery with `Mozilla/5.0`.
48
+ That fetch looks like a real open. Proton fetches on delivery.
49
+ Clients with images off never fetch the pixel.
@@ -0,0 +1,109 @@
1
+ # Files
2
+
3
+ Use the file API to upload bytes, read file metadata, and link files to records.
4
+
5
+ ## Upload a file
6
+
7
+ - Import `hitch` from the client or server SDK.
8
+ - Call `hitch.files.upload(file)` with a web `File`.
9
+ - Use the same upload call in the client and server halves.
10
+ - Receive the complete file row plus a `downloadUrl` when the call resolves: storage has the bytes.
11
+ - A failed upload throws an `Error` and leaves no usable id. Call `upload(file)` again to retry — the abandoned row is harmless.
12
+
13
+ ```ts
14
+ import { hitch } from "@hitch42/applet/client";
15
+
16
+ const uploaded = await hitch.files.upload(file);
17
+ ```
18
+
19
+ Show progress or allow cancellation with the options argument:
20
+
21
+ ```ts
22
+ const controller = new AbortController();
23
+
24
+ const uploaded = await hitch.files.upload(file, {
25
+ signal: controller.signal,
26
+ onProgress: ({ loaded, total }) => setPercent(Math.round((100 * loaded) / total)),
27
+ });
28
+ ```
29
+
30
+ - `onProgress` reports uploaded bytes in the browser. The server half uploads without progress.
31
+ - Abort the signal to cancel; the call rejects with an abort error.
32
+
33
+ Use a TanStack mutation in a React component:
34
+
35
+ ```ts
36
+ import { useMutation } from "@tanstack/react-query";
37
+ import { hitch } from "@hitch42/applet/client";
38
+
39
+ const upload = useMutation({
40
+ mutationFn: (file: File) => hitch.files.upload(file),
41
+ });
42
+
43
+ upload.mutate(file);
44
+ ```
45
+
46
+ Use the server SDK for an imperative upload:
47
+
48
+ ```ts
49
+ import { hitch } from "@hitch42/applet/server";
50
+
51
+ const uploaded = await hitch.files.upload(file);
52
+ ```
53
+
54
+ ## Set the content type
55
+
56
+ The browser sets `file.type` for picked files. On the server, set the type when you construct the `File`:
57
+
58
+ ```ts
59
+ const file = new File([csvBytes], "report.csv", { type: "text/csv" });
60
+ ```
61
+
62
+ An empty `file.type` uploads as `application/octet-stream`.
63
+
64
+ ## Read a file
65
+
66
+ Use `download` when a component needs one fresh link without query state:
67
+
68
+ ```ts
69
+ const file = await hitch.files.download(id);
70
+ file.downloadUrl; // a download link, valid for at least a day
71
+ ```
72
+
73
+ Use the `get` query utilities when React needs file metadata as query state.
74
+
75
+ `get` returns `{ data, downloadUrl }`. Every file you can fetch is complete: `upload` resolves only after storage confirms the bytes. A file whose upload never finished answers 404 with code `file_not_arrived` — treat that id as dead and upload again.
76
+
77
+ ```ts
78
+ const fileQuery = useQuery(
79
+ hitch.files.get.queryOptions({
80
+ input: { params: { id } },
81
+ }),
82
+ );
83
+
84
+ if (fileQuery.data) {
85
+ const { data: row, downloadUrl } = fileQuery.data;
86
+ row.filename; // "report.csv"
87
+ row.contentType; // "text/csv"
88
+ row.sizeBytes; // 1024
89
+ downloadUrl; // a download link, valid for at least a day
90
+ }
91
+ ```
92
+
93
+ A `downloadUrl` expires after 24 to 48 hours. Call `get` again for a fresh link instead of storing one.
94
+
95
+ ## Link a file to a record
96
+
97
+ Store `uploaded.id` as the value of an attachment attribute. A multi-value attachment attribute takes an array of ids.
98
+
99
+ ```ts
100
+ const uploaded = await hitch.files.upload(file);
101
+
102
+ await hitch.records.claims.update.call({
103
+ params: { id: claimId },
104
+ body: { receipt_id: uploaded.id }, // multi-value: [uploaded.id]
105
+ });
106
+ ```
107
+
108
+ - Upload the file before the record write: the write rejects a missing id ("file not found") and a pending id ("file has not arrived").
109
+ - Store the file id, never a URL — URLs expire.