Skip to content

How to Setup Storybook in a Qwik Project

This article was written over 18 months ago and may contain information that is out of date. Some content may be relevant but please refer to the relevant official documentation or available resources for the latest information.

Introduction

Storybook is a great tool for testing and visualizing your components in different states. In this article, we will see how to setup Storybook in a Qwik project.

Qwik

Qwik is a new JavaScript framework by Misko Hevery, creator of Angular, for building frontend browser applications. The major benefit of Qwik is its performance optimization, and this is achieved through zero loading, resumability, lazy loading, reduced rendering, scalability, and code once.

For more information on Qwik, you can check out the docs, github repo, and discord.

Project Set Up

To get started, we need to create a new Qwik app. We can do this by running the following command in our terminal:

npm create qwik@latest

Initialize Storybook

Storybook, unfortunately, doesn’t have a Qwik template yet because it is a new Framework. So the work around is to use the html template .

Using the command below, we can initialize Storybook:

npx storybook init --type html
bootstrapping app & installing dep

During the initialization, Storybook would ask to automatically install some optional dependencies such as; EslintPlugin and npm7, you can accept or reject it. To accept, type y and hit Enter to progress.

installing optional deps

Storybook would try to setup a default stories folder, which is based on the –type template we choose, which is html. It is not compatible with the Qwik compiler and will result in compilation errors, so we will have to delete it to avoid running into such errors.

default stories folder

Project Structure

Our project structure is already setup by Qwik, and Storybook initialization has created a .storybook folder. But we need to make some changes to the Storybook file extension since our project is in TypeScript. This is a snippet of the folders in our project:

        ├── .storybook
            ├── main.ts
            ├── preview.ts
            └── preview-head.html
        ├── public
        ├── vite.config.ts
        └── src

Configuring Storybook

Since Qwik runs on Vite, we need to set up the viteFinal function in our main.ts file, which will give us the config that we will use to register our Qwik Vite plugin. Add this line of code in the configuration object:

      viteFinal: async (config, options) => {
        const { qwikVite: qwikVite } = await import('@builder.io/qwik/optimizer');
        config.plugins?.unshift(qwikVite());
        return config;
      },

In the preview.ts file, this is where we configure how Storybook renders our stories. We need to execute Qwikloader. This will help in registering global browser events, and much more Qwik related benefits. We will replace the content in the file with the code below:

    import { JSXNode } from '@builder.io/qwik';
    import { QWIK_LOADER } from '@builder.io/qwik/loader/index';
    import { render } from '@builder.io/qwik';
    import '../src/global.css';
    eval(QWIK_LOADER);

    export const decorators = [
      (Story: () => JSXNode) => {
        const parent = document.createElement('div');
        const jsxNode = Story();
        render(parent, jsxNode);
        return parent;
      },
    ];

This solution was found in this discussion: How to do component testing with Qwik?.

I believe when the Qwik Storybook type template becomes available these configurations will be there by default.

Now we are done with the configuration, let's run storybook and see what we have:

    npm run storybook

Creating Stories

We can create our first story, we will create a story for our Qwik app component. We will create this story for our default Qwik Header component. I modified the Header component to accept a menus props:

    import { Meta } from '@storybook/html';
    import Header, { HeaderProps } from './header';

    export default {
      title: 'Header',
    } as Meta;

    const Template = (args: HeaderProps) => <Header menus={args.menus} />;

    export const Demo: any = Template.bind({
        menus: []
    });

    Demo.args = {
        menus: [
            {
              name: 'Docs',
              link: 'https://qwik.builder.io/docs/components/overview/',
            },
            {
              name: 'Examples',
              link: 'https://qwik.builder.io/examples/introduction/hello-world/',
            },
            {
              name: 'Tutorials',
              link: 'https://qwik.builder.io/tutorial/welcome/overview/',
            },
          ]
    };

Conclusion

In this article, we saw how to setup Storybook in a Qwik project. We also saw how to create our first story. I hope you enjoyed this article. Thanks for reading.

If you don't want to do these steps yourself, check out our starter.dev Qwik kit that already has Storybook enabled for your use here.

A link to the project repo can be found here.

If you have any questions or run into any trouble, feel free to reach out on Twitter.

This Dot is a consultancy dedicated to guiding companies through their modernization and digital transformation journeys. Specializing in replatforming, modernizing, and launching new initiatives, we stand out by taking true ownership of your engineering projects.

We love helping teams with projects that have missed their deadlines or helping keep your strategic digital initiatives on course. Check out our case studies and our clients that trust us with their engineering.

You might also like

How to Build Apps with Great Startup Performance Using Qwik cover image

How to Build Apps with Great Startup Performance Using Qwik

In this article, we will recap the JS Drops Qwik workshop with Misko Hevery. This workshop provided an overview on Qwik, its unique features and a look at some example components. We will also address some of the questions raised at the end of the workshop. If you want to learn more about Qwik with Misko Hevery, then please check out this presentation on This Dot Media’s YouTube Channel. Also don’t forget to subscribe to get the latest on all things web development. Table of Contents - What is Qwik? - How to create a Counter Component in Qwik - Unique features of Qwik - Directory Based Routing - Slots in Qwik - Very little JavaScript in production - Resumability with Qwik - Lazy load components by default - Questions asked during the workshop - Are all these functions generated at build time or are they generated at runtime? What's the server consideration here (if any) or are we able to put everything behind a CDN? - How do you access elements in Qwik? - Can you force a download of something out of view? - What is the choice to use $ on Qwik declarations? - Can you explain the interop story with web components and Qwik? Any parts of the Qwik magic that aren’t available to us if, say, our web components are too complex? - Is there an ideal use case for Qwik? - When to use useWatch$ instead of useClientEffect$? - Conclusion What is Qwik? Qwik is a web framework that builds fast web applications with consistent performance at scale regardless of size or complexity. To get started with Qwik, run the following command: ` The Qwik CLI will prompt options to scaffold a starter project on your local machine. To start the demo application, run npm start and navigate to http://127.0.0.1:5173/ in the browser. How to create a Counter Component in Qwik Create a sub-directory in the routes directory named counter and add an index.tsx file with the component definition below. ` Now navigate to http://127.0.0.1:5173/counter and you should see the counter component rendered on the page. Unique features of Qwik Directory Based Routing Qwik is a directory-based routing framework. When we initiated Qwik, it created a routes sub-directory in the src directory and added index and layout files for route matching. The index.tsx is the base route component and the layout.tsx is the component for handling the base page layout. The sub-directories in the route directory serve as the application’s structure for route matching with its index.tsx files as the route components. Every index.tsx file does a look up for the layout component. If it doesn’t exist in the same directory, then it moves up to the parent directory. ` Slots in Qwik Qwik uses slots as a way of connecting content from the parent component to the child projection. The parent component uses the q:slot attribute to identify the source of the projection and the element to identify the destination of the projection. To learn more about slots, please check out the Qwik documentation. Very little JavaScript in production In production, Qwik starts the application with no JavaScript at startup, which makes the startup performance really fast. To see this in action, open the browser’s dev tools, click on the Network tab, and on the Filter tab select JS. You will notice the Vite files for hot module reloading are currently the only JavaScript files served which will not be shipped to production. Go to the filter tab and check the invert checkbox then in the filter input type select Vite. Resumability with Qwik Qwik applications do not require hydration to resume an application on the client. To see this in action, click on the increment button and observe the browser’s dev tools network tab. You will notice Qwik is downloading only the required amount of JavaScript needed. The way Qwik attaches the event to the DOM and handles the state of components is that it serializes the attribute, which tells the browser where to download the event handler and its state. To learn more about serialization with Qwik, read through the Qwik documentation. By default, the code associated with the click event will not download until the user triggers that event. On this interaction, Qwik will only download the minimum code for the event handler to work. To learn more about Qwik events, please read through the [documentation] (https://qwik.builder.io/docs/components/events/#events)....

Using React In Your Qwik Application cover image

Using React In Your Qwik Application

Introduction React, developed by Meta, is a JavaScript library for building user interfaces, and it is one of the most used UI JavaScript libraries in the world. React will be turning a decade old by May 2023. It has gained a lot of popularity over the years, and its latest version, React 18, was released in March 2022. Qwik is a new JavaScript framework by Misko Hevery, creator of Angular, for building frontend browser applications. The major benefit of Qwik is its performance optimization, which features resumability and lazy loading. As it stands now, there are virtually no Qwik third-party packages or libraries that currently exist, but luckily the Qwik team factored this in, making it easy for developers to easily integrate React libraries or your old React components into your Qwik project without too much difficulty. In this article, I will show you how to easily integrate React libraries or components into your Qwik project. Project Set Up To get started, we need to create a new Qwik app. We can do this by running the following command in our terminal: ` You can also get additional tools and configurations using our starter.dev kit by running the command in your terminal: ` You will be prompted to enter the name of your project (let’s call it qwik-react), choose the default option when asked to select a starter, and then install npm dependencies. Now we have our Qwik application ready to go. Let’s start the development server and see what it looks like; ` Now that our app is up and running we will see how we can integrate a React package and component into our Qwik project. Integrating React in Qwik Like most JavaScript frontend libraries or frameworks, React makes use of hydration, which has its drawbacks and might be more expensive than you think. Qwik needs no hydration on load. It’s just pure HTML. This makes Qwik qwiker to load UIs, with which users can start interacting. You should keep this in mind when considering to include React components in your Qwik applications. QwikReact is a tool that allows you to use React components in Qwik, including the whole ecosystem of component libraries such as Material UI, Threejs and React Spring. To get started, we need to run this command inside our Qwik app: ` This will install needed dependencies such as qwik-react, react, and react-dom. It will also add emotion and mui, which you can uninstall if you don’t intend to use them. If we check our project, we should now have some new folders generated. The most important is the src/integrations/react. This is where all our React components will be implemented or React packages will be used. Qwikify$ The qwikify$ function is exported from @builder.io/qwik-react, which converts React components into Qwik components that you can use across your application, and allows Qwik to implement partial hydration of React components. You cannot use React components in Qwik without converting them first to remove React’s hydration pattern, which is not supported in Qwik, using qwikify$(). Another important thing to remember is to make sure the file containing your React component has this; ` This needs to be imported at the top of the file as this serves as instructions to the compiler to use React as the JSX factory. This means you cannot mix your React components with a Qwik component. The code above is from the Qwik demo. You can see how the React components are wrapped with the qwikify$() function. If your React package requires some configuration, don’t try to pass it as a props. Instead, do every configuration right inside the file, ensuring only the dynamic data is passed through. The code above is from our Qwik GitHub showcase. Check out the full source code here. So once you are done with Qwikifying your React component, you can now import and use it just as you would normally do a Qwik component. Let’s run our application, and navigate to the React page at ` to view the default Qwik demo; ` Interactivity Qwik tries to reduce or completely remove hydrations, but React heavily depends on it. This means we have to find a way to hydrate our React Component without affecting the concept of Qwik. Qwik allows you to decide when to hydrate your components by using the client: JSX properties. This technique is commonly referred to as “partial hydration”. For more information on this checkout Adding Interactivity on Qwik Docs. Conclusion In this article, we saw how to convert React to a Qwik component. We also learned about the dos and don’ts of using React in Qwik, as well as how to handle hydration. I hope you enjoyed this article. Thank you for reading! If you have any questions or run into any trouble, feel free to join the discussions going on at starter.dev or on our Discord....

Using Zustand in Your Next React Project cover image

Using Zustand in Your Next React Project

Introduction This article, we will focus more on the practical use of Zustand in a real world project. You can check this article Zustand for State Management if you need an introductory read on the topic. We will be focusing on making API calls right from our Zustand store, and also persisting state to either session or local storage. The project we are going to build is a GitHub user search page where we can experiment with GitHub API. We will be able to search for users, and get more information about a user. We will also see how we can persist the store state. Project Set Up To get started, we need to create a new React app. We can do this by running the following command in our terminal: npx create-react-app zustand-demo --template typescript Project Dependencies After the project is created, we need to install our project dependencies. We can do this by running the following command in our terminal: yarn add zustand @chakra-ui/react @emotion/react @emotion/styled react-icons react-router-dom axios framer-motion pluralize query-string react-helmet-async react-hook-form react-paginate Project Structure After installing our project dependencies, we need to create our project structure. We can do this by creating the following folders in our project: src ├── index.tsx ├── assets ├── container ├── components ├── pages ├── routes ├── services ├── store └── theme ENV Variables After creating our project structure, we need to create our env variables. We can do this by creating a .env file in our project root, and adding the following variables: REACT_APP_GITHUB_API_URL=https://api.github.com Services After creating our env variables, we need to create our services. We can do this by creating a githubService.ts file in our services folder, and adding the following code: ` Store Setup Next, we will set up our Github store. We will be implementing the Zustand persist method to persist our state to either session or local storage. ` We were able to make an asynchronous call to the GitHub api, and set the response to our store right from our store nicely without having to use extra middleware. We also cached our users details so that we don't have to make another API call to get the same user details again. We also persisted our state to session storage. We can also persist our state to local storage by changing the getStorage method to localStorage. Clear/Reset Store Right now, there is no out of the box method from Zustand. But we can do that by adding a clear/reset method to our store, resetting our state back to the initial state and calling the sessionStorage or localStorage clear() method. ` A link to the project repo can be found here, and a link to the live demo can be found here. If you have any questions or run into any trouble, feel free to reach out on Twitter or Github....

What does it actually look like to build software with AI today? Not in theory, but in practice. cover image

What does it actually look like to build software with AI today? Not in theory, but in practice.

What does it actually look like to build software with AI today? Not in theory, but in practice. At the Leadership Exchange, this was the question at the center of the Developer Panel, where leaders from across the industry unpacked what’s really changing inside engineering teams and what organizations need to do right now to keep up. The Developer Panel at the Leadership Exchange explored the cutting edge of AI in software engineering and examined what organizations should focus on today to prepare for the future. Moderated by Jeff Cross, Co-Founder & CEO at Nx, the panel featured Victor Savkin, Cofounder & CTO at Nx, Alex Sover, Vice President of Engineering at OpenAP, Brent Zucker, Senior Director of Engineering at Visa, and Jonathan Fontanez, AI Engineering Lead at This Dot Labs. Panelists shared insights into how AI is transforming the software development lifecycle and how teams can adopt tools effectively while preparing for organizational change. Panelists discussed emerging workflows, including CI-in-the-loop, agentic healing, and context engineering. They examined how validation, code reviews, and PRDs are evolving alongside AI capabilities and how teams are integrating external sources such as production traces to improve quality and reliability. The discussion also covered what the next generation of agentic tools might look like and how these capabilities will shape engineering practices in the near future. Adoption of AI comes with challenges. Teams often rely on plugins or extensions without foundational understanding, and individual contributors may fear displacement. Panelists emphasized that education, governance, and skill-building are essential for teams to manage AI agents effectively while maintaining quality. They also highlighted the need to standardize workflows and ensure organizational alignment to fully leverage AI capabilities. The conversation extended beyond technical challenges to organizational implications. Panelists discussed how teams can avoid issues like Conway’s Law, manage distributed teams effectively, and evolve engineering practices alongside AI adoption. Leadership and management strategies play a crucial role in ensuring that AI integration delivers meaningful outcomes while maintaining efficiency and alignment with business objectives. Key Takeaways - AI workflows require both technical and organizational preparation. - Education, governance, and skill development are essential for successful implementation. - Forward-looking teams are rethinking validation, CI pipelines, and context management to fully leverage agentic AI. The discussion highlighted that adopting AI at the cutting edge is not just about new tools - it is about rethinking processes, workflows, and organizational culture. Companies that embrace this holistic approach are most likely to succeed in leveraging AI to its full potential. Are you interested in more conversations like this? Message us for an invite to the next, or for a private discussion around these topics. Tracy can be reached at tlee@thisdot.co....

Let's innovate together!

We're ready to be your trusted technical partners in your digital innovation journey.

Whether it's modernization or custom software solutions, our team of experts can guide you through best practices and how to build scalable, performant software that lasts.

Prefer email? hi@thisdot.co