How I created another JS framework

Many may scoff at the thought of launching yet another JavaScript framework, given the many proven solutions that already exist. Why start creating something new?

Let me tell my personal story about what prompted me to develop this JavaScript framework.

Let's start with history

All jokes aside, I can't call myself a JavaScript expert, but let me tell you a little about my experience so you can better understand my frustration with web frontend development. I've worked with Angular version 1 in the past, and currently use Vue primarily and occasionally resort to jQuery. Faced with three specific and painful development situations, I decided to try experimenting with the TiniJS framework.

Problem #1: Designing high-quality user interface (UI/UX) is difficult, demanding, and time-consuming.

In the early 2010s, websites could be broadly divided into two types: some were heavy on text, links, and barely visible images, while others were heavy on graphical elements such as GIF animations, Flash backgrounds, and colorful cursors.

There is a widespread belief that back-end development is more difficult than front-end. At first glance this may seem true, but this is not always the case. I won't judge, because with basic knowledge of HTML and CSS you can actually create a simple static website without any difficulty. However, developing a high-quality user interface (UI/UX) will require significantly more effort. You need to have competencies in many areas, and this is not an easy task!

Problem #2: CSS frameworks are limited in functionality and often inefficient to customize.

In response to the complexity of developing user interfaces, developers began creating CSS frameworks to simplify the process. Bootstrap has become one of the pioneers in this area, along with such popular frameworks as Foundation, Semantic UI, Bulma, Skeleton and Pure CSS. Undoubtedly, these CSS frameworks make a significant contribution in making it easier for us to develop attractive interfaces faster. However, they also have their limitations.

One of the main problems is that, despite the availability of tools for personalizing styles, the overall customization process can be quite labor-intensive and not always easy to reuse.

The second problem concerns the lack of built-in functionality. These frameworks mostly offer only CSS, although they do include some functionality, often implemented using jQuery plugins. In most development scenarios, you will still need to add custom JavaScript to enable certain features.

Problem #3: JavaScript frameworks can sometimes be overly complex and illogically repetitive.

The entry into the modern era of web development has brought JavaScript frameworks into the mainstream. However, the problem is excessive diversity, which is both an advantage and a disadvantage. They offer superior capabilities but often suffer from a lack of interoperability; it is impossible to easily transfer part of the code from one framework to another. In particular, developing a user interface using separate packages specific to different frameworks is a complex task.

Whenever I start a new project or work related to front-end development, I am acutely aware of the problem of its fragmentation. It seems like an integral part of this industry that can't be gotten rid of, doesn't it? Don't misunderstand me, I'm not against using frameworks; I'm a big believer in choosing solutions based on your needs, so if something works for you, go ahead and use it. However, I still wonder if there is a way to somehow combine or at least bridge this gap in front-end development experience?

Introducing TiniJS

This is why I spend time experimenting with the TiniJS framework. It is a toolkit for developing web, desktop and mobile applications, which is based on the use of native web components and is supported by the Lit library. I would like to thank the Lit team for their wonderful product that makes it easier for us to work with standard web components.

The goal of TiniJS is to provide standardization, compactness and versatility. It cannot be a direct analogue of other frameworks and meta-frameworks, but, nevertheless, it provides similar functionality with significant differences. TiniJS can serve as both an alternative and a complement to other frameworks. It can be used to create a variety of application types, from landing pages and single page applications (SPA) to progressive web applications (PWA), desktop and mobile applications. From a functionality point of view, anything that works in JavaScript should also work perfectly in TiniJS applications.

This was a brief overview of the multi-part toolkit that TiniJS provides.

Please note that not all components of the framework are available at this time. The project is in the early stages of development, and many elements that were previously only prototypes are now actively being brought to working condition. The road map can be found at link.

Core

At its core, TiniJS provides a standard project structure with a streamlined development process. There are folders for organizing materials, a local server for development, and when distributing you can choose Vite, Parcel or Webpack for creating products.

The core also includes: a router for navigation between pages, simple storage for global state management, PWA support.

You can try the example project(photo gallery app):

UI

TiniJS includes a specialized UI library that aims to provide a wide range of commonly used components, blocks, and even full page templates. The components are designed according to a unique architecture as custom elements, which allows them to be used not only in the context of TiniJS, but also in combination with other frameworks or even independently of them.

TiniJS makes it easy to work with reusable components by making it easy to pass props directly into custom element tags. Customizing components can be done through props, using CSS::part(), custom themes, or even by cloning the original component for further modifications.

The components are designed in such a way that they can be adapted to almost any design system with minimal effort thanks to a powerful theming system. Here are the basic principles of this system:

  • Components are created for one-time use and do not contain specific styles.

  • Themes are structured into “families” (design systems), each of which defines its own basic stylistic characteristics – for example, Bootstrap, Material, Fluent, Spectrum and others.

  • Based on the base characteristics, each family offers different style options called “skins”. So, in the Bootstrap family there can be light and dark skins, etc.

Given this concept, applications can be themed as follows:

  • One theme family – this is suitable for 80-90% of all modern web applications that use one specific style corresponding to one theme family in TiniJS.

  • One theme family with multiple skins – a typical use case is light and dark theme modes corresponding to one TiniJS theme family with multiple skins from the same family.

  • Multiple theme families – Highly customized applications can use multiple theme families with one or more skins for each, applying a specific theme depending on the user's preferences.

A more detailed description of how to use the user interface will be available at TiniJS official website. At the moment you can also check out the experimental versionto see the concept in action.

Web App Pages, Progressive Web Apps (PWAs), and Hybrid Desktop/Mobile Apps

By default, a TiniJS-based application is a single page application (SPA), which is compact and fast to load, and can be deployed as a standard web application. However, TiniJS provides the flexibility to transform your project into different types of applications:

  • A Progressive Web Application (PWA) can be created with a single command in the CLI (feature coming soon).

  • Hybrid desktop and mobile applications can be developed using Tauri 2.0 or similar tools (instructions will be provided).

Static and server application modes

Applications built using TiniJS can function as static web applications, allowing them to run efficiently without depending on a server or database, regardless of their size. In this case, you can use SaaS solutions to meet your backend needs. I'm also working on a content management system @tinijs/content, a file-based platform that simplifies the administration of a variety of content. Plans also include creating a system for generating static sites (SSG) or pre-rendering them.

If server-side task processing is required, an additional Nitro server can be used for back-end routes/APIs and other back-end functions. This will allow you to handle backend tasks and serve the web application from a Node server rather than from static hosting. Given the limited development capabilities, Server Side Rendering (SSR) may not be supported in the first version. Instead, a semi-SSR implementation is being considered, in which the server would serve SPA for users and provide a minimal amount of server-rendered content to search engines.

Features and modular structure

Because TiniJS is built on standard web technologies, you can be sure that most of the libraries and features supported by browsers will be compatible with TiniJS. This eliminates many of the functionality issues found in other frameworks. Moreover, you can even integrate other frameworks inside your TiniJS application, for example by running and attaching a Vue application to an element on a TiniJS page.

TiniJS's modular architecture allows individual modules to interact with the application's workflow, thus facilitating more efficient development.

Tools

The official command line tool (CLI) TiniJS offers a number of convenient commands to make working with your application easier:

  • new – creating a new project based on templates;

  • dev – launching a local server for development;

  • build – compilation of the project for production;

  • preview – preview of the assembly before publication;

  • generate – generation of components, pages, utilities, etc.

The CLI is versatile enough to be used in a variety of projects, not limited to TiniJS. With an extensible architecture, you can add new commands for specialized automation tasks. Official extensions such as ui (from directory @tinijs/ui) for user interface tasks or content (from @tinijs/content) for working with content, demonstrate additional capabilities of the tool. You can also create your own CLI extensions for private or shared use.

Enough theory, it's time to start practicing!

Beginning of work

Tini, pronounced “Tí nị” in Vietnamese, gently conveys the meaning of something very small and cute.

To quickly start a project using TiniJS, you can use CLIto initialize the template.

npx @tinijs/cli@latest new my-app -l

Running the above command will create an application using the Bare template. In the future, I plan to offer several options for starting templates. You can also create your own templates and share them with the community or use them for personal projects. The following templates are currently available:

  • Bare (default) – represents the minimal structure of a TiniJS application.

  • Blank (-t blank) – includes router, state management system, meta tags and theming Bootstrap.

After creating the project, we can start the development server with the command npm run dev. Development can begin by modifying the file ./app/app.ts, which is the root component of your application. To learn more about working with custom elements through Lit, you can visit Lit components. Although there are certain differences between LitElement And TiniComponentit is possible to make changes to static styles and method render() in the usual way.

To build a ready-made distribution, use the command npm run buildand to preview the assembled version – npm run preview. Then we can expand the contents of the folder .output on any static hosting.

To understand how TiniJS works, you can check out the example task list application:

And here with the home page:


Thanks, and have fun coding!

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *