create-shibumi 0.0.1 → 0.2.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.
- package/LICENSE +21 -0
- package/README.md +44 -2
- package/package.json +57 -5
- package/scripts/shibumi.lock.json +22 -0
- package/scripts/ship.lock.json +4 -0
- package/src/args.ts +162 -0
- package/src/cli.ts +232 -0
- package/src/create.ts +272 -0
- package/src/templates/blog/README.md +10 -0
- package/src/templates/blog/agents.md +36 -0
- package/src/templates/blog/astro.config.mjs +13 -0
- package/src/templates/blog/bun.lock +787 -0
- package/src/templates/blog/gitignore +4 -0
- package/src/templates/blog/package.json +29 -0
- package/src/templates/blog/public/og-default.png +0 -0
- package/src/templates/blog/public/style.css +147 -0
- package/src/templates/blog/src/components/BaseHead.astro +37 -0
- package/src/templates/blog/src/content/blog/one-vps-is-plenty.md +13 -0
- package/src/templates/blog/src/content/blog/own-your-source.md +13 -0
- package/src/templates/blog/src/content/blog/writing-for-agents.md +13 -0
- package/src/templates/blog/src/content.config.ts +17 -0
- package/src/templates/blog/src/layouts/Base.astro +26 -0
- package/src/templates/blog/src/pages/404.astro +11 -0
- package/src/templates/blog/src/pages/index.astro +30 -0
- package/src/templates/blog/src/pages/llms.txt.ts +29 -0
- package/src/templates/blog/src/pages/posts/[id].astro +31 -0
- package/src/templates/blog/src/pages/posts/[id].md.ts +18 -0
- package/src/templates/blog/src/pages/robots.txt.ts +6 -0
- package/src/templates/blog/src/pages/rss.xml.ts +21 -0
- package/src/templates/blog/src/site.ts +7 -0
- package/src/templates/blog/tsconfig.json +5 -0
- package/src/templates/full-stack/.dockerignore +14 -0
- package/src/templates/full-stack/Dockerfile +23 -0
- package/src/templates/full-stack/README.md +10 -0
- package/src/templates/full-stack/agents.md +60 -0
- package/src/templates/full-stack/bun.lock +225 -0
- package/src/templates/full-stack/compose.yaml +24 -0
- package/src/templates/full-stack/drizzle.config.ts +11 -0
- package/src/templates/full-stack/gitignore +6 -0
- package/src/templates/full-stack/package.json +39 -0
- package/src/templates/full-stack/public/app.js +11 -0
- package/src/templates/full-stack/public/style.css +60 -0
- package/src/templates/full-stack/public/vendor/alpine-csp-3.16.2.min.js +23 -0
- package/src/templates/full-stack/scripts/db.ts +39 -0
- package/src/templates/full-stack/src/app.ts +106 -0
- package/src/templates/full-stack/src/db/index.ts +11 -0
- package/src/templates/full-stack/src/db/lifecycle.ts +214 -0
- package/src/templates/full-stack/src/db/migrations/0001_notes.sql +9 -0
- package/src/templates/full-stack/src/db/schema.ts +13 -0
- package/src/templates/full-stack/src/env.ts +24 -0
- package/src/templates/full-stack/src/server.ts +30 -0
- package/src/templates/full-stack/test/app.test.ts +144 -0
- package/src/templates/full-stack/test/db.test.ts +169 -0
- package/src/templates/full-stack/tsconfig.json +19 -0
- package/src/templates/shibumi.ts +809 -0
- package/src/templates/ship.ts +2056 -0
- package/src/templates/static/README.md +10 -0
- package/src/templates/static/agents.md +31 -0
- package/src/templates/static/gitignore +2 -0
- package/src/templates/static/package.json +17 -0
- package/src/templates/static/public/404.html +15 -0
- package/src/templates/static/public/index.html +16 -0
- package/src/templates/static/public/style.css +50 -0
- package/src/templates/static/scripts/preview.ts +42 -0
- package/src/templates/web/.dockerignore +12 -0
- package/src/templates/web/Dockerfile +24 -0
- package/src/templates/web/README.md +10 -0
- package/src/templates/web/agents.md +54 -0
- package/src/templates/web/bun.lock +45 -0
- package/src/templates/web/compose.yaml +17 -0
- package/src/templates/web/gitignore +5 -0
- package/src/templates/web/package.json +33 -0
- package/src/templates/web/public/app.js +11 -0
- package/src/templates/web/public/style.css +60 -0
- package/src/templates/web/public/vendor/alpine-csp-3.16.2.min.js +23 -0
- package/src/templates/web/src/app.ts +96 -0
- package/src/templates/web/src/env.ts +21 -0
- package/src/templates/web/src/server.ts +23 -0
- package/src/templates/web/test/app.test.ts +137 -0
- package/src/templates/web/tsconfig.json +13 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# Agent Notes
|
|
2
|
+
|
|
3
|
+
Static site generated by create-shibumi. Plain committed files in `public/`, no build step, no framework.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
bun dev # preview public/ locally (scripts/preview.ts, dev only)
|
|
9
|
+
bun ship:setup # configure the deploy target (preconfigured: static, public/)
|
|
10
|
+
bun ship # verify public/, build the static image, upload, deploy
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Routes and templates
|
|
14
|
+
|
|
15
|
+
Every file in `public/` is a route. `public/index.html` is `/`, `public/404.html` answers unknown paths. There are no templates or generators; add a generator later by pointing its output directory at `bun ship:setup --static --output-dir <dir> --build-script <script>`.
|
|
16
|
+
|
|
17
|
+
## Trust boundaries and validation
|
|
18
|
+
|
|
19
|
+
Before every image build, Ship verifies the output directory from a clean checkout of the committed HEAD: inside the project root, non-empty, `index.html` present, no symlinks. The image contains only that verified output plus a pinned BusyBox httpd running as an unprivileged user; there is no runtime code in production.
|
|
20
|
+
|
|
21
|
+
## Database
|
|
22
|
+
|
|
23
|
+
None. Static files only.
|
|
24
|
+
|
|
25
|
+
## Files Ship generates
|
|
26
|
+
|
|
27
|
+
`bun ship:setup` writes `Dockerfile`, `compose.yaml`, `.dockerignore`, and `shibumi-server.json` (all committed); static settings live as `dev.shibumistack.static.*` labels in `compose.yaml`. SSH targets stay in `~/.config/shibumi/config.json`, never committed.
|
|
28
|
+
|
|
29
|
+
## Checks required before commit
|
|
30
|
+
|
|
31
|
+
`public/index.html` must exist; without a build script, `public/` must be committed or `bun ship` refuses to package it.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "shibumi-static-site",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "bun scripts/preview.ts",
|
|
8
|
+
"ship": "bun scripts/ship.ts",
|
|
9
|
+
"ship:setup": "bun scripts/ship.ts --setup --static --output-dir public",
|
|
10
|
+
"ship:update": "bun scripts/ship.ts --update",
|
|
11
|
+
"ship:status": "bun scripts/ship.ts --status",
|
|
12
|
+
"ship:logs": "bun scripts/ship.ts --logs"
|
|
13
|
+
},
|
|
14
|
+
"engines": {
|
|
15
|
+
"bun": ">=1.4.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Not found</title>
|
|
7
|
+
<link rel="stylesheet" href="/style.css" />
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<main>
|
|
11
|
+
<h1>Not found.</h1>
|
|
12
|
+
<p><a href="/">Back to the start.</a></p>
|
|
13
|
+
</main>
|
|
14
|
+
</body>
|
|
15
|
+
</html>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
6
|
+
<title>Shibumi static site</title>
|
|
7
|
+
<link rel="stylesheet" href="/style.css" />
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<main>
|
|
11
|
+
<h1>It ships.</h1>
|
|
12
|
+
<p>To get started, open <code>public/index.html</code>; this page is that file. Edit, commit, run <code>bun ship</code>.</p>
|
|
13
|
+
<p>Using Astro, Jekyll, Eleventy, or another generator? Point its output here, or run <code>bun ship:setup</code> in that project instead; the Ship client packages any verified build directory.</p>
|
|
14
|
+
</main>
|
|
15
|
+
</body>
|
|
16
|
+
</html>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
color-scheme: light dark;
|
|
3
|
+
--paper: #f5f0e4;
|
|
4
|
+
--ink: #1b130f;
|
|
5
|
+
--accent: #e95f19;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
@media (prefers-color-scheme: dark) {
|
|
9
|
+
:root {
|
|
10
|
+
--paper: #1b130f;
|
|
11
|
+
--ink: #f5f0e4;
|
|
12
|
+
--accent: #ff8648;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
margin: 0;
|
|
18
|
+
background: var(--paper);
|
|
19
|
+
color: var(--ink);
|
|
20
|
+
font-family: system-ui, sans-serif;
|
|
21
|
+
font-size: 1.125rem;
|
|
22
|
+
line-height: 1.6;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
main {
|
|
26
|
+
max-width: 40rem;
|
|
27
|
+
margin: 0 auto;
|
|
28
|
+
padding: 4rem 1.5rem;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
h1 {
|
|
32
|
+
font-family: Georgia, "Times New Roman", serif;
|
|
33
|
+
font-weight: 500;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
a {
|
|
37
|
+
color: inherit;
|
|
38
|
+
text-decoration: underline;
|
|
39
|
+
text-decoration-color: color-mix(in srgb, var(--accent) 30%, transparent);
|
|
40
|
+
text-underline-offset: 0.18em;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
a:hover {
|
|
44
|
+
text-decoration-color: var(--accent);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
code {
|
|
48
|
+
font-family: ui-monospace, monospace;
|
|
49
|
+
font-size: 0.9em;
|
|
50
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Local preview of public/. Production serving is the pinned static image
|
|
2
|
+
// that bun ship builds; this file never ships.
|
|
3
|
+
import { realpathSync } from "node:fs";
|
|
4
|
+
import { join, normalize } from "node:path";
|
|
5
|
+
|
|
6
|
+
const ROOT = join(import.meta.dir, "..", "public");
|
|
7
|
+
function withHeaders(res: Response): Response {
|
|
8
|
+
res.headers.set("X-Content-Type-Options", "nosniff");
|
|
9
|
+
res.headers.set("X-Frame-Options", "DENY");
|
|
10
|
+
res.headers.set("Referrer-Policy", "strict-origin-when-cross-origin");
|
|
11
|
+
return res;
|
|
12
|
+
}
|
|
13
|
+
const server = Bun.serve({
|
|
14
|
+
port: Number(process.env.PORT) || 4173,
|
|
15
|
+
async fetch(request) {
|
|
16
|
+
if (request.method !== "GET" && request.method !== "HEAD") return withHeaders(new Response("Not found", { status: 404 }));
|
|
17
|
+
let pathname;
|
|
18
|
+
try {
|
|
19
|
+
pathname = decodeURIComponent(new URL(request.url).pathname);
|
|
20
|
+
} catch {
|
|
21
|
+
return withHeaders(new Response("Bad request", { status: 400 }));
|
|
22
|
+
}
|
|
23
|
+
const safe = normalize(pathname).replaceAll("\\", "/");
|
|
24
|
+
if (safe.includes("..")) return withHeaders(new Response("Not found", { status: 404 }));
|
|
25
|
+
const candidate = safe.endsWith("/") ? join(ROOT, safe, "index.html") : join(ROOT, safe);
|
|
26
|
+
if (!candidate.startsWith(ROOT)) return withHeaders(new Response("Not found", { status: 404 }));
|
|
27
|
+
let resolved;
|
|
28
|
+
try {
|
|
29
|
+
resolved = realpathSync(candidate);
|
|
30
|
+
} catch {
|
|
31
|
+
resolved = undefined;
|
|
32
|
+
}
|
|
33
|
+
// realpath containment: a symlink inside public/ must not escape it.
|
|
34
|
+
if (resolved && (resolved === realpathSync(ROOT) || resolved.startsWith(realpathSync(ROOT) + "/"))) {
|
|
35
|
+
const file = Bun.file(resolved);
|
|
36
|
+
if (await file.exists()) return withHeaders(new Response(file));
|
|
37
|
+
}
|
|
38
|
+
const notFound = Bun.file(join(ROOT, "404.html"));
|
|
39
|
+
return withHeaders(new Response((await notFound.exists()) ? notFound : "Not found", { status: 404 }));
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
console.log(`Previewing public/ on http://localhost:${server.port}`);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
FROM oven/bun:1-alpine AS deps
|
|
2
|
+
WORKDIR /app
|
|
3
|
+
COPY package.json bun.lock ./
|
|
4
|
+
RUN bun install --frozen-lockfile --production
|
|
5
|
+
|
|
6
|
+
# Major-pinned: minors and patches flow, a future Bun 2 cannot break deploys.
|
|
7
|
+
FROM oven/bun:1-alpine AS build
|
|
8
|
+
WORKDIR /app
|
|
9
|
+
COPY package.json bun.lock ./
|
|
10
|
+
RUN bun install --frozen-lockfile
|
|
11
|
+
COPY tsconfig.json ./
|
|
12
|
+
COPY src ./src
|
|
13
|
+
RUN bun run build
|
|
14
|
+
|
|
15
|
+
FROM oven/bun:1-alpine
|
|
16
|
+
WORKDIR /app
|
|
17
|
+
COPY --from=build /app/dist ./dist
|
|
18
|
+
COPY public ./public
|
|
19
|
+
COPY package.json ./
|
|
20
|
+
# Production mode: extensions gate security behavior on this. Never unset it.
|
|
21
|
+
ENV NODE_ENV=production
|
|
22
|
+
USER bun
|
|
23
|
+
EXPOSE 3000
|
|
24
|
+
CMD ["bun", "dist/server.js"]
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# Agent Notes
|
|
2
|
+
|
|
3
|
+
Bun web app generated by create-shibumi. Hono routes, Zod validation, Alpine behavior, no framework runtime. All source is owned by this project; edit anything.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
bun dev # Ship wrapper starts hot reload on the configured app port
|
|
9
|
+
bun dev:app # plain watch mode on PORT (default 3000)
|
|
10
|
+
bun test # route and security-header tests
|
|
11
|
+
bun run check # TypeScript check
|
|
12
|
+
bun run build # bundle src/server.ts to dist/server.js
|
|
13
|
+
bun ship # build image, upload, deploy via shibumi-server
|
|
14
|
+
bun ship:setup # configure the deploy target
|
|
15
|
+
bun run shibumi add <name> # install an extension (auth, email); --dry-run previews
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Routes and templates
|
|
19
|
+
|
|
20
|
+
- `src/app.ts`: all routes and the HTML page. `src/server.ts`: startup and graceful shutdown. `src/env.ts`: environment schema.
|
|
21
|
+
- Static assets under `public/`, served at `/public/*`.
|
|
22
|
+
- Alpine is the vendored CSP build (`public/vendor/alpine-csp-*.min.js`): register components with `Alpine.data()` in `public/app.js` and reference methods by name in markup; inline expressions do not evaluate.
|
|
23
|
+
|
|
24
|
+
## Trust boundaries and validation
|
|
25
|
+
|
|
26
|
+
- Every environment variable goes through the Zod schema in `src/env.ts`; the app never reads `process.env` elsewhere.
|
|
27
|
+
- Every request input (query, params, body) is validated with Zod at the route before use; `/api/hello` is the pattern.
|
|
28
|
+
- The response header set in `SECURITY_HEADERS` (`src/app.ts`) is asserted verbatim by tests on success, error, API, and static responses; change both together. The CSP allows no inline or eval'd script.
|
|
29
|
+
- Add no unauthenticated mutation endpoints (POST/PUT/PATCH/DELETE); tests fail if a route registers one. Add authentication first.
|
|
30
|
+
|
|
31
|
+
## Database
|
|
32
|
+
|
|
33
|
+
This template has no database. The full-stack template adds Drizzle and SQLite under `/data`.
|
|
34
|
+
|
|
35
|
+
## Files Ship generates
|
|
36
|
+
|
|
37
|
+
`bun ship:setup` writes `shibumi-server.json` (committed) and stores SSH targets in `~/.config/shibumi/config.json` (never committed). `scripts/ship.ts` is owned source, vendored at generation time; update it with `bun ship:update`.
|
|
38
|
+
|
|
39
|
+
## Secrets and runtime config
|
|
40
|
+
|
|
41
|
+
Set production env vars (secrets, per-deploy config) on the server, never in git or the image:
|
|
42
|
+
|
|
43
|
+
```sh
|
|
44
|
+
bun ship:env set KEY=VALUE # one or more
|
|
45
|
+
bun ship:env import .env.production # bulk from a local file
|
|
46
|
+
bun ship:env list # names only
|
|
47
|
+
bun ship:env rm KEY
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Values are stored per-app on the server and injected at deploy; run `bun ship` to apply. Non-secret tunables that belong in git live in `src/config/*.yaml` instead.
|
|
51
|
+
|
|
52
|
+
## Checks required before commit
|
|
53
|
+
|
|
54
|
+
`bun test` and `bun run check` must pass. The Docker image copies only `dist/`, `public/`, and `package.json`; if you add runtime files elsewhere, update the Dockerfile and `.dockerignore` together.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"lockfileVersion": 2,
|
|
3
|
+
"configVersion": 1,
|
|
4
|
+
"workspaces": {
|
|
5
|
+
"": {
|
|
6
|
+
"name": "shibumi-web-app",
|
|
7
|
+
"dependencies": {
|
|
8
|
+
"hono": "4.13.3",
|
|
9
|
+
"zod": "4.4.3",
|
|
10
|
+
},
|
|
11
|
+
"devDependencies": {
|
|
12
|
+
"@clack/prompts": "1.7.0",
|
|
13
|
+
"@types/bun": "latest",
|
|
14
|
+
"typescript": "5.9.2",
|
|
15
|
+
},
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
"packages": {
|
|
19
|
+
"@clack/core": ["@clack/core@1.4.3", "", { "dependencies": { "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-/kr3UWNtdJfxZtPgDqUOmG2pvwlmcLGheex5yiZKdwbzZJxhV+HMNR9QNmyY5cGwTNV6LrR7Jtp+KjhUAP1qBQ=="],
|
|
20
|
+
|
|
21
|
+
"@clack/prompts": ["@clack/prompts@1.7.0", "", { "dependencies": { "@clack/core": "1.4.3", "fast-string-width": "^3.0.2", "fast-wrap-ansi": "^0.2.0", "sisteransi": "^1.0.5" } }, "sha512-y7/yvZ2TPAnR9+jnc00klvNNLkJiXFFrQA/hlLCcxA9a2A4zQIOimyFQ9XfwYKiGD1fb5GY8vbKIIgO8d5Tb2A=="],
|
|
22
|
+
|
|
23
|
+
"@types/bun": ["@types/bun@1.4.0", "", { "dependencies": { "bun-types": "1.4.0" } }, "sha512-K+lZULY23vRgK/CfTjFIV+tyifaNdSMlPh9j+6mQ/cLfpOznLyAuzgV/JQysyECpkBQLVMSyvjlr2fBUSA9wFQ=="],
|
|
24
|
+
|
|
25
|
+
"@types/node": ["@types/node@26.2.0", "", { "dependencies": { "undici-types": "~8.3.0" } }, "sha512-5IviulTZeRNp2vAJ514cc/HUlY5nZ9fCbq9DMyC52BrhFZACo3nI0R7qBxhQmo/d27NFe96ur/b7Wwxklda+kg=="],
|
|
26
|
+
|
|
27
|
+
"bun-types": ["bun-types@1.4.0", "", { "dependencies": { "@types/node": "*" } }, "sha512-iIKw23BspnQQYd3prITOBxeUsxBHnwzX6YJfGMuNOZzeNcMmVqzIIVGRm1l69ogaPQmb4wB6BN8mA5bE9YuC5Q=="],
|
|
28
|
+
|
|
29
|
+
"fast-string-truncated-width": ["fast-string-truncated-width@3.0.3", "", {}, "sha512-0jjjIEL6+0jag3l2XWWizO64/aZVtpiGE3t0Zgqxv0DPuxiMjvB3M24fCyhZUO4KomJQPj3LTSUnDP3GpdwC0g=="],
|
|
30
|
+
|
|
31
|
+
"fast-string-width": ["fast-string-width@3.0.2", "", { "dependencies": { "fast-string-truncated-width": "^3.0.2" } }, "sha512-gX8LrtNEI5hq8DVUfRQMbr5lpaS4nMIWV+7XEbXk2b8kiQIizgnlr12B4dA3ZEx3308ze0O4Q1R+cHts8kyUJg=="],
|
|
32
|
+
|
|
33
|
+
"fast-wrap-ansi": ["fast-wrap-ansi@0.2.2", "", { "dependencies": { "fast-string-width": "^3.0.2" } }, "sha512-7F2Fl+TjRSenLqlU3UjSH0iyqopqoZIu7eZVpEirP2g1GtWa2G/ecEmBdgz31+Mxr+ELclgg6sokpSFIQiZ02Q=="],
|
|
34
|
+
|
|
35
|
+
"hono": ["hono@4.13.3", "", {}, "sha512-r8AO2mYHoLxSHkgafNeC/BXyb2vWRxD3jem4Ts+ptav8oTG5FIRifAjuJEmZI4bSvvc2ns0GxmIYiZnHqN3mMw=="],
|
|
36
|
+
|
|
37
|
+
"sisteransi": ["sisteransi@1.0.5", "", {}, "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="],
|
|
38
|
+
|
|
39
|
+
"typescript": ["typescript@5.9.2", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A=="],
|
|
40
|
+
|
|
41
|
+
"undici-types": ["undici-types@8.3.0", "", {}, "sha512-j375ScV60dom+YkPFIfTLcOiPxkN/buHz5GobjLhixFuANaNs3C9l4GmrWqejgXWJ7BbJcFYpTEUkS1Ge8bpZQ=="],
|
|
42
|
+
|
|
43
|
+
"zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="],
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
services:
|
|
2
|
+
app:
|
|
3
|
+
build: .
|
|
4
|
+
ports:
|
|
5
|
+
- "127.0.0.1:${SHIBUMI_PORT:-9001}:3000"
|
|
6
|
+
restart: unless-stopped
|
|
7
|
+
healthcheck:
|
|
8
|
+
test: ["CMD", "wget", "-q", "-T", "5", "-O", "/dev/null", "http://127.0.0.1:3000/healthz"]
|
|
9
|
+
interval: 60s
|
|
10
|
+
timeout: 10s
|
|
11
|
+
retries: 3
|
|
12
|
+
start_period: 10s
|
|
13
|
+
deploy:
|
|
14
|
+
resources:
|
|
15
|
+
limits:
|
|
16
|
+
cpus: "1.0"
|
|
17
|
+
memory: 512M
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "shibumi-web-app",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "bun scripts/ship.ts --dev",
|
|
8
|
+
"dev:app": "bun --watch src/server.ts",
|
|
9
|
+
"start": "bun dist/server.js",
|
|
10
|
+
"build": "bun build src/server.ts --outdir dist --target bun",
|
|
11
|
+
"test": "bun test",
|
|
12
|
+
"check": "tsc --noEmit",
|
|
13
|
+
"ship": "bun scripts/ship.ts",
|
|
14
|
+
"ship:setup": "bun scripts/ship.ts --setup",
|
|
15
|
+
"ship:update": "bun scripts/ship.ts --update",
|
|
16
|
+
"ship:status": "bun scripts/ship.ts --status",
|
|
17
|
+
"ship:logs": "bun scripts/ship.ts --logs",
|
|
18
|
+
"ship:env": "bun scripts/ship.ts --env",
|
|
19
|
+
"shibumi": "bun scripts/shibumi.ts"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"hono": "4.13.3",
|
|
23
|
+
"zod": "4.4.3"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@clack/prompts": "1.7.0",
|
|
27
|
+
"@types/bun": "1.4.0",
|
|
28
|
+
"typescript": "5.9.2"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"bun": ">=1.4.0"
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// Alpine behavior lives here. The vendored build is the CSP-safe variant:
|
|
2
|
+
// register components with Alpine.data() and reference methods by name in
|
|
3
|
+
// markup; inline expressions are not evaluated.
|
|
4
|
+
document.addEventListener("alpine:init", () => {
|
|
5
|
+
Alpine.data("counter", () => ({
|
|
6
|
+
count: 0,
|
|
7
|
+
inc() {
|
|
8
|
+
this.count++;
|
|
9
|
+
},
|
|
10
|
+
}));
|
|
11
|
+
});
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
color-scheme: light dark;
|
|
3
|
+
--paper: #f5f0e4;
|
|
4
|
+
--ink: #1b130f;
|
|
5
|
+
--accent: #e95f19;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
@media (prefers-color-scheme: dark) {
|
|
9
|
+
:root {
|
|
10
|
+
--paper: #1b130f;
|
|
11
|
+
--ink: #f5f0e4;
|
|
12
|
+
--accent: #ff8648;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
body {
|
|
17
|
+
margin: 0;
|
|
18
|
+
background: var(--paper);
|
|
19
|
+
color: var(--ink);
|
|
20
|
+
font-family: system-ui, sans-serif;
|
|
21
|
+
font-size: 1.125rem;
|
|
22
|
+
line-height: 1.6;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
main {
|
|
26
|
+
max-width: 40rem;
|
|
27
|
+
margin: 0 auto;
|
|
28
|
+
padding: 4rem 1.5rem;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
h1 {
|
|
32
|
+
font-family: Georgia, "Times New Roman", serif;
|
|
33
|
+
font-weight: 500;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
a {
|
|
37
|
+
color: inherit;
|
|
38
|
+
text-decoration: underline;
|
|
39
|
+
text-decoration-color: color-mix(in srgb, var(--accent) 30%, transparent);
|
|
40
|
+
text-underline-offset: 0.18em;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
a:hover {
|
|
44
|
+
text-decoration-color: var(--accent);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
button {
|
|
48
|
+
font: inherit;
|
|
49
|
+
padding: 0.4rem 1rem;
|
|
50
|
+
border: 1px solid var(--ink);
|
|
51
|
+
background: transparent;
|
|
52
|
+
color: inherit;
|
|
53
|
+
border-radius: 4px;
|
|
54
|
+
cursor: pointer;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
output {
|
|
58
|
+
margin-left: 0.75rem;
|
|
59
|
+
font-variant-numeric: tabular-nums;
|
|
60
|
+
}
|