Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 48 additions & 47 deletions hackathon-infra/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@

This repository deploys the complete virtual event infrastructure for nf-core hackathons:

| Service | Description | URL |
|---------|-------------|-----|
| **WorkAdventure** | Virtual office for the hackathon | [app.hackathon.nf-co.re](https://app.hackathon.nf-co.re) |
| **LiveKit** | Proximity audio/video chat | [livekit.hackathon.nf-co.re](https://livekit.hackathon.nf-co.re) |
| **Coturn** | TURN server for NAT traversal | `turn.hackathon.nf-co.re` |
| **Jitsi** | Video conferencing for meeting rooms | [jitsi.hackathon.nf-co.re](https://jitsi.hackathon.nf-co.re) |
| Service | Description | URL |
| ----------------- | ------------------------------------ | ---------------------------------------------------------------- |
| **WorkAdventure** | Virtual office for the hackathon | [app.hackathon.nf-co.re](https://app.hackathon.nf-co.re) |
| **LiveKit** | Proximity audio/video chat | [livekit.hackathon.nf-co.re](https://livekit.hackathon.nf-co.re) |
| **Coturn** | TURN server for NAT traversal | `turn.hackathon.nf-co.re` |
| **Jitsi** | Video conferencing for meeting rooms | [jitsi.hackathon.nf-co.re](https://jitsi.hackathon.nf-co.re) |

Built with open source software: [WorkAdventure](https://workadventu.re/), [LiveKit](https://livekit.io/), [Coturn](https://github.com/coturn/coturn), and [Jitsi](https://jitsi.org/).

Expand All @@ -35,36 +35,36 @@ This repository is designed for AI-assisted operation. Clone the repo, open it w

Maps define the virtual office layout - rooms, interactive zones, and navigation. Edit them with the [Tiled Map Editor](https://www.mapeditor.org/).

> *"I want to add a new meeting room called 'Quiet Zone' to the map"*
> _"I want to add a new meeting room called 'Quiet Zone' to the map"_
>
> *"Sync the latest map changes to the live server"*
> _"Sync the latest map changes to the live server"_

See [`maps/README.md`](maps/README.md) for the full map editing guide.

### Deploy / Teardown / Debug

Manage the infrastructure stack with natural language:

> *"Deploy the hackathon infrastructure"*
> _"Deploy the hackathon infrastructure"_
>
> *"OAuth isn't working, can you help debug?"*
> _"OAuth isn't working, can you help debug?"_
>
> *"Tear down everything, the event is over"*
> _"Tear down everything, the event is over"_

The AI reads `CLAUDE.md` for safety rules and loads task-specific skills automatically:

| Skill | When to Use |
|-------|-------------|
| `/deploy` | Setting up for a new event, first-time deployment, recovering from destruction |
| `/teardown` | Event is over, cleanup needed, starting fresh |
| `/debug` | Services unhealthy, users report problems, OAuth/video/maps not working |
| `/maps` | Working with map files, syncing changes, setting up interactive zones |
| Skill | When to Use |
| ----------- | ------------------------------------------------------------------------------ |
| `/deploy` | Setting up for a new event, first-time deployment, recovering from destruction |
| `/teardown` | Event is over, cleanup needed, starting fresh |
| `/debug` | Services unhealthy, users report problems, OAuth/video/maps not working |
| `/maps` | Working with map files, syncing changes, setting up interactive zones |

<details>
<summary><b>For AI Agents</b></summary>

- Read `CLAUDE.md` for core safety rules and guidelines
- Skills are in `.claude/skills/<name>/SKILL.md`
- Skills are in `.agents/skills/hackathon-<name>/SKILL.md`
- Always validate each step before proceeding to the next
- Ask for confirmation before any destructive operations

Expand All @@ -78,30 +78,31 @@ Everything can also be done manually without AI assistance.

### Helper Scripts

| Script | Description |
|--------|-------------|
| `./scripts/validate-env.sh` | Check environment is configured |
| `./scripts/bootstrap.sh` | Create Terraform backend (S3 + DynamoDB) |
| `./scripts/sync-maps.sh` | Sync maps to server |
| `./scripts/status.sh` | Check health of all services |
| `./scripts/ssh.sh <service>` | SSH to instance (wa\|lk\|turn\|jitsi) |
| Script | Description |
| ---------------------------- | ---------------------------------------- |
| `./scripts/validate-env.sh` | Check environment is configured |
| `./scripts/bootstrap.sh` | Create Terraform backend (S3 + DynamoDB) |
| `./scripts/sync-maps.sh` | Sync maps to server |
| `./scripts/status.sh` | Check health of all services |
| `./scripts/ssh.sh <service>` | SSH to instance (wa\|lk\|turn\|jitsi) |

### Terraform Commands

| Command | Description |
|---------|-------------|
| `terraform init` | Initialize Terraform |
| `terraform plan` | Preview changes |
| `terraform apply` | Apply changes (creates/updates infrastructure) |
| `terraform destroy` | Destroy all infrastructure |
| Command | Description |
| ------------------- | ---------------------------------------------- |
| `terraform init` | Initialize Terraform |
| `terraform plan` | Preview changes |
| `terraform apply` | Apply changes (creates/updates infrastructure) |
| `terraform destroy` | Destroy all infrastructure |

### Detailed Procedures

For step-by-step instructions, read the skill files directly:
- **Deploy:** `.claude/skills/deploy/SKILL.md`
- **Teardown:** `.claude/skills/teardown/SKILL.md`
- **Debug:** `.claude/skills/debug/SKILL.md`
- **Maps:** `.claude/skills/maps/SKILL.md`

- **Deploy:** `.agents/skills/hackathon-deploy/SKILL.md`
- **Teardown:** `.agents/skills/hackathon-teardown/SKILL.md`
- **Debug:** `.agents/skills/hackathon-debug/SKILL.md`
- **Maps:** `.agents/skills/hackathon-maps/SKILL.md`

## Architecture

Expand Down Expand Up @@ -141,12 +142,12 @@ flowchart TB

## Documentation

| Document | Description |
|----------|-------------|
| [docs/architecture.md](docs/architecture.md) | VPC layout, service roles, design rationale |
| [docs/costs.md](docs/costs.md) | Instance sizing, daily costs, tracking via AWS Cost Explorer |
| [docs/branding.md](docs/branding.md) | Customizing logos, sign-in page, social sharing |
| [maps/README.md](maps/README.md) | Map editing guide for Tiled |
| Document | Description |
| -------------------------------------------- | ------------------------------------------------------------ |
| [docs/architecture.md](docs/architecture.md) | VPC layout, service roles, design rationale |
| [docs/costs.md](docs/costs.md) | Instance sizing, daily costs, tracking via AWS Cost Explorer |
| [docs/branding.md](docs/branding.md) | Customizing logos, sign-in page, social sharing |
| [maps/README.md](maps/README.md) | Map editing guide for Tiled |

## Directory Structure

Expand All @@ -158,12 +159,12 @@ flowchart TB
β”‚ β”œβ”€β”€ architecture.md # Design rationale and VPC layout
β”‚ β”œβ”€β”€ costs.md # Cost estimates and sizing
β”‚ └── branding.md # Customization guide
β”œβ”€β”€ .claude/
β”‚ └── skills/ # Task-specific AI skills
β”‚ β”œβ”€β”€ deploy/
β”‚ β”œβ”€β”€ teardown/
β”‚ β”œβ”€β”€ debug/
β”‚ └── maps/
β”œβ”€β”€ .agents/
β”‚ └── skills/ # Task-specific AI skills (at repo root)
β”‚ β”œβ”€β”€ hackathon-deploy/
β”‚ β”œβ”€β”€ hackathon-teardown/
β”‚ β”œβ”€β”€ hackathon-debug/
β”‚ └── hackathon-maps/
β”œβ”€β”€ terraform/ # Infrastructure code
β”‚ β”œβ”€β”€ main.tf
β”‚ β”œβ”€β”€ variables.tf
Expand Down
61 changes: 38 additions & 23 deletions hackathon-infra/maps/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ The `maps/` folder in this repository is the **source of truth** for all map ass
## Workflow

- **Humans:** Edit maps using Tiled Map Editor (this guide)
- **AI Agents:** Validate maps and sync to server (see `.claude/skills/maps/SKILL.md`)
- **AI Agents:** Validate maps and sync to server (see `.agents/skills/hackathon-maps/SKILL.md`)

## Quick Start

Expand Down Expand Up @@ -67,6 +67,7 @@ maps/
Interactive features are implemented using the [WorkAdventure Scripting API](https://docs.workadventu.re/developer/map-scripting/).

The script provides:

- **Welcome message** - Displays when users enter the map
- **Help zone popup** - Links to Slack, Documentation, GitHub (triggered by `needHelp` zone)
- **Social links popup** - Links to Mastodon, Bluesky, YouTube, LinkedIn (triggered by `followUs` zone)
Expand All @@ -75,6 +76,7 @@ The script provides:
### Script Architecture

The script is built using TypeScript and Vite:

- **Source**: `src/main.ts` - TypeScript with WorkAdventure API types
- **Wrapper**: `src/index.html` - Loads WorkAdventure iframe API before script
- **Output**: `dist/` - Pre-built HTML and JS files (committed to git, served as `script/`)
Expand All @@ -100,13 +102,15 @@ git commit -m "Rebuild map scripts"
```

For development with hot reload:

```bash
npm run dev
```

### Adding Interactive Zones

To add interactive zones to the map:

1. In Tiled, create an Object Layer
2. Draw a rectangle where you want the interaction
3. Set the object's `name` property to match the zone name in your script (e.g., `needHelp`)
Expand All @@ -116,6 +120,7 @@ To add interactive zones to the map:
### How It Works

When the map loads:

1. WorkAdventure reads the `script` property from `map.json` (points to `script/index.html`)
2. WorkAdventure loads the HTML in a sandboxed iframe
3. The HTML loads `iframe_api.js` which provides the global `WA` object
Expand Down Expand Up @@ -158,6 +163,7 @@ Layers panel (top = rendered last):
4. **Paint** using the Stamp Brush tool (B) or fill with Bucket Fill (F)

**Tips:**

- Furniture that should appear above players goes in `abovePlayer/` group
- Furniture below players goes in `furniture` layer
- Add `collides: true` to tiles that block movement
Expand All @@ -167,12 +173,14 @@ Layers panel (top = rendered last):
To make tiles solid (players can't walk through):

**Method 1: Per-tile (recommended)**

1. Select a tileset in the Tilesets panel
2. Click "Edit Tileset" (wrench icon)
3. Select the tile(s) to make solid
4. In Properties panel, add: `collides` (bool) = `true`

**Method 2: Per-layer**

1. Create a new tile layer named `collisions`
2. Add property: `collides` = `true`
3. Paint blocking tiles on this layer (they'll be invisible in-game)
Expand All @@ -191,62 +199,66 @@ Add these as custom properties on tiles, objects, or layers:

### Movement & Collision

| Property | Type | Description |
|----------|------|-------------|
| `collides` | bool | Blocks player movement |
| `start` | bool | Legacy spawn point (use `startLayer` instead) |
| `startLayer` | bool | Marks layer as spawn area |
| Property | Type | Description |
| ------------ | ---- | --------------------------------------------- |
| `collides` | bool | Blocks player movement |
| `start` | bool | Legacy spawn point (use `startLayer` instead) |
| `startLayer` | bool | Marks layer as spawn area |

### Audio & Video

| Property | Type | Description |
|----------|------|-------------|
| `playAudio` | string | URL/path to background audio |
| `playAudioLoop` | bool | Loop the audio (default: true) |
| `silent` | bool | Mutes proximity video/audio in zone |
| `jitsiRoom` | string | Jitsi meeting room name |
| `jitsiTrigger` | string | `onaction` = click to join, else auto-join |
| `jitsiWidth` | int | Jitsi iframe width (%) |
| Property | Type | Description |
| --------------- | ------ | ------------------------------------------ |
| `playAudio` | string | URL/path to background audio |
| `playAudioLoop` | bool | Loop the audio (default: true) |
| `silent` | bool | Mutes proximity video/audio in zone |
| `jitsiRoom` | string | Jitsi meeting room name |
| `jitsiTrigger` | string | `onaction` = click to join, else auto-join |
| `jitsiWidth` | int | Jitsi iframe width (%) |

### Web Integration

| Property | Type | Description |
|----------|------|-------------|
| `openWebsite` | string | URL to open in iframe |
| `openWebsiteTrigger` | string | `onaction` = click to open |
| `openWebsiteAllowApi` | bool | Allow WorkAdventure scripting API |
| `openTab` | string | URL to open in new browser tab |
| Property | Type | Description |
| --------------------- | ------ | --------------------------------- |
| `openWebsite` | string | URL to open in iframe |
| `openWebsiteTrigger` | string | `onaction` = click to open |
| `openWebsiteAllowApi` | bool | Allow WorkAdventure scripting API |
| `openTab` | string | URL to open in new browser tab |

### Navigation

| Property | Type | Description |
|----------|------|-------------|
| `exitUrl` | string | Teleport to another map (full URL) |
| Property | Type | Description |
| -------------- | ------ | ---------------------------------------------- |
| `exitUrl` | string | Teleport to another map (full URL) |
| `exitSceneUrl` | string | Teleport to map on same server (relative path) |

### Examples

**Meeting room zone:**

```
Object properties:
jitsiRoom: "standup-room"
jitsiTrigger: "onaction"
```

**Website kiosk:**

```
Object properties:
openWebsite: "https://nf-co.re"
openWebsiteTrigger: "onaction"
```

**Quiet zone (no proximity chat):**

```
Layer or object property:
silent: true
```

**Background music area:**

```
Object properties:
playAudio: "assets/bensound-thelounge.mp3"
Expand Down Expand Up @@ -306,6 +318,7 @@ Maps are validated before syncing. To validate without syncing:
```

Checks performed:

- JSON syntax is valid
- All tileset images exist
- Start/spawn layer is present
Expand All @@ -332,6 +345,7 @@ curl -I https://app.hackathon.nf-co.re/maps/default/map.json
### Tilesets not loading in Tiled

If Tiled shows red X for tilesets:

1. Ensure you opened `map.json` from the `maps/default/` directory
2. Check that `assets/` folder contains all PNG files
3. Verify tileset paths in map.json match actual filenames
Expand All @@ -358,6 +372,7 @@ The hackathon map includes LimeZu modern interior tilesets. For additional asset
- [Kenney Assets](https://kenney.nl/assets) - Free game assets

**Requirements for new tilesets:**

- PNG format
- 32x32 pixel tiles
- Place in `maps/default/assets/`
Expand Down
5 changes: 5 additions & 0 deletions hackathon-infra/maps/default/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
node_modules/

# NOTE: dist/ is intentionally tracked (not ignored).
# Pre-built scripts are committed so the EC2 instance can serve them
# directly from the git clone without requiring a build step on deploy.
# Rebuild with `npm run build` only when modifying src/main.ts.
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,13 @@ echo "Starting LiveKit installation..."

# Update system
dnf update -y
dnf install -y docker jq
dnf install -y docker docker-compose-plugin jq

# Start Docker
systemctl start docker
systemctl enable docker

# Install docker-compose
curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose
# docker compose v2 is included as a docker plugin via dnf

# Get metadata
TOKEN=$(curl -s -X PUT "http://169.254.169.254/latest/api/token" -H "X-aws-ec2-metadata-token-ttl-seconds: 21600")
Expand Down Expand Up @@ -76,7 +74,7 @@ volumes:
EOF

# Start services
docker-compose up -d
docker compose up -d

echo "LiveKit installation complete!"
echo "LiveKit domain: $LIVEKIT_DOMAIN"
Loading
Loading