vibes-plug 1.0.0 → 2.5.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 (123) hide show
  1. package/.github/workflows/publish.yml +20 -0
  2. package/AGENTS.md +66 -0
  3. package/BLUEPRINT.md +152 -60
  4. package/CHANGELOG.md +50 -0
  5. package/README.md +346 -194
  6. package/package.json +25 -25
  7. package/plugin.json +1 -1
  8. package/skills/ai-cost-token-optimizer/SKILL.md +52 -0
  9. package/skills/ai-llm-integration-expert/SKILL.md +180 -162
  10. package/skills/api-design-expert/SKILL.md +314 -310
  11. package/skills/app-analyzer-optimizer/SKILL.md +193 -189
  12. package/skills/apple-ecosystem-expert/SKILL.md +142 -0
  13. package/skills/async-queue-temporal-expert/SKILL.md +54 -0
  14. package/skills/authentication-identity-expert/SKILL.md +251 -20
  15. package/skills/auto-doc-updater/SKILL.md +214 -204
  16. package/skills/autonomous-chaos-monkey/SKILL.md +63 -0
  17. package/skills/autonomous-red-teamer/SKILL.md +59 -0
  18. package/skills/autonomous-swarm-director/SKILL.md +69 -0
  19. package/skills/autonomous-tdd-debugger/SKILL.md +65 -0
  20. package/skills/bootstrap-to-modern/SKILL.md +90 -86
  21. package/skills/brainstorming/SKILL.md +373 -353
  22. package/skills/browser-automation-expert/SKILL.md +46 -0
  23. package/skills/ci-cd-devops-architect/SKILL.md +72 -45
  24. package/skills/cloud-hosting-expert/SKILL.md +244 -244
  25. package/skills/coderabbit/SKILL.md +192 -192
  26. package/skills/cron-scheduler-expert/SKILL.md +298 -0
  27. package/skills/data-telemetry-expert/SKILL.md +213 -213
  28. package/skills/database-orm-expert/SKILL.md +294 -294
  29. package/skills/dependency-upgrade-migrator/SKILL.md +295 -0
  30. package/skills/design-system-architect/SKILL.md +27 -10
  31. package/skills/doku-mcp-server/SKILL.md +251 -0
  32. package/skills/doku-payment-gateway/SKILL.md +227 -0
  33. package/skills/e2e-testing-expert/SKILL.md +315 -315
  34. package/skills/edge-serverless-db-expert/SKILL.md +43 -0
  35. package/skills/email-notification-expert/SKILL.md +362 -0
  36. package/skills/error-resilience-expert/SKILL.md +480 -0
  37. package/skills/event-driven-architect/SKILL.md +81 -81
  38. package/skills/feature-flag-analytics-expert/SKILL.md +46 -0
  39. package/skills/file-upload-media-expert/SKILL.md +431 -0
  40. package/skills/form-validation-expert/SKILL.md +401 -0
  41. package/skills/fullstack-expert/SKILL.md +202 -202
  42. package/skills/fullstack-expert/references/api_design_guide.md +466 -466
  43. package/skills/fullstack-expert/references/multi_language_backend.md +528 -528
  44. package/skills/fullstack-expert/scripts/api_contract_validator.py +253 -253
  45. package/skills/fullstack-expert/scripts/architecture_analyzer.py +326 -326
  46. package/skills/gemini-agent-booster/SKILL.md +135 -135
  47. package/skills/global-a11y-i18n-expert/SKILL.md +81 -81
  48. package/skills/glsl-shader-expert/SKILL.md +101 -0
  49. package/skills/go-programming-expert/SKILL.md +295 -295
  50. package/skills/graphql-apollo-expert/SKILL.md +108 -0
  51. package/skills/hig/SKILL.md +188 -188
  52. package/skills/hyper-context-synthesizer/SKILL.md +55 -0
  53. package/skills/js-backend-expert/SKILL.md +34 -9
  54. package/skills/legacy-code-translator/SKILL.md +65 -0
  55. package/skills/llm-cost-arbitrage-router/SKILL.md +59 -0
  56. package/skills/logging-error-tracking-expert/SKILL.md +338 -0
  57. package/skills/mcp-client-orchestrator/SKILL.md +70 -0
  58. package/skills/mcp-server-architect/SKILL.md +194 -194
  59. package/skills/micro-frontend-architect/SKILL.md +106 -0
  60. package/skills/mobile-expo-expert/SKILL.md +186 -186
  61. package/skills/mobile-push-notification-expert/SKILL.md +51 -0
  62. package/skills/monday-design-aesthetic/SKILL.md +67 -67
  63. package/skills/monorepo-architect/SKILL.md +227 -227
  64. package/skills/mpa-orchestrator/SKILL.md +101 -101
  65. package/skills/multi-agent-orchestration/SKILL.md +234 -234
  66. package/skills/multiple-entry-points/SKILL.md +55 -55
  67. package/skills/mvc-expert/SKILL.md +231 -231
  68. package/skills/payment-gateway-expert/SKILL.md +45 -45
  69. package/skills/performance-web-vitals/SKILL.md +332 -332
  70. package/skills/post-quantum-crypto-migrator/SKILL.md +57 -0
  71. package/skills/prd-architect/SKILL.md +201 -191
  72. package/skills/proactive-background-watcher/SKILL.md +62 -0
  73. package/skills/production-ready-hardener/PRODUCTION_READINESS_REPORT.md +67 -0
  74. package/skills/production-ready-hardener/SKILL.md +173 -186
  75. package/skills/production-ready-hardener/references/production_checklist.md +161 -161
  76. package/skills/production-ready-hardener/scripts/production_readiness_scanner.py +881 -875
  77. package/skills/project-context-mapper/SKILL.md +79 -0
  78. package/skills/python-programming-expert/SKILL.md +263 -132
  79. package/skills/rate-limit-abuse-prevention/SKILL.md +371 -0
  80. package/skills/realtime-collaboration-expert/SKILL.md +45 -45
  81. package/skills/rust-programming-expert/SKILL.md +235 -235
  82. package/skills/saas-billing/SKILL.md +377 -377
  83. package/skills/saas-multi-tenant/SKILL.md +251 -237
  84. package/skills/saas-mvp-launcher/SKILL.md +10 -0
  85. package/skills/saas-transformer/SKILL.md +187 -144
  86. package/skills/saas-transformer/references/billing_integration_guide.md +401 -401
  87. package/skills/saas-transformer/references/feature_gating_patterns.md +137 -137
  88. package/skills/saas-transformer/references/saas_transformation_checklist.md +121 -121
  89. package/skills/saas-transformer/scripts/saas_transformation_scanner.py +39 -29
  90. package/skills/scalability-clean-code/SKILL.md +229 -229
  91. package/skills/self-evolving-memory-graph/SKILL.md +75 -0
  92. package/skills/self-healing-cloud-orchestrator/SKILL.md +57 -0
  93. package/skills/senior-frontend/SKILL.md +161 -161
  94. package/skills/senior-fullstack/SKILL.md +167 -167
  95. package/skills/seo/SKILL.md +235 -225
  96. package/skills/seo-geo/SKILL.md +188 -188
  97. package/skills/session-context-loader/SKILL.md +77 -0
  98. package/skills/session-handoff-resume/SKILL.md +158 -158
  99. package/skills/skill_baru/SKILL.md +172 -147
  100. package/skills/spa-orchestrator/SKILL.md +288 -288
  101. package/skills/state-management-expert/SKILL.md +272 -272
  102. package/skills/supabase-security-expert/SKILL.md +243 -243
  103. package/skills/tailwind-expert/SKILL.md +188 -188
  104. package/skills/tanstack-query-expert/SKILL.md +199 -199
  105. package/skills/token-saver/SKILL.md +119 -111
  106. package/skills/typescript-expert/SKILL.md +324 -279
  107. package/skills/ui-components-expert/SKILL.md +263 -46
  108. package/skills/ui-ux-pro-max/SKILL.md +202 -201
  109. package/skills/ui-ux-pro-max/scripts/__pycache__/core.cpython-310.pyc +0 -0
  110. package/skills/ui-ux-pro-max/scripts/__pycache__/design_system.cpython-310.pyc +0 -0
  111. package/skills/ui_ux_expert/SKILL.md +17 -6
  112. package/skills/vector-db-rag-expert/SKILL.md +52 -0
  113. package/skills/vibe-code-gardener/SKILL.md +181 -173
  114. package/skills/visual-qa-vision-agent/SKILL.md +65 -0
  115. package/skills/vue-frontend-expert/SKILL.md +126 -0
  116. package/skills/web-3d-graphics-expert/SKILL.md +131 -0
  117. package/skills/web-game-engine-expert/SKILL.md +96 -0
  118. package/skills/web-scraper/SKILL.md +207 -205
  119. package/skills/website-design-cloner/SKILL.md +174 -0
  120. package/skills/webxr-ar-vr-expert/SKILL.md +117 -0
  121. package/skills/zero-to-prod-orchestrator/SKILL.md +206 -180
  122. package/skills/zero-trust-secret-vault/SKILL.md +40 -0
  123. package/vibes-swarm-demo.gif +0 -0
@@ -1,528 +1,528 @@
1
- # Multi-Language Backend Patterns
2
-
3
- ## Overview
4
- This reference documents idiomatic backend patterns across TypeScript, Python, Go, and Rust. Each section shows the same core concepts (HTTP handlers, database access, error handling, middleware) implemented in each language's preferred framework.
5
-
6
- ---
7
-
8
- ## 1. TypeScript (Hono + Drizzle ORM)
9
-
10
- ### Project Structure
11
- ```
12
- src/
13
- ├── index.ts # Entry point
14
- ├── routes/
15
- │ ├── products.ts # Product routes
16
- │ └── users.ts # User routes
17
- ├── db/
18
- │ ├── index.ts # Database client
19
- │ └── schema.ts # Drizzle schema
20
- ├── middleware/
21
- │ ├── auth.ts # JWT auth middleware
22
- │ └── logger.ts # Request logger
23
- ├── services/
24
- │ └── product.ts # Business logic
25
- └── lib/
26
- ├── errors.ts # Custom error classes
27
- └── validators.ts # Zod schemas
28
- ```
29
-
30
- ### HTTP Handler + Validation
31
-
32
- ```typescript
33
- // routes/products.ts
34
- import { Hono } from 'hono';
35
- import { zValidator } from '@hono/zod-validator';
36
- import { z } from 'zod';
37
- import { db } from '../db';
38
- import { products } from '../db/schema';
39
- import { eq } from 'drizzle-orm';
40
-
41
- const CreateProductSchema = z.object({
42
- name: z.string().min(1).max(255),
43
- description: z.string().optional(),
44
- price: z.number().positive(),
45
- categoryId: z.string().uuid(),
46
- });
47
-
48
- const app = new Hono()
49
- .get('/', async (c) => {
50
- const limit = Number(c.req.query('limit') ?? '20');
51
- const cursor = c.req.query('cursor');
52
-
53
- const items = await db
54
- .select()
55
- .from(products)
56
- .orderBy(products.createdAt)
57
- .limit(limit + 1);
58
-
59
- const hasMore = items.length > limit;
60
- const data = hasMore ? items.slice(0, limit) : items;
61
-
62
- return c.json({ data, hasMore });
63
- })
64
- .post('/', zValidator('json', CreateProductSchema), async (c) => {
65
- const input = c.req.valid('json');
66
-
67
- const [product] = await db
68
- .insert(products)
69
- .values(input)
70
- .returning();
71
-
72
- return c.json(product, 201);
73
- })
74
- .get('/:id', async (c) => {
75
- const id = c.req.param('id');
76
- const product = await db.query.products.findFirst({
77
- where: eq(products.id, id),
78
- });
79
-
80
- if (!product) {
81
- return c.json({ error: 'Product not found' }, 404);
82
- }
83
-
84
- return c.json(product);
85
- });
86
-
87
- export default app;
88
- ```
89
-
90
- ---
91
-
92
- ## 2. Python (FastAPI + SQLAlchemy 2.x)
93
-
94
- ### Project Structure
95
- ```
96
- app/
97
- ├── main.py # Entry point
98
- ├── routes/
99
- │ ├── products.py # Product routes
100
- │ └── users.py # User routes
101
- ├── db/
102
- │ ├── session.py # Database session
103
- │ └── models.py # SQLAlchemy models
104
- ├── schemas/
105
- │ └── product.py # Pydantic schemas
106
- ├── services/
107
- │ └── product.py # Business logic
108
- └── middleware/
109
- ├── auth.py # JWT auth dependency
110
- └── logging.py # Request logging
111
- ```
112
-
113
- ### HTTP Handler + Validation
114
-
115
- ```python
116
- # routes/products.py
117
- from uuid import UUID
118
- from fastapi import APIRouter, Depends, HTTPException, Query
119
- from sqlalchemy.ext.asyncio import AsyncSession
120
- from sqlalchemy import select
121
-
122
- from app.db.session import get_db
123
- from app.db.models import Product
124
- from app.schemas.product import (
125
- ProductCreate,
126
- ProductResponse,
127
- ProductListResponse,
128
- )
129
-
130
- router = APIRouter(prefix="/products", tags=["Products"])
131
-
132
-
133
- @router.get("/", response_model=ProductListResponse)
134
- async def list_products(
135
- limit: int = Query(default=20, ge=1, le=100),
136
- cursor: str | None = None,
137
- category: str | None = None,
138
- db: AsyncSession = Depends(get_db),
139
- ):
140
- query = select(Product).order_by(Product.created_at).limit(limit + 1)
141
-
142
- if category:
143
- query = query.where(Product.category_id == category)
144
-
145
- result = await db.execute(query)
146
- items = list(result.scalars().all())
147
-
148
- has_more = len(items) > limit
149
- data = items[:limit] if has_more else items
150
-
151
- return ProductListResponse(data=data, has_more=has_more)
152
-
153
-
154
- @router.post("/", response_model=ProductResponse, status_code=201)
155
- async def create_product(
156
- payload: ProductCreate,
157
- db: AsyncSession = Depends(get_db),
158
- ):
159
- product = Product(**payload.model_dump())
160
- db.add(product)
161
- await db.commit()
162
- await db.refresh(product)
163
- return product
164
-
165
-
166
- @router.get("/{product_id}", response_model=ProductResponse)
167
- async def get_product(
168
- product_id: UUID,
169
- db: AsyncSession = Depends(get_db),
170
- ):
171
- result = await db.execute(
172
- select(Product).where(Product.id == product_id)
173
- )
174
- product = result.scalar_one_or_none()
175
-
176
- if not product:
177
- raise HTTPException(status_code=404, detail="Product not found")
178
-
179
- return product
180
- ```
181
-
182
- ### Pydantic Schema
183
-
184
- ```python
185
- # schemas/product.py
186
- from datetime import datetime
187
- from uuid import UUID
188
- from pydantic import BaseModel, Field
189
-
190
-
191
- class ProductCreate(BaseModel):
192
- name: str = Field(min_length=1, max_length=255)
193
- description: str | None = None
194
- price: float = Field(gt=0)
195
- category_id: UUID
196
-
197
-
198
- class ProductResponse(BaseModel):
199
- id: UUID
200
- name: str
201
- description: str | None
202
- price: float
203
- category_id: UUID
204
- created_at: datetime
205
- updated_at: datetime
206
-
207
- model_config = {"from_attributes": True}
208
-
209
-
210
- class ProductListResponse(BaseModel):
211
- data: list[ProductResponse]
212
- has_more: bool
213
- ```
214
-
215
- ---
216
-
217
- ## 3. Go (Gin + sqlc)
218
-
219
- ### Project Structure
220
- ```
221
- cmd/
222
- └── server/
223
- └── main.go # Entry point
224
- internal/
225
- ├── handler/
226
- │ ├── products.go # Product handlers
227
- │ └── users.go # User handlers
228
- ├── db/
229
- │ ├── db.go # Database connection
230
- │ ├── queries.sql # SQL queries (for sqlc)
231
- │ └── sqlc/ # Generated code
232
- ├── middleware/
233
- │ ├── auth.go # JWT auth middleware
234
- │ └── logger.go # Request logging
235
- ├── service/
236
- │ └── product.go # Business logic
237
- └── model/
238
- └── product.go # Domain types
239
- ```
240
-
241
- ### HTTP Handler
242
-
243
- ```go
244
- // internal/handler/products.go
245
- package handler
246
-
247
- import (
248
- "net/http"
249
-
250
- "github.com/gin-gonic/gin"
251
- "github.com/google/uuid"
252
- "github.com/example/api/internal/db/sqlc"
253
- )
254
-
255
- type ProductHandler struct {
256
- queries *sqlc.Queries
257
- }
258
-
259
- func NewProductHandler(q *sqlc.Queries) *ProductHandler {
260
- return &ProductHandler{queries: q}
261
- }
262
-
263
- type CreateProductRequest struct {
264
- Name string `json:"name" binding:"required,min=1,max=255"`
265
- Description *string `json:"description"`
266
- Price float64 `json:"price" binding:"required,gt=0"`
267
- CategoryID string `json:"category_id" binding:"required,uuid"`
268
- }
269
-
270
- func (h *ProductHandler) ListProducts(c *gin.Context) {
271
- limit := 20 // Default
272
- products, err := h.queries.ListProducts(c, sqlc.ListProductsParams{
273
- Limit: int32(limit + 1),
274
- })
275
- if err != nil {
276
- c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch products"})
277
- return
278
- }
279
-
280
- hasMore := len(products) > limit
281
- if hasMore {
282
- products = products[:limit]
283
- }
284
-
285
- c.JSON(http.StatusOK, gin.H{
286
- "data": products,
287
- "has_more": hasMore,
288
- })
289
- }
290
-
291
- func (h *ProductHandler) CreateProduct(c *gin.Context) {
292
- var req CreateProductRequest
293
- if err := c.ShouldBindJSON(&req); err != nil {
294
- c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
295
- return
296
- }
297
-
298
- categoryID, _ := uuid.Parse(req.CategoryID)
299
- product, err := h.queries.CreateProduct(c, sqlc.CreateProductParams{
300
- Name: req.Name,
301
- Description: req.Description,
302
- Price: req.Price,
303
- CategoryID: categoryID,
304
- })
305
- if err != nil {
306
- c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create product"})
307
- return
308
- }
309
-
310
- c.JSON(http.StatusCreated, product)
311
- }
312
-
313
- func (h *ProductHandler) GetProduct(c *gin.Context) {
314
- id, err := uuid.Parse(c.Param("id"))
315
- if err != nil {
316
- c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product ID"})
317
- return
318
- }
319
-
320
- product, err := h.queries.GetProduct(c, id)
321
- if err != nil {
322
- c.JSON(http.StatusNotFound, gin.H{"error": "Product not found"})
323
- return
324
- }
325
-
326
- c.JSON(http.StatusOK, product)
327
- }
328
- ```
329
-
330
- ---
331
-
332
- ## 4. Rust (Axum + SQLx)
333
-
334
- ### Project Structure
335
- ```
336
- src/
337
- ├── main.rs # Entry point
338
- ├── routes/
339
- │ ├── mod.rs
340
- │ ├── products.rs # Product routes
341
- │ └── users.rs # User routes
342
- ├── db/
343
- │ ├── mod.rs
344
- │ └── models.rs # Database models
345
- ├── middleware/
346
- │ ├── mod.rs
347
- │ └── auth.rs # JWT auth layer
348
- ├── services/
349
- │ ├── mod.rs
350
- │ └── product.rs # Business logic
351
- └── error.rs # Custom error types
352
- ```
353
-
354
- ### HTTP Handler + Validation
355
-
356
- ```rust
357
- // src/routes/products.rs
358
- use axum::{
359
- extract::{Path, Query, State},
360
- http::StatusCode,
361
- Json,
362
- };
363
- use serde::{Deserialize, Serialize};
364
- use sqlx::PgPool;
365
- use uuid::Uuid;
366
-
367
- use crate::error::AppError;
368
-
369
- #[derive(Debug, Deserialize)]
370
- pub struct ListParams {
371
- pub limit: Option<i64>,
372
- pub cursor: Option<String>,
373
- pub category: Option<String>,
374
- }
375
-
376
- #[derive(Debug, Deserialize)]
377
- pub struct CreateProductRequest {
378
- pub name: String,
379
- pub description: Option<String>,
380
- pub price: f64,
381
- pub category_id: Uuid,
382
- }
383
-
384
- #[derive(Debug, Serialize, sqlx::FromRow)]
385
- pub struct Product {
386
- pub id: Uuid,
387
- pub name: String,
388
- pub description: Option<String>,
389
- pub price: f64,
390
- pub category_id: Uuid,
391
- pub created_at: chrono::DateTime<chrono::Utc>,
392
- pub updated_at: chrono::DateTime<chrono::Utc>,
393
- }
394
-
395
- #[derive(Serialize)]
396
- pub struct ProductListResponse {
397
- pub data: Vec<Product>,
398
- pub has_more: bool,
399
- }
400
-
401
- pub async fn list_products(
402
- State(pool): State<PgPool>,
403
- Query(params): Query<ListParams>,
404
- ) -> Result<Json<ProductListResponse>, AppError> {
405
- let limit = params.limit.unwrap_or(20).min(100);
406
-
407
- let products = sqlx::query_as::<_, Product>(
408
- "SELECT * FROM products ORDER BY created_at LIMIT $1"
409
- )
410
- .bind(limit + 1)
411
- .fetch_all(&pool)
412
- .await?;
413
-
414
- let has_more = products.len() as i64 > limit;
415
- let data = if has_more {
416
- products[..limit as usize].to_vec()
417
- } else {
418
- products
419
- };
420
-
421
- Ok(Json(ProductListResponse { data, has_more }))
422
- }
423
-
424
- pub async fn create_product(
425
- State(pool): State<PgPool>,
426
- Json(input): Json<CreateProductRequest>,
427
- ) -> Result<(StatusCode, Json<Product>), AppError> {
428
- if input.name.is_empty() || input.price <= 0.0 {
429
- return Err(AppError::Validation("Invalid product data".into()));
430
- }
431
-
432
- let product = sqlx::query_as::<_, Product>(
433
- r#"
434
- INSERT INTO products (name, description, price, category_id)
435
- VALUES ($1, $2, $3, $4)
436
- RETURNING *
437
- "#
438
- )
439
- .bind(&input.name)
440
- .bind(&input.description)
441
- .bind(input.price)
442
- .bind(input.category_id)
443
- .fetch_one(&pool)
444
- .await?;
445
-
446
- Ok((StatusCode::CREATED, Json(product)))
447
- }
448
-
449
- pub async fn get_product(
450
- State(pool): State<PgPool>,
451
- Path(id): Path<Uuid>,
452
- ) -> Result<Json<Product>, AppError> {
453
- let product = sqlx::query_as::<_, Product>(
454
- "SELECT * FROM products WHERE id = $1"
455
- )
456
- .bind(id)
457
- .fetch_optional(&pool)
458
- .await?
459
- .ok_or(AppError::NotFound)?;
460
-
461
- Ok(Json(product))
462
- }
463
- ```
464
-
465
- ### Custom Error Type
466
-
467
- ```rust
468
- // src/error.rs
469
- use axum::{
470
- http::StatusCode,
471
- response::{IntoResponse, Response},
472
- Json,
473
- };
474
- use serde_json::json;
475
-
476
- #[derive(Debug)]
477
- pub enum AppError {
478
- NotFound,
479
- Validation(String),
480
- Database(sqlx::Error),
481
- Internal(String),
482
- }
483
-
484
- impl IntoResponse for AppError {
485
- fn into_response(self) -> Response {
486
- let (status, message) = match self {
487
- AppError::NotFound => (StatusCode::NOT_FOUND, "Resource not found".to_string()),
488
- AppError::Validation(msg) => (StatusCode::BAD_REQUEST, msg),
489
- AppError::Database(e) => {
490
- tracing::error!("Database error: {:?}", e);
491
- (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".to_string())
492
- }
493
- AppError::Internal(msg) => {
494
- tracing::error!("Internal error: {}", msg);
495
- (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".to_string())
496
- }
497
- };
498
-
499
- (status, Json(json!({ "error": message }))).into_response()
500
- }
501
- }
502
-
503
- impl From<sqlx::Error> for AppError {
504
- fn from(err: sqlx::Error) -> Self {
505
- AppError::Database(err)
506
- }
507
- }
508
- ```
509
-
510
- ---
511
-
512
- ## Language Selection Guide
513
-
514
- | Criteria | TypeScript | Python | Go | Rust |
515
- |----------|-----------|--------|-----|------|
516
- | **Best for** | Full-stack web apps | ML/AI, data pipelines | High-concurrency services | Systems, performance-critical |
517
- | **Ecosystem** | Largest (npm) | Rich (ML/data) | Growing | Growing |
518
- | **Performance** | Good (V8/Bun) | Moderate (async) | Excellent | Best |
519
- | **Type Safety** | Good (strict TS) | Good (Pydantic) | Built-in | Best (compiler) |
520
- | **Concurrency** | Event loop | asyncio/threading | Goroutines | async/tokio |
521
- | **Learning Curve** | Low | Low | Medium | High |
522
- | **Deploy Size** | Medium | Medium | Small (static) | Smallest (static) |
523
- | **Startup Time** | Fast | Moderate | Very fast | Very fast |
524
-
525
- ---
526
-
527
- ## Conclusion
528
- Choose the right language for the right job. TypeScript for rapid full-stack development, Python for data-heavy workloads, Go for high-concurrency microservices, and Rust for performance-critical systems. The patterns (validation, error handling, middleware) remain consistent across all languages.
1
+ # Multi-Language Backend Patterns
2
+
3
+ ## Overview
4
+ This reference documents idiomatic backend patterns across TypeScript, Python, Go, and Rust. Each section shows the same core concepts (HTTP handlers, database access, error handling, middleware) implemented in each language's preferred framework.
5
+
6
+ ---
7
+
8
+ ## 1. TypeScript (Hono + Drizzle ORM)
9
+
10
+ ### Project Structure
11
+ ```
12
+ src/
13
+ ├── index.ts # Entry point
14
+ ├── routes/
15
+ │ ├── products.ts # Product routes
16
+ │ └── users.ts # User routes
17
+ ├── db/
18
+ │ ├── index.ts # Database client
19
+ │ └── schema.ts # Drizzle schema
20
+ ├── middleware/
21
+ │ ├── auth.ts # JWT auth middleware
22
+ │ └── logger.ts # Request logger
23
+ ├── services/
24
+ │ └── product.ts # Business logic
25
+ └── lib/
26
+ ├── errors.ts # Custom error classes
27
+ └── validators.ts # Zod schemas
28
+ ```
29
+
30
+ ### HTTP Handler + Validation
31
+
32
+ ```typescript
33
+ // routes/products.ts
34
+ import { Hono } from 'hono';
35
+ import { zValidator } from '@hono/zod-validator';
36
+ import { z } from 'zod';
37
+ import { db } from '../db';
38
+ import { products } from '../db/schema';
39
+ import { eq } from 'drizzle-orm';
40
+
41
+ const CreateProductSchema = z.object({
42
+ name: z.string().min(1).max(255),
43
+ description: z.string().optional(),
44
+ price: z.number().positive(),
45
+ categoryId: z.string().uuid(),
46
+ });
47
+
48
+ const app = new Hono()
49
+ .get('/', async (c) => {
50
+ const limit = Number(c.req.query('limit') ?? '20');
51
+ const cursor = c.req.query('cursor');
52
+
53
+ const items = await db
54
+ .select()
55
+ .from(products)
56
+ .orderBy(products.createdAt)
57
+ .limit(limit + 1);
58
+
59
+ const hasMore = items.length > limit;
60
+ const data = hasMore ? items.slice(0, limit) : items;
61
+
62
+ return c.json({ data, hasMore });
63
+ })
64
+ .post('/', zValidator('json', CreateProductSchema), async (c) => {
65
+ const input = c.req.valid('json');
66
+
67
+ const [product] = await db
68
+ .insert(products)
69
+ .values(input)
70
+ .returning();
71
+
72
+ return c.json(product, 201);
73
+ })
74
+ .get('/:id', async (c) => {
75
+ const id = c.req.param('id');
76
+ const product = await db.query.products.findFirst({
77
+ where: eq(products.id, id),
78
+ });
79
+
80
+ if (!product) {
81
+ return c.json({ error: 'Product not found' }, 404);
82
+ }
83
+
84
+ return c.json(product);
85
+ });
86
+
87
+ export default app;
88
+ ```
89
+
90
+ ---
91
+
92
+ ## 2. Python (FastAPI + SQLAlchemy 2.x)
93
+
94
+ ### Project Structure
95
+ ```
96
+ app/
97
+ ├── main.py # Entry point
98
+ ├── routes/
99
+ │ ├── products.py # Product routes
100
+ │ └── users.py # User routes
101
+ ├── db/
102
+ │ ├── session.py # Database session
103
+ │ └── models.py # SQLAlchemy models
104
+ ├── schemas/
105
+ │ └── product.py # Pydantic schemas
106
+ ├── services/
107
+ │ └── product.py # Business logic
108
+ └── middleware/
109
+ ├── auth.py # JWT auth dependency
110
+ └── logging.py # Request logging
111
+ ```
112
+
113
+ ### HTTP Handler + Validation
114
+
115
+ ```python
116
+ # routes/products.py
117
+ from uuid import UUID
118
+ from fastapi import APIRouter, Depends, HTTPException, Query
119
+ from sqlalchemy.ext.asyncio import AsyncSession
120
+ from sqlalchemy import select
121
+
122
+ from app.db.session import get_db
123
+ from app.db.models import Product
124
+ from app.schemas.product import (
125
+ ProductCreate,
126
+ ProductResponse,
127
+ ProductListResponse,
128
+ )
129
+
130
+ router = APIRouter(prefix="/products", tags=["Products"])
131
+
132
+
133
+ @router.get("/", response_model=ProductListResponse)
134
+ async def list_products(
135
+ limit: int = Query(default=20, ge=1, le=100),
136
+ cursor: str | None = None,
137
+ category: str | None = None,
138
+ db: AsyncSession = Depends(get_db),
139
+ ):
140
+ query = select(Product).order_by(Product.created_at).limit(limit + 1)
141
+
142
+ if category:
143
+ query = query.where(Product.category_id == category)
144
+
145
+ result = await db.execute(query)
146
+ items = list(result.scalars().all())
147
+
148
+ has_more = len(items) > limit
149
+ data = items[:limit] if has_more else items
150
+
151
+ return ProductListResponse(data=data, has_more=has_more)
152
+
153
+
154
+ @router.post("/", response_model=ProductResponse, status_code=201)
155
+ async def create_product(
156
+ payload: ProductCreate,
157
+ db: AsyncSession = Depends(get_db),
158
+ ):
159
+ product = Product(**payload.model_dump())
160
+ db.add(product)
161
+ await db.commit()
162
+ await db.refresh(product)
163
+ return product
164
+
165
+
166
+ @router.get("/{product_id}", response_model=ProductResponse)
167
+ async def get_product(
168
+ product_id: UUID,
169
+ db: AsyncSession = Depends(get_db),
170
+ ):
171
+ result = await db.execute(
172
+ select(Product).where(Product.id == product_id)
173
+ )
174
+ product = result.scalar_one_or_none()
175
+
176
+ if not product:
177
+ raise HTTPException(status_code=404, detail="Product not found")
178
+
179
+ return product
180
+ ```
181
+
182
+ ### Pydantic Schema
183
+
184
+ ```python
185
+ # schemas/product.py
186
+ from datetime import datetime
187
+ from uuid import UUID
188
+ from pydantic import BaseModel, Field
189
+
190
+
191
+ class ProductCreate(BaseModel):
192
+ name: str = Field(min_length=1, max_length=255)
193
+ description: str | None = None
194
+ price: float = Field(gt=0)
195
+ category_id: UUID
196
+
197
+
198
+ class ProductResponse(BaseModel):
199
+ id: UUID
200
+ name: str
201
+ description: str | None
202
+ price: float
203
+ category_id: UUID
204
+ created_at: datetime
205
+ updated_at: datetime
206
+
207
+ model_config = {"from_attributes": True}
208
+
209
+
210
+ class ProductListResponse(BaseModel):
211
+ data: list[ProductResponse]
212
+ has_more: bool
213
+ ```
214
+
215
+ ---
216
+
217
+ ## 3. Go (Gin + sqlc)
218
+
219
+ ### Project Structure
220
+ ```
221
+ cmd/
222
+ └── server/
223
+ └── main.go # Entry point
224
+ internal/
225
+ ├── handler/
226
+ │ ├── products.go # Product handlers
227
+ │ └── users.go # User handlers
228
+ ├── db/
229
+ │ ├── db.go # Database connection
230
+ │ ├── queries.sql # SQL queries (for sqlc)
231
+ │ └── sqlc/ # Generated code
232
+ ├── middleware/
233
+ │ ├── auth.go # JWT auth middleware
234
+ │ └── logger.go # Request logging
235
+ ├── service/
236
+ │ └── product.go # Business logic
237
+ └── model/
238
+ └── product.go # Domain types
239
+ ```
240
+
241
+ ### HTTP Handler
242
+
243
+ ```go
244
+ // internal/handler/products.go
245
+ package handler
246
+
247
+ import (
248
+ "net/http"
249
+
250
+ "github.com/gin-gonic/gin"
251
+ "github.com/google/uuid"
252
+ "github.com/example/api/internal/db/sqlc"
253
+ )
254
+
255
+ type ProductHandler struct {
256
+ queries *sqlc.Queries
257
+ }
258
+
259
+ func NewProductHandler(q *sqlc.Queries) *ProductHandler {
260
+ return &ProductHandler{queries: q}
261
+ }
262
+
263
+ type CreateProductRequest struct {
264
+ Name string `json:"name" binding:"required,min=1,max=255"`
265
+ Description *string `json:"description"`
266
+ Price float64 `json:"price" binding:"required,gt=0"`
267
+ CategoryID string `json:"category_id" binding:"required,uuid"`
268
+ }
269
+
270
+ func (h *ProductHandler) ListProducts(c *gin.Context) {
271
+ limit := 20 // Default
272
+ products, err := h.queries.ListProducts(c, sqlc.ListProductsParams{
273
+ Limit: int32(limit + 1),
274
+ })
275
+ if err != nil {
276
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to fetch products"})
277
+ return
278
+ }
279
+
280
+ hasMore := len(products) > limit
281
+ if hasMore {
282
+ products = products[:limit]
283
+ }
284
+
285
+ c.JSON(http.StatusOK, gin.H{
286
+ "data": products,
287
+ "has_more": hasMore,
288
+ })
289
+ }
290
+
291
+ func (h *ProductHandler) CreateProduct(c *gin.Context) {
292
+ var req CreateProductRequest
293
+ if err := c.ShouldBindJSON(&req); err != nil {
294
+ c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
295
+ return
296
+ }
297
+
298
+ categoryID, _ := uuid.Parse(req.CategoryID)
299
+ product, err := h.queries.CreateProduct(c, sqlc.CreateProductParams{
300
+ Name: req.Name,
301
+ Description: req.Description,
302
+ Price: req.Price,
303
+ CategoryID: categoryID,
304
+ })
305
+ if err != nil {
306
+ c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create product"})
307
+ return
308
+ }
309
+
310
+ c.JSON(http.StatusCreated, product)
311
+ }
312
+
313
+ func (h *ProductHandler) GetProduct(c *gin.Context) {
314
+ id, err := uuid.Parse(c.Param("id"))
315
+ if err != nil {
316
+ c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid product ID"})
317
+ return
318
+ }
319
+
320
+ product, err := h.queries.GetProduct(c, id)
321
+ if err != nil {
322
+ c.JSON(http.StatusNotFound, gin.H{"error": "Product not found"})
323
+ return
324
+ }
325
+
326
+ c.JSON(http.StatusOK, product)
327
+ }
328
+ ```
329
+
330
+ ---
331
+
332
+ ## 4. Rust (Axum + SQLx)
333
+
334
+ ### Project Structure
335
+ ```
336
+ src/
337
+ ├── main.rs # Entry point
338
+ ├── routes/
339
+ │ ├── mod.rs
340
+ │ ├── products.rs # Product routes
341
+ │ └── users.rs # User routes
342
+ ├── db/
343
+ │ ├── mod.rs
344
+ │ └── models.rs # Database models
345
+ ├── middleware/
346
+ │ ├── mod.rs
347
+ │ └── auth.rs # JWT auth layer
348
+ ├── services/
349
+ │ ├── mod.rs
350
+ │ └── product.rs # Business logic
351
+ └── error.rs # Custom error types
352
+ ```
353
+
354
+ ### HTTP Handler + Validation
355
+
356
+ ```rust
357
+ // src/routes/products.rs
358
+ use axum::{
359
+ extract::{Path, Query, State},
360
+ http::StatusCode,
361
+ Json,
362
+ };
363
+ use serde::{Deserialize, Serialize};
364
+ use sqlx::PgPool;
365
+ use uuid::Uuid;
366
+
367
+ use crate::error::AppError;
368
+
369
+ #[derive(Debug, Deserialize)]
370
+ pub struct ListParams {
371
+ pub limit: Option<i64>,
372
+ pub cursor: Option<String>,
373
+ pub category: Option<String>,
374
+ }
375
+
376
+ #[derive(Debug, Deserialize)]
377
+ pub struct CreateProductRequest {
378
+ pub name: String,
379
+ pub description: Option<String>,
380
+ pub price: f64,
381
+ pub category_id: Uuid,
382
+ }
383
+
384
+ #[derive(Debug, Serialize, sqlx::FromRow)]
385
+ pub struct Product {
386
+ pub id: Uuid,
387
+ pub name: String,
388
+ pub description: Option<String>,
389
+ pub price: f64,
390
+ pub category_id: Uuid,
391
+ pub created_at: chrono::DateTime<chrono::Utc>,
392
+ pub updated_at: chrono::DateTime<chrono::Utc>,
393
+ }
394
+
395
+ #[derive(Serialize)]
396
+ pub struct ProductListResponse {
397
+ pub data: Vec<Product>,
398
+ pub has_more: bool,
399
+ }
400
+
401
+ pub async fn list_products(
402
+ State(pool): State<PgPool>,
403
+ Query(params): Query<ListParams>,
404
+ ) -> Result<Json<ProductListResponse>, AppError> {
405
+ let limit = params.limit.unwrap_or(20).min(100);
406
+
407
+ let products = sqlx::query_as::<_, Product>(
408
+ "SELECT * FROM products ORDER BY created_at LIMIT $1"
409
+ )
410
+ .bind(limit + 1)
411
+ .fetch_all(&pool)
412
+ .await?;
413
+
414
+ let has_more = products.len() as i64 > limit;
415
+ let data = if has_more {
416
+ products[..limit as usize].to_vec()
417
+ } else {
418
+ products
419
+ };
420
+
421
+ Ok(Json(ProductListResponse { data, has_more }))
422
+ }
423
+
424
+ pub async fn create_product(
425
+ State(pool): State<PgPool>,
426
+ Json(input): Json<CreateProductRequest>,
427
+ ) -> Result<(StatusCode, Json<Product>), AppError> {
428
+ if input.name.is_empty() || input.price <= 0.0 {
429
+ return Err(AppError::Validation("Invalid product data".into()));
430
+ }
431
+
432
+ let product = sqlx::query_as::<_, Product>(
433
+ r#"
434
+ INSERT INTO products (name, description, price, category_id)
435
+ VALUES ($1, $2, $3, $4)
436
+ RETURNING *
437
+ "#
438
+ )
439
+ .bind(&input.name)
440
+ .bind(&input.description)
441
+ .bind(input.price)
442
+ .bind(input.category_id)
443
+ .fetch_one(&pool)
444
+ .await?;
445
+
446
+ Ok((StatusCode::CREATED, Json(product)))
447
+ }
448
+
449
+ pub async fn get_product(
450
+ State(pool): State<PgPool>,
451
+ Path(id): Path<Uuid>,
452
+ ) -> Result<Json<Product>, AppError> {
453
+ let product = sqlx::query_as::<_, Product>(
454
+ "SELECT * FROM products WHERE id = $1"
455
+ )
456
+ .bind(id)
457
+ .fetch_optional(&pool)
458
+ .await?
459
+ .ok_or(AppError::NotFound)?;
460
+
461
+ Ok(Json(product))
462
+ }
463
+ ```
464
+
465
+ ### Custom Error Type
466
+
467
+ ```rust
468
+ // src/error.rs
469
+ use axum::{
470
+ http::StatusCode,
471
+ response::{IntoResponse, Response},
472
+ Json,
473
+ };
474
+ use serde_json::json;
475
+
476
+ #[derive(Debug)]
477
+ pub enum AppError {
478
+ NotFound,
479
+ Validation(String),
480
+ Database(sqlx::Error),
481
+ Internal(String),
482
+ }
483
+
484
+ impl IntoResponse for AppError {
485
+ fn into_response(self) -> Response {
486
+ let (status, message) = match self {
487
+ AppError::NotFound => (StatusCode::NOT_FOUND, "Resource not found".to_string()),
488
+ AppError::Validation(msg) => (StatusCode::BAD_REQUEST, msg),
489
+ AppError::Database(e) => {
490
+ tracing::error!("Database error: {:?}", e);
491
+ (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".to_string())
492
+ }
493
+ AppError::Internal(msg) => {
494
+ tracing::error!("Internal error: {}", msg);
495
+ (StatusCode::INTERNAL_SERVER_ERROR, "Internal server error".to_string())
496
+ }
497
+ };
498
+
499
+ (status, Json(json!({ "error": message }))).into_response()
500
+ }
501
+ }
502
+
503
+ impl From<sqlx::Error> for AppError {
504
+ fn from(err: sqlx::Error) -> Self {
505
+ AppError::Database(err)
506
+ }
507
+ }
508
+ ```
509
+
510
+ ---
511
+
512
+ ## Language Selection Guide
513
+
514
+ | Criteria | TypeScript | Python | Go | Rust |
515
+ |----------|-----------|--------|-----|------|
516
+ | **Best for** | Full-stack web apps | ML/AI, data pipelines | High-concurrency services | Systems, performance-critical |
517
+ | **Ecosystem** | Largest (npm) | Rich (ML/data) | Growing | Growing |
518
+ | **Performance** | Good (V8/Bun) | Moderate (async) | Excellent | Best |
519
+ | **Type Safety** | Good (strict TS) | Good (Pydantic) | Built-in | Best (compiler) |
520
+ | **Concurrency** | Event loop | asyncio/threading | Goroutines | async/tokio |
521
+ | **Learning Curve** | Low | Low | Medium | High |
522
+ | **Deploy Size** | Medium | Medium | Small (static) | Smallest (static) |
523
+ | **Startup Time** | Fast | Moderate | Very fast | Very fast |
524
+
525
+ ---
526
+
527
+ ## Conclusion
528
+ Choose the right language for the right job. TypeScript for rapid full-stack development, Python for data-heavy workloads, Go for high-concurrency microservices, and Rust for performance-critical systems. The patterns (validation, error handling, middleware) remain consistent across all languages.