diff --git a/README.md b/README.md index 77f2370..2dcb657 100644 --- a/README.md +++ b/README.md @@ -8,6 +8,31 @@ Download the latest `.dmg` from [Releases](https://github.com/dakl/papershelf/re > Requires macOS (Apple Silicon). The app is signed and notarized. +### Run with Nix flake + +If you have [Nix](https://nixos.org/) with flakes enabled, you can run PaperShelf directly from the repository without installing system dependencies manually: + +```bash +# Start the development environment +nix run github:dakl/papershelf#default + +# Or drop into a dev shell with all dependencies available +nix develop github:dakl/papershelf +npm install +npm run dev +``` + +Run from a local clone: + +```bash +git clone https://github.com/dakl/papershelf.git +cd papershelf +nix run .#default # start the app +nix develop # enter the dev shell +``` + +> Tested on Linux. macOS (Darwin) support is included but untested. + ## Features - **arXiv search** -- find papers and save them to your library with one click diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..bf24a07 --- /dev/null +++ b/flake.lock @@ -0,0 +1,61 @@ +{ + "nodes": { + "flake-utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1731533236, + "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1771848320, + "narHash": "sha256-0MAd+0mun3K/Ns8JATeHT1sX28faLII5hVLq0L3BdZU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "2fc6539b481e1d2569f25f8799236694180c0993", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": "nixpkgs" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..5691040 --- /dev/null +++ b/flake.nix @@ -0,0 +1,187 @@ +{ + description = "PaperShelf - A native-feeling desktop app for organizing research papers"; + + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + flake-utils.url = "github:numtide/flake-utils"; + }; + + outputs = { self, nixpkgs, flake-utils }: + flake-utils.lib.eachDefaultSystem (system: + let + pkgs = import nixpkgs { + inherit system; + config.allowUnfree = true; + }; + + isLinux = pkgs.stdenv.isLinux; + isDarwin = pkgs.stdenv.isDarwin; + + # Linux-specific runtime libraries for Electron + linuxRuntimeLibs = with pkgs; [ + glib + gtk3 + nss + nspr + atk + at-spi2-atk + libdrm + expat + libxkbcommon + libx11 + libxcomposite + libxdamage + libxext + libxfixes + libxrandr + libxcb + mesa + libgbm + libGL + alsa-lib + cups + dbus + pango + cairo + udev + libnotify + ]; + + # Common dependencies for both platforms + commonDeps = with pkgs; [ + nodejs_20 + python3 + gnumake + pkg-config + sqlite + ]; + + # Platform-specific build dependencies + linuxBuildDeps = with pkgs; [ + gcc + electron + poppler-utils + ] ++ linuxRuntimeLibs; + + darwinBuildDeps = with pkgs; [ + darwin.cctools + poppler + ]; + + buildDeps = commonDeps + ++ (if isLinux then linuxBuildDeps else []) + ++ (if isDarwin then darwinBuildDeps else []); + + libPath = if isLinux then pkgs.lib.makeLibraryPath linuxRuntimeLibs else ""; + + # Wrapper script to run the app + papershelf = pkgs.writeShellScriptBin "papershelf" '' + set -e + + PROJECT_DIR="''${PAPERSHELF_PROJECT_DIR:-$(pwd)}" + + if [ ! -f "$PROJECT_DIR/package.json" ]; then + echo "Error: package.json not found in $PROJECT_DIR" + echo "Run this command from the PaperShelf project directory," + echo "or set PAPERSHELF_PROJECT_DIR to the project path." + exit 1 + fi + + cd "$PROJECT_DIR" + + # Set up environment + export PATH="${pkgs.nodejs_20}/bin:$PROJECT_DIR/node_modules/.bin:$PATH" + export npm_config_build_from_source=true + export SQLITE3_INCLUDE_DIR="${pkgs.sqlite.dev}/include" + export SQLITE3_LIB_DIR="${pkgs.sqlite.out}/lib" + ${if isLinux then '' + export LD_LIBRARY_PATH="${libPath}:$LD_LIBRARY_PATH" + export ELECTRON_OZONE_PLATFORM_HINT=auto + '' else ""} + + # Install dependencies if needed + if [ ! -d "node_modules" ]; then + echo "Installing dependencies..." + ${pkgs.nodejs_20}/bin/npm install + fi + + # Run the app + echo "Starting PaperShelf..." + exec ${pkgs.nodejs_20}/bin/npm run dev + ''; + + # Build script (builds but doesn't run) + papershelf-build = pkgs.writeShellScriptBin "papershelf-build" '' + set -e + PROJECT_DIR="''${PAPERSHELF_PROJECT_DIR:-$(pwd)}" + + if [ ! -f "$PROJECT_DIR/package.json" ]; then + echo "Error: package.json not found in $PROJECT_DIR" + exit 1 + fi + + cd "$PROJECT_DIR" + + export PATH="${pkgs.nodejs_20}/bin:$PROJECT_DIR/node_modules/.bin:$PATH" + export npm_config_build_from_source=true + export SQLITE3_INCLUDE_DIR="${pkgs.sqlite.dev}/include" + export SQLITE3_LIB_DIR="${pkgs.sqlite.out}/lib" + ${if isLinux then '' + export LD_LIBRARY_PATH="${libPath}:$LD_LIBRARY_PATH" + '' else ""} + + if [ ! -d "node_modules" ]; then + echo "Installing dependencies..." + ${pkgs.nodejs_20}/bin/npm install + fi + + echo "Building PaperShelf..." + ${pkgs.nodejs_20}/bin/npm run build + echo "Build complete! Output in dist/" + ''; + in + { + packages = { + default = papershelf; + build = papershelf-build; + }; + + apps = { + default = { + type = "app"; + program = "${papershelf}/bin/papershelf"; + }; + build = { + type = "app"; + program = "${papershelf-build}/bin/papershelf-build"; + }; + }; + + devShells.default = pkgs.mkShell { + buildInputs = buildDeps; + + shellHook = '' + # Set up npm to use local node_modules/.bin + export PATH="$PWD/node_modules/.bin:$PATH" + + # Fix for native module compilation + export npm_config_build_from_source=true + ${if isLinux then '' + # Required for Electron on Linux + export ELECTRON_OZONE_PLATFORM_HINT=auto + + # Help native modules find system libraries + export LD_LIBRARY_PATH="${libPath}:$LD_LIBRARY_PATH" + '' else ""} + echo "PaperShelf development environment loaded" + echo "Run 'npm install' to install dependencies" + echo "Run 'npm run dev' to start development server" + ''; + + # Environment variables for better-sqlite3 + SQLITE3_INCLUDE_DIR = "${pkgs.sqlite.dev}/include"; + SQLITE3_LIB_DIR = "${pkgs.sqlite.out}/lib"; + }; + } + ); +}