Add Foundry Tauri v2 desktop app with UI polish

- Scaffold Tauri v2 desktop package (foundry/packages/desktop)
- Sidecar build script compiles backend into standalone Bun binary
- Frontend build script packages Vite output for Tauri webview
- macOS glass-effect app icon following Big Sur design standards
- Collapsible sidebars with smooth width transitions
- Inset content framing with borders and nested border-radius (Outer R = Inner R + Padding)
- iMessage-style chat bubble styling with proper corner radii
- Styled composer input with matching border-radius
- Vertical separator between chat and right sidebar
- Website download button component
- Cargo workspace exclude for standalone Tauri build

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Nicholas Kissel 2026-03-11 15:11:12 -07:00
parent dbc2ff0682
commit f6656a90af
80 changed files with 6621 additions and 152 deletions

View file

@ -0,0 +1,42 @@
import { execSync } from "node:child_process";
import { cpSync, readFileSync, writeFileSync, rmSync, existsSync } from "node:fs";
import { resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const desktopRoot = resolve(__dirname, "..");
const repoRoot = resolve(desktopRoot, "../../..");
const frontendDist = resolve(desktopRoot, "../frontend/dist");
const destDir = resolve(desktopRoot, "frontend-dist");
function run(cmd: string, opts?: { cwd?: string; env?: NodeJS.ProcessEnv }) {
console.log(`> ${cmd}`);
execSync(cmd, {
stdio: "inherit",
cwd: opts?.cwd ?? repoRoot,
env: { ...process.env, ...opts?.env },
});
}
// Step 1: Build the frontend with the desktop-specific backend endpoint
console.log("\n=== Building frontend for desktop ===\n");
run("pnpm --filter @sandbox-agent/foundry-frontend build", {
env: {
VITE_HF_BACKEND_ENDPOINT: "http://127.0.0.1:7741/api/rivet",
},
});
// Step 2: Copy dist to frontend-dist/
console.log("\n=== Copying frontend build output ===\n");
if (existsSync(destDir)) {
rmSync(destDir, { recursive: true });
}
cpSync(frontendDist, destDir, { recursive: true });
// Step 3: Strip react-scan script from index.html (it loads unconditionally)
const indexPath = resolve(destDir, "index.html");
let html = readFileSync(indexPath, "utf-8");
html = html.replace(/<script\s+src="https:\/\/unpkg\.com\/react-scan\/dist\/auto\.global\.js"[^>]*><\/script>\s*/g, "");
writeFileSync(indexPath, html);
console.log("\n=== Frontend build complete ===\n");

View file

@ -0,0 +1,68 @@
import { execSync } from "node:child_process";
import { mkdirSync, existsSync } from "node:fs";
import { resolve, dirname } from "node:path";
import { fileURLToPath } from "node:url";
const __dirname = dirname(fileURLToPath(import.meta.url));
const desktopRoot = resolve(__dirname, "..");
const sidecarDir = resolve(desktopRoot, "src-tauri/sidecars");
const isDev = process.argv.includes("--dev");
// Detect current architecture
function currentTarget(): string {
const arch = process.arch === "arm64" ? "aarch64" : "x86_64";
return `${arch}-apple-darwin`;
}
// Target triples to build
const targets: Array<{ bunTarget: string; tripleTarget: string }> = isDev
? [
{
bunTarget: process.arch === "arm64" ? "bun-darwin-arm64" : "bun-darwin-x64",
tripleTarget: currentTarget(),
},
]
: [
{
bunTarget: "bun-darwin-arm64",
tripleTarget: "aarch64-apple-darwin",
},
{
bunTarget: "bun-darwin-x64",
tripleTarget: "x86_64-apple-darwin",
},
];
function run(cmd: string, opts?: { cwd?: string; env?: NodeJS.ProcessEnv }) {
console.log(`> ${cmd}`);
execSync(cmd, {
stdio: "inherit",
cwd: opts?.cwd ?? desktopRoot,
env: { ...process.env, ...opts?.env },
});
}
// Step 1: Build the backend with tsup
console.log("\n=== Building backend with tsup ===\n");
run("pnpm --filter @sandbox-agent/foundry-backend build", {
cwd: resolve(desktopRoot, "../../.."),
});
// Step 2: Compile standalone binaries with bun
mkdirSync(sidecarDir, { recursive: true });
const backendEntry = resolve(desktopRoot, "../backend/dist/index.js");
if (!existsSync(backendEntry)) {
console.error(`Backend build output not found at ${backendEntry}`);
process.exit(1);
}
for (const { bunTarget, tripleTarget } of targets) {
const outfile = resolve(sidecarDir, `foundry-backend-${tripleTarget}`);
console.log(`\n=== Compiling sidecar for ${tripleTarget} ===\n`);
run(`bun build --compile --target ${bunTarget} ${backendEntry} --outfile ${outfile}`);
}
console.log("\n=== Sidecar build complete ===\n");