Application Types
Zhiva supports two main types of applications, giving you the flexibility to choose the right approach for your project's needs.
1. Serverless (Static-only)
This is the simplest way to create a Zhiva application and is perfect for pure frontend projects.
- How it works: You provide a directory with built static files (e.g.,
dist/orbuild/). Zhiva's built-in web server hosts these files directly. - Use cases:
- Single Page Applications (SPAs) built with frameworks like React, Vue, Svelte, or Angular.
- Static websites or documentation sites.
- Configuration: To enable this mode, add the
"static"property to yourzhiva.json.
Example
A zhiva.json for a static Vite application built into the dist directory:
{
"name": "My Static App",
"icon": "./public/icon.png",
"static": {
"dirs": {
"/": "./public",
"-/": "./dist"
}
}
}
2. URL-based
This mode allows you to wrap an existing web application or website within a Zhiva window.
- How it works: You provide a URL in the
zhiva.jsonfile. Zhiva will create a window that loads the content directly from that URL. - Use cases:
- Turning a website or web app into a desktop application.
- Creating a dedicated browser for a specific service.
- Configuration: To enable this mode, add the
"url"property to yourzhiva.json. Theurlandstaticproperties are mutually exclusive.
Example
A zhiva.json for loading an external website:
{
"name": "My Wrapped App",
"icon": "./assets/icon.png",
"url": "https://example.com"
}
3. Full-stack (with Backend)
For applications that require server-side logic, Zhiva provides a powerful backend framework internally powered by the falcon-frame library, exposed through its base-lib.
-
How it works: You write your backend code in a main entry file (e.g.,
src/index.ts). You importappandoneWindowfrom@wxn0brp/zhiva-base-lib/serverto serve static files and create the application window. For API endpoints, you importapiRouterfrom@wxn0brp/zhiva-base-lib/api. This provides an Express-like API experience. -
Convenient Response Handling: For enhanced Developer Experience (DX), API handlers can simply return a JavaScript
objectorstring, and the framework will automatically convert it into a proper JSON or text HTTP response. -
Secure
apiRouter: This router is designed for secure API communication. It automatically handles authentication, ensuring that only your application's frontend can access its endpoints. -
Use cases:
- Applications that need to interact with a local database or file system.
- Tools that need to execute shell commands.
- Applications requiring a persistent and secure state on the server.
-
Configuration: This is the default mode. If the
"static"or"url"property is not present inzhiva.json, Zhiva runs the file specified in yourpackage.json's"start"script.
Example
A typical full-stack Zhiva application has separate files for the backend (src/index.ts) and frontend (src/browser.ts).
Backend (src/index.ts)
// Import the necessary components from Zhiva's base library
import { apiRouter } from "@wxn0brp/zhiva-base-lib/api";
import { app, oneWindow } from "@wxn0brp/zhiva-base-lib/server";
// Serve static assets from the public and dist directories
app.static("public");
app.static("dist");
// Define a secure API endpoint to get a list of installed apps
apiRouter.get("/installed", async (req) => {
// ... logic to get installed apps ...
const installedApps = ["wxn0brP/example-app"];
// Simply return an object, and it will be sent as JSON
return { apps: installedApps, message: "Apps fetched successfully" };
});
apiRouter.get("/hello", (req) => {
// Return a string, and it will be sent as plain text
return "Hello from Zhiva backend!";
});
apiRouter.get("/error", (req, res) => {
// Like express, you can send a response with res.status()
res.status(500).send("Internal Server Error");
})
// Create the application window
oneWindow();
// The server is started automatically by Zhiva.
Frontend (src/browser.ts)
Your frontend code (which is compiled into the dist folder) can then make simple fetch calls.
import { fetchApi } from "@wxn0brp/zhiva-base-lib/front/api";
async function getApps() {
const response = await fetchApi('installed');
const data = await response.json();
console.log(data.apps); // -> ["wxn0brP/example-app"]
}
async function sayHello() {
const response = await fetchApi('hello');
const text = await response.text();
console.log(text); // -> "Hello from Zhiva backend!"
}
getApps();
sayHello();
In these examples, API handlers can return a JavaScript object or a string directly, providing a clear and concise way to define responses without explicit res.json() or res.send() calls. The req object is available for accessing query parameters, headers, etc.