{"id":50396385,"url":"https://github.com/allansomensi/setlyst-api","last_synced_at":"2026-05-30T21:01:45.025Z","repository":{"id":351100324,"uuid":"1207197056","full_name":"allansomensi/setlyst-api","owner":"allansomensi","description":"A modern, stage-ready setlist management API.","archived":false,"fork":false,"pushed_at":"2026-05-18T19:17:44.000Z","size":122,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-18T21:28:23.851Z","etag":null,"topics":["api","axum","backend","band-management","chordpro","lyrics","music","musicians","rest-api","rust","setlist"],"latest_commit_sha":null,"homepage":"https://setlyst-api.onrender.com","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/allansomensi.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-10T17:20:52.000Z","updated_at":"2026-05-18T19:18:10.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/allansomensi/setlyst-api","commit_stats":null,"previous_names":["allansomensi/setlyst-api"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/allansomensi/setlyst-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allansomensi%2Fsetlyst-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allansomensi%2Fsetlyst-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allansomensi%2Fsetlyst-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allansomensi%2Fsetlyst-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/allansomensi","download_url":"https://codeload.github.com/allansomensi/setlyst-api/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allansomensi%2Fsetlyst-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33709269,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-30T02:00:06.278Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["api","axum","backend","band-management","chordpro","lyrics","music","musicians","rest-api","rust","setlist"],"created_at":"2026-05-30T21:01:39.286Z","updated_at":"2026-05-30T21:01:40.016Z","avatar_url":"https://github.com/allansomensi.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003ch1\u003e🎸 Setlyst API\u003c/h1\u003e\n\n\u003cp\u003eA REST API for managing setlists, songs, and artists — built for live musicians.\u003c/p\u003e\n\n[![Rust](https://img.shields.io/badge/rust-2024-orange?style=flat-square\u0026logo=rust)](https://www.rust-lang.org/)\n[![Axum](https://img.shields.io/badge/axum-0.8-blue?style=flat-square)](https://github.com/tokio-rs/axum)\n[![PostgreSQL](https://img.shields.io/badge/postgresql-18-336791?style=flat-square\u0026logo=postgresql)](https://www.postgresql.org/)\n[![License: MIT](https://img.shields.io/badge/license-MIT-green?style=flat-square)](./LICENSE)\n[![Version](https://img.shields.io/badge/version-0.8.0-purple?style=flat-square)](./Cargo.toml)\n\n\u003c/div\u003e\n\n---\n\n## Overview\n\n**Setlyst API** is the backend powering [Setlyst](https://github.com/allansomensi/setlyst-web) — a musician assistant designed for live performances. It handles everything from song and artist management to full setlist organization, with support for PDF export, ChordPro format, data backup/restore, and per-user preferences.\n\nBuilt with Rust for reliability and performance, using Axum, SQLx, and PostgreSQL.\n\n---\n\n## Features\n\n- **User management** — Registration, authentication (JWT), role-based access control (`user`, `moderator`, `admin`), and per-user preferences (theme, language, live mode font size)\n- **Artists \u0026 Songs** — Full CRUD with pagination, user-scoped data isolation, uniqueness enforcement, and metadata fields (tonality, BPM, genre, duration, lyrics)\n- **Setlists** — Create and manage ordered song lists, reorder tracks, and compute total duration automatically\n- **PDF Export** — Generate printable setlist PDFs with optional title, duration, key, and BPM display; supports `en`, `pt-BR`, and `es` locales\n- **ChordPro Export** — Export all songs as a single `.cho` file compatible with ChordPro readers\n- **Backup \u0026 Restore** — Export/import a full portable JSON snapshot of all user data; atomic import with smart merge rules\n- **Rate Limiting** — IP-based rate limiting on auth routes and globally across all endpoints\n- **OpenAPI / Swagger UI** — Interactive API documentation available at `/swagger-ui`\n- **Structured Logging** — Console and optional rolling file logs with configurable levels via `RUST_LOG_CONSOLE` / `RUST_LOG_FILE`\n- **Graceful Shutdown** — Handles `SIGTERM` and `Ctrl+C` cleanly\n\n---\n\n## Tech Stack\n\n| Layer | Technology |\n|---|---|\n| Language | Rust |\n| Web Framework | [Axum](https://github.com/tokio-rs/axum) |\n| Async Runtime | [Tokio](https://tokio.rs/) |\n| Database | PostgreSQL 18 |\n| ORM / Query Builder | [SQLx](https://github.com/launchbadge/sqlx) |\n| Authentication | JWT ([jsonwebtoken](https://github.com/Keats/jsonwebtoken)) |\n| Password Hashing | Argon2 |\n| Validation | [validator](https://github.com/Keats/validator) |\n| API Docs | [utoipa](https://github.com/juhaku/utoipa) + Swagger UI |\n| PDF Generation | [genpdf](https://github.com/elegaanz/genpdf) |\n| Rate Limiting | [tower_governor](https://github.com/benwis/tower-governor) |\n| Containerization | Docker Compose |\n\n---\n\n## Getting Started\n\n### Prerequisites\n\n- [Rust](https://rustup.rs/) (stable toolchain)\n- [Docker](https://www.docker.com/) \u0026 Docker Compose\n- [`just`](https://github.com/casey/just) (task runner)\n- [`cargo-watch`](https://github.com/watchexec/cargo-watch) (optional, for hot reload)\n\n### Setup\n\n**1. Clone the repository**\n\n```bash\ngit clone https://github.com/allansomensi/setlyst-api.git\ncd setlyst-api\n```\n\n**2. Configure environment**\n\n```bash\ncp .env.example .env\n```\n\nEdit `.env` and set a secure `JWT_SECRET` (minimum 32 characters) and your database credentials.\n\n**3. Start the database**\n\n```bash\njust services-up\n```\n\n**4. Run database migrations**\n\n```bash\njust migrate-run\n```\n\n**5. Start the server**\n\n```bash\njust serve\n```\n\nThe API will be available at `http://127.0.0.1:8000`.  \nSwagger UI: `http://127.0.0.1:8000/swagger-ui`\n\n---\n\n## Environment Variables\n\n| Variable | Description | Default |\n|---|---|---|\n| `JWT_SECRET` | Secret key for JWT signing (min. 32 chars) | — |\n| `JWT_EXPIRATION_TIME` | Token expiration in seconds | `86400` |\n| `DATABASE_URL` | Full PostgreSQL connection URL | — |\n| `POSTGRES_HOST` | Database host | `localhost` |\n| `POSTGRES_PORT` | Database port | `5432` |\n| `POSTGRES_USER` | Database user | `postgres` |\n| `POSTGRES_PASSWORD` | Database password | `postgres` |\n| `POSTGRES_DB` | Database name | `local_db` |\n| `HOST` | Server bind address | `127.0.0.1:8000` |\n| `CORS_ALLOWED_ORIGINS` | Comma-separated allowed origins | `http://localhost:3000` |\n| `RUST_LOG_CONSOLE` | Console log level | `info` |\n| `RUST_LOG_FILE` | File log level | `trace` |\n| `LOG_TO_FILE` | Enable rolling file logs | `false` |\n\n---\n\n## API Reference\n\nFull interactive documentation is available via Swagger UI at `/swagger-ui` when the server is running.\n\n### Endpoint Groups\n\n| Tag | Base Path | Description |\n|---|---|---|\n| Auth | `/api/v1/auth` | Login, register, token verification |\n| Users | `/api/v1/users` | User management, profiles, preferences |\n| Artists | `/api/v1/artists` | Artist CRUD |\n| Songs | `/api/v1/songs` | Song CRUD, ChordPro export |\n| Setlists | `/api/v1/setlists` | Setlist management, song ordering, PDF export |\n| Metrics | `/api/v1/metrics` | User and admin dashboard metrics |\n| Backup | `/api/v1/backup` | Data export and import |\n| Status | `/api/v1/status` | Database info |\n| Health | `/api/v1/health` | API health |\n| Migrations | `/api/v1/migrations` | Admin-only migration runner |\n\n### Authentication\n\nAll protected endpoints require a `Bearer` token in the `Authorization` header:\n\n```\nAuthorization: Bearer \u003cyour_jwt_token\u003e\n```\n\n### Creating a Superuser\n\n```bash\njust create-superuser\n# or with a specific username:\njust create-superuser -- --username admin\n```\n\n## Backup Format\n\nThe backup system uses a versioned, self-contained JSON structure:\n\n```json\n{\n  \"version\": 1,\n  \"exported_at\": \"2026-01-01T00:00:00\",\n  \"artists\": [...],\n  \"songs\": [...],\n  \"setlists\": [\n    {\n      \"title\": \"Black Night\",\n      \"songs\": [{ \"song_id\": \"...\", \"position\": 1 }]\n    }\n  ]\n}\n```\n\n**Import merge rules:**\n- Existing artists and songs (matched by name/title) are reused — not duplicated\n- Setlists are always created fresh\n- The entire import is atomic — any failure rolls back completely\n\n---\n\n## PDF Export\n\nGenerate a printable setlist via:\n\n```\nGET /api/v1/setlists/{id}/export/pdf?show_title=true\u0026show_key=true\u0026show_bpm=true\u0026show_total_duration=true\u0026lang=en\n```\n\nSupported locales: `en`, `pt-BR`, `es`.\n\n---\n\n## Rate Limiting\n\n| Scope | Limit |\n|---|---|\n| Global (all endpoints) | 60 req/burst, 1 req/200ms per IP |\n| Auth (login, register) | 5 req/burst, 1 req/2s per IP |\n\n## Contributing\n\nContributions are welcome! Please open an issue first to discuss what you'd like to change.\n\n1. Fork the repository\n2. Create a feature branch (`git checkout -b feat/my-feature`)\n3. Commit your changes\n4. Push to your branch and open a Pull Request\n\nPre-commit and pre-push hooks run `cargo test`, `cargo clippy`, and `cargo fmt` automatically via [cargo-husky](https://github.com/rhysd/cargo-husky).\n\n---\n\n## License\n\nThis project is licensed under the [MIT License](./LICENSE).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fallansomensi%2Fsetlyst-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fallansomensi%2Fsetlyst-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fallansomensi%2Fsetlyst-api/lists"}