Live streaming web radio from Moabit, Berlin.
- Live audio streaming (HLS for iOS, FLV for desktop)
- SoundCloud archive integration
- Responsive design
- Privacy-focused analytics (Plausible)
- Frontend: Vanilla TypeScript + Vite (in
frontend/) - Archive generator: Python 3.13 + uv (in
frontend/, SoundCloud API integration) - Backend: Rust (in
backend/) - Deployment:
- Frontend: GitHub Actions + GitHub Pages
- Backend: GitHub Actions → GHCR image → AWS Lightsail (Docker Compose) behind nginx
- Node.js 18+ and npm
- Python 3.13+
- uv (Python package manager)
- Clone the repository:
git clone https://github.com/yourusername/live.moafunk.de.git
cd live.moafunk.de- Switch into the frontend directory:
cd frontend- Install Node.js dependencies:
npm install- Copy environment variables template:
cp .env.example .env- Edit
.envand configure your environment variables (see Environment Variables section below)
- Generate tracks data from SoundCloud:
cd frontend
uv run scripts/generate_relisten.py \
--client-id "$SOUNDCLOUD_CLIENT_ID" \
--client-secret "$SOUNDCLOUD_CLIENT_SECRET"- Start development server:
cd frontend
npm run dev- Open http://localhost:3000 in your browser
Important: You must generate the SoundCloud tracks data before building:
# First, generate tracks data
cd frontend
uv run scripts/generate_relisten.py \
--client-id "$SOUNDCLOUD_CLIENT_ID" \
--client-secret "$SOUNDCLOUD_CLIENT_SECRET"
# Then build
npm run buildThe output will be in frontend/dist/.
Note: In production (CI/CD), this is automated by the deployment workflow.
Create a .env file with the following variables:
| Variable | Description | Default |
|---|---|---|
VITE_STREAM_HLS_URL |
HLS stream URL (for iOS devices) | https://stream.moafunk.de/live/stream-io/index.m3u8 |
VITE_STREAM_FLV_URL |
FLV stream URL (for desktop) | https://stream.moafunk.de/live/stream-io.flv |
VITE_ANALYTICS_DOMAIN |
Plausible analytics domain | live.moafunk.de |
VITE_ANALYTICS_SCRIPT_URL |
Plausible script URL | https://plausible.moafunk.de/js/plausible.js |
These must be set as GitHub Secrets:
| Secret | Description | How to Get |
|---|---|---|
SOUNDCLOUD_CLIENT_ID |
SoundCloud OAuth Client ID | SoundCloud Apps |
SOUNDCLOUD_CLIENT_SECRET |
SoundCloud OAuth Client Secret | SoundCloud Apps |
.
├── backend/ # Rust backend (independent)
└── frontend/
├── src/
│ ├── index.html # Main live stream page
│ ├── main.ts # Entry point for TypeScript
│ ├── main.css # Global styles
│ ├── config.ts # Environment configuration
│ ├── player.ts # Audio player logic
│ ├── streamDetector.ts # Platform detection & stream status
│ └── pages/
│ ├── re-listen.html # Generated archive page (gitignored)
│ └── tech-rider.html # Equipment info page
├── public/
│ ├── sc-img.html # SoundCloud artwork editor (standalone)
│ ├── moafunk.png # Logo
│ ├── icons/ # Favicons & PWA icons
│ └── CNAME # GitHub Pages domain
├── scripts/
│ ├── generate_relisten.py # Fetch SoundCloud tracks → JSON
│ └── generate-html.js # JSON → HTML template
├── tests/ # Vitest & pytest tests
├── package.json # Node.js dependencies
└── pyproject.toml # Python deps for generator
├── .github/workflows/ # CI/CD pipelines
| Command | Description |
|---|---|
npm run dev |
Start Vite development server |
npm run build |
Build for production |
npm run preview |
Preview production build locally |
npm test |
Run Vitest tests |
npm run test:ui |
Run tests with UI |
npm run lint |
Lint code with ESLint |
npm run lint:fix |
Fix linting issues automatically |
npm run format |
Format code with Prettier |
npm run typecheck |
Type-check TypeScript files |
npm run generate:html |
Generate re-listen.html from tracks.json |
The project uses GitHub Actions for automated builds and deployment.
On push to main:
- Fetch SoundCloud tracks →
public/data/tracks.json - Generate
re-listen.htmlfrom JSON - Install Node.js dependencies
- Run linting and tests
- Build with Vite
- Deploy to GitHub Pages
See .github/workflows/deploy.yml for details.
On push to main, the backend image is built and published to GitHub Container Registry (GHCR):
The production backend is deployed by pulling that image on the Lightsail instance via Docker Compose:
- backend/scripts/deploy_lightsail.sh
- Backend details and configuration: backend/README.md
cd frontend
npm test # Run all tests
npm run test:ui # Interactive test UIcd frontend
uv run pytest # Run Python tests[Add your license here]
- Instagram: @moafunk_radio
- Telegram: Join