appjet
v0.1.1
Published
Modern desktop apps with web technologies
Downloads
10
Maintainers
Readme
Appjet ✈️
⚠️ This project is in early development - Only basic template is currently available.
Fast, simple desktop apps with modern web technologies
Appjet is a lightweight alternative to Electron, built for speed and simplicity. Create desktop applications using Vue.js, HTML, CSS, and JavaScript - powered by Bun and native webviews.
📋 Prerequisites
Required
- Bun (not Node.js compatible)
- System webview libraries:
Windows
- Windows 11: ✅ Built-in (no additional setup)
- Windows 10: May require WebView2 runtime
macOS
- Built-in WebKit (no additional setup required)
Linux
Install GTK 4 and WebkitGTK 6:
# Debian/Ubuntu
sudo apt install libgtk-4-1 libwebkitgtk-6.0-4
# Arch Linux
sudo pacman -S gtk4 webkitgtk-6.0
# Fedora
sudo dnf install gtk4 webkitgtk6.0⚡ Why Appjet?
- 🚀 Lightning Fast - Built on Bun, compiles to native executables
- 🪶 Lightweight - No bundled Chromium, uses system webview
- 🎯 Simple - Minimal API, focus on your app logic
- 🔧 Modern Stack - Vue.js, Vite, TypeScript out of the box
- 📦 Single Binary - Compile to standalone executables
- 🔥 Hot Reload - Instant updates during development
- 🔗 Auto Binding - Automatic function binding between backend and frontend
🚀 Quick Start
Create a new Appjet app:
bun create appjet my-app
cd my-appSetup Frontend (Vue.js example)
cd frontend
bun create vue@latest .
bun install
# Start frontend dev server
bun devSetup Backend
cd ../backend
bun install
# Start backend (in another terminal)
bun dev⚙️ Configuration
Window & Webview Settings (appjet.config.ts)
import type { AppjetConfig } from "appjet";
export const config: AppjetConfig = {
window: {
debug: true, // Enable dev tools
height: 800, // Window height
width: 1200, // Window width
resizable: true, // Allow window resize
title: "My Appjet App", // Window title
},
frontend: {
distPath: "../frontend/dist", // Production build path
entryPointFile: "index.html", // Entry HTML file
viteServer: "http://localhost:5173", // Dev server URL
},
};Build Configuration (appjet.build.ts)
import { buildAppjetApp, type BuildConfig } from "appjet";
export const build: BuildConfig = {
appName: "my-app", // Executable name
entrypoint: "./appjet.ts", // Backend entry point
outputDir: "./dist", // Build output directory
frontendDir: "../frontend", // Frontend source directory
targets: ["bun-linux-x64"], // Target platforms
};
await buildAppjetApp(build);🔗 Backend ↔ Frontend Communication
Appjet's magic: just register a function in your backend, and it's automatically available in your frontend!
Backend (backend/api.ts)
import { registerBinding } from "appjet";
import { readdir, writeFile } from "fs/promises";
// Simple function
const greetUser = (name: string) => {
return `Hello ${name}! Welcome to Appjet ✈️`;
};
// Async function with file system access
const listFiles = async (directory: string) => {
try {
const files = await readdir(directory);
return { success: true, files };
} catch (error) {
return { success: false, error: error.message };
}
};
// Complex function with multiple operations
const saveUserData = async (userData: { name: string; email: string }) => {
await writeFile('user.json', JSON.stringify(userData, null, 2));
console.log("User data saved!");
return { saved: true, timestamp: Date.now() };
};
// Register functions (they become available in frontend automatically!)
registerBinding("greetUser", greetUser);
registerBinding("listFiles", listFiles);
registerBinding("saveUserData", saveUserData);
// Or register multiple at once
registerBinding({
getCurrentTime: () => new Date().toISOString(),
getSystemInfo: () => ({ platform: process.platform, arch: process.arch })
});Frontend (Vue.js, React, or vanilla JS)
// Cast window to access bound functions
const w = window as any;
// Call the backend functions directly
const greeting = await w.greetUser("Alice");
console.log(greeting); // "Hello Alice! Welcome to Appjet ✈️"
// File system operations from frontend
const result = await w.listFiles("/home/user/documents");
if (result.success) {
console.log("Files:", result.files);
}
// Save data
await w.saveUserData({ name: "Bob", email: "[email protected]" });
// Get system info
const info = await w.getSystemInfo();
console.log(info); // { platform: "linux", arch: "x64" }💡 Pro tip: For better TypeScript support, you can create a types file:
// types/appjet.d.ts
declare global {
interface Window {
greetUser: (name: string) => Promise<string>;
listFiles: (directory: string) => Promise<{success: boolean, files?: string[], error?: string}>;
saveUserData: (userData: {name: string, email: string}) => Promise<{saved: boolean, timestamp: number}>;
getSystemInfo: () => Promise<{platform: string, arch: string}>;
}
}Then use with full type safety:
const greeting = await window.greetUser("Alice"); // ✅ Fully typed!✨ That's it! No IPC setup, no manual bindings, no complex messaging. Just write functions in your backend and call them from your frontend like magic! 🪄
🛠️ Build for Production
For Vue.js Projects
- Update your router (
src/router/index.ts) to use memory history:
import { createRouter, createMemoryHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
const router = createRouter({
history: createMemoryHistory(), // Use memory history for embedded apps
routes: [
{
path: '/',
name: 'home',
component: HomeView,
},
{
path: '/about',
name: 'about',
component: () => import('../views/AboutView.vue'),
},
],
})
export default router- Update your
vite.config.tsfor single-file output:
export default defineConfig({
// ... other config
build: {
assetsInlineLimit: 999999999, // Inline all assets
cssCodeSplit: false, // Single CSS file
rollupOptions: {
output: {
manualChunks: undefined,
inlineDynamicImports: true,
entryFileNames: 'assets/index.js',
chunkFileNames: 'assets/index.js',
assetFileNames: 'assets/index.[ext]',
},
},
},
});Build Commands
# Build everything
cd backend
bun run build
# Or build executable directly
bun run appjet.build.ts📚 Available Targets
bun-linux-x64- Linux 64-bitbun-windows-x64- Windows 64-bitbun-darwin-x64- macOS Intelbun-darwin-arm64- macOS Apple Silicon
🤝 Contributing
Contributions welcome! This project is in early development.
📄 License
MIT © Bastien Etienne
