@jgamaraalv/ts-dev-kit 1.0.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/.claude-plugin/marketplace.json +24 -0
- package/.claude-plugin/plugin.json +24 -0
- package/CHANGELOG.md +24 -0
- package/LICENSE +21 -0
- package/README.md +128 -0
- package/agents/accessibility-pro.md +139 -0
- package/agents/api-builder.md +110 -0
- package/agents/code-reviewer.md +190 -0
- package/agents/database-expert.md +138 -0
- package/agents/debugger.md +241 -0
- package/agents/docker-expert.md +51 -0
- package/agents/multi-agent-coordinator.md +378 -0
- package/agents/nextjs-expert.md +136 -0
- package/agents/performance-engineer.md +138 -0
- package/agents/playwright-expert.md +126 -0
- package/agents/react-specialist.md +97 -0
- package/agents/security-scanner.md +105 -0
- package/agents/test-generator.md +221 -0
- package/agents/typescript-pro.md +253 -0
- package/agents/ux-optimizer.md +93 -0
- package/docs/rules/orchestration.md.template +126 -0
- package/package.json +28 -0
- package/skills/bullmq/SKILL.md +225 -0
- package/skills/bullmq/references/flows-and-schedulers.md +186 -0
- package/skills/bullmq/references/job-types-and-options.md +163 -0
- package/skills/bullmq/references/patterns.md +273 -0
- package/skills/bullmq/references/production.md +308 -0
- package/skills/composition-patterns/SKILL.md +58 -0
- package/skills/composition-patterns/references/architecture-avoid-boolean-props.md +87 -0
- package/skills/composition-patterns/references/architecture-compound-components.md +107 -0
- package/skills/composition-patterns/references/patterns-children-over-render-props.md +77 -0
- package/skills/composition-patterns/references/patterns-explicit-variants.md +87 -0
- package/skills/composition-patterns/references/react19-no-forwardref.md +37 -0
- package/skills/composition-patterns/references/state-context-interface.md +194 -0
- package/skills/composition-patterns/references/state-decouple-implementation.md +96 -0
- package/skills/composition-patterns/references/state-lift-state.md +126 -0
- package/skills/conventional-commits/SKILL.md +148 -0
- package/skills/docker/SKILL.md +55 -0
- package/skills/docker/references/compose-configs.md +95 -0
- package/skills/docker/references/monorepo-dockerfile.md +111 -0
- package/skills/drizzle-pg/SKILL.md +202 -0
- package/skills/drizzle-pg/references/advanced.md +299 -0
- package/skills/drizzle-pg/references/migrations.md +214 -0
- package/skills/drizzle-pg/references/queries.md +321 -0
- package/skills/drizzle-pg/references/relations.md +272 -0
- package/skills/drizzle-pg/references/schema-pg.md +256 -0
- package/skills/drizzle-pg/references/sql-operator.md +215 -0
- package/skills/fastify-best-practices/SKILL.md +143 -0
- package/skills/fastify-best-practices/references/hooks-and-lifecycle.md +122 -0
- package/skills/fastify-best-practices/references/plugins-and-encapsulation.md +137 -0
- package/skills/fastify-best-practices/references/request-reply-errors.md +189 -0
- package/skills/fastify-best-practices/references/routes-and-handlers.md +134 -0
- package/skills/fastify-best-practices/references/server-and-options.md +127 -0
- package/skills/fastify-best-practices/references/typescript-and-logging.md +223 -0
- package/skills/fastify-best-practices/references/validation-and-serialization.md +190 -0
- package/skills/ioredis/SKILL.md +51 -0
- package/skills/ioredis/references/advanced-patterns.md +312 -0
- package/skills/ioredis/references/cluster-sentinel.md +280 -0
- package/skills/ioredis/references/connection-options.md +187 -0
- package/skills/ioredis/references/core-api.md +179 -0
- package/skills/nextjs-best-practices/SKILL.md +194 -0
- package/skills/nextjs-best-practices/references/async-patterns.md +84 -0
- package/skills/nextjs-best-practices/references/bundling.md +192 -0
- package/skills/nextjs-best-practices/references/data-patterns.md +310 -0
- package/skills/nextjs-best-practices/references/debug-tricks.md +127 -0
- package/skills/nextjs-best-practices/references/directives.md +74 -0
- package/skills/nextjs-best-practices/references/error-handling.md +237 -0
- package/skills/nextjs-best-practices/references/file-conventions.md +152 -0
- package/skills/nextjs-best-practices/references/font.md +175 -0
- package/skills/nextjs-best-practices/references/functions.md +116 -0
- package/skills/nextjs-best-practices/references/hydration-error.md +86 -0
- package/skills/nextjs-best-practices/references/image.md +184 -0
- package/skills/nextjs-best-practices/references/metadata.md +305 -0
- package/skills/nextjs-best-practices/references/parallel-routes.md +299 -0
- package/skills/nextjs-best-practices/references/route-handlers.md +154 -0
- package/skills/nextjs-best-practices/references/rsc-boundaries.md +168 -0
- package/skills/nextjs-best-practices/references/runtime-selection.md +40 -0
- package/skills/nextjs-best-practices/references/scripts.md +148 -0
- package/skills/nextjs-best-practices/references/self-hosting.md +210 -0
- package/skills/nextjs-best-practices/references/suspense-boundaries.md +67 -0
- package/skills/owasp-security-review/SKILL.md +98 -0
- package/skills/owasp-security-review/references/a01-broken-access-control.md +78 -0
- package/skills/owasp-security-review/references/a02-security-misconfiguration.md +81 -0
- package/skills/owasp-security-review/references/a03-supply-chain-failures.md +65 -0
- package/skills/owasp-security-review/references/a04-cryptographic-failures.md +82 -0
- package/skills/owasp-security-review/references/a05-injection.md +106 -0
- package/skills/owasp-security-review/references/a06-insecure-design.md +76 -0
- package/skills/owasp-security-review/references/a07-authentication-failures.md +83 -0
- package/skills/owasp-security-review/references/a08-integrity-failures.md +72 -0
- package/skills/owasp-security-review/references/a09-logging-alerting-failures.md +76 -0
- package/skills/owasp-security-review/references/a10-exceptional-conditions.md +131 -0
- package/skills/postgresql/SKILL.md +50 -0
- package/skills/postgresql/references/ddl-schema.md +300 -0
- package/skills/postgresql/references/indexes.md +257 -0
- package/skills/postgresql/references/jsonb.md +261 -0
- package/skills/postgresql/references/performance.md +291 -0
- package/skills/postgresql/references/psql-cli.md +153 -0
- package/skills/postgresql/references/queries.md +287 -0
- package/skills/postgresql/references/transactions.md +280 -0
- package/skills/react-best-practices/SKILL.md +110 -0
- package/skills/react-best-practices/references/advanced-patterns.md +91 -0
- package/skills/react-best-practices/references/async-patterns.md +233 -0
- package/skills/react-best-practices/references/bundle-optimization.md +201 -0
- package/skills/react-best-practices/references/client-patterns.md +178 -0
- package/skills/react-best-practices/references/js-performance.md +210 -0
- package/skills/react-best-practices/references/rendering-performance.md +209 -0
- package/skills/react-best-practices/references/rerender-optimization.md +316 -0
- package/skills/react-best-practices/references/server-performance.md +274 -0
- package/skills/service-worker/SKILL.md +195 -0
- package/skills/service-worker/references/api-reference.md +114 -0
- package/skills/service-worker/references/caching-strategies.md +202 -0
- package/skills/service-worker/references/push-and-sync.md +261 -0
- package/skills/typescript-conventions/SKILL.md +51 -0
- package/skills/ui-ux-guidelines/SKILL.md +105 -0
- package/skills/ui-ux-guidelines/references/accessibility-and-interaction.md +74 -0
- package/skills/ui-ux-guidelines/references/forms-content-checklist.md +126 -0
- package/skills/ui-ux-guidelines/references/layout-typography-animation.md +95 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
## Lift State into Provider Components
|
|
2
|
+
|
|
3
|
+
### Table of Contents
|
|
4
|
+
|
|
5
|
+
- [Incorrect: State Trapped Inside Component](#incorrect-state-trapped-inside-component)
|
|
6
|
+
- [Incorrect: useEffect to Sync State Up](#incorrect-useeffect-to-sync-state-up)
|
|
7
|
+
- [Incorrect: Reading State from Ref on Submit](#incorrect-reading-state-from-ref-on-submit)
|
|
8
|
+
- [Correct: State Lifted to Provider](#correct-state-lifted-to-provider)
|
|
9
|
+
- [Key Insight](#key-insight)
|
|
10
|
+
|
|
11
|
+
Move state management into dedicated provider components. This allows sibling
|
|
12
|
+
components outside the main UI to access and modify state without prop drilling
|
|
13
|
+
or awkward refs.
|
|
14
|
+
|
|
15
|
+
**Incorrect (state trapped inside component):**
|
|
16
|
+
|
|
17
|
+
```tsx
|
|
18
|
+
function ForwardMessageComposer() {
|
|
19
|
+
const [state, setState] = useState(initialState);
|
|
20
|
+
const forwardMessage = useForwardMessage();
|
|
21
|
+
|
|
22
|
+
return (
|
|
23
|
+
<Composer.Frame>
|
|
24
|
+
<Composer.Input />
|
|
25
|
+
<Composer.Footer />
|
|
26
|
+
</Composer.Frame>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Problem: How does this button access composer state?
|
|
31
|
+
function ForwardMessageDialog() {
|
|
32
|
+
return (
|
|
33
|
+
<Dialog>
|
|
34
|
+
<ForwardMessageComposer />
|
|
35
|
+
<MessagePreview /> {/* Needs composer state */}
|
|
36
|
+
<DialogActions>
|
|
37
|
+
<CancelButton />
|
|
38
|
+
<ForwardButton /> {/* Needs to call submit */}
|
|
39
|
+
</DialogActions>
|
|
40
|
+
</Dialog>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Incorrect (useEffect to sync state up):**
|
|
46
|
+
|
|
47
|
+
```tsx
|
|
48
|
+
function ForwardMessageDialog() {
|
|
49
|
+
const [input, setInput] = useState("");
|
|
50
|
+
return (
|
|
51
|
+
<Dialog>
|
|
52
|
+
<ForwardMessageComposer onInputChange={setInput} />
|
|
53
|
+
<MessagePreview input={input} />
|
|
54
|
+
</Dialog>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function ForwardMessageComposer({ onInputChange }) {
|
|
59
|
+
const [state, setState] = useState(initialState);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
onInputChange(state.input); // Sync on every change 😬
|
|
62
|
+
}, [state.input]);
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
**Incorrect (reading state from ref on submit):**
|
|
67
|
+
|
|
68
|
+
```tsx
|
|
69
|
+
function ForwardMessageDialog() {
|
|
70
|
+
const stateRef = useRef(null);
|
|
71
|
+
return (
|
|
72
|
+
<Dialog>
|
|
73
|
+
<ForwardMessageComposer stateRef={stateRef} />
|
|
74
|
+
<ForwardButton onPress={() => submit(stateRef.current)} />
|
|
75
|
+
</Dialog>
|
|
76
|
+
);
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Correct (state lifted to provider):**
|
|
81
|
+
|
|
82
|
+
```tsx
|
|
83
|
+
function ForwardMessageProvider({ children }: { children: React.ReactNode }) {
|
|
84
|
+
const [state, setState] = useState(initialState);
|
|
85
|
+
const forwardMessage = useForwardMessage();
|
|
86
|
+
const inputRef = useRef(null);
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<Composer.Provider
|
|
90
|
+
state={state}
|
|
91
|
+
actions={{ update: setState, submit: forwardMessage }}
|
|
92
|
+
meta={{ inputRef }}
|
|
93
|
+
>
|
|
94
|
+
{children}
|
|
95
|
+
</Composer.Provider>
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function ForwardMessageDialog() {
|
|
100
|
+
return (
|
|
101
|
+
<ForwardMessageProvider>
|
|
102
|
+
<Dialog>
|
|
103
|
+
<ForwardMessageComposer />
|
|
104
|
+
<MessagePreview /> {/* Custom components can access state and actions */}
|
|
105
|
+
<DialogActions>
|
|
106
|
+
<CancelButton />
|
|
107
|
+
<ForwardButton /> {/* Custom components can access state and actions */}
|
|
108
|
+
</DialogActions>
|
|
109
|
+
</Dialog>
|
|
110
|
+
</ForwardMessageProvider>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function ForwardButton() {
|
|
115
|
+
const { actions } = use(Composer.Context);
|
|
116
|
+
return <Button onPress={actions.submit}>Forward</Button>;
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
The ForwardButton lives outside the Composer.Frame but still has access to the
|
|
121
|
+
submit action because it's within the provider. Even though it's a one-off
|
|
122
|
+
component, it can still access the composer's state and actions from outside the
|
|
123
|
+
UI itself.
|
|
124
|
+
|
|
125
|
+
**Key insight:** Components that need shared state don't have to be visually
|
|
126
|
+
nested inside each other—they just need to be within the same provider.
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: conventional-commits
|
|
3
|
+
description: "Write, review, and validate commit messages following the Conventional Commits v1.0.0 specification. Use when: (1) crafting a git commit message for any change, (2) reviewing or correcting an existing commit message, (3) choosing the right commit type for a change, (4) deciding how to mark a breaking change, (5) writing multi-line commits with body and footers, or (6) understanding how commits map to SemVer bumps (PATCH/MINOR/MAJOR). Covers all standard types: feat, fix, docs, chore, refactor, perf, test, build, ci, style, revert."
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
## Table of Contents
|
|
7
|
+
|
|
8
|
+
- [Format](#format)
|
|
9
|
+
- [Types and SemVer impact](#types-and-semver-impact)
|
|
10
|
+
- [Breaking changes](#breaking-changes)
|
|
11
|
+
- [Examples](#examples)
|
|
12
|
+
- [Non-obvious rules](#non-obvious-rules)
|
|
13
|
+
- [Choosing the right type](#choosing-the-right-type)
|
|
14
|
+
- [SemVer cheatsheet](#semver-cheatsheet)
|
|
15
|
+
|
|
16
|
+
## Format
|
|
17
|
+
|
|
18
|
+
```
|
|
19
|
+
<type>[optional scope]: <description>
|
|
20
|
+
|
|
21
|
+
[optional body]
|
|
22
|
+
|
|
23
|
+
[optional footer(s)]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
- **type**: lowercase noun (see table below)
|
|
27
|
+
- **scope**: optional noun in parentheses describing the affected section, e.g. `feat(auth):`
|
|
28
|
+
- **description**: imperative, present tense, no period at end, immediately after `": "`
|
|
29
|
+
- **body**: free-form; begins one blank line after description
|
|
30
|
+
- **footers**: one blank line after body; follow git trailer format (`Token: value` or `Token #value`)
|
|
31
|
+
|
|
32
|
+
## Types and SemVer impact
|
|
33
|
+
|
|
34
|
+
| Type | Use for | SemVer |
|
|
35
|
+
| ---------- | -------------------------------------------- | ------ |
|
|
36
|
+
| `feat` | New feature | MINOR |
|
|
37
|
+
| `fix` | Bug fix | PATCH |
|
|
38
|
+
| `docs` | Documentation only | none |
|
|
39
|
+
| `style` | Formatting, whitespace (no logic change) | none |
|
|
40
|
+
| `refactor` | Code restructure (not a fix or feature) | none |
|
|
41
|
+
| `perf` | Performance improvement | none |
|
|
42
|
+
| `test` | Adding or fixing tests | none |
|
|
43
|
+
| `build` | Build system, dependencies (npm, gradle…) | none |
|
|
44
|
+
| `ci` | CI configuration (GitHub Actions, CircleCI…) | none |
|
|
45
|
+
| `chore` | Maintenance not fitting above types | none |
|
|
46
|
+
| `revert` | Reverts a previous commit | none |
|
|
47
|
+
|
|
48
|
+
Any type + `BREAKING CHANGE` → **MAJOR**.
|
|
49
|
+
|
|
50
|
+
## Breaking changes
|
|
51
|
+
|
|
52
|
+
Two ways to signal a breaking change (can combine both):
|
|
53
|
+
|
|
54
|
+
**1. `!` after type/scope** (visible at a glance):
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
feat(api)!: remove deprecated v1 endpoints
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
**2. `BREAKING CHANGE:` footer** (required if you need a description):
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
feat: allow config object to extend other configs
|
|
64
|
+
|
|
65
|
+
BREAKING CHANGE: `extends` key now used for extending config files
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Both together:
|
|
69
|
+
|
|
70
|
+
```
|
|
71
|
+
chore!: drop support for Node 6
|
|
72
|
+
|
|
73
|
+
BREAKING CHANGE: use JavaScript features not available in Node 6.
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Examples
|
|
77
|
+
|
|
78
|
+
**Simple fix:**
|
|
79
|
+
|
|
80
|
+
```
|
|
81
|
+
fix: prevent racing of requests
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Feature with scope:**
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
feat(lang): add Polish language
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Fix with body and footers:**
|
|
91
|
+
|
|
92
|
+
```
|
|
93
|
+
fix: prevent racing of requests
|
|
94
|
+
|
|
95
|
+
Introduce a request id and a reference to latest request. Dismiss
|
|
96
|
+
incoming responses other than from latest request.
|
|
97
|
+
|
|
98
|
+
Remove timeouts which were used to mitigate the racing issue but are
|
|
99
|
+
obsolete now.
|
|
100
|
+
|
|
101
|
+
Reviewed-by: Z
|
|
102
|
+
Refs: #123
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
**Revert with footer references:**
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
revert: let us never again speak of the noodle incident
|
|
109
|
+
|
|
110
|
+
Refs: 676104e, a215868
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Docs with no body:**
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
docs: correct spelling of CHANGELOG
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Non-obvious rules
|
|
120
|
+
|
|
121
|
+
- **NEVER** add `Co-Authored-By` trailers to commit messages. This project does not use authorship footers.
|
|
122
|
+
- Types are **case-insensitive** in parsing, but `BREAKING CHANGE` footer token **must be uppercase**.
|
|
123
|
+
- `BREAKING-CHANGE` (hyphen) is a valid synonym for `BREAKING CHANGE` in footers.
|
|
124
|
+
- Footer tokens use `-` instead of spaces (e.g. `Reviewed-by`), **except** `BREAKING CHANGE`.
|
|
125
|
+
- Footer separator is either `": "` (colon-space) or `" #"` (space-hash for issue refs): `Refs #123`.
|
|
126
|
+
- A footer value may span multiple lines; parsing stops at the next valid `Token: ` or `Token #` pair.
|
|
127
|
+
- When a commit fits multiple types, split into multiple commits instead of picking one.
|
|
128
|
+
- Wrong type used before merge? Ask the developer to fix manually with an interactive rebase. Claude Code cannot run interactive commands. After release, the commit is simply missed by automation tools — not catastrophic.
|
|
129
|
+
- Squash workflows: lead maintainer can rewrite messages at merge time; contributors don't need to follow the spec perfectly on every WIP commit.
|
|
130
|
+
|
|
131
|
+
## Choosing the right type
|
|
132
|
+
|
|
133
|
+
```
|
|
134
|
+
Is it a new user-facing capability? → feat
|
|
135
|
+
Is it fixing incorrect behavior? → fix
|
|
136
|
+
Is it changing docs/comments only? → docs
|
|
137
|
+
Is it improving speed/memory? → perf
|
|
138
|
+
Is it reorganizing code (no behavior Δ)? → refactor
|
|
139
|
+
Is it adding/fixing tests only? → test
|
|
140
|
+
Is it CI pipeline config? → ci
|
|
141
|
+
Is it build tooling or dependency updates? → build
|
|
142
|
+
Is it undoing a previous commit? → revert
|
|
143
|
+
Everything else (scripts, config, etc.)? → chore
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## SemVer cheatsheet
|
|
147
|
+
|
|
148
|
+
`fix`→PATCH, `feat`→MINOR, `BREAKING CHANGE`→MAJOR
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: docker
|
|
3
|
+
|
|
4
|
+
description: "Docker containerization reference — multi-stage builds, Compose configs, image optimization, and container security for Yarn 4 monorepos. Use when: (1) creating or optimizing Dockerfiles, (2) configuring docker-compose for dev or production, (3) reducing image size with multi-stage builds, (4) hardening container security, or (5) setting up health checks and resource limits."
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
# Docker — Containerization for Monorepos
|
|
8
|
+
|
|
9
|
+
Docker best practices for Node.js monorepos with Yarn 4 Berry.
|
|
10
|
+
|
|
11
|
+
## When to Load References
|
|
12
|
+
|
|
13
|
+
| Need | Reference file |
|
|
14
|
+
| -------------------------------------------------- | ---------------------------------------------------------------------- |
|
|
15
|
+
| Writing or reviewing a Dockerfile for the monorepo | [references/monorepo-dockerfile.md](references/monorepo-dockerfile.md) |
|
|
16
|
+
| Configuring docker-compose for dev or production | [references/compose-configs.md](references/compose-configs.md) |
|
|
17
|
+
|
|
18
|
+
## Key Principles
|
|
19
|
+
|
|
20
|
+
- **Minimal images**: Alpine-based, only runtime dependencies in final stage
|
|
21
|
+
- **Layer caching order**: system deps → package manifests → install → source → build
|
|
22
|
+
- **Non-root users**: Create `app` user, never run as root in production
|
|
23
|
+
- **One process per container**: Compose multiple containers, not multiple processes
|
|
24
|
+
- **Health checks on every service**: Use the existing `/health` endpoint
|
|
25
|
+
|
|
26
|
+
## Image Optimization Quick Reference
|
|
27
|
+
|
|
28
|
+
- Use `node:22-alpine` as base
|
|
29
|
+
- Multi-stage builds: exclude build tools from final image
|
|
30
|
+
- `yarn cache clean` after install
|
|
31
|
+
- `.dockerignore`: exclude `.git`, `node_modules`, `*.md`, `.env*`, `.claude`, `__tests__`, `coverage`, `.turbo`
|
|
32
|
+
- `--production` flag for runtime dependencies only
|
|
33
|
+
- Pin base image versions (not just `latest`)
|
|
34
|
+
|
|
35
|
+
## Container Security Quick Reference
|
|
36
|
+
|
|
37
|
+
- Run as non-root user (`addgroup --system app && adduser --system --ingroup app app`)
|
|
38
|
+
- Don't store secrets in images — use env vars or secrets management
|
|
39
|
+
- Scan images: `docker scout cves <image>`
|
|
40
|
+
- Set resource limits in compose: `mem_limit`, `cpus`
|
|
41
|
+
- Read-only filesystem where possible: `read_only: true`
|
|
42
|
+
- Drop capabilities: `cap_drop: [ALL]`
|
|
43
|
+
|
|
44
|
+
## Useful Commands
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
docker compose build api # Build specific service
|
|
48
|
+
docker compose up -d # Start all services
|
|
49
|
+
docker compose logs -f api # Follow logs
|
|
50
|
+
docker compose exec api sh # Shell into container
|
|
51
|
+
docker images | grep myapp # Check image sizes
|
|
52
|
+
docker system df # View cache usage
|
|
53
|
+
docker system prune -a # Prune unused images
|
|
54
|
+
docker stats # Resource usage
|
|
55
|
+
```
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
# Docker Compose Configurations
|
|
2
|
+
|
|
3
|
+
## Development (`docker-compose.yml`)
|
|
4
|
+
|
|
5
|
+
Infrastructure services only — app runs natively via `yarn dev`.
|
|
6
|
+
|
|
7
|
+
```yaml
|
|
8
|
+
services:
|
|
9
|
+
postgres:
|
|
10
|
+
image: postgis/postgis:16-3.4-alpine
|
|
11
|
+
restart: unless-stopped
|
|
12
|
+
environment:
|
|
13
|
+
POSTGRES_USER: ${POSTGRES_USER:-myapp}
|
|
14
|
+
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-myapp}
|
|
15
|
+
POSTGRES_DB: ${POSTGRES_DB:-myapp}
|
|
16
|
+
ports:
|
|
17
|
+
- "${POSTGRES_PORT:-5432}:5432"
|
|
18
|
+
volumes:
|
|
19
|
+
- postgres_data:/var/lib/postgresql/data
|
|
20
|
+
healthcheck:
|
|
21
|
+
test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-myapp}"]
|
|
22
|
+
interval: 10s
|
|
23
|
+
timeout: 5s
|
|
24
|
+
retries: 5
|
|
25
|
+
|
|
26
|
+
redis:
|
|
27
|
+
image: redis:7-alpine
|
|
28
|
+
restart: unless-stopped
|
|
29
|
+
ports:
|
|
30
|
+
- "${REDIS_PORT:-6379}:6379"
|
|
31
|
+
volumes:
|
|
32
|
+
- redis_data:/data
|
|
33
|
+
healthcheck:
|
|
34
|
+
test: ["CMD", "redis-cli", "ping"]
|
|
35
|
+
interval: 10s
|
|
36
|
+
timeout: 5s
|
|
37
|
+
retries: 5
|
|
38
|
+
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
|
|
39
|
+
|
|
40
|
+
volumes:
|
|
41
|
+
postgres_data:
|
|
42
|
+
redis_data:
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Production Override (`docker-compose.prod.yml`)
|
|
46
|
+
|
|
47
|
+
Adds containerized app services on top of infrastructure.
|
|
48
|
+
|
|
49
|
+
```yaml
|
|
50
|
+
services:
|
|
51
|
+
api:
|
|
52
|
+
build:
|
|
53
|
+
context: .
|
|
54
|
+
dockerfile: apps/api/Dockerfile
|
|
55
|
+
target: api-runner
|
|
56
|
+
restart: unless-stopped
|
|
57
|
+
ports:
|
|
58
|
+
- "3001:3001"
|
|
59
|
+
environment:
|
|
60
|
+
NODE_ENV: production
|
|
61
|
+
DATABASE_URL: postgres://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}
|
|
62
|
+
REDIS_URL: redis://redis:6379
|
|
63
|
+
depends_on:
|
|
64
|
+
postgres:
|
|
65
|
+
condition: service_healthy
|
|
66
|
+
redis:
|
|
67
|
+
condition: service_healthy
|
|
68
|
+
|
|
69
|
+
web:
|
|
70
|
+
build:
|
|
71
|
+
context: .
|
|
72
|
+
dockerfile: apps/web/Dockerfile
|
|
73
|
+
target: web-runner
|
|
74
|
+
restart: unless-stopped
|
|
75
|
+
ports:
|
|
76
|
+
- "3000:3000"
|
|
77
|
+
environment:
|
|
78
|
+
NODE_ENV: production
|
|
79
|
+
API_URL: http://api:3001
|
|
80
|
+
depends_on:
|
|
81
|
+
- api
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Health Checks
|
|
85
|
+
|
|
86
|
+
Every service should have a health check:
|
|
87
|
+
|
|
88
|
+
```yaml
|
|
89
|
+
healthcheck:
|
|
90
|
+
test: ["CMD", "wget", "--spider", "--quiet", "http://localhost:3001/health"]
|
|
91
|
+
interval: 30s
|
|
92
|
+
timeout: 5s
|
|
93
|
+
start_period: 10s
|
|
94
|
+
retries: 3
|
|
95
|
+
```
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
# Multi-Stage Dockerfile for Yarn 4 Monorepo
|
|
2
|
+
|
|
3
|
+
## API Dockerfile (`apps/api/Dockerfile`)
|
|
4
|
+
|
|
5
|
+
```dockerfile
|
|
6
|
+
# ============================================
|
|
7
|
+
# Stage 1: Base with Yarn 4 Berry
|
|
8
|
+
# ============================================
|
|
9
|
+
FROM node:22-alpine AS base
|
|
10
|
+
ENV YARN_ENABLE_GLOBAL_CACHE=false
|
|
11
|
+
WORKDIR /app
|
|
12
|
+
|
|
13
|
+
# Install Yarn Berry
|
|
14
|
+
COPY .yarnrc.yml ./
|
|
15
|
+
COPY .yarn/ .yarn/
|
|
16
|
+
COPY package.json yarn.lock ./
|
|
17
|
+
|
|
18
|
+
# ============================================
|
|
19
|
+
# Stage 2: Install ALL dependencies (for building)
|
|
20
|
+
# ============================================
|
|
21
|
+
FROM base AS deps
|
|
22
|
+
# Copy all workspace package.json files
|
|
23
|
+
COPY apps/api/package.json apps/api/
|
|
24
|
+
COPY apps/web/package.json apps/web/
|
|
25
|
+
COPY packages/shared/package.json packages/shared/
|
|
26
|
+
COPY packages/config/package.json packages/config/
|
|
27
|
+
RUN yarn install --immutable
|
|
28
|
+
|
|
29
|
+
# ============================================
|
|
30
|
+
# Stage 3: Build shared packages first
|
|
31
|
+
# ============================================
|
|
32
|
+
FROM deps AS builder
|
|
33
|
+
COPY . .
|
|
34
|
+
# Build in dependency order
|
|
35
|
+
RUN yarn workspace @myapp/shared build
|
|
36
|
+
RUN yarn workspace @myapp/api build
|
|
37
|
+
# Or for web: RUN yarn workspace @myapp/web build
|
|
38
|
+
|
|
39
|
+
# ============================================
|
|
40
|
+
# Stage 4: Production runtime (API)
|
|
41
|
+
# ============================================
|
|
42
|
+
FROM node:22-alpine AS api-runner
|
|
43
|
+
WORKDIR /app
|
|
44
|
+
|
|
45
|
+
# Security: non-root user
|
|
46
|
+
RUN addgroup --system app && adduser --system --ingroup app app
|
|
47
|
+
|
|
48
|
+
# Copy only production dependencies and built output
|
|
49
|
+
COPY --from=builder /app/apps/api/dist ./apps/api/dist
|
|
50
|
+
COPY --from=builder /app/apps/api/package.json ./apps/api/
|
|
51
|
+
COPY --from=builder /app/packages/shared/dist ./packages/shared/dist
|
|
52
|
+
COPY --from=builder /app/packages/shared/package.json ./packages/shared/
|
|
53
|
+
COPY --from=builder /app/package.json ./
|
|
54
|
+
COPY --from=builder /app/yarn.lock ./
|
|
55
|
+
COPY --from=builder /app/.yarnrc.yml ./
|
|
56
|
+
COPY --from=builder /app/.yarn/ ./.yarn/
|
|
57
|
+
|
|
58
|
+
# Install production dependencies only
|
|
59
|
+
RUN yarn workspaces focus @myapp/api --production && yarn cache clean
|
|
60
|
+
|
|
61
|
+
USER app
|
|
62
|
+
EXPOSE 3001
|
|
63
|
+
|
|
64
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
|
|
65
|
+
CMD wget --no-verbose --tries=1 --spider http://localhost:3001/health || exit 1
|
|
66
|
+
|
|
67
|
+
CMD ["node", "apps/api/dist/index.js"]
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Layer Caching Order
|
|
71
|
+
|
|
72
|
+
```dockerfile
|
|
73
|
+
# 1. System dependencies (rarely change)
|
|
74
|
+
RUN apk add --no-cache ...
|
|
75
|
+
|
|
76
|
+
# 2. Package manifests (change on dependency update)
|
|
77
|
+
COPY package.json yarn.lock ./
|
|
78
|
+
|
|
79
|
+
# 3. Install dependencies (cached unless manifests change)
|
|
80
|
+
RUN yarn install --immutable
|
|
81
|
+
|
|
82
|
+
# 4. Source code (changes most frequently)
|
|
83
|
+
COPY . .
|
|
84
|
+
|
|
85
|
+
# 5. Build
|
|
86
|
+
RUN yarn build
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## .dockerignore
|
|
90
|
+
|
|
91
|
+
```
|
|
92
|
+
.git
|
|
93
|
+
node_modules
|
|
94
|
+
*.md
|
|
95
|
+
.env*
|
|
96
|
+
.vscode
|
|
97
|
+
.claude
|
|
98
|
+
**/__tests__
|
|
99
|
+
**/*.test.ts
|
|
100
|
+
**/*.spec.ts
|
|
101
|
+
coverage
|
|
102
|
+
.turbo
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Size Reduction Tips
|
|
106
|
+
|
|
107
|
+
- Use Alpine-based images (`node:22-alpine`)
|
|
108
|
+
- Multi-stage builds to exclude build tools from final image
|
|
109
|
+
- `yarn cache clean` after install
|
|
110
|
+
- Don't copy `.git`, `node_modules`, or test files
|
|
111
|
+
- Use `--production` flag for runtime dependencies only
|