diff --git a/.github/workflows/deploy-backend.yml b/.github/workflows/deploy-backend.yml
index 7559fd0..285fd47 100644
--- a/.github/workflows/deploy-backend.yml
+++ b/.github/workflows/deploy-backend.yml
@@ -49,6 +49,7 @@ jobs:
run: |
DOCKER_BUILDKIT=0 docker build \
--platform linux/amd64 \
+ --target production \
-t registry.heroku.com/${HEROKU_BACKEND_APP}/web \
-f backend/Dockerfile backend
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d0d923a
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,55 @@
+# Docker Compose Commands for Different Environments
+
+# Development - with hot reload and dev tools
+dev:
+ docker compose -f docker-compose.dev.yml up --build
+
+dev-detached:
+ docker compose -f docker-compose.dev.yml up --build -d
+
+# Production - optimized builds
+prod:
+ docker compose -f docker-compose.prod.yml up --build
+
+prod-detached:
+ docker compose -f docker-compose.prod.yml up --build -d
+
+# Testing - run tests in containers
+test:
+ docker compose -f docker-compose.test.yml up --build --abort-on-container-exit
+
+# Database only - just PostgreSQL
+db:
+ docker compose -f docker-compose.db-only.yml up -d
+
+# Clean up
+clean:
+ docker compose -f docker-compose.dev.yml down -v
+ docker compose -f docker-compose.prod.yml down -v
+ docker compose -f docker-compose.test.yml down -v
+ docker compose -f docker-compose.db-only.yml down -v
+
+# Stop all services
+stop:
+ docker compose -f docker-compose.dev.yml down
+ docker compose -f docker-compose.prod.yml down
+ docker compose -f docker-compose.test.yml down
+ docker compose -f docker-compose.db-only.yml down
+
+# View logs
+logs-dev:
+ docker compose -f docker-compose.dev.yml logs -f
+
+logs-prod:
+ docker compose -f docker-compose.prod.yml logs -f
+
+# Shell access
+shell-backend-dev:
+ docker compose -f docker-compose.dev.yml exec backend bash
+
+shell-backend-prod:
+ docker compose -f docker-compose.prod.yml exec backend bash
+
+# Database access
+db-shell:
+ docker compose -f docker-compose.db-only.yml exec postgres psql -U guild_user -d guild_genesis
diff --git a/README.md b/README.md
index 77b18e9..bb91836 100644
--- a/README.md
+++ b/README.md
@@ -39,26 +39,107 @@ This is a monorepo containing:
### Prerequisites
- [Docker](https://www.docker.com/)
+- [Node.js](https://nodejs.org/) (for frontend development)
+- [Astro CLI](https://docs.astro.build/en/getting-started/) (for frontend development)
- [Foundry](https://book.getfoundry.sh/getting-started/installation) (for smart contracts)
+### Environment Setup
+
+Create a `.env` file in the project root with the following variables:
+
+```bash
+# Database
+DATABASE_URL=postgresql://guild_user:guild_password@localhost:5433/guild_genesis
+
+# Frontend Environment Variables
+PUBLIC_WALLET_CONNECT_PROJECT_ID=your_wallet_connect_project_id
+PUBLIC_API_URL=http://localhost:3001
+PUBLIC_BADGE_REGISTRY_ADDRESS=0x...
+PUBLIC_EAS_CONTRACT_ADDRESS=0x...
+PUBLIC_ACTIVITY_TOKEN_ADDRESS=0x...
+PUBLIC_SCHEMA_ID=0x...
+
+# Discord Bot (if using)
+DISCORD_TOKEN=your_discord_bot_token
+DISCORD_CLIENT_ID=your_discord_client_id
+DISCORD_GUILD_ID=your_discord_guild_id
+
+# Optional: Skip migrations in development
+SKIP_MIGRATIONS=1
+
+# Optional: Disable SQLx compile-time validation
+SQLX_OFFLINE=true
+```
+
+**Required for Production:**
+- `DATABASE_URL` - PostgreSQL connection string
+- `PUBLIC_WALLET_CONNECT_PROJECT_ID` - Get from [WalletConnect Cloud](https://cloud.walletconnect.com/)
+- Contract addresses - Deploy smart contracts first
+
+**Optional for Development:**
+- `SKIP_MIGRATIONS=1` - Skip automatic migrations (run manually)
+- `SQLX_OFFLINE=true` - Disable SQLx compile-time validation
+
### Development Workflow
-#### Quick Start
+#### Option 1: Docker Compose (Recommended)
+
+We provide multiple Docker Compose configurations for different environments:
+```bash
+# Development with hot reload
+make dev
+
+# Production build
+make prod
+
+# Run tests
+make test
+
+# Database only
+make db
+
+# Stop all services
+make stop
+```
+
+#### Option 2: Local Development
+
+**Backend:**
```bash
cd backend
cargo install sqlx-cli --no-default-features --features rustls,postgres
cargo sqlx prepare -- --bin guild-backend
```
+**Frontend:**
+```bash
+cd frontend
+npm install
+npm run dev
+```
+
+**Database:**
+```bash
+docker compose up -d postgres
+```
+
+### Docker Compose Environments
+
+- **`docker-compose.dev.yml`** - Development with hot reload, volume mounts, and dev tools
+- **`docker-compose.prod.yml`** - Production with optimized builds and restart policies
+- **`docker-compose.test.yml`** - Testing environment with test-specific configurations
+- **`docker-compose.db-only.yml`** - Just PostgreSQL for local development
+
+Use `make` commands or specify files directly:
```bash
-docker-compose up -d
+docker compose -f docker-compose.dev.yml up --build
```
**Access the applications:**
-- Frontend: http://localhost:4321
+- Frontend: http://localhost:3000
- Backend API: http://localhost:3001
-- PostgreSQL: localhost:5432
+- PostgreSQL: localhost:5433
#### Smart Contracts Development
@@ -131,9 +212,9 @@ event BadgeCreated(bytes32 indexed name, bytes32 description, address indexed cr
- [x] Web3 wallet integration
- [x] Basic profile and badge system
- [x] Smart contracts for on-chain badges
-- [ ] SIWE authentication
+- [x] SIWE authentication
- [ ] Database models and migrations
-- [ ] API endpoints for profiles and badges
+- [x] API endpoints for profiles and badges
### V1+ (Future)
- [ ] Gasless transactions
@@ -152,7 +233,7 @@ event BadgeCreated(bytes32 indexed name, bytes32 description, address indexed cr
## Contributing
-This is a community-driven project. Join our [Discord](https://discord.gg/pg4UgaTr) to discuss features, propose changes, and contribute to the codebase.
+This is a community-driven project. Join our [Discord](https://discord.gg/axCqT23Xhj) to discuss features, propose changes, and contribute to the codebase.
See detailed steps in [CONTRIBUTION.md](CONTRIBUTION.md).
diff --git a/backend/.dockerignore b/backend/.dockerignore
new file mode 100644
index 0000000..abb23e6
--- /dev/null
+++ b/backend/.dockerignore
@@ -0,0 +1,34 @@
+# Rust build artifacts
+target/
+Cargo.lock
+
+# IDE files
+.vscode/
+.idea/
+*.swp
+*.swo
+
+# OS files
+.DS_Store
+Thumbs.db
+
+# Git
+.git/
+.gitignore
+
+# Documentation
+README.md
+*.md
+
+# Environment files
+.env
+.env.local
+.env.*.local
+
+# Logs
+*.log
+logs/
+
+# Temporary files
+tmp/
+temp/
diff --git a/backend/Dockerfile b/backend/Dockerfile
index 068cd67..f26d484 100644
--- a/backend/Dockerfile
+++ b/backend/Dockerfile
@@ -1,18 +1,35 @@
-FROM rust:latest AS build
+FROM rust:latest AS base
+WORKDIR /app
+
+# Development stage
+FROM base AS dev
+RUN cargo install cargo-watch
+COPY . .
+ENV RUST_LOG=debug RUST_BACKTRACE=1
+CMD ["cargo", "watch", "-x", "run --bin guild-backend"]
+
+# Test stage
+FROM base AS test
+COPY . .
+CMD ["cargo", "test", "--", "--test-threads=1"]
+
+# Build stage
+FROM base AS build
WORKDIR /app
ENV SQLX_OFFLINE=true
COPY . .
RUN cargo build --release
-FROM debian:bookworm-slim
+# Production stage
+FROM debian:bookworm-slim AS production
RUN apt-get update && apt-get install -y --no-install-recommends \
netcat-openbsd \
&& rm -rf /var/lib/apt/lists/*
RUN useradd -m appuser
WORKDIR /app
-COPY --from=build /app/target/release/guild-backend /app/app
+COPY --from=build /app/target/release/guild-backend /app/guild-backend
ENV RUST_LOG=info PORT=3001
EXPOSE 3001
USER appuser
-CMD ["/app/app"]
+CMD ["/app/guild-backend"]
diff --git a/backend/README.md b/backend/README.md
index 293db90..dbb243c 100644
--- a/backend/README.md
+++ b/backend/README.md
@@ -18,19 +18,24 @@ RUST_LOG=guild_backend=debug,tower_http=debug
```
The server requires `DATABASE_URL` at runtime.
-## 3) Start local Postgres
-From the repo root, using Just:
-```
-just db-setup
-```
-This will:
-- init `.postgres/` if missing
-- start Postgres on localhost:5432
-- create DB `guild_genesis` and user `guild_user/guild_password`
-- run backend migrations
+## 3) Database Setup
+
+### Option A: Use existing PostgreSQL (Recommended)
+If you have PostgreSQL running locally (via Homebrew, Docker, etc.):
+```bash
+# Create database and user
+psql -h localhost -p 5432 -U $(whoami) -c "CREATE DATABASE guild_genesis;" || true
+psql -h localhost -p 5432 -U $(whoami) -c "CREATE USER guild_user WITH PASSWORD 'guild_password';" || true
+psql -h localhost -p 5432 -U $(whoami) -c "GRANT ALL PRIVILEGES ON DATABASE guild_genesis TO guild_user;" || true
-Manual alternative (repo root):
+# Grant schema permissions
+psql -h localhost -p 5432 -U $(whoami) -d guild_genesis -c "GRANT ALL PRIVILEGES ON SCHEMA public TO guild_user;"
+psql -h localhost -p 5432 -U $(whoami) -d guild_genesis -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO guild_user;"
```
+
+### Option B: Start local PostgreSQL instance
+From the repo root:
+```bash
initdb -D .postgres
pg_ctl -D .postgres -l .postgres/postgres.log start
@@ -38,18 +43,36 @@ createdb guild_genesis || true
psql -d guild_genesis -c "CREATE USER guild_user WITH PASSWORD 'guild_password';" || true
psql -d guild_genesis -c "GRANT ALL PRIVILEGES ON DATABASE guild_genesis TO guild_user;" || true
```
-Stop Postgres:
-```
+
+Stop local Postgres:
+```bash
pg_ctl -D .postgres stop
```
-## 4) Run migrations (optional)
-Migrations run on server startup. To run explicitly:
-```
+## 4) Database Migrations
+
+### Development (Manual Migrations)
+For local development, run migrations manually to avoid SQLx compile-time validation issues:
+```bash
cd backend
-cargo run --bin guild-backend
+psql -h localhost -p 5432 -U $(whoami) -d guild_genesis -f migrations/001_initial_schema.sql
+psql -h localhost -p 5432 -U $(whoami) -d guild_genesis -f migrations/002_add_github_login.sql
+psql -h localhost -p 5432 -U $(whoami) -d guild_genesis -f migrations/003_add_nonces.sql
+
+# Then start server with migrations disabled
+SKIP_MIGRATIONS=1 cargo run --bin guild-backend
```
+### Production (Automatic Migrations)
+In production (Heroku, etc.), migrations run automatically on server startup. No additional setup needed.
+
+### Disable SQLx Compile-time Validation (Development Only)
+To avoid SQLx compile-time query validation issues during development:
+```bash
+export SQLX_OFFLINE=true
+```
+This allows compilation without a database connection, but you lose compile-time query validation.
+
## 5) Launch the API
```
cd backend
@@ -114,23 +137,55 @@ curl -X PUT \
Integration and automated tests run under `TEST_MODE=1`, which swaps in a test-only auth layer so GitHub handle flows can be exercised without Ethereum signature verification.
-## 7) Troubleshooting
-- initdb locale error:
-```
-LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 initdb --locale=en_US.UTF-8 --encoding=UTF8 -D .postgres
-```
-- Permission denied on schema `public`:
-```
-psql -U postgres -d guild_genesis -c "ALTER SCHEMA public OWNER TO guild_user;"
-psql -U postgres -d guild_genesis -c "GRANT USAGE, CREATE ON SCHEMA public TO guild_user;"
-```
-- Rust edition 2024 error: repo pins `base64ct = 1.7.3`. If still present, `rustup update` or `rustup override set nightly` in `backend/`.
-
-## 8) Structure
-- `src/main.rs`: boot server, run migrations
+## 7) Deployment
+
+### Heroku
+1. Set environment variables:
+ ```bash
+ heroku config:set DATABASE_URL=postgresql://...
+ heroku config:set RUST_LOG=guild_backend=info
+ ```
+
+2. Deploy:
+ ```bash
+ git push heroku main
+ ```
+
+Migrations run automatically on deployment. No additional setup needed.
+
+### Docker
+```bash
+docker build -t guild-backend .
+docker run -e DATABASE_URL=postgresql://... guild-backend
+```
+
+## 8) Troubleshooting
+
+### Database Issues
+- **Port already in use**: Check what's running on port 5432: `lsof -i :5432`
+- **Permission denied**: Ensure `guild_user` has proper permissions:
+ ```bash
+ psql -h localhost -p 5432 -U $(whoami) -d guild_genesis -c "GRANT ALL PRIVILEGES ON SCHEMA public TO guild_user;"
+ psql -h localhost -p 5432 -U $(whoami) -d guild_genesis -c "GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO guild_user;"
+ ```
+- **initdb locale error**:
+ ```bash
+ LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 initdb --locale=en_US.UTF-8 --encoding=UTF8 -D .postgres
+ ```
+
+### Server Issues
+- **Port 3001 already in use**: Use a different port: `PORT=3002 cargo run --bin guild-backend`
+- **SQLx compile errors**:
+ - For development: Set `SQLX_OFFLINE=true` and run migrations manually
+ - For production: Ensure database is accessible during compilation
+- **Migration conflicts**: Use `SKIP_MIGRATIONS=1` to disable automatic migrations
+- **Rust edition 2024 error**: Repo pins `base64ct = 1.7.3`. If still present, `rustup update` or `rustup override set nightly` in `backend/`.
+
+## 9) Structure
+- `src/main.rs`: boot server (automatic migrations in production, manual in dev)
- `src/bin/migrate.rs`: standalone migrator
- `src/presentation`: routes, handlers, middlewares
- `src/infrastructure`: Postgres repository, Ethereum verification
- `src/domain`: entities, repository traits, services
- `src/application`: commands and DTOs
-- `migrations/`: SQLx migrations
+- `migrations/`: SQLx migration files
diff --git a/backend/migrations/001_initial_schema.sql b/backend/migrations/001_initial_schema.sql
index a495824..c3960e2 100644
--- a/backend/migrations/001_initial_schema.sql
+++ b/backend/migrations/001_initial_schema.sql
@@ -1,4 +1,4 @@
-CREATE TABLE profiles (
+CREATE TABLE IF NOT EXISTS profiles (
address VARCHAR(255) PRIMARY KEY,
name VARCHAR(255),
description TEXT,
diff --git a/backend/src/main.rs b/backend/src/main.rs
index add0c9b..3cd0dd0 100644
--- a/backend/src/main.rs
+++ b/backend/src/main.rs
@@ -27,7 +27,10 @@ async fn main() -> anyhow::Result<()> {
panic!("Database connection required");
});
- sqlx::migrate!("./migrations").run(&pool).await?;
+ // Run migrations automatically in production, manually in development
+ if env::var("SKIP_MIGRATIONS").is_err() {
+ sqlx::migrate!("./migrations").run(&pool).await?;
+ }
let app = create_app(pool).await;
diff --git a/docker-compose.db-only.yml b/docker-compose.db-only.yml
new file mode 100644
index 0000000..ef1d2e5
--- /dev/null
+++ b/docker-compose.db-only.yml
@@ -0,0 +1,16 @@
+version: "3.9"
+
+services:
+ postgres:
+ image: postgres:16
+ environment:
+ POSTGRES_USER: guild_user
+ POSTGRES_PASSWORD: guild_password
+ POSTGRES_DB: guild_genesis
+ ports:
+ - "5433:5432"
+ volumes:
+ - pg_data_db:/var/lib/postgresql/data
+
+volumes:
+ pg_data_db:
diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml
new file mode 100644
index 0000000..0331733
--- /dev/null
+++ b/docker-compose.dev.yml
@@ -0,0 +1,56 @@
+services:
+ postgres:
+ image: postgres:16
+ environment:
+ POSTGRES_USER: guild_user
+ POSTGRES_PASSWORD: guild_password
+ POSTGRES_DB: guild_genesis
+ ports:
+ - "5433:5432"
+ volumes:
+ - pg_data_dev:/var/lib/postgresql/data
+ # Mount migrations for easy access
+ - ./backend/migrations:/docker-entrypoint-initdb.d
+
+ backend:
+ build:
+ context: ./backend
+ target: dev
+ command: ["cargo", "run", "--bin", "guild-backend"]
+ environment:
+ RUST_LOG: debug
+ RUST_BACKTRACE: 1
+ PORT: 3001
+ DATABASE_URL: postgresql://guild_user:guild_password@postgres:5432/guild_genesis
+ SKIP_MIGRATIONS: 1 # Skip migrations in dev
+ SQLX_OFFLINE: true # Disable compile-time validation
+ env_file:
+ - .env
+ ports:
+ - "3001:3001"
+ volumes:
+ - ./backend:/app
+ - cargo_cache:/usr/local/cargo/registry
+ depends_on:
+ - postgres
+
+ frontend:
+ build:
+ context: ./frontend
+ dockerfile: Dockerfile.dev
+ command: ["npm", "run", "dev"]
+ environment:
+ HOST: 0.0.0.0
+ PORT: 4321
+ NODE_ENV: development
+ ports:
+ - "4321:4321"
+ volumes:
+ - ./frontend:/app
+ - /app/node_modules
+ depends_on:
+ - backend
+
+volumes:
+ pg_data_dev:
+ cargo_cache:
diff --git a/docker-compose.prod.yml b/docker-compose.prod.yml
new file mode 100644
index 0000000..d83087c
--- /dev/null
+++ b/docker-compose.prod.yml
@@ -0,0 +1,84 @@
+version: "3.9"
+
+services:
+ postgres:
+ image: postgres:16
+ environment:
+ POSTGRES_USER: guild_user
+ POSTGRES_PASSWORD: guild_password
+ POSTGRES_DB: guild_genesis
+ ports:
+ - "5433:5432"
+ volumes:
+ - pg_data_prod:/var/lib/postgresql/data
+ # Production: no volume mounts for security
+
+ backend:
+ build:
+ context: ./backend
+ target: production
+ command: ["/app/guild-backend"]
+ environment:
+ RUST_LOG: info
+ PORT: 3001
+ # No SKIP_MIGRATIONS - migrations run automatically
+ env_file:
+ - .env
+ ports:
+ - "3001:3001"
+ depends_on:
+ - postgres
+ restart: unless-stopped
+
+ indexer:
+ build:
+ context: ./indexer
+ target: production
+ command: ["/app/indexer"]
+ environment:
+ RUST_LOG: info
+ PORT: 3002
+ env_file:
+ - .env
+ ports:
+ - "3002:3002"
+ depends_on:
+ - postgres
+ restart: unless-stopped
+
+ frontend:
+ build:
+ context: ./frontend
+ dockerfile: Dockerfile
+ args:
+ PUBLIC_WALLET_CONNECT_PROJECT_ID: ${PUBLIC_WALLET_CONNECT_PROJECT_ID}
+ PUBLIC_API_URL: ${PUBLIC_API_URL}
+ PUBLIC_BADGE_REGISTRY_ADDRESS: ${PUBLIC_BADGE_REGISTRY_ADDRESS}
+ PUBLIC_EAS_CONTRACT_ADDRESS: ${PUBLIC_EAS_CONTRACT_ADDRESS}
+ PUBLIC_ACTIVITY_TOKEN_ADDRESS: ${PUBLIC_ACTIVITY_TOKEN_ADDRESS}
+ PUBLIC_SCHEMA_ID: ${PUBLIC_SCHEMA_ID}
+ environment:
+ HOST: 0.0.0.0
+ PORT: 3000
+ NODE_ENV: production
+ ports:
+ - "3000:3000"
+ depends_on:
+ - backend
+ restart: unless-stopped
+
+ discord-bot:
+ build:
+ context: ./discord-bot
+ target: production
+ env_file:
+ - .env
+ environment:
+ DATABASE_URL: postgresql://guild_user:guild_password@postgres:5432/guild_genesis
+ NODE_ENV: production
+ depends_on:
+ - postgres
+ restart: unless-stopped
+
+volumes:
+ pg_data_prod:
diff --git a/docker-compose.test.yml b/docker-compose.test.yml
new file mode 100644
index 0000000..893c819
--- /dev/null
+++ b/docker-compose.test.yml
@@ -0,0 +1,33 @@
+version: "3.9"
+
+services:
+ postgres:
+ image: postgres:16
+ environment:
+ POSTGRES_USER: guild_user
+ POSTGRES_PASSWORD: guild_password
+ POSTGRES_DB: guild_genesis
+ ports:
+ - "5433:5432"
+ volumes:
+ - pg_data_test:/var/lib/postgresql/data
+
+ backend:
+ build:
+ context: ./backend
+ target: test
+ command: ["cargo", "test"]
+ environment:
+ RUST_LOG: debug
+ RUST_BACKTRACE: 1
+ TEST_MODE: 1
+ SKIP_MIGRATIONS: 1
+ env_file:
+ - .env
+ volumes:
+ - ./backend:/app
+ depends_on:
+ - postgres
+
+volumes:
+ pg_data_test:
diff --git a/frontend/.astro/data-store.json b/frontend/.astro/data-store.json
index 9e8a7dc..805c3fe 100644
--- a/frontend/.astro/data-store.json
+++ b/frontend/.astro/data-store.json
@@ -1 +1 @@
-[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.14.1","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"server\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":false,\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\",\"entrypoint\":\"astro/assets/endpoint/node\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false},\"legacy\":{\"collections\":false},\"session\":{\"driver\":\"fs-lite\",\"options\":{\"base\":\"/Users/antoineestienne/GithubRepositories/TheGuildGenesis/frontend/node_modules/.astro/sessions\"}}}"]
\ No newline at end of file
+[["Map",1,2],"meta::meta",["Map",3,4,5,6],"astro-version","5.14.1","astro-config-digest","{\"root\":{},\"srcDir\":{},\"publicDir\":{},\"outDir\":{},\"cacheDir\":{},\"compressHTML\":true,\"base\":\"/\",\"trailingSlash\":\"ignore\",\"output\":\"server\",\"scopedStyleStrategy\":\"attribute\",\"build\":{\"format\":\"directory\",\"client\":{},\"server\":{},\"assets\":\"_astro\",\"serverEntry\":\"entry.mjs\",\"redirects\":true,\"inlineStylesheets\":\"auto\",\"concurrency\":1},\"server\":{\"open\":false,\"host\":\"0.0.0.0\",\"port\":4321,\"streaming\":true,\"allowedHosts\":[]},\"redirects\":{},\"image\":{\"endpoint\":{\"route\":\"/_image\",\"entrypoint\":\"astro/assets/endpoint/node\"},\"service\":{\"entrypoint\":\"astro/assets/services/sharp\",\"config\":{}},\"domains\":[],\"remotePatterns\":[],\"responsiveStyles\":false},\"devToolbar\":{\"enabled\":true},\"markdown\":{\"syntaxHighlight\":{\"type\":\"shiki\",\"excludeLangs\":[\"math\"]},\"shikiConfig\":{\"langs\":[],\"langAlias\":{},\"theme\":\"github-dark\",\"themes\":{},\"wrap\":false,\"transformers\":[]},\"remarkPlugins\":[],\"rehypePlugins\":[],\"remarkRehype\":{},\"gfm\":true,\"smartypants\":true},\"security\":{\"checkOrigin\":true},\"env\":{\"schema\":{},\"validateSecrets\":false},\"experimental\":{\"clientPrerender\":false,\"contentIntellisense\":false,\"headingIdCompat\":false,\"preserveScriptOrder\":false,\"liveContentCollections\":false,\"csp\":false,\"staticImportMetaEnv\":false,\"chromeDevtoolsWorkspace\":false,\"failOnPrerenderConflict\":false},\"legacy\":{\"collections\":false},\"session\":{\"driver\":\"fs-lite\",\"options\":{\"base\":\"/app/node_modules/.astro/sessions\"}}}"]
\ No newline at end of file
diff --git a/frontend/.astro/settings.json b/frontend/.astro/settings.json
index cf5b02c..2e8ce89 100644
--- a/frontend/.astro/settings.json
+++ b/frontend/.astro/settings.json
@@ -1,6 +1,6 @@
{
"_variables": {
- "lastUpdateCheck": 1759589860759
+ "lastUpdateCheck": 1761559074026
},
"eslint.validate": [
"javascript",
diff --git a/frontend/.astro/types.d.ts b/frontend/.astro/types.d.ts
index f964fe0..03d7cc4 100644
--- a/frontend/.astro/types.d.ts
+++ b/frontend/.astro/types.d.ts
@@ -1 +1,2 @@
///
+///
\ No newline at end of file
diff --git a/frontend/.dockerignore b/frontend/.dockerignore
new file mode 100644
index 0000000..2d52b1b
--- /dev/null
+++ b/frontend/.dockerignore
@@ -0,0 +1,42 @@
+# Node.js
+node_modules/
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# Build outputs
+dist/
+build/
+.next/
+.nuxt/
+
+# IDE files
+.vscode/
+.idea/
+*.swp
+*.swo
+
+# OS files
+.DS_Store
+Thumbs.db
+
+# Git
+.git/
+.gitignore
+
+# Documentation
+README.md
+*.md
+
+# Environment files
+.env
+.env.local
+.env.*.local
+
+# Logs
+*.log
+logs/
+
+# Temporary files
+tmp/
+temp/
diff --git a/frontend/Dockerfile.dev b/frontend/Dockerfile.dev
new file mode 100644
index 0000000..c26f034
--- /dev/null
+++ b/frontend/Dockerfile.dev
@@ -0,0 +1,21 @@
+FROM node:20-alpine
+
+# Install Python and build tools for native dependencies
+RUN apk add --no-cache python3 make g++
+
+WORKDIR /app
+
+# Copy package files
+COPY package*.json ./
+
+# Install dependencies
+RUN npm install
+
+# Copy source code
+COPY . .
+
+# Expose port
+EXPOSE 4321
+
+# Start development server
+CMD ["npx", "astro", "dev", "--host", "0.0.0.0"]
diff --git a/frontend/README.md b/frontend/README.md
index 87b813a..54b1860 100644
--- a/frontend/README.md
+++ b/frontend/README.md
@@ -1,33 +1,38 @@
-# Astro Starter Kit: Minimal
+# Guild Genesis Frontend
-```sh
-npm create astro@latest -- --template minimal
-```
+Astro + React frontend with Web3 integration for The Guild Genesis project.
-> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
+## Prerequisites
-## 🚀 Project Structure
+- [Node.js](https://nodejs.org/) (v18 or higher)
+- [Astro CLI](https://docs.astro.build/en/getting-started/)
-Inside of your Astro project, you'll see the following folders and files:
+Install Astro CLI globally:
+```bash
+npm install -g @astrojs/cli
+```
+
+## 🚀 Project Structure
```text
-/
+frontend/
├── public/
+│ ├── favicon.svg
+│ └── logo_animated.svg
├── src/
-│ └── pages/
-│ └── index.astro
+│ ├── components/ # React components
+│ ├── hooks/ # Custom React hooks
+│ ├── layouts/ # Astro layouts
+│ ├── lib/ # Utility functions
+│ ├── pages/ # Astro pages
+│ └── styles/ # Global styles
+├── astro.config.mjs
└── package.json
```
-Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
-
-There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
-
-Any static assets, like images, can be placed in the `public/` directory.
-
## 🧞 Commands
-All commands are run from the root of the project, from a terminal:
+All commands are run from the `frontend/` directory:
| Command | Action |
| :------------------------ | :----------------------------------------------- |
@@ -36,8 +41,47 @@ All commands are run from the root of the project, from a terminal:
| `npm run build` | Build your production site to `./dist/` |
| `npm run preview` | Preview your build locally, before deploying |
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
-| `npm run astro -- --help` | Get help using the Astro CLI |
-## 👀 Want to learn more?
+## Environment Variables
+
+Make sure to set up your `.env` file in the project root with:
+
+```bash
+PUBLIC_WALLET_CONNECT_PROJECT_ID=your_wallet_connect_project_id
+PUBLIC_API_URL=http://localhost:3001
+PUBLIC_BADGE_REGISTRY_ADDRESS=0x...
+PUBLIC_EAS_CONTRACT_ADDRESS=0x...
+PUBLIC_ACTIVITY_TOKEN_ADDRESS=0x...
+PUBLIC_SCHEMA_ID=0x...
+```
+
+## Tech Stack
+
+- **Astro** - Fast static site generator with React islands
+- **React** - For interactive Web3 components
+- **Tailwind CSS** - Utility-first CSS framework
+- **wagmi** - React hooks for Ethereum
+- **viem** - TypeScript interface for Ethereum
+- **RainbowKit** - Wallet connection UI
+- **TanStack Query** - Data fetching and caching
+- **TanStack Router** - Type-safe routing
+
+## Development
+
+1. Install dependencies:
+ ```bash
+ npm install
+ ```
+
+2. Start the development server:
+ ```bash
+ npm run dev
+ ```
+
+3. Open [http://localhost:4321](http://localhost:4321) in your browser
+
+## Learn More
-Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
+- [Astro Documentation](https://docs.astro.build)
+- [React Documentation](https://react.dev)
+- [Tailwind CSS Documentation](https://tailwindcss.com/docs)
diff --git a/frontend/astro.config.mjs b/frontend/astro.config.mjs
index 8ab94a5..8d154be 100644
--- a/frontend/astro.config.mjs
+++ b/frontend/astro.config.mjs
@@ -10,6 +10,10 @@ export default defineConfig({
output: "server",
adapter: node({ mode: "standalone" }),
integrations: [react()],
+ server: {
+ host: "0.0.0.0",
+ port: 4321,
+ },
vite: {
// @ts-expect-error https://github.com/withastro/astro/issues/14030
diff --git a/pr_description.md b/pr_description.md
deleted file mode 100644
index e762f2c..0000000
--- a/pr_description.md
+++ /dev/null
@@ -1,42 +0,0 @@
-## Files Changed
-- .github/workflows/ci.yml
-- .github/workflows/test.yml
-- backend/.env.example
-- backend/.sqlx/query-177358fec702a5f78c1ff0dbd5eed42fa868487c84ebef42dfcf695e9ce42725.json
-- backend/.sqlx/query-5c8b9a2a1431a71613c6fd9d06e7f1dc430db4e2256fad1d38a33e31ef536810.json
-- backend/.sqlx/query-7acd8c9bc567ef80f66a38130bb708068882a4559856e38e6231405e9acc5a74.json
-- backend/.sqlx/query-b521c6c7f362753693d7059c6815de444a5c6aadc1a9950d9d71f49f52dee768.json
-- backend/.sqlx/query-fd6f338fcae9c81fbf1d7590574fa950a74fa68daabb48c80a0a7754e4066987.json
-- backend/Cargo.lock
-- backend/Cargo.toml
-- backend/migrations/002_add_github_login.sql
-- backend/src/application/commands/create_profile.rs
-- backend/src/application/commands/get_all_profiles.rs
-- backend/src/application/commands/get_profile.rs
-- backend/src/application/commands/update_profile.rs
-- backend/src/application/dtos/profile_dtos.rs
-- backend/src/domain/entities/profile.rs
-- backend/src/domain/repositories/profile_repository.rs
-- backend/src/infrastructure/repositories/postgres_profile_repository.rs
-- backend/src/lib.rs
-- backend/src/presentation/api.rs
-- backend/src/presentation/handlers.rs
-- backend/src/presentation/middlewares.rs
-- backend/tests/integration_github_handle.rs
-- backend/tests/profile_tests.rs
-- backend/README.md
-
-## Summary
-- add end-to-end GitHub handle support across application, domain, and persistence layers
-- expose REST endpoints for creating and updating profiles with validated, unique GitHub handles
-- provide migration, dto, and test coverage for the new field
-- align profile routes and HTTP status expectations with the audit guidance (no trailing slash, explicit 200 OK responses)
-- document GitHub handle behavior and API usage in the backend README
-
-## Notes
-- integration tests run under `TEST_MODE=1`, using the test-only auth layer to bypass signature verification while still exercising the API
-- profile integration tests now assert the refined status codes and updated `/profiles` paths
-
-## Reviewer Instructions
-- cargo test
-- cargo test --test integration_github_handle -- --test-threads=1