{
description = "Bluesky feed dashboard (Python + Preact) using uv2nix";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
pyproject-nix = {
url = "github:pyproject-nix/pyproject.nix";
inputs.nixpkgs.follows = "nixpkgs";
};
uv2nix = {
url = "github:pyproject-nix/uv2nix";
inputs.pyproject-nix.follows = "pyproject-nix";
inputs.nixpkgs.follows = "nixpkgs";
};
pyproject-build-systems = {
url = "github:pyproject-nix/build-system-pkgs";
inputs.pyproject-nix.follows = "pyproject-nix";
inputs.uv2nix.follows = "uv2nix";
inputs.nixpkgs.follows = "nixpkgs";
};
};
outputs = { self, nixpkgs, pyproject-nix, uv2nix, pyproject-build-systems }:
let
inherit (nixpkgs) lib;
forAllSystems = lib.genAttrs lib.systems.flakeExposed;
# Load workspace from uv.lock
workspace = uv2nix.lib.workspace.loadWorkspace { workspaceRoot = ./.; };
# Create overlay from workspace (uses wheels by default)
overlay = workspace.mkPyprojectOverlay {
sourcePreference = "wheel";
};
# Build Python sets for all systems
pythonSets = forAllSystems (system:
let
pkgs = nixpkgs.legacyPackages.${system};
python = pkgs.python312;
in
(pkgs.callPackage pyproject-nix.build.packages {
inherit python;
}).overrideScope
(lib.composeManyExtensions [
pyproject-build-systems.overlays.default
overlay
])
);
in
{
devShells = forAllSystems (system:
let
pkgs = nixpkgs.legacyPackages.${system};
pythonSet = pythonSets.${system};
# Non-editable virtualenv (avoids libcst/Rust dependency)
virtualenv = pythonSet.mkVirtualEnv "bluesky-dashboard-dev" workspace.deps.all;
in
{
default = pkgs.mkShell {
packages = [
virtualenv
pkgs.uv
pkgs.nodejs_24
pkgs.git
pkgs.just
pkgs.watchexec
pkgs.flyctl
];
env = {
UV_NO_SYNC = "1";
UV_PYTHON = "${virtualenv}/bin/python";
UV_PYTHON_DOWNLOADS = "never";
};
shellHook = ''
unset PYTHONPATH
export REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
export APP_DATA="$REPO_ROOT/app_data"
mkdir -p $APP_DATA
if [ ! -d ClientApp/node_modules ]; then
echo "Installing npm dependencies..."
(cd ClientApp && npm install)
fi
if [ ! -f wwwroot/js/app.js ] || [ ClientApp/src/main.tsx -nt wwwroot/js/app.js ]; then
echo "Building frontend..."
(cd ClientApp && npm run build)
fi
echo ""
echo "═══════════════════════════════════════════════════════"
echo " Bluesky Dashboard (Python + Preact) with uv2nix"
echo "═══════════════════════════════════════════════════════"
echo " Python: $(python --version)"
echo " Node: $(node --version)"
echo " uv: $(uv --version)"
echo ""
echo " Quick start: just run"
echo "═══════════════════════════════════════════════════════"
'';
};
});
packages = forAllSystems (system:
let
pkgs = nixpkgs.legacyPackages.${system};
pythonSet = pythonSets.${system};
virtualenv = pythonSet.mkVirtualEnv "bluesky-dashboard-env" workspace.deps.default;
in
{
default = pkgs.stdenv.mkDerivation {
name = "bluesky-dashboard";
src = ./.;
dontConfigure = true;
buildInputs = [ virtualenv ];
installPhase = ''
mkdir -p $out
cp -r backend run.py $out/
# Copy pre-built wwwroot (run 'npm run build' in devShell first)
if [ -d wwwroot ]; then
cp -r wwwroot $out/
fi
mkdir -p $out/bin
cat > $out/bin/bluesky-dashboard << EOF
#!/bin/sh
export PYTHONPATH="$out:$PYTHONPATH"
exec ${virtualenv}/bin/python $out/run.py "\$@"
EOF
chmod +x $out/bin/bluesky-dashboard
'';
};
});
};
}