@alxia/create 0.1.0 → 0.1.2

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 (48) hide show
  1. package/README.md +37 -6
  2. package/dist/copy.d.ts +24 -0
  3. package/dist/copy.d.ts.map +1 -0
  4. package/dist/index.js +61 -281
  5. package/dist/index.js.map +8 -9
  6. package/dist/main.d.ts.map +1 -1
  7. package/dist/registry.d.ts +28 -7
  8. package/dist/registry.d.ts.map +1 -1
  9. package/dist/versions.d.ts +0 -2
  10. package/dist/versions.d.ts.map +1 -1
  11. package/dist/write.d.ts +2 -1
  12. package/dist/write.d.ts.map +1 -1
  13. package/docs/README.md +3 -3
  14. package/docs/guide.md +104 -27
  15. package/docs/roadmap.md +35 -9
  16. package/docs/troubleshooting.md +58 -63
  17. package/package.json +5 -3
  18. package/templates/api/.dockerignore +6 -0
  19. package/templates/api/.env.example +3 -0
  20. package/templates/api/Dockerfile +22 -0
  21. package/templates/api/README.md +64 -0
  22. package/templates/api/gitignore +6 -0
  23. package/templates/api/package.json +21 -0
  24. package/templates/api/src/app.spec.ts +46 -0
  25. package/templates/api/src/app.ts +33 -0
  26. package/templates/api/src/server.ts +4 -0
  27. package/templates/api/tsconfig.json +25 -0
  28. package/templates/react-router/.dockerignore +4 -0
  29. package/templates/react-router/Dockerfile +29 -0
  30. package/templates/react-router/README.md +87 -0
  31. package/templates/react-router/_bunfig.toml +4 -0
  32. package/templates/react-router/app/app.css +15 -0
  33. package/templates/react-router/app/root.tsx +75 -0
  34. package/templates/react-router/app/routes/home.tsx +13 -0
  35. package/templates/react-router/app/routes.ts +3 -0
  36. package/templates/react-router/app/welcome/logo-dark.svg +23 -0
  37. package/templates/react-router/app/welcome/logo-light.svg +23 -0
  38. package/templates/react-router/app/welcome/welcome.tsx +89 -0
  39. package/templates/react-router/gitignore +7 -0
  40. package/templates/react-router/package.json +31 -0
  41. package/templates/react-router/public/favicon.ico +0 -0
  42. package/templates/react-router/react-router.config.ts +7 -0
  43. package/templates/react-router/tsconfig.json +26 -0
  44. package/templates/react-router/vite.config.ts +11 -0
  45. package/dist/templates/api.d.ts +0 -16
  46. package/dist/templates/api.d.ts.map +0 -1
  47. package/dist/templates/react-router.d.ts +0 -26
  48. package/dist/templates/react-router.d.ts.map +0 -1
@@ -26,17 +26,16 @@ nothing — the symptom.
26
26
 
27
27
  **Writing the project**
28
28
 
29
- - [`create-alxia: create-react-router's … is not what this @alxia/create expects: …`](#create-alxia-create-react-routers--is-not-what-this-alxiacreate-expects-)
30
- - [`create-alxia: failed: create-react-router exited with 1.`](#create-alxia-failed-create-react-router-exited-with-1)
31
29
  - [`create-alxia: failed: …`](#create-alxia-failed-)
32
30
  - [`create-alxia: warning: the registry did not answer for …; kept the versions the template ships.`](#create-alxia-warning-the-registry-did-not-answer-for--kept-the-versions-the-template-ships)
33
31
  - [`typescript: kept to ^6.0.3 || ^7.0.0, where the newest is 7.0.2; npm's latest, 8.0.0, is outside it`](#typescript-kept-to-603--700-where-the-newest-is-702-npms-latest-800-is-outside-it)
34
32
  - [`zod: no release within ^4.2.0; kept ^4.2.0`](#zod-no-release-within-420-kept-420)
33
+ - [`@alxia/core: the registry has no release within ^0.3.1 yet; wrote ^0.3.0, the newest of ~0.3.0`](#alxiacore-the-registry-has-no-release-within-031-yet-wrote-030-the-newest-of-030)
35
34
  - [`create-alxia: bun install failed; the files are written.`](#create-alxia-bun-install-failed-the-files-are-written)
36
35
 
37
36
  **After**
38
37
 
39
- - [The `react-router` project's `docker build` fails](#the-react-router-projects-docker-build-fails)
38
+ - [`error: lockfile had changes, but lockfile is frozen`](#error-lockfile-had-changes-but-lockfile-is-frozen)
40
39
  - [The project's `@alxia/*` are older than npm's latest](#the-projects-alxia-are-older-than-npms-latest)
41
40
 
42
41
  ## Before it runs
@@ -148,47 +147,6 @@ project beside it and move the files in.
148
147
 
149
148
  ## Writing the project
150
149
 
151
- ### `create-alxia: create-react-router's … is not what this @alxia/create expects: …`
152
-
153
- **When:** the `react-router` template, after `create-react-router` ran.
154
- The message names the file — `package.json`, `vite.config.ts` or
155
- `bunfig.toml` — and what was expected of it:
156
-
157
- - `it is missing`: no `package.json` or `vite.config.ts`;
158
- - `react-router in its dependencies, and the scripts dev: react-router dev, build: react-router build and a start`;
159
- - `reactRouter() from "@react-router/dev/vite", called once in plugins: [...]`;
160
- - `it already imports @alxia/react-router/vite`;
161
- - `none, and there is one`: a `bunfig.toml` already.
162
-
163
- **Why:** React Router's template changed since this `@alxia/create` was
164
- released, and the edits that add alxia check each file before changing it
165
- rather than write a project that does not start. What was written is
166
- removed: the target directory is emptied when it was there, removed when
167
- it was not. A parent directory the command created for it, as `a/b` for
168
- `a/b/my-site`, stays.
169
-
170
- **Fix:** run the newest `@alxia/create`, whose edits follow the newest
171
- template:
172
-
173
- ```sh
174
- bunx @alxia/create@latest my-site --template react-router
175
- ```
176
-
177
- If that one refuses too, add alxia to React Router's template by hand, as
178
- [`@alxia/react-router`'s README](https://www.npmjs.com/package/@alxia/react-router)
179
- shows (`bun add`, `alxia()` in `vite.config.ts`, `start`), and open an
180
- issue.
181
-
182
- ### `create-alxia: failed: create-react-router exited with 1.`
183
-
184
- **When:** the `react-router` template, when `create-react-router` itself
185
- failed; its own output, just above, says why. Most often the network:
186
- `bunx` could not fetch it, or it could not fetch React Router's template
187
- from GitHub.
188
-
189
- **Fix:** what its output says, then run the command again: what was
190
- written is removed.
191
-
192
150
  ### `create-alxia: failed: …`
193
151
 
194
152
  **When:** any other error while writing the project, with the error's own
@@ -196,7 +154,22 @@ message after `failed:` — most often the file system: `EACCES` writing
196
154
  into a directory the user cannot write to, `ENOSPC` with the disk full.
197
155
 
198
156
  **Fix:** what the message names, then run the command again: what was
199
- written is removed, as above.
157
+ written is removed — the target directory is emptied when it was there,
158
+ removed when it was not. A parent directory the command created for it, as
159
+ `a/b` for `a/b/my-site`, stays.
160
+
161
+ ### `create-alxia: failed: the api template names @alxia/zod at workspace:, which this @alxia/create has no version for`
162
+
163
+ **When:** at once, before anything is written; the template and package
164
+ vary.
165
+
166
+ **Why:** a template names an `@alxia/*` package at `workspace:^`, which
167
+ the command replaces with the version it was published beside, and this
168
+ release has none for that package. It is a broken `@alxia/create`
169
+ release, not your setup.
170
+
171
+ **Fix:** run the previous release, `bunx @alxia/create@<version>`, and
172
+ report it on [GitHub](https://github.com/softistx/alxia/issues).
200
173
 
201
174
  ### `create-alxia: warning: the registry did not answer for …; kept the versions the template ships.`
202
175
 
@@ -211,7 +184,10 @@ that is React Router's, whose TypeScript may be older than alxia accepts.
211
184
 
212
185
  **Fix:** once the registry answers, run the command again in an empty
213
186
  directory, or move the packages named within alxia's ranges by hand:
214
- `bun add -d typescript@^7 vite@^8`. Behind a proxy, check `BUN_CONFIG_REGISTRY` or
187
+ `bun add -d typescript@^7 vite@^8`. The message can name an `@alxia/*`
188
+ package too, on a mirror that does not hold alxia's: the range kept is the
189
+ one this `@alxia/create` was published with, which that mirror cannot
190
+ install either, so let it proxy npmjs.org. Behind a proxy, check `BUN_CONFIG_REGISTRY` or
215
191
  `npm_config_registry`, which the command reads.
216
192
 
217
193
  ### `typescript: kept to ^6.0.3 || ^7.0.0, where the newest is 7.0.2; npm's latest, 8.0.0, is outside it`
@@ -231,11 +207,27 @@ once the major is tested, and the next `@alxia/create` takes it.
231
207
  **When:** a notice: the registry answered for the package, but none of its
232
208
  releases is in the range alxia's packages accept — a registry mirror that
233
209
  holds only some versions, most often. The template's own version is kept.
210
+ An `@alxia/*` package prints it too when the registry holds none of the
211
+ range's minor, not even an older patch.
234
212
 
235
213
  **Fix:** check what the registry holds (`bun pm view zod versions`), let
236
214
  the mirror fetch the missing ones, or write a version within the range by
237
215
  hand after the project is created.
238
216
 
217
+ ### `@alxia/core: the registry has no release within ^0.3.1 yet; wrote ^0.3.0, the newest of ~0.3.0`
218
+
219
+ **When:** a notice, not an error, right after an alxia release: the
220
+ registry lists `@alxia/create`'s new version but not yet the
221
+ `@alxia/core` (or `@alxia/client`, `@alxia/react-router`) published beside
222
+ it. npm can take a few minutes to serve a version everywhere.
223
+
224
+ **Why:** a project written with `^0.3.1` would fail its `bun install` with
225
+ `No version matching "^0.3.1" found`. The command writes the newest release
226
+ of the same minor instead; `^0.3.0` still takes 0.3.1.
227
+
228
+ **Fix:** nothing to do. Once the registry serves the new version,
229
+ `bun update @alxia/core` moves the project to it.
230
+
239
231
  ### `create-alxia: bun install failed; the files are written.`
240
232
 
241
233
  **When:** `bun install` exited non-zero in the new project; its output,
@@ -247,32 +239,35 @@ project is complete; only `node_modules` is missing.
247
239
 
248
240
  ## After
249
241
 
250
- ### The `react-router` project's `docker build` fails
242
+ ### `error: lockfile had changes, but lockfile is frozen`
251
243
 
252
- **Symptom:** `COPY ./package.json package-lock.json /app/` finds no
253
- `package-lock.json`, or the image starts and `bun: not found`.
244
+ **When:** `docker build` in a project stops at
245
+ `RUN bun install --frozen-lockfile` (`react-router`) or
246
+ `RUN bun install --frozen-lockfile --production` (`api`).
254
247
 
255
- **Why:** React Router's `Dockerfile` is kept as its template writes it: on
256
- Node, installed with npm. Once `start` runs `bun build/server/index.js`,
257
- it no longer fits.
248
+ **Why:** the project's `Dockerfile` installs exactly what `bun.lock`
249
+ records, and `package.json` now asks for something it does not: a
250
+ dependency added or changed by hand, without `bun install`, or a `bun.lock` left
251
+ behind in a clone where `package.json` moved on without it.
258
252
 
259
- **Fix:** base it on an `oven/bun` image, install with
260
- `bun install --production`, and make its command
261
- `bun build/server/index.js`, as
262
- [`@alxia/react-router`'s guide](https://github.com/softistx/alxia/blob/develop/packages/react-router/docs/guide.md#deploying)
263
- says.
253
+ **Fix:** run `bun install`, commit `bun.lock`, and build again. The other
254
+ traps of the `react-router` image, a write refused to the `bun` user among them, are in
255
+ [`@alxia/react-router`'s troubleshooting](https://github.com/softistx/alxia/blob/develop/packages/react-router/docs/troubleshooting.md#eacces-permission-denied-open-app).
264
256
 
265
257
  ### The project's `@alxia/*` are older than npm's latest
266
258
 
267
- **Symptom:** a fresh project declares `@alxia/core` at `^0.3.0` while npm
268
- has `0.4.0`.
259
+ **Symptom:** a fresh project declares `@alxia/core` at `^0.3.4` while npm
260
+ has `0.4.0`, and the output said `@alxia/core: kept to ^0.3.1, where the
261
+ newest is 0.3.4; npm's latest, 0.4.0, is outside it`.
269
262
 
270
- **Why:** alxia's packages are written at the versions the `@alxia/create`
271
- that ran was published with ([Versions](guide.md#versions)), and a release
272
- of `@alxia/core` alone does not release a new `@alxia/create`.
263
+ **Why:** alxia's packages move only within the ranges the `@alxia/create`
264
+ that ran was published with ([Versions](guide.md#versions)): a new minor
265
+ is outside them, and a release of `@alxia/core` alone does not release a
266
+ new `@alxia/create`.
273
267
 
274
268
  **Fix:** `bunx @alxia/create@latest` for the newest `@alxia/create`, and in
275
269
  an existing project
276
- `bun add @alxia/core@latest @alxia/client@latest`, reading
270
+ `bun add @alxia/core@latest @alxia/client@latest` (`api`) or
271
+ `bun add @alxia/core@latest @alxia/react-router@latest` (`react-router`), reading
277
272
  [`@alxia/core`'s upgrading page](https://github.com/softistx/alxia/blob/develop/packages/core/docs/upgrading.md)
278
273
  for what a minor changed.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alxia/create",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Start an alxia app: `bun create @alxia` writes an API with Zod, or React Router's official template served by alxia",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -10,6 +10,8 @@
10
10
  "files": [
11
11
  "dist",
12
12
  "docs",
13
+ "templates/api",
14
+ "templates/react-router",
13
15
  "README.md",
14
16
  "package.json",
15
17
  "LICENSE"
@@ -28,7 +30,7 @@
28
30
  },
29
31
  "scripts": {
30
32
  "build": "bun run ../../build.ts",
31
- "test": "bun test src",
33
+ "test": "bun test ./src",
32
34
  "typecheck": "tsc --noEmit"
33
35
  },
34
36
  "alxia": {
@@ -39,7 +41,7 @@
39
41
  "devDependencies": {
40
42
  "@alxia/client": "^0.2.1",
41
43
  "@alxia/core": "^0.3.1",
42
- "@alxia/react-router": "^0.2.0",
44
+ "@alxia/react-router": "^0.3.0",
43
45
  "@types/bun": "^1.4.2",
44
46
  "zod": "^4.6.5"
45
47
  }
@@ -0,0 +1,6 @@
1
+ node_modules
2
+ dist
3
+ .env
4
+ .env.local
5
+ README.md
6
+ **/*.spec.ts
@@ -0,0 +1,3 @@
1
+ # Copy to .env, which Bun loads on every command: bun dev, bun test, bun start.
2
+ PORT=3000
3
+ API_KEY=dev-key
@@ -0,0 +1,22 @@
1
+ # Bun runs the app's TypeScript as it is: no build stage, the image holds
2
+ # src/ and the production dependencies. Pinned to Bun 1, the major alxia
3
+ # supports.
4
+
5
+ # The production dependencies alone, for the final image.
6
+ FROM oven/bun:1 AS production-dependencies
7
+ WORKDIR /app
8
+ COPY package.json bun.lock* bunfig.toml* ./
9
+ RUN bun install --frozen-lockfile --production
10
+
11
+ # The app and its production dependencies, run as Bun's own non-root user
12
+ # with the start script's command, written out so that Bun is the
13
+ # container's process. The server listens on PORT (3000); set API_KEY.
14
+ FROM oven/bun:1
15
+ WORKDIR /app
16
+ ENV NODE_ENV=production
17
+ COPY package.json ./
18
+ COPY --from=production-dependencies /app/node_modules ./node_modules
19
+ COPY src ./src
20
+ USER bun
21
+ EXPOSE 3000
22
+ CMD ["bun", "src/server.ts"]
@@ -0,0 +1,64 @@
1
+ # An alxia API
2
+
3
+ An [alxia](https://github.com/softistx/alxia) app with
4
+ [Zod](https://zod.dev), made with `bun create @alxia`.
5
+
6
+ - `src/app.ts`: the app. `POST /todos` validates its body with Zod, and
7
+ its own hook, `requireKey`, answers 401 without the `x-api-key` header.
8
+ - `src/server.ts`: listens on `PORT`, 3000 by default.
9
+ - `src/app.spec.ts`: `app.request()` and `@alxia/client`, no port.
10
+
11
+ ## Environment
12
+
13
+ Bun loads `.env` on every command. Copy `.env.example` to `.env` to set
14
+ `PORT` and `API_KEY`. Outside development, set `API_KEY`: its default,
15
+ `dev-key`, is for development only.
16
+
17
+ ```sh
18
+ cp .env.example .env
19
+ ```
20
+
21
+ ## Develop
22
+
23
+ ```sh
24
+ bun dev # http://localhost:3000, restarted on every change
25
+ ```
26
+
27
+ ```sh
28
+ curl -X POST localhost:3000/todos \
29
+ -H 'content-type: application/json' -H 'x-api-key: dev-key' \
30
+ -d '{"title":"Write a route"}'
31
+ ```
32
+
33
+ ## Test
34
+
35
+ ```sh
36
+ bun test # src/app.spec.ts: in process, and through the typed client
37
+ bun run typecheck
38
+ ```
39
+
40
+ ## Build
41
+
42
+ Bun runs the TypeScript as it is: `bun start` serves `src/server.ts`, with
43
+ no build step. `bun run build` bundles the server and its dependencies into
44
+ one file, for a host with Bun and no `node_modules`:
45
+
46
+ ```sh
47
+ bun run build # dist/server.js
48
+ bun dist/server.js
49
+ ```
50
+
51
+ ## Docker
52
+
53
+ The `Dockerfile` installs the production dependencies on `oven/bun:1` and
54
+ runs `src/server.ts` as the image's non-root `bun` user. It installs with
55
+ `--frozen-lockfile`, from the `bun.lock` that `bun install` wrote: commit
56
+ it.
57
+
58
+ ```sh
59
+ docker build -t my-api .
60
+ docker run --rm -p 3000:3000 -e API_KEY=change-me my-api
61
+ ```
62
+
63
+ Next: [Getting started](https://github.com/softistx/alxia/blob/develop/packages/core/docs/guide/getting-started.md)
64
+ and the rest of [`@alxia/core`'s guide](https://github.com/softistx/alxia/tree/develop/packages/core/docs).
@@ -0,0 +1,6 @@
1
+ node_modules
2
+ dist
3
+ *.log
4
+ .DS_Store
5
+ .env
6
+ .env.local
@@ -0,0 +1,21 @@
1
+ {
2
+ "name": "my-api",
3
+ "private": true,
4
+ "type": "module",
5
+ "scripts": {
6
+ "dev": "bun --watch src/server.ts",
7
+ "build": "bun build src/server.ts --target=bun --outdir=dist",
8
+ "start": "bun src/server.ts",
9
+ "test": "bun test",
10
+ "typecheck": "tsc --noEmit"
11
+ },
12
+ "dependencies": {
13
+ "@alxia/core": "workspace:^",
14
+ "zod": "^4.2.0"
15
+ },
16
+ "devDependencies": {
17
+ "@alxia/client": "workspace:^",
18
+ "@types/bun": "^1.4.2",
19
+ "typescript": "^6.0.3"
20
+ }
21
+ }
@@ -0,0 +1,46 @@
1
+ import { expect, test } from 'bun:test';
2
+ import { client } from '@alxia/client';
3
+ import { apiKey, app } from './app';
4
+
5
+ const json = { 'content-type': 'application/json', 'x-api-key': apiKey };
6
+
7
+ test('creates a todo from JSON', async () => {
8
+ const response = await app.request('/todos', {
9
+ method: 'POST',
10
+ headers: json,
11
+ body: JSON.stringify({ title: 'Write a route' }),
12
+ });
13
+ expect(response.status).toBe(201);
14
+ expect(await response.json()).toEqual({
15
+ id: expect.any(Number),
16
+ title: 'Write a route',
17
+ done: false,
18
+ });
19
+ });
20
+
21
+ test('refuses an empty title with a 400 naming it', async () => {
22
+ const response = await app.request('/todos', {
23
+ method: 'POST',
24
+ headers: json,
25
+ body: JSON.stringify({ title: '' }),
26
+ });
27
+ expect(response.status).toBe(400);
28
+ expect((await response.json()).issues[0].path).toEqual(['title']);
29
+ });
30
+
31
+ test('the typed client reads each status the route answers', async () => {
32
+ // Given the app itself, the client calls its fetch in process.
33
+ const api = client(app, { headers: { 'x-api-key': apiKey } });
34
+ const created = await api.post('/todos', {
35
+ body: { title: 'Call it typed' },
36
+ });
37
+ if (created.status !== 201) throw new Error(`got ${created.status}`);
38
+ expect(created.data.title).toBe('Call it typed'); // data is the Todo schema's type
39
+
40
+ const anonymous = await client(app).post('/todos', {
41
+ body: { title: 'No key' },
42
+ });
43
+ expect(anonymous.status).toBe(401);
44
+ if (anonymous.status === 401)
45
+ expect(anonymous.data.error).toBe('unauthorized');
46
+ });
@@ -0,0 +1,33 @@
1
+ import { alxia, defineHook } from '@alxia/core';
2
+ import { z } from 'zod';
3
+
4
+ const Todo = z.object({ id: z.number(), title: z.string(), done: z.boolean() });
5
+ const NewTodo = z.object({ title: z.string().min(1) });
6
+
7
+ /** Set API_KEY in the environment: this default is for development. */
8
+ export const apiKey = Bun.env['API_KEY'] ?? 'dev-key';
9
+
10
+ // A hook of the routes it is given to: it answers 401 without the key, and
11
+ // that 401 joins the type of each, so the client reads it.
12
+ const requireKey = defineHook(({ request, reply }) =>
13
+ request.headers.get('x-api-key') === apiKey
14
+ ? undefined
15
+ : reply(401, { error: 'unauthorized' as const }),
16
+ );
17
+
18
+ const todos: z.infer<typeof Todo>[] = [];
19
+
20
+ export const app = alxia()
21
+ .decorate({ todos })
22
+ .post(
23
+ '/todos',
24
+ [requireKey],
25
+ { body: NewTodo, response: { 201: Todo } },
26
+ ({ body, todos, reply }) => {
27
+ const todo = { id: todos.length + 1, title: body.title, done: false };
28
+ todos.push(todo);
29
+ return reply.created(todo);
30
+ },
31
+ );
32
+
33
+ export type App = typeof app;
@@ -0,0 +1,4 @@
1
+ import { app } from './app';
2
+
3
+ const server = app.listen(Number(Bun.env['PORT'] ?? 3000));
4
+ console.log(`listening on ${server.url}`);
@@ -0,0 +1,25 @@
1
+ {
2
+ "compilerOptions": {
3
+ "types": ["bun"],
4
+ "lib": ["ESNext", "DOM"],
5
+ "target": "ESNext",
6
+ "module": "ESNext",
7
+ "moduleDetection": "force",
8
+ "moduleResolution": "bundler",
9
+ "verbatimModuleSyntax": true,
10
+ "noEmit": true,
11
+ "skipLibCheck": true,
12
+ "resolveJsonModule": true,
13
+ "strict": true,
14
+ "noImplicitOverride": true,
15
+ "noImplicitReturns": true,
16
+ "noFallthroughCasesInSwitch": true,
17
+ "noUncheckedIndexedAccess": true,
18
+ "exactOptionalPropertyTypes": true,
19
+ "noPropertyAccessFromIndexSignature": true,
20
+ "noUnusedLocals": true,
21
+ "noUnusedParameters": true,
22
+ "forceConsistentCasingInFileNames": true
23
+ },
24
+ "include": ["src"]
25
+ }
@@ -0,0 +1,4 @@
1
+ .react-router
2
+ build
3
+ node_modules
4
+ README.md
@@ -0,0 +1,29 @@
1
+ # Bun builds the app and runs it: build/server/index.js is alxia's server,
2
+ # which runs on Bun. Pinned to Bun 1, the major alxia supports.
3
+
4
+ # The production dependencies alone, for the final image.
5
+ FROM oven/bun:1 AS production-dependencies
6
+ WORKDIR /app
7
+ COPY package.json bun.lock* bunfig.toml* ./
8
+ RUN bun install --frozen-lockfile --production
9
+
10
+ # Every dependency, then react-router build: build/client and
11
+ # build/server/index.js.
12
+ FROM oven/bun:1 AS build
13
+ WORKDIR /app
14
+ COPY package.json bun.lock* bunfig.toml* ./
15
+ RUN bun install --frozen-lockfile
16
+ COPY . .
17
+ RUN bun run build
18
+
19
+ # The build and the production dependencies, run as Bun's own non-root
20
+ # user. The server listens on PORT (3000) and HOST (0.0.0.0).
21
+ FROM oven/bun:1
22
+ WORKDIR /app
23
+ ENV NODE_ENV=production
24
+ COPY package.json ./
25
+ COPY --from=production-dependencies /app/node_modules ./node_modules
26
+ COPY --from=build /app/build ./build
27
+ USER bun
28
+ EXPOSE 3000
29
+ CMD ["bun", "build/server/index.js"]
@@ -0,0 +1,87 @@
1
+ # Welcome to React Router!
2
+
3
+ A modern, production-ready template for building full-stack React applications using React Router.
4
+
5
+ [![Open in StackBlitz](https://developer.stackblitz.com/img/open_in_stackblitz.svg)](https://stackblitz.com/github/remix-run/react-router-templates/tree/main/default)
6
+
7
+ ## Features
8
+
9
+ - 🚀 Server-side rendering
10
+ - ⚡️ Hot Module Replacement (HMR)
11
+ - 📦 Asset bundling and optimization
12
+ - 🔄 Data loading and mutations
13
+ - 🔒 TypeScript by default
14
+ - 🎉 TailwindCSS for styling
15
+ - 📖 [React Router docs](https://reactrouter.com/)
16
+
17
+ ## Getting Started
18
+
19
+ ### Installation
20
+
21
+ Install the dependencies:
22
+
23
+ ```bash
24
+ bun install
25
+ ```
26
+
27
+ ### Development
28
+
29
+ Start the development server with HMR:
30
+
31
+ ```bash
32
+ bun dev
33
+ ```
34
+
35
+ Your application will be available at `http://localhost:5173`.
36
+
37
+ ## Building for Production
38
+
39
+ Create a production build:
40
+
41
+ ```bash
42
+ bun run build
43
+ ```
44
+
45
+ ## Deployment
46
+
47
+ ### Docker Deployment
48
+
49
+ To build and run using Docker:
50
+
51
+ ```bash
52
+ docker build -t my-app .
53
+
54
+ # Run the container
55
+ docker run -p 3000:3000 my-app
56
+ ```
57
+
58
+ The containerized application can be deployed to any platform that supports Docker, including:
59
+
60
+ - AWS ECS
61
+ - Google Cloud Run
62
+ - Azure Container Apps
63
+ - Digital Ocean App Platform
64
+ - Fly.io
65
+ - Railway
66
+
67
+ ### DIY Deployment
68
+
69
+ The build is production-ready: `bun run start` runs `build/server/index.js` on Bun.
70
+
71
+ Make sure to deploy the output of `bun run build`
72
+
73
+ ```
74
+ ├── package.json
75
+ ├── bun.lock
76
+ ├── build/
77
+ │ ├── client/ # Static assets
78
+ │ └── server/ # Server-side code
79
+ ```
80
+
81
+ ## Styling
82
+
83
+ This template comes with [Tailwind CSS](https://tailwindcss.com/) already configured for a simple default starting experience. You can use whatever CSS framework you prefer.
84
+
85
+ ---
86
+
87
+ Built with ❤️ using React Router.
@@ -0,0 +1,4 @@
1
+ [run]
2
+ # The React Router CLI is a node script: this starts it on Bun, which
3
+ # alxia's server needs, even where a node is installed.
4
+ bun = true
@@ -0,0 +1,15 @@
1
+ @import "tailwindcss";
2
+
3
+ @theme {
4
+ --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif,
5
+ "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
6
+ }
7
+
8
+ html,
9
+ body {
10
+ @apply bg-white dark:bg-gray-950;
11
+
12
+ @media (prefers-color-scheme: dark) {
13
+ color-scheme: dark;
14
+ }
15
+ }