diff --git a/build.rs b/build.rs
index 9bf5c85..93d0a8c 100644
--- a/build.rs
+++ b/build.rs
@@ -1,152 +1,158 @@
 use chrono::Datelike;
 use flate2::read::GzDecoder;
 use reqwest;
 use tar::Archive;
 
 use std::{
     env,
     fs::{self, File},
     io::{self, copy},
     path::{Path, PathBuf},
     process::Command,
 };
 
 const NODE_VERSION: &str = "20.10.0";
 const PNPM_VERSION: &str = "8.11.0";
 
 fn extract_tar_gz(tar: &PathBuf, download_dir: &PathBuf) -> io::Result<()> {
     let file = File::open(tar)?;
     let decoder = GzDecoder::new(file);
     let mut archive = Archive::new(decoder);
 
     archive.unpack(download_dir)?;
     Ok(fs::remove_file(tar)?)
 }
 
 fn download_file(url: String, destination: &PathBuf, download_dir: &PathBuf) {
     if !download_dir.exists() {
         fs::create_dir_all(download_dir).unwrap();
     }
 
     let mut response = reqwest::blocking::get(url).expect("Failed to send request");
     let mut file = File::create(destination).expect("Failed to create file");
 
     copy(&mut response, &mut file).expect("Failed to copy content");
 }
 
 fn download_node() -> PathBuf {
     #[cfg(target_os = "linux")]
     let target_os = "linux";
     #[cfg(all(target_os = "macos"))]
     let target_os = "darwin";
 
     #[cfg(all(target_arch = "arm"))]
     let target_arch = "armv7l";
     #[cfg(all(target_arch = "x86_64"))]
     let target_arch = "x64";
     #[cfg(all(target_arch = "aarch64"))]
     let target_arch = "arm64";
 
     let download_url = format!("https://nodejs.org/dist/v{NODE_VERSION}/node-v{NODE_VERSION}-{target_os}-{target_arch}.tar.gz");
 
     /* paths */
     let download_dir = Path::new("target").join("downloads");
     let node_extract_dir = download_dir.join(format!("node-v{NODE_VERSION}-{target_os}-{target_arch}"));
 
     if node_extract_dir.is_dir() {
         return node_extract_dir;
     }
 
     /* download node */
     let node_archive = download_dir.join(format!("node-v{}-{}.tar.gz", NODE_VERSION, target_os));
     download_file(download_url, &node_archive, &download_dir);
 
     /* extract node */
     if let Err(err) = extract_tar_gz(&node_archive, &download_dir) {
         panic!("Failed to extract Node.js: {:?}", err)
     }
 
     /* set env */
     println!(
         "cargo:rerun-if-env-changed=NODE_HOME\n\
          cargo:rerun-if-env-changed=PATH\n\
          cargo:rerun-if-env-changed=PNPM_HOME"
     );
 
     let path = match env::var("PATH") {
         Ok(path) => path,
         Err(err) => panic!("{err}"),
     };
 
+    let mut paths = env::var_os("PATH").unwrap_or_default();
+
+    paths.push(":");
+    paths.push(std::ffi::OsString::from(&node_extract_dir));
+    env::set_var("PATH", paths);
+
     println!("cargo:rustc-env=NODE_HOME={}", node_extract_dir.to_str().unwrap());
-    println!("cargo:rustc-env=PATH={}/bin:{path}", node_extract_dir.to_str().unwrap());
+    println!("cargo:rustc-env=PATH={}/bin:{path}/bin/node", node_extract_dir.to_str().unwrap());
 
     return node_extract_dir;
 }
 
 fn download_then_build(node_extract_dir: PathBuf) {
     /* install pnpm */
     Command::new("./npm")
         .args(["install", "-g", &format!("pnpm@{}", PNPM_VERSION)])
         .current_dir(&node_extract_dir.join("bin"))
         .env("NODE_PATH", &node_extract_dir.join("lib").join("node_modules"))
         .status()
         .expect("Failed to install PNPM");
 
     /* install deps */
     Command::new("pnpm")
         .args(["install"])
         .current_dir("src/webui")
         .env("NODE_PATH", &node_extract_dir.join("lib").join("node_modules"))
         .status()
         .expect("Failed to install dependecies");
 
     /* build frontend */
-    Command::new("pnpm")
-        .args(["run", "build"])
+    Command::new(format!("./{}/npx", &node_extract_dir.join("bin").as_path().display()))
+        .args(["astro", "build"])
         .current_dir("src/webui")
         .env("NODE_PATH", &node_extract_dir.join("lib").join("node_modules"))
         .status()
-        .expect("Failed to install dependecies");
+        .expect("Failed to build frontend");
 }
 
 fn main() {
     #[cfg(target_os = "windows")]
     compile_error!("This project is not supported on Windows.");
 
     #[cfg(target_arch = "x86")]
     compile_error!("This project is not supported on 32 bit.");
 
     /* version attributes */
     let date = chrono::Utc::now();
     let profile = env::var("PROFILE").unwrap();
     let output = Command::new("git").args(&["rev-parse", "--short=10", "HEAD"]).output().unwrap();
     let output_full = Command::new("git").args(&["rev-parse", "HEAD"]).output().unwrap();
 
     println!("cargo:rustc-env=TARGET={}", env::var("TARGET").unwrap());
     println!("cargo:rustc-env=GIT_HASH={}", String::from_utf8(output.stdout).unwrap());
     println!("cargo:rustc-env=GIT_HASH_FULL={}", String::from_utf8(output_full.stdout).unwrap());
     println!("cargo:rustc-env=BUILD_DATE={}-{}-{}", date.year(), date.month(), date.day());
 
     /* profile matching */
     match profile.as_str() {
         "debug" => println!("cargo:rustc-env=PROFILE=debug"),
         "release" => {
             println!("cargo:rustc-env=PROFILE=release");
 
             /* pre-build */
             let path = download_node();
             download_then_build(path);
 
             /* cc linking */
             cxx_build::bridge("src/lib.rs")
                 .file("lib/bridge.cc")
                 .file("lib/process.cc")
                 .file("lib/fork.cc")
                 .include("lib/include")
                 .flag_if_supported("-std=c++17")
                 .compile("bridge");
         }
         _ => println!("cargo:rustc-env=PROFILE=none"),
     }
 }