@farm.js/create-app 0.1.0-beta.4 → 0.1.0-beta.41

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 (164) hide show
  1. package/README.md +41 -4
  2. package/bin/create-farm-app.js +8 -2
  3. package/dist/index.js +3244 -19
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +3239 -18
  6. package/dist/index.mjs.map +1 -1
  7. package/dist/utils.js +9 -6
  8. package/dist/utils.js.map +1 -1
  9. package/dist/utils.mjs +9 -6
  10. package/dist/utils.mjs.map +1 -1
  11. package/package.json +2 -2
  12. package/templates/_integrations/better-auth/preact/farm.config.ts +17 -0
  13. package/templates/_integrations/better-auth/preact/src/app/dashboard/page.tsx +73 -0
  14. package/templates/_integrations/better-auth/preact/src/app/layout.tsx +14 -0
  15. package/templates/_integrations/better-auth/preact/src/app/page.tsx +36 -0
  16. package/templates/_integrations/better-auth/preact/src/app/sign-in/page.tsx +10 -0
  17. package/templates/_integrations/better-auth/preact/src/app/sign-up/page.tsx +10 -0
  18. package/templates/_integrations/better-auth/preact/src/components/auth-form.tsx +92 -0
  19. package/templates/_integrations/better-auth/preact/src/components/auth-shell.tsx +16 -0
  20. package/templates/_integrations/better-auth/preact/src/lib/auth-client.ts +5 -0
  21. package/templates/_integrations/better-auth/solid/farm.config.ts +17 -0
  22. package/templates/_integrations/better-auth/solid/src/app/dashboard/page.tsx +67 -0
  23. package/templates/_integrations/better-auth/solid/src/app/layout.tsx +14 -0
  24. package/templates/_integrations/better-auth/solid/src/app/page.tsx +36 -0
  25. package/templates/_integrations/better-auth/solid/src/app/sign-in/page.tsx +10 -0
  26. package/templates/_integrations/better-auth/solid/src/app/sign-up/page.tsx +10 -0
  27. package/templates/_integrations/better-auth/solid/src/components/auth-form.tsx +91 -0
  28. package/templates/_integrations/better-auth/solid/src/components/auth-shell.tsx +16 -0
  29. package/templates/_integrations/better-auth/solid/src/lib/auth-client.ts +5 -0
  30. package/templates/_integrations/better-auth/svelte/farm.config.ts +17 -0
  31. package/templates/_integrations/better-auth/svelte/src/app/dashboard/page.svelte +62 -0
  32. package/templates/_integrations/better-auth/svelte/src/app/layout.svelte +20 -0
  33. package/templates/_integrations/better-auth/svelte/src/app/page.svelte +32 -0
  34. package/templates/_integrations/better-auth/svelte/src/app/sign-in/page.svelte +10 -0
  35. package/templates/_integrations/better-auth/svelte/src/app/sign-up/page.svelte +10 -0
  36. package/templates/_integrations/better-auth/svelte/src/components/auth-form.svelte +83 -0
  37. package/templates/_integrations/better-auth/svelte/src/components/auth-shell.svelte +16 -0
  38. package/templates/_integrations/better-auth/svelte/src/components/resource-links.svelte +47 -0
  39. package/templates/_integrations/better-auth/svelte/src/lib/auth-client.ts +5 -0
  40. package/templates/_integrations/better-auth/vue/farm.config.ts +17 -0
  41. package/templates/_integrations/better-auth/vue/src/app/dashboard/page.vue +62 -0
  42. package/templates/_integrations/better-auth/vue/src/app/layout.vue +20 -0
  43. package/templates/_integrations/better-auth/vue/src/app/page.vue +34 -0
  44. package/templates/_integrations/better-auth/vue/src/app/sign-in/page.vue +12 -0
  45. package/templates/_integrations/better-auth/vue/src/app/sign-up/page.vue +12 -0
  46. package/templates/_integrations/better-auth/vue/src/components/auth-form.vue +86 -0
  47. package/templates/_integrations/better-auth/vue/src/components/auth-shell.vue +15 -0
  48. package/templates/_integrations/better-auth/vue/src/components/resource-links.vue +43 -0
  49. package/templates/_integrations/better-auth/vue/src/lib/auth-client.ts +5 -0
  50. package/templates/_renderers/preact/farm.config.ts +12 -0
  51. package/templates/_renderers/preact/package.json +27 -0
  52. package/templates/_renderers/preact/src/app/api/greeting/route.ts +15 -0
  53. package/templates/_renderers/preact/src/app/layout.tsx +16 -0
  54. package/templates/_renderers/preact/src/app/page.tsx +66 -0
  55. package/templates/_renderers/preact/src/app/preact.css +26 -0
  56. package/templates/_renderers/preact/src/components/resource-links.tsx +71 -0
  57. package/templates/_renderers/preact/src/lib/api-client.ts +4 -0
  58. package/templates/_renderers/preact/src/lib/api.generated.ts +7 -0
  59. package/templates/_renderers/preact/tsconfig.json +25 -0
  60. package/templates/_renderers/solid/farm.config.ts +12 -0
  61. package/templates/_renderers/solid/package.json +26 -0
  62. package/templates/_renderers/solid/src/app/api/greeting/route.ts +15 -0
  63. package/templates/_renderers/solid/src/app/layout.tsx +15 -0
  64. package/templates/_renderers/solid/src/app/page.tsx +56 -0
  65. package/templates/_renderers/solid/src/app/solid.css +22 -0
  66. package/templates/_renderers/solid/src/components/resource-links.tsx +71 -0
  67. package/templates/_renderers/solid/src/lib/api-client.ts +4 -0
  68. package/templates/_renderers/solid/src/lib/api.generated.ts +7 -0
  69. package/templates/_renderers/solid/tsconfig.json +25 -0
  70. package/templates/_renderers/svelte/farm.config.ts +9 -0
  71. package/templates/_renderers/svelte/package.json +28 -0
  72. package/templates/_renderers/svelte/src/app/api/greeting/route.ts +15 -0
  73. package/templates/_renderers/svelte/src/app/layout.svelte +21 -0
  74. package/templates/_renderers/svelte/src/app/page.svelte +64 -0
  75. package/templates/_renderers/svelte/src/app/svelte.css +26 -0
  76. package/templates/_renderers/svelte/src/components/resource-links.svelte +31 -0
  77. package/templates/_renderers/svelte/src/lib/api-client.ts +4 -0
  78. package/templates/_renderers/svelte/src/lib/api.generated.ts +7 -0
  79. package/templates/_renderers/svelte/tsconfig.json +23 -0
  80. package/templates/_renderers/vue/farm.config.ts +12 -0
  81. package/templates/_renderers/vue/package.json +27 -0
  82. package/templates/_renderers/vue/src/app/api/greeting/route.ts +15 -0
  83. package/templates/_renderers/vue/src/app/layout.vue +21 -0
  84. package/templates/_renderers/vue/src/app/page.vue +69 -0
  85. package/templates/_renderers/vue/src/app/vue.css +26 -0
  86. package/templates/_renderers/vue/src/components/resource-links.vue +33 -0
  87. package/templates/_renderers/vue/src/env.d.ts +7 -0
  88. package/templates/_renderers/vue/src/lib/api-client.ts +4 -0
  89. package/templates/_renderers/vue/src/lib/api.generated.ts +7 -0
  90. package/templates/_renderers/vue/tsconfig.json +23 -0
  91. package/templates/auth/.env.example +6 -0
  92. package/templates/auth/README.md +95 -0
  93. package/templates/auth/farm.config.ts +14 -0
  94. package/templates/auth/gitignore +10 -0
  95. package/templates/auth/package.json +32 -0
  96. package/templates/auth/pnpm-workspace.yaml +13 -0
  97. package/templates/auth/src/app/dashboard/middleware.ts +13 -0
  98. package/templates/auth/src/app/dashboard/page.tsx +140 -0
  99. package/templates/auth/src/app/error.tsx +25 -0
  100. package/templates/auth/src/app/globals.css +1064 -0
  101. package/templates/auth/src/app/layout.tsx +11 -0
  102. package/templates/auth/src/app/loading.tsx +15 -0
  103. package/templates/auth/src/app/not-found.tsx +26 -0
  104. package/templates/auth/src/app/page.tsx +46 -0
  105. package/templates/auth/src/app/sign-in/page.tsx +16 -0
  106. package/templates/auth/src/app/sign-up/page.tsx +16 -0
  107. package/templates/auth/src/components/auth-form.tsx +120 -0
  108. package/templates/auth/src/components/auth-shell.tsx +21 -0
  109. package/templates/auth/src/components/resource-links.tsx +78 -0
  110. package/templates/auth/src/components/sign-out-button.tsx +45 -0
  111. package/templates/auth/src/components/site-header.tsx +46 -0
  112. package/templates/auth/tsconfig.json +20 -0
  113. package/templates/basic/farm.config.ts +3 -0
  114. package/templates/basic/gitignore +23 -0
  115. package/templates/basic/package.json +4 -2
  116. package/templates/basic/pnpm-workspace.yaml +8 -0
  117. package/templates/basic/public/favicon.svg +13 -0
  118. package/templates/basic/src/app/globals.css +241 -0
  119. package/templates/basic/src/app/layout.tsx +6 -5
  120. package/templates/basic/src/app/page.tsx +20 -61
  121. package/templates/basic/src/components/resource-links.tsx +78 -0
  122. package/templates/basic/tsconfig.json +4 -0
  123. package/templates/better-auth/.env.example +3 -0
  124. package/templates/better-auth/README.md +89 -0
  125. package/templates/better-auth/farm.config.ts +32 -0
  126. package/templates/better-auth/gitignore +10 -0
  127. package/templates/better-auth/package.json +34 -0
  128. package/templates/better-auth/pnpm-workspace.yaml +13 -0
  129. package/templates/better-auth/src/app/dashboard/middleware.ts +15 -0
  130. package/templates/better-auth/src/app/dashboard/page.tsx +188 -0
  131. package/templates/better-auth/src/app/error.tsx +25 -0
  132. package/templates/better-auth/src/app/globals.css +1064 -0
  133. package/templates/better-auth/src/app/layout.tsx +11 -0
  134. package/templates/better-auth/src/app/loading.tsx +15 -0
  135. package/templates/better-auth/src/app/not-found.tsx +26 -0
  136. package/templates/better-auth/src/app/page.tsx +50 -0
  137. package/templates/better-auth/src/app/sign-in/page.tsx +16 -0
  138. package/templates/better-auth/src/app/sign-up/page.tsx +16 -0
  139. package/templates/better-auth/src/components/auth-form.tsx +120 -0
  140. package/templates/better-auth/src/components/auth-shell.tsx +21 -0
  141. package/templates/better-auth/src/components/resource-links.tsx +78 -0
  142. package/templates/better-auth/src/components/sign-out-button.tsx +45 -0
  143. package/templates/better-auth/src/components/site-header.tsx +46 -0
  144. package/templates/better-auth/src/lib/auth-client.ts +5 -0
  145. package/templates/better-auth/src/lib/auth.ts +50 -0
  146. package/templates/better-auth/src/lib/session.ts +8 -0
  147. package/templates/better-auth/tsconfig.json +20 -0
  148. package/templates/react-compiler/README.md +62 -0
  149. package/templates/react-compiler/farm.config.ts +23 -0
  150. package/templates/react-compiler/gitignore +23 -0
  151. package/templates/react-compiler/package.json +31 -0
  152. package/templates/react-compiler/pnpm-workspace.yaml +8 -0
  153. package/templates/react-compiler/public/favicon.svg +5 -0
  154. package/templates/react-compiler/scripts/verify-experiment.mjs +113 -0
  155. package/templates/react-compiler/src/app/globals.css +470 -0
  156. package/templates/react-compiler/src/app/layout.tsx +22 -0
  157. package/templates/react-compiler/src/app/page.tsx +47 -0
  158. package/templates/react-compiler/src/components/compiler-comparison.tsx +93 -0
  159. package/templates/react-compiler/src/components/resource-links.tsx +78 -0
  160. package/templates/react-compiler/src/farm.d.ts +73 -0
  161. package/templates/react-compiler/src/lib/api.generated.ts +10 -0
  162. package/templates/react-compiler/tsconfig.json +24 -0
  163. package/templates/basic/src/app/about/page.tsx +0 -32
  164. package/templates/basic/src/farm-images.d.ts +0 -59
@@ -0,0 +1,66 @@
1
+ "use client";
2
+
3
+ import { useState } from "preact/hooks";
4
+ import { ResourceLinks } from "../components/resource-links";
5
+ import { api } from "../lib/api-client";
6
+
7
+ export default function HomePage() {
8
+ const [message, setMessage] = useState("Call a typed server function");
9
+ const [pending, setPending] = useState(false);
10
+ const [failed, setFailed] = useState(false);
11
+
12
+ const callServer = async () => {
13
+ setPending(true);
14
+ setFailed(false);
15
+ try {
16
+ const result = await api.greeting.post({
17
+ body: { name: "Preact" },
18
+ });
19
+ if (result.error) throw result.error;
20
+ if (!result.data) throw new Error("The server returned no greeting");
21
+ setMessage(result.data.message);
22
+ } catch {
23
+ setFailed(true);
24
+ setMessage("Try the server call again");
25
+ } finally {
26
+ setPending(false);
27
+ }
28
+ };
29
+
30
+ return (
31
+ <main className="landing-main">
32
+ <section className="hero-section">
33
+ <div className="hero-copy">
34
+ <div className="eyebrow-row">
35
+ <span>00</span>
36
+ <span>FARMJS / Preact starter</span>
37
+ </div>
38
+
39
+ <h1>
40
+ Edit <code>page.tsx</code> to begin.
41
+ </h1>
42
+
43
+ <div className="command-list" aria-label="Getting started">
44
+ <div className="command-row">
45
+ <span>01</span>
46
+ <code>pnpm dev</code>
47
+ </div>
48
+ <div className="command-row">
49
+ <span>02</span>
50
+ <button
51
+ type="button"
52
+ className={`server-call${failed ? " server-call-error" : ""}`}
53
+ onClick={callServer}
54
+ disabled={pending}
55
+ >
56
+ {pending ? "Calling…" : message}
57
+ </button>
58
+ </div>
59
+ </div>
60
+
61
+ <ResourceLinks className="resource-links" />
62
+ </div>
63
+ </section>
64
+ </main>
65
+ );
66
+ }
@@ -0,0 +1,26 @@
1
+ .server-call {
2
+ appearance: none;
3
+ width: fit-content;
4
+ border: 0;
5
+ padding: 0;
6
+ color: var(--ink);
7
+ background: transparent;
8
+ cursor: pointer;
9
+ font-family: var(--font-mono);
10
+ font-size: 0.75rem;
11
+ text-align: left;
12
+ }
13
+
14
+ .server-call:hover:not(:disabled) {
15
+ text-decoration: underline;
16
+ text-underline-offset: 0.25rem;
17
+ }
18
+
19
+ .server-call:disabled {
20
+ color: var(--ink-soft);
21
+ cursor: wait;
22
+ }
23
+
24
+ .server-call-error {
25
+ color: #fca5a5;
26
+ }
@@ -0,0 +1,71 @@
1
+ interface ResourceLinkAction {
2
+ href: string;
3
+ label: string;
4
+ }
5
+
6
+ interface ResourceLinksProps {
7
+ className: string;
8
+ primary?: ResourceLinkAction;
9
+ }
10
+
11
+ function DocsIcon() {
12
+ return (
13
+ <svg
14
+ className="resource-icon"
15
+ viewBox="0 0 24 24"
16
+ fill="none"
17
+ stroke="currentColor"
18
+ strokeWidth="1.8"
19
+ strokeLinecap="round"
20
+ strokeLinejoin="round"
21
+ aria-hidden="true"
22
+ >
23
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" />
24
+ <path d="M14 2v6h6M8 13h8M8 17h6" />
25
+ </svg>
26
+ );
27
+ }
28
+
29
+ function GitHubIcon() {
30
+ return (
31
+ <svg className="resource-icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
32
+ <path d="M12 .7a11.5 11.5 0 0 0-3.64 22.41c.58.1.79-.25.79-.56v-2.23c-3.22.7-3.9-1.37-3.9-1.37-.52-1.34-1.28-1.69-1.28-1.69-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.57-.29-5.27-1.29-5.27-5.68 0-1.26.45-2.28 1.18-3.09-.12-.29-.51-1.47.11-3.05 0 0 .96-.31 3.16 1.18A10.95 10.95 0 0 1 12 6.1c.98 0 1.95.13 2.87.39 2.2-1.49 3.16-1.18 3.16-1.18.62 1.58.23 2.76.11 3.05.74.81 1.18 1.83 1.18 3.09 0 4.4-2.71 5.38-5.29 5.67.42.36.79 1.07.79 2.16v3.27c0 .31.21.67.8.56A11.5 11.5 0 0 0 12 .7Z" />
33
+ </svg>
34
+ );
35
+ }
36
+
37
+ function ResourceSeparator() {
38
+ return (
39
+ <span className="resource-separator" aria-hidden="true">
40
+ /
41
+ </span>
42
+ );
43
+ }
44
+
45
+ export function ResourceLinks({ className, primary }: ResourceLinksProps) {
46
+ return (
47
+ <nav className={className} aria-label="Starter resources">
48
+ {primary ? (
49
+ <span className="resource-link-item">
50
+ <a className="resource-link-primary" href={primary.href}>
51
+ {primary.label}
52
+ </a>
53
+ </span>
54
+ ) : null}
55
+ <span className="resource-link-item">
56
+ {primary ? <ResourceSeparator /> : null}
57
+ <a href="https://farm.js.dev">
58
+ <DocsIcon />
59
+ <span>Docs</span>
60
+ </a>
61
+ </span>
62
+ <span className="resource-link-item">
63
+ <ResourceSeparator />
64
+ <a href="https://github.com/farming-labs/farm.js">
65
+ <GitHubIcon />
66
+ <span>GitHub</span>
67
+ </a>
68
+ </span>
69
+ </nav>
70
+ );
71
+ }
@@ -0,0 +1,4 @@
1
+ import { createAPIClient } from "@farm.js/core/client";
2
+ import type { APIRouter } from "./api.generated";
3
+
4
+ export const api = createAPIClient<APIRouter>();
@@ -0,0 +1,7 @@
1
+ import type { POST as POST_greeting } from "../app/api/greeting/route";
2
+
3
+ export type APIRouter = {
4
+ greeting: {
5
+ post: typeof POST_greeting;
6
+ };
7
+ };
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "baseUrl": ".",
10
+ "paths": {
11
+ "@/*": ["./src/*"]
12
+ },
13
+ "allowImportingTsExtensions": true,
14
+ "resolveJsonModule": true,
15
+ "isolatedModules": true,
16
+ "noEmit": true,
17
+ "jsx": "react-jsx",
18
+ "jsxImportSource": "preact",
19
+ "strict": true,
20
+ "noUnusedLocals": true,
21
+ "noUnusedParameters": true,
22
+ "noFallthroughCasesInSwitch": true
23
+ },
24
+ "include": ["src", "farm.config.ts"]
25
+ }
@@ -0,0 +1,12 @@
1
+ import { defineConfig } from "@farm.js/core/config";
2
+ import { solid } from "@farm.js/solid";
3
+
4
+ export default defineConfig({
5
+ renderer: solid(),
6
+ theme: {
7
+ default: "dark",
8
+ },
9
+ deploy: {
10
+ target: "vercel",
11
+ },
12
+ });
@@ -0,0 +1,26 @@
1
+ {
2
+ "name": "farm-app",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "scripts": {
6
+ "dev": "farm dev",
7
+ "build": "farm build",
8
+ "deploy": "farm deploy",
9
+ "start": "farm start",
10
+ "type-check": "tsc --noEmit"
11
+ },
12
+ "dependencies": {
13
+ "@farm.js/core": "0.1.0-beta.41",
14
+ "@farm.js/solid": "0.1.0-beta.26",
15
+ "@fontsource-variable/geist": "5.3.0",
16
+ "@fontsource-variable/geist-mono": "5.3.0",
17
+ "solid-js": "1.9.14",
18
+ "zod": "4.1.12"
19
+ },
20
+ "devDependencies": {
21
+ "@farm.js/cli": "0.1.0-beta.41",
22
+ "tailwindcss": "^4.0.0",
23
+ "typescript": "^5.3.3"
24
+ },
25
+ "packageManager": "pnpm@8.12.1"
26
+ }
@@ -0,0 +1,15 @@
1
+ import { createEndpoint } from "@farm.js/core/api";
2
+ import { z } from "zod";
3
+
4
+ export const POST = createEndpoint(
5
+ "/api/greeting",
6
+ {
7
+ method: "POST",
8
+ body: z.object({
9
+ name: z.string().trim().min(1).max(40),
10
+ }),
11
+ },
12
+ async ({ body }) => ({
13
+ message: `Hello, ${body.name}, from the FARMJS server.`,
14
+ }),
15
+ );
@@ -0,0 +1,15 @@
1
+ import type { LayoutProps, Metadata } from "@farm.js/core";
2
+ import "./globals.css";
3
+ import "./solid.css";
4
+
5
+ export const metadata: Metadata = {
6
+ title: "FARMJS Solid App",
7
+ description: "A framework for product-integrated apps",
8
+ icons: {
9
+ icon: [{ url: "/favicon.svg", type: "image/svg+xml", sizes: "any" }],
10
+ },
11
+ };
12
+
13
+ export default function RootLayout(props: LayoutProps) {
14
+ return <>{props.children}</>;
15
+ }
@@ -0,0 +1,56 @@
1
+ "use client";
2
+
3
+ import { createSignal } from "solid-js";
4
+ import { ResourceLinks } from "../components/resource-links";
5
+ import { api } from "../lib/api-client";
6
+
7
+ export default function HomePage() {
8
+ const [message, setMessage] = createSignal("Call a typed server function");
9
+ const [pending, setPending] = createSignal(false);
10
+
11
+ const callServer = async () => {
12
+ setPending(true);
13
+ try {
14
+ const result = await api.greeting.post({
15
+ body: { name: "Solid" },
16
+ });
17
+ if (result.error) throw result.error;
18
+ if (!result.data) throw new Error("The server returned no greeting");
19
+ setMessage(result.data.message);
20
+ } finally {
21
+ setPending(false);
22
+ }
23
+ };
24
+
25
+ return (
26
+ <main class="landing-main">
27
+ <section class="hero-section">
28
+ <div class="hero-copy">
29
+ <div class="eyebrow-row">
30
+ <span>00</span>
31
+ <span>FARMJS / Solid starter</span>
32
+ </div>
33
+
34
+ <h1>
35
+ Edit <code>page.tsx</code> to begin.
36
+ </h1>
37
+
38
+ <div class="command-list" aria-label="Getting started">
39
+ <div class="command-row">
40
+ <span>01</span>
41
+ <code>pnpm dev</code>
42
+ </div>
43
+ <div class="command-row">
44
+ <span>02</span>
45
+ <button type="button" class="server-call" onClick={callServer} disabled={pending()}>
46
+ {pending() ? "Calling…" : message()}
47
+ </button>
48
+ </div>
49
+ </div>
50
+
51
+ <ResourceLinks className="resource-links" />
52
+ </div>
53
+ </section>
54
+ </main>
55
+ );
56
+ }
@@ -0,0 +1,22 @@
1
+ .server-call {
2
+ appearance: none;
3
+ width: fit-content;
4
+ border: 0;
5
+ padding: 0;
6
+ color: var(--ink);
7
+ background: transparent;
8
+ cursor: pointer;
9
+ font-family: var(--font-mono);
10
+ font-size: 0.75rem;
11
+ text-align: left;
12
+ }
13
+
14
+ .server-call:hover:not(:disabled) {
15
+ text-decoration: underline;
16
+ text-underline-offset: 0.25rem;
17
+ }
18
+
19
+ .server-call:disabled {
20
+ color: var(--ink-soft);
21
+ cursor: wait;
22
+ }
@@ -0,0 +1,71 @@
1
+ interface ResourceLinkAction {
2
+ href: string;
3
+ label: string;
4
+ }
5
+
6
+ interface ResourceLinksProps {
7
+ className: string;
8
+ primary?: ResourceLinkAction;
9
+ }
10
+
11
+ function DocsIcon() {
12
+ return (
13
+ <svg
14
+ class="resource-icon"
15
+ viewBox="0 0 24 24"
16
+ fill="none"
17
+ stroke="currentColor"
18
+ stroke-width="1.8"
19
+ stroke-linecap="round"
20
+ stroke-linejoin="round"
21
+ aria-hidden="true"
22
+ >
23
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" />
24
+ <path d="M14 2v6h6M8 13h8M8 17h6" />
25
+ </svg>
26
+ );
27
+ }
28
+
29
+ function GitHubIcon() {
30
+ return (
31
+ <svg class="resource-icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
32
+ <path d="M12 .7a11.5 11.5 0 0 0-3.64 22.41c.58.1.79-.25.79-.56v-2.23c-3.22.7-3.9-1.37-3.9-1.37-.52-1.34-1.28-1.69-1.28-1.69-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.57-.29-5.27-1.29-5.27-5.68 0-1.26.45-2.28 1.18-3.09-.12-.29-.51-1.47.11-3.05 0 0 .96-.31 3.16 1.18A10.95 10.95 0 0 1 12 6.1c.98 0 1.95.13 2.87.39 2.2-1.49 3.16-1.18 3.16-1.18.62 1.58.23 2.76.11 3.05.74.81 1.18 1.83 1.18 3.09 0 4.4-2.71 5.38-5.29 5.67.42.36.79 1.07.79 2.16v3.27c0 .31.21.67.8.56A11.5 11.5 0 0 0 12 .7Z" />
33
+ </svg>
34
+ );
35
+ }
36
+
37
+ function ResourceSeparator() {
38
+ return (
39
+ <span class="resource-separator" aria-hidden="true">
40
+ /
41
+ </span>
42
+ );
43
+ }
44
+
45
+ export function ResourceLinks(props: ResourceLinksProps) {
46
+ return (
47
+ <nav class={props.className} aria-label="Starter resources">
48
+ {props.primary ? (
49
+ <span class="resource-link-item">
50
+ <a class="resource-link-primary" href={props.primary.href}>
51
+ {props.primary.label}
52
+ </a>
53
+ </span>
54
+ ) : null}
55
+ <span class="resource-link-item">
56
+ {props.primary ? <ResourceSeparator /> : null}
57
+ <a href="https://farm.js.dev">
58
+ <DocsIcon />
59
+ <span>Docs</span>
60
+ </a>
61
+ </span>
62
+ <span class="resource-link-item">
63
+ <ResourceSeparator />
64
+ <a href="https://github.com/farming-labs/farm.js">
65
+ <GitHubIcon />
66
+ <span>GitHub</span>
67
+ </a>
68
+ </span>
69
+ </nav>
70
+ );
71
+ }
@@ -0,0 +1,4 @@
1
+ import { createAPIClient } from "@farm.js/core/client";
2
+ import type { APIRouter } from "./api.generated";
3
+
4
+ export const api = createAPIClient<APIRouter>();
@@ -0,0 +1,7 @@
1
+ import type { POST as POST_greeting } from "../app/api/greeting/route";
2
+
3
+ export type APIRouter = {
4
+ greeting: {
5
+ post: typeof POST_greeting;
6
+ };
7
+ };
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "useDefineForClassFields": true,
5
+ "lib": ["ES2020", "DOM", "DOM.Iterable"],
6
+ "module": "ESNext",
7
+ "skipLibCheck": true,
8
+ "moduleResolution": "bundler",
9
+ "baseUrl": ".",
10
+ "paths": {
11
+ "@/*": ["./src/*"]
12
+ },
13
+ "allowImportingTsExtensions": true,
14
+ "resolveJsonModule": true,
15
+ "isolatedModules": true,
16
+ "noEmit": true,
17
+ "jsx": "preserve",
18
+ "jsxImportSource": "solid-js",
19
+ "strict": true,
20
+ "noUnusedLocals": true,
21
+ "noUnusedParameters": true,
22
+ "noFallthroughCasesInSwitch": true
23
+ },
24
+ "include": ["src", "farm.config.ts"]
25
+ }
@@ -0,0 +1,9 @@
1
+ import { defineConfig } from "@farm.js/core/config";
2
+ import { svelte } from "@farm.js/svelte";
3
+
4
+ export default defineConfig({
5
+ renderer: svelte(),
6
+ theme: {
7
+ default: "dark",
8
+ },
9
+ });
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "farm-app",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "scripts": {
7
+ "dev": "farm dev",
8
+ "build": "farm build",
9
+ "deploy": "farm deploy",
10
+ "start": "farm start",
11
+ "type-check": "svelte-check --tsconfig ./tsconfig.json"
12
+ },
13
+ "dependencies": {
14
+ "@farm.js/core": "0.1.0-beta.41",
15
+ "@farm.js/svelte": "0.1.0-beta.29",
16
+ "@fontsource-variable/geist": "5.3.0",
17
+ "@fontsource-variable/geist-mono": "5.3.0",
18
+ "svelte": "5.56.8",
19
+ "zod": "4.1.12"
20
+ },
21
+ "devDependencies": {
22
+ "@farm.js/cli": "0.1.0-beta.41",
23
+ "svelte-check": "4.7.5",
24
+ "tailwindcss": "^4.0.0",
25
+ "typescript": "^5.3.3"
26
+ },
27
+ "packageManager": "pnpm@8.12.1"
28
+ }
@@ -0,0 +1,15 @@
1
+ import { createEndpoint } from "@farm.js/core/api";
2
+ import { z } from "zod";
3
+
4
+ export const POST = createEndpoint(
5
+ "/api/greeting",
6
+ {
7
+ method: "POST",
8
+ body: z.object({
9
+ name: z.string().trim().min(1).max(40),
10
+ }),
11
+ },
12
+ async ({ body }) => ({
13
+ message: `Hello, ${body.name}, from the FARMJS server.`,
14
+ }),
15
+ );
@@ -0,0 +1,21 @@
1
+ <script module lang="ts">
2
+ import type { Metadata } from "@farm.js/core";
3
+ import "./globals.css";
4
+ import "./svelte.css";
5
+
6
+ export const metadata: Metadata = {
7
+ title: "FARMJS Svelte App",
8
+ description: "A framework for product-integrated apps",
9
+ icons: {
10
+ icon: [{ url: "/favicon.svg", type: "image/svg+xml", sizes: "any" }],
11
+ },
12
+ };
13
+ </script>
14
+
15
+ <script lang="ts">
16
+ import type { Snippet } from "svelte";
17
+
18
+ let { children }: { children?: Snippet } = $props();
19
+ </script>
20
+
21
+ {@render children?.()}
@@ -0,0 +1,64 @@
1
+ <script module lang="ts">
2
+ export const hydrate = true;
3
+ </script>
4
+
5
+ <script lang="ts">
6
+ import ResourceLinks from "../components/resource-links.svelte";
7
+ import { api } from "../lib/api-client";
8
+
9
+ let message = $state("Call a typed server function");
10
+ let pending = $state(false);
11
+ let failed = $state(false);
12
+
13
+ async function callServer() {
14
+ pending = true;
15
+ failed = false;
16
+ try {
17
+ const result = await api.greeting.post({
18
+ body: { name: "Svelte" },
19
+ });
20
+ if (result.error) throw result.error;
21
+ if (!result.data) throw new Error("The server returned no greeting");
22
+ message = result.data.message;
23
+ } catch {
24
+ failed = true;
25
+ message = "Try the server call again";
26
+ } finally {
27
+ pending = false;
28
+ }
29
+ }
30
+ </script>
31
+
32
+ <main class="landing-main">
33
+ <section class="hero-section">
34
+ <div class="hero-copy">
35
+ <div class="eyebrow-row">
36
+ <span>00</span>
37
+ <span>FARMJS / Svelte starter</span>
38
+ </div>
39
+
40
+ <h1>Edit <code>page.svelte</code> to begin.</h1>
41
+
42
+ <div class="command-list" aria-label="Getting started">
43
+ <div class="command-row">
44
+ <span>01</span>
45
+ <code>pnpm dev</code>
46
+ </div>
47
+ <div class="command-row">
48
+ <span>02</span>
49
+ <button
50
+ type="button"
51
+ class:server-call-error={failed}
52
+ class="server-call"
53
+ disabled={pending}
54
+ onclick={callServer}
55
+ >
56
+ {pending ? "Calling…" : message}
57
+ </button>
58
+ </div>
59
+ </div>
60
+
61
+ <ResourceLinks class="resource-links" />
62
+ </div>
63
+ </section>
64
+ </main>
@@ -0,0 +1,26 @@
1
+ .server-call {
2
+ appearance: none;
3
+ width: fit-content;
4
+ border: 0;
5
+ padding: 0;
6
+ color: var(--ink);
7
+ background: transparent;
8
+ cursor: pointer;
9
+ font-family: var(--font-mono);
10
+ font-size: 0.75rem;
11
+ text-align: left;
12
+ }
13
+
14
+ .server-call:hover:not(:disabled) {
15
+ text-decoration: underline;
16
+ text-underline-offset: 0.25rem;
17
+ }
18
+
19
+ .server-call:disabled {
20
+ color: var(--ink-soft);
21
+ cursor: wait;
22
+ }
23
+
24
+ .server-call-error {
25
+ color: #fca5a5;
26
+ }
@@ -0,0 +1,31 @@
1
+ <nav aria-label="Starter resources">
2
+ <span class="resource-link-item">
3
+ <a href="https://farm.js.dev">
4
+ <svg
5
+ class="resource-icon"
6
+ viewBox="0 0 24 24"
7
+ fill="none"
8
+ stroke="currentColor"
9
+ stroke-width="1.8"
10
+ stroke-linecap="round"
11
+ stroke-linejoin="round"
12
+ aria-hidden="true"
13
+ >
14
+ <path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8Z" />
15
+ <path d="M14 2v6h6M8 13h8M8 17h6" />
16
+ </svg>
17
+ <span>Docs</span>
18
+ </a>
19
+ </span>
20
+ <span class="resource-link-item">
21
+ <span class="resource-separator" aria-hidden="true">/</span>
22
+ <a href="https://github.com/farming-labs/farm.js">
23
+ <svg class="resource-icon" viewBox="0 0 24 24" fill="currentColor" aria-hidden="true">
24
+ <path
25
+ d="M12 .7a11.5 11.5 0 0 0-3.64 22.41c.58.1.79-.25.79-.56v-2.23c-3.22.7-3.9-1.37-3.9-1.37-.52-1.34-1.28-1.69-1.28-1.69-1.05-.72.08-.7.08-.7 1.16.08 1.77 1.19 1.77 1.19 1.03 1.77 2.7 1.26 3.36.96.1-.75.4-1.26.73-1.55-2.57-.29-5.27-1.29-5.27-5.68 0-1.26.45-2.28 1.18-3.09-.12-.29-.51-1.47.11-3.05 0 0 .96-.31 3.16 1.18A10.95 10.95 0 0 1 12 6.1c.98 0 1.95.13 2.87.39 2.2-1.49 3.16-1.18 3.16-1.18.62 1.58.23 2.76.11 3.05.74.81 1.18 1.83 1.18 3.09 0 4.4-2.71 5.38-5.29 5.67.42.36.79 1.07.79 2.16v3.27c0 .31.21.67.8.56A11.5 11.5 0 0 0 12 .7Z"
26
+ />
27
+ </svg>
28
+ <span>GitHub</span>
29
+ </a>
30
+ </span>
31
+ </nav>