Skip to content

Introducing the New Shopify and Next.js 13 Starter Kit

Screenshot 2023-08-02 180048


We are delighted to announce our brand new Shopify and Next.js 13 starter kit to our kits collection. This Starter kit is amazing to help you and your team quickly bootstrap a custom Shopify storefronts powered by Next.js 13 App Router since it has almost every feature you need for production set up and running!

Why did we build it?

At This Dot Labs, we work with a variety of clients, from big corporations to startups. Recently, we realized that we have a lot of clients who use Shopify that want to build custom stores using Next.js to benefit from its features. Additionally, we know that Hydrogen Shopify has only been limited to Remix since they acquired it. We had a lot of a hard time refilling the gap Hydrogen left to implement its features from scratch in our client projects. And from here, we realized that we need to build a starter kit to:

  • Help our teams build custom storefronts using Next.js Quickly
  • Reduce the cost for our clients

There were a lot of Next.js Shopify starters out there, but they were very basic and didn’t have all the features our teams needed, unlike the Official Hydrogen Starter Example which is complete. So, we decided to convert the Hydrogen starter from Remix/Hydrogen to Next.js, and use the power of the App Router and React Server Components.

Tech Stack

We used in this project:

Why Shopify

Shopify is a great e-commerce platform. They have a lot of experience in this field since 2006, and now over 4.12 million e-commerce sites are built with Shopify. (Source: Shopify is used by online sellers in over 175 countries around the world, with 63% of Shopify stores estimated to be based in the US.

Why Next.js 13

As we mentioned above, we have a lot of clients who already use Next.js and it’s a very popular framework in the market for its flexibility, scalability, and diverse collection of features.


Since this starter kit is based on the official Shopify Hydrogen template, it has all of it’s features as well including:

  • Light/Dark themes support
  • Authentication system with login, register, forgot password, and account pages
  • Supports both Mobile/Desktop screens
  • Has built-in infinity scroll pagination, built with Server Components
  • State management using Zustand
  • Variety of custom fonts
  • All components have been built with Tailwind
  • Static analysis testing tools pre-configured like TypeScript, Eslint, Prettier, and a lot of useful extensions
  • Storybooks for the consistency of the system design
  • GitHub Pull requests and release templates
  • Shopify analytics integrated with the kit
  • Great performance and SEO scores
  • And finally, incompatible performance tested by both Lighthouse and PerfBuddy


This kit is running at top performance! It has amazing performance, SEO, and accessibility scores.

We tested it using PerfBuddy, and the results are incredible on both Desktop and Mobile. Here is the full report.

Screenshot 2023-08-02 181153

Note: PerfBuddy is an incredible free tool to analyze the performance of your web apps accurately. Check it out!

Also, the results from Lighthouse are pretty fascinating:

Screenshot 2023-08-02 181411

When do I use this kit?

This starter kit is great for starting new custom storefronts rapidly, especially for startups to save time and money. Also, it can be used to migrate from the old Next.js storefront to the new App router directory as it has all of the examples your team will need to integrate Shopify in Next.js 13


We are very excited to share this starter kit with you, and we hope you find it useful for your projects. We are looking forward to hearing your feedback and suggestions to improve it, and add more features to it. Also, we are planning to add more starter kits to our collection, so stay tuned for more updates!

This Dot Labs is a development consultancy that is trusted by top industry companies, including Stripe, Xero, Wikimedia, Docusign, and Twilio. This Dot takes a hands-on approach by providing tailored development strategies to help you approach your most pressing challenges with clarity and confidence. Whether it's bridging the gap between business and technology or modernizing legacy systems, you’ll find a breadth of experience and knowledge you need. Check out how This Dot Labs can empower your tech journey.

You might also like

Setting Up a Shopify App and Getting Order Data cover image

Setting Up a Shopify App and Getting Order Data

Today, we are going on an adventure! We’re starting a three-part guide on creating a Shopify app and updating a customer's order with tracking information. For this article, it's assumed that you already have a Shopify store. If you want to skip ahead and look at the code, it can be found here. To start us off, we’ll use the Shopify Create app and then follow it up with retrieving customer orders. Shopify Create app Getting started with the Shopify Create app will be a quick and easy process. We’ll start by navigating to a directory where we want to create our app and run the following `shell yarn create @shopify/app. ` We’ll be greeted by a few different prompts asking for the project name, and building your app selection. Success! Now let's navigate into our new directory and do a yarn dev, and we’ll get a few options. We’ll choose to create it as a new app, add an app name, config name, and select the store we want to use. With that out of the way, we’ll open the preview by pressing the p button. It should automatically open it up in a window and show us an app install screen where we will click the Install app button. This should redirect us to our Remix app template screen Install__ Template__ Perfect! We now have a basic Shopify Create app up and running. Next, we will move on to adding in the ability to retrieve our customer orders. Orders query Alright, it’s customer order time! We’re going to be leaving the template mostly as is. We are going to focus on adding the call and verifying the data comes back. We’ll navigate over to our app/routes/app.index.jsx file and start changing the loader function. Start by removing: `js const { session } = await authenticate.admin(request); return json({ shop:"", "") }); ` And replacing it with: `js const { admin } = await authenticate.admin(request); const response = await admin.graphql( query getOrders { fulfillmentOrders (first: 30) { edges { node { requestStatus createdAt updatedAt status fulfillAt fulfillBy fulfillments (first: 10) { edges { node { createdAt deliveredAt displayStatus estimatedDeliveryAt id inTransitAt legacyResourceId name status totalQuantity updatedAt trackingInfo { company number url } } } } order { id name note createdAt displayFulfillmentStatus } assignedLocation { address1 address2 city countryCode name phone province zip } destination { address1 address2 city company countryCode email firstName lastName phone province zip } } } } } ); const responseJson = await response.json(); console.log("responseJson", responseJson); const orders = responseJson?.data?.fulfillmentOrders?.edges?.map( (edge) => edge.node ) || [[]]; return json({ orders: orders, }); ` Next, swap Wrap change { shop } in: `js const { shop } = useLoaderData(); ` With ` Orders ` Follow that up with changing `js useEffect(() => { if (productId) {"Product created"); } }, [productId]); ` To `js useEffect(() => { if (orders) {"Orders received"); } }, [orders]); ` Then, we’ll remove the View product button that has the old shop variable in it. When you go back and look at your application, you should see the Error: Access denied for fulfillmentOrders field. This is due to scopes that we haven’t updated. To fix this, we’ll head over to our file and replace `js scopes = “writeproducts” ` with `toml scopes = "writeproducts,read_orders,read_assigned_fulfillment_orders,read_merchant_managed_fulfillment_orders,read_third_party_fulfillment_orders,write_assigned_fulfillment_orders,write_merchant_managed_fulfillment_orders,write_third_party_fulfillment_orders" ` Here is what you should now have: `toml name = "blog-test" clientid = "" applicationurl = "" embedded = true [accessscopes] Learn more at scopes = "writeproducts,read_orders,read_assigned_fulfillment_orders,read_merchant_managed_fulfillment_orders,read_third_party_fulfillment_orders,write_assigned_fulfillment_orders,write_merchant_managed_fulfillment_orders,write_third_party_fulfillment_orders" [auth] redirecturls = [ "", "", "" ] [webhooks] apiversion = "2023-07" [pos] embedded = false [build] automaticallyupdate_urls_on_dev = true devstore_url = "" ` We’ll now do another yarn dev` which will tell us that our scopes inside the TOML don’t match the scopes in our Partner Dashboard. To fix this, we simply need to run: `shell yarn shopify app config push ` And then we’ll be prompted to confirm our changes with the difference shown. It will give us a success response, and now we can do another yarn dev to look at our application. Doing so brings us back to our old friend the app install page. Only this time it’s telling us to update the app and redirecting us back to the application page. Huh, seems like we’re getting a new error this time. For some reason, the app is not approved to access the FulfillmentOrder object. No worries, follow the link in that message. It should be[partnerId]/apps/[appId]/customerdata Here, we select the Protected customer data and just toggle Store management and save. After this, go down to the Protected customer fields (optional) and do the same thing for Name, Email, Phone, and Address. With that all said and done, we’ll exit the page. After that, go back to our application, and refresh it. Tada! It works! We will see a toast notification at the bottom of the screen that says Orders received and in our terminal console, we will see our orders returning. Conclusion That was an exciting start to our three-part adventure. We covered a lot, from setting up a Shopify app to getting our orders back and everything up and running! Next time, we’ll be digging into how to get our fulfillment ids, which will be needed to update a customer's order with tracking information....

Next.js 13 Server Actions cover image

Next.js 13 Server Actions

Introduction May 2023, Vercel announced that the App Router is recommended for production in the new version of Next.js v13.4, and it came with a lot of good features. In this article, we will focus on one of the best new features in the App Router: the Server Actions. Server Actions vs Server Components At first, you may think both Server Components and Server Actions are the same, but they are not. Server Components are featured in React 18 to render some components on the server side. On the other hand, Server Actions is a Next.js 13 feature that allows you to execute functions on the backend from the frontend. Back to Web 1.0 Before Single Page Applications frameworks, we were using HTML forms for most things. All you had to do was add a directory to their action attribute, and it would push the data to the server with each input name. No state was required, no async and await, etc. When Remix became open source last year, it introduced this idea again to the market. Its form actions would work even without JavaScript enabled in the browsers. It was mind-blowing. Next.js Server Actions are similar, with a wider range of use cases. They added a lot to it so you don’t only use them on HTML forms, but also on buttons and client components. How useful are Server Actions As I said in the section above, the Server Actions are like Form Actions in Remix and also they work on both Server and Client in a way similar to tRPC or Telefunc. Think about it. Instead of creating an API endpoint and making a fetch request to it from the client side, you execute a function that’s already on the server from the client like any other JavaScript function. Server Actions on the Server Side To make this post more effective, I’ll build a simple counter component with Server Actions. It runs even if JavaScript is turned off. First, create a new Next.js 13 App router project: ` npx create-next-app@latest ` Then, in the app/page.tsx, add a variable outside of the page component. `js let count = 0; export default function Home() { // ... } ` Then, add the Server Action, which is an async function with the “use server”; tag. `js let count = 0; export default function Home() { async function increment() { "use server"; count++; } return ( Count {count} Increment ) } ` After implementing the above, when you click on the increment button, you shouldn’t see the change until you refresh the page. You need to use revalidatePath to get a reactive state. `js import { revalidatePath } from "next/cache"; let count = 0; export default function Home() { async function increment() { "use server"; count++; revalidatePath("/"); } return ( Count {count} Increment ) } ` Now you have a Counter that can run with zero JavaScript. Server Actions on the Client Side You can also use the Server Action on the client component (it will be more like tRPC and Telefunc) to trigger a function on the server from the client and get data. But it will not work in the exact same way because in Next.js, each file has to be run on the server or the client. You can’t run the same file on both. So we need to move the function to its own new file, and add the ”use server”; tag on the top of the file. `js "use server"; export async function increment() { "use server"; count++; revalidatePath("/"); } ` We can import it from the client component, and use this server action there! Conclusion Server Actions are a great addition to Next.js, and it will make it easier to build full-stack applications that require a lot of work to be done in traditional frontend/backend ways like creating the API route, and then fetching it. I hope you enjoyed this article, and if you have any questions or feedback, feel free to reach out to us....

Introducing the new Expo, Styled Components, and Zustand Starter Kit cover image

Introducing the new Expo, Styled Components, and Zustand Starter Kit

Intro We are delighted to announce our brand new Expo React Native starter kit to our kits collection. We built this starter kit to enable our team members who work mostly with web technologies to make an easy transition for them to work on native mobile apps with their current knowledge without any extra effort. This Starter kit contains: - Expo a React native wrapper. - Styled Components lets you write actual CSS in your JavaScript-like web. - Zustand A small, fast, and scalable barebones state-management solution. - TypeScript JavaScript with syntax for types. - Jest is a delightful JavaScript Testing Framework with a focus on simplicity. - React Navigation Routing and navigation for Expo and React Native apps. Problems This Kit Addresses React Native Styling One of the most difficult things for React Native beginners is its styling system. It's difficult for people who come from a web background because it’s not similar to CSS at all. It has different units, and each property accepts a different value. For more information visit React Native Style Documentation styled-components/native` fixed that problem, you literally write CSS like for web and it translates the CSS code to a React Native Styles without any extra effort. Share Components Across Platforms Thanks to the Expo team, we can use the React Native components cross-platform, even with frameworks like Next.js. This saves teams a lot of work. Instead of building the same feature twice, one for the web and the other for the mobile apps, we only build it once. Let me show you an example: A lot of libraries in the React ecosystem use the setImmediate()` API (like react-native-reanimated). It’s a method used to break up long-running operations, and run a callback function immediately after the browser has completed other operations such as events and display updates, which Next.js doesn't polyfill by default. To fix this, you can polyfill it yourself. First, we need to install set immediate package yarn add setimmediate` Then import it in the app root pages/_app.js` import 'setimmediate';` Use the @expo/next-adapter` in the `next.config.js` `js const { withExpo } = require('@expo/next-adapter'); module.exports = withExpo({ / next.config.js code */ }); ` Add image support with next-images` `js const { withExpo } = require('@expo/next-adapter'); const withImages = require('next-images'); module.exports = withExpo( withImages({ projectRoot: dirname, }) ); ` Add font support with next-fonts` `js const { withExpo } = require('@expo/next-adapter'); const withFonts = require('next-fonts'); module.exports = withExpo( withFonts({ projectRoot: dirname, }) ); ` Now you can use your Expo React Native components in Next.js site. Skip the Tedious Steps of Installing React Navigation We use React Navigation in almost every project we work on, it’s a necessary piece of the app, so we already set it up so you can start your new app quickly. We also grouped the screens under the src/screens` directory, where each screen has its own folder with its related files. Defining a better organization pattern for components to scale your app We structured this project from our experiences with big React projects. One challenging part of using React is that it gives the developer a lot of freedom to choose their own file structure. However this is not good on a bigger app scale, because every developer has their own way to organize the files, and with a big React project that a lot of developers are working on, we usually end up with a mess. We figured this structure out from the previous projects we built. Imagine we have a component, and this component has different files like, testing, …etc Our way to structure the components is: Each component has its own folder: ` components/ FirstComponent/ SecondComponent/ ` Each folder has the component files ` components/ FirstComponent/ FirstComponent.tsx FirstComponent.test.tsx FirstComponent.stories.tsx // …etc SecondComponent/ SecondComponent.tsx SecondComponent.test.tsx SecondComponent.stories.tsx // …etc ` The problem now is the importing sentences gonna be ugly like this: `js import FirstComponent from ‘./components/FirstComponent/FirstComponent’; ` So it solve this, we add in each Component folder an index.ts` file with the following: `js export { default } from ‘./FirstComponent’; ` Now the folder structure will look like this: ` components/ FirstComponent/ Index.ts <- To solve the import sentences FirstComponent.tsx FirstComponent.test.tsx FirstComponent.stories.tsx // …etc SecondComponent/ Index.ts <- To solve the import sentences SecondComponent.tsx SecondComponent.test.tsx SecondComponent.stories.tsx // …etc ` Now the import sentence will be much cleaner: `js import FirstComponent from ‘./components/FirstComponent’ ` This can help keep your files and folders organized, and help scale your codebase with time. Conclusion This starter kit is the result of a lot of experience we gained on React projects we built internally and for clients. It helps you to start quickly without going through the tedious task of installing and setting up dev tools, and at the same time, it helps your app scale more easily....

Being a CTO at Any Level: A Discussion with Kathy Keating, Co-Founder of CTO Levels cover image

Being a CTO at Any Level: A Discussion with Kathy Keating, Co-Founder of CTO Levels

In this episode of the engineering leadership series, Kathy Keating, co-founder of CTO Levels and CTO Advisor, shares her insights on the role of a CTO and the challenges they face. She begins by discussing her own journey as a technologist and her experience in technology leadership roles, including founding companies and having a recent exit. According to Kathy, the primary responsibility of a CTO is to deliver the technology that aligns with the company's business needs. However, she highlights a concerning statistic that 50% of CTOs have a tenure of less than two years, often due to a lack of understanding and mismatched expectations. She emphasizes the importance of building trust quickly in order to succeed in this role. One of the main challenges CTOs face is transitioning from being a technologist to a leader. Kathy stresses the significance of developing effective communication habits to bridge this gap. She suggests that CTOs create a playbook of best practices to enhance their communication skills and join communities of other CTOs to learn from their experiences. Matching the right CTO to the stage of a company is another crucial aspect discussed in the episode. Kathy explains that different stages of a company require different types of CTOs, and it is essential to find the right fit. To navigate these challenges, Kathy advises CTOs to build a support system of advisors and coaches who can provide guidance and help them overcome obstacles. Additionally, she encourages CTOs to be aware of their own preferences and strengths, as self-awareness can greatly contribute to their success. In conclusion, this podcast episode sheds light on the technical aspects of being a CTO and the challenges they face. Kathy Keating's insights provide valuable guidance for CTOs to build trust, develop effective communication habits, match their skills to the company's stage, and create a support system for their professional growth. By understanding these key technical aspects, CTOs can enhance their leadership skills and contribute to the success of their organizations....