DEV Community

Cover image for Onlook: A React visual editor
Megan Lee for LogRocket

Posted on • Originally published at blog.logrocket.com

Onlook: A React visual editor

Written by Jude Miracle✏️

The gap between design and development often frustrates many teams. Designers use tools like Figma to create beautiful interfaces, but developers find it hard to turn these designs into working code using traditional IDEs. This disconnect sometimes slows down development and can lead to misunderstandings and costly fixes.

Onlook is a new tool that helps bridge this gap by bringing design features directly into your development environment. With Onlook, you can improve your workflow, enhance teamwork between designers and developers, and deliver products faster and more accurately.

In this article, we'll explore Onlook, a tool that brings design capabilities directly into the development environment. We will look at how it compares to existing tools like Figma and Webflow, and provide a practical guide to setting it up.

What is Onlook?

Onlook is an open source visual editor designed specifically for React applications. It enables developers to create and modify user interfaces while working with their live React components. Onlook provides a direct manipulation interface similar to Figma, offering features like drag-and-drop editing, real-time preview, and seamless code generation.

With Onlook, developers can visually manipulate components, adjust styles, and see changes in real time, all while working within their application's actual codebase. Its direct integration simplifies the handoff process between design and development, reducing inconsistencies and streamlining the overall workflow.

Unlike traditional design tools or no-code builders, Onlook allows developers to directly integrate their existing React projects and maintain full development control while gaining the benefits of visual editing. Onlook is relatively new, with over 4.2k Github stars. It has over 40 contributors, which means they regularly ship updates and new features.

Onlook features

  • Live editing within React apps: Onlook allows you to edit components while they are fully functional and interactive. It allows you to see how your changes affect the actual application state and behavior, modify layouts with real data flowing through your components, and test interactions immediately as you make design changes
  • Real-time design edit: Onlook's real-time editing capabilities extend beyond basic styling. They include a drag-and-drop interface for component positioning and layout adjustments, a live preview of CSS changes with immediate feedback, interactive resizing of elements with responsive breakpoint visualization, and real-time updates to component props and state
  • AI chat: Onlook integrates AI chat to improve its features. With AI it can suggest designs based on current work, recommend color palettes, layouts, and component choices, and help users quickly develop their ideas
  • Code-first approach: Its code-first approach ensures that your visual edits translate to clean, maintainable React code, with direct manipulation of existing component code, no generation of unnecessary wrapper elements or style bloat, and full access to component props, state, and methods during editing
  • Compatible with existing React projects: Onlook can integrate seamlessly with existing React projects, working with any React project structure, supporting modern React features and popular styling solutions like Tailwind CSS, CSS modules, context, hooks, and preserving existing build and deployment workflows

Benefits of using Onlook

  • Onlook helps remove the need to switch between design tools and code editors as well as fosters a more efficient and integrated development process
  • It allows experimenting with different layouts, styles, and interactions with speed
  • Onlook bridges the gap between designers and developers by providing a shared visual language which makes it easier to communicate design ideas and ensure alignment
  • Translating its design to React codes makes Onlook easier for React developers

Prerequisites

Onlook is a standalone app, but to follow along with this tutorial, you will also need:

  • A code editor like VS Code or Cursor
  • Basic familiarity with running commands on your terminal
  • Basic familiarity with design and React concepts

Project setup

To get started with Onlook, follow these steps:

  • Download and install the Onlook desktop application, selecting the version appropriate for your system.
  • Launch the Onlook application. You will be prompted to sign up or log in using your GitHub or Google account.
  • Create a new React project:
    • Give your project a name.
    • Select a folder for your application.
    • After setup is complete, you'll be directed to the interface where you can design your application.
  • Start the development server: Click the play button in the bottom toolbar.
  • Verify the URL: Ensure that http://localhost:3000/ is pointing to the correct location. If it opens in your browser, it should also open within the Onlook application.
  • Check the terminal: You can also open the terminal to confirm that your app is running.

Once running, you will be presented with your application's homepage. Onlook Interface Example Now that we’ve got our app running, let's dive into the Onlook interface before designing our first app.

Understanding the Onlook interface

When you first open Onlook, you'll see an interface that combines visual editing with code features. The interface has several key areas, each with a specific purpose in your development process.

The main workspace has three main sections:

  • The Component Canvas is in the center, where you can see your components working in real-time
  • The Properties and AI chat panel are on the right and show controls for the element you are currently editing, including a section where you can chat with AI
  • The Component Tree Navigator is on the left and displays the structure of your application

Additionally, there are other important sections:

  • Toolbar: Found at the bottom of the interface, it includes buttons for selecting elements, panning the view, inserting objects and text, starting the app, and accessing the console/terminal.

The Onlook interface connects design and development. Any design change you make updates the underlying React code immediately. Any code changes are also reflected in the design. This two-way relationship is what differentiates Onlook from traditional design tools.

From design to code

Unlike traditional workflows where you export designs to code, Onlook maintains a live connection between your visual edits and the React code. This allows for:

  • Visual changes to immediately update the code in your React application
  • Code to remain accessible through your preferred editor (like VS Code)
  • Changes to be made either visually or in code, staying in sync

Let’s break it down to the components. When you're working on a component, you can:

  • Design it visually in Onlook's interface
  • Click "Open in VS Code" to see and edit the generated code
  • Make changes in either environment
  • See your changes reflected in both places instantly Onlook Interface 2

Creating and managing components

Let's create a to-do list app using Onlook to show how the visual editor works with React. This example will highlight Onlook's main features while building a real application that uses state management, user interactions, and component composition.

When you start designing in Onlook, you have two options: you can either use the visual editor directly, or you can use Onlook's AI assistant. Beginners or those who want guidance may find the AI assistant helpful. You can describe what you want, and the AI will help you create a basic layout that you can improve: Creating And Managing Components In Onlook The visual editor lets you drag and drop elements, change styles, and see quick results. As you make changes, Onlook automatically writes the React code for you. At first, all the code goes into the page.tsx file, which is a starting point, but not the best setup for a production app.

Structuring the application While Onlook's automatic code generation is useful, real-world applications need a clearer structure. To address this, we can use component-based architecture. This approach will separate concerns and make the code easier to maintain. Here’s how we will organize our project:

app/
├── page.tsx
└── components/
    ├── TodoContainer.tsx
    ├── TodoForm.tsx
    ├── TodoList.tsx
    ├── TodoItem.tsx
    └── types.ts
Enter fullscreen mode Exit fullscreen mode

This structure follows React best practices by breaking the user interface into clear, reusable components. Each component, which we’ll demonstrate below, has a specific function, helping the code stay organized and easier to understand. Onlook’s Types component:


// types.ts
export interface Todo {
    id: number;
    text: string;
    completed: boolean;
}
Enter fullscreen mode Exit fullscreen mode

Onlook’s Page component:


// page.tsx
import TodoContainer from './components/TodoContainer';

export default function Page() {
    return (
        <div className="w-full min-h-screen bg-gradient-to-br from-purple-50 to-white dark:from-gray-900 dark:to-gray-800 p-4">
            <div className="max-w-2xl mx-auto">
                <div className="text-center mb-8">
                    <h1 className="text-4xl font-bold text-purple-600 dark:text-purple-400 mb-2">
                        Todo List
                    </h1>
                    <p className="text-gray-600 dark:text-gray-300">
                        Stay organized and productive
                    </p>
                </div>
                <TodoContainer />
            </div>
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

Onlook’s TodoContainer component:


// components/TodoContainer.tsx
'use client';

import { useState } from 'react';
import TodoForm from './TodoForm';
import TodoList from './TodoList';
import { Todo } from './types';

export default function TodoContainer() {
    const [todos, setTodos] = useState<Todo[]>([]);
    const [newTodo, setNewTodo] = useState('');

    const addTodo = (e: React.FormEvent) => {
        e.preventDefault();
        if (newTodo.trim()) {
            setTodos([
                ...todos,
                {
                    id: Date.now(),
                    text: newTodo.trim(),
                    completed: false,
                },
            ]);
            setNewTodo('');
        }
    };

    const toggleTodo = (id: number) => {
        setTodos(
            todos.map((todo) => (todo.id === id ? { ...todo, completed: !todo.completed } : todo)),
        );
    };

    const deleteTodo = (id: number) => {
        setTodos(todos.filter((todo) => todo.id !== id));
    };

    return (
        <>
            <TodoForm
                newTodo={newTodo}
                setNewTodo={setNewTodo}
                addTodo={addTodo}
            />
            <TodoList
                todos={todos}
                toggleTodo={toggleTodo}
                deleteTodo={deleteTodo}
            />
        </>
    );
}
Enter fullscreen mode Exit fullscreen mode

Onlook’s TodoForm component:


// components/TodoForm.tsx
'use client';

interface TodoFormProps {
    newTodo: string;
    setNewTodo: (value: string) => void;
    addTodo: (e: React.FormEvent) => void;
}

export default function TodoForm({ newTodo, setNewTodo, addTodo }: TodoFormProps) {
    return (
        <form onSubmit={addTodo} className="mb-8">
            <div className="flex gap-2">
                <input
                    type="text"
                    value={newTodo}
                    onChange={(e) => setNewTodo(e.target.value)}
                    placeholder="What needs to be done?"
                    className="flex-1 p-3 rounded-lg border border-gray-300 dark:border-gray-600 
                             bg-white dark:bg-gray-700 text-gray-900 dark:text-white
                             focus:ring-2 focus:ring-purple-500 focus:border-transparent"
                />
                <button
                    type="submit"
                    className="px-6 py-3 bg-purple-600 text-white rounded-lg
                             hover:bg-purple-700 focus:outline-none focus:ring-2
                             focus:ring-purple-500 focus:ring-offset-2
                             transition-colors duration-200"
                >
                    Add
                </button>
            </div>
        </form>
    );
}
Enter fullscreen mode Exit fullscreen mode

Onlook’s TodoList component:


// components/TodoList.tsx
'use client';

import { Todo } from './types';
import TodoItem from './TodoItem';

interface TodoListProps {
    todos: Todo[];
    toggleTodo: (id: number) => void;
    deleteTodo: (id: number) => void;
}

export default function TodoList({ todos, toggleTodo, deleteTodo }: TodoListProps) {
    return (
        <div className="bg-white dark:bg-gray-800 rounded-xl shadow-lg p-6">
            {todos.length === 0 ? (
                <p className="text-center text-gray-500 dark:text-gray-400 py-8">
                    No todos yet. Add one above!
                </p>
            ) : (
                <ul className="space-y-3">
                    {todos.map((todo) => (
                        <TodoItem
                            key={todo.id}
                            todo={todo}
                            toggleTodo={toggleTodo}
                            deleteTodo={deleteTodo}
                        />
                    ))}
                </ul>
            )}

            {todos.length > 0 && (
                <div className="mt-6 pt-6 border-t border-gray-200 dark:border-gray-700">
                    <div className="flex justify-between text-sm text-gray-600 dark:text-gray-400">
                        <span>{todos.filter((t) => !t.completed).length} items left</span>
                        <span>{todos.filter((t) => t.completed).length} completed</span>
                    </div>
                </div>
            )}
        </div>
    );
}
Enter fullscreen mode Exit fullscreen mode

Onlook’s TodoItem component:


// components/TodoItem.tsx
'use client';

import { Todo } from './types';

interface TodoItemProps {
    todo: Todo;
    toggleTodo: (id: number) => void;
    deleteTodo: (id: number) => void;
}

export default function TodoItem({ todo, toggleTodo, deleteTodo }: TodoItemProps) {
    return (
        <li className="flex items-center gap-3 bg-gray-50 dark:bg-gray-700/50 
                      p-4 rounded-lg group">
            <input
                type="checkbox"
                checked={todo.completed}
                onChange={() => toggleTodo(todo.id)}
                className="w-5 h-5 rounded border-gray-300 
                         text-purple-600 focus:ring-purple-500"
            />
            <span
                className={`flex-1 ${
                    todo.completed
                        ? 'line-through text-gray-400 dark:text-gray-500'
                        : 'text-gray-700 dark:text-gray-200'
                }`}
            >
                {todo.text}
            </span>
            <button
                onClick={() => deleteTodo(todo.id)}
                className="opacity-0 group-hover:opacity-100 transition-opacity
                         text-red-500 hover:text-red-600 p-1"
            >
                <svg
                    xmlns="http://www.w3.org/2000/svg"
                    className="h-5 w-5"
                    viewBox="0 0 20 20"
                    fill="currentColor"
                >
                    <path
                        fillRule="evenodd"
                        d="M9 2a1 1 0 00-.894.553L7.382 4H4a1 1 0 000 2v10a2 2 0 002 2h8a2 2 0 002-2V6a1 1 0 100-2h-3.382l-.724-1.447A1 1 0 0011 2H9zM7 8a1 1 0 012 0v6a1 1 0 11-2 0V8zm5-1a1 1 0 00-1 1v6a1 1 0 102 0V8a1 1 0 00-1-1z"
                        clipRule="evenodd"
                    />
                </svg>
            </button>
        </li>
    );
}
Enter fullscreen mode Exit fullscreen mode

One useful feature of Onlook is its ability to link the visual editor and the code in both directions. This is done using a special data-oid attribute that Onlook adds to components during development:

<TodoContainer data-oid="zshvwmp"/>
Enter fullscreen mode Exit fullscreen mode

This attribute helps Onlook keep track of changes to components, connect visual elements with the code, allow real-time updates in both directions and maintain component functions while editing visually.

While you build your application, you can use Onlook's visual editor to improve the design without hurting the quality of your code. For instance, you can change component layouts, adjust spacing, refine colors and fonts, and test how your app responds to different screen sizes:

Where Onlook fits in the design ecosystem

Web development tools meet different needs and workflows. They offer solutions for both design and development. To understand where Onlook fits in, we’ll compare it to other tools, highlighting its strengths and weaknesses.

Onlook vs. Figma: Comparing traditional design tools Traditional design tools are strong at illustration, collaboration, prototyping, and design asset management. Onlook offers something different by allowing direct manipulation of React components, real-time interaction with component states and props, production-ready code, seamless integration with development workflows, and active testing of component behavior during design.

Onlook vs. Webflow: Comparing no-code builders
No-code platforms offer visual development and code export, they are strong at rapid prototyping, visual CMS integration, and built-in hosting. Onlook is different by being directly integrated into existing React codebases, maintaining component logic, and being developer-first while allowing visual editing. It integrates with development tools and supports custom components with full React features, and clean React code.

Advantages of designing directly within React

  • Developers can see how components behave using real data and state changes during the design process. This helps them find interaction issues, and state management problems
  • Using live React components allows developers to quickly assess how design choices affect performance
  • Designers and developers can make smart decisions about how components look in different states, making sure they consider all possible states during design
  • Working in React gives designers quick access to the application’s prop system and context, so they can work with real data flows
  • Developers can try out different ways to combine components and organize them while still having full access to the component’s logic and props

Conclusion

Onlook improves workflow across the React ecosystem. It improves cohesion between design and development teams and allows users to edit React components visually while keeping the code intact. By syncing visual changes with the code in real time, Onlook resolves a variety of common workflow issues. In addition, its AI features and smooth integration with existing React projects make it a useful addition to modern development processes.

Although Onlook is still being improved, it shows great potential to change how React applications are built. As it adds new features, it could become a vital tool for React developers looking to enhance their workflows and create high-quality user experiences more easily. Check out Onlook and try out its features in your projects.


Get set up with LogRocket's modern React error tracking in minutes:

  1. Visit https://logrocket.com/signup/ to get an app ID.
  2. Install LogRocket via NPM or script tag. LogRocket.init() must be called client-side, not server-side.

NPM:

$ npm i --save logrocket 

// Code:

import LogRocket from 'logrocket'; 
LogRocket.init('app/id');
Enter fullscreen mode Exit fullscreen mode

Script Tag:

Add to your HTML:

<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
Enter fullscreen mode Exit fullscreen mode

3.(Optional) Install plugins for deeper integrations with your stack:

  • Redux middleware
  • ngrx middleware
  • Vuex plugin

Get started now

Top comments (3)

Collapse
 
tbogard profile image
Erick Rodriguez

Not fan of react, but it is excellent that React devs get this tooling. Congratulations 🎉🎉🎉

Collapse
 
ronakjain2012 profile image
Ronak Bokaria

Loved this tool 🔥

Collapse
 
md_mostakinhossain_0f569 profile image
Md Mostakin Hossain

good man