diff --git a/README.md b/README.md index 3fb6cc2..81493e2 100644 --- a/README.md +++ b/README.md @@ -1,57 +1,32 @@
- Hack Club flag - -

- stickers.hackclub.com -

- - Hack Club logo -

- The Rails 8 + Inertia.js + Svelte 5 codebase powering - stickers.hackclub.com -

+ Hack Club flag +

stickers.hackclub.com

+ Hack Club logo +

The Rails 8 + Inertia.js + Svelte 5 codebase powering stickers.hackclub.com

-
+--- -

Hack Club Stickers

+# Hack Club Stickers -

- Every Hack Clubber gets free, high-quality stickers. Completing - programs and attending - hackathons - can earn more event-specific merch! -

+Every Hack Clubber gets free, high-quality stickers. Completing [programs](https://ysws.hackclub.com/) and attending [hackathons](https://hackathons.hackclub.com/) can earn more event-specific merch! -

Features

- +## Features -

Contributing

- +- Trade stickers with other Hack Clubbers +- Browse an archive of all printed Hack Club stickers +- Submit new sticker designs +- Vote on your favourite designs +- Hack to earn monthly sticker shipments +- Use as an API for sticker designs -

Development Setup

+## Contributing -
+- Help archive stickers at [forms.hackclub.com/archive](https://forms.hackclub.com/archive)
+
+## Development Setup
+
+```bash
 git clone https://github.com/hackclub/stickers
 cd stickers
 
@@ -68,13 +43,13 @@ bin/rails db:create db:migrate
 
 # Start the server (runs on port 3100)
 bin/dev
-
+``` -

Environment Variables

+## Environment Variables -

Required environment variables in .env:

+Required environment variables in `.env`: -
+```bash
 # Airtable
 AIRTABLE_PAT=your_personal_access_token
 AIRTABLE_BASE_ID=your_base_id
@@ -86,48 +61,78 @@ AIRTABLE_SHOP_TABLE_ID=your_shop_table_id
 OIDC_CLIENT_ID=your_client_id
 OIDC_CLIENT_SECRET=your_client_secret
 OIDC_REDIRECT_URI=http://localhost:3100/auth/oidc/callback
-
+``` -

API Usage

+## API Usage -

You can use stickers.hackclub.com/api/ to get a list of all Hack Club stickers in JSON. Please don't hammer it too hard — let us know what you're up to and we can help you coexist within the rate limit.

+You can use `stickers.hackclub.com/api/` to get a list of all Hack Club stickers in JSON. Please don't hammer it too hard — let us know what you're up to and we can help you coexist within the rate limit. -

Stickers

- +### Stickers -

Designs

- +- `GET /api/stickers` - List all visible stickers +- `GET /api/stickers/:id` - Get sticker details -Our Airtable has no passwords or secrets — if you want a read-only personal access token scoped to the base we can provide it! -In general we're happy to help you over DM, but please have a glance over the code first! +### Designs -

Deployment

+- `GET /api/designs` - List current user's designs (requires auth) +- `GET /api/designs/all` - List all designs (requires auth) +- `POST /api/designs` - Submit a new design (requires auth) +- `POST /api/designs/:id/vote` - Toggle vote on a design (requires auth) -

The app is deployed using Docker. To deploy:

+Our Airtable has no passwords or secrets — if you want a read-only personal access token scoped to the base we can provide it! In general we're happy to help you over DM, but please have a glance over the code first! -
-# Build assets for production
-bin/rails assets:precompile
-
+## Deployment -

deploy with Docker directly:

+### Option 1: Coolify (Recommended) -
+**Using Docker Compose (app + database):**
+
+1. Create new resource → **Docker Compose**
+2. Point to your Git repo
+3. Set compose file to `docker-compose.coolify.yml`
+4. Set environment variables including `POSTGRES_PASSWORD`
+5. Set your domain for the `stickers` service
+6. Deploy
+
+**Using Dockerfile (app only):**
+
+1. Create new resource → **Application** → **Dockerfile**
+2. Point to your Git repo
+3. Set environment variables (see `.env.example`)
+4. Set `DATABASE_URL` to your PostgreSQL instance
+5. Set your domain
+6. Deploy
+
+### Option 2: Docker (Manual)
+
+```bash
+# Build and run
 docker build -t stickers .
-docker run -p 3000:3000 --env-file .env stickers
-
+docker run -d -p 80:80 \ + -e SECRET_KEY_BASE="$(rails secret)" \ + -e DATABASE_URL="postgresql://user:pass@host/db" \ + -e AIRTABLE_PAT="..." \ + stickers +``` -

- Made with <3 by - nora, - euan, and - end. -

+### Production Environment Variables + +| Variable | Description | +|----------|-------------| +| `SECRET_KEY_BASE` | Rails secret (generate with `rails secret`) | +| `DATABASE_URL` | PostgreSQL connection string | +| `AIRTABLE_PAT` | Airtable Personal Access Token | +| `AIRTABLE_BASE_ID` | Airtable base ID | +| `AIRTABLE_STICKER_DB_TABLE_ID` | Stickers table ID | +| `AIRTABLE_SHOP_TABLE_ID` | Shop table ID | +| `AIRTABLE_DESIGN_TABLE_ID` | Designs table ID | +| `OIDC_ISSUER` | `https://auth.hackclub.com` | +| `OIDC_CLIENT_ID` | OIDC client ID | +| `OIDC_CLIENT_SECRET` | OIDC client secret | +| `OIDC_REDIRECT_URI` | `https://your-domain.com/auth/oidc/callback` | + +See `.env.example` for a complete list. + +--- + +Made with <3 by [nora](https://github.com/24c02), [euan](https://github.com/EDripper), and [end](https://github.com/System-End). diff --git a/docker-compose.coolify.yml b/docker-compose.coolify.yml new file mode 100644 index 0000000..e545f26 --- /dev/null +++ b/docker-compose.coolify.yml @@ -0,0 +1,64 @@ + +# Required Environment Variables (set in Coolify UI): +# - SECRET_KEY_BASE +# - DATABASE_URL +# - AIRTABLE_PAT +# - AIRTABLE_BASE_ID +# - AIRTABLE_STICKER_DB_TABLE_ID +# - AIRTABLE_SHOP_TABLE_ID +# - AIRTABLE_DESIGN_TABLE_ID +# - OIDC_ISSUER +# - OIDC_CLIENT_ID +# - OIDC_CLIENT_SECRET +# - OIDC_REDIRECT_URI + +services: + stickers: + build: + context: . + dockerfile: Dockerfile + ports: + - "80:80" + environment: + - RAILS_ENV=production + - RAILS_LOG_TO_STDOUT=true + - RAILS_SERVE_STATIC_FILES=true + - SECRET_KEY_BASE=${SECRET_KEY_BASE} + - DATABASE_URL=${DATABASE_URL} + - AIRTABLE_PAT=${AIRTABLE_PAT} + - AIRTABLE_BASE_ID=${AIRTABLE_BASE_ID} + - AIRTABLE_STICKER_DB_TABLE_ID=${AIRTABLE_STICKER_DB_TABLE_ID} + - AIRTABLE_SHOP_TABLE_ID=${AIRTABLE_SHOP_TABLE_ID} + - AIRTABLE_DESIGN_TABLE_ID=${AIRTABLE_DESIGN_TABLE_ID} + - OIDC_ISSUER=${OIDC_ISSUER} + - OIDC_CLIENT_ID=${OIDC_CLIENT_ID} + - OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET} + - OIDC_REDIRECT_URI=${OIDC_REDIRECT_URI} + - AUTH_SUCCESS_REDIRECT=${AUTH_SUCCESS_REDIRECT:-/stickers} + - AUTH_LOGOUT_REDIRECT=${AUTH_LOGOUT_REDIRECT:-/} + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:80/up"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 40s + depends_on: + db: + condition: service_healthy + + db: + image: postgres:17-alpine + volumes: + - postgres_data:/var/lib/postgresql/data + environment: + - POSTGRES_USER=${POSTGRES_USER:-stickers} + - POSTGRES_PASSWORD=${POSTGRES_PASSWORD} + - POSTGRES_DB=${POSTGRES_DB:-stickers_production} + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-stickers}"] + interval: 10s + timeout: 5s + retries: 5 + +volumes: + postgres_data: