Back

Start with Ultra, the new React web framework

Start with Ultra, the new React web framework

Ultra is a modern streaming React framework buily with Deno that heavily relies on the built-in functionality of your browser. It makes use of ES Modules, Import Maps, and Web Streams in the future. All the while, it supports some of the deviations from the norm that many ordinary people enjoy for whatever reason (JSX and TypeScript). Ultra uses Deno and React and focuses on using web streams and native features within the browser.

Let’s look at some of the reasons you should consider using Ultra for your next project.

  • Permissions module: Ultra has the Deno permission-based security module features to allow you to set permissions for running your applications.
  • Lazy routing: Ultra uses the Wouter a small Hooks-based router for current React and Preact projects to create routes.
  • Suspense data fetching: Ultra uses the Vercel’s SWR with Suspense to allow you to fetch data anywhere in your components.
  • Service Workers: Ultra uses the vanilla Service Workers to serve, cache, and optimize your website
  • Dynamic MDX: Ultra has support for MDX to allow you to generate dynamic MDX in your applications.

In this tutorial we’ll build a small bookstore app using Ultra.

Project setup

Let’s create a basic project.

First, we need to set up a new Ultra project by running the following commands on your terminal.

git clone https://github.com/exhibitionist-digital/create-ultra-app
cd create-ultra-app
deno task dev

The above command will generate the following folder structures below.

 ┣ src
 ┃ ┣ api
 ┃ ┃ ┗ example.ts
 ┃ ┣ app.tsx
 ┃ ┣ favicon.ico
 ┃ ┗ style.css
 ┣ .gitignore
 ┣ README.md
 ┣ deno.json
 ┣ importMap.json
 ┣ package-lock.json
 ┗ server.ts

Ultra creates the following folder structures.

  • Server.ts: This code runs Ultra’s server.
  • src: This is the folder where the code for your project is.
  • app.tsx: This is the root file for every Ultra project.
  • importMap.json: Here is where dependencies for the project are documented.
  • deno.json: Here is where the configuration file that allows customizing the built-in TypeScript compiler, formatter, and linter.

Let’s update the app.tsx file to include the Bootstrap CDN to enable the style of the components. Ultra uses react-helmet-async to add markup to the html <head>. To replace the code in <Helmet> component with the code snippet below.

<Helmet>
  <title>Book store</title>
  <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous" />
</Helmet>

Open Source Session Replay

OpenReplay is an open-source, session replay suite that lets you see what users do on your web app, helping you troubleshoot issues faster. OpenReplay is self-hosted for full control over your data.

replayer.png

Start enjoying your debugging experience - start using OpenReplay for free.

Create Book Component

Now let’s create another folder called component for our components. In the component folder, create a file called Book.tsx and add the code snippet below. (In real life we’d get books from an API -and we’d have more than two!- but that doesn’t concern us now.)

import React from "react";
const BookList = React.lazy(() => import("./BookList.tsx"));

const books = [
  {
    id: 1,
    title: 'The Design of EveryDay Things',
    author: 'Don Norman',
    price: '$22.00',
    coverImage: 'https://miro.medium.com/max/1200/1*ixC7mJJRK55qPhyRwj3iGg.jpeg',
    description: 'Don Norman is a designer who lives and works in San Francisco. He has designed more than 100 products for companies such as Google, Motorola, and eBay. He has also designed products for non-profit organizations such as the World Food Program and UNICEF.',
  },
  {
    id: 2,
    title: 'Things fall Apart',
    author: 'Chinua Achebe',
    coverage: 'https://i0.wp.com/feminisminindia.com/wp-content/uploads/2021/07/Things_Fall_Apart_by_Chinua_Achebe_1_.jpg?fit=1200%2C675&ssl=1',
    description: 'Don Norman is a designer who lives and works in San Francisco. He has designed more than 100 products for companies such as Google, Motorola, and eBay. He has also designed products for non-profit organizations such as the World Food Program and UNICEF.',
  }
];

In the above code snippet, we imported React and the BookList components which we’ll create later in this tutorial. Then we created a book array with some book data. Now let’s create and render the JSX for the Book component with the code snippet below.

export default function Book() {
  return (
    <>
      <nav class="navbar navbar-light bg-light">
        <div class="container-fluid">
          <a class="navbar-brand">Book Store</a>
          <form class="d-flex">
            <input class="form-control me-2" type="search" placeholder="Search" aria-label="Search" />
            <button class="btn btn-outline-success" type="submit">Search</button>
          </form>
        </div>
      </nav>
      <div class="container-md">
        <div class="row">
          {books.map((book) => (
            <BookList key={book.id} book={book} />
          ))}
        </div>
      </div>
    </>
  );
}

In the above code snippet, we created the JSX for the Book component and render the BookList component passing the book array as props.

Create BookList component

With the Book component created, let’s create another component in the component folder called BookList.tsx file and add the code snippet below.

import React from "react";
export default function BookList({ book }) {
    return (
        <div class="col-sm-6">
            <div class="card">
                <img src={book.coverImage} class="card-img-top" alt="..." />
                <div class="card-body">
                    <h5 class="card-title">
                        {book.title}</h5>
                    <p class="card-text">{book.description}</p>
                    <a href="#" class="btn btn-primary">View Details</a>
                </div>
            </div>
        </div>

    );
}

In the above snippet, we created the BookList component. Here we destructure the book array from the props to access the book objects and render them.

Adding Routes

Now let’s configure a route for the application. Ultra uses a Wouter router for routing and that is already set up in the app.tsx file for you. But we need to do a few modifications. We’ll render the Book component on the /books route.

...
<Switch>
  <Route path="/book">
    <Book />
 </Route>
</Switch>
...

Conclusion

Throughout this tutorial, you’ve learned about Ultra by creating a simple Book application. We started with the introduction, then we looked at some of the reasons a developer should use Ultra for their projects. You can learn more about Ultra from the official documentation.