From 649bda94e9a368dfb29a654de01e0f910cb8c87f Mon Sep 17 00:00:00 2001 From: Antoine Estienne Date: Mon, 27 Oct 2025 09:30:38 +0100 Subject: [PATCH 1/2] fix readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 77b18e9..a80e762 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,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). From d265a72ac767e019c0e75ef920d5aedea4c25e0d Mon Sep 17 00:00:00 2001 From: Antoine Estienne Date: Mon, 27 Oct 2025 11:22:30 +0100 Subject: [PATCH 2/2] rewrite readmes and fix docker compose --- .github/workflows/deploy-backend.yml | 1 + Makefile | 55 ++++++++++ README.md | 93 +++++++++++++++-- backend/.dockerignore | 34 +++++++ backend/Dockerfile | 25 ++++- backend/README.md | 119 ++++++++++++++++------ backend/migrations/001_initial_schema.sql | 2 +- backend/src/main.rs | 5 +- docker-compose.db-only.yml | 16 +++ docker-compose.dev.yml | 56 ++++++++++ docker-compose.prod.yml | 84 +++++++++++++++ docker-compose.test.yml | 33 ++++++ frontend/.astro/data-store.json | 2 +- frontend/.astro/settings.json | 2 +- frontend/.astro/types.d.ts | 1 + frontend/.dockerignore | 42 ++++++++ frontend/Dockerfile.dev | 21 ++++ frontend/README.md | 84 +++++++++++---- frontend/astro.config.mjs | 4 + pr_description.md | 42 -------- 20 files changed, 613 insertions(+), 108 deletions(-) create mode 100644 Makefile create mode 100644 backend/.dockerignore create mode 100644 docker-compose.db-only.yml create mode 100644 docker-compose.dev.yml create mode 100644 docker-compose.prod.yml create mode 100644 docker-compose.test.yml create mode 100644 frontend/.dockerignore create mode 100644 frontend/Dockerfile.dev delete mode 100644 pr_description.md 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 a80e762..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 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