@farm.js/create-app 0.1.0-beta.10 → 0.1.0-beta.100

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 (174) hide show
  1. package/README.md +41 -6
  2. package/bin/create-farm-app.js +8 -3
  3. package/dist/index.js +3289 -27
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +3285 -25
  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 +5 -2
  12. package/templates/_integrations/better-auth/preact/farm.config.ts +22 -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 +22 -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 +22 -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 +22 -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 +14 -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.generated.ts +23 -0
  58. package/templates/_renderers/preact/src/lib/api.ts +4 -0
  59. package/templates/_renderers/preact/tsconfig.json +25 -0
  60. package/templates/_renderers/solid/farm.config.ts +14 -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.generated.ts +23 -0
  68. package/templates/_renderers/solid/src/lib/api.ts +4 -0
  69. package/templates/_renderers/solid/tsconfig.json +25 -0
  70. package/templates/_renderers/svelte/farm.config.ts +11 -0
  71. package/templates/_renderers/svelte/package.json +29 -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.generated.ts +23 -0
  78. package/templates/_renderers/svelte/src/lib/api.ts +4 -0
  79. package/templates/_renderers/svelte/tsconfig.json +23 -0
  80. package/templates/_renderers/vue/farm.config.ts +14 -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.generated.ts +23 -0
  89. package/templates/_renderers/vue/src/lib/api.ts +4 -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/docs.config.ts +33 -0
  94. package/templates/auth/docs.json +36 -0
  95. package/templates/auth/farm.config.ts +22 -0
  96. package/templates/auth/gitignore +10 -0
  97. package/templates/auth/package.json +38 -0
  98. package/templates/auth/pnpm-workspace.yaml +13 -0
  99. package/templates/auth/src/app/dashboard/middleware.ts +13 -0
  100. package/templates/auth/src/app/dashboard/page.tsx +140 -0
  101. package/templates/auth/src/app/docs/page.md +29 -0
  102. package/templates/auth/src/app/error.tsx +25 -0
  103. package/templates/auth/src/app/globals.css +1064 -0
  104. package/templates/auth/src/app/layout.tsx +11 -0
  105. package/templates/auth/src/app/loading.tsx +15 -0
  106. package/templates/auth/src/app/not-found.tsx +26 -0
  107. package/templates/auth/src/app/page.tsx +46 -0
  108. package/templates/auth/src/app/sign-in/page.tsx +16 -0
  109. package/templates/auth/src/app/sign-up/page.tsx +16 -0
  110. package/templates/auth/src/components/auth-form.tsx +120 -0
  111. package/templates/auth/src/components/auth-shell.tsx +21 -0
  112. package/templates/auth/src/components/resource-links.tsx +78 -0
  113. package/templates/auth/src/components/sign-out-button.tsx +45 -0
  114. package/templates/auth/src/components/site-header.tsx +46 -0
  115. package/templates/auth/tsconfig.json +20 -0
  116. package/templates/basic/docs.config.ts +33 -0
  117. package/templates/basic/docs.json +36 -0
  118. package/templates/basic/farm.config.ts +11 -0
  119. package/templates/basic/package.json +11 -3
  120. package/templates/basic/pnpm-workspace.yaml +8 -0
  121. package/templates/basic/src/app/docs/page.md +29 -0
  122. package/templates/basic/src/app/globals.css +241 -0
  123. package/templates/basic/src/app/layout.tsx +3 -5
  124. package/templates/basic/src/app/page.tsx +20 -61
  125. package/templates/basic/src/components/resource-links.tsx +78 -0
  126. package/templates/basic/tsconfig.json +4 -0
  127. package/templates/better-auth/.env.example +3 -0
  128. package/templates/better-auth/README.md +95 -0
  129. package/templates/better-auth/docs.config.ts +33 -0
  130. package/templates/better-auth/docs.json +36 -0
  131. package/templates/better-auth/farm.config.ts +48 -0
  132. package/templates/better-auth/gitignore +10 -0
  133. package/templates/better-auth/package.json +41 -0
  134. package/templates/better-auth/pnpm-workspace.yaml +13 -0
  135. package/templates/better-auth/src/app/dashboard/middleware.ts +15 -0
  136. package/templates/better-auth/src/app/dashboard/page.tsx +188 -0
  137. package/templates/better-auth/src/app/docs/page.md +29 -0
  138. package/templates/better-auth/src/app/error.tsx +25 -0
  139. package/templates/better-auth/src/app/globals.css +1064 -0
  140. package/templates/better-auth/src/app/layout.tsx +11 -0
  141. package/templates/better-auth/src/app/loading.tsx +15 -0
  142. package/templates/better-auth/src/app/not-found.tsx +26 -0
  143. package/templates/better-auth/src/app/page.tsx +50 -0
  144. package/templates/better-auth/src/app/sign-in/page.tsx +16 -0
  145. package/templates/better-auth/src/app/sign-up/page.tsx +16 -0
  146. package/templates/better-auth/src/components/auth-form.tsx +120 -0
  147. package/templates/better-auth/src/components/auth-shell.tsx +21 -0
  148. package/templates/better-auth/src/components/resource-links.tsx +78 -0
  149. package/templates/better-auth/src/components/sign-out-button.tsx +45 -0
  150. package/templates/better-auth/src/components/site-header.tsx +46 -0
  151. package/templates/better-auth/src/lib/auth-client.ts +5 -0
  152. package/templates/better-auth/src/lib/auth.ts +46 -0
  153. package/templates/better-auth/src/lib/migrate-auth.ts +10 -0
  154. package/templates/better-auth/src/lib/session.ts +8 -0
  155. package/templates/better-auth/tsconfig.json +20 -0
  156. package/templates/react-compiler/README.md +62 -0
  157. package/templates/react-compiler/docs.config.ts +33 -0
  158. package/templates/react-compiler/docs.json +36 -0
  159. package/templates/react-compiler/farm.config.ts +31 -0
  160. package/templates/react-compiler/gitignore +23 -0
  161. package/templates/react-compiler/package.json +38 -0
  162. package/templates/react-compiler/pnpm-workspace.yaml +8 -0
  163. package/templates/react-compiler/public/favicon.svg +5 -0
  164. package/templates/react-compiler/scripts/verify-experiment.mjs +113 -0
  165. package/templates/react-compiler/src/app/docs/page.md +29 -0
  166. package/templates/react-compiler/src/app/globals.css +470 -0
  167. package/templates/react-compiler/src/app/layout.tsx +22 -0
  168. package/templates/react-compiler/src/app/page.tsx +47 -0
  169. package/templates/react-compiler/src/components/compiler-comparison.tsx +93 -0
  170. package/templates/react-compiler/src/components/resource-links.tsx +78 -0
  171. package/templates/react-compiler/src/farm.d.ts +74 -0
  172. package/templates/react-compiler/src/lib/api.generated.ts +10 -0
  173. package/templates/react-compiler/tsconfig.json +24 -0
  174. package/templates/basic/src/app/about/page.tsx +0 -32
@@ -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,16 @@
1
+ import type { Metadata } from "@farm.js/core";
2
+ import type { ComponentChildren } from "preact";
3
+ import "./globals.css";
4
+ import "./preact.css";
5
+
6
+ export const metadata: Metadata = {
7
+ title: "FARMJS Preact 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
+
14
+ export default function RootLayout({ children }: { children?: ComponentChildren }) {
15
+ return <>{children}</>;
16
+ }
@@ -0,0 +1,66 @@
1
+ "use client";
2
+
3
+ import { useState } from "preact/hooks";
4
+ import { ResourceLinks } from "../components/resource-links";
5
+ import { apiClient } from "../lib/api";
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 apiClient.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://farmjs.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,23 @@
1
+ /**
2
+ * Auto-generated API router types
3
+ * This file is automatically generated - do not edit manually
4
+ *
5
+ * Server modules are imported only as types. Runtime data contains paths and methods only.
6
+ */
7
+
8
+ import type { POST as POST_greeting } from "../app/api/greeting/route";
9
+
10
+ // Type-only representation of your API routes
11
+ export type APIRouter = {
12
+ greeting: {
13
+ post: typeof POST_greeting;
14
+ };
15
+ };
16
+
17
+ // Pass this schema-free manifest to createApiClients({ routes: apiRoutes }).
18
+ export const apiRoutes = [
19
+ {
20
+ path: "/api/greeting",
21
+ methods: ["POST"],
22
+ },
23
+ ] as const;
@@ -0,0 +1,4 @@
1
+ import { createApiClients } from "@farm.js/core/client";
2
+ import { apiRoutes, type APIRouter } from "./api.generated";
3
+
4
+ export const { api, apiClient } = createApiClients<APIRouter>({ routes: apiRoutes });
@@ -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,14 @@
1
+ import { defineConfig } from "@farm.js/core/config";
2
+ import { devtools } from "@farm.js/devtools";
3
+ import { solid } from "@farm.js/solid";
4
+
5
+ export default defineConfig({
6
+ plugins: [devtools()],
7
+ renderer: solid(),
8
+ theme: {
9
+ default: "dark",
10
+ },
11
+ deploy: {
12
+ target: "vercel",
13
+ },
14
+ });
@@ -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
+ "type-check": "tsc --noEmit"
10
+ },
11
+ "dependencies": {
12
+ "@farm.js/core": "0.1.0-beta.100",
13
+ "@farm.js/solid": "0.1.0-beta.27",
14
+ "@fontsource-variable/geist": "5.3.0",
15
+ "@fontsource-variable/geist-mono": "5.3.0",
16
+ "solid-js": "1.9.14",
17
+ "zod": "4.1.12"
18
+ },
19
+ "devDependencies": {
20
+ "@farm.js/cli": "0.1.0-beta.100",
21
+ "@farm.js/devtools": "0.1.0-beta.1",
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 { apiClient } from "../lib/api";
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 apiClient.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://farmjs.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,23 @@
1
+ /**
2
+ * Auto-generated API router types
3
+ * This file is automatically generated - do not edit manually
4
+ *
5
+ * Server modules are imported only as types. Runtime data contains paths and methods only.
6
+ */
7
+
8
+ import type { POST as POST_greeting } from "../app/api/greeting/route";
9
+
10
+ // Type-only representation of your API routes
11
+ export type APIRouter = {
12
+ greeting: {
13
+ post: typeof POST_greeting;
14
+ };
15
+ };
16
+
17
+ // Pass this schema-free manifest to createApiClients({ routes: apiRoutes }).
18
+ export const apiRoutes = [
19
+ {
20
+ path: "/api/greeting",
21
+ methods: ["POST"],
22
+ },
23
+ ] as const;
@@ -0,0 +1,4 @@
1
+ import { createApiClients } from "@farm.js/core/client";
2
+ import { apiRoutes, type APIRouter } from "./api.generated";
3
+
4
+ export const { api, apiClient } = createApiClients<APIRouter>({ routes: apiRoutes });
@@ -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,11 @@
1
+ import { defineConfig } from "@farm.js/core/config";
2
+ import { devtools } from "@farm.js/devtools";
3
+ import { svelte } from "@farm.js/svelte";
4
+
5
+ export default defineConfig({
6
+ plugins: [devtools()],
7
+ renderer: svelte(),
8
+ theme: {
9
+ default: "dark",
10
+ },
11
+ });
@@ -0,0 +1,29 @@
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.100",
15
+ "@farm.js/svelte": "0.1.0-beta.30",
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.100",
23
+ "@farm.js/devtools": "0.1.0-beta.1",
24
+ "svelte-check": "4.7.5",
25
+ "tailwindcss": "^4.0.0",
26
+ "typescript": "^5.3.3"
27
+ },
28
+ "packageManager": "pnpm@8.12.1"
29
+ }
@@ -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?.()}