Skip to content

Commit de33972

Browse files
authored
Merge pull request #126 from judithJn/fix/judith-issues-113-118-119-120
docs: fix .gitignore, architecture.md, add ADR folder and API reference
2 parents 9bc254c + 2e70234 commit de33972

7 files changed

Lines changed: 820 additions & 51 deletions

.gitignore

Lines changed: 114 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,115 @@
1-
.qodo
1+
# ============================================================
2+
# StellarHunts — root .gitignore
3+
# Covers: Node.js / NestJS, Next.js, Rust / Cargo, and IDEs
4+
# ============================================================
5+
6+
# ── Environment & secrets ───────────────────────────────────
7+
.env
8+
.env.*
9+
.env.local
10+
.env.*.local
11+
.env.development
12+
.env.development.local
13+
.env.test
14+
.env.test.local
15+
.env.production
16+
.env.production.local
17+
*.pem
18+
*.key
19+
*.p12
20+
secrets/
21+
22+
# ── Node / npm / yarn / pnpm ────────────────────────────────
23+
node_modules/
24+
npm-debug.log*
25+
yarn-debug.log*
26+
yarn-error.log*
27+
pnpm-debug.log*
28+
lerna-debug.log*
29+
.pnp
30+
.pnp.js
31+
.yarn/cache
32+
.yarn/unplugged
33+
.yarn/build-state.yml
34+
.yarn/install-state.gz
35+
36+
# ── Build artefacts ─────────────────────────────────────────
37+
dist/
38+
build/
39+
out/
40+
.next/
41+
.nuxt/
42+
.output/
43+
.cache/
44+
*.tsbuildinfo
45+
46+
# ── Rust / Cargo ────────────────────────────────────────────
47+
target/
48+
**/*.rs.bk
49+
.cargo/registry/
50+
.cargo/git/
51+
52+
# ── Test & coverage ─────────────────────────────────────────
53+
coverage/
54+
.nyc_output/
55+
test_snapshots/
56+
*.lcov
57+
*.snap
58+
59+
# ── Logs & diagnostics ──────────────────────────────────────
60+
logs/
61+
*.log
62+
pids/
63+
*.pid
64+
*.pid.lock
65+
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
66+
67+
# ── OS-generated ────────────────────────────────────────────
268
.DS_Store
3-
node_modules
4-
dist
5-
.env
69+
.DS_Store?
70+
._*
71+
.Spotlight-V100
72+
.Trashes
73+
Thumbs.db
74+
ehthumbs.db
75+
Desktop.ini
76+
77+
# ── IDE — JetBrains (IntelliJ / WebStorm / CLion / …) ───────
78+
.idea/
79+
*.iml
80+
*.iws
81+
*.ipr
82+
.project
83+
.classpath
84+
.settings/
85+
*.sublime-workspace
86+
*.sublime-project
87+
88+
# ── IDE — VS Code ───────────────────────────────────────────
89+
.vscode/*
90+
!.vscode/settings.json
91+
!.vscode/tasks.json
92+
!.vscode/launch.json
93+
!.vscode/extensions.json
94+
95+
# ── IDE — Eclipse / generic ─────────────────────────────────
96+
.c9/
97+
*.launch
98+
99+
# ── Temporary files ─────────────────────────────────────────
100+
.temp/
101+
.tmp/
102+
tmp/
103+
*.tmp
104+
*.bak
105+
*.swp
106+
*~
107+
108+
# ── Tooling ─────────────────────────────────────────────────
109+
.qodo
110+
.tool-versions
111+
.turbo/
112+
.parcel-cache/
113+
114+
# ── Docker (local overrides only — Dockerfiles stay tracked) ─
115+
docker-compose.override.yml
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
# ADR-0001: Record Architecture Decisions
2+
3+
**Date:** 2025-07-24
4+
**Status:** Accepted
5+
**Deciders:** StellarHunts core team
6+
7+
---
8+
9+
## Context
10+
11+
Architecture decisions in StellarHunts have historically been made in PR
12+
descriptions, Discord threads, and informal team discussions. When a new
13+
contributor joins, there is no single place to find *why* certain choices
14+
were made — only *what* the current code does. This creates ramp-up
15+
friction and leads to decisions being revisited unnecessarily.
16+
17+
## Decision
18+
19+
We will use Architecture Decision Records (ADRs) to capture significant
20+
architectural and design decisions. Each ADR is a short Markdown document
21+
stored in `docs/adr/` with a sequential four-digit prefix and a
22+
kebab-case title.
23+
24+
ADRs should be created when:
25+
- A technology or library is selected over alternatives
26+
- A structural pattern is established (e.g., module layout, naming)
27+
- An existing decision is reversed or superseded
28+
- A design has meaningful trade-offs worth documenting
29+
30+
ADRs are **immutable once accepted**. Superseding an old decision means
31+
creating a new ADR and updating the old one's status field.
32+
33+
### Template
34+
35+
```
36+
# ADR-NNNN: <Title>
37+
38+
**Date:** YYYY-MM-DD
39+
**Status:** Proposed | Accepted | Deprecated | Superseded by ADR-XXXX
40+
**Deciders:** <team or individuals>
41+
42+
---
43+
44+
## Context
45+
<What situation or problem prompted this decision?>
46+
47+
## Decision
48+
<What was decided?>
49+
50+
## Consequences
51+
### Positive
52+
<Benefits of this choice.>
53+
### Negative / Trade-offs
54+
<Costs, risks, or constraints introduced.>
55+
```
56+
57+
## Consequences
58+
59+
### Positive
60+
- New contributors can understand system rationale without reading PRs
61+
- Decisions are revisited deliberately rather than accidentally
62+
- Lightweight process — one Markdown file per decision
63+
64+
### Negative / Trade-offs
65+
- Requires discipline to write an ADR *before* merging significant changes
66+
- ADRs can go stale if not kept up to date with status changes
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# ADR-0002: Use Zustand as the Primary State Manager Alongside Redux Toolkit
2+
3+
**Date:** 2025-07-24
4+
**Status:** Accepted
5+
**Deciders:** StellarHunts frontend team
6+
7+
---
8+
9+
## Context
10+
11+
The StellarHunts frontend needs client-side state management for:
12+
13+
1. **Game state** — current puzzle, difficulty level, completed puzzles,
14+
score, NFT collection. This state must survive page refreshes
15+
(localStorage persistence) and is mutated frequently during gameplay.
16+
2. **Auth state** — current user, JWT token, wallet address.
17+
3. **Server state** — leaderboard data, puzzle content, referral stats.
18+
This is cached, stale-while-revalidate data fetched from the NestJS API.
19+
20+
Two popular choices were on the table: **Zustand** and
21+
**Redux Toolkit (RTK)**.
22+
23+
| Criterion | Zustand | Redux Toolkit |
24+
|-----------|---------|---------------|
25+
| Bundle size | ~3 kB | ~20 kB |
26+
| Boilerplate | Minimal (no actions/reducers) | Moderate (slice files) |
27+
| Middleware / devtools | Optional, plugin-based | First-class |
28+
| Persistence | `zustand/middleware` `persist` | `redux-persist` |
29+
| Learning curve | Low | Medium |
30+
| Ecosystem maturity | Stable, wide adoption | Very mature, huge ecosystem |
31+
32+
`@reduxjs/toolkit` is already listed as a production dependency (version
33+
`^2.5.1`) because it was planned for a more complex slice-based state
34+
model. In practice the team converged on Zustand stores for all current
35+
state needs.
36+
37+
## Decision
38+
39+
- **Zustand** is the **primary** state management library for game state,
40+
auth state, and reward state (see `frontend/store/`).
41+
- **`@reduxjs/toolkit`** remains in `package.json` and should be used if
42+
future requirements call for complex middleware chains, time-travel
43+
debugging, or shared state slices that benefit from RTK's code
44+
generation patterns (e.g., `createEntityAdapter`).
45+
- **TanStack Query** handles all *server state* — API responses, caching,
46+
background refetching — and is not replaced by either of the above.
47+
48+
## Consequences
49+
50+
### Positive
51+
- Simple, readable store definitions — a store is just a `create()` call
52+
- `persist` middleware handles localStorage serialization out of the box
53+
- Low bundle size contribution
54+
- Devtools integration available via `zustand/middleware` `devtools`
55+
56+
### Negative / Trade-offs
57+
- RTK's advanced features (immer-backed reducers, RTK Query, entity
58+
adapters) are unavailable unless RTK is wired up in the future
59+
- Two state libraries in `package.json` can confuse new contributors —
60+
this ADR resolves that ambiguity
61+
- No centralized dispatcher pattern; state mutations are co-located in
62+
store files, which can scatter business logic
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# ADR-0003: NestJS Modular Monolith Over Microservices
2+
3+
**Date:** 2025-07-24
4+
**Status:** Accepted
5+
**Deciders:** StellarHunts backend team
6+
7+
---
8+
9+
## Context
10+
11+
StellarHunts requires a backend that handles authentication, puzzle
12+
management, NFT claim orchestration, real-time multiplayer matchmaking,
13+
notifications, referrals, analytics, and more. These are distinct
14+
domains, so the question arose: should the backend be structured as a
15+
**microservices** cluster or a **monolith**?
16+
17+
The team evaluated three architectural patterns:
18+
19+
| Pattern | Deployment | Scaling | Complexity | Team size fit |
20+
|---------|-----------|---------|------------|---------------|
21+
| Unstructured monolith | Single process | Vertical only | Low initially | Small |
22+
| Modular monolith | Single process | Vertical + horizontal replicas | Medium | Small–medium |
23+
| Microservices | Many processes | Per-service horizontal | High | Large |
24+
25+
Key constraints at the time of decision:
26+
- Team of fewer than 10 engineers
27+
- Early-stage product — domain boundaries still evolving
28+
- Single PostgreSQL instance; cross-service transactions would be complex
29+
- Redis already required for Socket.IO adapter and rate limiting
30+
- Need to ship quickly and iterate
31+
32+
## Decision
33+
34+
The backend is a **NestJS modular monolith**.
35+
36+
- All domains live under `backend/src/` as NestJS feature modules
37+
(`@Module()` decorated classes).
38+
- Each module owns its controller, service, entities, and DTOs.
39+
- Cross-domain calls happen through NestJS dependency injection (imported
40+
modules), **not** via HTTP or a message bus.
41+
- The monolith is deployed as a single Docker container / process;
42+
horizontal scaling is achieved by running multiple replicas behind a
43+
load balancer with Redis as the shared session/socket adapter.
44+
45+
If a specific domain needs independent scaling in the future (e.g.,
46+
the multiplayer matchmaking gateway), it can be extracted into a
47+
standalone NestJS microservice using the built-in `@nestjs/microservices`
48+
transport layer with minimal refactoring because the module boundary
49+
already exists.
50+
51+
## Consequences
52+
53+
### Positive
54+
- Single deployment unit — simpler CI/CD and local development
55+
- No distributed-transaction complexity; TypeORM transactions work across
56+
all domains
57+
- NestJS DI container enforces explicit module boundaries without the
58+
operational overhead of separate services
59+
- Straightforward to extract a module into a microservice later
60+
61+
### Negative / Trade-offs
62+
- A poorly written module can import anything, eroding boundaries over
63+
time — code review must enforce the module contract
64+
- A crash in one domain crashes the whole process (mitigated by process
65+
managers and health checks)
66+
- Vertical scaling limits apply; the team must monitor whether any single
67+
domain (e.g., real-time sockets) becomes a bottleneck before extracting
68+
it

docs/adr/0004-soroban-over-evm.md

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
# ADR-0004: Use Soroban (Stellar) Over EVM-Compatible Chains
2+
3+
**Date:** 2025-07-24
4+
**Status:** Accepted
5+
**Deciders:** StellarHunts core team
6+
7+
---
8+
9+
## Context
10+
11+
StellarHunts awards on-chain NFT badges when players complete puzzle
12+
levels. The team needed to select a smart-contract platform to host:
13+
14+
1. **Game contract** — question lifecycle, answer validation (SHA-256),
15+
player level progression.
16+
2. **NFT badge contract** — per-level badge minting with role-gated
17+
authorization.
18+
19+
The two primary candidates were **Soroban on Stellar** and an
20+
**EVM-compatible chain** (Ethereum mainnet, Polygon, or Base).
21+
22+
| Criterion | Soroban / Stellar | EVM (Ethereum / Polygon) |
23+
|-----------|-------------------|--------------------------|
24+
| Transaction fees | Sub-cent on Stellar | Variable (gwei spikes on mainnet; low on L2s) |
25+
| Finality | ~5 s (Stellar consensus) | ~12 s ETH / ~2 s Polygon |
26+
| Smart contract language | Rust (soroban-sdk) | Solidity / Vyper |
27+
| Tooling maturity | Growing (Stellar CLI, soroban-cli) | Very mature (Hardhat, Foundry, OpenZeppelin) |
28+
| NFT standards | Custom (no ERC-721 equivalent yet) | ERC-721 / ERC-1155 well established |
29+
| Wallet ecosystem | Freighter, Lobstr, Albedo | MetaMask, WalletConnect (broad) |
30+
| Developer community | Smaller, niche | Large, extensive resources |
31+
| Educational alignment | Matches project's Stellar-learning theme | Generic blockchain knowledge |
32+
33+
The project's **educational mission** is to teach players about
34+
blockchain technology — specifically the Stellar ecosystem. Using Soroban
35+
keeps the on-chain layer consistent with the subject matter being taught.
36+
37+
## Decision
38+
39+
StellarHunts uses **Soroban smart contracts on the Stellar network** for
40+
all on-chain game logic and NFT badge minting.
41+
42+
- Contracts are written in **Rust** using `soroban-sdk 22.x`.
43+
- The workspace lives in `onchain/` with a Cargo workspace manifest.
44+
- Two production contracts exist:
45+
- `stellar_hunts` — game logic
46+
- `stellar_hunts_nft` — badge minting
47+
- Local development and CI use Stellar Testnet;
48+
`STELLAR_MODE=mock` allows the backend to run without a live network.
49+
- Answer privacy is preserved on-chain via `env.crypto().sha256()`
50+
no plaintext answers are stored in contract state.
51+
52+
## Consequences
53+
54+
### Positive
55+
- Aligns with the project's educational goal of teaching Stellar/Soroban
56+
- Very low and predictable transaction fees
57+
- Fast finality reduces wait time after puzzle completion
58+
- Rust's type system and Soroban's sandboxed WASM runtime provide strong
59+
safety guarantees
60+
- `STELLAR_MODE=mock` lets the backend be developed and tested without
61+
a live network dependency
62+
63+
### Negative / Trade-offs
64+
- Smaller developer community means fewer tutorials and third-party
65+
tooling compared to EVM
66+
- No standardized NFT interface (ERC-721) — badge ownership queries use
67+
a custom `has_level_badge` function
68+
- Freighter wallet has less browser/mobile coverage than MetaMask's
69+
ecosystem
70+
- Team members with an EVM background need to learn Rust and the Soroban
71+
execution model

0 commit comments

Comments
 (0)