https://github.com/s15n/ive
An extremely small Web Framework but just as powerful as all the others: Reactive without React.
https://github.com/s15n/ive
framework frontend jsx lightweight typescript
Last synced: 2 months ago
JSON representation
An extremely small Web Framework but just as powerful as all the others: Reactive without React.
- Host: GitHub
- URL: https://github.com/s15n/ive
- Owner: s15n
- License: gpl-3.0
- Created: 2024-02-25T12:51:03.000Z (about 2 years ago)
- Default Branch: main
- Last Pushed: 2024-12-29T09:13:26.000Z (over 1 year ago)
- Last Synced: 2025-03-27T03:51:21.333Z (about 1 year ago)
- Topics: framework, frontend, jsx, lightweight, typescript
- Language: TypeScript
- Homepage:
- Size: 35.2 KB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# IVE
[](https://www.npmjs.com/package/ive-fw)
[](https://www.npmjs.com/package/ive-fw)

IVE /ˈaɪ.viː/ is an extremely lightweight front-end framework best used
alongside Vite and TypeScript.
## Features
- Extremely small and lightweight
- No virtual DOM
- No dependencies
- TypeScript and JSX support
- Really just two functions: `ive.createState` and `ive.watch`
- Convenience functions on top for awaiting promises and routing
## Installation
Create a vite project (creates a new folder with the project name)
```bash
npm init vite
```
Use the following settings:
- Select framework: `vanilla`
- Select variant: `TypeScript`
Install IVE
```bash
npm install ive-fw
```
## Usage
```typescript
import ive from 'ive-fw/ive';
```
You have to add the following to your `tsconfig.json` file:
```jsonc
{
"compilerOptions": {
/* ... */
"jsx": "preserve",
"jsxFactory": "ive._jsx",
"jsxFragmentFactory": "ive._jsxFragment",
/* ... */
}
}
```
And you might need to add this line somewhere in your code (best in a separate `jsx.ts` file)
```typescript
import 'ive-fw/jsx';
```
And you're good to go!
## Example
### Hello, World!
Create a new file `App.tsx` with the following content:
```tsx
import ive from 'ive-fw/ive';
const Hello = ({ name }: { name: string }) => (
Hello, {name}!
);
export default () => (
);
```
Render this component in `main.ts`:
```typescript
import App from './App';
document.body.appendChild(App());
```
### Counter with State
Create a new file `Counter.tsx` with the following content:
```tsx
import ive from 'ive-fw/ive';
const counter = ive.createState(0);
export default ive.watch([counter], ([count]) => (
Counter
{count}
counter.set(count + 1)}>Increment
));
```
This component will be re-rendered every time the `counter` state changes.
Keep in mind that events need to be prefixed with `on:` in ive in order to work.
### Fetching Data (awaiting Promises)
Ive provides a convenience function `ive.wait` to await promises.
Though it really is just a wrapper around `ive.watch`.
Create a new file `Posts.tsx` with the following content:
```tsx
import ive from 'ive-fw/ive';
export default ive.wait(fetch('https://jsonplaceholder.typicode.com/posts').then((response) => response.json()), (posts) => (
Posts
{posts.map((post: any) => (
-
{post.title}
{post.body}
))}
), () => ( // optional loading component
Loading...
), (error) => ( // optional error component
Error
{JSON.stringify(error)}
));
```
### Routing
Ive provides a convenience function `ive.router` to conditionally render components based on the current route.
Again, it really is just a wrapper around `ive.watch`.
Create a new file `Routing.tsx` with the following content:
```tsx
import ive from 'ive-fw/ive';
const Home = () => (
Home
Welcome to the home page!
About
);
const About = () => (
About
Learn more about us!
);
const Greet = ({ name }: { name: string }) => (
Greet
Hello, {name}!
);
export default ive.router("/", {
'/': , // statically rendered
'/about': About, // lazily rendered
'/greet/{name}': Greet, // lazily rendered with parameters
}, () => ( // optional fallback route
404
Page not found!
));
```
You could also use dynamic imports to lazily load components:
```tsx
export default ive.route({
'/greet/{name}': import('./Greet')
});
```