The gallformers.org website - a comprehensive database and reference guide for galls.
# Install Elixir dependencies
mix setup
# Start the dev server
mix phx.serverVisit localhost:4000 in your browser.
- Elixir 1.19+ and OTP 28+
- Node.js 20+ (for asset compilation)
- SQLite (bundled via ecto_sqlite3)
- libvips (for image processing - resizing uploaded images)
- ChromeDriver (for E2E tests only)
The easiest way on macOS:
brew install elixirOr use asdf for version management:
asdf plugin add elixir
asdf plugin add erlang
asdf install erlang 28.0
asdf install elixir 1.19.0-otp-28# macOS
brew install libvips
# Ubuntu/Debian
sudo apt-get install libvips libvips-dev# macOS
brew install chromedriver
xattr -d com.apple.quarantine $(which chromedriver) # Allow through Gatekeeper
# Ubuntu/Debian
sudo apt-get install chromium-chromedriverVerify with make e2e-setup.
The database file is not committed. To get started:
# Download from S3 (recommended - daily snapshot from production)
make download-db
# Or copy from V1 if you have it locally
cp v1/prisma/gallformers.sqlite priv/gallformers.sqlitemix phx.server # Start dev server
make test # Rebuild test DB + run tests (excludes E2E)
mix test # Run tests without rebuilding DB
mix format # Format code
mix credo --strict # Code quality
mix precommit # Run all checks (do this before committing)
make ci # Full CI check (same as GitHub Actions)Tests use a separate database (priv/gallformers_test.sqlite) built from:
priv/repo/structure.sql- Schema only (no production data)priv/repo/test_seeds.sql- Minimal seed data for tests
make test rebuilds this automatically. Use make test-db to rebuild manually.
Browser-based E2E tests use Wallaby with Chrome. These tests are excluded from regular test runs to keep the dev loop fast.
Requires ChromeDriver - see Prerequisites.
make e2e # Run all E2E tests
make e2e-changed # Run only tests affected by changed files (smart)
make e2e-public # Public pages only
make e2e-search # Search functionality only
make e2e-browse # Species/hosts/galls browsing only
make e2e-admin # Admin pages only
make e2e-auth # Authentication flows onlymake e2e-headed # Run with visible browser
E2E_HEADED=1 make e2e-public # Specific area with visible browserE2E tests are organized by functional area in test/e2e/:
| Directory | Coverage |
|---|---|
public/ |
Home, about, glossary, resources, explore |
search/ |
Global search, ID tool |
browse/ |
Species, hosts, galls detail pages |
admin/ |
Admin dashboard, CRUD operations |
auth/ |
Login, logout, protected routes |
See test/support/e2e_case.ex for documentation. All E2E tests must be tagged:
defmodule GallformersWeb.E2E.MyTest do
use GallformersWeb.E2ECase
@moduletag :e2e
@moduletag :e2e_public # Area tag
test "page loads", %{session: session} do
session
|> visit("/")
|> assert_has(css("body.phx-connected"))
end
endgallformers/
├── lib/ # Elixir application code
├── assets/ # Frontend (JS, CSS, Tailwind)
├── priv/ # Static files, migrations, database
├── test/ # Tests
├── config/ # Phoenix configuration
├── services/ # Auxiliary services (tileserver, usda_plants)
└── v1/ # Legacy Next.js app (see v1/README.md)
The original Next.js implementation is in v1/. It runs on Digital Ocean and is in maintenance mode (bug fixes only). See v1/README.md for V1-specific documentation.
Production runs on Fly.io:
fly deploy # Deploy to production
fly logs # View logs
fly status # Check statusSee runbooks/ for operational procedures.
The database is backed up using two complementary approaches:
- Litestream - Continuous replication to S3 (near real-time)
- Daily snapshots - GitHub Actions workflow creating point-in-time snapshots
Daily snapshots are stored in two locations:
- Public (
s3://gallformers-backups/public/) - Sanitized, PII removed - Private (
s3://gallformers-full-backups/) - Full backup with PII
See docs/backup-setup.md for complete backup documentation.
The users table contains personally identifiable information:
| Field | Description |
|---|---|
auth0_id |
Unique identifier from Auth0 |
display_name |
User's chosen display name |
nickname |
Fallback name from Auth0 |
inaturalist_url |
Link to iNaturalist profile |
social_url |
Link to social media |
personal_url |
Link to personal website |
Public database downloads are sanitized - all PII fields are set to NULL and auth0_id is replaced with a placeholder.
- Public site requires no authentication
- Admin/curation features require Auth0 login
- User management is handled via Auth0 console
- Production: gallformers.org
- Images: AWS S3
- Auth: Auth0
- Domains: Namecheap (gallformers.org, gallformers.com)
- Status page: jeffdc.github.io/gallformers-status - Uptime monitoring via Upptime
- Metrics dashboard: fly-metrics.net - CPU, memory, HTTP metrics (view-only, no alerting)
Fly.io also sends automatic email alerts on OOM (out-of-memory) events.
See CLAUDE.md for detailed development guidelines.