DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 966,155 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Cover image for nazca - Introduction tutorial
Q'inti
Q'inti

Posted on

nazca - Introduction tutorial

Nazca is a new GUI programming language. It is based on CSS. If you describe the style (CSS) that has functions (JavaScript) and the ability to define page structure (HTML), you'll get nazca. Another way to imagine it - the syntactic sugar that converts a single UI code into CSS, JavaScript, and HTML.

Let's see how easily we can create web applications with it.

Install and init first nazca project

It is better to install it globally

npm i -g nazca
Enter fullscreen mode Exit fullscreen mode

Now you have a tool installed that can initialize the project for you, compile it and analyze if there are any errors.
Let's create a new project

mkdir firstProject
cd firstProject
nazca init
Enter fullscreen mode Exit fullscreen mode

This creates a new folder, called "firstProject", it adds the default .nazca configuration to it and some folder structure for you. It also creates the default *.nazca file.

You can easily compile it

nazca
Enter fullscreen mode Exit fullscreen mode

Nazca does not serve files. It is up to you what you want to use, will it be the nodeJS app, or simple nginx serving static files - it does not matter. Nazca is just a front-end compiler that takes the sources and converts them to *.css, *.js, and .html for your browser to understand.
For this tutorial, we will use a simple HTTP nodeJS server.

npm i -g http-server
cd www
http-server -c-1
Enter fullscreen mode Exit fullscreen mode

We installed http-server package, which will serve the files, then changed to the output directory (check .nazca settings file) and ran it with the cache living for 1 second.
Open your browser and go to http://localhost:8080, you'll see the compiled default nazca code.

Import existing JS code

The easiest way to do something is to import the module intended to be used on the browser side. I have one useful module just for the sake of the tutorial, but you can import any existing modules you would like. During the compile nazca searches the module you specified in the node_modules directory, puts the script inside the modules directory, and imports it with import of the ES6.

Let's install it first

npm i nazca-logo-3d
Enter fullscreen mode Exit fullscreen mode

You should install it locally for nazca to be able to search node_modules.

Let's modify nazca/index.nazca we created previously.

*import: Logo = nazca-logo-3d;

.html {
    .head {
        .title {
            text: Nazca 3D logo;
        };
    };

    .body {
        constructor: () {
            new Logo(native);
        };
    };
};
Enter fullscreen mode Exit fullscreen mode

Here we have a few elements without the names, but with the defined classes. Nazca has pre-defined classes for all html elements. If you define .head it is compiled as an html element <head></head>.
The body element has constructor() method. This method is executed, when all the elements are loaded (DOMContentLoaded event).
At the beginning of the file, we used import directive. It defines a new global variable, called "Logo", which is imported from the module we installed. In the constructor, the new instance of the Logo is created. Because the code is inside the constructor of the body, to access its properties you don't have to specify this, but use the property instead. All nazca elements have default native property. It allows you to access the native element. It is useful in this case to pass it to the constructor of the module.

Compile it and refresh it in the browser.

Adding the loader

Your program uses the nazca-logo-3d module that loads the models from the web and renders them. What if you have a slow connection and can't load the models quickly? Let's create a loader for it.
Let's imitate the loading process by adding 5s timeout before adding the Logo to the page

Replace contents of nazca/index.nazca with this code

*import: Logo = nazca-logo-3d;

.html {
    .head {
        .title {
            text: Nazca 3D logo;
        };
    };

    .body {
        constructor: () {
            setTimeout(() => {
                new Logo(native);
            }, 5000);
        };

        .div {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%,-50%);
            z-index: -1;

            .div {
                -maxCounter: 45;
                -counter: 0;
                -increment: 1;

                constructor: () {
                    animate();
                };

                -animate: () {
                    counter += increment;

                    if (counter >= maxCounter) {
                        increment = -1;
                    } else if (counter < 0) {
                        increment = 1;
                    }

                    point.left = `${counter}px`;
                    requestAnimationFrame(animate);
                };

                point.div {
                    background-color: #80e780;
                    position: absolute;
                    left: 0;
                    top: 0;
                    width: 1px;
                    height: 1px;
                    box-shadow: 1px 0 10px 3px #2c9d2c;
                };
            };

            .div {
                text: Loading;
                text-transform: uppercase;
                font-family: sans-serif;
                font-size: 10px;
                padding-top: 15px;
            };
        };
    };
};
Enter fullscreen mode Exit fullscreen mode

Nazca has 3 types of accessors. Private properties and methods are accessible only by the instance of the class, where they are declared. Protected can be accessible by the instance of any class extended from that one and the public, accessible by anyone. In nazca they are specified by a special prefix. - means private methods and properties. If no properties are specified, it is public. See full nazca README for more details.

Here we added a new element, called point, so later we can access it in the parent element in the hierarchy. The code in animate() moves it by one pixel every frame, making running animation. All public properties that are named as CSS parameters are treated by the compiler as CSS properties.

Conclusion

In this tutorial I covered a small portion of what nazca can do. Check the project's GitHub page and see the full README to learn more features.

Top comments (2)

Collapse
 
panphora profile image
David Miranda

Hi Q'inti, this is an amazing project and so creative! I love how everything complicated about web dev is simplified into a single syntax. It makes me realize how much effort is wasted on connecting the pieces together and how much debugging time could be saved if there was just a single language for writing web apps.

I'm working on something similar (Remake, check my profile), but taking a different approach of using HTML as the foundational language β€” with the ability to add additional functionality with raw JS. I'd be very interested in talking with you about the future of web dev and web frameworks in general if you want to connect!

Great work and good luck on your project either way!

Collapse
 
qinti profile image
Q'inti Author

Sorry it took me so long reading the documentation. I believe our projects are different. Mine is to treat all elements on the page as an object. The goal was not to write in css-like syntax. The goal of your project is an html templating engine.
Your project is greqt and can find its usage, but I don't like how little control it gives to the developer. For example dev don't have to implement back-end. From one side it is cool and fatens the development, from the other side it is not good as developer don't have full control over the backend and can't modify it's architecture.

Need a better mental model for async/await?

Check out this classic DEV post on the subject.

β­οΈπŸŽ€ JavaScript Visualized: Promises & Async/Await

async await