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:

Direct Data Binding

Templates access JSON documents directly without ORM translation

REST API

Any data source via REST APIs through RESTHeart and plugins

Authentication & Authorization

JWT, OAuth2, LDAP, and role-based access control

Real-time Updates

WebSocket Change Streams for live data

Aggregations & Queries

Complex queries and data pipelines for templates

Extensible

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.