Skip to content

SoftInstigate/facet

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

95 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Facet logo Facet

Turn your API into HTML. No code required.

decorate API

What is Facet?

Facet transforms REST APIs into web interfaces using simple HTML templates. You already have the API—just add templates where you want HTML.

The core idea: Your API structure is your site structure.

Your API:
├── /shop/products     → Returns JSON
└── /shop/products/123 → Returns JSON

Add templates:
└── templates/
    └── shop/
        └── products/
            ├── list.html   → Renders /shop/products as HTML
            └── view.html   → Renders /shop/products/123 as HTML

Result:
├── /shop/products     → HTML for browsers, JSON for APIs
└── /shop/products/123 → HTML for browsers, JSON for APIs

No routing files. No controllers. No duplicate logic. Just drop templates where your data lives.

See It in Action

Try the working example:

git clone https://github.com/SoftInstigate/facet.git
cd facet
mvn package -DskipTests

cd examples/product-catalog
docker-compose up

Open: http://localhost:8080/shop/products

You'll see a complete product catalog with search, pagination, and authentication—all built with templates.

→ Follow the Tutorial to understand how it works by exploring the code.

How It Works

1. You have data in MongoDB

{
  "name": "Laptop Pro",
  "price": 1299,
  "category": "Electronics"
}

2. Facet exposes it as REST API

curl http://localhost:8080/shop/products
# Returns JSON array of products

3. Add a template

{% extends "layout" %}

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

{% for product in items %}
<article>
  <h3>{{ product.data.name }}</h3>
  <p>Category: {{ product.data.category }}</p>
  <span>${{ product.data.price }}</span>
</article>
{% endfor %}
{% endblock %}

4. Done

Open http://localhost:8080/shop/products in your browser—you get HTML. Call it from your app with Accept: application/json—you get JSON.

What You Get

Convention Over Configuration

Templates automatically match API paths:

GET /shop/products      →  templates/shop/products/list.html
GET /shop/products/123  →  templates/shop/products/view.html
GET /shop/categories    →  templates/shop/categories/list.html

No routing configuration needed.

Everything You Need in Templates

Pagination, filters, sorting—all available automatically:

<!-- Pagination works out of the box -->
<nav>
  Page {{ page }} of {{ totalPages }}
  {% if page < totalPages %}
    <a href="?page={{ page + 1 }}">Next</a>
  {% endif %}
</nav>

<!-- MongoDB queries accessible -->
{% if filter %}
  <p>Showing filtered results</p>
{% endif %}

<!-- Authentication built in -->
{% if roles contains 'admin' %}
  <button>Delete</button>
{% endif %}

HTMX for Smooth Interactions

Partial page updates work automatically—no backend code needed:

<!-- Click updates just the product list -->
<a href="?sort=price" 
   hx-get="?sort=price" 
   hx-target="#product-list">
  Sort by Price
</a>

<div id="product-list">
  <!-- Products here -->
</div>

Facet detects HTMX requests and renders only what changed.

Live Development

Edit templates, refresh browser, see changes. No restart required.

When to Use Facet

Good for:

  • Admin dashboards over MongoDB data
  • Content-driven websites
  • Internal tools and CRUD interfaces
  • Adding web UI to existing REST APIs
  • Projects where you want HTML without complex frameworks

Not for:

  • Heavy client-side state management (use React/Vue)
  • Non-MongoDB databases (Facet requires a MongoDB-compatible database)
  • Projects without REST API layer

Quick Comparison

vs Traditional Frameworks (Spring MVC, Django, Rails)

Facet: Drop templates in folder matching API path → Done
Traditional: Write routes + controllers + views + models

vs JavaScript Frameworks (Next.js, Remix)

Facet: Server-renders from REST API, simpler stack
Next.js: Full-stack React, complex build process, more moving parts

vs Hypermedia Frameworks (HTMX + Flask/Express)

Facet: Built-in HTMX support, convention-based routing
HTMX + Framework: More manual setup, explicit route definitions

Technical Details

Built on proven technologies:

  • RESTHeart - Production-grade MongoDB REST API server
  • Pebble - Fast template engine (similar to Jinja2/Twig)
  • GraalVM - High-performance runtime with optional native compilation

Runtime options:

  • Standard JVM: ~1s startup, full plugin support
  • Native image: <100ms startup, minimal memory (~50MB)

Deployment: Single JAR or native binary, runs anywhere—Docker, Kubernetes, bare metal.

Database Compatibility

Database Support Level Notes
MongoDB Full All versions 3.6+
MongoDB Atlas Full Cloud-native support
Percona Server Full Drop-in MongoDB replacement
⚙️ FerretDB Good PostgreSQL-backed MongoDB alternative
⚙️ AWS DocumentDB Good Most features work, some MongoDB 4.0+ features missing
⚙️ Azure Cosmos DB Good With MongoDB API compatibility layer

Compatibility depends on MongoDB wire protocol implementation.

Get Started

Learn by example:

  1. Product Catalog Tutorial - Walk through working code
  2. Developer's Guide - Complete reference
  3. Template Variables - What's available in templates

Try it yourself:

# Start with MongoDB
docker-compose up -d

# Add data
curl -X POST http://localhost:8080/mydb/products \
  -H "Content-Type: application/json" \
  -d '{"name":"Laptop","price":999}'

# Create template
mkdir -p templates/mydb/products
echo '<h1>{{ item.data.name }}</h1>' > templates/mydb/products/view.html

# Visit in browser
open http://localhost:8080/mydb/products

Project Status

Java CI with Maven GitHub releases

⚠️ Pre-1.0 Status: API may change. Watch releases for updates.

Contributing

Contributions welcome! See open issues or start a discussion.

License

Apache License 2.0 - Free for commercial use.


Made by SoftInstigate - Creators of RESTHeart

Releases

No releases published

Packages

No packages published

Languages