feat: add Claude Code project skills — clean-code, hub-rules, commit-convention, event-driven, deploy-workflow
This commit is contained in:
@@ -0,0 +1,29 @@
|
|||||||
|
{
|
||||||
|
"skills": [
|
||||||
|
{
|
||||||
|
"name": "clean-code",
|
||||||
|
"filePattern": ".claude/skills/clean-code.md",
|
||||||
|
"description": "Clean Code, SOLID, dan Clean Architecture principles untuk proyek ini"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "hub-rules",
|
||||||
|
"filePattern": ".claude/skills/hub-rules.md",
|
||||||
|
"description": "Aturan repository hub, submodule, infra patterns, dan arsitektur"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "commit-convention",
|
||||||
|
"filePattern": ".claude/skills/commit-convention.md",
|
||||||
|
"description": "Commit message convention — type(scope): description"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "event-driven",
|
||||||
|
"filePattern": ".claude/skills/event-driven.md",
|
||||||
|
"description": "Event-driven patterns with Dapr + NATS untuk hub services"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "deploy-workflow",
|
||||||
|
"filePattern": ".claude/skills/deploy-workflow.md",
|
||||||
|
"description": "CI/CD pipeline, Docker patterns, deployment guide"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
---
|
||||||
|
name: clean-code
|
||||||
|
description: Clean Code, Clean Architecture, SOLID principles untuk proyek Asepharyana Hub
|
||||||
|
---
|
||||||
|
|
||||||
|
# Clean Code — Asepharyana Hub
|
||||||
|
|
||||||
|
## Prinsip Dasar
|
||||||
|
|
||||||
|
### 1. Naming
|
||||||
|
- **Gunakan nama yang mengungkapkan intensi**: `calculateTotal`, `fetchAnimeData`, `ImageCacheRepository` — bukan `calc`, `getData`, `Repo`.
|
||||||
|
- **Boolean prefix** dengan `is`, `has`, `should`: `isHealthy`, `hasPoster`, `shouldRetry`.
|
||||||
|
- **Hindari singkatan** kecuali sangat umum (`config`, `url`, `db`).
|
||||||
|
|
||||||
|
### 2. Fungsi
|
||||||
|
- **Satu fungsi = satu tanggung jawab**. Max 20 baris.
|
||||||
|
- **Nama fungsi sebagai kata kerja**: `validateToken()`, `cacheImage()`.
|
||||||
|
- **Parameter minimal**: max 3 parameter. Lebih dari itu bungkus jadi struct/object.
|
||||||
|
|
||||||
|
### 3. Clean Architecture Layers
|
||||||
|
|
||||||
|
```
|
||||||
|
Domain → Entities, Repository traits, Error enums
|
||||||
|
Application → Use cases
|
||||||
|
Infrastructure → Implementasi konkret (SeaORM, Redis, HTTP clients)
|
||||||
|
Presentation → Axum handlers, DTOs, middleware
|
||||||
|
```
|
||||||
|
|
||||||
|
Dependency rule: **kode layer dalam tidak tahu tentang layer luar**. Domain gak import framework.
|
||||||
|
|
||||||
|
### 4. Error Handling
|
||||||
|
- **Gunakan `thiserror`** untuk domain errors, bukan `anyhow` untuk library code.
|
||||||
|
- **`anyhow` hanya untuk** binary/app entry point dan test.
|
||||||
|
- **Convert domain errors ke HTTP** di presentation layer, bukan di use case.
|
||||||
|
|
||||||
|
### 5. Testing
|
||||||
|
- **TDD mindset**: tulis test sebelum implementasi untuk logic bisnis.
|
||||||
|
- **Unit test untuk use case + domain** (tanpa infra).
|
||||||
|
- **Integration test untuk repository** (dengan test container).
|
||||||
|
- **Mock trait**, bukan struct konkret.
|
||||||
|
|
||||||
|
## Untuk Proyek Ini
|
||||||
|
|
||||||
|
### Scraper Service (Rust)
|
||||||
|
- `src/domain/` — tipe data murni, trait, error — **tanpa framework**
|
||||||
|
- `src/application/` — use cases, orchestrasi, **tanpa HTTP**
|
||||||
|
- `src/infrastructure/` — implementasi repository, cache, HTTP client
|
||||||
|
- `src/presentation/` — handler Axum, routing, middleware
|
||||||
|
|
||||||
|
### Event-Driven (Dapr + NATS)
|
||||||
|
- Event schema pake CloudEvents format
|
||||||
|
- Topic naming: `hub.<domain>.<action>` (e.g. `hub.image.cached`)
|
||||||
|
- Handler hanya untuk satu tipe event, pisah file per domain
|
||||||
|
|
||||||
|
### Infra Config (YAML)
|
||||||
|
- Satu compose file per service
|
||||||
|
- Networking via `app-shared-net`
|
||||||
|
- Image tag selalu `sha-<short-sha>`, bukan `latest` di production
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
---
|
||||||
|
name: commit-convention
|
||||||
|
description: Enforce commit message convention untuk Asepharyana Hub
|
||||||
|
---
|
||||||
|
|
||||||
|
# Commit Convention — Asepharyana Hub
|
||||||
|
|
||||||
|
## Format
|
||||||
|
|
||||||
|
```
|
||||||
|
<type>(<scope>): <description>
|
||||||
|
|
||||||
|
[optional body]
|
||||||
|
|
||||||
|
[optional footer]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
| Type | Usage |
|
||||||
|
| ---------- | ------------------------------------ |
|
||||||
|
| `feat` | Fitur baru |
|
||||||
|
| `fix` | Bug fix |
|
||||||
|
| `chore` | Maintenance, config, tooling |
|
||||||
|
| `docs` | Dokumentasi |
|
||||||
|
| `refactor` | Perubahan kode tanpa fungsional baru |
|
||||||
|
| `test` | Nambah/update test |
|
||||||
|
| `ci` | CI/CD workflows |
|
||||||
|
| `perf` | Optimasi performa |
|
||||||
|
| `style` | Formatting (tanda kutip, dll) |
|
||||||
|
|
||||||
|
## Scopes
|
||||||
|
|
||||||
|
| Scope | Area |
|
||||||
|
| ------------- | --------------------------------- |
|
||||||
|
| `scraper` | apps/scraper submodule |
|
||||||
|
| `infra` | infra/ (compose, traefik, docker) |
|
||||||
|
| `ci` | .github/workflows/ |
|
||||||
|
| `dapr` | Dapr config & sidecar |
|
||||||
|
| `nats` | NATS message bus |
|
||||||
|
| `docs` | Dokumentasi |
|
||||||
|
| `deps` | Dependencies |
|
||||||
|
| `scripts` | Utility scripts |
|
||||||
|
| `root` | Root config files |
|
||||||
|
|
||||||
|
## Contoh
|
||||||
|
|
||||||
|
```
|
||||||
|
feat(scraper): add anime detail caching via Dapr pubsub
|
||||||
|
fix(infra): correct NATS CLI flags for JetStream
|
||||||
|
chore(deps): update biome to v2.5.3
|
||||||
|
docs(infra): add deployment order for Dapr services
|
||||||
|
ci(deploy): add nats.yml to ALL_COMPOSE_FILES
|
||||||
|
refactor(scraper): migrate EventBus from tokio broadcast to Dapr pubsub
|
||||||
|
```
|
||||||
|
|
||||||
|
## Aturan
|
||||||
|
|
||||||
|
1. **Wajib** menyertakan scope dalam tanda kurung
|
||||||
|
2. **Wajib** `Co-Authored-By` untuk commit yang digenerate AI
|
||||||
|
3. **Gunakan imperative mood**: "add" bukan "added" / "adds"
|
||||||
|
4. **Jangan capitalize** type: `feat:` bukan `Feat:`
|
||||||
|
5. **No period** di akhir subject baris
|
||||||
|
6. Body explain **why** dan **what**, bukan **how**
|
||||||
|
7. Refer issue dengan `Closes #123` atau `Fixes #123` di footer
|
||||||
@@ -0,0 +1,103 @@
|
|||||||
|
---
|
||||||
|
name: deploy-workflow
|
||||||
|
description: Panduan deploy, CI/CD, dan Docker compose patterns untuk Asepharyana Hub
|
||||||
|
---
|
||||||
|
|
||||||
|
# Deploy & Workflow — Asepharyana Hub
|
||||||
|
|
||||||
|
## CI/CD Pipeline
|
||||||
|
|
||||||
|
### Build Pipeline (`docker-build-push.yml`)
|
||||||
|
Trigger: push ke `main` yang touch `apps/**`, `infra/**`, `infra/docker/**`
|
||||||
|
|
||||||
|
1. **changes** — detect service mana yg berubah via git diff
|
||||||
|
2. **wait-submodule-ref** — (repository_dispatch only) tunggu SHA commit fetchable
|
||||||
|
3. **build** — matrix build per service, push ke GHCR (`sha-<short>` + `latest`)
|
||||||
|
4. **update-manifest** — update image tag di compose file, commit + push
|
||||||
|
|
||||||
|
### Deploy Pipeline (`deploy-docker.yml`)
|
||||||
|
Trigger: build selesai, atau push ke `main` touch `infra/**`
|
||||||
|
|
||||||
|
1. SSH ke `orangevps` (via `secrets.VPS_HOST`)
|
||||||
|
2. Sync repo (`git fetch --depth=1 + reset`)
|
||||||
|
3. Login ke GHCR
|
||||||
|
4. Deteksi compose file yg berubah
|
||||||
|
5. Pull images + restart container selektif
|
||||||
|
|
||||||
|
### Secrets Required
|
||||||
|
| Secret | Untuk |
|
||||||
|
|--------|-------|
|
||||||
|
| `SSH_PRIVATE_KEY` | SSH ke VPS |
|
||||||
|
| `VPS_HOST` | IP/host VPS (tailscale IP) |
|
||||||
|
| `VPS_USER` | SSH user, biasanya `root` |
|
||||||
|
| `VPS_TARGET_DIR` | Lokasi repo di VPS |
|
||||||
|
| `ENV_FILE_PRODUCTION` | .env content untuk production |
|
||||||
|
|
||||||
|
### Selective Deployment
|
||||||
|
- Hanya compose file yg berubah yang di-redeploy
|
||||||
|
- Selective: `UP_FLAGS="-d"` (tanpa `--remove-orphans`)
|
||||||
|
- Full deploy: `UP_FLAGS="-d --remove-orphans"`
|
||||||
|
|
||||||
|
## Docker Patterns
|
||||||
|
|
||||||
|
### Build dengan cargo-chef (Rust)
|
||||||
|
```dockerfile
|
||||||
|
FROM lukemathwalker/cargo-chef:latest-rust-1.89.0 AS chef
|
||||||
|
WORKDIR /app
|
||||||
|
FROM chef AS planner
|
||||||
|
COPY apps/scraper .
|
||||||
|
RUN cargo chef prepare --recipe-path recipe.json
|
||||||
|
FROM chef AS builder
|
||||||
|
COPY --from=planner /app/recipe.json recipe.json
|
||||||
|
RUN cargo chef cook --release --recipe-path recipe.json
|
||||||
|
COPY apps/scraper .
|
||||||
|
RUN cargo build --release
|
||||||
|
```
|
||||||
|
|
||||||
|
### Runtime minimal untuk Rust binary
|
||||||
|
```dockerfile
|
||||||
|
FROM debian:bookworm-slim AS runtime
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
ca-certificates curl libssl3 && rm -rf /var/lib/apt/lists/*
|
||||||
|
```
|
||||||
|
|
||||||
|
## Image Tagging
|
||||||
|
- `sha-<short-sha>` — immutable, untuk rollback
|
||||||
|
- `latest` — mutable, untuk convenience
|
||||||
|
- Build cache: `sha-<short>-buildcache`
|
||||||
|
- Registry: `ghcr.io/asepharyana/asepharyana-hub/<service>`
|
||||||
|
|
||||||
|
## Manual Deploy Steps
|
||||||
|
```bash
|
||||||
|
# 1. Login GHCR
|
||||||
|
echo $GITHUB_TOKEN | docker login ghcr.io -u asepharyana --password-stdin
|
||||||
|
|
||||||
|
# 2. Full stack
|
||||||
|
docker compose -f infra/compose/traefik.yml \
|
||||||
|
-f infra/compose/shared.yml \
|
||||||
|
-f infra/compose/nats.yml \
|
||||||
|
-f infra/compose/dapr.yml \
|
||||||
|
-f infra/compose/scraper.yml \
|
||||||
|
--env-file .env up -d --remove-orphans
|
||||||
|
|
||||||
|
# 3. Selective (hanya satu service)
|
||||||
|
docker compose -f infra/compose/scraper.yml --env-file .env up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Container reach Tailscale
|
||||||
|
Pastikan route ke Tailscale di main table:
|
||||||
|
```bash
|
||||||
|
ip route add 100.64.0.0/10 dev tailscale0 table main
|
||||||
|
systemctl restart tailscale-routes
|
||||||
|
```
|
||||||
|
|
||||||
|
### Healthcheck gagal di scratch images
|
||||||
|
NATS dan Dapr placement pake scratch — tidak bisa healthcheck. Cukup `service_started` di depends_on.
|
||||||
|
|
||||||
|
### Dapr sidecar crash
|
||||||
|
```bash
|
||||||
|
docker logs scraper-api-dapr | grep -iE "fatal|error"
|
||||||
|
```
|
||||||
|
Penyebab umum: komponen config salah, NATS/Dapr placement belum siap.
|
||||||
@@ -0,0 +1,133 @@
|
|||||||
|
---
|
||||||
|
name: event-driven
|
||||||
|
description: Event-driven patterns dengan Dapr + NATS untuk Asepharyana Hub
|
||||||
|
---
|
||||||
|
|
||||||
|
# Event-Driven Architecture — Asepharyana Hub
|
||||||
|
|
||||||
|
## Stack
|
||||||
|
- **Message Backbone**: NATS + JetStream (untuk streaming & job queue)
|
||||||
|
- **Pub/Sub Runtime**: Dapr sidecar per service (pubsub via Redis built-in)
|
||||||
|
- **State Store**: Dapr → Redis
|
||||||
|
|
||||||
|
## Event Topics Convention
|
||||||
|
|
||||||
|
```
|
||||||
|
hub.<domain>.<action>
|
||||||
|
|
||||||
|
Contoh:
|
||||||
|
hub.image.cached → Image selesai di-cache ke CDN
|
||||||
|
hub.image.repaired → Image diperbaiki (CNAME change)
|
||||||
|
hub.scrape.anime.done → Scrape anime selesai
|
||||||
|
hub.system.alert → Error/alert dari service
|
||||||
|
```
|
||||||
|
|
||||||
|
## CloudEvents Format
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"specversion": "1.0",
|
||||||
|
"type": "hub.image.cached",
|
||||||
|
"source": "scraper-api",
|
||||||
|
"subject": "anime-poster",
|
||||||
|
"id": "uuid-v4",
|
||||||
|
"time": "2026-07-21T10:00:00Z",
|
||||||
|
"datacontenttype": "application/json",
|
||||||
|
"data": { ... }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Publish Event (Rust via HTTP API)
|
||||||
|
|
||||||
|
Gunakan `reqwest` langsung ke Dapr sidecar (SDK Rust masih experimental):
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let event = serde_json::json!({
|
||||||
|
"specversion": "1.0",
|
||||||
|
"type": "hub.image.cached",
|
||||||
|
"source": "scraper-api",
|
||||||
|
"id": Uuid::new_v4().to_string(),
|
||||||
|
"time": chrono::Utc::now().to_rfc3339(),
|
||||||
|
"datacontenttype": "application/json",
|
||||||
|
"data": { "original_url": url, "cdn_url": cdn_url }
|
||||||
|
});
|
||||||
|
|
||||||
|
reqwest::Client::new()
|
||||||
|
.post("http://localhost:3500/v1.0/publish/pubsub/hub.image.cached")
|
||||||
|
.json(&event)
|
||||||
|
.send()
|
||||||
|
.await?;
|
||||||
|
```
|
||||||
|
|
||||||
|
## Service Invocation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl http://localhost:3500/v1.0/invoke/<app-id>/method/<path>
|
||||||
|
```
|
||||||
|
|
||||||
|
## State Store
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Set
|
||||||
|
curl -X POST http://localhost:3500/v1.0/state/statestore \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-d '[{"key": "mykey", "value": "myvalue"}]'
|
||||||
|
|
||||||
|
# Get
|
||||||
|
curl http://localhost:3500/v1.0/state/statestore/mykey
|
||||||
|
|
||||||
|
# Delete
|
||||||
|
curl -X DELETE http://localhost:3500/v1.0/state/statestore/mykey
|
||||||
|
```
|
||||||
|
|
||||||
|
## Scraper Event Integration
|
||||||
|
|
||||||
|
File yang perlu dimodifikasi untuk event-driven:
|
||||||
|
|
||||||
|
| File | Perubahan |
|
||||||
|
|------|-----------|
|
||||||
|
| `src/events/bus.rs` | Ganti backend dari tokio broadcast ke Dapr pub/sub |
|
||||||
|
| `src/bootstrap/mod.rs` | Init DaprClient, inject ke AppState |
|
||||||
|
| `src/presentation/state.rs` | Tambah `dapr_client` field |
|
||||||
|
| `src/proxy/use_cases.rs` | Publish `ImageRepaired` & `ImageCached` events |
|
||||||
|
| `src/infrastructure/services/images/cache.rs` | Emit event tiap cache selesai |
|
||||||
|
| `Cargo.toml` | Tambah `reqwest`, `uuid`, `chrono` (jika belum ada) |
|
||||||
|
|
||||||
|
## Event Handlers (Subscribe)
|
||||||
|
|
||||||
|
Buat `src/subscribers/` untuk handler:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
// src/subscribers/image_handler.rs
|
||||||
|
pub async fn handle_image_cached(event: CloudEvent) -> Result<()> {
|
||||||
|
// Log, notifikasi, update status
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Daftarkan subscribers di `bootstrap/mod.rs` dengan spawn task:
|
||||||
|
```rust
|
||||||
|
tokio::spawn(async move {
|
||||||
|
let mut stream = dapr_client.subscribe("pubsub", "hub.image.cached");
|
||||||
|
while let Some(event) = stream.next().await {
|
||||||
|
handle_image_cached(event).await;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing Event-Driven Code
|
||||||
|
|
||||||
|
```rust
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_publish_event() {
|
||||||
|
let client = MockDaprClient::new();
|
||||||
|
client.expect_publish()
|
||||||
|
.with(...)
|
||||||
|
.returning(|_| Ok(()));
|
||||||
|
// ... test
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,96 @@
|
|||||||
|
---
|
||||||
|
name: hub-rules
|
||||||
|
description: Aturan repository, arsitektur hub, submodule, dan workflow Asepharyana Hub
|
||||||
|
---
|
||||||
|
|
||||||
|
# Asepharyana Hub — Repository Rules
|
||||||
|
|
||||||
|
## Struktur Repository
|
||||||
|
|
||||||
|
```
|
||||||
|
asepharyana-hub/
|
||||||
|
├── apps/ # Git submodules — source code aplikasi
|
||||||
|
├── docs/ # Dokumentasi, ADR, deployment guide
|
||||||
|
├── infra/ # Infrastructure as code
|
||||||
|
│ ├── compose/ # Satu compose file per service
|
||||||
|
│ ├── dapr/ # Dapr component configs
|
||||||
|
│ ├── docker/ # Dockerfiles per service
|
||||||
|
│ └── traefik/ # Static & dynamic Traefik config
|
||||||
|
├── scripts/ # Utility scripts (cleanup, update-deps)
|
||||||
|
└── .github/workflows/ # CI/CD pipelines
|
||||||
|
```
|
||||||
|
|
||||||
|
### Aturan Submodule
|
||||||
|
- Setiap aplikasi di `apps/` adalah **submodule** ke repo terpisah.
|
||||||
|
- Perubahan kode aplikasi dilakukan di **repo masing-masing**, bukan di sini.
|
||||||
|
- Submodule pointer diupdate oleh CI/CD (bukan manual).
|
||||||
|
|
||||||
|
## Infrastructure Patterns
|
||||||
|
|
||||||
|
### Networking
|
||||||
|
- Semua service join **`app-shared-net`** (external Docker bridge)
|
||||||
|
- Service discovery via Docker DNS (container alias)
|
||||||
|
- Traefik sebagai ingress untuk HTTP/S eksternal
|
||||||
|
- Tailscale untuk cross-VPS (PostgreSQL, Redis, browserless di `imrnes`)
|
||||||
|
|
||||||
|
### Compose File Pattern
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
<service>:
|
||||||
|
container_name: <service>
|
||||||
|
image: ghcr.io/asepharyana/asepharyana-hub/<service>:sha-<sha>
|
||||||
|
restart: always
|
||||||
|
networks:
|
||||||
|
app-shared-net:
|
||||||
|
aliases:
|
||||||
|
- <service>
|
||||||
|
env_file:
|
||||||
|
- ../../.env
|
||||||
|
|
||||||
|
networks:
|
||||||
|
app-shared-net:
|
||||||
|
name: app-shared-net
|
||||||
|
external: true
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dapr Sidecar Pattern
|
||||||
|
```yaml
|
||||||
|
<service>-dapr:
|
||||||
|
container_name: <service>-dapr
|
||||||
|
image: daprio/daprd:latest
|
||||||
|
restart: always
|
||||||
|
depends_on:
|
||||||
|
nats:
|
||||||
|
condition: service_started
|
||||||
|
dapr-placement:
|
||||||
|
condition: service_started
|
||||||
|
networks:
|
||||||
|
- app-shared-net
|
||||||
|
command:
|
||||||
|
- './daprd'
|
||||||
|
- '--app-id=<service>'
|
||||||
|
- '--app-port=<port>'
|
||||||
|
- '--dapr-http-port=3500'
|
||||||
|
- '--dapr-grpc-port=50001'
|
||||||
|
- '--placement-host-address=dapr-placement:50005'
|
||||||
|
- '--resources-path=/components'
|
||||||
|
volumes:
|
||||||
|
- ../../infra/dapr/components:/components
|
||||||
|
```
|
||||||
|
|
||||||
|
### Traefik Routing
|
||||||
|
- Router + service definition di `infra/traefik/dynamic/apps.yaml`
|
||||||
|
- Subdomain pattern: `<service>.asepharyana.my.id` + `<service>.asepharyana.web.id`
|
||||||
|
- TLS cert dari volume mount (bukan auto-acme)
|
||||||
|
|
||||||
|
### CI/CD
|
||||||
|
- `docker-build-push.yml` — build per service, push ke GHCR, update compose manifest
|
||||||
|
- `deploy-docker.yml` — SSH ke orangevps, pull images, restart
|
||||||
|
- Selective deploy: hanya compose file yg berubah
|
||||||
|
|
||||||
|
## Deployment Order
|
||||||
|
1. `shared.yml` (Redis)
|
||||||
|
2. `nats.yml` (NATS message bus)
|
||||||
|
3. `dapr.yml` (Dapr placement)
|
||||||
|
4. `traefik.yml` (Reverse proxy)
|
||||||
|
5. Service compose files (apps + Dapr sidecar)
|
||||||
+3
-2
@@ -38,12 +38,13 @@ testem.log
|
|||||||
# System Files
|
# System Files
|
||||||
.DS_Store
|
.DS_Store
|
||||||
Thumbs.db
|
Thumbs.db
|
||||||
.claude
|
.claude/*
|
||||||
|
!.claude/skills/
|
||||||
|
!.claude/settings.json
|
||||||
# Next.js
|
# Next.js
|
||||||
.next
|
.next
|
||||||
out
|
out
|
||||||
**/.codegraph/**
|
**/.codegraph/**
|
||||||
**/.claude/**
|
|
||||||
test-output
|
test-output
|
||||||
**/**.env
|
**/**.env
|
||||||
**/**.env.**
|
**/**.env.**
|
||||||
|
|||||||
Reference in New Issue
Block a user