diff --git a/.github/workflows/run-tests.yml b/.github/workflows/run-tests.yml
index 33806a1..0b2ce1c 100644
--- a/.github/workflows/run-tests.yml
+++ b/.github/workflows/run-tests.yml
@@ -8,9 +8,9 @@ jobs:
     strategy:
       fail-fast: true
       matrix:
-        os: [ubuntu-latest]
-        php: [8.4, 8.3, 8.2, 8.1]
-        stability: [prefer-stable]
+        os: [ubuntu-latest, windows-latest]
+        php: [8.3, 8.2, 8.1]
+        stability: [prefer-lowest, prefer-stable]
 
     name: P${{ matrix.php }} - ${{ matrix.stability }} - ${{ matrix.os }}
 
diff --git a/bin/mjml.mjs b/bin/mjml.mjs
new file mode 100644
index 0000000..927e54a
--- /dev/null
+++ b/bin/mjml.mjs
@@ -0,0 +1,28 @@
+import mjml2html from 'mjml'
+
+const args = JSON.parse(atob(process.argv.slice(2)));
+
+const mjml = args[0];
+const options = args[1];
+
+let result = ''
+
+try {
+    result = await mjml2html(mjml, options);
+} catch (exception) {
+    const errorString = JSON.stringify({mjmlError: exception.toString()});
+
+    process.stdout.write(utoa(errorString));
+    process.exit(0);
+}
+
+process.stdout.write(utoa(JSON.stringify(result)));
+
+/**
+ * Unicode to ASCII (encode data to Base64)
+ * @param {string} data
+ * @return {string}
+ */
+function utoa(data) {
+    return btoa(unescape(encodeURIComponent(data)));
+}
diff --git a/composer.json b/composer.json
index 4075718..ac51320 100644
--- a/composer.json
+++ b/composer.json
@@ -16,7 +16,6 @@
     ],
     "require": {
         "php": "^8.1",
-        "spatie/temporary-directory": "^2.2",
         "symfony/process": "^6.3.2|^7.0"
     },
     "require-dev": {
diff --git a/src/Mjml.php b/src/Mjml.php
index f0d9a73..51967a2 100755
--- a/src/Mjml.php
+++ b/src/Mjml.php
@@ -5,7 +5,7 @@
 use Spatie\Mjml\Exceptions\CouldNotConvertMjml;
 use Spatie\Mjml\Exceptions\SidecarPackageUnavailable;
 use Spatie\MjmlSidecar\MjmlFunction;
-use Spatie\TemporaryDirectory\TemporaryDirectory;
+use Symfony\Component\Process\Exception\ProcessFailedException;
 use Symfony\Component\Process\ExecutableFinder;
 use Symfony\Component\Process\Process;
 
@@ -23,6 +23,8 @@ class Mjml
 
     protected string $filePath = '.';
 
+    protected string $workingDirectory;
+
     protected bool $sidecar = false;
 
     public static function new(): self
@@ -33,6 +35,8 @@ public static function new(): self
     protected function __construct()
     {
         $this->validationLevel = ValidationLevel::Soft;
+
+        $this->workingDirectory = realpath(dirname(__DIR__).'/bin');
     }
 
     public function keepComments(bool $keepComments = true): self
@@ -89,6 +93,13 @@ public function filePath(string $filePath): self
         return $this;
     }
 
+    public function workingDirectory(string $workingDirectory): self
+    {
+        $this->workingDirectory = $workingDirectory;
+
+        return $this;
+    }
+
     public function canConvert(string $mjml): bool
     {
         try {
@@ -123,11 +134,19 @@ public function convert(string $mjml, array $options = []): MjmlResult
             $this->configOptions($options),
         ];
 
-        if ($this->sidecar) {
-            return $this->getSideCarResult($arguments);
+        $resultString = $this->sidecar
+            ? $this->getSideCarResult($arguments)
+            : $this->getLocalResult($arguments);
+
+        $resultString = $this->checkForDeprecationWarning($resultString);
+
+        $resultProperties = json_decode($resultString, true);
+
+        if (array_key_exists('mjmlError', $resultProperties)) {
+            throw CouldNotConvertMjml::make($resultProperties['mjmlError']);
         }
 
-        return $this->getLocalResult($arguments);
+        return new MjmlResult($resultProperties);
     }
 
     protected function checkForDeprecationWarning(string $result): string
@@ -141,36 +160,24 @@ protected function checkForDeprecationWarning(string $result): string
         return $result;
     }
 
-    protected function getCommand(string $templatePath, string $outputPath, $arguments): array
+    protected function getCommand(array $arguments): array
     {
-        $home = getenv('HOME');
-
         $extraDirectories = [
             '/usr/local/bin',
             '/opt/homebrew/bin',
-            $home.'/n/bin', // support https://github.com/tj/n
-            __DIR__.'/../node_modules/mjml/bin',
         ];
 
-        $mjmlPathFromEnv = getenv('MJML_PATH');
+        $nodePathFromEnv = getenv('MJML_NODE_PATH');
 
-        if ($mjmlPathFromEnv) {
-            array_unshift($extraDirectories, $mjmlPathFromEnv);
+        if ($nodePathFromEnv) {
+            array_unshift($extraDirectories, $nodePathFromEnv);
         }
 
-        $command = [
-            (new ExecutableFinder)->find('mjml', 'mjml', $extraDirectories),
-            $templatePath,
-            '-o',
-            $outputPath,
+        return [
+            (new ExecutableFinder)->find('node', 'node', $extraDirectories),
+            'mjml.mjs',
+            base64_encode(json_encode(array_values($arguments))),
         ];
-
-        foreach ($arguments as $configKey => $configValue) {
-            $command[] = "-c.{$configKey}";
-            $command[] = $configValue;
-        }
-
-        return $command;
     }
 
     protected function configOptions(array $overrides): array
@@ -187,75 +194,33 @@ protected function configOptions(array $overrides): array
         return array_merge($defaults, $overrides);
     }
 
-    protected function getSideCarResult(array $arguments): MjmlResult
+    protected function getSideCarResult(array $arguments): string
     {
         if (! class_exists(MjmlFunction::class)) {
             throw SidecarPackageUnavailable::make();
         }
 
-        $result = MjmlFunction::execute([
+        return MjmlFunction::execute([
             'mjml' => $arguments[0],
             'options' => $arguments[1],
         ])->body();
-
-        $result = $this->checkForDeprecationWarning($result);
-
-        $resultProperties = json_decode($result, true);
-
-        if (array_key_exists('mjmlError', $resultProperties)) {
-            throw CouldNotConvertMjml::make($resultProperties['mjmlError']);
-        }
-
-        return new MjmlResult($resultProperties);
     }
 
-    protected function getLocalResult(array $arguments): MjmlResult
+    protected function getLocalResult(array $arguments): string
     {
-        $tempDir = TemporaryDirectory::make();
-        $filename = date('U');
-
-        $templatePath = $tempDir->path("{$filename}.mjml");
-        file_put_contents($templatePath, $arguments[0]);
-
-        $outputPath = $tempDir->path("{$filename}.html");
+        $process = new Process(
+            $this->getCommand($arguments),
+            $this->workingDirectory,
+        );
 
-        $command = $this->getCommand($templatePath, $outputPath, $arguments[1]);
-
-        $process = new Process($command);
         $process->run();
 
         if (! $process->isSuccessful()) {
-            $output = explode("\n", $process->getErrorOutput());
-            $errors = array_filter($output, fn (string $output) => str_contains($output, 'Error'));
-
-            $tempDir->delete();
-
-            throw CouldNotConvertMjml::make($errors[0] ?? $process->getErrorOutput());
-        }
-
-        $errors = [];
-
-        if ($process->getErrorOutput()) {
-            $errors = array_filter(explode("\n", $process->getErrorOutput()));
-            $errors = array_map(function (string $error) {
-                preg_match('/Line (\d+) of (.+) \((.+)\) — (.+)/u', $error, $matches);
-                [, $line, , $tagName, $message] = $matches;
-
-                return [
-                    'line' => $line,
-                    'message' => $message,
-                    'tagName' => $tagName,
-                ];
-            }, $errors);
+            throw new ProcessFailedException($process);
         }
 
-        $html = file_get_contents($outputPath);
-
-        $tempDir->delete();
+        $items = explode("\n", $process->getOutput());
 
-        return new MjmlResult([
-            'html' => $html,
-            'errors' => $errors,
-        ]);
+        return base64_decode(end($items));
     }
 }
diff --git a/tests/.pest/snapshots/MjmlTest/it_can_beautify_the_rendered_html.snap b/tests/.pest/snapshots/MjmlTest/it_can_beautify_the_rendered_html.snap
index 73422c0..a144254 100644
--- a/tests/.pest/snapshots/MjmlTest/it_can_beautify_the_rendered_html.snap
+++ b/tests/.pest/snapshots/MjmlTest/it_can_beautify_the_rendered_html.snap
@@ -40,7 +40,6 @@
       display: block;
       margin: 13px 0;
     }
-
   </style>
   <!--[if mso]>
     <noscript>
@@ -61,7 +60,6 @@
   <link href="https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700" rel="stylesheet" type="text/css">
   <style type="text/css">
     @import url(https://fonts.googleapis.com/css?family=Ubuntu:300,400,500,700);
-
   </style>
   <!--<![endif]-->
   <style type="text/css">
@@ -71,14 +69,12 @@
         max-width: 100%;
       }
     }
-
   </style>
   <style media="screen and (min-width:480px)">
     .moz-text-html .mj-column-per-100 {
       width: 100% !important;
       max-width: 100%;
     }
-
   </style>
 </head>
 
@@ -112,4 +108,4 @@
   </div>
 </body>
 
-</html>
+</html>
\ No newline at end of file