Hey guys, hopefully you are doing well, today is an introduction to get started with Grandjs the promising nodejs framework! What is Grandjs? Grandjs is a javascript server side framework for building scalable web applications with solid architecture in nodejs What is the difference between grandjs and express? As anyone live in this planet hears every day about a new javascript framework and library and don't know why this happens or what is the difference between these new frameworks and the current frameworks!! Expressjs is amazing and great framework, it have been maintaining nodejs development applications for many and many years, it gives you the ability to create, build anything you want because it's simplicity! One concern on express, it's doesn't developed for javascript ES6+ features, it's a great choice for any type of applications but it doesn't have a new vision based on the current javascript state Why Grandjs? Grandjs is build on typescript to get the benefits of typescript types, decorators and ES6+ features such as classes and so on However Grandjs is built upon typescript, it's available for usage also in javascript without any need for compilation or code transpiling. Grandjs gives you the ability to create solid routing architecture based on javascript classes, it gives you the ability to write one router which can be extended for different purposes and uses, it also gives you the ability to specify middle wares in an organized way for each route, router or apply global middle wares over the whole app. These routing features gives you a full control over your routes to customize and consume your routes in different ways for different purposes When it comes to rendering dynamic pages, you may find yourself puzzled to chose one good template engine contains everything you need, you may choose handlebars, ejs, pug or any other template engine, but have you asked yourself why a template engine in a language has template literals and JSX like javascript? Javascript is a great language in itself, it contains most of things you need to build a full web application just in javascript, one of these amazing features is jsx syntax which allows you writing HTML like markup inside javascript code, which gives you the ability to do any operation on this markup, render data you want, easy to access data and many many other operations! Grandjs decided to use JSX syntax to make server side rendering, so instead of using normal template engine, we need to get the power of javascript inside our HTML markups, so using JSX is the best choice! Grandjs also doesn't just includes it's own architecture and methodology, it has an API similar to express js like render method which is renders the components, request object, response object and middle ware injecting. Also Grandjs accepts many expressjs packages to be used inside it, it accepts using body-parser for parsing request body, cookie-parser for parsing cookies, sessions, morgan, express-fileupload and many other packages that can be used by injecting them inside the app by using this function app.use() However using these middlewares, Grandjs includes also a built in methods such as native request body parsing and fileupload without a nead to middlewares! One of the amazing parts in grandjs, it gives you another helpers such as working with directories and files based on fs module, data validation, and ciphering methods to hash and secure data How can I start with Grandjs Getting started with grandjs is so easy, you just need to be installed nodejs previously! Create a new Directory, navigate to it and hit the following command in your cmd npm init Now you can install grandjs by the following command npm i grandjs Create a file called index.js as your entry point and require grandjs as the following: {Server} = ( ) const require "grandjs/lib" As you can see above I am requiring server object from grandjs/lib Then we will set some configurations for this server as the following: {Server} = ( ); path = ( ) Server.setConfig({ : , : { : , : path.join(process.env.cwd(), ) } }) const require "grandjs/lib" const require "path" // set config port 3000 staticFolder url "/public" path "/uploads" We have added some configurations to the server such as specify the port that the application will work on and static folder which contains our assets such as client side js files, css files or images The static folder is an object contains two properties: the url that will be resolved to get the requested assets path: which is the local path that will be used to read the requested assets from, this option gives you a powerful feature which allows you to read files from any directory may be outside your project directory and the client will not see where is the actual path of the data, it's good for security Now we will create A directory call views which will be the folder that contains our jsx components, this folder will contain the following components: Header.jsx Body.jsx homePage.jsx UserPage.jsx BasePage.jsx In each component we have to require View which is an object contains some methods to recognize the written component and parse them {View} = ( ) const require "grandjs/lib" The component should be a stateless functional component as the following {View} = ( ); Header = { ( <meta charset="utf-8"/> <title>{pageTitle}</title> </head> const require "grandjs/lib" const ( ) => {pageTitle} return < > head ) } module.exports = Header; If you are familiar with react, you will find the code is too similar to react components, we are rendering some markup language to render the header of the page Note that to export the component you have to use commonjs export syntax which is as the following: .exports = Header module Header.jsx component finally should be something similar to the following: {View} = ( ); Header = { ( <meta charset="utf-8"/> <title>{pageTitle}</title> </head> const require "grandjs/lib" const ( ) => {pageTitle} return < > head ) } module.exports = Header; Body.jsx: This file will contain the html body markup and any data you want to insert at the middle of the rendered html page {View} = ( ); Body = { ( <h1>this is body from Body.jsx file & {props.pageT}</h1> ) } .exports = Body; const require "grandjs/lib" const ( ) => props return < > body {props.children} </ > body module As you can see above, we can pass child items to be rendered inside the component to render dynamic childs, as you can do with react BasePage.jsx: This page page is considered as the page that we will extend or reuse for any other page we want to render, this basepage simply includes the header and body components {View} = ( ); Header = View.importJsx( ); BasePage = { ( <Header pageTitle={props.pageTitle}/> {props.children} </html> const require "grandjs/lib" const "./Header.jsx" const ( ) => props return < = = > html lang "en" dir "ltr" ) } module.exports = BasePage; In Granjs to import a component from another file you cannot import this component normally with require function, instead of that grandjs View provides you a function you can use to import jsx files, this function called View.importJsx. This method takes one argument which is the path of the jsx component. {View} = ( ); Header = View.importJsx( ); const require "grandjs/lib" const "./Header.jsx" Home.jsx: This page will be rendered as the home page, it has a simple html markup as the following: {View} = ( ); BasePage = View.importJsx( ); Body = View.importJsx( ); Home = { ( <Body> <h1>{props.message}</h1> </Body> ) } .exports = Home; const require "grandjs/lib" const "./BasePage.jsx" const "./Body.jsx" const ( ) => props return < = > BasePage pageTitle {props.pageTitle} </ > BasePage module User.jsx: This page contains markup syntax similar to the home page: {View} = ( ); BasePage = View.importJsx( ); Body = View.importJsx( ); User = { ( <Body> <h1>{props.message}</h1> </Body> ) } .exports = User; const require "grandjs/lib" const "./BasePage.jsx" const "./Body.jsx" const ( ) => props return < = > BasePage pageTitle {props.pageTitle} </ > BasePage module As you can see in the two pages home and user, we are passing dynamic data like pageTitle and message, these data will be passed later when we render the components, don't worry just keep reading 😂 Now we will create a directory called routes which will include our routes, inside this directory we will create two files, one called index.js which will contain the main router and the second file will called user.js which will contain the user routes user.js. First require Router class from grandjs {Router} = ( ); const require "grandjs/lib" This Router is a class can be extended or instantiated directly, in this example we will extend this router {Router} = ( ); { } const require "grandjs/lib" class UserRouter extends Router In this router we will add single route which will be with url / to render the user page component. Adding routers in grandjs is something easy as the following: { (props) { (props); .base = .getRouters.push( .getUserPage()); } getUserPage() { { : , : , : { .res.status( ).render(User, { : , : }) } } } } class UserRouter extends Router constructor super this "/user" this this return url "/" method "GET" handler => () return this 200 pageTitle "user page" message "Hello User" Inside router class we have an array called getRouters this array contains all routes inside this router with GET method, the same thing for other methods, each request method as the following: getRouters postRouters deleteRouter putRouters patchRouters The method inside the router class should return an object, this object contains the following properties url method handler This Router has a property called /base which is the main url that all routes inside this router will be resolved to. Now we can export this router {Router, View} = ( ); User = View.importJsx( ); { (props) { (props); .base = .getRouters.push( .getUserPage()); } getUserPage() { { : , : , : { res.status( ).render(User, { : , : }) } } } } .exports = UserRouter; const require "grandjs/lib" const "../views/User.jsx" class UserRouter extends Router constructor super this "/user" this this return url "/user" method "GET" handler ( ) => req, res return 200 pageTitle "user page" message "Hello User" module As you can see, we have imported User Page which will be render when the route /user will be visited res.status( ).render(User, { : , : }) return 200 pageTitle "user page" message "Hello User" This statement inside the route handler sets the status of response as 200 which means that everything is OK and uses a method called render which is method used to render a JSX component. This method takes two parameters, the first one is the component that we need to render, and the second parameter is the data object that we want to pass to the component to be rendered inside the HTML In index.js file we will create a main router {Router, View} = ( ); Home = View.importJsx( ); UserRouter = ( ); { (props) { (props); .base = .getRouters.push( .getHomePage()); .useRouter(UserRouter); } getHomePage() { { : , : , : { .res.status( ).render(Home, { : , : }) } } } } .exports = HomeRouter; const require "grandjs/lib" const "../views/Home.jsx" const require "./user" class HomeRouter extends Router constructor super this "/" this this this return url "/" method "GET" handler => () return this 200 pageTitle "Home Page" message "Hello Home Page" module We have imported the User Router, Home page component and created another router called HomeRouter which will be the main and base router Inside this router we are using function called useRouter which is can be used to append a router inside another router! This way is so good because it allows you to append the parent router global middlewares and other functionality to the child router. In our example we are adding UserRouter as a router inside the HomeRouter In the project entry point which is index.js we will import our needed dependencies and routers as the following: {Server, Router, View} = ( ); View.settings.set( , ); HomeRouter = ( ); const require "grandjs/lib" "views" "./views" const require "./routes/index" As you can see in the part above I have imported Server, Router and view. Note: before Importing any component or router include a component, you have to define something in the view which is the path of the directory that your views components will be exist in, for me the views folder path is ./views View.settings.set( , ); "views" "./views" Now we will instantiate the HomeRouter and build it as the following: router = HomeRouter(); router.build(); // instantiate home router let new // build home router Instantiating the router means start parsing it's properties and routes Build method should be called to complete the router bootstrapping process and make the router ready to be consumed on the fly! Now we will set some configuration related to the folder, these configuration will be the port that the application will work on Server.setConfig({ : }); port 3000 Then initialize the server Server.initServer(); Then initServer method can take a callback function after listening to the port Server.initServer( { .log( ) }); => () console "server is running" As you can see, it's super simple and easy to build extendable routes, rendering components like react but for server side rendering without a need to a template engine! Thanks guys for reading this article, if you have any question don't hesitate to write it, and is the documentation to learn more about this framework, also if you liked this article tell me to make more tutorials about it, thank you. here