DEV Community

Liu Chenyang
Liu Chenyang

Posted on

[Open source front-end framework]Some middle school students' framework tntjs

We made a runtime frontend framework from scratch


We're an open source team named BugDuck, which is mainly of middle school developers.

In April 2022, we started TNTjs with a sudden thought. At first, we promoted a runtime programming language to the outside world, implemented with pure JavaScript, but later felt unrealistic, so we changed TNTjs to a real-time dynamic fully reactive front-end framework and supports two-way data binding.

Now, we are refactoring TNTjs again. We are about to release tntjs Alpha 0.2.0 in the end of July this year.

So hop on and let me introduce you some core features of TNTjs!

In 0.2.0, you can use dynamic variables by using reactive(), just like in Vuejs. You can use <v data="variableName"> tags to render their data as well:

<v data="x"></v>
Enter fullscreen mode Exit fullscreen mode

And more than that, we wrapped all core functionalities into the TNTApp top-level class. You can use it like follows:

const app = new TNT.TNTApp()
      x: 233333
Enter fullscreen mode Exit fullscreen mode

In TNTjs Alpha 0.2, we're using Virtual DOMs, and it turned out to be much faster than TNTjs Alpha 1.0. For rendering 10000 nodes it will take about 200ms. However - that is still pretty slow and we're currently working on improving the performance.

You can use <t-for> to implement a loop, and you can use <t-if> <t-elif> <t-else> to implement condition rendering.

Here's a kitchen-sink demo of TNTjs:

<!DOCTYPE html>
<html lang="en">

  <meta charset="UTF-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>TNTjs Demo</title>
  <script src="./dist/tnt.min.js"></script>
    .green {
      color: green;

    .red {
      color: red;

  <div id="root">
      <v data="nae"></v>
      Bar: <v data="bar"></v>
      <p :class="(sum % 2 === 0 ? 'green' : 'red')">
        <v data="sum"></v>
      <button onClick="">Plus 1</button>
      <button onClick="foo.push(-1)">Minus 1</button>
      <button onClick="foo.pop()">Pop top</button>
      <button onClick="bar++">Plus bar</button>
      <button onClick="foo[foo.length - 2] += 2">Plus 2</button>
      <t-if cond="sum % 2 === 0"> It's even! </t-if>
      <t-else> It's odd! </t-else>
      <br />
      <t-for data="currentNumber in foo">
        <span onclick="alert(`You clicked: ${currentNumber}`)">
          <t-if cond="currentNumber > 0">
            <v data="`${currentNumber}`"></v>,
            &larr; 0
      <t-if cond="foo.length && foo[foo.length - 1] > 0">
          <v data="`${foo[foo.length - 1]}`"></v>
      <t-get src="./test.json" type="json">
        <v data="name"></v>
  const app = new TNT.TNTApp()
      nae: 114514,
      foo: [],
      bar: 5,
      sum() {
        let sum = 0; => (sum += v));
        return sum;
    .useEffect(() => {
      console.log(`Sum changed: ${data.sum}`);
    .onMounted((app) => {
      console.log("App mounted!");
    .mount(document.getElementById("root")); = [233];

Enter fullscreen mode Exit fullscreen mode

Finally, if you like our framework, please leave us a star on GitHub !

If you have some good ideas about improving TNTjs, please file us an issue or email us at

And at last, any contributions are highly welcomed. If you want to become a contributor, you can fork the repo and submit us a pull request. We will be happy to review it!

Thank you!

Top comments (2)

safouene1 profile image
Safouene Turki

So basically vue js light edition

sheepbox8646 profile image
Liu Chenyang

Yes, but there is a big difference between tntjs and Vue. Vue's components are deeply dependent on Vue. tntjs is committed to native development. One of the biggest drawbacks of scaffolding development is that once the project scales, it will become difficult to maintain. tntjs simplifies native development based on native development and introduces the concept of components