Skip to content

Commit e67b3cb

Browse files
committed
chore: scaffold
- React Router v7 SSR + Hono via react-router-hono-server (Bun runtime) - Tailwind v4 + @datum-cloud/datum-ui theming (system-preference, no toggle) - ThemeProvider + ThemeScript in root.tsx (FOUC-free, suppressed hydration warning) - Type-safe env vars via Zod in app/lib/env.ts - ESLint flat config, Prettier, Lefthook, Renovate, EditorConfig, .tool-versions - Multi-stage Dockerfile (Debian, datum user UID 1001, prod-only deps) - docker-compose.yml for local production image testing - CI workflow: install → lint → typecheck → build → status-check
1 parent 3eb9148 commit e67b3cb

31 files changed

Lines changed: 3110 additions & 0 deletions

.dockerignore

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
node_modules
2+
.react-router
3+
build
4+
.env
5+
.env.local
6+
.env.*.local
7+
.git
8+
.github
9+
.vscode
10+
.cursor
11+
.claude
12+
docs
13+
cypress
14+
*.md
15+
!README.md
16+
Dockerfile
17+
docker-compose.yml
18+
.dockerignore

.editorconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
end_of_line = lf
6+
indent_style = space
7+
indent_size = 2
8+
insert_final_newline = true
9+
trim_trailing_whitespace = true
10+
11+
[*.md]
12+
trim_trailing_whitespace = false

.env.example

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Public (exposed to client via Vite)
2+
VITE_APP_URL=https://agents.datum.net
3+
VITE_MAIN_SITE_URL=https://datum.net
4+
VITE_PORTAL_URL=https://cloud.datum.net
5+
VITE_DOCS_URL=https://docs.datum.net
6+
VITE_GITHUB_ORG_URL=https://github.com/datum-cloud
7+
8+
# Server-only
9+
NODE_ENV=development
10+
PORT=3000
11+
12+
# Optional analytics (v1.1+)
13+
# VITE_PLAUSIBLE_DOMAIN=

.github/workflows/ci.yml

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
name: CI
2+
3+
on:
4+
pull_request:
5+
push:
6+
branches: [ main ]
7+
paths-ignore:
8+
- "docs/**"
9+
- "README.md"
10+
- "agents-datum.md"
11+
release:
12+
types: [ "published" ]
13+
14+
concurrency:
15+
group: ${{ github.workflow }}-${{ github.ref }}
16+
cancel-in-progress: true
17+
18+
env:
19+
BUN_CACHE: ~/.bun/install/cache
20+
21+
jobs:
22+
# ─── Install ────────────────────────────────────────────────
23+
install:
24+
name: Install Dependencies
25+
runs-on: ubuntu-latest
26+
steps:
27+
- uses: actions/checkout@v4
28+
- uses: oven-sh/setup-bun@v2
29+
with: { bun-version: latest }
30+
- uses: actions/cache@v4
31+
id: cache-deps
32+
with:
33+
path: |
34+
${{ env.BUN_CACHE }}
35+
**/node_modules
36+
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
37+
- if: steps.cache-deps.outputs.cache-hit != 'true'
38+
run: bun install --frozen-lockfile
39+
40+
# ─── Quality ────────────────────────────────────────────────
41+
lint:
42+
name: Lint & Format
43+
needs: install
44+
runs-on: ubuntu-latest
45+
steps:
46+
- uses: actions/checkout@v4
47+
- uses: oven-sh/setup-bun@v2
48+
- uses: actions/cache@v4
49+
with:
50+
path: |
51+
${{ env.BUN_CACHE }}
52+
**/node_modules
53+
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
54+
- run: bun run lint && bun run format:check
55+
56+
typecheck:
57+
name: Type Check
58+
needs: install
59+
runs-on: ubuntu-latest
60+
steps:
61+
- uses: actions/checkout@v4
62+
- uses: oven-sh/setup-bun@v2
63+
with: { bun-version: latest }
64+
- uses: actions/cache@v4
65+
with:
66+
path: |
67+
${{ env.BUN_CACHE }}
68+
**/node_modules
69+
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
70+
- run: bun run typecheck
71+
72+
build:
73+
name: Build
74+
needs: [ lint, typecheck ]
75+
runs-on: ubuntu-latest
76+
if: ${{ !failure() && !cancelled() }}
77+
steps:
78+
- uses: actions/checkout@v4
79+
- uses: oven-sh/setup-bun@v2
80+
with: { bun-version: latest }
81+
- uses: actions/cache@v4
82+
with:
83+
path: |
84+
${{ env.BUN_CACHE }}
85+
**/node_modules
86+
key: ${{ runner.os }}-deps-${{ hashFiles('**/bun.lock', '**/package.json') }}
87+
- run: bun run build
88+
89+
# ─── Status Gate ────────────────────────────────────────────
90+
status-check:
91+
name: Final Status Check
92+
needs: [ install, lint, typecheck, build ]
93+
if: always()
94+
runs-on: ubuntu-latest
95+
steps:
96+
- name: Check Workflow Status
97+
run: |
98+
if [[ "${{ contains(needs.*.result, 'failure') }}" == "true" ]]; then
99+
echo "❌ One or more jobs failed"
100+
exit 1
101+
elif [[ "${{ contains(needs.*.result, 'cancelled') }}" == "true" ]]; then
102+
echo "⚠️ One or more jobs were cancelled"
103+
exit 1
104+
else
105+
echo "✅ All jobs passed"
106+
fi

.gitignore

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
node_modules
2+
3+
/.cache
4+
/build
5+
/.react-router
6+
.env
7+
.env.local
8+
.env.*.local
9+
.DS_Store
10+
11+
/.cursor
12+
/.windsurf
13+
/.claude
14+
!/.claude/settings.json
15+
.superpowers/
16+
17+
/cypress/screenshots
18+
/cypress/videos
19+
/cypress/results

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
24.15.0

.prettierignore

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
node_modules
2+
bun.lock
3+
package-lock.json
4+
pnpm-lock.yaml
5+
yarn.lock
6+
Dockerfile
7+
8+
/build
9+
/.react-router
10+
.env
11+
12+
# Project brief — keep author's compact markdown table style intact.
13+
agents-datum.md

.tool-versions

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
nodejs 24.15.0
2+
bun 1.3.13

.vscode/extensions.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"recommendations": [
3+
"esbenp.prettier-vscode",
4+
"dbaeumer.vscode-eslint",
5+
"bradlc.vscode-tailwindcss",
6+
"editorconfig.editorconfig",
7+
"mikestead.dotenv",
8+
"redhat.vscode-yaml",
9+
"yoavbls.pretty-ts-errors"
10+
],
11+
"unwantedRecommendations": []
12+
}

.vscode/settings.json

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
{
2+
// Editor — aligned with .editorconfig + prettier.config.mjs
3+
"editor.formatOnSave": true,
4+
"editor.defaultFormatter": "esbenp.prettier-vscode",
5+
"editor.codeActionsOnSave": {
6+
"source.fixAll.eslint": "explicit"
7+
},
8+
"editor.tabSize": 2,
9+
"editor.insertSpaces": true,
10+
"editor.detectIndentation": false,
11+
12+
// Files — aligned with .editorconfig
13+
"files.eol": "\n",
14+
"files.insertFinalNewline": true,
15+
"files.trimTrailingWhitespace": true,
16+
"files.encoding": "utf8",
17+
18+
// Prettier — pin to our config, ignore .editorconfig (config is the source of truth)
19+
"prettier.requireConfig": true,
20+
"prettier.useEditorConfig": false,
21+
"prettier.configPath": "prettier.config.mjs",
22+
23+
// Per-language formatter routing
24+
"[typescript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
25+
"[typescriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
26+
"[javascript]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
27+
"[javascriptreact]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
28+
"[json]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
29+
"[jsonc]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
30+
"[yaml]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
31+
"[markdown]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
32+
"[css]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
33+
"[html]": { "editor.defaultFormatter": "esbenp.prettier-vscode" },
34+
35+
// ESLint flat config (eslint.config.mjs)
36+
"eslint.useFlatConfig": true,
37+
"eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"],
38+
39+
// TypeScript — use workspace TS, prefer @/* path alias over relative imports
40+
"typescript.tsdk": "node_modules/typescript/lib",
41+
"typescript.enablePromptUseWorkspaceTsdk": true,
42+
"typescript.preferences.importModuleSpecifier": "non-relative",
43+
"javascript.preferences.importModuleSpecifier": "non-relative",
44+
"typescript.updateImportsOnFileMove.enabled": "always",
45+
"javascript.updateImportsOnFileMove.enabled": "always",
46+
47+
// Tailwind v4 — treat .css as Tailwind so @theme, @source, @custom-variant don't error,
48+
// and enable IntelliSense inside cn() and class-variance-authority cva() calls.
49+
"files.associations": {
50+
"*.css": "tailwindcss"
51+
},
52+
"tailwindCSS.experimental.classRegex": [
53+
["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
54+
["cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
55+
["clsx\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
56+
["class:list=\\{([^}]*)\\}", "[\"'`]([^\"'`]*).*?[\"'`]"]
57+
],
58+
"css.lint.unknownAtRules": "ignore",
59+
"scss.lint.unknownAtRules": "ignore",
60+
"less.lint.unknownAtRules": "ignore",
61+
62+
// Emmet for React
63+
"emmet.includeLanguages": {
64+
"typescript": "typescriptreact",
65+
"javascript": "javascriptreact"
66+
},
67+
"emmet.syntaxProfiles": {
68+
"typescript": "jsx",
69+
"javascript": "jsx"
70+
},
71+
72+
// Search/explorer noise
73+
"search.exclude": {
74+
"**/node_modules": true,
75+
"**/build": true,
76+
"**/.react-router": true,
77+
"**/dist": true,
78+
"**/bun.lock": true,
79+
"**/.git": true
80+
},
81+
"files.watcherExclude": {
82+
"**/node_modules/**": true,
83+
"**/build/**": true,
84+
"**/.react-router/**": true
85+
}
86+
}

0 commit comments

Comments
 (0)