HRML - Minimal Web Framework
A minimal, production-ready web framework combining Rust performance with Python flexibility. Create server-rendered web applications with dynamic interactivity using a simple HTML-first approach.
It was thought as a replacement for HCML but now has many more features.
Philosophy
HRML follows these principles:
- Server-side first - HTML rendered on the server for fast initial loads and SEO
- Minimal JavaScript - Only 3KB runtime for dynamic updates, no heavy frameworks
- Simple templates - HTML with clean, readable processing instructions
- Python for logic - Familiar scripting language for backend development
- Rust for speed - Fast HTTP handling and template rendering
- Zero configuration - Sensible defaults that just work
Quick Start
Installation
# Build from source
# The binary will be at target/release/hrml
Create a New Project
Visit http://localhost:8080
Project Structure
HRML enforces a strict project structure for consistency:
myapp/
├── hrml.toml # Configuration
├── templates/
│ ├── layouts/
│ │ └── base.hrml # Base layout (required)
│ ├── components/ # Reusable components
│ │ └── nav.hrml
│ └── pages/
│ ├── index.hrml # Home page (required)
│ └── about.hrml
├── endpoints/
│ └── api/ # Python endpoints
│ └── hello.py
└── static/
├── css/
│ └── style.css
└── js/
For complete documentation of the project structure and all behaviors, see spec.
CLI Commands
hrml new <name>
Creates a new HRML project with the complete directory structure, configuration file, and sample files.
Created structure:
hrml.toml- Configuration with sensible defaultstemplates/layouts/base.hrml- Base HTML layouttemplates/components/nav.hrml- Navigation componenttemplates/pages/index.hrml- Home pagetemplates/pages/about.hrml- About pageendpoints/api/hello.py- Sample Python endpointstatic/css/style.css- Default stylesheet.gitignore- Standard ignore patternsREADME.md- Project documentation
hrml dev [path]
Runs the development server with the following behaviors:
- Serves the application on the configured host and port
- Watches for file changes
- Provides detailed error messages in the browser
- Logs all requests to stderr
- Uses the configuration from
hrml.toml
Default behavior: Uses current directory if no path specified
hrml serve [path]
Runs the production server:
- Optimized for production use
- Serves static files efficiently
- Handles concurrent requests
- Cleaner logging than dev mode
hrml check [path]
Validates the project structure:
- Verifies
hrml.tomlexists and is valid - Checks that required templates exist (base.hrml, index.hrml)
- Ensures template engine can be initialized
- Validates static directory exists
- Attempts to render index template
- Reports any warnings or errors
hrml version
Displays the HRML version.
hrml help
Shows command usage and examples.
Template System
HRML uses a powerful but simple template system with the following directives:
Layout System
Base Layout (templates/layouts/base.hrml):
<?get id="site_name"?>
<?load file="components/nav.hrml"?>
<?slot id="content"?>
Page Template (templates/pages/index.hrml):
<?load file="layouts/base.hrml"?>
<?block slot="content"?>
Welcome
This is the home page.
<?/block?>
Template Directives
<?load file="path"?>- Include another template<?slot id="name"?>- Define a content placeholder<?block slot="name"?>...<?/block?>- Fill a slot<?set id="name"?>value<?/set?>- Set a variable<?get id="name"?>- Get a variable value
Python Endpoints
Create dynamic functionality with Python endpoints:
File: endpoints/api/todos.py
"""
Handle API requests.
req dict contains:
- 'id': Resource ID (e.g., "123" for /api/todos/123)
- 'action': Action name (e.g., "create" for /api/todos/create)
- 'data': Form data as dictionary
Returns: HTML string to be inserted into the page
"""
=
=
=
# Insert into database
=
return f
# Get all todos
=
=
=
+= f
return
Database API
HRML provides a built-in SQLite database with a simple API:
# Create table
# Insert
=
# Find by ID
=
=
# Get all
=
=
# Update
# Delete
Client-Side Interactivity
HRML provides a 3KB JavaScript runtime at /hrml.js that enables dynamic updates:
AJAX Buttons
Increment
Behavior: POSTs to the endpoint and replaces the target element's innerHTML with the response.
AJAX Links
Load About
Auto-Loading Content
Loading...
Behavior: Automatically fetches content when the page loads.
AJAX Forms
Add Todo
Behavior: Submits form via AJAX, inserts response before the end of target element, resets form on success.
Configuration
Configure your application in hrml.toml:
[]
= "my-app"
= "1.0.0"
[]
= "127.0.0.1"
= 8080
[]
= "templates"
= "endpoints"
= "static"
[]
= "My Application"
= "A great web app"
= "/static/favicon.ico"
Behavior: If hrml.toml is missing, HRML uses sensible defaults:
- Host: 127.0.0.1
- Port: 8080
- All paths as shown above
URL Routing
HRML automatically routes requests based on the URL structure:
Pages
GET /→ Renderstemplates/pages/index.hrmlGET /about→ Renderstemplates/pages/about.hrmlGET /contact→ Renderstemplates/pages/contact.hrml
API Endpoints
GET /api/todos→ Callsendpoints/api/todos.py::handler()GET /api/todos/123→ Calls handler withid="123"POST /api/todos/create→ Calls handler withaction="create"POST /api/todos/123/toggle→ Calls handler withid="123",action="toggle"DELETE /api/todos/123/delete→ Calls handler withid="123",action="delete"
Static Files
GET /static/css/style.css→ Servesstatic/css/style.cssGET /static/js/app.js→ Servesstatic/js/app.js
Error Handling
Development Mode
In development (hrml dev):
- Detailed error messages in browser
- Stack traces logged to stderr
- Template rendering errors show line numbers
- Python endpoint errors show full traceback
Production Mode
In production (hrml serve):
- Generic error messages in browser
- Detailed errors logged to stderr only
- No stack traces exposed to clients
Examples
Todo List Application
templates/pages/todos.hrml:
<?load file="layouts/base.hrml"?>
<?block slot="content"?>
Todo List
Add
Loading...
<?/block?>
endpoints/api/todos.py:
=
=
=
=
return f
return
# Return all todos
=
=
=
=
+= f
return
Performance
HRML is designed for performance:
- Templates - Compiled and cached in memory
- Static files - Served efficiently with proper caching headers
- Database - Connection pooling and prepared statements
- Minimal JavaScript - 3KB runtime vs 100KB+ frameworks
- Rust foundation - Fast HTTP handling and concurrent request processing
Security
HRML includes security best practices:
- SQL Injection Protection - All database queries use parameterized statements
- XSS Prevention - Template system escapes HTML by default
- Static File Serving - Proper MIME types and security headers
- Input Validation - Form data is properly parsed and validated
Deployment
Option 1: Binary + Project Files
# Build the binary
# Copy binary and project to server
# Run on server
Option 2: Systemd Service
Create /etc/systemd/system/hrml.service:
[Unit]
Description=HRML Web Application
After=network.target
[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/usr/local/bin/hrml serve
Restart=always
[Install]
WantedBy=multi-user.target
Enable and start:
Development
Running Tests
Project Validation
Before deploying, always validate:
This ensures:
- All required files exist
- Templates are valid
- Configuration is correct
- Static directories exist
Troubleshooting
"No hrml.toml found"
Run hrml check to verify you're in the correct directory.
"Template not found"
Check that the template file exists in the correct subdirectory of templates/.
"Module not found" in Python
Ensure __init__.py files exist in endpoints/ and endpoints/api/.
Changes not appearing
- Restart the dev server:
hrml dev - Check browser cache (Ctrl+Shift+R to hard reload)
- Verify file was saved
Port already in use
Change the port in hrml.toml:
[]
= 3000 # Use a different port
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
License
MIT License - See LICENSE file for details.
Documentation
- PROJECT_STRUCTURE.md - Complete project structure documentation
- CHANGELOG.md - Version history and changes
- API.md - Detailed API documentation (coming soon)