The data-driven Web framework
One API, many facets
Turn your API into HTML, no code required.
What is Facet?
Facet transforms JSON into server-rendered HTML using path-based templates. Templates simply mirror your API structure. The same endpoint serves JSON to clients and HTML to browsers.
- Direct data binding: Automatically maps APIs to HTML using path-based templates.
- No backend code: Templates + JSON documents = HTML — no controllers.
- Content negotiation: Browsers get HTML, API clients get JSON - same endpoint, no extra wiring.
- Progressive: Full rendering and HTMX fragments for dynamic but SEO-friendly UIs.
Why Facet?
Zero Backend
Ship features without writing controllers or services: templates + data = HTML, end to end.
Hybrid by Default
API and UI from the same endpoint. JSON for mobile apps, HTML for web. Zero duplication.
Convention-Based
Drop a template where the path matches the resource and you're done. No routing files.
Progressive
Start with fast SSR, sprinkle HTMX for interactivity. SEO-friendly, minimal JS, smooth UX.
See It In Action
GET /products
Accept: application/json → JSON facet (API)
Accept: text/html → HTML facet (Browser)
# One source of truth. Multiple representations.
<!-- templates/products/index.html -->
{% extends "layout" %}
{% block content %}
<h1>Products</h1>
{% if documents %}
{% for product in documents %}
<div class="product-card">
<h2>{{ product.name }}</h2>
<p>{{ product.description }}</p>
<span class="price">${{ product.price }}</span>
</div>
{% endfor %}
{% endif %}
<!-- Pagination automatically available -->
{% if totalPages > 1 %}
<nav class="pagination">
{% for p in range(1, totalPages + 1) %}
<a href="?page={{ p }}">{{ p }}</a>
{% endfor %}
</nav>
{% endif %}
{% endblock %}
# Browser requests HTML
curl -u admin:secret -H "Accept: text/html" \
http://localhost:8080/products
→ Rendered HTML page
# API clients request JSON
curl -u admin:secret -H "Accept: application/json" \
http://localhost:8080/products
→ JSON response
# No template? Still returns JSON
curl -u admin:secret http://localhost:8080/orders
→ JSON (SSR is opt-in per resource)
Perfect For
Data-driven applications where templates consume documents and collections directly from your database or API. No transformation layers, no controllers. Some examples:
Dashboards
Build internal tools and back-office interfaces. CRUD operations, user management, data monitoring.
Hybrid CMS
Serve JSON and HTML from one endpoint. Drop templates on your API—no backend code.
Product Catalogs
E-commerce listings, filters, search, and pagination directly rendered from your database.
Data Browsers
Turn any document collection into a web application, instantly. Search, filtering, and pagination out of the box.
How Facet Compares
Many web frameworks require backend coding to connect REST APIs with HTML views. Facet eliminates this need through convention-based templates that map directly to REST endpoints. See how Facet stacks up against popular alternatives:
| Feature | WordPress | Strapi + Next | Rails | Facet |
|---|---|---|---|---|
| Backend Code | PHP | Node | Ruby | None (*) |
| Native SSR | Yes | External | Yes | Yes |
| API + HTML | Partial | No | Separate | Same |
| Convention Routing | No | Partial | Yes | Yes |
| Hybrid SSR/SPA | No | Separate | Turbo | Yes |
| Deployment | Moderate | Two systems | App server | Single |
| Database | MySQL | Multiple | PostgreSQL | Multiple (**) |
| Target | Editors | Full-stack | Full-stack | Web devs |
(*) Custom backend code can be added via RESTHeart plugins.
(**) Default with MongoDB-compatible databases or PostgreSQL via FerretDB. Other databases via custom plugins.
The Stack
Built with proven technologies for reliability and developer productivity
Database
MongoDB, FerretDB, and more
RESTHeart
API engine
GraalVM
JavaScript plugins with hot-reload
Pebble
Twig/Jinja templates
HTMX
Progressive enhancement
Architecture
Facet leverages RESTHeart, the Development Platform for MongoDB. Facet adds Server-Side Rendering capabilities while keeping all RESTHeart features intact:
Templates access JSON documents directly without ORM translation
Any data source via REST APIs through RESTHeart and plugins
JWT, OAuth2, LDAP, and role-based access control
WebSocket Change Streams for live data
Complex queries and data pipelines for templates
JavaScript plugins with hot-reload (no recompile) or Java plugins for full JVM power
Ready to Build?
🚀 Start transforming your REST and GraphQL APIs into complete web interfaces.