QetriX is a paradigm for creating apps, websites, and games.
We implemented the paradigm into an open-source QetriX Framework, available for various languages, platforms, and frameworks. QetriX is opinionated, and we used the same coding style across platforms wherever possible.
With the QetriX Framework, you build apps in a just-enough and low-effort manner, using as few as four types of components: QElem, QForm, QList, and QView. Components transform data received from services into a particular representation, defined by converters.
The QetriX App consists of modules, which are called by a path or URL via routing middleware. The module generates a page with either text-based content (like HTML, CSV, or JSON – depending on the selected converter) or a component, converted to an appropriate output format by the Framework.
Page inspects the incoming request to determine the response format and language, parses the URL, and loads the appropriate Module.
Module loads data from Services and passes it to its Components, which are then converted into the target format (HTML, XML, JSON, etc.), returned as a response. While the Page is universal, each Module is designed for its particular purpose.
The Framework is robust and powerful, yet fairly simple, performant, and lightweight. We have used it for enough projects to know it provides everything you need for your projects as well. Converter classes are designed to be standalone, so you can use them in your project.
Many of our products are interconnected and extend each other.
Many platforms, single coding style, open source. Quick and easy full stack development paradigm for any target. Opinionated modular approach using components, converters and services.
Commercial QetriX extension for rapid development of rich HTML5-based apps and websites. Offers data modeler, layout builder, process designer and more.
Simple game engine for 2D/2.5D mobile and desktop games. Works on Windows, Linux, MacOS, Android, iOS and in all major web browsers.
Easy to use online and offline personal wiki with Qip and QPDB support. It's decentralized, uses simple markup or WYSIWYG and works nicely as a CMS for websites, blogs and galleries.
Extensible lightweight feed reader, e-mail client and messenger. Works best with RSS, RDF, Atom, Bluesky and IMAP, but also with QB, Qip and Qui.
Social network, focusing on rating anything and everything on a scale from 1 (worst) to 5 (best). Uses data from QB.
Czech internet multiportal, featuring forums, articles, discussion boards, Q/A, news, games, blogs and more. Uses Quiky for content management.
ERP for companies and individuals with simple BPM. Contains Omni Management (Project, Asset, Facility, Fleet, Property, Incident), CRM, HR, Service Desk, CMDB, KB and more.
Time tracker, work planner with agile support. Projects, boards, tasks, todos, issues, releases. Standalone part of Quid.
Trip planner, flight log, travel diary and geo tracker with privacy in mind. Works great in connection with Qarate, QB and Quid. Online and offline usage.
Scriptable task automatizer, Smart Home information system and family hub to help you with day-to-day tasks, like shopping, cooking or fitness. Support for devices and appliances.
Data system for anything and everything. QB allows to store, process, present, analyse and visualize data, with BI and reporting capabilities.
Database schema for dynamically structured and interlinked semantic data particles. EAV on steroids, if you will. Also features geographical extension.
Rapid search of content using custom tags. Excellent for photos or frequently used text snippets (notes, memos, recipes...).
Experimental notation, process and scripting language, used for describing action sequences.
Code examples of various parts in a QetriX App, where we try to show Framework's single coding style across different programming languages and their variants.
Note: We use our custom Dict
class (basically a HashMap or Assoc. Array) for passing arguments into methods.
public class PageInJava extends QModule
{
public String main(Dict args)
{
var view = new QView();
view.label("Page in Java");
view.add("This is a HTML page in Java.");
return view.convert("page");
}
}
class TableInPHP extends QModule
{
public function table(Dict $args)
{
$tbl = new QList();
$tbl->label("Table in PHP");
$tbl->add(QElem::create(ElemType::number, "id", "ID");
$tbl->add(QElem::create(ElemType::text, "name", "Name");
$tbl->data($this->ds()->getTableData());
return $tbl->convert("table");
}
}
public class FormInCS : QModule
{
public String form(Dict args)
{
var frm = new QForm();
frm.heading("Form in C#");
frm.action("formSubmit");
frm.add(new QElem(ElemType.text, "email", "E-mail", "", 10));
frm.add((new QElem(ElemType.button)).action("validate"));
frm.add(new QElemButton("Submit"));
return frm.convert();
}
}
class Person extends QModule
{
const _data = {};
main(args) // Default method for every Module
{
_data.name = args.get("name");
}
get name()
{
return _data.name;
}
};
Older version of JavaScript, compatible with Internet Explorer 9
com.qetrix.modules.Person = function($QModule) // $QModule contains QModule methods
{
var _data = {};
$public.main = function (args) // Default method for every Module
{
_data.name = args.get("name");
}
$public.name = function (args)
{
return _data.name;
}
return $public;
};
class NavInPython(QModule):
def nav()
nav = QList("nav");
nav.add({"text":"First", "action":"first.html"});
nav.add({"text":"Second", "action":"second.html"});
nav.add({"text":"third", "action":"third.html"});
nav.actionBase(self.page().pathBase());
nav.value(self.page().path());
return nav.convert();
class RubyOracleDs < QService
def self.getTableData()
return self.get("SELECT a, b, c FROM ".self.prefix()."qtable WHERE d = 1 ORDER BY a, b DESC");
end
end
{
"qform": "",
"name": "form",
"label": "Form for Qedy",
"add": [,
{"qelem": "text", "name": "email"},
{"qelem": "button", "action": "formSubmit"},
]
}
fun QList_Xml(list: QList): String {
val sb = StringBuilder()
sb.append("<").append(qlist.name()).append(">")
// ...
sb.append("</").append(qlist.name()).append(">")
return sb.toString();
}
func swiftMod(args: Dict) -> String {
let str = "It works!"
return str
}
class NodeHttpDs extends QService
def self.getTableData()
return self.get("SELECT a, b, c FROM ".self.prefix()."table WHERE c = 1 ORDER BY a, b DESC");
end
end
class FormInTS extends QModule
{
public form(Dict args): string
{
var frm = new QForm("form");
frm.heading("Form in TypeScript");
frm.add(new QElem(ElemType.text, "email", "E-mail", "", 10));
frm.add((new QElem(ElemType.button)).action(formSubmit));
return frm.convert();
}
function formSubmit() { ... }
}
qview:page heading:Module in Que
#1.add Lorem ipsum dolor sit amet
qform:search
#3.add:text
#3.add:button
#1.add #3
#1.convert html page
fn rustmssqlds(x: Dict) -> string
{
def self.getTableData()
return self.get("SELECT a, b, c FROM ".self.prefix()."table WHERE c = 1 ORDER BY a, b DESC");
}
func QList_Json(list QList) string
{
var buffer bytes.Buffer
buffer.WriteString("{")
// ...
buffer.WriteString("}")
return buffer.String();
}
return (
<QForm label="Form for Qedy" action={submitAction}>
<QElemText name="name" label="Name" />
<QElemEmail name="email" label="E-mail" />
<QElemButton text="Validate" action={() => true} />
<QElem elem="button" text="Submit" />
</QForm>
)
function NavInLua(args)
local nav = QList:create()
nav.data(this.ds().nav()); // Load data from e.g. database
nav.actionBase(this.page().pathBase());
nav.value(this.page().path());
return nav:convert()
end
CREATE TABLE `p` (
`p` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'Primary Key (ID)',
`pp` INT(10) UNSIGNED NOT NULL COMMENT 'Entity (p.p of a parent Particle)',
`pt` INT(10) UNSIGNED NOT NULL COMMENT 'Type, Category or Classification (t.t)',
`pv` VARCHAR(200) NULL DEFAULT NULL COMMENT 'Value' COLLATE 'utf8mb4_unicode_ci',
`pr` INT(10) UNSIGNED NULL DEFAULT NULL COMMENT 'Relation (p.p of a foreign Particle)',
`ps` INT(10) NOT NULL DEFAULT '0' COMMENT 'Sort order, significance',
PRIMARY KEY (`p`),
INDEX `pt` (`pt`),
INDEX `pp` (`pp`),
INDEX `pr` (`pr`)
)
CHARSET=utf8mb4 COLLATE='utf8mb4_unicode_ci';
{
"p": 24,
"pp": 24,
"pt": 7,
"pv": "QetriX",
"ps": 999
}
You can get source code for different languages on GitHub.