@girardmedia/bootspring 3.3.2 → 3.4.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.
Files changed (171) hide show
  1. package/assets/agents/accessibility-auditor.md +39 -0
  2. package/assets/agents/api-designer.md +40 -0
  3. package/assets/agents/auth-implementer.md +64 -0
  4. package/assets/agents/bug-hunter.md +42 -0
  5. package/assets/agents/bundle-analyzer.md +40 -0
  6. package/assets/agents/cache-optimizer.md +55 -0
  7. package/assets/agents/changelog-writer.md +55 -0
  8. package/assets/agents/ci-cd-builder.md +40 -0
  9. package/assets/agents/code-explainer.md +39 -0
  10. package/assets/agents/code-reviewer.md +39 -0
  11. package/assets/agents/cost-optimizer.md +57 -0
  12. package/assets/agents/cron-scheduler.md +51 -0
  13. package/assets/agents/data-seeder.md +56 -0
  14. package/assets/agents/database-architect.md +40 -0
  15. package/assets/agents/dependency-updater.md +40 -0
  16. package/assets/agents/deploy-checker.md +40 -0
  17. package/assets/agents/docker-optimizer.md +40 -0
  18. package/assets/agents/documentation-writer.md +40 -0
  19. package/assets/agents/email-builder.md +55 -0
  20. package/assets/agents/env-setup.md +40 -0
  21. package/assets/agents/error-handler.md +40 -0
  22. package/assets/agents/eslint-fixer.md +46 -0
  23. package/assets/agents/feature-flagger.md +69 -0
  24. package/assets/agents/git-detective.md +39 -0
  25. package/assets/agents/graphql-builder.md +60 -0
  26. package/assets/agents/incident-responder.md +59 -0
  27. package/assets/agents/log-analyzer.md +39 -0
  28. package/assets/agents/migration-planner.md +41 -0
  29. package/assets/agents/monorepo-navigator.md +39 -0
  30. package/assets/agents/nextjs-expert.md +57 -0
  31. package/assets/agents/notification-builder.md +56 -0
  32. package/assets/agents/onboarding-guide.md +39 -0
  33. package/assets/agents/performance-profiler.md +40 -0
  34. package/assets/agents/prisma-expert.md +57 -0
  35. package/assets/agents/rate-limiter.md +58 -0
  36. package/assets/agents/react-expert.md +58 -0
  37. package/assets/agents/refactorer.md +42 -0
  38. package/assets/agents/regex-builder.md +46 -0
  39. package/assets/agents/release-manager.md +40 -0
  40. package/assets/agents/s3-manager.md +58 -0
  41. package/assets/agents/schema-validator.md +40 -0
  42. package/assets/agents/search-builder.md +62 -0
  43. package/assets/agents/security-auditor.md +39 -0
  44. package/assets/agents/sitemap-generator.md +53 -0
  45. package/assets/agents/stripe-integrator.md +59 -0
  46. package/assets/agents/tailwind-expert.md +55 -0
  47. package/assets/agents/tech-debt-tracker.md +39 -0
  48. package/assets/agents/test-writer.md +42 -0
  49. package/assets/agents/type-fixer.md +45 -0
  50. package/assets/agents/webhook-builder.md +54 -0
  51. package/assets/rules/cpp.md +53 -0
  52. package/assets/rules/css.md +52 -0
  53. package/assets/rules/go.md +50 -0
  54. package/assets/rules/html.md +52 -0
  55. package/assets/rules/java.md +51 -0
  56. package/assets/rules/kotlin.md +50 -0
  57. package/assets/rules/php.md +51 -0
  58. package/assets/rules/python.md +51 -0
  59. package/assets/rules/ruby.md +51 -0
  60. package/assets/rules/rust.md +49 -0
  61. package/assets/rules/shell.md +52 -0
  62. package/assets/rules/sql.md +49 -0
  63. package/assets/rules/swift.md +50 -0
  64. package/assets/rules/typescript.md +52 -0
  65. package/assets/rules/yaml-json.md +51 -0
  66. package/assets/skills/accessibility.md +210 -0
  67. package/assets/skills/agent-patterns.md +387 -0
  68. package/assets/skills/ai-integration.md +263 -0
  69. package/assets/skills/animation-patterns.md +224 -0
  70. package/assets/skills/api-design.md +218 -0
  71. package/assets/skills/api-gateway.md +341 -0
  72. package/assets/skills/api-versioning.md +226 -0
  73. package/assets/skills/astro-patterns.md +233 -0
  74. package/assets/skills/auth-patterns.md +248 -0
  75. package/assets/skills/aws-patterns.md +171 -0
  76. package/assets/skills/background-jobs.md +162 -0
  77. package/assets/skills/browser-extensions.md +309 -0
  78. package/assets/skills/caching-patterns.md +253 -0
  79. package/assets/skills/ci-cd.md +251 -0
  80. package/assets/skills/cli-development.md +296 -0
  81. package/assets/skills/code-review.md +185 -0
  82. package/assets/skills/cron-patterns.md +327 -0
  83. package/assets/skills/data-fetching.md +231 -0
  84. package/assets/skills/database-migrations.md +346 -0
  85. package/assets/skills/database-patterns.md +219 -0
  86. package/assets/skills/debugging.md +281 -0
  87. package/assets/skills/design-system.md +289 -0
  88. package/assets/skills/django-patterns.md +182 -0
  89. package/assets/skills/docker-patterns.md +235 -0
  90. package/assets/skills/e2e-testing.md +287 -0
  91. package/assets/skills/edge-computing.md +268 -0
  92. package/assets/skills/electron-patterns.md +266 -0
  93. package/assets/skills/email-templates.md +206 -0
  94. package/assets/skills/error-handling.md +265 -0
  95. package/assets/skills/event-driven.md +232 -0
  96. package/assets/skills/express-patterns.md +239 -0
  97. package/assets/skills/fastapi-patterns.md +198 -0
  98. package/assets/skills/feature-flags.md +212 -0
  99. package/assets/skills/figma-to-code.md +298 -0
  100. package/assets/skills/file-upload.md +228 -0
  101. package/assets/skills/forms-patterns.md +264 -0
  102. package/assets/skills/gcp-patterns.md +189 -0
  103. package/assets/skills/git-workflow.md +187 -0
  104. package/assets/skills/golang-patterns.md +185 -0
  105. package/assets/skills/graphql-patterns.md +244 -0
  106. package/assets/skills/i18n-patterns.md +172 -0
  107. package/assets/skills/image-processing.md +350 -0
  108. package/assets/skills/java-springboot.md +226 -0
  109. package/assets/skills/kotlin-patterns.md +207 -0
  110. package/assets/skills/kubernetes-patterns.md +326 -0
  111. package/assets/skills/laravel-patterns.md +261 -0
  112. package/assets/skills/llm-fine-tuning.md +335 -0
  113. package/assets/skills/load-testing.md +303 -0
  114. package/assets/skills/logging-observability.md +228 -0
  115. package/assets/skills/markdown-processing.md +318 -0
  116. package/assets/skills/mcp-server-patterns.md +292 -0
  117. package/assets/skills/microservices.md +272 -0
  118. package/assets/skills/migration-patterns.md +239 -0
  119. package/assets/skills/mongodb-patterns.md +189 -0
  120. package/assets/skills/monorepo-patterns.md +287 -0
  121. package/assets/skills/nextjs-app-router.md +237 -0
  122. package/assets/skills/notification-patterns.md +348 -0
  123. package/assets/skills/oauth-patterns.md +246 -0
  124. package/assets/skills/payment-integration.md +222 -0
  125. package/assets/skills/pdf-generation.md +307 -0
  126. package/assets/skills/performance-optimization.md +277 -0
  127. package/assets/skills/php-patterns.md +210 -0
  128. package/assets/skills/prisma-patterns.md +241 -0
  129. package/assets/skills/prompt-engineering.md +193 -0
  130. package/assets/skills/pwa-patterns.md +247 -0
  131. package/assets/skills/python-patterns.md +158 -0
  132. package/assets/skills/python-testing.md +172 -0
  133. package/assets/skills/queue-patterns.md +295 -0
  134. package/assets/skills/rag-patterns.md +159 -0
  135. package/assets/skills/rate-limiting.md +319 -0
  136. package/assets/skills/react-components.md +201 -0
  137. package/assets/skills/react-native-patterns.md +299 -0
  138. package/assets/skills/real-time-patterns.md +181 -0
  139. package/assets/skills/redis-patterns.md +188 -0
  140. package/assets/skills/refactoring.md +218 -0
  141. package/assets/skills/regex-patterns.md +191 -0
  142. package/assets/skills/remix-patterns.md +262 -0
  143. package/assets/skills/responsive-design.md +199 -0
  144. package/assets/skills/ruby-rails-patterns.md +178 -0
  145. package/assets/skills/rust-patterns.md +211 -0
  146. package/assets/skills/search-patterns.md +227 -0
  147. package/assets/skills/security-hardening.md +237 -0
  148. package/assets/skills/seo-patterns.md +179 -0
  149. package/assets/skills/serverless-patterns.md +223 -0
  150. package/assets/skills/sql-optimization.md +154 -0
  151. package/assets/skills/state-management.md +254 -0
  152. package/assets/skills/storybook-patterns.md +330 -0
  153. package/assets/skills/svelte-patterns.md +258 -0
  154. package/assets/skills/swift-patterns.md +227 -0
  155. package/assets/skills/tailwind-patterns.md +272 -0
  156. package/assets/skills/tdd-workflow.md +199 -0
  157. package/assets/skills/terraform-patterns.md +270 -0
  158. package/assets/skills/testing-react.md +240 -0
  159. package/assets/skills/testing-vitest.md +232 -0
  160. package/assets/skills/typescript-strict.md +159 -0
  161. package/assets/skills/video-processing.md +340 -0
  162. package/assets/skills/vue-patterns.md +247 -0
  163. package/assets/skills/web-workers.md +327 -0
  164. package/assets/skills/webhooks-patterns.md +283 -0
  165. package/assets/skills/websocket-patterns.md +306 -0
  166. package/dist/cli/index.js +941 -958
  167. package/dist/core/index.d.ts +341 -11
  168. package/dist/core.js +58 -95
  169. package/dist/mcp/index.d.ts +33 -1
  170. package/dist/mcp-server.js +177 -255
  171. package/package.json +4 -1
@@ -0,0 +1,264 @@
1
+ ---
2
+ name: forms-patterns
3
+ description: Form patterns with React Hook Form, Zod validation, multi-step forms, file uploads, and optimistic submission.
4
+ ---
5
+
6
+ # Form Patterns
7
+
8
+ ## When to Use
9
+ Apply when building user input forms in React applications. Use React Hook Form for performance, Zod for type-safe validation, multi-step wizards for complex flows, and optimistic submission for snappy UX. These patterns prevent common pitfalls: re-renders, unvalidated submissions, and poor error feedback.
10
+
11
+ ## How It Works
12
+
13
+ ### React Hook Form + Zod Validation
14
+
15
+ Type-safe forms with zero re-renders on input change:
16
+
17
+ ```typescript
18
+ import { useForm } from "react-hook-form";
19
+ import { zodResolver } from "@hookform/resolvers/zod";
20
+ import { z } from "zod";
21
+
22
+ const signupSchema = z.object({
23
+ name: z.string().min(2, "Name must be at least 2 characters"),
24
+ email: z.string().email("Invalid email address"),
25
+ password: z
26
+ .string()
27
+ .min(8, "Password must be at least 8 characters")
28
+ .regex(/[A-Z]/, "Must contain an uppercase letter")
29
+ .regex(/[0-9]/, "Must contain a number"),
30
+ confirmPassword: z.string(),
31
+ }).refine((data) => data.password === data.confirmPassword, {
32
+ message: "Passwords do not match",
33
+ path: ["confirmPassword"],
34
+ });
35
+
36
+ type SignupForm = z.infer<typeof signupSchema>;
37
+
38
+ function SignupPage() {
39
+ const {
40
+ register,
41
+ handleSubmit,
42
+ formState: { errors, isSubmitting },
43
+ } = useForm<SignupForm>({
44
+ resolver: zodResolver(signupSchema),
45
+ });
46
+
47
+ const onSubmit = async (data: SignupForm) => {
48
+ await fetch("/api/auth/signup", {
49
+ method: "POST",
50
+ headers: { "Content-Type": "application/json" },
51
+ body: JSON.stringify(data),
52
+ });
53
+ };
54
+
55
+ return (
56
+ <form onSubmit={handleSubmit(onSubmit)} noValidate>
57
+ <div>
58
+ <label htmlFor="name">Name</label>
59
+ <input id="name" {...register("name")} />
60
+ {errors.name && <p role="alert">{errors.name.message}</p>}
61
+ </div>
62
+ <div>
63
+ <label htmlFor="email">Email</label>
64
+ <input id="email" type="email" {...register("email")} />
65
+ {errors.email && <p role="alert">{errors.email.message}</p>}
66
+ </div>
67
+ <div>
68
+ <label htmlFor="password">Password</label>
69
+ <input id="password" type="password" {...register("password")} />
70
+ {errors.password && <p role="alert">{errors.password.message}</p>}
71
+ </div>
72
+ <div>
73
+ <label htmlFor="confirmPassword">Confirm Password</label>
74
+ <input id="confirmPassword" type="password" {...register("confirmPassword")} />
75
+ {errors.confirmPassword && <p role="alert">{errors.confirmPassword.message}</p>}
76
+ </div>
77
+ <button type="submit" disabled={isSubmitting}>
78
+ {isSubmitting ? "Creating account..." : "Sign Up"}
79
+ </button>
80
+ </form>
81
+ );
82
+ }
83
+ ```
84
+
85
+ ### Multi-Step Form Wizard
86
+
87
+ Break complex forms into digestible steps:
88
+
89
+ ```typescript
90
+ const stepSchemas = [
91
+ z.object({ name: z.string().min(1), email: z.string().email() }),
92
+ z.object({ company: z.string().min(1), role: z.string().min(1) }),
93
+ z.object({ plan: z.enum(["free", "pro", "enterprise"]) }),
94
+ ];
95
+
96
+ function MultiStepForm() {
97
+ const [step, setStep] = useState(0);
98
+ const [formData, setFormData] = useState({});
99
+
100
+ const currentSchema = stepSchemas[step];
101
+ const { register, handleSubmit, formState: { errors } } = useForm({
102
+ resolver: zodResolver(currentSchema),
103
+ defaultValues: formData,
104
+ });
105
+
106
+ const onStepSubmit = (data: Record<string, unknown>) => {
107
+ const merged = { ...formData, ...data };
108
+ setFormData(merged);
109
+
110
+ if (step < stepSchemas.length - 1) {
111
+ setStep(step + 1);
112
+ } else {
113
+ submitFinalForm(merged);
114
+ }
115
+ };
116
+
117
+ return (
118
+ <form onSubmit={handleSubmit(onStepSubmit)}>
119
+ <div aria-label={`Step ${step + 1} of ${stepSchemas.length}`}>
120
+ <progress value={step + 1} max={stepSchemas.length} />
121
+ </div>
122
+ {step === 0 && (
123
+ <>
124
+ <input {...register("name")} placeholder="Name" />
125
+ <input {...register("email")} placeholder="Email" />
126
+ </>
127
+ )}
128
+ {step === 1 && (
129
+ <>
130
+ <input {...register("company")} placeholder="Company" />
131
+ <input {...register("role")} placeholder="Role" />
132
+ </>
133
+ )}
134
+ {step === 2 && (
135
+ <select {...register("plan")}>
136
+ <option value="free">Free</option>
137
+ <option value="pro">Pro</option>
138
+ <option value="enterprise">Enterprise</option>
139
+ </select>
140
+ )}
141
+ <div>
142
+ {step > 0 && <button type="button" onClick={() => setStep(step - 1)}>Back</button>}
143
+ <button type="submit">{step === stepSchemas.length - 1 ? "Submit" : "Next"}</button>
144
+ </div>
145
+ </form>
146
+ );
147
+ }
148
+ ```
149
+
150
+ ### File Upload with Preview
151
+
152
+ ```typescript
153
+ function FileUploadField({ name, control }: { name: string; control: Control }) {
154
+ const { field } = useController({ name, control });
155
+ const [preview, setPreview] = useState<string | null>(null);
156
+
157
+ const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
158
+ const file = e.target.files?.[0];
159
+ if (!file) return;
160
+
161
+ if (file.size > 5 * 1024 * 1024) {
162
+ alert("File must be under 5MB");
163
+ return;
164
+ }
165
+
166
+ field.onChange(file);
167
+ const reader = new FileReader();
168
+ reader.onload = () => setPreview(reader.result as string);
169
+ reader.readAsDataURL(file);
170
+ };
171
+
172
+ return (
173
+ <div>
174
+ <input type="file" accept="image/*" onChange={handleChange} />
175
+ {preview && <img src={preview} alt="Preview" style={{ maxWidth: 200 }} />}
176
+ </div>
177
+ );
178
+ }
179
+ ```
180
+
181
+ ### Optimistic Submission
182
+
183
+ Show success immediately, roll back on failure:
184
+
185
+ ```typescript
186
+ function TodoList() {
187
+ const [todos, setTodos] = useState<Todo[]>([]);
188
+
189
+ const addTodo = async (text: string) => {
190
+ const optimisticTodo: Todo = {
191
+ id: `temp-${Date.now()}`,
192
+ text,
193
+ completed: false,
194
+ };
195
+
196
+ // Optimistic update
197
+ setTodos((prev) => [...prev, optimisticTodo]);
198
+
199
+ try {
200
+ const created = await fetch("/api/todos", {
201
+ method: "POST",
202
+ headers: { "Content-Type": "application/json" },
203
+ body: JSON.stringify({ text }),
204
+ }).then((r) => r.json());
205
+
206
+ // Replace optimistic with real
207
+ setTodos((prev) =>
208
+ prev.map((t) => (t.id === optimisticTodo.id ? created : t))
209
+ );
210
+ } catch {
211
+ // Roll back
212
+ setTodos((prev) => prev.filter((t) => t.id !== optimisticTodo.id));
213
+ toast.error("Failed to add todo");
214
+ }
215
+ };
216
+ }
217
+ ```
218
+
219
+ ### Server-Side Validation Error Handling
220
+
221
+ ```typescript
222
+ const onSubmit = async (data: SignupForm) => {
223
+ const res = await fetch("/api/auth/signup", {
224
+ method: "POST",
225
+ headers: { "Content-Type": "application/json" },
226
+ body: JSON.stringify(data),
227
+ });
228
+
229
+ if (!res.ok) {
230
+ const body = await res.json();
231
+ // Map server errors to form fields
232
+ if (body.errors) {
233
+ for (const [field, message] of Object.entries(body.errors)) {
234
+ setError(field as keyof SignupForm, {
235
+ type: "server",
236
+ message: message as string,
237
+ });
238
+ }
239
+ }
240
+ return;
241
+ }
242
+ router.push("/dashboard");
243
+ };
244
+ ```
245
+
246
+ ## Examples
247
+
248
+ | Pattern | When | Result |
249
+ |---------|------|--------|
250
+ | RHF + Zod | Any form | Type-safe, zero unnecessary re-renders |
251
+ | Multi-step wizard | Onboarding, checkout | Digestible steps, per-step validation |
252
+ | File upload preview | Avatar, documents | Instant visual feedback before submit |
253
+ | Optimistic submission | Todos, comments, likes | Instant UX, graceful rollback |
254
+ | Server error mapping | Signup, settings | Field-level errors from API |
255
+
256
+ ## Checklist
257
+ - [ ] Forms use React Hook Form with zodResolver for type-safe validation
258
+ - [ ] Every input has a visible label and accessible error message
259
+ - [ ] Submit button shows loading state and is disabled during submission
260
+ - [ ] Server validation errors mapped back to individual form fields
261
+ - [ ] Multi-step forms validate per step, not only on final submit
262
+ - [ ] File uploads validate size and type before upload
263
+ - [ ] Form state persists across page navigation (for long forms)
264
+ - [ ] `noValidate` on form element to prevent browser default validation
@@ -0,0 +1,189 @@
1
+ ---
2
+ name: gcp-patterns
3
+ description: GCP patterns for Cloud Run, Firestore, Cloud Functions, Pub/Sub, Cloud Storage, and IAM best practices.
4
+ ---
5
+
6
+ # GCP Patterns
7
+
8
+ ## When to Use
9
+ Apply when building on Google Cloud Platform. Covers Cloud Run for containerized services, Firestore for document databases, Cloud Functions for event-driven compute, Pub/Sub for messaging, Cloud Storage for objects, and IAM for access control. Use this skill when designing GCP architectures, migrating workloads, or optimizing existing deployments.
10
+
11
+ ## How It Works
12
+
13
+ ### Cloud Run -- Serverless Containers
14
+
15
+ ```dockerfile
16
+ FROM node:20-slim AS builder
17
+ WORKDIR /app
18
+ COPY package*.json ./
19
+ RUN npm ci --production
20
+ COPY . .
21
+ RUN npm run build
22
+
23
+ FROM node:20-slim
24
+ WORKDIR /app
25
+ COPY --from=builder /app/dist ./dist
26
+ COPY --from=builder /app/node_modules ./node_modules
27
+ ENV PORT=8080
28
+ EXPOSE 8080
29
+ CMD ["node", "dist/server.js"]
30
+ ```
31
+
32
+ ```bash
33
+ gcloud run deploy my-service \
34
+ --image gcr.io/my-project/my-service:latest \
35
+ --region us-central1 \
36
+ --concurrency 80 \
37
+ --min-instances 1 \
38
+ --max-instances 10 \
39
+ --memory 512Mi \
40
+ --cpu 1 \
41
+ --set-env-vars "NODE_ENV=production" \
42
+ --service-account my-service@my-project.iam.gserviceaccount.com
43
+ ```
44
+
45
+ Set `--min-instances 1` to avoid cold starts for critical services. Use `--concurrency` to match your app's threading model. Keep container startup under 10 seconds.
46
+
47
+ ### Firestore -- Document Database
48
+
49
+ ```typescript
50
+ import { Firestore, FieldValue } from "@google-cloud/firestore";
51
+
52
+ const db = new Firestore();
53
+
54
+ // Create/update with merge
55
+ await db.collection("users").doc(userId).set({
56
+ name: "Alice",
57
+ email: "alice@example.com",
58
+ updatedAt: FieldValue.serverTimestamp(),
59
+ }, { merge: true });
60
+
61
+ // Query with composite filter
62
+ const activeOrders = await db.collection("orders")
63
+ .where("userId", "==", userId)
64
+ .where("status", "in", ["pending", "processing"])
65
+ .orderBy("createdAt", "desc")
66
+ .limit(20)
67
+ .get();
68
+
69
+ // Transaction -- atomic read-modify-write
70
+ await db.runTransaction(async (tx) => {
71
+ const ref = db.collection("accounts").doc(accountId);
72
+ const snap = await tx.get(ref);
73
+ const balance = snap.data()?.balance ?? 0;
74
+ if (balance < amount) throw new Error("Insufficient funds");
75
+ tx.update(ref, { balance: balance - amount });
76
+ tx.create(db.collection("transactions").doc(), {
77
+ accountId, amount: -amount, createdAt: FieldValue.serverTimestamp(),
78
+ });
79
+ });
80
+ ```
81
+
82
+ Design documents for the read pattern -- denormalize. Keep documents under 1MB. Use subcollections for 1:many relationships.
83
+
84
+ ### Cloud Functions -- Event-Driven
85
+
86
+ ```typescript
87
+ import { onDocumentCreated } from "firebase-functions/v2/firestore";
88
+ import { onMessagePublished } from "firebase-functions/v2/pubsub";
89
+
90
+ export const onOrderCreated = onDocumentCreated("orders/{orderId}", async (event) => {
91
+ const order = event.data?.data();
92
+ if (!order) return;
93
+ await sendConfirmationEmail(order.userId, order);
94
+ await updateInventory(order.items);
95
+ });
96
+
97
+ export const processAnalytics = onMessagePublished("analytics-events", async (event) => {
98
+ const data = event.data.message.json;
99
+ await bigquery.insert("events", data);
100
+ });
101
+ ```
102
+
103
+ ### Pub/Sub -- Async Messaging
104
+
105
+ ```typescript
106
+ import { PubSub } from "@google-cloud/pubsub";
107
+
108
+ const pubsub = new PubSub();
109
+
110
+ // Publish with ordering key
111
+ const topic = pubsub.topic("order-events", { enableMessageOrdering: true });
112
+ await topic.publishMessage({
113
+ data: Buffer.from(JSON.stringify({ orderId, action: "created" })),
114
+ orderingKey: orderId,
115
+ attributes: { eventType: "order.created" },
116
+ });
117
+
118
+ // Subscribe with flow control
119
+ const sub = pubsub.subscription("order-processor", {
120
+ flowControl: { maxMessages: 10 },
121
+ });
122
+ sub.on("message", async (message) => {
123
+ try {
124
+ await processOrderEvent(JSON.parse(message.data.toString()));
125
+ message.ack();
126
+ } catch {
127
+ message.nack();
128
+ }
129
+ });
130
+ ```
131
+
132
+ Set dead-letter topics for messages that fail repeatedly. Use ordering keys only when needed -- they reduce throughput.
133
+
134
+ ### Cloud Storage -- Object Store
135
+
136
+ ```typescript
137
+ import { Storage } from "@google-cloud/storage";
138
+
139
+ const storage = new Storage();
140
+ const bucket = storage.bucket("my-app-assets");
141
+
142
+ // Resumable upload for large files
143
+ await bucket.upload(localPath, {
144
+ destination: `uploads/${userId}/${filename}`,
145
+ resumable: true,
146
+ metadata: { contentType: "application/pdf" },
147
+ });
148
+
149
+ // Signed URL for temporary access
150
+ const [url] = await bucket.file(`uploads/${userId}/${filename}`).getSignedUrl({
151
+ action: "read",
152
+ expires: Date.now() + 15 * 60 * 1000,
153
+ });
154
+ ```
155
+
156
+ ### IAM -- Least Privilege
157
+
158
+ ```bash
159
+ # One service account per service
160
+ gcloud iam service-accounts create my-service-sa \
161
+ --display-name "My Service"
162
+
163
+ # Grant only needed roles
164
+ gcloud projects add-iam-policy-binding my-project \
165
+ --member "serviceAccount:my-service-sa@my-project.iam.gserviceaccount.com" \
166
+ --role "roles/datastore.user"
167
+ ```
168
+
169
+ Never use the default compute service account in production. Use Workload Identity Federation for external services instead of key files.
170
+
171
+ ## Examples
172
+
173
+ | Pattern | Service | Use Case |
174
+ |---------|---------|----------|
175
+ | Container API | Cloud Run | REST/gRPC microservices |
176
+ | Document store | Firestore | User profiles, settings |
177
+ | Event trigger | Cloud Functions | Firestore/Pub/Sub handlers |
178
+ | Message bus | Pub/Sub | Service decoupling |
179
+ | File storage | Cloud Storage | Uploads, backups, static assets |
180
+
181
+ ## Checklist
182
+ - [ ] Cloud Run services have `--min-instances 1` for latency-critical paths
183
+ - [ ] Firestore composite indexes created for all multi-field queries
184
+ - [ ] Cloud Functions have memory and timeout configured per function
185
+ - [ ] Pub/Sub subscriptions have dead-letter topics configured
186
+ - [ ] Cloud Storage buckets have lifecycle rules for old objects
187
+ - [ ] Each service uses a dedicated service account with minimal roles
188
+ - [ ] No service account key files -- use Workload Identity Federation
189
+ - [ ] Infrastructure defined in Terraform or Deployment Manager
@@ -0,0 +1,187 @@
1
+ ---
2
+ name: git-workflow
3
+ description: Git workflow patterns including branching strategies, conventional commits, rebasing, cherry-pick, and bisect.
4
+ ---
5
+
6
+ # Git Workflow Patterns
7
+
8
+ ## When to Use
9
+ Apply these patterns when collaborating on any software project using Git. Whether you are managing feature branches, writing commit messages, resolving merge conflicts, or tracking down regressions, consistent Git workflows reduce friction and keep the history readable. These patterns are especially important in teams using CI/CD, code review, and automated release pipelines.
10
+
11
+ ## How It Works
12
+
13
+ ### Branching Strategy (Trunk-Based with Short-Lived Branches)
14
+
15
+ ```bash
16
+ # Create a feature branch from main
17
+ git checkout main
18
+ git pull origin main
19
+ git checkout -b feat/user-avatars
20
+
21
+ # Work on the branch with small, atomic commits
22
+ git add src/components/Avatar.tsx src/components/Avatar.test.tsx
23
+ git commit -m "feat(ui): add Avatar component with fallback initials"
24
+
25
+ git add src/api/upload-avatar.ts
26
+ git commit -m "feat(api): add avatar upload endpoint with S3 presigned URL"
27
+
28
+ # Keep branch up to date with main
29
+ git fetch origin
30
+ git rebase origin/main
31
+
32
+ # Push and create PR
33
+ git push -u origin feat/user-avatars
34
+ gh pr create --title "feat: user avatar upload and display" \
35
+ --body "Adds avatar component and S3 upload endpoint"
36
+ ```
37
+
38
+ ### Conventional Commits
39
+
40
+ ```bash
41
+ # Format: <type>(<scope>): <description>
42
+ # Types: feat, fix, docs, style, refactor, test, chore, perf, ci, build
43
+
44
+ # Feature
45
+ git commit -m "feat(auth): add OAuth 2.0 Google login"
46
+
47
+ # Bug fix
48
+ git commit -m "fix(api): handle null response in user endpoint"
49
+
50
+ # Breaking change (note the ! after scope)
51
+ git commit -m "feat(api)!: change /users response format to paginated"
52
+
53
+ # Multi-line with body and footer
54
+ git commit -m "fix(db): resolve connection pool exhaustion under load
55
+
56
+ The pool was not releasing connections after transaction rollback.
57
+ Added explicit release in the finally block of executeTransaction.
58
+
59
+ Closes #342"
60
+ ```
61
+
62
+ ### Interactive Rebase for Clean History
63
+
64
+ ```bash
65
+ # Squash the last 4 commits into a clean history before PR merge
66
+ git rebase -i HEAD~4
67
+
68
+ # In the editor:
69
+ # pick abc1234 feat(auth): add login form skeleton
70
+ # squash def5678 wip: hook up validation
71
+ # squash 789abcd fix typo in error message
72
+ # squash bcd0123 add tests for login flow
73
+
74
+ # Result: one clean commit with a comprehensive message
75
+ ```
76
+
77
+ ### Cherry-Pick a Specific Commit
78
+
79
+ ```bash
80
+ # Bring a hotfix from main into a release branch
81
+ git checkout release/2.1
82
+ git cherry-pick abc1234
83
+
84
+ # Cherry-pick without committing (to modify before committing)
85
+ git cherry-pick --no-commit abc1234
86
+ git add -p # stage only the parts you need
87
+ git commit -m "fix(billing): backport invoice rounding fix to 2.1"
88
+ ```
89
+
90
+ ### Git Bisect to Find Regressions
91
+
92
+ ```bash
93
+ # Start bisect
94
+ git bisect start
95
+
96
+ # Mark the current commit as bad
97
+ git bisect bad
98
+
99
+ # Mark a known good commit (e.g., last release tag)
100
+ git bisect good v2.0.0
101
+
102
+ # Git checks out a midpoint - test it, then mark good or bad
103
+ npm test -- --run src/billing.test.ts
104
+ git bisect good # or: git bisect bad
105
+
106
+ # Automate with a test script
107
+ git bisect start HEAD v2.0.0
108
+ git bisect run npm test -- --run src/billing.test.ts
109
+
110
+ # Clean up
111
+ git bisect reset
112
+ ```
113
+
114
+ ### Stash and Apply
115
+
116
+ ```bash
117
+ # Save work in progress before switching branches
118
+ git stash push -m "wip: dashboard chart refactor"
119
+
120
+ # List stashes
121
+ git stash list
122
+
123
+ # Apply and remove from stash
124
+ git stash pop
125
+
126
+ # Apply without removing (keep stash for reuse)
127
+ git stash apply stash@{0}
128
+
129
+ # Stash only unstaged changes (keep staged files)
130
+ git stash push --keep-index -m "unstaged changes only"
131
+ ```
132
+
133
+ ### Handling Merge Conflicts
134
+
135
+ ```bash
136
+ # During rebase, when conflicts occur:
137
+ git rebase origin/main
138
+ # CONFLICT in src/config.ts
139
+
140
+ # 1. Open the file, resolve the conflict markers
141
+ # 2. Stage the resolved file
142
+ git add src/config.ts
143
+
144
+ # 3. Continue the rebase
145
+ git rebase --continue
146
+
147
+ # If you want to abort and go back to before the rebase
148
+ git rebase --abort
149
+ ```
150
+
151
+ ### Tags and Releases
152
+
153
+ ```bash
154
+ # Create an annotated tag for release
155
+ git tag -a v2.1.0 -m "Release 2.1.0: avatar upload, improved billing"
156
+
157
+ # Push tags
158
+ git push origin v2.1.0
159
+
160
+ # List tags matching a pattern
161
+ git tag -l "v2.*"
162
+
163
+ # Delete a tag locally and remotely
164
+ git tag -d v2.1.0-beta
165
+ git push origin --delete v2.1.0-beta
166
+ ```
167
+
168
+ ## Examples
169
+
170
+ | Scenario | Command | Purpose |
171
+ |----------|---------|---------|
172
+ | Undo last commit (keep changes) | `git reset --soft HEAD~1` | Recommit with different message |
173
+ | View file at specific commit | `git show abc1234:src/config.ts` | Inspect historical state |
174
+ | Find who changed a line | `git blame -L 10,20 src/auth.ts` | Track authorship |
175
+ | See branches merged to main | `git branch --merged main` | Clean up stale branches |
176
+ | Diff only file names | `git diff --name-only HEAD~3` | Quick overview of recent changes |
177
+ | Restore a deleted file | `git checkout HEAD~1 -- src/removed.ts` | Recover from accidental deletion |
178
+
179
+ ## Checklist
180
+ - [ ] Feature branches are short-lived (< 2 days) and branched from main
181
+ - [ ] Commits follow conventional commit format (`feat:`, `fix:`, `chore:`, etc.)
182
+ - [ ] Rebase onto main before creating a PR to avoid merge commits
183
+ - [ ] Each commit is atomic: it compiles, tests pass, and represents one logical change
184
+ - [ ] Tags follow semver and are created for every release
185
+ - [ ] Stale branches are deleted after PR merge
186
+ - [ ] Never force-push to main or shared branches
187
+ - [ ] Use `git bisect` instead of manual searching when tracking regressions