https://github.com/mohammedhrima/urajs
Frontend framework built with JavaScript/TypeScript
https://github.com/mohammedhrima/urajs
framework front-end frontend javascript open-source typescript
Last synced: 9 months ago
JSON representation
Frontend framework built with JavaScript/TypeScript
- Host: GitHub
- URL: https://github.com/mohammedhrima/urajs
- Owner: mohammedhrima
- License: mit
- Created: 2024-06-09T02:25:48.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-11-28T17:18:35.000Z (over 1 year ago)
- Last Synced: 2024-12-02T09:27:42.110Z (over 1 year ago)
- Topics: framework, front-end, frontend, javascript, open-source, typescript
- Language: JavaScript
- Homepage:
- Size: 104 MB
- Stars: 29
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
**UraJS** is a lightweight single-page application (SPA) framework designed to make building interactive and dynamic web applications intuitive and efficient.
Inspired by the simplicity of **React**, the directory-based routing of **Next.js**, UraJS introduces its own take on SPA development. Its directory-based routing system automatically generates routes from the file structure, streamlining navigation setup for developers.
With built-in support for **live reloading**, **state-driven UI updates**.
## Summary
- [Get Started](#get-started)
- [Generate Route](#generate-component-or-route)
- [Example Generated JSX](#example-generated-jsx)
- [Folders Structure](#folders-structure)
- [Configuration](#configuration)
- [Navigate between routes](#navigate-between-routes)
- [Navigate with Parameters](#navigate-with-parameters)
- [Tailwind](#tailwind)
- [Conditions `//`](#conditions)
- [Loops ``](#loops)
- [Component Composition](#component-composition)
- [Deploy using Docker](#deploy-using-docker)
## Get Started
To get started with **UraJS**, follow these simple steps:
1. **Clone the repository**:
```bash
git clone https://github.com/mohammedhrima/UraJS
```
2. **Navigate to the project directory**:
```bash
cd UraJS
```
3. **Install the dependencies**:
```bash
npm install
```
4. **Start the development server**:
```bash
npm start
```
5. **Open your browser** and visit http://localhost:17000 to see the app running.
+ you should see something like this
6. **all commands**:
```bash
npm start #start server
```
```bash
npm run clear #clear outfile
```
```bash
npm run route #create route
```
```bash
npm run comp #create component
```
```bash
npm run build #to build
```
```bash
npm run config #change configuration
```
## Generate Route
To generate routes automatically, you can use the following commands:
- To generate a **basic route and its CSS/SCSS file if neede**, run:
```bash
npm run route /helloworld
```
+ This will create
`pages/helloworld/helloworld.[jsx|tsx]` mapped to the /helloworld route.
`pages/helloworld/helloworld.[css|scss]` for styling the route.
After generating the route and its styles, visit the route in the browser by navigating to the corresponding URL `http://localhost:17000/helloworld`
- To generate a **nested route and its SCSS file**, run:
```bash
npm run route /helloworld/again
```
## Example Generated JSX
+ Component:
```js
import Ura from 'ura';
function Component() {
const [render, State] = Ura.init(); // Initialize Ura and state management
const [getter, setter] = State(0); // Declare a state with an initial value of 0
return render(() => (
Hello from the Component component!
setter(getter() + 1)}>
Click me [{getter()}]
));
}
export default Component;
```
+ Route: Route tag should have `` so the can be viewed
```js
function Route() {
document.title = "Route Page";
const [render, State] = Ura.init();
const [count, setCount] = State(0);
const [darkMode, setDarkMode] = State(true);
return render(() => (
UraJS
GitHub
setDarkMode(!darkMode())}>
{darkMode() ? 'Light Mode' : 'Dark Mode'}
Welcome to UraJS
Lightweight. Reactive. Yours.
setCount(count() + 1)}>
Click me [{count()}]
Built with 💙 using UraJS
));
}
export default Route;
```
#### Explanation of the Code:
1. State:
- used to updated the view wherever the value change: `const [getter, setter] = State(initialValue); `
- componenet can hold multiple states
- essential for updating the view weh state change
2. Rendering the Component:
+ `return render(() => ( ... ))`: saves JSX component for future reconciliation.
3. Event Handling:
+ ` setter(getter() + 1)}>`: onlick state change
+ In UraJS, event names should be written in lowercase. This is the standard convention for handling events in JavaScript.
+ For example:
+ `onclick` for mouse clicks.
+ `onchange` for input changes.
+ `onkeyup` for key presses.
For a complete list of event names, check W3Schools JavaScript Events (https://www.w3schools.com/jsref/obj_events.asp)
4. `` reference to the `` in ./src/index.html
## Folders structure:
```
UraJS/
├── out/ # Production-ready transpiled JavaScript files
│ └── (All framework and app code transpiled to vanilla JS)
│
├── scripts/ # scripts used by the framework.
│
├── src/
│ ├── assets/ # Static assets
│ │ └── (image.png, ...)
│ │
│ ├── components/ # Reusable UI components
│ │ ├── Button/ # Example component
│ │ │ ├── Button.jsx
│ │ │ └── Button.css
│ │ └── (Other components...)
│ │
│ ├── pages/ # Route-based components
│ │ ├── home/ # Example route: /home
│ │ │ ├── home.jsx # Route component
│ │ │ └── home.css # Route-specific styles
│ │ │
│ │ ├── main.js # Application entry point
│ │ ├── main.scss # Global styles/variables
│ │ └── tailwind.css # Tailwind imports (if enabled)
│ │
│ ├── services/ # Business logic/services
│ │ ├── api.jsx # API service layer
│ │ └── events.js # Event bus/service (in developement)
│ │
│ └── ura/ # Framework frontend code
│
├── tailwind.config.js # Tailwind CSS configuration
├── ura.config.js # Framework configuration
├── tsconfig.json # TypeScript configuration
└── package.json # Project dependencies and scripts
```
## Configuration
+ The `ura.config.js` file allows you to customize various settings for your project
+ Default config:
```js
typescript: "disable"
dirRouting: "enable"
defaultRoute: "home"
tailwind: "disable"
scss: "disable"
css: "enable"
port: 17000
```
+ to change it: run
```bash
npm run config #change configuration
```
+ you will get a validation messages like this
## Navigate between routes
```bash
npm run route /home
npm run route /about
npm run comp /navbar
```
```js
// components/Navbar.jsx
import Ura from 'ura';
function Navbar() {
const [render, State] = Ura.init();
return render(() => (
));
}
export default Navbar;
```
**Explanation of the navigate Hook:**
+ `Ura.navigate` is a built-in function in UraJS that programmatically changes the current route of the app. When you call this function, it will update the URL and load the corresponding component.
### Adding the Navbar to the Home Page
Once the `Navbar` component is created, you can include it in your `home` page component. For instance:
```js
// pages/home/home.jsx
import Ura from 'ura';
import Navbar from '../../components/Navbar.js';
function Home() {
const [render, State] = Ura.init();
return render(() => (
Welcome to the Home Page!
));
}
export default Home;
```
## Navigate with Parameters
```bash
npm run route /home
npm run route /user
npm run comp /navbar
```
This component uses Ura.navigate to navigate to a new page (`/user`) and passes the `name` and `email` parameters.
```js
import Ura from 'ura';
function Home() {
const [render, State] = Ura.init();
return render(() => (
Welcome to the Home Page!
Ura.navigate("/user", { name: "John Doe", email: "john.doe@example.com" })}>
Show Details
));
}
export default Home;
```
#### Component That Receives and Visualizes the Parameters
This component receives the name and email parameters from the navigation and displays them.
```js
import Ura from 'ura';
function User() {
const { name, email } = Ura.getParams();
const [render, State] = Ura.init();
return render(() => (
User Name: {name}
Email: {email}
));
}
export default user;
```
## Tailwind
+ make sure to enbale the tailwind in config to see the change
```js
import Ura from "ura"
function Button() {
const [render, State] = Ura.init();
return render(() => (
Click Me
));
}
```
## Conditions:
- `ura-if`, `ura-elif`, `ura-else`
- you can use them as tags ``, ``, ``
- or you can use as attributes
```js
import Ura from "ura";
function WeatherDisplay() {
const [render, State] = Ura.init();
const [getTemp, setTemp] = State(25); // Default temperature
const [isRaining, setIsRaining] = State(false);
return render(() => (
Weather Conditions
{/* Tag syntax */}
30}>
{/* Attribute syntax */}
{/* Shorthand if statement (ternary) */}
Current temperature: {getTemp()}°C -
{getTemp() > 20 ? " Warm" : " Cool"}
{/* Controls to demo dynamic changes */}
setTemp(getTemp() + 5)}>Increase Temp
setTemp(getTemp() - 5)}>Decrease Temp
setIsRaining(!isRaining())}>
Toggle Rain
));
}
export default WeatherDisplay;
```
## Loops:
- `` tag can be treated as any tag you can style it, add className etc...
```js
function Card() {
const [render, State] = Ura.init();
const [getItems, setItems] = State(["Milk", "Eggs", "Bread", "Fruits"]);
return render(() => (
Grocery Items
{/* Tag syntax with tag won't be shown in the view*/}
{(item, index) => (
{index + 1}. {item}
setItems(getItems().filter((_, i) => i !== index))}>
Remove
)}
{/* ura-loop as attribute div tag will be shown in the view even if the array is empty */}
{(item, index) => (
{index + 1}. {item}
setItems(getItems().filter((_, i) => i !== index))}>
Remove
)}
{/* use map method */}
{getItems().map((item, index) => (
{index + 1}. {item}
setItems(getItems().filter((_, i) => i !== index))}>
Remove
))}
setItems([...getItems(), "New Item"])}>
Add Item
));
}
```
## Component Composition
+ example card component
```js
import Ura from 'ura';
function Card(props, children) {
const [render] = Ura.init();
return render(() => (
{props.title}
{children}
));
}
export default Card;
```
```js
import Ura from 'ura';
import Card from '../../components/Card.js';
function Dashboard() {
const [render] = Ura.init();
return render(() => (
Name: John Doe
Email: john@example.com
- Posts: 34
- Followers: 120
));
}
export default Dashboard;
```
## Deploy using docker
1. Build the Project
+ To build the project and generate the necessary Docker configuration files, run the following command:
```bash
npm run build
```
This command will use Nginx to serve your static files and generate a docker directory with the following structure:
```
docker/
├── app/ # Contains all transpiled files (e.g., JavaScript, CSS, etc.)
├── nginx/ # Contains the nginx configuration file
│ └── nginx.conf
├── Dockerfile # Dockerfile to build the application container
├── docker-compose.yml # Docker Compose file to set up and run the container
└── Makefile # Makefile to run Docker container
```
2. Build and Run the Container
+ After running npm run build, navigate to the docker directory:
```bash
cd docker
```
+ To start the Docker container, run:
```bash
make
```
3. Stop the Container
```bash
make down
```
4. Clean Up Volumes and Remove Docker Images
```
make clean
```
5. Check Nginx Configuration
+ The Nginx configuration is in docker/nginx/nginx.conf. It serves the transpiled files
+ Check the port in nginx.conf (e.g., listen 17000). The port is automatically selected during the build process by choosing the available one.
+ After starting the container, open your browser and go to:
```
http://localhost:17000
```