Forgo | Forgo JS

Forgo Logo

Forgo is a 4KB library that makes it super easy to create modern web apps using JSX (like React).

Unlike React, there are very few framework specific patterns and lingo to learn. Everything you already know about DOM APIs and JavaScript will easily carry over.

A Forgo Component is a function that returns an object with a render() function. The render function is called for the first render, and then subsequently for each rerender.

import { rerender } from "forgo";
return <div>{seconds} secs have elapsed...</div>;

Mounting the Component#

Use the mount() function once your document has loaded.

import { mount } from "forgo";
window.addEventListener("load", () => {
mount(<SimpleTimer />, document.getElementById("root"));

Child Components and Passing Props#

That works just as you'd have seen in React.

<Greeter firstName="Jeswin" />
<Greeter firstName="Kai" />
function Greeter(props) {
return <div>Hello {props.firstName}</div>;

Reading Form Input Elements#

You can read form input element values with regular DOM APIs.

There's a small hurdle though - how do we get a reference to the actual DOM element? That's where the ref attribute comes in. An object referenced by the ref attribute in an element's markup will have its value property set to the actual DOM element.

Better explained with an example:

function Component(props) {
const inputElement = myInputRef.value;
<input type="text" ref={myInputRef} />
<button onclick={onClick}>Click me!</button>


When a component is unmounted, Forgo will invoke the unmount() function if defined for a component. This is of course, totally optional.

function Greeter(props) {
return <div>Hello {props.firstName}</div>;
console.log("Got unloaded.");

Recap with a complete example#

Finally, let's do a recap with a more complete example. Let's make a Todo List app in TypeScript.

There will be three components:

  1. TodoList (the main component)
  2. TodoListItem
  3. AddTodo

Here's the TodoList, which hosts the other two components.

function TodoList(props: TodoListProps) {
let todos: string[] = [];
render(props: TodoListProps, args: ForgoRenderArgs) {
function onTodoAdd(text: string) {
<TodoListItem text={t} />
<AddTodo onAdd={onTodoAdd} />

Here's the TodoListItem component, which simply displays a Todo.

type TodoListItemProps = {
function TodoListItem(props: TodoListItemProps) {
return <li>{props.text}</li>;

And here's the AddTodo component. It takes an onAdd function from the parent, which gets called whenever a new todo is added.

onAdd: (text: string) => void;
function AddTodo(props: AddTodoProps) {
const input: { value?: HTMLInputElement } = {};
const inputEl = input.value;
function onKeyPress(e: KeyboardEvent) {
<input onkeypress={onKeyPress} type="text" ref={input} />
<button onclick={saveTodo}>Add me!</button>

That's all. Mount it, and we're ready to go.

window.addEventListener("load", () => {
mount(<TodoList />, document.getElementById("root"));


Forgo uses the latest JSX createElement factory changes, so you might need to enable this with Babel. More details here:

For your babel config:

"throwIfNamespace": false,

If you're using TypeScript, add the following lines to your tsconfig.json file.

"jsxImportSource": "forgo"

Getting Help#

You can reach out to me via twitter or email. If you find issues, please file a bug on Github.