Skip to content

Repository files navigation

🦀 ShellCon Smart Aquarium – Full-Stack Challenge Guide 🐚

Welcome to ShellCon, an onboarding playground where you will repair a broken Smart Aquarium while learning Rust and Shuttle Cloud.
When you launch the dashboard, read the short Scenario banner at the top. It sets the story context and your mission before you start clicking around.

This monorepo contains everything:

  • Three Rust micro-services (aqua-monitor, species-hub, aqua-brain).
  • A React + Vite dashboard (frontend/).

Your mission has three phases:

  1. Get it running – start every service & the UI locally; verify every dashboard button works.
  2. Fix performance bugs – complete four optimisation challenges inside the services.
  3. Ship to the cloud & celebrate – deploy with Shuttle.

📂 Repo layout

services/
aqua-monitor/ # environmental sensors (Challenges 1 & 4)
species-hub/ # species DB (Challenge 2)
aqua-brain/ # analytics engine (Challenge 3)
frontend/ # React dashboard

🛠️ Prerequisites

  • Rust 1.70+ & Cargo
  • Docker Desktop (Postgres for local Shuttle)
  • Shuttle CLI (latest)
  • Node ≥16 & npm (or Yarn/Bun)
  • OR VS Code with Dev Containers extension (for containerized development)

🔑 One-time Shuttle setup

Install or update the Shuttle CLI, then log in before running any shuttle run or shuttle deploy commands.

# Install / update the CLI
curl -sSfL https://www.shuttle.dev/install | bash
# Authenticate (opens a browser for sign-in or account creation)
shuttle login

🚀 Quick-start

Option A: DevContainer Environment (Recommended)

The easiest way to get started is using the pre-configured DevContainer that includes all tools and dependencies.

Setup Steps:

  1. Clone the repository:

    git clone https://github.com/shuttle-hq/shuttle-shellcon.git
    cd shuttle-shellcon
  2. Open in VS Code and start DevContainer:

    • Open VS Code in the project directory
    • When prompted, click "Reopen in Container" OR
    • Use Command Palette (Cmd/Ctrl+Shift+P) → "Dev Containers: Reopen in Container"
    • Wait for the container to start (should be fast with pre-built image)
  3. Authenticate with Shuttle:

    shuttle login
  4. Launch all backend services in separate terminals:

    # Terminal 1 - Aqua Monitor (Environmental sensors)cd shellcon-backend/services/aqua-monitor && shuttle run --port 8000
    # Terminal 2 - Species Hub (Species database) cd shellcon-backend/services/species-hub && shuttle run --port 8001
    # Terminal 3 - Aqua Brain (Analytics engine)cd shellcon-backend/services/aqua-brain && shuttle run --port 8002
  5. Start the frontend dashboard:

    # Terminal 4 - Frontend (React dashboard)cd shellcon-frontend
    npm install # first time only
    npm run dev:localhost # opens http://localhost:8080
  6. Verify everything works:

    • Open http://localhost:8080 in your browser
    • Click "Read Story Now" to begin the ShellCon scenario
    • In the System Control Panel, click each button – no red errors should appear

Option B: Local Development (Native)

1 · Launch the back-end services

First off, clone this repository on your local machine:

# Clone the repository
git clone https://github.com/shuttle-hq/shuttle-shellcon.git
# Change directory to the cloned repositorycd shuttle-shellcon

Run the following commands in three separate terminals:

# Terminal 1cd shellcon-backend/services/aqua-monitor && shuttle run --port 8000
# Terminal 2cd shellcon-backend/services/species-hub && shuttle run --port 8001
# Terminal 3cd shellcon-backend/services/aqua-brain && shuttle run --port 8002

If a port is busy: lsof -ti :<port> | xargs kill -9 then retry. Alternatively, you can use the environment files to customize the ports as shown in the "Environment files – local development" section below.

2 · Start the dashboard & confirm every API call locally

Open a new terminal and run the following commands at the root of the repository:

cd shellcon-frontend
npm install # first time only
npm run dev:localhost # opens http://localhost:8080

Then open http://localhost:8080 in your browser and click "Read Story Now" to begin the ShellCon scenario.

In the System Control Panel click each button – no red errors should appear.

UI actionRequestService
View all tanksGET /api/tanksaqua-monitor
Fetch tank readingsGET /api/tanks/{id}/readingsaqua-monitor
Check sensor statusGET /api/sensors/statusaqua-monitor
List all speciesGET /api/speciesspecies-hub
Get species detailsGET /api/species/{id}species-hub
Get feeding scheduleGET /api/species/{id}/feeding-schedulespecies-hub
View all tank analysisGET /api/analysis/tanksaqua-brain
Tank health analysisGET /api/analysis/tanks/{id}aqua-brain

Challenges only affect performance/validation – the endpoint contracts above stay identical before & after solving them.


🖥️ Frontend dashboard tour

The dashboard is split into five panels:

PanelWhat it shows
Scenario Banner (top)A short narrative that frames why you are fixing the aquarium – read it first!
System Control PanelAction buttons that call the REST endpoints listed above.
System StatusLive backend connectivity and challenge status shown as Normal or Error/Degraded.
Optimization ChallengesCards describing each challenge with Show Hint, Validate, View Solution, and Teach Me How It Works buttons.

⚙️ Environment files – local development (.env.localhost)

IMPORTANT: Use the following custom environment variables ONLY if ports 8000-8002 are already in use on your machine.

vite.config.ts looks for three variables but falls back to the default localhost ports 8000-8002:

VITE_AQUA_MONITOR_URL (default http://localhost:8000)
VITE_SPECIES_HUB_URL (default http://localhost:8001)
VITE_AQUA_BRAIN_URL (default http://localhost:8002)

You override them by specifying other ports, as shown in the example below.

Steps:

  1. touch frontend/.env.localhost and adjust if needed.
  2. Restart the dev server whenever you edit an .env* file.
FileWhen Vite picks it upTypical use
.env.localhostnpm run dev:localhostCustom local ports or running services on another host.

Example .env.localhost (custom ports):

# Local development backend servicesVITE_AQUA_MONITOR_URL=http://localhost:8020VITE_SPECIES_HUB_URL=http://localhost:8021VITE_AQUA_BRAIN_URL=http://localhost:8022VITE_API_BASE_URL=/api# leave as /api unless you modify the proxy rules

3 · Solve the optimisation challenges

#LocationTopic
1aqua-monitor/src/challenges.rs::get_tank_readingsAsync I/O
2species-hub/src/challenges.rs::get_speciesSQL optimisation
3aqua-brain/src/challenges.rs::get_analysis_resultString allocations
4aqua-monitor/src/challenges.rs::get_sensor_statusHTTP-client reuse

Workflow per challenge:

  1. Read the lecture / hint.
  2. Edit the code inside the marked // ⚠️ CHALLENGE block.
  3. For some challenges, you’ll also need to modify main.rs to adjust relevant structures and functions so they can be imported in challenges.rs.
  4. Re-run only that service (Ctrl-C, then shuttle run --port …).
  5. Click Validate in the UI.

Complete all four – the UI unlocks confetti! 🎉


☁️ Deploy & validate in the cloud

From DevContainer or Local Environment

  1. For each service (works the same in DevContainer or local):

    # Deploy aqua-monitorcd shellcon-backend/services/aqua-monitor && shuttle deploy
    # Deploy species-hub cd shellcon-backend/services/species-hub && shuttle deploy
    # Deploy aqua-braincd shellcon-backend/services/aqua-brain && shuttle deploy
    # For each deployment, choose "CREATE NEW" and use the folder name as project name
  2. Configure the frontend for cloud:

    # create the env file once (or edit it if it already exists)
    touch shellcon-frontend/.env.prod

    Open shellcon-frontend/.env.prod and paste the URLs printed by each shuttle deploy command:

    VITE_AQUA_MONITOR_URL=https://<aqua-monitor>.shuttleapp.appVITE_SPECIES_HUB_URL=https://<species-hub>.shuttleapp.appVITE_AQUA_BRAIN_URL=https://<aqua-brain>.shuttleapp.appVITE_API_BASE_URL=/api
  3. Restart the dashboard pointed at the cloud back-end:

    cd shellcon-frontend
    npm run dev:prod

    Re-validate each challenge card to confirm remote success.

❓ FAQ

Q: Shuttle complains I’m not logged in.
A: Run shuttle login once (see “One-time Shuttle setup”).

Q: A port is already in use.
A: lsof -ti :<port> | xargs kill -9 frees it before re-running.

Q: The UI shows red banners / fetch errors.
A: Check that each backend terminal shows Listening on 0.0.0.0:PORT and that your .env* URLs match.

Q: Validation keeps failing even after I fixed the code.
A: Restart the corresponding service, then click Validate again; the validator inspects live code. When you validate a function, you can see more details about the validation results in shuttle logs (shuttle logs --latest). For example, if you validate the get_tank_readings function, you can see the following validation results in the logs:

Challenge validation check results request_id=f576a0f6-059b-464c-bddb-0205748e1418 uses_async_io=true no_blocking_operations=true has_proper_tracing=true

Q: How do I reset a service database?
A: Find the Docker container for the desired PostgreSQL database (there will be two databases serving ShellCon microservices), and delete it using docker rm -f <container_name>. Then restart the service using shuttle run --port <port>.


🩹 Troubleshooting cheat-sheet

  • cargo check + cargo fmt before running.
  • Runtime errors: shuttle logs --latest.
  • Validation fails? Ensure the UI points to the right environment (localhost vs cloud).
  • Port in use: lsof -ti :<port> | xargs kill -9.

🎓 What you’ll learn

  • Async vs blocking I/O in Rust
  • Writing efficient SQL with SQLx & Postgres
  • Minimising heap allocations (Strings & Vec)
  • Resource pooling & shared state with Axum
  • Shuttle local dev → cloud deployment workflow

Good luck, Rustacean – the aquarium (and Ferris the crab 🦀) is counting on you!

Note: Any contribution to the project is welcome! Please open an issue or a pull request.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages