Slopper
It produces slop!
Slopper picks a random piece of media from a Jellyfin database, uses AI to find a clippable moment, cuts it with FFmpeg, and stores the clip. Clips are viewable on the web frontend and can be uploaded to short-form platforms.
Prerequisites
| Tool | Version | Notes |
|---|---|---|
| .NET SDK | 11.0.100-preview.2 | Pinned in global.json |
| Node.js | 26.1.0 | |
| corepack | latest | Manages pnpm |
| pnpm | (via corepack) | Run corepack install |
| FFmpeg | any | Required at runtime |
| sqlite3 | any | Required at runtime |
| Chrome/Chromium | stable | Required for E2E tests |
Recommended: use the devcontainer — it installs everything automatically. VS Code with the Dev Containers extension will prompt you on open.
Setup (first time)
These match the postCreateCommand in .devcontainer/devcontainer.json:
# Frontend deps
corepack install && pnpm ci
# .NET packages (locked)
dotnet restore --locked-mode
# .NET local tools (e.g. EF Core CLI)
dotnet tool restore
Project Structure
src/
Api/ # ASP.NET Core REST API
Cli/ # .NET console app for local experimentation
Domain/ # Core domain models and abstractions (class library)
Frontend/ # Vue 3 + TypeScript SPA (Vite)
Infrastructure/
Ai/ # Ollama AI integration
Database/ # EF Core / SQLite data access
Ffmpeg/ # FFmpeg media processing
YouTube/ # YouTube API integration
Building Everything
# All .NET projects
dotnet build
# Frontend
pnpm -C src/Frontend build
Development
Frontend (src/Frontend/)
pnpm dev # Vite dev server with hot reload
pnpm build # Production build (vue-tsc + vite)
pnpm dev will output a "random" port once it starts.
API (src/Api/)
dotnet run --project src/Api/Api.csproj
The Api project runs on port 5055 by default.
To perform end-to-end tests with both the Frontend and the Api, build the frontend and move the output from src/Frontend/dist to src/Api/wwwroot, then run the Api project. The Api project will serve the frontend from the same path.
For example, from project root:
pnpm -C src/Frontend build --emptyOutDir --outDir ../Api/wwwroot/
dotnet run --project src/Api/Api.csproj
CLI (src/Cli/)
dotnet run --project src/Cli/Cli.csproj
The Cli is the primary experimentation tool — use it to test Domain and Infrastructure services in isolation. Edit src/Cli/Program.cs freely to test new features in new ways. Do not worry about checking in the experiments, it's fun to see the progression of the project.
The Cli is wired up like the Api but with some dependencies skipped so it's easier to run with.
Domain (src/Domain/)
Pure class library — no runnable entry point. Built implicitly when building Api or Cli.
Infrastructure / Integrations (src/Infrastructure/)
Pure class libraries consumed by Api and Cli.
Configuration
Both Api and Cli use .NET User Secrets for local configuration. The secrets shape is identical for both projects.
Create a secrets.json for the project you are running:
# API (ID: ad38b97a-09e9-4354-9c4f-710bf6b7a3ac)
dotnet user-secrets set "ConnectionStrings:slopper" "Data Source=<path>;" --project src/Api
# CLI (ID: 9df5410d-6a82-44ba-9e77-7ec4ffcf582a)
dotnet user-secrets set "ConnectionStrings:slopper" "Data Source=<path>;" --project src/Cli
Or edit the file directly. The full schema (all keys required):
{
"ConnectionStrings": {
"jellyfin": "Data Source=<path-to-jellyfin.db>; Mode=ReadOnly;",
"slopper": "Data Source=<path-to-slopper.db>;"
},
"ClipDirectory": "<absolute-path-to-media-directory>",
"Ai": {
"Endpoint": "<ollama-base-url>",
"BasicAuth": "<base64-encoded user:password>",
"DescriptionModel": "<model-name>",
"EmbeddingModel": "<model-name>"
},
"YouTube": {
"ClientId": "<google-oauth-client-id>",
"ClientSecret": "<google-oauth-client-secret>",
"User": "<youtube-channel-user>"
}
}
The secrets file lives at:
- Windows:
%APPDATA%\Microsoft\UserSecrets\<ID>\secrets.json - Linux/macOS:
~/.microsoft/usersecrets/<ID>/secrets.json
Database Migrations
dotnet ef migrations add <MigrationName> --project src/Infrastructure/Database
Migrations are automatically run on startup of both the Api and the Cli projects.