Building Delphi Web Applications in Minutes with DMVCFramework and TemplatePro
In the fast-paced world of web development, speed and efficiency aren’t just advantages—they’re necessities. While the industry often gravitates toward complex JavaScript frameworks and intricate toolchains, DMVCFramework stands as the most popular Delphi project on GitHub for a compelling reason: it delivers enterprise-grade web applications with unprecedented simplicity and speed.
Combined with TemplatePro’s powerful templating engine and enhanced by modern tools like WebStencils, this ecosystem represents a paradigm shift in how web applications can be built. Let’s explore how these technologies enable developers to create sophisticated web applications in minutes, not months.
The Power Trio: DMVCFramework, TemplatePro, and WebStencils
DMVCFramework: The Foundation of Fast Web Development
DMVCFramework is a popular and powerful framework for WEB API in Delphi that supports RESTful and JSON-RPC WEB APIs development. What sets it apart is its remarkable ability to transform complex web development tasks into simple, intuitive operations.
Here’s what makes DMVCFramework exceptional:
Production-Ready Stability: Used by small/mid/big projects since 2010, DMVCFramework has proven its mettle in high-traffic environments. Some of the most heavy traffic Delphi WEB APIs (RESTful or JSONRPC) are powered by DMVCFramework.
Instant Development: You can create a full-flagged RESTful server in a couple of clicks. The integrated wizard makes project creation almost instantaneous.
Flexible Deployment: Whether you need a standalone server, Apache module, or ISAPI extension, DMVCFramework adapts to your infrastructure needs.
Rich Ecosystem: With over 100 samples and comprehensive documentation, developers can become productive immediately.
TemplatePro: Modern Templating Made Simple
TemplatePro is a modern and versatile templating engine designed to simplify the dynamic generation of HTML, email content, and text files. With syntax inspired by popular systems like Jinja and Smarty, it provides powerful features including conditional blocks, loops, template inheritance, and JSON data support.
Key Features:
- Intuitive Syntax: Uses familiar
{{}}
notation for expressions and logic - Template Inheritance: Build reusable layouts and components
- Custom Filters: Extend functionality with domain-specific data transformations
- JSON Integration: Seamlessly handle API data and complex objects
- Performance: Compiled templates ensure fast execution
TemplatePro Official Documentation is available here
WebStencils: RAD Studio’s Template Engine
WebStencils is RAD Studio 12.2’s native template engine that provides server-side scripting capabilities to extend WebBroker and RAD Server applications. WebStencils represents Embarcadero’s recognition of the importance of modern template engines in web development.
Both engines support conditional logic, loops, template inheritance, and include mechanisms. However, TemplatePro provides some unique features like custom filters, native JSON handling, and optional compilation. WebStencils’ main goal is to significantly extend the existing web technologies in RAD Studio by turning any a Web Service engine into a comprehensive Web Site and Web Service tool.
If you are interested in WebStencils engine I strongly suggest the Free Guide WebStencils and HTMX: Free Guide to Fast Web Development by my friend Antonio Zapater.
Quick Start: From Download to Running Web App in 2 Minutes
The beauty of DMVCFramework and TemplatePro lies in their immediate usability. Forget complex setup procedures—you can have a fully functional web application running in under 2 minutes.
Step 1: Download and Run
Simply download the quickstart project and you’re ready to go:
- Download the QuickStart zip archive
- Unzip it in a folder you like
- Open the project
dmvcframework_templatepro_htmx_quickstart.dproj
in Delphi and press F9 - That’s it! Your web server is running on localhost:8080
From now on you can rename files and add the functionalities you project requires.
The quickstart project includes a complete web application with:
- Pre-configured DMVCFramework server ready to run
- TemplatePro templates already set up
- Sample data and controllers demonstrating best practices
- Responsive web interface using Bootstrap
- Working examples of all major features
Step 2: Explore What’s Already Built
Open the project and you’ll find a fully functional customer management system:
// ControllerU.pas - Already implemented!
unit ControllerU;
interface
uses
MVCFramework, MVCFramework.Commons, MVCFramework.Serializer.Commons, System.Generics.Collections;
type
[MVCPath]
TMyController = class(TMVCController)
public
[MVCPath]
[MVCHTTPMethod([httpGET])]
[MVCProduces(TMVCMediaType.TEXT_HTML)]
function Index: String;
[MVCPath('/reversedstrings')]
[MVCHTTPMethod([httpGET])]
[MVCProduces(TMVCMediaType.TEXT_PLAIN)]
function GetReversedString(const [MVCFromQueryString('value','')] Value: String): String;
end;
implementation
uses
System.StrUtils, System.SysUtils, MVCFramework.Logger;
function TMyController.Index: String;
begin
Result := RenderView('index');
end;
function TMyController.GetReversedString(const Value: String): String;
begin
ViewData['reversed_string'] := System.StrUtils.ReverseString(Value.Trim);
Result := RenderView('partials/reversed');
end;
end.
Step 3: See TemplatePro in Action
The quickstart includes working templates you can examine and modify:
templates/index.html (included in the quickstart):
{{extends "_layout.html"}}
{{block "body"}}
<div class="row">
<div class="col">
<div class="text-center mt-5">
<h1>DMVCFramework + TemplatePro + HTMX</h1>
<p class="lead">A complete project boilerplate built with Bootstrap</p>
<p>Bootstrap v5.3.3</p>
</div>
</div>
</div>
<div class="row mt-5">
<div class="col col-3 offset-3">
<div class="mb-3">
<input type="text" name="value" class="form-control" id="exampleFormControlInput1"
placeholder="Write something here" value="Hello World">
</div>
</div>
<div class="col col-2">
<button type="button" hx-get="/reversedstrings" hx-include='input' hx-target="#result"
class="btn btn-primary">Reverse it!</button>
</div>
</div>
<div class="row">
<div class="col col-5 offset-3">
<div id="result" class="alert alert-primary" role="alert">
{{include "partials/reversed.html"}}
</div>
</div>
</div>
{{endblock}}
Step 4: Instant Customization
Want to see your changes immediately? The quickstart is designed for instant feedback:
- Modify a template - Edit
templates/index.html
- Refresh browser - See changes immediately (no compilation needed for templates!)
- Create new endpoints - Follow the existing controller patterns
templates/_layout.hmtl (also included):
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta name="description" content="A simple DMVCFramework + TemplatePro + HTMX Template for new projects.">
<meta name="author" content="Daniele Teti">
<title>DMVCFramework TemplatePro HTMX Quick Start</title>
<!-- Latest compiled and minified CSS -->
<script src="/assets/js/htmx.min.js"></script>
<link href="/assets/bootstrap-5.3.3/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<link rel="stylesheet" href="/assets/css/style.css"/>
<link rel="icon" type="image/x-icon" href="/assets/images/favicon.ico">
<link rel="manifest" href="/assets/site.webmanifest" />
</head>
<body>
<!-- Responsive navbar-->
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
<div class="container">
<a class="navbar-brand" href="#">Start Bootstrap</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ms-auto mb-2 mb-lg-0">
<li class="nav-item"><a class="nav-link active" aria-current="page" href="#">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#">Link</a></li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" id="navbarDropdown" href="#"
role="button" data-bs-toggle="dropdown" aria-expanded="false">Dropdown</a>
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#">Action</a></li>
<li><a class="dropdown-item" href="#">Another action</a></li>
<li><hr class="dropdown-divider" /></li>
<li><a class="dropdown-item" href="#">Something else here</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
{{block "body"}}{{endblock}}
</div>
<!-- Bootstrap core JS-->
<script src="/assets/bootstrap-5.3.3/js/bootstrap.bundle.min.js" crossorigin="anonymous"></script>
<!-- Core theme JS-->
<script src="/assets/js/scripts.js"></script>
</body>
</html>
Now it’s time for another completely unrelated photo… 😁
Advanced TemplatePro Features in Action
Working with JSON Data
TemplatePro excels at handling JSON data from APIs:
function TMyController.GetCustomers: String;
begin
//Let's create a dataset containing 15 random people we consider as customers.
//This dataset is generated by the "Delphi Fake Data Utils" project available here https://github.com/danieleteti/delphi_fake_data_utils
var lDS := ToFree<TDataSet>(GetPeople(15));
var lJSON := ToFree<TJSONObject>(TJSONObject.Create);
//calculate customers avg age
lDS.First;
var lAgeCumulative := 0;
_.ForEachRecord(lDS,
procedure(const DS: TDataSet)
begin
lAgeCumulative := lAgeCumulative + YearsBetween(Now, lDS.FieldByName('dob').AsDateTime);
end);
var lAvgAge := lAgeCumulative / lDS.RecordCount;
lDS.First;
// end - stats
lJSON.A['customers'] := lDS.AsJDOJSONArray();
lJSON.F['avg_age'] := lAvgAge;
ViewData['data'] := lJSON;
Result := RenderView('index');
end;
Customers Directory template (customers.html
):
{{extends "_layout.html"}}
{{block "body"}}
<h2 class="mb-4">Customers Directory</h2>
<!-- TemplatePro Template for Dataset Table -->
{{if data.customers}}
<div class="table-container">
<table class="table table-striped table-hover mb-0">
<thead>
<tr>
<th scope="col">#</th>
<th scope="col">Code</th>
<th scope="col">First Name</th>
<th scope="col">Last Name</th>
<th scope="col">Country</th>
<th scope="col">Date of Birth</th>
<th scope="col">Age</th>
</tr>
</thead>
<tbody>
{{for customer in data.customers}}
<tr {{if customer.@@odd}}class="table-light"{{endif}}>
<th scope="row">{{:customer.@@index}}</th>
<td>
<span class="badge bg-secondary">{{:customer.code}}</span>
</td>
<td>{{:customer.first_name|capitalize}}</td>
<td>{{:customer.last_name|uppercase}}</td>
<td>
<span class="badge bg-primary badge-country">{{:customer.country|uppercase}}</span>
</td>
<td>{{:customer.dob}}</td>
<td>
{{if customer.dob}}
<small class="text-muted">
<!-- Calculate age - you'd implement this as a custom filter -->
{{:customer.dob|age}} years
</small>
{{else}}
<small class="text-muted">N/A</small>
{{endif}}
</td>
</tr>
{{endfor}}
</tbody>
</table>
</div>
<!-- Dataset Statistics -->
<div class="row mt-4">
<div class="col-md-4">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">{{:data.customers|count}}</h5>
<p class="card-text">Total Customers</p>
</div>
</div>
</div>
<div class="offset-md-4 col-md-4">
<div class="card text-center">
<div class="card-body">
<h5 class="card-title">{{:data.avg_age|round,-2}} years</h5>
<p class="card-text">Average Age</p>
</div>
</div>
</div>
</div>
{{else}}
<!-- Empty State -->
<div class="alert alert-info text-center" role="alert">
<h4 class="alert-heading">No Data Available</h4>
<p>The employee dataset is empty or not loaded.</p>
<hr>
<p class="mb-0">Please check your data source and try again.</p>
</div>
{{endif}}
<!-- Action Buttons -->
<div class="d-flex justify-content-between mt-4">
<button class="btn btn-outline-secondary" onclick="window.print()">
Print Table
</button>
<div>
<button class="btn btn-success me-2" onclick="exportToCSV()">
Export CSV
</button>
<button class="btn btn-primary" onclick="addEmployee()">
Add Employee
</button>
</div>
</div>
</div>
<script>
function exportToCSV() {
// CSV export functionality
alert('CSV export would be implemented here');
}
function addEmployee() {
// Add employee functionality
alert('Add employee form would open here');
}
</script>
{{endblock}}
Custom Filters for Domain Logic
Create specialized filters for your business domain:
// Custom filter for "age" expressed as in "I'm x years old"
function Age(const Value: TValue; const Parameters: TArray<TFilterParameter>): TValue;
begin
//DOB is a string formatted as yyyy-mm-dd
Result := YearsBetween(Now, ISODateToDate(Value.AsString));
end;
// Register filters
procedure TemplateProContextConfigure;
begin
TTProConfiguration.OnContextConfiguration := procedure(const CompiledTemplate: ITProCompiledTemplate)
begin
// These filters will be available to the TemplatePro views as if they were the standard ones
CompiledTemplate.AddFilter('age', Age);
end;
end;
Use in templates:
{{if customer.dob}}
<small class="text-muted">
<!-- Calculate age - you'd implement this as a custom filter -->
{{:customer.dob|age}} years
</small>
{{else}}
<small class="text-muted">N/A</small>
{{endif}}
Here’s the resultant sample page.
Template Functions for Complex Logic
Functions provide even more power and can be used to implement complex logic.
Integration with HTMX
HTMX pages can benefit from server-side code generation and hook into REST servers regarding content updates. Delphi web technologies can offer page generation and REST APIs at a very high-quality level.
<!-- HTMX-powered dynamic content -->
<div id="customer-list">
{{include "partials/customer-list.html"}}
</div>
<button hx-get="/api/customers"
hx-target="#customer-list"
hx-swap="innerHTML">
Refresh Customers
</button>
<form hx-post="/api/customers"
hx-target="#customer-list"
hx-swap="innerHTML">
<input name="name" placeholder="Customer Name" required>
<input name="email" placeholder="Email" required>
<button type="submit">Add Customer</button>
</form>
TemplatePro supports enterprise Features as:
- Compiled Templates for maximum performances and less CPU load
- Authentication and Authorization templates can have access to the user roles.
- Error Handling in case of unhandled errors the dafult error handling is triggered (check sample \samples\custom_exception_handling_using_controller)
Learning Resources and Next Steps
Getting Started Immediately
The fastest way to get started is using the DMVCFramework wizard in Delphi IDE. DMVCFramework allows to create powerful RESTful servers without effort. You can create a full-flagged RESTful server in a couple of clicks.
Community and Support
- Free Support group at https://www.facebook.com/groups/delphimvcframework with more than 6000 active members provides an active community for developers.
- Premium PATREON subscription for direct help on Discord, advanced examples and in-dept articles and videos about dmvcframework at https://www.patreon.com/c/delphimvcframework
- Official trainings by bit Time Professionals on DMVCFramework, HTMX and a lot ot other topics.
About WebStencils
For comprehensive coverage of WebStencils and HTMX integration, we strongly recommend downloading the free White Paper by Antonio Zapater available at Embarcadero’s blog. This guide provides in-depth coverage of:
- Advanced WebStencils scripting techniques
- HTMX integration patterns
- Enterprise deployment strategies
- Performance optimization
- Security best practices
Conclusion
The combination of DMVCFramework and TemplatePro (or WebStencils) represents a powerful paradigm for rapid web development. While other frameworks require complex build processes, extensive JavaScript knowledge, and intricate deployment procedures, this Delphi-based stack delivers:
Speed: From concept to production in minutes, not weeks Simplicity: Intuitive syntax that developers can master quickly Power: Enterprise-grade features without enterprise-level complexity Flexibility: Deploy anywhere, integrate with anything Stability: Battle-tested in production environments worldwide
As revealed by an Embarcadero analysis, DMVCFramework is the most popular Delphi project for WebAPI and WebApp on GitHub since 2017, and its integration with modern templating engines like TemplatePro and WebStencils only strengthens its position as the go-to solution for rapid web development.
Whether you’re building internal tools, customer-facing applications, or enterprise APIs, this stack provides the perfect balance of productivity and professionalism. The learning curve is gentle, the documentation is comprehensive, and the community is supportive.
For developers tired of complex toolchains and overengineered solutions, DMVCFramework with TemplatePro offers a refreshing return to simplicity without sacrificing capability. In a world where web development often feels unnecessarily complicated, these tools prove that sometimes the best solution is also the simplest one.
Ready to experience the speed and simplicity for yourself? Start with the DMVCFramework wizard, explore the examples, and dive into the free resources available. Your next web application is just minutes away.
Comments
comments powered by Disqus