No description
  • Rust 61.3%
  • Svelte 30.3%
  • TypeScript 3.8%
  • Nix 2.5%
  • CSS 0.9%
  • Other 1.2%
Find a file
Christian Lengert ddf14cc972
Some checks failed
Backend / test (push) Failing after 20s
Backend / build (push) Has been skipped
Backend / deploy (push) Has been skipped
feat: move tasks between lists + kanban column management
Backend:
- UpdateTaskRequest gains group_id (double-option: absent=no change,
  null=personal, number=group); resets column_id on list move

Frontend:
- Task modal: List dropdown to move task to any group or Personal;
  clears assignee on change; removed task disappears from current view
- Sidebar: Manage columns button appears in kanban view (fixes personal
  board having no way to add/edit columns)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-26 17:32:32 +02:00
.forgejo/workflows workflow 2026-03-25 20:07:26 +01:00
be feat: move tasks between lists + kanban column management 2026-06-26 17:32:32 +02:00
frontend feat: move tasks between lists + kanban column management 2026-06-26 17:32:32 +02:00
nix add environmentFile option for secrets (JWT_SECRET etc.) 2026-05-30 23:08:04 +02:00
.gitignore add .gitignore and remove node_modules from tracking 2026-05-30 21:30:17 +02:00
docker-compose.yml docker 2026-03-27 18:45:27 +01:00
flake.lock tasks 2026-05-30 21:29:10 +02:00
flake.nix update npmDepsHash for svelte-dnd-action dependency 2026-05-31 09:23:57 +02:00
README.md document first-time user setup in README 2026-05-30 21:56:11 +02:00

Tasks

Home organisation task app for two people. SvelteKit PWA frontend embedded into a Rust/Rocket backend, deployed as a single binary.

Stack

  • Backend — Rust, Rocket, SeaORM, SQLite, JWT auth
  • Frontend — SvelteKit, TypeScript, PWA (offline-capable, installable)
  • Build — Nix flake; frontend is compiled and embedded into the binary via rust-embed

Development

Enter the dev shell (provides Rust stable + cargo-watch + Node 22):

nix develop

Run backend and frontend dev servers in separate terminals:

# terminal 1 — backend (auto-reloads on save)
cd be
DATABASE_URL=sqlite://./dev.db cargo watch -x run

# terminal 2 — frontend dev server (proxies /api and /auth to :8000)
cd frontend
npm run dev

The frontend dev server runs on http://localhost:5173. Configure a proxy in vite.config.js if you need the frontend to talk to the backend during development.

Nix build

# build the backend binary (with frontend embedded)
nix build

# build only the frontend
nix build .#frontend

# build only the backend
nix build .#backend

The resulting binary at ./result/bin/tasks-be serves everything: the REST API and the compiled frontend as static files.

Which URL serves the frontend?

The frontend and API share the same port. The backend serves the compiled SvelteKit app at / — just open http://host:port/ in a browser. Routes are prioritised as follows:

Path Served by
/api/* REST API
/auth/*, /healthz, /readyz Backend routes
/swagger-ui/, /rapidoc/ API docs
/metrics Prometheus
/* (everything else) SvelteKit frontend (falls back to index.html for client-side routing)

First-time setup

The database starts empty. Registration is open and requires no authentication, so create both accounts before exposing the service publicly.

curl -s -X POST https://tasks.recfx.net/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"username":"alice","password":"..."}'

curl -s -X POST https://tasks.recfx.net/auth/register \
  -H 'Content-Type: application/json' \
  -d '{"username":"bob","password":"..."}'

Both calls return { "token": "...", "userId": ... }. Use the token as Authorization: Bearer <token> for all subsequent requests. After both accounts are created you can log in from the app at /login.

Importing into a NixOS system flake

The flake exposes three ways to import the module, all of which auto-wire the package.

Call mkTasksModule with your chosen defaults. These become lib.mkDefault values so you can still override them in configuration.nix.

# flake.nix on your NixOS host
{
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";

    tasks = {
      url = "github:youruser/tasks";      # or "path:/path/to/tasks" for local
      inputs.nixpkgs.follows = "nixpkgs"; # share nixpkgs to avoid double builds
    };
  };

  outputs = { nixpkgs, tasks, ... }: {
    nixosConfigurations.myhostname = nixpkgs.lib.nixosSystem {
      system = "x86_64-linux";
      modules = [
        (tasks.lib.mkTasksModule { port = 8001; address = "127.0.0.1"; })
        ./configuration.nix
      ];
    };
  };
}

Then in configuration.nix:

services.tasks.enable = true;
# port and address are already defaulted by mkTasksModule above;
# override here if needed.

Option B — pre-wired module (no port/host defaults)

nixosModules.tasks sets only the package. Configure port and address in your own module.

modules = [
  tasks.nixosModules.tasks
  ./configuration.nix
];
# configuration.nix
services.tasks = {
  enable  = true;
  port    = 8001;
  address = "127.0.0.1";
};

Option C — bare module + manual package

nixosModules.default is the raw module with no package pre-set, for when you supply your own build.

modules = [ tasks.nixosModules.default ];

# configuration.nix
services.tasks = {
  enable  = true;
  package = tasks.packages.x86_64-linux.default;
  port    = 8001;
};

Service options

Option Type Default Description
enable bool false Enable the service
port port 8000 TCP port to listen on
address string "0.0.0.0" Bind address

The SQLite database is stored at /var/lib/tasks/app.db (managed by systemd StateDirectory).

Traefik example

The service binds directly on port; put Traefik (or nginx) in front for TLS:

services.tasks = {
  enable  = true;
  port    = 8001;
  address = "127.0.0.1";   # only listen on loopback; Traefik handles public traffic
};

# Traefik label equivalent in NixOS (dynamic config file or docker labels):
# rule: Host(`tasks.example.com`)
# service port: 8001

Updating the npm deps hash

After changing frontend/package.json and running npm install:

nix shell nixpkgs#prefetch-npm-deps --command \
  prefetch-npm-deps frontend/package-lock.json

Paste the printed hash into flake.nix under npmDepsHash.