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,38 @@
|
|
|
1
|
+
# Agents (__PROJECT_NAME__)
|
|
2
|
+
|
|
3
|
+
Generated from [next-style-guide](https://github.com/alidanial7/next-style-guide).
|
|
4
|
+
|
|
5
|
+
## Maintenance
|
|
6
|
+
|
|
7
|
+
Stack-wide → here. Feature detail → `.cursor/rules/*.mdc` (glob-scoped — only load when editing matching files). Don't re-read this file mid-task.
|
|
8
|
+
|
|
9
|
+
## Stack
|
|
10
|
+
|
|
11
|
+
App Router · TS strict · Zod/Yup env (`src/lib/env.ts`) · __PACKAGE_MANAGER__.
|
|
12
|
+
Optional features (Query, store, endpoints, i18n, SEO, tests, Docker, CI, …) exist only when enabled at scaffold.
|
|
13
|
+
|
|
14
|
+
## Do
|
|
15
|
+
|
|
16
|
+
- Thin `page.tsx` / `layout.tsx` — UI in folder-per-component `_components/`.
|
|
17
|
+
- Route-only → `src/app/<route>/_components/<name>/index.tsx`.
|
|
18
|
+
- Layout / home → `src/app/_components/<name>/`.
|
|
19
|
+
- Shared (≥2 routes) → `src/components/` (`ui/` flat for shadcn).
|
|
20
|
+
- Infra → `src/lib/`; API helpers → `src/utils/`; client state → `src/stores/` (when present).
|
|
21
|
+
- Named exports `function Foo()`; default only for Next route files.
|
|
22
|
+
- Prefer Server Components; `"use client"` only when needed.
|
|
23
|
+
- Single `<main>` in root layout — never nest `<main>` in pages/components.
|
|
24
|
+
|
|
25
|
+
## Don't
|
|
26
|
+
|
|
27
|
+
- Park single-route UI in `src/components/`.
|
|
28
|
+
- Flat files in `_components/` (use `<name>/index.tsx`).
|
|
29
|
+
- Invent a second folder convention without updating this file + `docs/style-guide/`.
|
|
30
|
+
- Auto `git commit` / `git push` — leave that to the developer.
|
|
31
|
+
|
|
32
|
+
## Read when needed
|
|
33
|
+
|
|
34
|
+
| Task | Open |
|
|
35
|
+
|------|------|
|
|
36
|
+
| Conventions | `docs/style-guide/README.md` |
|
|
37
|
+
| Architecture | `docs/style-guide/overview/architecture.md` |
|
|
38
|
+
| Cursor rules | `.cursor/rules/` (glob-scoped) |
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# __PROJECT_NAME__
|
|
2
|
+
|
|
3
|
+
Next.js App Router app generated with [next-style-guide](https://github.com/alidanial7/next-style-guide).
|
|
4
|
+
|
|
5
|
+
## Docs
|
|
6
|
+
|
|
7
|
+
| Audience | Start |
|
|
8
|
+
|----------|--------|
|
|
9
|
+
| Coding agents | [`AGENTS.md`](AGENTS.md) → [`.cursor/rules/`](.cursor/rules/) |
|
|
10
|
+
| Humans | [`docs/style-guide/`](docs/style-guide/) |
|
|
11
|
+
|
|
12
|
+
## Stack
|
|
13
|
+
|
|
14
|
+
- Next.js 16 · React 19 · TypeScript
|
|
15
|
+
- Env validation via Zod or Yup
|
|
16
|
+
- App Router under `src/app/`
|
|
17
|
+
- Route-colocated UI under `_components/` (folder-per-component)
|
|
18
|
+
- Package manager: __PACKAGE_MANAGER__
|
|
19
|
+
|
|
20
|
+
## Setup
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
cp .env.example .env
|
|
24
|
+
__PACKAGE_MANAGER__ install
|
|
25
|
+
__PACKAGE_MANAGER__ dev
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
App: [http://localhost:3000](http://localhost:3000)
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Style guide — __PROJECT_NAME__
|
|
2
|
+
|
|
3
|
+
Living conventions for this app. Open one page at a time.
|
|
4
|
+
|
|
5
|
+
| Page | Topic |
|
|
6
|
+
|------|--------|
|
|
7
|
+
| [Architecture](overview/architecture.md) | Layers: app / components / lib / utils |
|
|
8
|
+
| [Project structure](overview/project-structure.md) | Folder map |
|
|
9
|
+
| [HTTP client](http/client.md) | `apiFetch` helper |
|
|
10
|
+
|
|
11
|
+
Coding agents: start at [`AGENTS.md`](../../AGENTS.md) → [`.cursor/rules/`](../../.cursor/rules/).
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# HTTP client
|
|
2
|
+
|
|
3
|
+
Base helper: `src/lib/http.ts` → `apiFetch`.
|
|
4
|
+
|
|
5
|
+
- Builds URLs from `NEXT_PUBLIC_API_URL`
|
|
6
|
+
- Expects JSON
|
|
7
|
+
- Throws on non-OK responses
|
|
8
|
+
|
|
9
|
+
When **endpoints** / axios helpers are enabled, prefer generated clients and `unwrapApiResult` for `{ result, status, success, messages }` responses so route UI never parses envelopes by hand.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
```text
|
|
4
|
+
src/app/ → routes + layouts (thin)
|
|
5
|
+
src/app/_components/ → layout / homepage UI only
|
|
6
|
+
src/app/<route>/_components/ → route-only UI
|
|
7
|
+
src/components/ → shared UI (≥2 routes) + ui/ primitives
|
|
8
|
+
src/lib/ → env, http, shared helpers
|
|
9
|
+
src/utils/ → API client helpers (when enabled)
|
|
10
|
+
src/providers/ → client providers (Query, theme, Redux, …)
|
|
11
|
+
src/stores/ → client global state (Zustand / Redux, when enabled)
|
|
12
|
+
src/hooks/ · types/ · constants/
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Rules of thumb
|
|
16
|
+
|
|
17
|
+
1. **Routes orchestrate** — load data, compose colocated `_components`.
|
|
18
|
+
2. **Colocate by usage** — one route → that route's `_components/`; two+ routes → `src/components/`.
|
|
19
|
+
3. **Server first** — prefer RSC; `"use client"` only at the leaves that need interactivity.
|
|
20
|
+
4. **One HTTP doorway** — `src/lib/http.ts` and/or generated `src/endpoints/*` (when enabled). Avoid ad-hoc `fetch` in UI.
|
|
21
|
+
5. **Split server cache vs UI state** — TanStack Query for server/async cache; Zustand/Redux for client UI/session state only.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Project structure
|
|
2
|
+
|
|
3
|
+
Lean App Router layout. Installers only add folders they need (e.g. `stores/`, `endpoints/`).
|
|
4
|
+
|
|
5
|
+
```text
|
|
6
|
+
__PROJECT_SLUG__/
|
|
7
|
+
├── src/
|
|
8
|
+
│ ├── app/ # routes + layouts (thin)
|
|
9
|
+
│ │ ├── _components/ # layout / homepage UI
|
|
10
|
+
│ │ └── <route>/_components/ # route-only UI (folder-per-component)
|
|
11
|
+
│ ├── components/ # shared UI (≥2 routes); ui/ for primitives
|
|
12
|
+
│ ├── lib/ # env, http, cn, seo, …
|
|
13
|
+
│ ├── utils/ # API helpers (axios, errors, tokens, …)
|
|
14
|
+
│ ├── providers/ # client providers (Query, theme, Redux, …)
|
|
15
|
+
│ ├── stores/ # client store slices (Zustand / Redux) — when enabled
|
|
16
|
+
│ ├── hooks/ # shared hooks
|
|
17
|
+
│ ├── types/ # shared types
|
|
18
|
+
│ └── constants/ # shared constants
|
|
19
|
+
├── docs/style-guide/ # conventions that match enabled options
|
|
20
|
+
├── AGENTS.md
|
|
21
|
+
├── .cursor/rules/ # glob-scoped agent rules
|
|
22
|
+
├── .env.example
|
|
23
|
+
└── package.json
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Placement rules
|
|
27
|
+
|
|
28
|
+
| What | Where |
|
|
29
|
+
|------|--------|
|
|
30
|
+
| One route only | `src/app/<route>/_components/<name>/index.tsx` |
|
|
31
|
+
| Layout / home chrome | `src/app/_components/<name>/` |
|
|
32
|
+
| Shared across ≥2 routes | `src/components/` |
|
|
33
|
+
| Env / pure helpers | `src/lib/` |
|
|
34
|
+
| HTTP / API adapters | `src/utils/` (or generated `src/endpoints/`) |
|
|
35
|
+
| Client global state | `src/stores/` |
|
|
36
|
+
| Client providers | `src/providers/` |
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import nextVitals from "eslint-config-next/core-web-vitals";
|
|
2
|
+
import nextTs from "eslint-config-next/typescript";
|
|
3
|
+
|
|
4
|
+
/** Minimal Next flat config. Replaced when the enhanced ESLint option is on. */
|
|
5
|
+
const eslintConfig = [
|
|
6
|
+
...nextVitals,
|
|
7
|
+
...nextTs,
|
|
8
|
+
{
|
|
9
|
+
ignores: [".next/**", "out/**", "build/**", "next-env.d.ts", "node_modules/**"],
|
|
10
|
+
},
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
export default eslintConfig;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# dependencies
|
|
2
|
+
/node_modules
|
|
3
|
+
/.pnp
|
|
4
|
+
.pnp.*
|
|
5
|
+
.yarn/*
|
|
6
|
+
!.yarn/patches
|
|
7
|
+
!.yarn/plugins
|
|
8
|
+
!.yarn/releases
|
|
9
|
+
!.yarn/versions
|
|
10
|
+
|
|
11
|
+
# testing
|
|
12
|
+
/coverage
|
|
13
|
+
|
|
14
|
+
# next.js
|
|
15
|
+
/.next/
|
|
16
|
+
/out/
|
|
17
|
+
|
|
18
|
+
# production
|
|
19
|
+
/build
|
|
20
|
+
|
|
21
|
+
# misc
|
|
22
|
+
.DS_Store
|
|
23
|
+
*.pem
|
|
24
|
+
*.tsbuildinfo
|
|
25
|
+
next-env.d.ts
|
|
26
|
+
|
|
27
|
+
# debug
|
|
28
|
+
npm-debug.log*
|
|
29
|
+
yarn-debug.log*
|
|
30
|
+
yarn-error.log*
|
|
31
|
+
.pnpm-debug.log*
|
|
32
|
+
|
|
33
|
+
# env
|
|
34
|
+
.env
|
|
35
|
+
.env*.local
|
|
36
|
+
!.env.example
|
|
37
|
+
|
|
38
|
+
# vercel
|
|
39
|
+
.vercel
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "__PROJECT_SLUG__",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"private": true,
|
|
5
|
+
"packageManager": "pnpm@9.15.0",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"dev": "next dev --turbopack",
|
|
8
|
+
"build": "next build",
|
|
9
|
+
"start": "next start",
|
|
10
|
+
"lint": "eslint .",
|
|
11
|
+
"typecheck": "tsc --noEmit"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"next": "16.4.5",
|
|
15
|
+
"react": "19.2.8",
|
|
16
|
+
"react-dom": "19.2.8",
|
|
17
|
+
"zod": "^3.24.1"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/node": "^22.10.2",
|
|
21
|
+
"@types/react": "19.2.18",
|
|
22
|
+
"@types/react-dom": "19.2.4",
|
|
23
|
+
"eslint": "^9.17.0",
|
|
24
|
+
"eslint-config-next": "16.4.5",
|
|
25
|
+
"typescript": "^5.7.2"
|
|
26
|
+
}
|
|
27
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** Homepage sample — replace when you add real route UI. */
|
|
2
|
+
export function WelcomeCard() {
|
|
3
|
+
return (
|
|
4
|
+
<div className="card">
|
|
5
|
+
<h2>App layout</h2>
|
|
6
|
+
<ul>
|
|
7
|
+
<li>
|
|
8
|
+
Route-only UI →{" "}
|
|
9
|
+
<code>src/app/<route>/_components/<name>/index.tsx</code>
|
|
10
|
+
</li>
|
|
11
|
+
<li>
|
|
12
|
+
Layout / homepage UI → <code>src/app/_components/</code>
|
|
13
|
+
</li>
|
|
14
|
+
<li>
|
|
15
|
+
Shared across 2+ routes → <code>src/components/</code>
|
|
16
|
+
</li>
|
|
17
|
+
<li>
|
|
18
|
+
HTTP / env → <code>src/lib/</code> · API helpers →{" "}
|
|
19
|
+
<code>src/utils/</code>
|
|
20
|
+
</li>
|
|
21
|
+
</ul>
|
|
22
|
+
</div>
|
|
23
|
+
);
|
|
24
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
color-scheme: light;
|
|
3
|
+
--bg: #f6f4ef;
|
|
4
|
+
--fg: #14201b;
|
|
5
|
+
--muted: #5b6b63;
|
|
6
|
+
--accent: #0b5fff;
|
|
7
|
+
--card: #ffffff;
|
|
8
|
+
--border: #d9e0db;
|
|
9
|
+
--font: "Segoe UI", system-ui, sans-serif;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
* {
|
|
13
|
+
box-sizing: border-box;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
html,
|
|
17
|
+
body {
|
|
18
|
+
margin: 0;
|
|
19
|
+
padding: 0;
|
|
20
|
+
min-height: 100%;
|
|
21
|
+
background: radial-gradient(circle at top left, #eef3ff, transparent 40%),
|
|
22
|
+
var(--bg);
|
|
23
|
+
color: var(--fg);
|
|
24
|
+
font-family: var(--font);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
a {
|
|
28
|
+
color: var(--accent);
|
|
29
|
+
text-decoration: none;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
a:hover {
|
|
33
|
+
text-decoration: underline;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
main {
|
|
37
|
+
width: min(720px, calc(100% - 2rem));
|
|
38
|
+
margin: 0 auto;
|
|
39
|
+
padding: 4rem 0 3rem;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
.hero {
|
|
43
|
+
display: grid;
|
|
44
|
+
gap: 1rem;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.hero h1 {
|
|
48
|
+
margin: 0;
|
|
49
|
+
font-size: clamp(2rem, 5vw, 3rem);
|
|
50
|
+
letter-spacing: -0.03em;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.hero p {
|
|
54
|
+
margin: 0;
|
|
55
|
+
color: var(--muted);
|
|
56
|
+
line-height: 1.6;
|
|
57
|
+
max-width: 40rem;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.card {
|
|
61
|
+
margin-top: 2rem;
|
|
62
|
+
padding: 1.25rem 1.5rem;
|
|
63
|
+
background: var(--card);
|
|
64
|
+
border: 1px solid var(--border);
|
|
65
|
+
border-radius: 12px;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.card h2 {
|
|
69
|
+
margin: 0 0 0.5rem;
|
|
70
|
+
font-size: 1rem;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.card ul {
|
|
74
|
+
margin: 0;
|
|
75
|
+
padding-left: 1.1rem;
|
|
76
|
+
color: var(--muted);
|
|
77
|
+
line-height: 1.7;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.meta {
|
|
81
|
+
margin-top: 2rem;
|
|
82
|
+
font-size: 0.875rem;
|
|
83
|
+
color: var(--muted);
|
|
84
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Metadata } from "next";
|
|
2
|
+
|
|
3
|
+
import "./globals.css";
|
|
4
|
+
|
|
5
|
+
export const metadata: Metadata = {
|
|
6
|
+
title: "__PROJECT_NAME__",
|
|
7
|
+
description: "Generated with next-style-guide",
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export default function RootLayout({
|
|
11
|
+
children,
|
|
12
|
+
}: Readonly<{
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
}>) {
|
|
15
|
+
return (
|
|
16
|
+
<html lang="en">
|
|
17
|
+
<body>
|
|
18
|
+
<main>{children}</main>
|
|
19
|
+
</body>
|
|
20
|
+
</html>
|
|
21
|
+
);
|
|
22
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { WelcomeCard } from "@/app/_components/welcome-card";
|
|
2
|
+
|
|
3
|
+
export default function HomePage() {
|
|
4
|
+
return (
|
|
5
|
+
<>
|
|
6
|
+
<section className="hero">
|
|
7
|
+
<h1>__PROJECT_NAME__</h1>
|
|
8
|
+
<p>
|
|
9
|
+
Next.js App Router scaffold from{" "}
|
|
10
|
+
<strong>next-style-guide</strong>. Route UI lives under{" "}
|
|
11
|
+
<code>src/app/_components/</code> (or a route's{" "}
|
|
12
|
+
<code>_components/</code>); shared primitives under{" "}
|
|
13
|
+
<code>src/components/</code>; HTTP helpers under <code>src/lib/</code>.
|
|
14
|
+
</p>
|
|
15
|
+
</section>
|
|
16
|
+
|
|
17
|
+
<WelcomeCard />
|
|
18
|
+
|
|
19
|
+
<p className="meta">
|
|
20
|
+
Read <code>AGENTS.md</code> and <code>docs/style-guide/</code> before
|
|
21
|
+
adding routes.
|
|
22
|
+
</p>
|
|
23
|
+
</>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Validated public env. Import from Client Components only for NEXT_PUBLIC_*.
|
|
5
|
+
* Server-only secrets stay out of this schema until needed.
|
|
6
|
+
*/
|
|
7
|
+
const publicEnvSchema = z.object({
|
|
8
|
+
NEXT_PUBLIC_APP_URL: z.string().url().default("http://localhost:3000"),
|
|
9
|
+
NEXT_PUBLIC_API_URL: z.string().url().default("http://localhost:8000"),
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export type PublicEnv = z.infer<typeof publicEnvSchema>;
|
|
13
|
+
|
|
14
|
+
export const env: PublicEnv = publicEnvSchema.parse({
|
|
15
|
+
NEXT_PUBLIC_APP_URL: process.env.NEXT_PUBLIC_APP_URL,
|
|
16
|
+
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
|
|
17
|
+
});
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { env } from "@/lib/env";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Minimal JSON fetch helper.
|
|
5
|
+
* Prefer generated endpoints / axios helpers when that option is enabled.
|
|
6
|
+
*/
|
|
7
|
+
export async function apiFetch<T>(
|
|
8
|
+
path: string,
|
|
9
|
+
init?: RequestInit,
|
|
10
|
+
): Promise<T> {
|
|
11
|
+
const url = path.startsWith("http")
|
|
12
|
+
? path
|
|
13
|
+
: `${env.NEXT_PUBLIC_API_URL.replace(/\/$/, "")}/${path.replace(/^\//, "")}`;
|
|
14
|
+
|
|
15
|
+
const response = await fetch(url, {
|
|
16
|
+
...init,
|
|
17
|
+
headers: {
|
|
18
|
+
Accept: "application/json",
|
|
19
|
+
...(init?.headers ?? {}),
|
|
20
|
+
},
|
|
21
|
+
});
|
|
22
|
+
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
throw new Error(`API ${response.status}: ${response.statusText}`);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return response.json() as Promise<T>;
|
|
28
|
+
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2017",
|
|
4
|
+
"lib": ["dom", "dom.iterable", "esnext"],
|
|
5
|
+
"allowJs": true,
|
|
6
|
+
"skipLibCheck": true,
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noEmit": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"module": "esnext",
|
|
11
|
+
"moduleResolution": "bundler",
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"isolatedModules": true,
|
|
14
|
+
"jsx": "preserve",
|
|
15
|
+
"incremental": true,
|
|
16
|
+
"plugins": [{ "name": "next" }],
|
|
17
|
+
"paths": {
|
|
18
|
+
"@/*": ["./src/*"]
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
|
22
|
+
"exclude": ["node_modules"]
|
|
23
|
+
}
|
package/README.md
DELETED