create-appystack 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.
- package/README.md +54 -0
- package/bin/index.js +243 -0
- package/package.json +39 -0
- package/template/.claude/skills/recipe/SKILL.md +71 -0
- package/template/.claude/skills/recipe/domains/care-provider-operations.md +185 -0
- package/template/.claude/skills/recipe/domains/youtube-launch-optimizer.md +154 -0
- package/template/.claude/skills/recipe/references/file-crud.md +295 -0
- package/template/.claude/skills/recipe/references/nav-shell.md +233 -0
- package/template/.dockerignore +39 -0
- package/template/.env.example +13 -0
- package/template/.github/workflows/ci.yml +43 -0
- package/template/.husky/pre-commit +1 -0
- package/template/.prettierignore +7 -0
- package/template/.prettierrc +8 -0
- package/template/.vscode/launch.json +59 -0
- package/template/CLAUDE.md +114 -0
- package/template/Dockerfile +56 -0
- package/template/README.md +219 -0
- package/template/client/index.html +13 -0
- package/template/client/package.json +43 -0
- package/template/client/src/App.test.tsx +67 -0
- package/template/client/src/App.tsx +11 -0
- package/template/client/src/components/ErrorFallback.test.tsx +64 -0
- package/template/client/src/components/ErrorFallback.tsx +18 -0
- package/template/client/src/config/env.test.ts +64 -0
- package/template/client/src/config/env.ts +34 -0
- package/template/client/src/contexts/AppContext.test.tsx +81 -0
- package/template/client/src/contexts/AppContext.tsx +52 -0
- package/template/client/src/demo/ContactForm.test.tsx +97 -0
- package/template/client/src/demo/ContactForm.tsx +100 -0
- package/template/client/src/demo/DemoPage.tsx +56 -0
- package/template/client/src/demo/SocketDemo.test.tsx +160 -0
- package/template/client/src/demo/SocketDemo.tsx +65 -0
- package/template/client/src/demo/StatusGrid.test.tsx +181 -0
- package/template/client/src/demo/StatusGrid.tsx +77 -0
- package/template/client/src/demo/TechStackDisplay.test.tsx +63 -0
- package/template/client/src/demo/TechStackDisplay.tsx +75 -0
- package/template/client/src/hooks/useServerStatus.test.ts +133 -0
- package/template/client/src/hooks/useServerStatus.ts +67 -0
- package/template/client/src/hooks/useSocket.test.ts +152 -0
- package/template/client/src/hooks/useSocket.ts +43 -0
- package/template/client/src/lib/utils.test.ts +33 -0
- package/template/client/src/lib/utils.ts +14 -0
- package/template/client/src/main.test.tsx +113 -0
- package/template/client/src/main.tsx +14 -0
- package/template/client/src/pages/LandingPage.test.tsx +30 -0
- package/template/client/src/pages/LandingPage.tsx +29 -0
- package/template/client/src/styles/index.css +50 -0
- package/template/client/src/test/msw/browser.ts +4 -0
- package/template/client/src/test/msw/handlers.ts +12 -0
- package/template/client/src/test/msw/msw-example.test.ts +69 -0
- package/template/client/src/test/msw/server.ts +14 -0
- package/template/client/src/test/setup.ts +10 -0
- package/template/client/src/utils/api.test.ts +79 -0
- package/template/client/src/utils/api.ts +42 -0
- package/template/client/src/vite-env.d.ts +13 -0
- package/template/client/tsconfig.json +17 -0
- package/template/client/vite.config.ts +38 -0
- package/template/client/vitest.config.ts +36 -0
- package/template/docker-compose.yml +19 -0
- package/template/e2e/smoke.test.ts +95 -0
- package/template/e2e/socket.test.ts +96 -0
- package/template/eslint.config.js +2 -0
- package/template/package.json +50 -0
- package/template/playwright.config.ts +14 -0
- package/template/scripts/customize.ts +175 -0
- package/template/server/nodemon.json +5 -0
- package/template/server/package.json +45 -0
- package/template/server/src/app.test.ts +103 -0
- package/template/server/src/config/env.test.ts +97 -0
- package/template/server/src/config/env.ts +29 -0
- package/template/server/src/config/logger.test.ts +58 -0
- package/template/server/src/config/logger.ts +17 -0
- package/template/server/src/helpers/response.test.ts +53 -0
- package/template/server/src/helpers/response.ts +17 -0
- package/template/server/src/index.ts +118 -0
- package/template/server/src/middleware/errorHandler.test.ts +84 -0
- package/template/server/src/middleware/errorHandler.ts +27 -0
- package/template/server/src/middleware/rateLimiter.test.ts +68 -0
- package/template/server/src/middleware/rateLimiter.ts +8 -0
- package/template/server/src/middleware/requestLogger.test.ts +111 -0
- package/template/server/src/middleware/requestLogger.ts +17 -0
- package/template/server/src/middleware/validate.test.ts +213 -0
- package/template/server/src/middleware/validate.ts +23 -0
- package/template/server/src/routes/health.test.ts +17 -0
- package/template/server/src/routes/health.ts +12 -0
- package/template/server/src/routes/info.test.ts +20 -0
- package/template/server/src/routes/info.ts +19 -0
- package/template/server/src/shared.test.ts +53 -0
- package/template/server/src/shutdown.test.ts +98 -0
- package/template/server/src/socket.test.ts +185 -0
- package/template/server/src/static.test.ts +166 -0
- package/template/server/tsconfig.json +16 -0
- package/template/server/vitest.config.ts +22 -0
- package/template/shared/package.json +19 -0
- package/template/shared/src/constants.ts +11 -0
- package/template/shared/src/index.ts +8 -0
- package/template/shared/src/types.ts +33 -0
- package/template/shared/tsconfig.json +10 -0
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Dependencies
|
|
2
|
+
node_modules
|
|
3
|
+
**/node_modules
|
|
4
|
+
|
|
5
|
+
# Build output
|
|
6
|
+
dist
|
|
7
|
+
**/dist
|
|
8
|
+
|
|
9
|
+
# Test coverage
|
|
10
|
+
coverage
|
|
11
|
+
**/coverage
|
|
12
|
+
|
|
13
|
+
# Git
|
|
14
|
+
.git
|
|
15
|
+
.gitignore
|
|
16
|
+
|
|
17
|
+
# Editor
|
|
18
|
+
.vscode
|
|
19
|
+
.idea
|
|
20
|
+
*.swp
|
|
21
|
+
*.swo
|
|
22
|
+
|
|
23
|
+
# Environment files (inject at runtime)
|
|
24
|
+
.env
|
|
25
|
+
.env.local
|
|
26
|
+
.env.*.local
|
|
27
|
+
|
|
28
|
+
# Playwright / E2E
|
|
29
|
+
e2e
|
|
30
|
+
test-results
|
|
31
|
+
playwright-report
|
|
32
|
+
|
|
33
|
+
# OS
|
|
34
|
+
.DS_Store
|
|
35
|
+
Thumbs.db
|
|
36
|
+
|
|
37
|
+
# Logs
|
|
38
|
+
*.log
|
|
39
|
+
npm-debug.log*
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Server
|
|
2
|
+
# Runtime environment: development | production | test
|
|
3
|
+
NODE_ENV=development
|
|
4
|
+
# Port the Express server listens on
|
|
5
|
+
PORT=5501
|
|
6
|
+
# Origin the Vite dev server runs on (used for CORS)
|
|
7
|
+
CLIENT_URL=http://localhost:5500
|
|
8
|
+
|
|
9
|
+
# Client (Vite — prefix VITE_ required)
|
|
10
|
+
# Base URL for API requests. Leave empty to use the Vite dev proxy.
|
|
11
|
+
VITE_API_URL=
|
|
12
|
+
# Application display name shown in the UI
|
|
13
|
+
VITE_APP_NAME=AppyStack
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
build-and-test:
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
|
|
17
|
+
strategy:
|
|
18
|
+
matrix:
|
|
19
|
+
node-version: [20.x]
|
|
20
|
+
|
|
21
|
+
steps:
|
|
22
|
+
- uses: actions/checkout@v4
|
|
23
|
+
|
|
24
|
+
- name: Use Node.js ${{ matrix.node-version }}
|
|
25
|
+
uses: actions/setup-node@v4
|
|
26
|
+
with:
|
|
27
|
+
node-version: ${{ matrix.node-version }}
|
|
28
|
+
cache: npm
|
|
29
|
+
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: npm ci
|
|
32
|
+
|
|
33
|
+
- name: Lint
|
|
34
|
+
run: npm run lint
|
|
35
|
+
|
|
36
|
+
- name: Format check
|
|
37
|
+
run: npm run format:check
|
|
38
|
+
|
|
39
|
+
- name: Build
|
|
40
|
+
run: npm run build
|
|
41
|
+
|
|
42
|
+
- name: Test
|
|
43
|
+
run: npm test
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
npx lint-staged
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "0.2.0",
|
|
3
|
+
"configurations": [
|
|
4
|
+
{
|
|
5
|
+
"name": "Debug Server",
|
|
6
|
+
"type": "node",
|
|
7
|
+
"request": "launch",
|
|
8
|
+
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/tsx",
|
|
9
|
+
"args": ["${workspaceFolder}/server/src/index.ts"],
|
|
10
|
+
"cwd": "${workspaceFolder}/server",
|
|
11
|
+
"env": {
|
|
12
|
+
"NODE_ENV": "development",
|
|
13
|
+
"PORT": "5501",
|
|
14
|
+
"CLIENT_URL": "http://localhost:5500"
|
|
15
|
+
},
|
|
16
|
+
"sourceMaps": true,
|
|
17
|
+
"outFiles": ["${workspaceFolder}/server/dist/**/*.js"],
|
|
18
|
+
"skipFiles": ["<node_internals>/**"]
|
|
19
|
+
},
|
|
20
|
+
{
|
|
21
|
+
"name": "Attach to Server",
|
|
22
|
+
"type": "node",
|
|
23
|
+
"request": "attach",
|
|
24
|
+
"port": 9229,
|
|
25
|
+
"restart": true,
|
|
26
|
+
"sourceMaps": true,
|
|
27
|
+
"outFiles": ["${workspaceFolder}/server/dist/**/*.js"],
|
|
28
|
+
"skipFiles": ["<node_internals>/**"]
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
"name": "Debug Client",
|
|
32
|
+
"type": "chrome",
|
|
33
|
+
"request": "launch",
|
|
34
|
+
"url": "http://localhost:5500",
|
|
35
|
+
"webRoot": "${workspaceFolder}/client/src",
|
|
36
|
+
"sourceMaps": true,
|
|
37
|
+
"sourceMapPathOverrides": {
|
|
38
|
+
"webpack:///./src/*": "${webRoot}/*"
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"name": "Debug Current Test",
|
|
43
|
+
"type": "node",
|
|
44
|
+
"request": "launch",
|
|
45
|
+
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/vitest",
|
|
46
|
+
"args": ["run", "${relativeFile}"],
|
|
47
|
+
"cwd": "${workspaceFolder}",
|
|
48
|
+
"sourceMaps": true,
|
|
49
|
+
"skipFiles": ["<node_internals>/**"],
|
|
50
|
+
"smartStep": true
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"compounds": [
|
|
54
|
+
{
|
|
55
|
+
"name": "Full Stack",
|
|
56
|
+
"configurations": ["Debug Server", "Debug Client"]
|
|
57
|
+
}
|
|
58
|
+
]
|
|
59
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
AI agent context for the AppyStack template project.
|
|
4
|
+
|
|
5
|
+
## What Is This?
|
|
6
|
+
|
|
7
|
+
A RVETS stack boilerplate (React, Vite, Express, TypeScript, Socket.io) structured as an npm workspaces monorepo with three packages: client, server, and shared.
|
|
8
|
+
|
|
9
|
+
## Architecture
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
client (React 19 + Vite 7 + TailwindCSS v4) → port 5500
|
|
13
|
+
↕ proxy (/api, /health, /socket.io)
|
|
14
|
+
server (Express 5 + Socket.io + Pino + Zod) → port 5501
|
|
15
|
+
↕ imports
|
|
16
|
+
shared (TypeScript interfaces only)
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Commands
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm run dev # Start both client + server (concurrently)
|
|
23
|
+
npm run build # Build shared → server → client
|
|
24
|
+
npm test # Run server + client tests
|
|
25
|
+
npm run lint # ESLint 9 flat config
|
|
26
|
+
npm run format:check # Prettier check
|
|
27
|
+
npm run typecheck # TypeScript across all workspaces
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Key Files
|
|
31
|
+
|
|
32
|
+
- `server/src/config/env.ts` — Zod-validated environment config
|
|
33
|
+
- `server/src/index.ts` — Express app + Socket.io + graceful shutdown
|
|
34
|
+
- `client/src/pages/LandingPage.tsx` — Clean starting page with ASCII banner (replace TODO content with your app)
|
|
35
|
+
- `client/src/demo/DemoPage.tsx` — Template feature showcase (delete when building your app)
|
|
36
|
+
- `client/src/demo/StatusGrid.tsx` — Demo: server health status cards (in demo/, delete when done)
|
|
37
|
+
- `client/src/demo/TechStackDisplay.tsx` — Demo: tech stack listing (in demo/, delete when done)
|
|
38
|
+
- `client/src/demo/SocketDemo.tsx` — Demo: Socket.io ping/pong (in demo/, delete when done)
|
|
39
|
+
- `client/src/hooks/useServerStatus.ts` — Fetches /health and /api/info
|
|
40
|
+
- `client/src/hooks/useSocket.ts` — Socket.io connection hook
|
|
41
|
+
- `shared/src/types.ts` — All shared TypeScript interfaces
|
|
42
|
+
- `client/vite.config.ts` — Dev proxy config (routes /api, /health, /socket.io to server)
|
|
43
|
+
|
|
44
|
+
## Patterns
|
|
45
|
+
|
|
46
|
+
- **Shared types**: Define in `shared/src/types.ts`, import via `@appystack-template/shared`
|
|
47
|
+
- **API routes**: Add to `server/src/routes/`, mount in `server/src/index.ts`
|
|
48
|
+
- **Socket events**: Add to `ServerToClientEvents` / `ClientToServerEvents` in shared, handle in `server/src/index.ts`
|
|
49
|
+
- **Components**: Place in `client/src/components/`, pages in `client/src/pages/`
|
|
50
|
+
- **Demo components**: Live in `client/src/demo/` — delete the entire folder when starting your app
|
|
51
|
+
- The `demo/` folder (StatusGrid, TechStackDisplay, SocketDemo, ContactForm) is intentionally untested
|
|
52
|
+
- It is scaffolding designed to be deleted when building a real app
|
|
53
|
+
- Tests for demo/ components would be maintenance debt on throwaway code
|
|
54
|
+
- When you delete `demo/`, delete any test files associated with it
|
|
55
|
+
- **Styling**: TailwindCSS v4 with CSS variables in `client/src/styles/index.css`
|
|
56
|
+
- **Environment**: Extend Zod schema in `server/src/config/env.ts`
|
|
57
|
+
|
|
58
|
+
## Customization TODO Markers
|
|
59
|
+
|
|
60
|
+
Search for `TODO` to find all customization points:
|
|
61
|
+
|
|
62
|
+
- Project name and package scopes
|
|
63
|
+
- Port numbers (5500/5501)
|
|
64
|
+
- ASCII banner branding
|
|
65
|
+
- Shared type interfaces
|
|
66
|
+
- ESLint config (now imports from `@appydave/appystack-config/eslint/react` — already done)
|
|
67
|
+
|
|
68
|
+
## Testing
|
|
69
|
+
|
|
70
|
+
- **Server**: Vitest + Supertest (`server/src/test/`)
|
|
71
|
+
- **Client**: Vitest + Testing Library + jsdom (`client/src/test/`)
|
|
72
|
+
- Mocks: Client tests mock `useServerStatus` and `useSocket` hooks
|
|
73
|
+
|
|
74
|
+
## Config Inheritance
|
|
75
|
+
|
|
76
|
+
ESLint config imports from `@appydave/appystack-config/eslint/react` (3-line config — migration complete as of Wave 2).
|
|
77
|
+
|
|
78
|
+
TypeScript configs extend from `@appydave/appystack-config/typescript/{base,node,react}`.
|
|
79
|
+
|
|
80
|
+
## For Consumer Apps (After Customizing This Template)
|
|
81
|
+
|
|
82
|
+
This CLAUDE.md describes the template as-shipped. Once you've built on top of it, update this section so AI coding agents understand your specific setup.
|
|
83
|
+
|
|
84
|
+
### Database (update if applicable)
|
|
85
|
+
|
|
86
|
+
- ORM/driver: \***\*\_\_\_\*\***
|
|
87
|
+
- Schema location: \***\*\_\_\_\*\***
|
|
88
|
+
- Migration command: \***\*\_\_\_\*\***
|
|
89
|
+
- Test strategy: \***\*\_\_\_\*\***
|
|
90
|
+
|
|
91
|
+
### Authentication (update if applicable)
|
|
92
|
+
|
|
93
|
+
- Approach: \***\*\_\_\_\*\***
|
|
94
|
+
- Token storage: \***\*\_\_\_\*\***
|
|
95
|
+
- Protected route middleware: \***\*\_\_\_\*\***
|
|
96
|
+
- Socket.io auth: \***\*\_\_\_\*\***
|
|
97
|
+
|
|
98
|
+
### State Management (update if applicable)
|
|
99
|
+
|
|
100
|
+
- Library: \***\*\_\_\_\*\***
|
|
101
|
+
- Store location: \***\*\_\_\_\*\***
|
|
102
|
+
- Key patterns: \***\*\_\_\_\*\***
|
|
103
|
+
|
|
104
|
+
### Custom Middleware (update if applicable)
|
|
105
|
+
|
|
106
|
+
List any middleware added beyond the defaults (helmet, compression, cors, requestLogger, rateLimiter, errorHandler):
|
|
107
|
+
|
|
108
|
+
- ***
|
|
109
|
+
|
|
110
|
+
### Additional Environment Variables
|
|
111
|
+
|
|
112
|
+
Document any env vars added beyond NODE_ENV, PORT, CLIENT_URL, VITE_API_URL, VITE_APP_NAME:
|
|
113
|
+
|
|
114
|
+
- ***
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# syntax=docker/dockerfile:1
|
|
2
|
+
|
|
3
|
+
# ── Build stage ───────────────────────────────────────────────────────────────
|
|
4
|
+
FROM node:20-alpine AS builder
|
|
5
|
+
|
|
6
|
+
WORKDIR /app
|
|
7
|
+
|
|
8
|
+
# Copy package files for all workspaces
|
|
9
|
+
COPY package.json package-lock.json ./
|
|
10
|
+
COPY shared/package.json ./shared/
|
|
11
|
+
COPY server/package.json ./server/
|
|
12
|
+
COPY client/package.json ./client/
|
|
13
|
+
|
|
14
|
+
# Install all dependencies (including devDependencies needed for build)
|
|
15
|
+
RUN npm ci
|
|
16
|
+
|
|
17
|
+
# Copy source files
|
|
18
|
+
COPY shared/ ./shared/
|
|
19
|
+
COPY server/ ./server/
|
|
20
|
+
COPY client/ ./client/
|
|
21
|
+
COPY eslint.config.js ./
|
|
22
|
+
COPY .prettierrc .prettierignore ./
|
|
23
|
+
|
|
24
|
+
# Build: shared → server → client
|
|
25
|
+
RUN npm run build
|
|
26
|
+
|
|
27
|
+
# ── Production stage ──────────────────────────────────────────────────────────
|
|
28
|
+
FROM node:20-alpine AS production
|
|
29
|
+
|
|
30
|
+
ENV NODE_ENV=production
|
|
31
|
+
|
|
32
|
+
WORKDIR /app
|
|
33
|
+
|
|
34
|
+
# Copy package files
|
|
35
|
+
COPY package.json package-lock.json ./
|
|
36
|
+
COPY shared/package.json ./shared/
|
|
37
|
+
COPY server/package.json ./server/
|
|
38
|
+
COPY client/package.json ./client/
|
|
39
|
+
|
|
40
|
+
# Install production dependencies only
|
|
41
|
+
RUN npm ci --omit=dev
|
|
42
|
+
|
|
43
|
+
# Copy built artifacts from builder
|
|
44
|
+
COPY --from=builder /app/shared/dist ./shared/dist
|
|
45
|
+
COPY --from=builder /app/server/dist ./server/dist
|
|
46
|
+
COPY --from=builder /app/client/dist ./client/dist
|
|
47
|
+
|
|
48
|
+
# Copy .env.example for reference (actual env comes from runtime)
|
|
49
|
+
COPY .env.example ./
|
|
50
|
+
|
|
51
|
+
EXPOSE 5501
|
|
52
|
+
|
|
53
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
54
|
+
CMD wget -qO- http://localhost:5501/health || exit 1
|
|
55
|
+
|
|
56
|
+
CMD ["node", "server/dist/index.js"]
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# [App Name]
|
|
2
|
+
|
|
3
|
+
> One line describing what this app is. Replace this.
|
|
4
|
+
|
|
5
|
+
Built on the [AppyStack](https://github.com/appydave/appystack) RVETS template — React, Vite, Express, TypeScript, Socket.io.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Stack
|
|
10
|
+
|
|
11
|
+
| Layer | Technology | Role in this project |
|
|
12
|
+
| ---------- | ---------------------------- | ------------------------------------------------------------------------------------ |
|
|
13
|
+
| Client | React 19 + Vite 7 | UI — served from port 5500 in dev, proxies `/api`, `/health`, `/socket.io` to server |
|
|
14
|
+
| Server | Express 5 + Socket.io | REST API + real-time events on port 5501 |
|
|
15
|
+
| Shared | TypeScript only | Interfaces that both client and server import — no runtime code |
|
|
16
|
+
| Styling | TailwindCSS v4 | Utility classes, CSS variables in `client/src/styles/index.css` |
|
|
17
|
+
| Validation | Zod | Server env vars + request body schemas |
|
|
18
|
+
| Logging | Pino + pino-http | Structured JSON logs, request tracing with UUID |
|
|
19
|
+
| Quality | Vitest + ESLint 9 + Prettier | Tests, linting, formatting across all workspaces |
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
npm install
|
|
27
|
+
cp .env.example .env
|
|
28
|
+
npm run dev
|
|
29
|
+
# Client: http://localhost:5500
|
|
30
|
+
# Server: http://localhost:5501
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Both processes start concurrently. The client dev server proxies all `/api`, `/health`, and `/socket.io` requests to the Express server — no CORS configuration needed in development.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## What's In Here
|
|
38
|
+
|
|
39
|
+
### `client/` — React app (port 5500)
|
|
40
|
+
|
|
41
|
+
**Demo components** (`client/src/demo/`) — delete this entire folder when starting your app:
|
|
42
|
+
|
|
43
|
+
| Component | What it does |
|
|
44
|
+
| ------------------ | ---------------------------------------------------------------- |
|
|
45
|
+
| `StatusGrid` | Displays server health + info fetched on load |
|
|
46
|
+
| `TechStackDisplay` | Lists the tech stack — replace or delete for your app |
|
|
47
|
+
| `SocketDemo` | Live ping/pong demo via Socket.io — shows real-time wiring works |
|
|
48
|
+
| `ContactForm` | Example form with React Hook Form + Zod validation |
|
|
49
|
+
|
|
50
|
+
**Components** (`client/src/components/`):
|
|
51
|
+
|
|
52
|
+
| Component | What it does |
|
|
53
|
+
| --------------- | -------------------------- |
|
|
54
|
+
| `ErrorFallback` | Error boundary fallback UI |
|
|
55
|
+
|
|
56
|
+
**Hooks** (`client/src/hooks/`):
|
|
57
|
+
|
|
58
|
+
| Hook | What it does |
|
|
59
|
+
| ----------------- | ---------------------------------------------------------------- |
|
|
60
|
+
| `useServerStatus` | Fetches `/health` and `/api/info` on mount, returns status state |
|
|
61
|
+
| `useSocket` | Manages Socket.io connection lifecycle, exposes connection state |
|
|
62
|
+
|
|
63
|
+
**Pages** (`client/src/pages/`):
|
|
64
|
+
|
|
65
|
+
- `LandingPage.tsx` — The default landing page with ASCII banner and status grid. Replace the banner and content for your app.
|
|
66
|
+
|
|
67
|
+
**Vite config** (`client/vite.config.ts`):
|
|
68
|
+
|
|
69
|
+
Dev proxy routes `/api`, `/health`, and `/socket.io` to `http://localhost:5501`. Update target if you change the server port.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
### `server/` — Express API (port 5501)
|
|
74
|
+
|
|
75
|
+
**Routes** (`server/src/routes/`):
|
|
76
|
+
|
|
77
|
+
| Route | What it does |
|
|
78
|
+
| --------------- | ----------------------------------------------- |
|
|
79
|
+
| `GET /health` | Returns `{ status: "ok", timestamp }` |
|
|
80
|
+
| `GET /api/info` | Returns Node version, environment, port, uptime |
|
|
81
|
+
|
|
82
|
+
**Middleware** (`server/src/middleware/`):
|
|
83
|
+
|
|
84
|
+
| Middleware | What it does |
|
|
85
|
+
| --------------- | ----------------------------------------------------------- |
|
|
86
|
+
| `requestLogger` | Pino-http request logging with UUID per request |
|
|
87
|
+
| `errorHandler` | Central error handler — catches thrown errors, returns JSON |
|
|
88
|
+
| `rateLimiter` | Express rate-limit — 100 requests per 15 minutes per IP |
|
|
89
|
+
| `validate` | Zod request body validation factory |
|
|
90
|
+
|
|
91
|
+
**Config** (`server/src/config/`):
|
|
92
|
+
|
|
93
|
+
- `env.ts` — Zod-validated environment variables. Add new vars here; they'll be type-safe everywhere.
|
|
94
|
+
- `logger.ts` — Pino logger instance. Import this rather than using `console` in server code.
|
|
95
|
+
|
|
96
|
+
**Socket.io events** (wired in `server/src/index.ts`):
|
|
97
|
+
|
|
98
|
+
| Event | Direction | What it does |
|
|
99
|
+
| ---------------- | --------------- | ----------------------------------- |
|
|
100
|
+
| `client:ping` | Client → Server | Ping |
|
|
101
|
+
| `server:message` | Server → Client | Response with message and timestamp |
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
### `shared/` — TypeScript interfaces
|
|
106
|
+
|
|
107
|
+
`shared/src/types.ts` holds all interfaces used by both client and server:
|
|
108
|
+
|
|
109
|
+
- `ApiResponse<T>` — wrapper for all API responses
|
|
110
|
+
- `HealthResponse` — shape of `/health`
|
|
111
|
+
- `ServerInfo` — shape of `/api/info`
|
|
112
|
+
- `SocketEvents` — `ServerToClientEvents` + `ClientToServerEvents`
|
|
113
|
+
|
|
114
|
+
Import in client or server:
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
import type { ApiResponse, SocketEvents } from '@appystack-template/shared';
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
---
|
|
121
|
+
|
|
122
|
+
## Customisation
|
|
123
|
+
|
|
124
|
+
Run the interactive setup script first:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
npm run customize
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
That handles renaming package scopes and setting ports. Then work through this checklist:
|
|
131
|
+
|
|
132
|
+
- [ ] Rename packages in `package.json`, `client/package.json`, `server/package.json`, `shared/package.json` — change `@appystack-template/*` to `@your-app/*`
|
|
133
|
+
- [ ] Update ports if 5500/5501 are taken — change `client/vite.config.ts`, `.env`, and `server/src/config/env.ts`
|
|
134
|
+
- [ ] Replace the ASCII banner in `client/src/pages/LandingPage.tsx`
|
|
135
|
+
- [ ] Define your domain types in `shared/src/types.ts` — replace or extend `ServerInfo` / `SocketEvents`
|
|
136
|
+
- [ ] Add your first API route in `server/src/routes/`, mount it in `server/src/index.ts`
|
|
137
|
+
- [ ] Add your first Socket.io event to `ClientToServerEvents` / `ServerToClientEvents` in shared, then handle in `server/src/index.ts`
|
|
138
|
+
- [ ] Delete or repurpose `TechStackDisplay` and `SocketDemo` once you have real content
|
|
139
|
+
- [ ] Add your environment variables to `.env.example` and the Zod schema in `server/src/config/env.ts`
|
|
140
|
+
|
|
141
|
+
Search for `TODO` across the codebase to find every customisation point:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
grep -r "TODO" --include="*.ts" --include="*.tsx" --include="*.json" .
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## Port Configuration
|
|
150
|
+
|
|
151
|
+
| Service | Port | Config location |
|
|
152
|
+
| ---------------- | ---- | ---------------------------------- |
|
|
153
|
+
| Client (Vite) | 5500 | `client/vite.config.ts` |
|
|
154
|
+
| Server (Express) | 5501 | `.env`, `server/src/config/env.ts` |
|
|
155
|
+
|
|
156
|
+
The client proxies `/api`, `/health`, and `/socket.io` to the server during development. No CORS config needed in dev.
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## Scripts
|
|
161
|
+
|
|
162
|
+
| Script | What it does |
|
|
163
|
+
| ----------------------- | ------------------------------------------------ |
|
|
164
|
+
| `npm run dev` | Start client + server concurrently |
|
|
165
|
+
| `npm run build` | Build shared → server → client |
|
|
166
|
+
| `npm test` | Run all tests (server + client) |
|
|
167
|
+
| `npm run test:coverage` | Run tests with coverage report |
|
|
168
|
+
| `npm run lint` | ESLint across all workspaces |
|
|
169
|
+
| `npm run lint:fix` | ESLint with auto-fix |
|
|
170
|
+
| `npm run format` | Prettier — write all files |
|
|
171
|
+
| `npm run format:check` | Prettier — check only |
|
|
172
|
+
| `npm run typecheck` | TypeScript check across all workspaces |
|
|
173
|
+
| `npm run clean` | Remove all `node_modules` and `dist` directories |
|
|
174
|
+
| `npm run customize` | Interactive rename + port setup script |
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Adding Things
|
|
179
|
+
|
|
180
|
+
### New API route
|
|
181
|
+
|
|
182
|
+
1. Create `server/src/routes/your-route.ts`
|
|
183
|
+
2. Mount it in `server/src/index.ts`: `app.use('/api/your-route', yourRouter)`
|
|
184
|
+
3. Add the response type to `shared/src/types.ts` if the client needs it
|
|
185
|
+
|
|
186
|
+
### New Socket.io event
|
|
187
|
+
|
|
188
|
+
1. Add to `ClientToServerEvents` or `ServerToClientEvents` in `shared/src/types.ts`
|
|
189
|
+
2. Handle the event in `server/src/index.ts` inside the `io.on('connection', ...)` block
|
|
190
|
+
3. Emit from the client via the `useSocket` hook
|
|
191
|
+
|
|
192
|
+
### New environment variable
|
|
193
|
+
|
|
194
|
+
1. Add to `.env` and `.env.example`
|
|
195
|
+
2. Add to the Zod schema in `server/src/config/env.ts`
|
|
196
|
+
3. Export from the `env` object — it will be type-safe everywhere it's imported
|
|
197
|
+
|
|
198
|
+
### New shared type
|
|
199
|
+
|
|
200
|
+
1. Add to `shared/src/types.ts`
|
|
201
|
+
2. Re-export from `shared/src/index.ts` if not already exported
|
|
202
|
+
3. Import in client or server: `import type { YourType } from '@appystack-template/shared'`
|
|
203
|
+
|
|
204
|
+
---
|
|
205
|
+
|
|
206
|
+
## Docs
|
|
207
|
+
|
|
208
|
+
AppyStack patterns and decisions are documented in the AppyStack repo:
|
|
209
|
+
|
|
210
|
+
| Guide | What's in it |
|
|
211
|
+
| --------------------------------------------- | ------------------------------------------------------ |
|
|
212
|
+
| [Testing guide](../docs/testing-guide.md) | Vitest patterns, MSW setup, hook testing, socket mocks |
|
|
213
|
+
| [Socket.io guide](../docs/socket-io.md) | Event patterns, auth, rooms, typed events |
|
|
214
|
+
| [API design](../docs/api-design.md) | Route conventions, error handling, validation patterns |
|
|
215
|
+
| [Architecture](../docs/architecture.md) | Full stack decisions, pitfalls, npm publishing |
|
|
216
|
+
| [Environment](../docs/environment.md) | Env var setup, Zod schema patterns |
|
|
217
|
+
| [Troubleshooting](../docs/troubleshooting.md) | Common problems and fixes |
|
|
218
|
+
|
|
219
|
+
> These links are relative to the AppyStack repo. If you copied the template without the docs, find them at https://github.com/appydave/appystack/tree/main/docs
|
|
@@ -0,0 +1,13 @@
|
|
|
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.0" />
|
|
6
|
+
<!-- TODO: Update title for your project -->
|
|
7
|
+
<title>AppyStack Template</title>
|
|
8
|
+
</head>
|
|
9
|
+
<body>
|
|
10
|
+
<div id="root"></div>
|
|
11
|
+
<script type="module" src="/src/main.tsx"></script>
|
|
12
|
+
</body>
|
|
13
|
+
</html>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@appystack-template/client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"description": "React + Vite client for AppyStack template",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"dev": "vite",
|
|
9
|
+
"build": "tsc -b && vite build",
|
|
10
|
+
"preview": "vite preview",
|
|
11
|
+
"typecheck": "tsc --noEmit",
|
|
12
|
+
"test": "vitest run",
|
|
13
|
+
"test:watch": "vitest",
|
|
14
|
+
"test:coverage": "vitest run --coverage"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"@appystack-template/shared": "*",
|
|
18
|
+
"clsx": "^2.1.1",
|
|
19
|
+
"react": "^19.2.4",
|
|
20
|
+
"react-dom": "^19.2.4",
|
|
21
|
+
"react-error-boundary": "^6.1.1",
|
|
22
|
+
"react-hook-form": "^7.71.2",
|
|
23
|
+
"socket.io-client": "^4.8.1",
|
|
24
|
+
"tailwind-merge": "^2.6.0",
|
|
25
|
+
"@hookform/resolvers": "^5.2.2"
|
|
26
|
+
},
|
|
27
|
+
"devDependencies": {
|
|
28
|
+
"@types/node": "^22.0.0",
|
|
29
|
+
"@tailwindcss/vite": "^4.1.18",
|
|
30
|
+
"@testing-library/jest-dom": "^6.6.3",
|
|
31
|
+
"@testing-library/react": "^16.3.0",
|
|
32
|
+
"@testing-library/user-event": "^14.6.1",
|
|
33
|
+
"@types/react": "^19.0.0",
|
|
34
|
+
"@types/react-dom": "^19.0.0",
|
|
35
|
+
"@vitejs/plugin-react": "^5.1.4",
|
|
36
|
+
"@vitest/coverage-v8": "^4.0.18",
|
|
37
|
+
"jsdom": "^26.1.0",
|
|
38
|
+
"msw": "^2.12.10",
|
|
39
|
+
"tailwindcss": "^4.1.18",
|
|
40
|
+
"vite": "^7.3.1",
|
|
41
|
+
"vitest": "^4.0.18"
|
|
42
|
+
}
|
|
43
|
+
}
|