Pattern
Full web applications.
Nift can be the frontend composition/build layer in a full application without trying to replace your backend runtime, API framework, database layer, package manager or browser framework. The boundary is simply files and HTTP.
Nift can own templates, partials, tracked pages and browser-facing paths. Everything else can stay with the tool that already does it well.
A general shape
app/
content/ # page-specific HTML/content
templates/ # shared document templates + partials
public/ # generated pages + browser assets
frontend/ # optional TS/React/Vue/Svelte/Vite source
server/ # Go / Node / Python / C++ / ...
.nift/
package.json # optional frontend tooling
Makefile # optional orchestration
The exact directories are yours. Nift only needs its configured content/output locations and tracking metadata.
Nift + vanilla JavaScript + Go
This is one of the cleanest full-stack combinations: Nift generates the pages, ordinary browser JavaScript consumes a Go API, and the Go service handles runtime state.
app/
content/
index.html
dashboard.html
templates/
template.html
partials/nav.html
public/
assets/app.js
assets/site.css
server/
main.go
api/
.nift/
<link rel="stylesheet" href="@pathto('public/assets/site.css')">
@input('templates/partials/nav.html')
<main>@content</main>
<script type="module" src="@pathto('public/assets/app.js')"></script>
const res = await fetch('/api/status');
const status = await res.json();
document.querySelector('#status').textContent = status.message;
http.Handle("/", http.FileServer(http.Dir("public")))
http.HandleFunc("/api/status", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
io.WriteString(w, `{"message":"online"}`)
})
Nothing requires a Nift-specific Go package. The generated frontend and HTTP API simply meet at the browser.
Nift + TypeScript + Vite + Go
As browser code grows, TypeScript/Vite can own bundling while Nift continues to own the HTML shell and page composition.
frontend/
src/app.ts
vite.config.ts
public/
assets/app.js
content/
templates/
server/
// vite.config.ts (conceptual)
export default defineConfig({
build: {
outDir: '../public/assets',
emptyOutDir: false
}
});
npm run build:frontend
nift build
# then run/build the Go server
Nift + React island + Go API
React can own a state-heavy part of a page while Nift emits the rest as direct HTML.
<section class="account-intro">
<h1>Account</h1>
<p>Static/helpful surrounding content stays plain HTML.</p>
</section>
<div id="account-app"></div>
<script type="module" src="@pathto('public/assets/account.js')"></script>
// React entry point produced by your normal bundler
createRoot(document.getElementById('account-app')).render(<AccountApp />);
This avoids requiring React to own every page just because one region benefits from it.
Nift + Vue or Svelte
The pattern is identical. Vite produces a browser entry point, and a Nift-generated page provides the mount point.
<div id="pricing-calculator"></div>
<script type="module" src="@pathto('public/assets/pricing-calculator.js')"></script>
Whether that bundle was produced by Vue, Svelte, React or vanilla TypeScript is deliberately outside Nift's concern.
Nift + Node + Express
Express can serve the generated public directory and expose APIs beside it.
import express from 'express';
const app = express();
app.use(express.json());
app.use(express.static('public'));
app.get('/api/health', (req, res) => {
res.json({ ok: true });
});
app.listen(3000);
{
"scripts": {
"build:site": "nift build-all",
"build:client": "vite build",
"build": "npm run build:client && npm run build:site",
"start": "node server.js"
}
}
Nift + Bun + TypeScript server
Bun can be both the package/tooling runtime and the backend runtime while Nift remains the HTML build layer.
bun run build:client
nift build
bun run server.ts
No special adaptation is necessary: use Bun normally and point it (or a reverse proxy) at public/.
Nift + Python + FastAPI
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
@app.get('/api/health')
def health():
return {'ok': True}
app.mount('/', StaticFiles(directory='public', html=True), name='public')
Flask or another Python framework can use the same arrangement. Django projects can also keep Nift-built static/frontend output separate from Django's runtime concerns if that fits the application.
Nift + Python API + React/Vue/Svelte frontend island
Nift Vite/framework FastAPI/Flask
---- -------------- -------------
page shell + interactive JS + API routes
navigation rich state auth/business logic
content pages client widgets database access
paths/assets bundling background jobs
This is often a useful separation for internal tools and dashboards: Nift handles the stable information architecture while the framework handles the stateful parts.
Nift + server-rendered backend routes
Nift does not have to generate every response your server returns. You can use it for static/documentation/marketing/help/account-shell pages while the backend renders or returns genuinely dynamic routes itself.
/ Nift-built page
/docs/* Nift-built pages
/help/* Nift-built pages
/app server route / SPA shell
/api/* backend JSON API
/auth/* backend authentication flow
Nift + WebSockets / realtime applications
Realtime behaviour is also just browser/runtime behaviour. Nift can generate the shell and JavaScript reference; your backend owns the socket connection.
const socket = new WebSocket('wss://example.com/ws');
socket.addEventListener('message', event => {
const data = JSON.parse(event.data);
updateDashboard(data);
});
This can back terminals, telemetry displays, live dashboards, collaborative tools or other realtime interfaces without changing Nift's role.
Nift + Tailwind
Tailwind can scan the HTML/templates and generate CSS into public/assets/. Nift simply references that file.
npx @tailwindcss/cli -i ./frontend/styles.css -o ./public/assets/site.css
nift build
<link rel="stylesheet" href="@pathto('public/assets/site.css')">
Nift + an external build orchestrator
For a larger repository, let a Makefile, task runner, package script or CI system define the order of operations.
build:
\tnpm run build:frontend
\tnift build-all
\tgo build -o bin/server ./server
Nift does not need a plugin system merely to participate in a build graph.
Development workflow
terminal 1: nift build-auto 0.5
terminal 2: npm run dev # if using Vite/etc.
terminal 3: go run ./server # or node/python/bun/etc.
You can keep each tool's normal development workflow. If you prefer one command, wrap them in your existing task runner.
Production workflow
npm run build:frontend # optional
nift build-all
go build ./server # or node/python/bun build/deploy steps
Then deploy public/ with the backend, upload it to a CDN/object store, or serve it independently—whatever fits the architecture.
What Nift is not trying to own
Runtime state
Sessions, databases, authentication, queues and business logic belong in your backend/runtime stack.
Component runtime
If React/Vue/Svelte is useful, use it normally. Nift does not need its own imitation of those frameworks.
Package ecosystem
npm, Bun and other package managers remain available without being wrapped in Nift-specific packages.
Specialist asset tooling
Vite, esbuild, Rollup, minifiers, Tailwind, Sass and image tools can write directly into the project/public pipeline.
A full application can be sophisticated without Nift itself becoming complicated. The point is to let Nift's small build/template model compose cleanly with whatever architecture the application actually needs.