Build Modern Web Apps just with JSON and JS
webJSON is a Node.js based framework to build modern dynamic and static web applications.
It's basically plain JSON with a special syntax which is parsed and converted to browser supported codes on runtime. Its simplicity and ease enables you to easily create and run a web application.
webJSON is based on NodeJS. You can create a server and run with only 5-6 lines of JSON. webJSON has its own CLI and file extension wjson
. The power of webJSON can be realized better in dynamic app development.
Make sure you have Node latest version installed. Install it using npm
or yarn
npm install webjson -g
yarn add webjson -g
Once you have installed the package, you can start coding. Create an index.wjson
file or whatever you name it. Now put the following
[
{
"type":"server",
"params": {
"port": 3000
}
}
]
This minimal amount of code is required to run a Server. Now navigate to the root folder and run
wjson run index.wjson //your file name
It should start a server in the specified port. By default, it will show Cannot GET /
. You can give it a visit to be sure.
As I am a student, I haven't been able to add enough support yet. I am actively developing and bringing more support for the basic things. Basic structure and code base is already built.
Every configuration or component is basically just a JSON object. The page is an array of all these objects. Each object must contain a type element which determines what it will do. Below are the currently supported Object types
- Server
- Page
- Scripts
- Script
- initScript
- StyleSheet
- Text
- Block
- TextInput
- Button
- Image
- Link
- List
NOTE: Make sure you type them in lower case letters.
This is a required object.
Param | Required | Value Type | Description |
---|---|---|---|
name |
No, But Recommended | string |
This is your application name. This is important, if you enable and purge Tailwind. |
port |
Yes | int |
The port of server where your application will be live |
A complete example of server object can be:
{
"type":"server",
"params": {
"port":3000,
"name": "My First WJSON app"
}
}
This is a configuration object for each page. page object acts as the building block of a web app. This is the base component for routing.
Param | Required | Value Type | Description |
---|---|---|---|
method |
Yes | string (get or post ) |
Method of acceptable requests |
route |
Yes (if the page should not be the index file) | string |
Route or Path of Page |
routeParam |
No | string |
Determines the name with which you want to receive URL parameters of the specified route |
title |
No | string |
Title of Page |
child |
Yes | array |
Array of Child Component Objects, which will be shown in the page |
childPath |
No | string |
Local relative path of the file from which you want to receive childs. If you want to get childs from different file, specify this. child value will be ignored if this is added |
A complete example of page object can be:
{
"type":"page",
"method": "get",
"title": "Home",
"child": [
{"type": "text", "value": "Home page"}
]
},
{
"type":"page",
"method": "get",
"title": "About",
"route": "about",
"childPath": "about.wjson"
}
You can load and add javascript code in JSON. As JSON supports only string, number and boolean value, It's difficult to write JS in JSON. So, the solution is to create a separate .js
file and load it in your webJSON page.
Param | Required | Value Type | Description |
---|---|---|---|
name |
Yes | string |
Local Relative path of js File |
A simple example of script object can be:
{
"type":"script",
"value": "scripts.js",
}
There is another object called initScript
or Initial Script This runs as soon as the page is loaded.
{
"type":"initScript",
"value": "getPosts.js",
}
Just like HTML stylesheet import, you can include CSS stylesheet in your page. The setup is similar to Scipts. A simple example of styleSheet object can be:
{
"type":"styleSheet",
"value": "styles.css",
}
This is equivalent to html p
element.
Param | Required | Value Type | Description |
---|---|---|---|
value |
Yes | string |
Text Value. Can be empty, but property must be declared |
id |
No | string |
ID of DOM Element |
style |
No | object or string |
Object, if you add inline styling. If you want to use CSS class or Tailwind class, then put class name(s) as string |
onClick |
No | string |
Function name to be called once Text is clicked |
A complete example of text object can be:
{
"type":"text",
"value": "Example Text",
"params": {
"id": "txt",
"style": {
"fontSize": 20
}
}
}
Take a look at the Style Support list for available style params.
This is equivalent to html div
element. With this, You can do everything that you can do with div. This has a special element called child
, Where you can append child components. Once again, it is an array of objects. Child components are parsed the same way parent components are parsed.
Param | Required | Value Type | Description |
---|---|---|---|
child |
Yes | array |
It can be empty, but must be declared. Array of Component Objects |
id |
No | string |
ID of DOM Element |
style |
No | object or string |
Object, if you add inline styling. If you want to use CSS class or Tailwind class, then put class name(s) as string |
onClick |
No | string |
Function name to be called once Block is clicked |
A complete example of block object can be:
{
"type": "block",
"child": [{ "type": "text", "value": "child Text!"}],
"params": {
"id": "myBlock",
"style": {
"height": 100,
"width": 100,
"backgroundColor": "blue"
}
}
}
This is equivalent to html input
element with type text. More options and params for this will be added soon.
Param | Required | Value Type | Description |
---|---|---|---|
placeHolder |
No | string |
Placeholder for Textinput |
id |
No | string |
ID of DOM Element |
style |
No | object or string |
Object, if you add inline styling. If you want to use CSS class or Tailwind class, then put class name(s) as string |
onTextChanged |
No | string |
Function name to be called once Input Text is changed. This triggers even if text is Pasted. |
multiline |
No | Bool | If text input should allow multiple lines |
{
"type":"textInput",
"params": {
"id": "name",
"style": {
"fontSize": 15
},
"placeHolder": "Write your Name..."
}
}
This is basically nothing but button
element.
Param | Required | Value Type | Description |
---|---|---|---|
value |
Yes | string |
Button Text Value. Can be empty, but property must be declared |
id |
No | string |
ID of DOM Element |
style |
No | object or string |
Object, if you add inline styling. If you want to use CSS class or Tailwind class, then put class name(s) as string |
onClick |
No | string |
Function name to be called once Button is clicked |
More options and params for this will be added soon.
{
"type":"button",
"value": "Click Me!",
"onClick": "alert('it is working...')
}
This is the HTML img
element. More options and params for this will be added soon.
Notice, how you it accepts the image location in the value
option. Height and Width style is not required. Only one special param available now is the lazy
param. If it's true, the image will be lazily loaded.
Param | Required | Value Type | Description |
---|---|---|---|
value |
Yes | string |
Image Source URL |
id |
No | string |
ID of DOM Element |
style |
No | object or string |
Object, if you add inline styling. If you want to use CSS class or Tailwind class, then put class name(s) as string |
onClick |
No | string |
Function name to be called once Image is clicked |
lazy |
No | Bool | If Image should be loaded lazily |
{
"type":"image",
"value": "https://images.unsplash.com/photo-1593642634315-48f5414c3ad9?ixid=MnwxMjA3fDF8MHxlZGl0b3JpYWwtZmVlZHwxfHx8ZW58MHx8fHw%3D&ixlib=rb-1.2.1&auto=format&fit=crop&w=700&q=60",
"params":{
"style": {
"height": 200,
"width": 200
},
"lazy": true
}
}
link
is equivalent to html a
element. In this object, value
is taken as the link text. To add the href
link, you need to pass link
element. Check the following example:
Param | Required | Value Type | Description |
---|---|---|---|
value |
Yes | string |
Text Value |
link |
Yes | string |
Link to redirect. Can be relative path or external uri |
id |
No | string |
ID of DOM Element |
style |
No | object or string |
Object, if you add inline styling. If you want to use CSS class or Tailwind class, then put class name(s) as string |
{
"type":"link",
"value": "Click Me!",
"link": "https://github.com/MadCoderme/webJSON"
}
List
is a useful and easy way to render a list of data with just one object. It can handle large amount of data with ease.
List provides two different ways to load and show data.
- Load when page loads
- In this method, all the data will be loaded when the page is being loaded and rendered instantly after page is loaded. This method is useful if you a small amount of data or a directly an object without fetching from external API. But, if you have a large amount of data, this method will badly slow down your page.
- Load after page is loaded
- This method is useful if you need to fetch data from API. This will keep performance and speed good and fetch data once page is loaded. You can add a
loader
to show until data is fetched.
- This method is useful if you need to fetch data from API. This will keep performance and speed good and fetch data once page is loaded. You can add a
Param | Required | Value Type | Description |
---|---|---|---|
data |
Yes | string |
array |
value |
Yes | array |
How each element will be rendered. Note, how $ is used to declare the looping variable. You are receiving the id property from each object using this syntax. It must be used inside a string and automatically will be converted to actual property. Array of Objects |
id |
Yes / No | string |
Required param if lazyLoad is true. In that case, without this, data won't be rendered |
style |
No | object or string |
Object, if you add inline styling. If you want to use CSS class or Tailwind class, then put class name(s) as string |
lazyLoad |
No | bool |
If the data should be fetched and rendered lazily. This is the configuration param to use second method |
loader |
No | array |
Displays a loading element while the data is being fetched. This is recommended to add. loader is once again an array of webJSON component objects. Can be multple objects. |
Check the following example of the first method
:
{
"type":"list",
"data": [{"id": 123}, {"id": 1234}, {"id": 12345}],
"value": [{
"type": "text",
"value": "$id"
}]
}
If you put an API link here, as the method works, page will keep loading until data is received.
It’s not recommended anyway. Use the second method
for those type of list:
{
"type":"list",
"data": "https://random-data-api.com/api/color/random_color?size=10",
"value": [{
"type": "block",
"child": [],
"params": {
"style": {
"backgroundColor": "$hex_value",
"height": 100,
"width": 100
}
}
}],
"params": {
"id": "colorList",
"lazyLoad": true
}
}
If you run the above example with lazyLoad
param true
, the page will quickly load. Then, all the data will be fetched and rendered lazily.
To add a loader, simply pass the loader
param. Check the example below:
{
"type":"list",
"data": "https://random-data-api.com/api/color/random_color?size=10",
"value": [{
"type": "text",
"value": "$color_name",
"params": {
"style": {
"color": "$hex_value"
}
}
}],
"params": {
"id": "colorList",
"lazyLoad": true,
"loader": [{
"type": "text",
"value": "Loading..."
}]
}
}
Take a look at the supported style params. More will be added soon. NOTE: You can use all the css params that has no conflict with the following style(no hyphens)
- color
- backgroundColor
- height
- width
- margin
- padding
- fontSize
- fontFamily
- position
- top
- bottom
- left
- right
- border
If you add a Stylesheet or enable Tailwind, you need to replace style array
with a string
. For example,
"style": "myClass m-10 bg-blue-200"
webJSON provides some basic but important functions and API.
Receiving server request information is too easy with webJSON. You can receive and work with query parameters of Get
requests in the following way.
//Request: http://localhost:3000/?id=12345&name=David
//Receive "id" and "name" param:
{
"type":"text",
"value": "Your Id is &id and Name is &name"
}
Just put &
before the name of the query param you want to work with. You can even use this functionality in JS scripts.
function giveAlert(){
if('&id' == "1234") {
alert('Provided id: &id is valid')
}
}
This method will also work with post
request body. Make sure the request body is in json
format.
You can receive URL parameters of get
request by putting && before the param name. For example, if the url is: http://localhost:3000/post/123, then you can receive 123 like below:
{
"value": "url param id is &&id"
}
Check Page object to understand how to configure URL params.
Routing or Navigation is one of the most important part of every web application. webJSON makes it very easy to setup and perform routing.
As mentioned earlier, every page object is indeed a Page. To navigate form one page to another, you can use the built in function of webJSON
{
"type": "button",
"value": "About",
"onClick": "navigate('about')"
}
Basically, you need to pass the route
name of the page, that you want to navigate to. You can pass extra data for example URL Parameters and Query Parameters too.
To make development easier and faster, webJSON comes with Tailwind CSS in the box. By default, it's not enabled. To enable and use Tailwind CSS classes, add enableTailwind
param to page object.
{
"type":"page",
"method": "get",
"title": "Home",
"childPath": "home.wjson",
"params": {
"enableTailwind": true
}
}
You can now use all Tailwind classes. For example,
{
"type":"text",
"value": "Example Tailwind Text",
"params": {
"id": "txt",
"style": "text-lg font-semibold"
}
}
Minified Tailwind CSS is a huge 3000kb+ file which will dramatically increase your loading time and decrease your Lighthouse score. The solution is to prevent unused CSS codes from loading.
webJSON provides a simple solution to this problem. You can run the following command
wjson purgeTailwind index.wjson
This will analyze your wjson file and configure your project by creating a custom css file with the used classes only. You need to run this whenever you update your code. Or, you may run it only once before deploying app to production.
Basic Conditional rendering has been made a lot easier in webJSON. You can pass a special condition element to every object except server. You need to follow a special syntax to write conditions. Each condition is an array of 3 elements.
"condition": ["&id", "==", "abcd"],
Yes, you can use those special functionalities of receiving inputs too. Only strings and Integers are supported to be passed as 1st and 3rd element.
These conditional operators are supported right now:
- "=="
- "!="
- ">"
- "<"
You can compare these to conditional if statements but more easier to apply. If the condition is true, then the object will be rendered. Else it won't be rendered.
I am actively developing this project. If you like it, please help not with Donation, but with Contribution
This project is not ready and perfect yet for big projects. Please help to grow this faster. If you make a big change, Open an issue first. If you make a small change, open a pull request.
Please let me know your suggestions about this project.
Thanks!