halide
v0.0.11
Published
A declarative BFF (Backend for Frontend) framework that standardizes SPA communication with auth, proxy, CSP, rate limiting, OpenAPI support, and static file hosting
Downloads
1,485
Maintainers
Readme
What is Halide?
Halide is a purpose-built, declarative BFF runtime that standardizes how your SPA communicates with backend services. It gives these concerns a shared, predictable structure, configured once rather than assembled from scratch every time.
Browser (SPA)
↓
Halide (auth, routing, composition)
↓
Private backend servicesHalide is not an API gateway, a service mesh, or a full backend framework. It is specifically designed around SPA application boundaries.
Get started
See the demo app for a complete example.
Run Halide in an empty project (npm init) or add it directly to your existing frontend project. The server runs as a standalone process alongside your SPA build tooling.
npx halide initThis automatically:
- Detects your package manager
- Installs
halide - Scaffolds a
server.tsentry point with a health route - Creates
tsconfig.server.jsonand updates project references - Adds
halide:startandhalide:buildscripts topackage.json - Installs agent skill via native copy from node_modules/halide/skill/
Manual Installation
npm install halide// routes.ts
import { apiRoute, proxyRoute } from 'halide';
export const healthRoute = apiRoute({
access: 'public',
method: 'get',
path: '/api/health',
handler: async () => ({ status: 'ok' }),
});
export const userProxyRoute = proxyRoute({
access: 'private',
methods: ['get', 'post'],
path: '/api/users',
target: 'http://user-svc:3000',
});// server.ts
import { healthRoute, userProxyRoute } from './routes';
import { createServer, type ServerConfig } from 'halide';
const config: ServerConfig = {
app: {
root: './browser',
},
security: {
auth: {
strategy: 'jwks',
jwksUri: 'https://my-tenant.us.auth0.com/.well-known/jwks.json',
audience: 'https://api.example.com',
},
},
apiRoutes: [healthRoute],
proxyRoutes: [userProxyRoute],
};
const server = createServer(config);
server.start((port) => console.log(`Serving on ${port}`));npx tsx server.tsThe server starts on port 3553. Override with
app.portor thePORTenvironment variable.
Why Halide?
In most SPA setups, each application carries its own ad-hoc BFF implementation. Across multiple apps this becomes a mess:
- Every SPA implements auth slightly differently, and debugging token issues across them is painful
- Proxy logic is copy-pasted between projects, drifting over time
- Frontend code ends up coupled to internal service topology (URLs, ports, paths)
- CORS configuration is repeated across services, often inconsistently
- No clear boundary between "frontend backend" and "actual backend" responsibilities
Halide provides a shared structure for all of these concerns, configured once and consistent across every SPA:
- Static SPA hosting with fallback routing
- Typed API routes with validation
- Secure proxying to backend services
- Built-in auth (JWT / JWKS)
- CORS, CSP, and rate limiting
- Optional OpenAPI documentation
The result is a predictable backend layer across all your SPAs, without duplication or drift.
When not to use Halide
Halide is opinionated but extensible. API route handlers are arbitrary async functions, and proxy routes support per-route authorize, transform, and identity hooks. Consider alternatives if:
- You need direct control over the HTTP layer. Halide abstracts Hono behind a typed config. If you need to set custom response headers/status codes, stream responses, handle file uploads, or run arbitrary Hono middleware, a full backend framework gives you that access.
- You're building a multi-service backend, not just a BFF layer. Halide sits between a frontend and its backends. If you need inter-service communication, routing, or discovery, an API gateway or service mesh is designed for that.
- You need infrastructure-level proxy control. Halide provides per-route request transformation, identity header injection, and path rewriting, but does not expose response transformation, circuit breakers, TLS termination, load balancing, or retry policies. An API gateway or service mesh is a better fit for those.
