{
  description = "Expo RN devshells (local emulator / remote AVD)";
  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    android-nixpkgs = {
      url = "github:tadfisher/android-nixpkgs";
      inputs.nixpkgs.follows = "nixpkgs";
    };
    fenix = {
      url = "github:nix-community/fenix";
      inputs.nixpkgs.follows = "nixpkgs";
    };
  };

  nixConfig = {
    extra-substituters = [
      "https://android-nixpkgs.cachix.org"
      "https://nix-community.cachix.org"
    ];
    extra-trusted-public-keys = [
      "android-nixpkgs.cachix.org-1:2lZoPmwoyTVGaNDHqa6A32tdn8Gc0aMWBRrfXN1H3dQ="
      "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs="
    ];
  };

  outputs = {
    self,
    nixpkgs,
    android-nixpkgs,
    fenix,
    ...
  }: let
    systems = ["x86_64-linux" "aarch64-darwin" "x86_64-darwin"];

    overlays = [
      android-nixpkgs.overlays.default
    ];

    forAllSystems = f:
      nixpkgs.lib.genAttrs systems (
        system:
          f {
            pkgs = import nixpkgs {
              inherit system overlays;
              config.allowUnfree = true; # emulator is unfree
            };
          }
      );
  in {
    devShells = forAllSystems (
      {pkgs}: let
        fen = fenix.packages.${pkgs.system};
        rustToolchain = fen.combine [
          (fen.stable.withComponents [
            "cargo"
            "clippy"
            "rust-src"
            "rustc"
            "rustfmt"
          ])

          fen.targets.aarch64-linux-android.stable.rust-std
          fen.targets.armv7-linux-androideabi.stable.rust-std
          fen.targets.x86_64-linux-android.stable.rust-std
          fen.targets.i686-linux-android.stable.rust-std
        ];

        defaultPkgs = with pkgs; [
          # System
          bash
          git
          pkg-config
          jq
          starship
          # JS
          nodejs_22
          turbo
          nodePackages.pnpm
          yarn
          watchman
          # Rust
          rustToolchain
          cargo-ndk
          # Android build helpers
          jdk17
          gradle_8
          scrcpy
          # Misc
          cmake
          ninja
          just
          alejandra
          clang-tools
        ];

        ndkId = "27-1-12297006"; # nix flake show github:tadfisher/android-nixpkgs | grep ndk
        ndkAttr = "ndk-${ndkId}";
        ndkVer = builtins.replaceStrings ["-"] ["."] ndkId;

        defaultAndroidPkgs = sdk: let
          ndkPkg = builtins.getAttr ndkAttr sdk;
        in
          with sdk; [
            cmdline-tools-latest
            platform-tools
            platforms-android-36
            platforms-android-35
            build-tools-35-0-0
            build-tools-36-0-0
            cmake-3-22-1
            ndkPkg
          ];

        makeAndroidSdk = mode: let
          androidSdk = pkgs.androidSdk (
            sdk:
              if mode == "full"
              then
                (with sdk;
                  [
                    emulator
                    system-images-android-36-1-google-apis-x86-64 # nix flake show github:tadfisher/android-nixpkgs | grep system-images-android-36
                  ]
                  ++ (defaultAndroidPkgs sdk))
              else if mode == "remote"
              then (defaultAndroidPkgs sdk)
              else throw "makeAndroidSdk: unknown mode '${mode}'. Use \"full\" or \"remote\"."
          );
          sdkRoot = "${androidSdk}/share/android-sdk";
        in {inherit androidSdk sdkRoot;};

        fullAndroidSdk = makeAndroidSdk "full";
        remoteAndroidSdk = makeAndroidSdk "remote";

        starshipToml = pkgs.writeText "starship.toml" ''
          # project-scoped Starship config (no files under ~/.config)
          add_newline = false
          format = "$nix_shell$directory$rust$python$cmd_duration$character"

          [nix_shell]
          disabled = false
          format = "[$symbol]($style) "
          symbol = "nix-fressh "
          pure_msg = ""
          impure_msg = "(impure) "
          style = "bold cyan"

          [directory]
          format = "[$path]($style) "
          truncation_length = 0
          truncate_to_repo = false
          home_symbol = "~"

          [character]
          success_symbol = "[➜](bold green) "
          error_symbol   = "[✗](bold red) "

        '';

        starshipBootstrap = pkgs.writeText "fressh-starship-bootstrap.sh" ''
          if [[ -n ''${__FRESSH_STARSHIP_INIT-} ]]; then
            if [[ -n ''${FRESSH_OLD_PROMPT_COMMAND:-} ]]; then
              PROMPT_COMMAND=''${FRESSH_OLD_PROMPT_COMMAND}
            else
              unset PROMPT_COMMAND
            fi
            unset FRESSH_OLD_PROMPT_COMMAND
            return
          fi

          __FRESSH_STARSHIP_INIT=1

          if [[ -n ''${FRESSH_OLD_PROMPT_COMMAND:-} ]]; then
            PROMPT_COMMAND=''${FRESSH_OLD_PROMPT_COMMAND}
          else
            unset PROMPT_COMMAND
          fi

          if [[ ''${TERM_PROGRAM:-} == "vscode" ]] && command -v code >/dev/null; then
            if ! declare -F __vsc_prompt_cmd_original >/dev/null; then
              . "$(code --locate-shell-integration-path bash)"
            fi
          fi

          unset FRESSH_OLD_PROMPT_COMMAND

          if command -v starship >/dev/null; then
            eval "$(starship init bash)"

            if [[ -t 1 ]]; then
              local __fressh_first_prompt
              __fressh_first_prompt="$(STARSHIP_SHELL=bash starship prompt 2>/dev/null)"
              if [[ -n "''${__fressh_first_prompt}" ]]; then
                PS1="''${__fressh_first_prompt}"
              fi
              unset __fressh_first_prompt
            fi
          fi
        '';

        commonAndroidInit = sdkRoot: ''
          unset ANDROID_SDK_ROOT
          unset ANDROID_HOME
          export ANDROID_SDK_ROOT="${sdkRoot}"
          export ANDROID_HOME="${sdkRoot}"
          export PATH="$ANDROID_SDK_ROOT/platform-tools:$ANDROID_SDK_ROOT/emulator:$ANDROID_SDK_ROOT/cmdline-tools/latest/bin:$PATH"
          export ANDROID_NDK_ROOT="$ANDROID_SDK_ROOT/ndk/${ndkVer}"
          export ANDROID_NDK_HOME="$ANDROID_NDK_ROOT"
          export ANDROID_NDK="$ANDROID_NDK_ROOT"
          export GRADLE_OPTS="-Dorg.gradle.project.android.aapt2FromMavenOverride=${sdkRoot}/build-tools/36.0.0/aapt2 -Dorg.gradle.project.android.builder.sdkDownload=false"
          export STARSHIP_CONFIG=${starshipToml}
          export STARSHIP_CACHE="$PWD/.starship-cache"
          mkdir -p "$STARSHIP_CACHE"

          export FRESSH_DEVENV=1
          export FRESSH_STARSHIP_PREINIT=${starshipBootstrap}
          export FRESSH_OLD_PROMPT_COMMAND=''${PROMPT_COMMAND:-}
          export PROMPT_COMMAND=". \"$FRESSH_STARSHIP_PREINIT\""
        '';
      in {
        default = pkgs.mkShell {
          packages = defaultPkgs ++ [remoteAndroidSdk.androidSdk];
          shellHook =
            commonAndroidInit remoteAndroidSdk.sdkRoot;
        };

        android-emulator = pkgs.mkShell {
          packages = defaultPkgs ++ [fullAndroidSdk.androidSdk];
          shellHook =
            commonAndroidInit fullAndroidSdk.sdkRoot;
        };
      }
    );

    formatter = forAllSystems (
      {pkgs}:
        pkgs.alejandra
    );
  };
}
