chore: scaffold monorepo for EventSnap

- Rust/Axum backend skeleton with all crates, multi-stage Dockerfile
- SvelteKit + TypeScript frontend with Tailwind CSS v4, adapter-node, Dockerfile
- docker-compose.yml: db (postgres:16) → app → frontend → caddy with healthcheck and named volumes
- Caddyfile: TLS via Let's Encrypt, cache headers, API/media routing to backend
- .env.example: all environment variables documented with defaults
- README.md: project overview, features, stack, deploy guide, roadmap
- .gitignore: excludes secrets, build artifacts, node_modules, media uploads

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
fabi
2026-03-31 20:15:44 +02:00
commit b89b1d6ffa
24 changed files with 4604 additions and 0 deletions

33
backend/Cargo.toml Normal file
View File

@@ -0,0 +1,33 @@
[package]
name = "eventsnap-backend"
version = "0.1.0"
edition = "2024"
[dependencies]
axum = { version = "0.8", features = ["multipart"] }
tokio = { version = "1", features = ["full"] }
sqlx = { version = "0.8", features = ["runtime-tokio", "postgres", "uuid", "chrono", "macros"] }
serde = { version = "1", features = ["derive"] }
serde_json = "1"
tower = "0.5"
tower-http = { version = "0.6", features = ["trace", "cors", "compression-full", "fs"] }
tower-governor = "0.4"
jsonwebtoken = "9"
bcrypt = "0.15"
uuid = { version = "1", features = ["v4", "serde"] }
chrono = { version = "0.4", features = ["serde"] }
anyhow = "1"
tracing = "0.1"
tracing-subscriber = { version = "0.3", features = ["env-filter"] }
dotenvy = "0.15"
sysinfo = "0.32"
image = "0.25"
oxipng = "9"
async-zip = { version = "0.0.17", features = ["tokio", "deflate"] }
minijinja = "2"
[profile.release]
opt-level = 3
lto = true
codegen-units = 1
strip = true

25
backend/Dockerfile Normal file
View File

@@ -0,0 +1,25 @@
# --- Build stage ---
FROM rust:1.87-alpine AS builder
RUN apk add --no-cache musl-dev pkgconfig openssl-dev
WORKDIR /app
COPY Cargo.toml Cargo.lock* ./
# Pre-fetch deps with a dummy build for layer caching
RUN mkdir src && echo "fn main(){}" > src/main.rs && \
cargo build --release && \
rm -rf src
COPY src ./src
RUN touch src/main.rs && cargo build --release
# --- Runtime stage ---
FROM alpine:3.21
RUN apk add --no-cache ca-certificates ffmpeg
WORKDIR /app
COPY --from=builder /app/target/release/eventsnap-backend ./
EXPOSE 3000
CMD ["./eventsnap-backend"]

27
backend/src/main.rs Normal file
View File

@@ -0,0 +1,27 @@
use anyhow::Result;
use tracing_subscriber::{layer::SubscriberExt, util::SubscriberInitExt};
#[tokio::main]
async fn main() -> Result<()> {
dotenvy::dotenv().ok();
tracing_subscriber::registry()
.with(tracing_subscriber::EnvFilter::try_from_default_env().unwrap_or_else(|_| {
"eventsnap_backend=debug,tower_http=debug".into()
}))
.with(tracing_subscriber::fmt::layer())
.init();
let port: u16 = std::env::var("APP_PORT")
.unwrap_or_else(|_| "3000".to_string())
.parse()?;
let router = axum::Router::new()
.route("/health", axum::routing::get(|| async { "ok" }));
let listener = tokio::net::TcpListener::bind(("0.0.0.0", port)).await?;
tracing::info!("listening on {}", listener.local_addr()?);
axum::serve(listener, router).await?;
Ok(())
}