~repos /edge-city

#react#js#ssr

git clone https://pyrossh.dev/repos/edge-city.git

edge-city is a next level meta-framework for react that runs only on edge runtimes


9e6ce31c Peter John

2 years ago
improve dir structure
.gitignore CHANGED
@@ -168,4 +168,5 @@ dist
168
168
  .yarn/install-state.gz
169
169
  .pnp.\*
170
170
  .cache
171
- dist
171
+ dist
172
+ .vercel
api/health.js CHANGED
@@ -1,3 +1,8 @@
1
1
  export const onGet = (req) => {
2
- return new Response("ok");
2
+ return new Response("ok", {
3
+ headers: {
4
+ "Content-Type": "application/json",
5
+ },
6
+ status: 200,
7
+ });
3
8
  }
api/todos/[id]/index.js CHANGED
@@ -8,7 +8,12 @@ export const onGet = async (req) => {
8
8
  filter: { id },
9
9
  });
10
10
  const data = JSON.stringify(item);
11
- return new Response(data);
11
+ return new Response(data, {
12
+ headers: {
13
+ "Content-Type": "application/json",
14
+ },
15
+ status: 200,
16
+ });
12
17
  }
13
18
 
14
19
  export const onPut = async (req) => {
astroPlugin.js CHANGED
@@ -1,4 +1,9 @@
1
1
  import { plugin } from "bun";
2
+ import path from "path";
3
+ import { readFileSync, writeFileSync, mkdirSync, existsSync } from "fs";
4
+ import postcss from "postcss"
5
+ import autoprefixer from "autoprefixer";
6
+ import postcssNested from "postcss-nested";
2
7
 
3
8
  const transpiler = new Bun.Transpiler({
4
9
  loader: "jsx",
@@ -9,13 +14,16 @@ const transpiler = new Bun.Transpiler({
9
14
  plugin({
10
15
  name: "Astro",
11
16
  async setup(build) {
12
- const { readFileSync, writeFileSync } = await import("fs");
13
17
  build.onLoad({ filter: /\.astro$/ }, async (args) => {
18
+ const folder = path.dirname(args.path).replace(process.cwd(), "");
19
+ const filename = path.basename(args.path).replace("astro", "js");
20
+ const outputFolder = path.join(process.cwd(), ".cache", folder);
21
+ const outputFile = path.join(outputFolder, filename);
14
22
  const text = readFileSync(args.path, "utf8");
15
- const [_, js, html] = text.split("---");
23
+ const [_, js, html, css] = text.split("---");
16
24
  const imports = js.split("\n").filter((line) => line.startsWith("import")).join("\n");
17
25
  const body = js.split("\n").filter((line) => !line.startsWith("import")).join("\n");
18
- const code = await transpiler.transform(`
26
+ const tpl = `
19
27
  ${imports}
20
28
 
21
29
  export default () => {
@@ -25,10 +33,20 @@ plugin({
25
33
  ${html}
26
34
  );
27
35
  }
28
- `);
36
+ `;
37
+ // console.log('tpl', tpl);
38
+ const code = await transpiler.transform(tpl);
29
39
  // console.log('code', code);
40
+ if (!existsSync(outputFolder)) {
41
+ mkdirSync(outputFolder);
42
+ }
30
- writeFileSync("./dist/index.js", code)
43
+ writeFileSync(outputFile, code);
44
+ if (css) {
45
+ const result = postcss([autoprefixer, postcssNested])
46
+ .process(css, { from: 'src/app.css', to: 'dest/app.css' });
47
+ writeFileSync(path.join(outputFolder, filename.replace("js", "css")), result.css);
48
+ }
31
- const src = await import("./dist/index.js");
49
+ const src = await import(outputFile);
32
50
  return {
33
51
  exports: {
34
52
  default: src.default,
bun.lockb CHANGED
Binary file
components/Todo.astro ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ const { id, text } = Astro.props;
3
+ const todos = [{ text: "123" }];
4
+ ---
5
+
6
+ <div>
7
+ <p>
8
+ {item.text}
9
+ </p>
10
+ </div>
11
+
12
+ ---
13
+ div {
14
+ font-size: 20px;
15
+ }
containers/TodoList.astro ADDED
@@ -0,0 +1,10 @@
1
+ ---
2
+ const todos = [{ text: "123" }];
3
+ ---
4
+
5
+ <div className="todo-list">
6
+ <h1>Todos</h1>
7
+ <ul>
8
+ {todos.map((item) => <li key={item.text}>{item.text}</li>)}
9
+ </ul>
10
+ </div>
index.css DELETED
@@ -1,3 +0,0 @@
1
- .ccs {
2
- display: flex;
3
- }
index.js CHANGED
@@ -1,6 +1,9 @@
1
1
  import './astroPlugin.js';
2
+ import path from 'path';
3
+ import { SWRConfig } from 'swr';
2
- import { renderToString, renderToReadableStream } from 'react-dom/server';
4
+ import { renderToReadableStream } from 'react-dom/server';
3
5
  import { RouterProvider } from './router.js';
6
+ import packageJson from "./package.json";
4
7
 
5
8
  const router = new Bun.FileSystemRouter({
6
9
  style: "nextjs",
@@ -20,7 +23,13 @@ const renderApi = async (route, req) => {
20
23
  console.log('routeImport', routeImport);
21
24
  }
22
25
 
26
+ const deps = Object.keys(packageJson.dependencies).reduce((acc, dep) => {
27
+ acc[dep] = `https://esm.sh/${dep}@${packageJson.dependencies[dep]}?dev`;
28
+ return acc;
29
+ }, {})
30
+
23
31
  const renderPage = async (filePath, url, params) => {
32
+ const file = path.basename(url.pathname).replace("astro", "js") + "index.js";
24
33
  const query = {};
25
34
  for (const key of url.searchParams.keys()) {
26
35
  query[key] = url.searchParams.get(key);
@@ -36,6 +45,7 @@ const renderPage = async (filePath, url, params) => {
36
45
  <html lang="en">
37
46
  <head>
38
47
  {/* {routeImport.head()} */}
48
+ <link rel="stylesheet" href="/routes/index.css" />
39
49
  <script id="initial_route_context" type='application/json' dangerouslySetInnerHTML={{
40
50
  __html: JSON.stringify(initialRouteValue)
41
51
  }} />
@@ -43,25 +53,44 @@ const renderPage = async (filePath, url, params) => {
43
53
  __html: JSON.stringify(
44
54
  {
45
55
  "imports": {
46
- "react": "https://esm.sh/react@18.2.0?dev",
56
+ ...deps,
47
- "react-dom": "https://esm.sh/react-dom@18.2.0?dev",
48
57
  "react-dom/client": "https://esm.sh/react-dom@18.2.0/client?dev",
49
58
  "react/jsx-dev-runtime": "https://esm.sh/react@18.2.0/jsx-dev-runtime?dev",
50
- "@/utils": "/assets/js/src/utils.js",
51
59
  "@/router.js": "/assets/js/src/router.js",
60
+ "@/routes/index.js": "/routes/index.js",
61
+ "@/components/Todo.astro": "/components/Todo.js",
62
+ "@/containers/TodoList.astro": "/containers/TodoList.js"
52
63
  }
53
64
  }
54
65
  )
55
66
  }}>
56
67
  </script>
57
- {/* <script id="initial_swr_fallback" dangerouslySetInnerHTML={{ __html: JSON.stringify(value) }} /> */}
68
+ <script type="module" defer dangerouslySetInnerHTML={{
69
+ __html: `
70
+ import* as JSX from "react/jsx-dev-runtime";
71
+ var $jsx = JSX.jsxDEV;
72
+ import { hydrateRoot } from 'react-dom/client';
73
+ import { SWRConfig } from 'swr';
74
+ import {RouterProvider} from "@/router.js";
75
+ import Page from "@/routes/${file}";
76
+
58
- <script type="module" src="/assets/js/routes/index.astro" defer></script>
77
+ const initialRouteValue = JSON.parse(document.getElementById('initial_route_context').textContent);
78
+ const root = hydrateRoot(document.getElementById("root"), $jsx(SWRConfig, {
79
+ value: { suspense: true },
80
+ children: $jsx(RouterProvider, {
81
+ value: initialRouteValue,
82
+ children: $jsx(Page, {}, undefined, false, undefined, this)
83
+ }, undefined, false, undefined, this)
84
+ }, undefined, false, undefined, this));
85
+ `}}></script>
59
86
  </head>
60
87
  <body>
61
88
  <div id="root">
89
+ <SWRConfig value={{ suspense: true }}>
62
- <RouterProvider value={initialRouteValue}>
90
+ <RouterProvider value={initialRouteValue}>
63
- <Page />
91
+ <Page />
64
- </RouterProvider>
92
+ </RouterProvider>
93
+ </SWRConfig>
65
94
  </div>
66
95
  </body>
67
96
  </html >
@@ -74,59 +103,80 @@ const renderPage = async (filePath, url, params) => {
74
103
  });
75
104
  }
76
105
 
106
+ // const renderBootstrap = async (url) => {
107
+ // const folder = path.dirname(url.pathname);
108
+ // const file = path.basename(url.pathname).replace("astro", "js");
109
+ // const result = await transpiler.transform(`
110
+ // import { hydrateRoot } from 'react-dom/client';
111
+ // import {RouterProvider} from "@/router.js";
112
+ // import Page from "@/routes/${file}";
113
+
114
+ // const initialRouteValue = JSON.parse(document.getElementById('initial_route_context').textContent);
115
+ // const root = hydrateRoot(document.getElementById('root'), (
116
+ // <RouterProvider value={initialRouteValue}>
117
+ // <Page />
118
+ // </RouterProvider>
119
+ // ));
120
+ // `);
121
+ // return new Response(result, {
122
+ // headers: {
123
+ // 'Content-Type': 'application/javascript',
124
+ // },
125
+ // status: 200,
126
+ // });
127
+ // }
128
+
129
+ const renderJs = async (url) => {
130
+ const localFile = url.pathname.replace("/assets/js/", "").replace("src/", "");
131
+ const src = await Bun.file(localFile).text();
132
+ const result = await transpiler.transform(src);
133
+ return new Response(result, {
134
+ headers: {
135
+ 'Content-Type': 'application/javascript',
136
+ },
137
+ status: 200,
138
+ });
139
+ }
140
+
141
+ const sendFile = async (url) => {
142
+ const localFile = url.pathname.replace("/assets/js/", "").replace("src/", "");
143
+ const result = await Bun.file(path.join(".cache", localFile)).text();
144
+ let contentType = "application/javascript";
145
+ if (url.pathname.endsWith(".css")) {
146
+ contentType = 'text/css';
147
+ }
148
+ return new Response(result, {
149
+ headers: {
150
+ 'Content-Type': contentType,
151
+ },
152
+ status: 200,
153
+ });
154
+ }
155
+
77
156
  export default {
78
157
  port: 3000,
79
158
  async fetch(req) {
80
159
  const url = new URL(req.url);
160
+ console.log(req.method, url.pathname)
81
- if (url.pathname.startsWith("/dist/js")) {
161
+ if (url.pathname.includes("/components/") || url.pathname.includes("/containers/") || url.pathname.includes("/routes/")) {
82
- const src = await Bun.file("./dist/index.js").text();
83
- return new Response(src, {
162
+ return sendFile(url);
84
- headers: {
85
- 'Content-Type': 'application/javascript',
86
- },
87
- status: 200,
88
- });
89
163
  }
90
- if (url.pathname.startsWith("/assets/js")) {
164
+ if (url.pathname.includes("/assets/js")) {
91
- const lib = url.pathname.replace("/assets/js/", "");
92
- const localFile = lib.replace("src/", "");
93
- let result;
94
- if (localFile.includes("routes")) {
95
- result = await transpiler.transform(`
96
- import { hydrateRoot } from 'react-dom/client';
97
- import {RouterProvider} from "@/router.js";
98
- import Page from "/dist/js/index.js";
99
-
100
- const initialRouteValue = JSON.parse(document.getElementById('initial_route_context').textContent);
101
- const root = hydrateRoot(document.getElementById('root'), (
102
- <RouterProvider value={initialRouteValue}>
103
- <Page />
104
- </RouterProvider>
105
- ));
106
- `);
107
- } else {
108
- const src = await Bun.file(localFile).text();
109
- result = await transpiler.transform(src);
110
- }
111
- return new Response(result, {
165
+ return renderJs(url);
112
- headers: {
113
- 'Content-Type': 'application/javascript',
114
- },
115
- status: 200,
116
- });
117
166
  }
118
- if (url.pathname.startsWith("/api")) {
167
+ if (url.pathname.includes("/api")) {
119
- console.log('api', url.pathname);
120
- // return renderApi(route, req);
168
+ return renderApi(url, req);
169
+ }
170
+ if (url.pathname.includes("/favicon")) {
171
+ return new Response(`Not Found`, {
172
+ headers: { 'Content-Type': 'text/html' },
173
+ status: 404,
174
+ });
121
175
  }
122
176
  return renderPage("./routes/index.astro", url, {});
123
177
  // const route = router.match(url.pathname);
124
178
  // if (route) {
125
179
  // return renderPage(route, url);
126
180
  // }
127
- return new Response(`Not Found`, {
128
- headers: { 'Content-Type': 'text/html' },
129
- status: 404,
130
- });
131
181
  },
132
182
  };
package-lock.json CHANGED
@@ -6,8 +6,11 @@
6
6
  "": {
7
7
  "name": "quickstart",
8
8
  "dependencies": {
9
+ "postcss": "^8.4.21",
10
+ "postcss-js": "^4.0.1",
9
11
  "react": "18.2.0",
10
12
  "react-dom": "^18.2.0",
13
+ "swr": "^2.1.0",
11
14
  "zod": "^3.21.0"
12
15
  },
13
16
  "devDependencies": {
@@ -18,6 +21,14 @@
18
21
  "version": "0.5.7",
19
22
  "dev": true
20
23
  },
24
+ "node_modules/camelcase-css": {
25
+ "version": "2.0.1",
26
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
27
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
28
+ "engines": {
29
+ "node": ">= 6"
30
+ }
31
+ },
21
32
  "node_modules/js-tokens": {
22
33
  "version": "4.0.0",
23
34
  "license": "MIT"
@@ -32,6 +43,63 @@
32
43
  "loose-envify": "cli.js"
33
44
  }
34
45
  },
46
+ "node_modules/nanoid": {
47
+ "version": "3.3.4",
48
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
49
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==",
50
+ "bin": {
51
+ "nanoid": "bin/nanoid.cjs"
52
+ },
53
+ "engines": {
54
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
55
+ }
56
+ },
57
+ "node_modules/picocolors": {
58
+ "version": "1.0.0",
59
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
60
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
61
+ },
62
+ "node_modules/postcss": {
63
+ "version": "8.4.21",
64
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
65
+ "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
66
+ "funding": [
67
+ {
68
+ "type": "opencollective",
69
+ "url": "https://opencollective.com/postcss/"
70
+ },
71
+ {
72
+ "type": "tidelift",
73
+ "url": "https://tidelift.com/funding/github/npm/postcss"
74
+ }
75
+ ],
76
+ "dependencies": {
77
+ "nanoid": "^3.3.4",
78
+ "picocolors": "^1.0.0",
79
+ "source-map-js": "^1.0.2"
80
+ },
81
+ "engines": {
82
+ "node": "^10 || ^12 || >=14"
83
+ }
84
+ },
85
+ "node_modules/postcss-js": {
86
+ "version": "4.0.1",
87
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
88
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
89
+ "dependencies": {
90
+ "camelcase-css": "^2.0.1"
91
+ },
92
+ "engines": {
93
+ "node": "^12 || ^14 || >= 16"
94
+ },
95
+ "funding": {
96
+ "type": "opencollective",
97
+ "url": "https://opencollective.com/postcss/"
98
+ },
99
+ "peerDependencies": {
100
+ "postcss": "^8.4.21"
101
+ }
102
+ },
35
103
  "node_modules/react": {
36
104
  "version": "18.2.0",
37
105
  "license": "MIT",
@@ -61,6 +129,36 @@
61
129
  "loose-envify": "^1.1.0"
62
130
  }
63
131
  },
132
+ "node_modules/source-map-js": {
133
+ "version": "1.0.2",
134
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
135
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
136
+ "engines": {
137
+ "node": ">=0.10.0"
138
+ }
139
+ },
140
+ "node_modules/swr": {
141
+ "version": "2.1.0",
142
+ "resolved": "https://registry.npmjs.org/swr/-/swr-2.1.0.tgz",
143
+ "integrity": "sha512-4hYl5p3/KalQ1MORealM79g/DtLohmud6yyfXw5l4wjtFksYUnocRFudvyaoUtgj3FrVNK9lS25Av9dsZYvz0g==",
144
+ "dependencies": {
145
+ "use-sync-external-store": "^1.2.0"
146
+ },
147
+ "engines": {
148
+ "pnpm": "7"
149
+ },
150
+ "peerDependencies": {
151
+ "react": "^16.11.0 || ^17.0.0 || ^18.0.0"
152
+ }
153
+ },
154
+ "node_modules/use-sync-external-store": {
155
+ "version": "1.2.0",
156
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
157
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
158
+ "peerDependencies": {
159
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
160
+ }
161
+ },
64
162
  "node_modules/zod": {
65
163
  "version": "3.21.0",
66
164
  "license": "MIT",
@@ -74,6 +172,11 @@
74
172
  "version": "0.5.7",
75
173
  "dev": true
76
174
  },
175
+ "camelcase-css": {
176
+ "version": "2.0.1",
177
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
178
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA=="
179
+ },
77
180
  "js-tokens": {
78
181
  "version": "4.0.0"
79
182
  },
@@ -83,6 +186,34 @@
83
186
  "js-tokens": "^3.0.0 || ^4.0.0"
84
187
  }
85
188
  },
189
+ "nanoid": {
190
+ "version": "3.3.4",
191
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.4.tgz",
192
+ "integrity": "sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw=="
193
+ },
194
+ "picocolors": {
195
+ "version": "1.0.0",
196
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
197
+ "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ=="
198
+ },
199
+ "postcss": {
200
+ "version": "8.4.21",
201
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.21.tgz",
202
+ "integrity": "sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==",
203
+ "requires": {
204
+ "nanoid": "^3.3.4",
205
+ "picocolors": "^1.0.0",
206
+ "source-map-js": "^1.0.2"
207
+ }
208
+ },
209
+ "postcss-js": {
210
+ "version": "4.0.1",
211
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
212
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
213
+ "requires": {
214
+ "camelcase-css": "^2.0.1"
215
+ }
216
+ },
86
217
  "react": {
87
218
  "version": "18.2.0",
88
219
  "requires": {
@@ -104,6 +235,25 @@
104
235
  "loose-envify": "^1.1.0"
105
236
  }
106
237
  },
238
+ "source-map-js": {
239
+ "version": "1.0.2",
240
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
241
+ "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw=="
242
+ },
243
+ "swr": {
244
+ "version": "2.1.0",
245
+ "resolved": "https://registry.npmjs.org/swr/-/swr-2.1.0.tgz",
246
+ "integrity": "sha512-4hYl5p3/KalQ1MORealM79g/DtLohmud6yyfXw5l4wjtFksYUnocRFudvyaoUtgj3FrVNK9lS25Av9dsZYvz0g==",
247
+ "requires": {
248
+ "use-sync-external-store": "^1.2.0"
249
+ }
250
+ },
251
+ "use-sync-external-store": {
252
+ "version": "1.2.0",
253
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
254
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
255
+ "requires": {}
256
+ },
107
257
  "zod": {
108
258
  "version": "3.21.0"
109
259
  }
package.json CHANGED
@@ -10,8 +10,12 @@
10
10
  "bun-types": "^0.5.0"
11
11
  },
12
12
  "dependencies": {
13
+ "autoprefixer": "^10.4.14",
14
+ "postcss": "^8.4.21",
15
+ "postcss-nested": "^6.0.1",
13
16
  "react": "18.2.0",
14
17
  "react-dom": "^18.2.0",
18
+ "swr": "^2.1.0",
15
19
  "zod": "^3.21.0"
16
20
  }
17
21
  }
public/index.html DELETED
@@ -1,44 +0,0 @@
1
- <!DOCTYPE html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8" />
5
- <link rel="icon" href="favicon.ico" />
6
- <meta name="viewport" content="width=device-width, initial-scale=1" />
7
- <meta name="theme-color" content="#000000" />
8
- <meta
9
- name="description"
10
- content="Web site created using create-react-app"
11
- />
12
- <link rel="apple-touch-icon" href="/logo192.png" />
13
- <!--
14
- manifest.json provides metadata used when your web app is installed on a
15
- user's mobile device or desktop. See https://developers.google.com/web/fundamentals/web-app-manifest/
16
- -->
17
- <link rel="manifest" href="/manifest.json" />
18
- <!--
19
- Notice the use of %PUBLIC_URL% in the tags above.
20
- It will be replaced with the URL of the `public` folder during the build.
21
- Only files inside the `public` folder can be referenced from the HTML.
22
-
23
- Unlike "/favicon.ico" or "favicon.ico", "%PUBLIC_URL%/favicon.ico" will
24
- work correctly both with client-side routing and a non-root public URL.
25
- Learn how to configure a non-root public URL by running `npm run build`.
26
- -->
27
- <title>React App</title>
28
- </head>
29
- <body>
30
- <noscript>You need to enable JavaScript to run this app.</noscript>
31
- <div id="root"></div>
32
- <!--
33
- This HTML file is a template.
34
- If you open it directly in the browser, you will see an empty page.
35
-
36
- You can add webfonts, meta tags, or analytics to this file.
37
- The build step will place the bundled scripts into the <body> tag.
38
-
39
- To begin the development, run `npm start` or `yarn start`.
40
- To create a production bundle, use `npm run build` or `yarn build`.
41
- -->
42
- <script src="/src/index.jsx" async type="module"></script>
43
- </body>
44
- </html>
routes/about/index.jsx DELETED
@@ -1,12 +0,0 @@
1
- import { page, useRouter } from "@/utils";
2
-
3
- export default page(() => {
4
- const router = useRouter();
5
- return (
6
- <div>
7
- <p>
8
- Hello from server
9
- </p>
10
- </div>
11
- );
12
- });
routes/index.astro CHANGED
@@ -1,34 +1,31 @@
1
1
  ---
2
- import { useState } from 'react';
2
+ import { useState } from "react";
3
- import { useRouter } from '@/router.js';
3
+ import { useRouter } from "@/router.js";
4
-
5
- const head = {
6
- title: "pyros.sh",
7
- description:
8
- "Hi there, I'm Peter John, a fullstack dev from Bangalore, India",
4
+ import TodoList from "@/containers/TodoList.astro";
9
- image: "/favicon.png",
10
- keywords: "pyros.sh,pyrossh",
11
- };
12
5
 
13
6
  const router = useRouter();
14
7
  const [count, setCount] = useState(5);
8
+ // const { data: todos, isLoading, isRevalidating } = usePromise("/todos");
15
9
  ---
16
10
 
17
- <div className="home-page">
11
+ <div>
18
12
  <div>
19
13
  <p>
20
14
  Hello from server path 123: {router.pathname}
21
15
  </p>
16
+ <TodoList />
22
17
  <div>
23
- <button onClick={() => setCount(count - 1)}>
18
+ <button onClick={() => setCount(count - 1)}>-</button>
24
- -
25
- </button>
26
19
  <div>
27
20
  {count}
28
21
  </div>
29
- <button onClick={() => setCount(count + 1)}>
22
+ <button onClick={() => setCount(count + 1)}>+</button>
30
- +
31
- </button>
32
23
  </div>
33
24
  </div>
34
25
  </div>
26
+
27
+ ---
28
+ div {
29
+ padding: 10px;
30
+ background-color: yellow;
31
+ }
routes/layout.astro ADDED
File without changes
routes/page.jsx ADDED
@@ -0,0 +1,21 @@
1
+ export default () => {
2
+ return (
3
+ <div className="home-page">
4
+ <div>
5
+ <p>
6
+ Hello from server path 123: {router.pathname}
7
+ </p>
8
+ <Suspense fallback={"Loading..."}>
9
+ <TodoList />
10
+ </Suspense>
11
+ <div>
12
+ <button onClick={() => setCount(count - 1)}> -</button>
13
+ <div>
14
+ {count}
15
+ </div>
16
+ <button onClick={() => setCount(count + 1)}> +</button>
17
+ </div>
18
+ </div>
19
+ </div>
20
+ )
21
+ }
{public → static}/favicon.ico RENAMED
File without changes
{public → static}/logo192.png RENAMED
File without changes
{public → static}/logo512.png RENAMED
File without changes
{public → static}/manifest.json RENAMED
File without changes
{public → static}/robots.txt RENAMED
File without changes
utils.js DELETED
@@ -1,13 +0,0 @@
1
- export const json = async (body, status = 200, headers = {}) => {
2
- return new Response(body, {
3
- headers: {
4
- 'Content-Type': 'application/json',
5
- ...headers,
6
- },
7
- status
8
- });
9
- }
10
-
11
- // const ErrorBoundary = () => {
12
-
13
- // }