create-backtick-app 0.0.0-stage → 0.1.0

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 (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +84 -2
  3. package/dist/index.d.ts +2 -0
  4. package/dist/index.js +146 -0
  5. package/package.json +52 -3
  6. package/templates/react/.prettierignore +8 -0
  7. package/templates/react/.prettierrc +3 -0
  8. package/templates/react/.turbo/turbo-typecheck.log +1 -0
  9. package/templates/react/.vscode/extensions.json +6 -0
  10. package/templates/react/gitignore +16 -0
  11. package/templates/react/node_modules/.bin/backtick-tsc +22 -0
  12. package/templates/react/node_modules/.bin/prettier +22 -0
  13. package/templates/react/node_modules/.bin/tsc +22 -0
  14. package/templates/react/node_modules/.bin/tsserver +22 -0
  15. package/templates/react/package.json +31 -0
  16. package/templates/react/scripts/reset-project.mjs +21 -0
  17. package/templates/react/scripts/start.mjs +20 -0
  18. package/templates/react/server/HelloWave.tsx +30 -0
  19. package/templates/react/server/Home.tsx +65 -0
  20. package/templates/react/server/html.ts +62 -0
  21. package/templates/react/server/index.tsx +33 -0
  22. package/templates/react/tsconfig.json +18 -0
  23. package/templates/react-native/.prettierignore +16 -0
  24. package/templates/react-native/.prettierrc +3 -0
  25. package/templates/react-native/.turbo/turbo-typecheck.log +1 -0
  26. package/templates/react-native/.vscode/extensions.json +6 -0
  27. package/templates/react-native/App.tsx +117 -0
  28. package/templates/react-native/app.json +9 -0
  29. package/templates/react-native/gitignore +41 -0
  30. package/templates/react-native/index.ts +8 -0
  31. package/templates/react-native/node_modules/.bin/backtick-tsc +22 -0
  32. package/templates/react-native/node_modules/.bin/expo +22 -0
  33. package/templates/react-native/node_modules/.bin/expo-modules-autolinking +22 -0
  34. package/templates/react-native/node_modules/.bin/fingerprint +22 -0
  35. package/templates/react-native/node_modules/.bin/prettier +22 -0
  36. package/templates/react-native/node_modules/.bin/react-native +22 -0
  37. package/templates/react-native/node_modules/.bin/tsc +22 -0
  38. package/templates/react-native/node_modules/.bin/tsserver +22 -0
  39. package/templates/react-native/package.json +44 -0
  40. package/templates/react-native/scripts/reset-project.mjs +22 -0
  41. package/templates/react-native/scripts/start.mjs +31 -0
  42. package/templates/react-native/server/HelloWave.tsx +51 -0
  43. package/templates/react-native/server/Home.tsx +84 -0
  44. package/templates/react-native/server/index.tsx +50 -0
  45. package/templates/react-native/server/tsconfig.json +17 -0
  46. package/templates/react-native/tsconfig.json +7 -0
  47. package/templates/solid-js/.prettierignore +8 -0
  48. package/templates/solid-js/.prettierrc +3 -0
  49. package/templates/solid-js/.turbo/turbo-typecheck.log +1 -0
  50. package/templates/solid-js/.vscode/extensions.json +6 -0
  51. package/templates/solid-js/gitignore +16 -0
  52. package/templates/solid-js/node_modules/.bin/backtick-tsc +22 -0
  53. package/templates/solid-js/node_modules/.bin/prettier +22 -0
  54. package/templates/solid-js/node_modules/.bin/tsc +22 -0
  55. package/templates/solid-js/node_modules/.bin/tsserver +22 -0
  56. package/templates/solid-js/package.json +31 -0
  57. package/templates/solid-js/scripts/reset-project.mjs +21 -0
  58. package/templates/solid-js/scripts/start.mjs +20 -0
  59. package/templates/solid-js/server/HelloWave.tsx +34 -0
  60. package/templates/solid-js/server/Home.tsx +65 -0
  61. package/templates/solid-js/server/html.ts +62 -0
  62. package/templates/solid-js/server/index.tsx +33 -0
  63. package/templates/solid-js/tsconfig.json +18 -0
@@ -0,0 +1,62 @@
1
+ import { bundler } from "@backtickjs/bundler";
2
+ import { cs } from "@backtickjs/core";
3
+ import { createRoot } from "@backtickjs/react/client";
4
+ import type { JSX } from "@backtickjs/react/jsx-runtime";
5
+
6
+ // The versions of React the page loads, below: what each page is bundled for.
7
+ const packageVersions = { react: "19.2.3", "react-dom": "19.2.3" };
8
+
9
+ // Development is only what `npm start` runs, which sets NODE_ENV: any other
10
+ // run, a deploy included, is production.
11
+ export const development = process.env.NODE_ENV === "development";
12
+
13
+ // In development, what reloads the page whenever the server restarts, as it
14
+ // does when you save.
15
+ const reload = `
16
+ <script type="module">
17
+ let run;
18
+ setInterval(async () => {
19
+ try {
20
+ const next = await (await fetch("/live")).text();
21
+ if (run !== undefined && next !== run) location.reload();
22
+ run = next;
23
+ } catch {}
24
+ }, 1000);
25
+ </script>`;
26
+
27
+ // A page: the element, bundled for the browser, and React from a CDN.
28
+ export async function toHtml(element: JSX.Element): Promise<string> {
29
+ const bundle = await bundler.build({
30
+ input: cs`$createRoot(document.getElementById("app")!).render($element)`,
31
+ packageVersions,
32
+ });
33
+ // In development, a map back to the files you wrote, for the browser's
34
+ // devtools.
35
+ const { code } = bundle.generate({
36
+ format: "es",
37
+ sourcemap: development ? "inline" : false,
38
+ });
39
+
40
+ return `<!doctype html>
41
+ <html lang="en">
42
+ <head>
43
+ <meta charset="utf-8">
44
+ <meta name="viewport" content="width=device-width, initial-scale=1">
45
+ <title>Backtick</title>
46
+ <script type="importmap">
47
+ {
48
+ "imports": {
49
+ "react": "https://esm.sh/react@19.2.3",
50
+ "react/jsx-runtime": "https://esm.sh/react@19.2.3/jsx-runtime",
51
+ "react-dom/client": "https://esm.sh/react-dom@19.2.3/client?external=react"
52
+ }
53
+ }
54
+ </script>
55
+ </head>
56
+ <body style="margin: 0">
57
+ <div id="app"></div>
58
+ <script type="module" src="data:text/javascript,${encodeURIComponent(code)}"></script>
59
+ ${development ? reload : ""}
60
+ </body>
61
+ </html>`;
62
+ }
@@ -0,0 +1,33 @@
1
+ import { createServer } from "node:http";
2
+ import { Home } from "./Home.js";
3
+ import { development, toHtml } from "./html.js";
4
+
5
+ // In development, this run of the server: `--watch` starts a new one whenever
6
+ // you save, and the page, seeing a new one at `/live`, reloads.
7
+ const run = crypto.randomUUID();
8
+
9
+ const server = createServer(async (request, response) => {
10
+ if (development && request.url === "/live") {
11
+ response.end(run);
12
+ return;
13
+ }
14
+ if (request.url === "/") {
15
+ try {
16
+ const html = await toHtml(<Home />);
17
+ response.setHeader("content-type", "text/html");
18
+ response.end(html);
19
+ } catch (error) {
20
+ // Answered rather than crashed on, so the browser can show why.
21
+ console.error(error);
22
+ response.statusCode = 500;
23
+ response.end(String(error));
24
+ }
25
+ return;
26
+ }
27
+ response.statusCode = 404;
28
+ response.end();
29
+ });
30
+
31
+ server.listen(3000, () => {
32
+ console.log("Backtick server on http://localhost:3000");
33
+ });
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ // Imports kept as written: a name a page only splices, as `$useRef`, looks
4
+ // unused to TypeScript, which would otherwise drop its import.
5
+ "verbatimModuleSyntax": true,
6
+ "module": "esnext",
7
+ "moduleResolution": "bundler",
8
+ "target": "esnext",
9
+ "strict": true,
10
+ "noEmit": true,
11
+ "skipLibCheck": true,
12
+ "lib": ["esnext", "dom"],
13
+ "types": ["node"],
14
+ "jsx": "react-jsx",
15
+ "jsxImportSource": "@backtickjs/react"
16
+ },
17
+ "include": ["server"]
18
+ }
@@ -0,0 +1,16 @@
1
+ # Written by the package manager.
2
+ pnpm-lock.yaml
3
+ package-lock.json
4
+ yarn.lock
5
+ bun.lock
6
+
7
+ # Generated by Expo and its native builds.
8
+ .expo/
9
+ dist/
10
+ web-build/
11
+ expo-env.d.ts
12
+ /ios
13
+ /android
14
+
15
+ # Written the way VS Code writes them, one entry per line.
16
+ .vscode/extensions.json
@@ -0,0 +1,3 @@
1
+ {
2
+ "plugins": ["@backtickjs/prettier-plugin"]
3
+ }
@@ -0,0 +1 @@
1
+ $ tsc --noEmit && backtick-tsc -p server --noEmit
@@ -0,0 +1,6 @@
1
+ {
2
+ "recommendations": [
3
+ "backtickjs.backtick-vscode",
4
+ "esbenp.prettier-vscode"
5
+ ]
6
+ }
@@ -0,0 +1,117 @@
1
+ import { evaluate } from "@backtickjs/react-native-client";
2
+ import Constants from "expo-constants";
3
+ import { StatusBar } from "expo-status-bar";
4
+ import * as React from "react";
5
+ import {
6
+ Component,
7
+ type ReactNode,
8
+ Suspense,
9
+ use,
10
+ useEffect,
11
+ useState,
12
+ } from "react";
13
+ import * as JSXRuntime from "react/jsx-runtime";
14
+ import * as ReactNative from "react-native";
15
+ import { ActivityIndicator, Text } from "react-native";
16
+
17
+ // What a screen may require: the packages this app was built with.
18
+ const modules = {
19
+ react: React,
20
+ "react/jsx-runtime": JSXRuntime,
21
+ "react-native": ReactNative,
22
+ };
23
+
24
+ // Your Backtick server runs on the computer Expo was started from.
25
+ const host = Constants.expoConfig?.hostUri?.split(":")[0] ?? "localhost";
26
+ const server = `http://${host}:3000`;
27
+
28
+ // The screen at `path` on your server: its bundle, fetched and run with the
29
+ // app's packages. Your fetch to shape: headers, auth, caching.
30
+ async function fetchScreen(path: string): Promise<ReactNode> {
31
+ const response = await fetch(`${server}${path}`);
32
+ if (!response.ok) {
33
+ throw new Error(`${path} answered ${response.status}.`);
34
+ }
35
+ return evaluate(await response.text(), modules) as ReactNode;
36
+ }
37
+
38
+ export default function App() {
39
+ // Held here, which doesn't suspend, so the request outlives the render
40
+ // that waits for it. Each request is numbered, so a new one also clears an
41
+ // error the last one showed.
42
+ const [request, setRequest] = useState(() => ({
43
+ number: 0,
44
+ screen: fetchScreen("/home"),
45
+ }));
46
+ useEffect(() => {
47
+ // In development, the screen is fetched again each time the server
48
+ // restarts, so a change to server/ shows as soon as you save.
49
+ if (__DEV__) {
50
+ return onServerRestart(() =>
51
+ setRequest(({ number }) => ({
52
+ number: number + 1,
53
+ screen: fetchScreen("/home"),
54
+ })),
55
+ );
56
+ }
57
+ }, []);
58
+ // The whole screen, its layout included, comes from the server: see
59
+ // server/Home.tsx.
60
+ return (
61
+ <>
62
+ <Boundary key={request.number}>
63
+ <Suspense fallback={<ActivityIndicator style={{ flex: 1 }} />}>
64
+ <Screen screen={request.screen} />
65
+ </Suspense>
66
+ </Boundary>
67
+ <StatusBar style="auto" />
68
+ </>
69
+ );
70
+ }
71
+
72
+ // What the server sent, once it has: suspending until then, and throwing,
73
+ // for the boundary, a screen that couldn't be fetched or run.
74
+ function Screen({ screen }: { screen: Promise<ReactNode> }) {
75
+ return use(screen);
76
+ }
77
+
78
+ // Calls `restarted` when the server starts a new run: it names each run at
79
+ // `/live`, and a new name is a new run.
80
+ function onServerRestart(restarted: () => void): () => void {
81
+ let run: string | undefined;
82
+ const timer = setInterval(async () => {
83
+ try {
84
+ const next = await (await fetch(`${server}/live`)).text();
85
+ if (run !== undefined && next !== run) {
86
+ restarted();
87
+ }
88
+ run = next;
89
+ } catch {
90
+ // Restarting: the next tick finds the new run.
91
+ }
92
+ }, 1000);
93
+ return () => clearInterval(timer);
94
+ }
95
+
96
+ // Why the screen couldn't be drawn: the server unreachable, or a screen the
97
+ // app can't run.
98
+ class Boundary extends Component<{ children: ReactNode }, { error: unknown }> {
99
+ state = { error: null as unknown };
100
+
101
+ static getDerivedStateFromError(error: unknown) {
102
+ return { error };
103
+ }
104
+
105
+ render() {
106
+ if (this.state.error === null) {
107
+ return this.props.children;
108
+ }
109
+ return (
110
+ <Text style={{ margin: 24, marginTop: 96, color: "#b91c1c" }}>
111
+ {String((this.state.error as Error).message ?? this.state.error)}
112
+ {"\n\n"}Is your Backtick server running? npm start runs it alongside
113
+ Expo.
114
+ </Text>
115
+ );
116
+ }
117
+ }
@@ -0,0 +1,9 @@
1
+ {
2
+ "expo": {
3
+ "name": "backtick-app",
4
+ "slug": "backtick-app",
5
+ "version": "1.0.0",
6
+ "orientation": "portrait",
7
+ "userInterfaceStyle": "light"
8
+ }
9
+ }
@@ -0,0 +1,41 @@
1
+ # Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
2
+
3
+ # dependencies
4
+ node_modules/
5
+
6
+ # Expo
7
+ .expo/
8
+ dist/
9
+ web-build/
10
+ expo-env.d.ts
11
+
12
+ # Native
13
+ .kotlin/
14
+ *.orig.*
15
+ *.jks
16
+ *.p8
17
+ *.p12
18
+ *.key
19
+ *.mobileprovision
20
+
21
+ # Metro
22
+ .metro-health-check*
23
+
24
+ # debug
25
+ npm-debug.*
26
+ yarn-debug.*
27
+ yarn-error.*
28
+
29
+ # macOS
30
+ .DS_Store
31
+ *.pem
32
+
33
+ # local env files
34
+ .env*.local
35
+
36
+ # typescript
37
+ *.tsbuildinfo
38
+
39
+ # generated native folders
40
+ /ios
41
+ /android
@@ -0,0 +1,8 @@
1
+ import { registerRootComponent } from "expo";
2
+
3
+ import App from "./App";
4
+
5
+ // registerRootComponent calls AppRegistry.registerComponent('main', () => App);
6
+ // It also ensures that whether you load the app in Expo Go or in a native build,
7
+ // the environment is set up appropriately
8
+ registerRootComponent(App);
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../@backtickjs/tsc/bin/backtick-tsc.js" "$@"
19
+ else
20
+ exec node "$basedir/../@backtickjs/tsc/bin/backtick-tsc.js" "$@"
21
+ fi
22
+ # cmd-shim-target=/home/runner/work/backtick/backtick/packages/create-backtick-app/templates/react-native/node_modules/@backtickjs/tsc/bin/backtick-tsc.js
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules/expo/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules/expo/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../expo/bin/cli" "$@"
19
+ else
20
+ exec node "$basedir/../expo/bin/cli" "$@"
21
+ fi
22
+ # cmd-shim-target=/home/runner/work/backtick/backtick/packages/create-backtick-app/templates/react-native/node_modules/expo/bin/cli
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules/expo/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules/expo/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../expo/bin/autolinking" "$@"
19
+ else
20
+ exec node "$basedir/../expo/bin/autolinking" "$@"
21
+ fi
22
+ # cmd-shim-target=/home/runner/work/backtick/backtick/packages/create-backtick-app/templates/react-native/node_modules/expo/bin/autolinking
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules/expo/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules/expo/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/expo@57.0.26_@babel+core@7.29.7_@expo+dom-webview@57.0.1_react-dom@19.2.3_react@19.2.3__fdb828cd1453efd2ba420c405053d76e/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../expo/bin/fingerprint" "$@"
19
+ else
20
+ exec node "$basedir/../expo/bin/fingerprint" "$@"
21
+ fi
22
+ # cmd-shim-target=/home/runner/work/backtick/backtick/packages/create-backtick-app/templates/react-native/node_modules/expo/bin/fingerprint
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/prettier@3.8.4/node_modules/prettier/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/prettier@3.8.4/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/prettier@3.8.4/node_modules/prettier/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/prettier@3.8.4/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../prettier/bin/prettier.cjs" "$@"
19
+ else
20
+ exec node "$basedir/../prettier/bin/prettier.cjs" "$@"
21
+ fi
22
+ # cmd-shim-target=/home/runner/work/backtick/backtick/packages/create-backtick-app/templates/react-native/node_modules/prettier/bin/prettier.cjs
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/react-native@0.86.3_@babel+core@7.29.7_@types+react@19.2.18_react@19.2.3/node_modules/react-native/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/react-native@0.86.3_@babel+core@7.29.7_@types+react@19.2.18_react@19.2.3/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/react-native@0.86.3_@babel+core@7.29.7_@types+react@19.2.18_react@19.2.3/node_modules/react-native/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/react-native@0.86.3_@babel+core@7.29.7_@types+react@19.2.18_react@19.2.3/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../react-native/cli.js" "$@"
19
+ else
20
+ exec node "$basedir/../react-native/cli.js" "$@"
21
+ fi
22
+ # cmd-shim-target=/home/runner/work/backtick/backtick/packages/create-backtick-app/templates/react-native/node_modules/react-native/cli.js
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/typescript@6.0.3/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/typescript@6.0.3/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../typescript/bin/tsc" "$@"
19
+ else
20
+ exec node "$basedir/../typescript/bin/tsc" "$@"
21
+ fi
22
+ # cmd-shim-target=/home/runner/work/backtick/backtick/packages/create-backtick-app/templates/react-native/node_modules/typescript/bin/tsc
@@ -0,0 +1,22 @@
1
+ #!/bin/sh
2
+ basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')")
3
+
4
+ case `uname` in
5
+ *CYGWIN*|*MINGW*|*MSYS*)
6
+ if command -v cygpath > /dev/null 2>&1; then
7
+ basedir=`cygpath -w "$basedir"`
8
+ fi
9
+ ;;
10
+ esac
11
+
12
+ if [ -z "$NODE_PATH" ]; then
13
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/typescript@6.0.3/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules"
14
+ else
15
+ export NODE_PATH="/home/runner/work/backtick/backtick/node_modules/.pnpm/typescript@6.0.3/node_modules/typescript/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/typescript@6.0.3/node_modules:/home/runner/work/backtick/backtick/node_modules/.pnpm/node_modules:$NODE_PATH"
16
+ fi
17
+ if [ -x "$basedir/node" ]; then
18
+ exec "$basedir/node" "$basedir/../typescript/bin/tsserver" "$@"
19
+ else
20
+ exec node "$basedir/../typescript/bin/tsserver" "$@"
21
+ fi
22
+ # cmd-shim-target=/home/runner/work/backtick/backtick/packages/create-backtick-app/templates/react-native/node_modules/typescript/bin/tsserver
@@ -0,0 +1,44 @@
1
+ {
2
+ "name": "backtick-app-react-native",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "main": "index.ts",
6
+ "scripts": {
7
+ "start": "node scripts/start.mjs",
8
+ "android": "node scripts/start.mjs --android",
9
+ "ios": "node scripts/start.mjs --ios",
10
+ "web": "node scripts/start.mjs --web",
11
+ "typecheck": "tsc --noEmit && backtick-tsc -p server --noEmit",
12
+ "reset-project": "node scripts/reset-project.mjs",
13
+ "format": "prettier --write --ignore-unknown .",
14
+ "format:check": "prettier --check --ignore-unknown ."
15
+ },
16
+ "dependencies": {
17
+ "@backtickjs/bundler": "^0.1.0",
18
+ "@backtickjs/core": "^0.1.0",
19
+ "@backtickjs/node-plugin": "^0.1.0",
20
+ "@backtickjs/react": "^19.2.3",
21
+ "@backtickjs/react-native": "^0.86.3",
22
+ "@backtickjs/react-native-client": "^0.1.0",
23
+ "expo": "~57.0.26",
24
+ "expo-constants": "~57.0.20",
25
+ "expo-status-bar": "~57.0.1",
26
+ "react": "19.2.3",
27
+ "react-dom": "19.2.3",
28
+ "react-native": "0.86.3",
29
+ "react-native-web": "^0.21.0",
30
+ "typescript": "^6.0.3"
31
+ },
32
+ "devDependencies": {
33
+ "@backtickjs/prettier-plugin": "^0.1.0",
34
+ "@backtickjs/tsc": "^0.1.0",
35
+ "@types/node": "^25.9.1",
36
+ "@types/react": "19.2.18",
37
+ "prettier": "^3.6.2"
38
+ },
39
+ "backtick": {
40
+ "plugins": [
41
+ "@backtickjs/react/plugin"
42
+ ]
43
+ }
44
+ }
@@ -0,0 +1,22 @@
1
+ // Replaces the welcome screen with a blank one, so you start fresh.
2
+ import { rmSync, writeFileSync } from "node:fs";
3
+
4
+ writeFileSync(
5
+ "server/Home.tsx",
6
+ `import { cs } from "@backtickjs/core";
7
+ import { Text, View } from "@backtickjs/react-native";
8
+
9
+ export async function Home() {
10
+ return cs\`(
11
+ <$View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}>
12
+ <$Text>Edit server/Home.tsx to edit this screen.</$Text>
13
+ </$View>
14
+ )\`;
15
+ }
16
+ `,
17
+ );
18
+ rmSync("server/HelloWave.tsx", { force: true });
19
+
20
+ console.log(
21
+ "✅ Project reset. server/Home.tsx is now a blank screen, and the welcome example is gone.",
22
+ );
@@ -0,0 +1,31 @@
1
+ // Starts your Backtick server in development, then Expo, both in this terminal:
2
+ // Expo keeps its keys and QR code, and the server restarts whenever a file
3
+ // under `server/` changes. Arguments are Expo's, as `npm run ios` passes
4
+ // `--ios`.
5
+ import { spawn } from "node:child_process";
6
+ import { readFileSync } from "node:fs";
7
+
8
+ // The runtime is the one package.json has a Backtick loader for: Bun's, or
9
+ // else Node's.
10
+ const { dependencies } = JSON.parse(readFileSync("package.json", "utf8"));
11
+ const [runtime, ...loader] =
12
+ "@backtickjs/bun-plugin" in dependencies
13
+ ? ["bun", "--preload", "@backtickjs/bun-plugin"]
14
+ : ["node", "--enable-source-maps", "--import", "@backtickjs/node-plugin"];
15
+
16
+ const server = spawn(runtime, ["--watch", ...loader, "server/index.tsx"], {
17
+ stdio: "inherit",
18
+ env: { ...process.env, NODE_ENV: process.env.NODE_ENV ?? "development" },
19
+ });
20
+
21
+ // `bunx` where Bun runs this script, as it does where Node isn't installed.
22
+ const npx = process.versions.bun ? "bunx" : "npx";
23
+ const expo = spawn(npx, ["expo", "start", ...process.argv.slice(2)], {
24
+ stdio: "inherit",
25
+ shell: process.platform === "win32",
26
+ });
27
+
28
+ expo.on("exit", (code) => {
29
+ server.kill();
30
+ process.exit(code ?? 0);
31
+ });