The data-driven Web framework

One API, many facets

Turn your API into HTML, no code required.

What is Facet?

Facet adds server-rendered HTML to your REST API through path-based templates. The template location mirrors your API structure. The same endpoint serves JSON to clients and HTML to browsers.

Path-based templates

Template location mirrors your API path. No routing config.

Opt-in per endpoint

When no template then JSON unchanged. Add HTML only where you need it.

Content negotiation

Add a template and your endpoint serves HTML to browsers alongside JSON for API clients.

Hot reload

Edit a template, refresh your browser. No server restart, no build step.

Why Facet?

Every framework that connects a REST API to HTML adds backend work: controllers in Thymeleaf, a build pipeline in React, duplicate routes in Next.js. Facet removes that layer entirely. Drop a template file in the right directory and the endpoint starts serving HTML. That is the only step.

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/list.html -->
{% extends "layout" %}

{% block content %}
  <h1>Products</h1>

  {% for item in items %}
    <div class="product-card">
      <h2>{{ item.data.name }}</h2>
      <p>{{ item.data.description }}</p>
      <span class="price">${{ item.data.price }}</span>
      <a href="{{ path }}/{{ item._id.value }}">View</a>
    </div>
  {% endfor %}

  {% if totalPages > 1 %}
    <nav class="pagination">
      {% for p in range(1, totalPages + 1) %}
        <a href="?page={{ p }}&pagesize={{ pagesize }}">{{ 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 Thymeleaf React + Spring Next.js Facet
Backend code per page Yes (controller) Yes (controller) No No (*)
Separate frontend project No Yes Yes No
JavaScript required No Yes Yes No
Native SSR Yes Partial Yes Yes
JSON API preserved Yes Yes No Yes
Template hot-reload Partial No Yes Yes

(*) Custom backend logic can be added via RESTHeart 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.