create-next-style-guide 0.0.0-stage → 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.
- package/addons/ci/.cursor/rules/ci.mdc +11 -0
- package/addons/ci/docs/style-guide/ops/ci.md +7 -0
- package/addons/docker/.cursor/rules/docker.mdc +12 -0
- package/addons/docker/.dockerignore +12 -0
- package/addons/docker/docker/production.Dockerfile +53 -0
- package/addons/docker/docs/style-guide/ops/docker.md +14 -0
- package/addons/docs/data/tanstack-query.md +7 -0
- package/addons/docs/examples/api-app-crud.md +94 -0
- package/addons/docs/ui/icons.md +5 -0
- package/addons/endpoints/.cursor/rules/endpoints.mdc +17 -0
- package/addons/endpoints/docs/style-guide/http/endpoints.md +21 -0
- package/addons/endpoints/scripts/endpoints.codegen.json +7 -0
- package/addons/endpoints/scripts/generate-endpoints.ts +1384 -0
- package/addons/endpoints/src/endpoints/Types.ts +105 -0
- package/addons/endpoints/src/endpoints/index.ts +2 -0
- package/addons/endpoints/src/utils/api-error.ts +181 -0
- package/addons/endpoints/src/utils/api-result.ts +13 -0
- package/addons/endpoints/src/utils/axios-instance.ts +23 -0
- package/addons/endpoints/src/utils/form-data.ts +37 -0
- package/addons/endpoints/src/utils/search-params.ts +21 -0
- package/addons/eslint/.cursor/rules/eslint.mdc +12 -0
- package/addons/eslint/docs/style-guide/tooling/eslint.md +13 -0
- package/addons/eslint/eslint.config.mjs +85 -0
- package/addons/husky/.husky/pre-commit +2 -0
- package/addons/husky/docs/style-guide/tooling/husky.md +10 -0
- package/addons/prettier/.cursor/rules/prettier.mdc +11 -0
- package/addons/prettier/.prettierrc +14 -0
- package/addons/prettier/docs/style-guide/tooling/prettier.md +9 -0
- package/dist/index.js +3848 -0
- package/dist/index.js.map +1 -0
- package/package.json +38 -4
- package/template/.cursor/rules/components.mdc +27 -0
- package/template/.cursor/rules/core.mdc +16 -0
- package/template/.cursor/rules/forms.mdc +16 -0
- package/template/.env.example +6 -0
- package/template/AGENTS.md +38 -0
- package/template/README.md +28 -0
- package/template/docs/style-guide/README.md +11 -0
- package/template/docs/style-guide/http/client.md +9 -0
- package/template/docs/style-guide/overview/architecture.md +21 -0
- package/template/docs/style-guide/overview/project-structure.md +36 -0
- package/template/eslint.config.mjs +13 -0
- package/template/gitignore +39 -0
- package/template/next-env.d.ts +4 -0
- package/template/next.config.ts +7 -0
- package/template/package.json +27 -0
- package/template/src/app/_components/welcome-card/index.tsx +24 -0
- package/template/src/app/globals.css +84 -0
- package/template/src/app/layout.tsx +22 -0
- package/template/src/app/page.tsx +25 -0
- package/template/src/components/.gitkeep +0 -0
- package/template/src/constants/.gitkeep +0 -0
- package/template/src/hooks/.gitkeep +0 -0
- package/template/src/lib/env.ts +17 -0
- package/template/src/lib/http.ts +28 -0
- package/template/src/lib/utils.ts +6 -0
- package/template/src/providers/.gitkeep +0 -0
- package/template/src/types/.gitkeep +0 -0
- package/template/src/utils/.gitkeep +0 -0
- package/template/tsconfig.json +23 -0
- package/README.md +0 -3
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: GitHub Actions CI workflow
|
|
3
|
+
globs: .github/workflows/**
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# CI
|
|
8
|
+
|
|
9
|
+
- Workflow: `.github/workflows/ci.yml` — install → typecheck → lint/format (if enabled) → build.
|
|
10
|
+
- Keep jobs green before merge. Don't skip checks with unrelated workflow edits.
|
|
11
|
+
- New required scripts must be reflected in the workflow steps.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Docker / standalone Next production image
|
|
3
|
+
globs: docker/**,.dockerignore,next.config.ts,Dockerfile*
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Docker
|
|
8
|
+
|
|
9
|
+
- Image: `docker/production.Dockerfile` (multi-stage, Next `output: "standalone"`).
|
|
10
|
+
- Build args: `NEXT_PUBLIC_APP_URL`, `NEXT_PUBLIC_API_URL` (inlined at build).
|
|
11
|
+
- `HUSKY=0` in builder. Healthcheck hits `/` on port 3000.
|
|
12
|
+
- Changing env/build args/ports → call out infra/deploy follow-ups in the final response.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# ---------------------------------------------------------------------------- #
|
|
2
|
+
# Stage 1: Base & Dependencies #
|
|
3
|
+
# ---------------------------------------------------------------------------- #
|
|
4
|
+
FROM node:22-alpine AS builder
|
|
5
|
+
|
|
6
|
+
RUN apk add --no-cache libc6-compat
|
|
7
|
+
RUN corepack enable && corepack prepare pnpm@9.15.0 --activate
|
|
8
|
+
|
|
9
|
+
WORKDIR /app
|
|
10
|
+
|
|
11
|
+
ENV HUSKY=0 \
|
|
12
|
+
NEXT_TELEMETRY_DISABLED=1
|
|
13
|
+
|
|
14
|
+
ARG NEXT_PUBLIC_APP_URL=http://localhost:3000
|
|
15
|
+
ARG NEXT_PUBLIC_API_URL=http://localhost:8000
|
|
16
|
+
|
|
17
|
+
ENV NEXT_PUBLIC_APP_URL=$NEXT_PUBLIC_APP_URL \
|
|
18
|
+
NEXT_PUBLIC_API_URL=$NEXT_PUBLIC_API_URL
|
|
19
|
+
|
|
20
|
+
COPY package.json pnpm-lock.yaml .npmrc* ./
|
|
21
|
+
RUN --mount=type=cache,id=pnpm,target=/root/.local/share/pnpm/store \
|
|
22
|
+
pnpm install --frozen-lockfile
|
|
23
|
+
|
|
24
|
+
COPY . /app/
|
|
25
|
+
|
|
26
|
+
RUN pnpm build
|
|
27
|
+
|
|
28
|
+
# ---------------------------------------------------------------------------- #
|
|
29
|
+
# Stage 2: Production Runner #
|
|
30
|
+
# ---------------------------------------------------------------------------- #
|
|
31
|
+
FROM node:22-alpine AS runner
|
|
32
|
+
|
|
33
|
+
RUN apk add --no-cache curl
|
|
34
|
+
|
|
35
|
+
WORKDIR /app
|
|
36
|
+
|
|
37
|
+
ENV NODE_ENV=production \
|
|
38
|
+
NEXT_TELEMETRY_DISABLED=1 \
|
|
39
|
+
HOSTNAME=0.0.0.0 \
|
|
40
|
+
PORT=3000
|
|
41
|
+
|
|
42
|
+
COPY --from=builder /app/public ./public
|
|
43
|
+
COPY --from=builder --chown=node:node /app/.next/standalone ./
|
|
44
|
+
COPY --from=builder --chown=node:node /app/.next/static ./.next/static
|
|
45
|
+
|
|
46
|
+
USER node
|
|
47
|
+
|
|
48
|
+
EXPOSE 3000
|
|
49
|
+
|
|
50
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=40s --retries=3 \
|
|
51
|
+
CMD curl -fsS http://127.0.0.1:3000/ || exit 1
|
|
52
|
+
|
|
53
|
+
CMD ["node", "server.js"]
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Docker
|
|
2
|
+
|
|
3
|
+
Production image: `docker/production.Dockerfile`.
|
|
4
|
+
|
|
5
|
+
Requires `output: "standalone"` in `next.config.ts` (set by the Docker installer).
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
docker build -f docker/production.Dockerfile \
|
|
9
|
+
--build-arg NEXT_PUBLIC_APP_URL=https://example.com \
|
|
10
|
+
--build-arg NEXT_PUBLIC_API_URL=https://api.example.com \
|
|
11
|
+
-t __PROJECT_SLUG__ .
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Runner exposes `3000`. See `.dockerignore`.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# TanStack Query
|
|
2
|
+
|
|
3
|
+
`QueryProvider` wraps the root layout (`src/providers/query-provider.tsx`).
|
|
4
|
+
|
|
5
|
+
- Use `useQuery` / `useMutation` for client data.
|
|
6
|
+
- Prefer generated endpoint modules + query-key factories when OpenAPI codegen is enabled.
|
|
7
|
+
- Keep Server Components for RSC-friendly fetches when you do not need client cache.
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Example: tiny CRUD + login flow (`api-app`)
|
|
2
|
+
|
|
3
|
+
This walkthrough matches the **`api-app`** preset (Tailwind · shadcn · JWT · TanStack Query · Zustand · endpoints · envelope).
|
|
4
|
+
|
|
5
|
+
## 1. Scaffold
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx create-next-style-guide@latest inventory --yes --preset api-app
|
|
9
|
+
cd inventory
|
|
10
|
+
cp .env.example .env
|
|
11
|
+
# NEXT_PUBLIC_API_URL=http://localhost:8000
|
|
12
|
+
docker compose up -d # stub API on :8000 — swap for your real backend
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## 2. Generate endpoints
|
|
16
|
+
|
|
17
|
+
Point `scripts/endpoints.codegen.json` at your OpenAPI schema, then:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
pnpm endpoints:generate
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
You get typed clients under `src/endpoints/` plus axios helpers that unwrap envelopes.
|
|
24
|
+
|
|
25
|
+
## 3. Login (JWT)
|
|
26
|
+
|
|
27
|
+
Store tokens with `src/utils/token-storage.ts`. After your API login:
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { setTokens } from "@/utils/token-storage";
|
|
31
|
+
|
|
32
|
+
await setTokens({
|
|
33
|
+
accessToken: result.access,
|
|
34
|
+
refreshToken: result.refresh,
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Axios (`src/utils/axios-instance.ts`) attaches `Authorization` and refreshes on `401`.
|
|
39
|
+
|
|
40
|
+
## 4. List + create (Query)
|
|
41
|
+
|
|
42
|
+
```tsx
|
|
43
|
+
"use client";
|
|
44
|
+
|
|
45
|
+
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query";
|
|
46
|
+
import { getItems, postItems } from "@/endpoints"; // names depend on your schema
|
|
47
|
+
|
|
48
|
+
export function ItemsPanel() {
|
|
49
|
+
const qc = useQueryClient();
|
|
50
|
+
const { data, isLoading } = useQuery({
|
|
51
|
+
queryKey: ["items"],
|
|
52
|
+
queryFn: () => getItems(),
|
|
53
|
+
});
|
|
54
|
+
const create = useMutation({
|
|
55
|
+
mutationFn: (body: { name: string }) => postItems(body),
|
|
56
|
+
onSuccess: () => qc.invalidateQueries({ queryKey: ["items"] }),
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
if (isLoading) return <p>Loading…</p>;
|
|
60
|
+
return (
|
|
61
|
+
<div>
|
|
62
|
+
<ul>{data?.map((item) => <li key={item.id}>{item.name}</li>)}</ul>
|
|
63
|
+
<button
|
|
64
|
+
type="button"
|
|
65
|
+
onClick={() => create.mutate({ name: "New item" })}
|
|
66
|
+
>
|
|
67
|
+
Add
|
|
68
|
+
</button>
|
|
69
|
+
</div>
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Colocate the panel under `src/app/(app)/items/_components/items-panel/`.
|
|
75
|
+
|
|
76
|
+
## 5. UI state (Zustand)
|
|
77
|
+
|
|
78
|
+
Keep server lists in Query; use the store for UI-only flags:
|
|
79
|
+
|
|
80
|
+
```ts
|
|
81
|
+
import { useAppStore } from "@/stores/app-store";
|
|
82
|
+
|
|
83
|
+
const hydrated = useAppStore((s) => s.hydrated);
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Conventions checklist
|
|
87
|
+
|
|
88
|
+
| Concern | Place |
|
|
89
|
+
|---------|--------|
|
|
90
|
+
| Route UI | `src/app/<route>/_components/<name>/` |
|
|
91
|
+
| Shared UI | `src/components/` |
|
|
92
|
+
| HTTP | generated `src/endpoints/*` / `apiFetch` |
|
|
93
|
+
| Providers | `src/providers/app-providers.tsx` |
|
|
94
|
+
| Agent rules | `AGENTS.md` + `.cursor/rules/` |
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: OpenAPI codegen + API helpers
|
|
3
|
+
globs: src/endpoints/**,scripts/generate-endpoints.ts,scripts/endpoints.codegen.json,src/utils/api-error.ts,src/utils/api-result.ts,src/utils/form-data.ts,src/utils/search-params.ts,src/utils/axios-instance.ts
|
|
4
|
+
alwaysApply: false
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Endpoints
|
|
8
|
+
|
|
9
|
+
`pnpm endpoints:generate` refreshes `src/endpoints/*` from OpenAPI (`scripts/endpoints.codegen.json`). Generated files are AUTO-GENERATED — don't edit (keep `Types.ts`). No Zod in codegen.
|
|
10
|
+
|
|
11
|
+
- Shape: `*Body` request; `*Call` `{ request: { path?, params?, body? } }`; unwrap with `unwrapApiResult`.
|
|
12
|
+
- Calls via `api` (`@/utils/axios-instance`) only — not from UI components directly.
|
|
13
|
+
- Uploads: `toApiBody` · queries: `toSearchParams`.
|
|
14
|
+
- Errors: `getApiErrorMessage` / `extractApiFieldErrors` / field helpers (`@/utils/api-error`).
|
|
15
|
+
- Query keys: always `get<EndpointName>QueryKey(...)` from generated modules — never ad-hoc `["resource"]` strings.
|
|
16
|
+
- Params: use exported `*DefaultParams`; don't hardcode page sizes in UI.
|
|
17
|
+
- Enums: reuse `src/endpoints/enums.ts` types + `AS_CONST` arrays for selects/Zod.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# OpenAPI endpoints
|
|
2
|
+
|
|
3
|
+
Generate typed clients from your Django (or any) OpenAPI schema:
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
pnpm endpoints:generate
|
|
7
|
+
# optional override:
|
|
8
|
+
pnpm endpoints:generate --url=http://localhost:8000/api/docs/schema/?format=json
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
Config: `scripts/endpoints.codegen.json`
|
|
12
|
+
|
|
13
|
+
| Path | Role |
|
|
14
|
+
|------|------|
|
|
15
|
+
| `src/endpoints/` | Generated modules (+ hand-written `Types.ts`) |
|
|
16
|
+
| `src/utils/axios-instance.ts` | Shared `api` client |
|
|
17
|
+
| `src/utils/api-result.ts` | Envelope unwrap |
|
|
18
|
+
| `src/utils/api-error.ts` | Error helpers |
|
|
19
|
+
| `src/utils/search-params.ts` / `form-data.ts` | Codegen helpers |
|
|
20
|
+
|
|
21
|
+
Do not call `api` from UI — import generated endpoint functions (and wire them through TanStack Query when enabled).
|