Fast, powerful & native

Yurai is an innovative full-stack web-framework written in the D programming language.

Get Started Support

Experience the web with Yurai

Yurai is built on modern principles using D, inspired by ASP.NET Core and razor templates.

It's completely free, open-source and fit for enterprise development with focus on rapid development, performance and the cloud.

It compiles natively but dynamically, and can run on most platforms and environments.

The goal of Yurai is to provide an environment fit for both enterprise projects and personal hobby projects.

Yurai also values safety and security and you'll find most security measures working out of the box with little to no effort on your part!

Get started with the Latest stable version of Yurai.

Examples

views/layout.dd

@[name: layout]
@(website | My Website)
@(doctype)
<html>
<head>
  <title>@(title) | @(website)</title>
</head>
<body>
  @(view)
</body>
</html>

Learn more about layouts

views/home.dd

@[layout: layout]
@[name: home]
@[route: /]
@[route: index]
@#(title | Home)

<p>Hello World</p>

Learn more about views

View Controller

import yurai.controllers;

public final class HomeController(View) : WebController!View
{
  public:
  final:
  this(View view, IHttpRequest request, IHttpResponse response)
  {
    super(view, request, response);
  }

  @HttpDefault
  Status index()
  {
    // Do stuff with view, request, response ...
    // Returns Status.success to render the view ...
    return Status.success;
  }
}

Learn more about view controllers

Api Controller

import yurai.controllers;

public class Foo
{
  public int x;
  public int y;
}

// The HttpRoute is not necessary.
// If it's not specified then the route becomes the name of the controller without the "Controller" part.
@HttpRoute("test")
public final class TestController : ApiController
{
  public:
  final:
  this(IHttpRequest request, IHttpResponse response)
  {
    super(request, response);
  }

  @HttpDefault
  Status index()
  {
    auto foo = new Foo;
    foo.x = 100;
    foo.y = 200;

    return json(foo);
  }
}

Learn more about API controllers

Database Model

@DbTable("tablename")
final class DbModel
{
  import std.datetime : DateTime;

  public:
  ulong id;
  string name;
  @DbCreateTime DateTime created;
  @DbTimestamp DateTime timestamp;
}

Setup

// Requires mysql-native dependency and the version flag "YURAI_MYSQL"
import yurai.data.mapping.mysql;

auto service = new MysqlDataService("connectionString");

Insert / Update

If the model's id doesn't evalute to truthy ex. if it's 0 then it will insert, otherwise it will update.

auto model = new DbModel;
model.name = "Name";
service.save(model);

Insert / Update Many

Ditto regarding when save does what.

DbModel[] models = [];
foreach (_; 0 .. 10)
{
  auto model = new DbModel;
  model.name = "Name";
  models ~= model;
}

service.save(models);

Select One

Parameters are query (where) and params.

auto params = new DbParam[1];
params[0] = cast(ulong)10;

auto model = service.selectSingle!(DbModel)("`id` = ?", params);

Select Many

Ditto regarding parameters.

auto modelsRange = service.selectMany!(DbModel)(null, null);

Learn more about ORM

Why Yura?

Experience speed and low memory-usage

Yurai is built to handle many connections, to be fast and with absolute excellent performance.

It's one of Yurai's main priorities; to deliver content and data fast!

Yurai's performance is also combined with low-memory-usage compared to many other frameworks.

You control setup, configurations, development and deployment

Everything in Yurai can be controlled by you.

That means you can configure Yurai to operate exactly how you want it.

This allows Yurai to be integrated on top of existing solutions or as a part of an already established environment.

Yurai is flexible and can work with any type of data and deliver any type of content.

Experience rapid development like never before

The infrastructure of Yurai was made to support rapid development, even for enterprise solutions.

Yurai's API is user-friendly and feature-rich, making sure you only have to write absolute minimum functionality and can focus on getting the job done.

It supports all modern functionality, along with many other out of the box and built-in features that other frameworks don't, or at least not without effort or third-party libraries.

With Yurai you can keep your dependencies as low as possible, keeping your environment and workspace safe from breakage.

Scaling your application has never been easier

Being able to scale environments and applications is an essential functionality for enterprise solutions.

Yurai was developed in a way to support scalability without a complex environment.

You can scale it as much or as little as you need or want.

Security is a priorty and Yurai builds on that

Today security is an absolute priority for professional solutions.

Security is not only protecting your data, server and platform from attacks, but also being secure from coding errors and bugs.

Yurai supports all modern security practices and one of its goals is to be OWASP Compliant.

Run Yurai on multiple platforms and within multiple environments

Unlike some other web-frameworks, then Yurai isn't limited to just one or few platforms and environments.

Yurai supports multiple operating systems and environments, including cloud environments.

Operating Systems Environments
Windows Microsoft Azure
Unix / Linux / Posix Heroku
macOS Nginx
  Apache
  Amazon Web Services

Testing is essential for professional solutions

Yurai has support for D's built-in unittesting, but also has a more advanced unittesting API.

Yurai's own unittesting API can be shaped to test certain requests and target specific areas of the application.

This is useful, because you can do real HTTP tests without a browser or third-party tools.

Wide range of Sql & No-sql database support

Software often use more than one type of database and thus it was a priority for Yurai to support that.

Yurai supports both no-sql and sql databases.

Database Built-in Wrapper? Third-Party?
MySQL Yes Yes
MariaDB Yes Yes
PostgreSQL Future support* Yes
Microsoft SQL Server Future support* Yes
SQLite Future support* Yes
MongoDB Yes Yes
Redis Future support* Yes

* All future support databases can currently be used using third party libraries and tools but has no built-in wrapper.

Yurai VS Diet Templates (vibe.d) & Razor (ASP.NET Core)

Below is a table comparison of Yurai templates and vibe.d (diet) templates.

The comparison serves the purpose of showcasing that Yurai's template engine has an advantage to vibe.d's default template engine.

Since Yurai uses vibe.d as the default web-server then one might think Diet templates are necessary.

However, Yurai does not depend on any web-server implementations for more than handling connections.

That's why Yurai has its own template engine with its own syntax.

Yurai aims to be similar to ASP.NET Core in development practice and thus the template engine is HTML-first, which is the largest difference between Diet templates and Yurai templates.

Functionality Diet Yurai
Compile-time parsing Yes Yes
Linear Expressions Yes Yes
D Code Yes (Partially)

Does not use fully D syntax.
Yes

Full D expressions and code blocks with D syntax.
Layouts / Extendable Views Yes Yes
Partial Views Yes Yes
Non-layout View Limitations Yes

You can only use -block
No
Metadata Configurations Yes (Limited) Yes (Very Functional)
Expressive Grammar No

Uses keywords for identifying view parts.
Yes

Lots of syntactic sugar that helps creating expressive views.
Custom Grammar No Yes
Caching Yes Yes
Dynamic HTML Generation Yes Yes
Dynamic CSS Generation Unknown Yes
Dynamic Any-type Generation Unknown Yes
Standard HTML No

You must use the Diet syntax.
Yes

Allows mixture between Yurai expressions and standard HTML.

However there's a full HTML compliance.
Placeholders No Yes
MVC No Yes
HMVC No Yes
View Inheritance No Yes
Static Templates Yes Yes

Supports dynamic content and statically-timed caching.
Sections No Yes

You can render specific sections of views, as well pass sections to layouts.
Total Score* 9(11)/20 20/20

* A higher score is better.

doctype html
- auto title = "Hello, <World>";
html
	head
		title #{title} - example page
	body
		h1= title
		h2 Index
		ol.pageindex
			- foreach (i; 0 .. 3)
				li: a(href="##{i}") Point #{i}
		- foreach (i; 0 .. 3)
			h2(id=i) Point #{i}
			p.
				These are the #[em contents] of point #{i}. Multiple
				lines of text are contained in this paragraph.
@(doctype)
@:auto title = "Hello, <World>";
<html>
  <head>
    <title>@=title; - example page</title>
  </head>
  <body>
    <h1>@=title;</h1>
    <h2> Index </h2>

    <ol class="pageindex">
      @:foreach (i; 0 .. 3) {
        <li><a href="#@=i;">Point @=i;</a></li>
      }
    </ol>

    @:foreach (i; 0 .. 3) {
      <h2 id="@=i;">Point @=i;</h2>

      <p>
        These are the <em>contents</em> of point @=i;. Multiple
        lines of text are contained in this paragraph.
      </p>
    }
  </body>
</html>

While Diet templates look shorter, they don't offer the same flexibility and will in turn become more complex with larger projects.

They also rely heavily on indentation and since they aren't html-first then it can be hard to use them with frameworks like bootstrap or just html5 themes/templates in general.

Yurai templates has been heavily inspired by razor templates from ASP.NET Core, but are much more flexible and has a slight syntactic difference.


Syntax ASP.NET Core (Razor) Yurai
Escaping @
@@
\@
Implicit expressions
@Foo.Bar
@=Foo.Bar;
Explicit expressions
@(Foo.Bar - Baz.Boo)
@=Foo.Bar - Baz.Boo;
Expression encoding
@("<span>Hello World</span>")
@="<span>Hello World</span>";
Raw expressions
@Html.Raw("<span>Hello World</span>")
@$="<span>Hello World</span>";
Code blocks
@{
    var quote = "The future depends on what you do today. - Mahatma Gandhi";
}

<p>@quote</p>
@{
	auto quote = "The future depends on what you do today. - Mahatma Gandhi";
}

<p>@=quote;</p>
Local functions with markup
@{
	void RenderName(string name)
	{
		<p>Name: <strong>@name</strong></p>
	}

	RenderName("Mahatma Ghandi");
	RenderName("Martin Luther King, Jr.");
}
@:void RenderName(string name) {
	<p>Name: <strong>@=name;</strong></p>
}

@:RenderName("Mahatma Ghandi");
@:RenderName("Martin Luther King, Jr.");
Scoped expressions
@for (var i = 0; i < people.Length; i++)
{
	var person = people[i];
	<text>Name: @person.Name</text>
}
@:foreach (i; 0 .. people.length) {
	@:auto person = people[i];
	Name: @=person.name;
}
Scoped expressions (explicit transition)
@for (var i = 0; i < people.Length; i++)
{
	var person = people[i];
	@:Name: @person.Name</text>
}
@:foreach (i; 0 .. people.length) {
	@:auto person = people[i];
	Name: @=person.name;
}
Comments
@*

	Comment here

*@
@*

	Comment here

*@
Metadata (layout)
@{
	Layout = "_Layout.cshtml"
}
@[layout: layout]
Metadata (model)
@model MyModel
@[model: MyModel]
Sections
@section Scripts {
    <script type="text/javascript" src="~/scripts/main.js"></script>
}

@RenderSection("Scripts", required: false)
@[section: Scripts]
<script type="text/javascript" src="~/scripts/main.js"></script>
@[section: *]

@(section: Scripts)

Learn more about Yurai views & templates.