html★ works with any server that returns HTML. No special setup required for basic usage.
Request Headers
Every html★ request includes the X-Requested-With: htmlstar header. This lets the server detect html★ requests and respond accordingly — for example, returning a fragment instead of a full page, or applying the POST-redirect-GET pattern via response headers.
data-send-headers Attribute
Add data-send-headers to opt in to sending target and select information to the server. This is useful for server-side fragment rendering, where the server can tailor its response based on which element will receive the content:
<nav data-target="#main" data-select="#content" data-send-headers data-push> <a href="/users">Users</a></nav>
With data-send-headers, the server receives the CSS selectors for both the target element and the selected fragment, enabling it to render only the relevant portion of the page.
| Header | Value | Description |
|---|---|---|
X-Requested-With | htmlstar | Always sent on every html★ request |
X-HTMLStar-Target | CSS selector | Sent when data-send-headers is present; identifies the target element |
X-HTMLStar-Select | CSS selector | Sent when data-send-headers is present and data-select is set |
Response Headers
html★ recognizes special response headers that allow the server to control client-side behavior. These headers are checked after every successful fetch and take effect before the normal content swap.
| Header | Value | Effect | Use Case |
|---|---|---|---|
X-HTMLStar-Redirect | URL | Client-side navigation to the given URL | POST-redirect-GET pattern, login flows |
X-HTMLStar-Refresh | true | Full page reload | Session expiry, major state changes |
X-HTMLStar-Retarget | CSS selector | Override which element receives the swapped content | Show errors in a toast, redirect response to a different panel |
X-HTMLStar-Redirect
The server can trigger a client-side navigation by setting X-HTMLStar-Redirect to a URL. html★ will navigate the browser to that URL instead of swapping the response body. This is the html★ equivalent of an HTTP redirect, but it happens on the client side, preserving SPA-like behavior.
app.post('/api/login', (req, res) => { // On success, redirect client-side res.set('X-HTMLStar-Redirect', '/dashboard'); res.send('<p>Redirecting...</p>');});
" {="" saveContact(req.body);="" if="" (req.get('X-Requested-With')="==" 'htmlstar')="" res.set('X-HTMLStar-Redirect',="" '="" contact="" success');="" return="" res.send('');="" }="" res.redirect('="" });<="" code-block=""><h3>X-HTMLStar-Refresh</h3><p>The server can force a full page reload by setting <code>X-HTMLStar-Refresh</code> to <code>true</code>. This is useful when a server-side state change (like updating session settings or deploying a new version) means the current page is stale and should be reloaded entirely.</p><code-block language="javascript">app.post('/api/settings', (req, res) => { // Force full page reload after settings change res.set('X-HTMLStar-Refresh', 'true'); res.send('');});
X-HTMLStar-Retarget
The server can dynamically change which element receives the swapped content by setting X-HTMLStar-Retarget to a CSS selector. html★ will look up that selector on the page and swap the response into the matched element instead of the original target. If the selector does not match any element, the original target is used as a fallback.
app.get('/api/notifications', (req, res) => { // Retarget response to a different element res.set('X-HTMLStar-Retarget', '#notification-panel'); res.send('<div>3 new messages</div>');});
" {="" const="" if="" (errors.length="" >="" 0)="" (req.get('X-Requested-With')="==" 'htmlstar')="" res.set('X-HTMLStar-Retarget',="" '#toast');="" return="" res.send(`<div="" class="error" >${errors.join(',="" ')}<="" div>`);="" }="" Normal="" processing...="" });<="" code-block=""><h2>Framework Examples</h2><h3>Express.js</h3><code-block language="javascript">const express = require('express');const app = express(); // Middleware to check for html★ requestsfunction isHtmlStar(req) { return req.get('X-Requested-With') === 'htmlstar';} app.get('/users', (req, res) => { const users = getUsers(); // Simplest approach: always return full page res.render('users', { users, layout: 'main' });}); // Or, with fragment optimization:app.get('/dashboard', (req, res) => { const data = getDashboardData(); if (isHtmlStar(req)) { res.set('Vary', 'X-Requested-With'); return res.render('dashboard', { data, layout: false }); } res.render('dashboard', { data, layout: 'main' });});
Ruby on Rails
class UsersController < ApplicationController def index @users = User.all if request.headers['X-Requested-With'] == 'htmlstar' response.headers['Vary'] = 'X-Requested-With' render layout: false end endend
Django
from django.shortcuts import render def users(request): users = User.objects.all() if request.headers.get('X-Requested-With') == 'htmlstar': response = render(request, 'users_fragment.html', {'users': users}) response['Vary'] = 'X-Requested-With' return response return render(request, 'users.html', {'users': users})
Laravel
public function index(Request $request){ $users = User::all(); if ($request->header('X-Requested-With') === 'htmlstar') { return response() ->view('users.fragment', compact('users')) ->header('Vary', 'X-Requested-With'); } return view('users.index', compact('users'));}
Go
func usersHandler(w http.ResponseWriter, r *http.Request) { users := getUsers() if r.Header.Get("X-Requested-With") == "htmlstar" { w.Header().Set("Vary", "X-Requested-With") renderFragment(w, "users", users) return } renderFull(w, "users", users)}
Summary
| Approach | Server Changes | Caching | Best For |
|---|---|---|---|
| Full Pages | None | Simple | Most projects, static sites |
| Server Fragments | Required | Needs Vary header | Large pages, bandwidth optimization |
Recommendation: Start with full pages (Pattern A). It's simpler, more robust, and handles progressive enhancement automatically. Only add server-side fragment detection if you have a specific performance need.
For more advanced server patterns, see the Content Negotiation, Fragment Rendering, and Component Registry guides.