Skip to content


Serving Multiple Websites and Business Logic From a Single Platform

February 9, 2021


Daniel Shafer

Restaurants’ online ordering needs vary greatly, spurring us to build the capability for customized visual and functional experiences on our platform. Our most recent effort, Storefront, required building custom frontend logic to serve a new experience on the same platform as DoorDash and Caviar, our two branded experiences.

While restaurants available through our DoorDash and Caviar frontends use a common interface design, Storefront lets restaurants build their own branding into the frontend experience. These individually branded websites are maintained by DoorDash and fulfilled by the Dasher delivery driver network so that restaurants can focus on what they do best: creating great food. In order for Storefront to meet restaurant needs, the websites require specialized business logic in their visuals.

We previously re-engineered our frontend so we could serve both the DoorDash and Caviar experiences from the same platform, as described in this article. Adding Storefront worked from similar principles, with additional engineering around unique business logic.

Creating Storefront gives us new tools that will help us serve the restaurant community even better, helping them reach customers and reinforce their brands.

Playing catchup

The Storefront and DoorDash frontends used two separate client-side applications that were nearly identical to each other, as a result of the former being a fork of the latter’s repository. These applications made almost all the same API calls and shared an Express server. Most engineers at DoorDash, outside of the immediate development teams, would assume feature parity between the DoorDash and Storefront applications.

Having to build and maintain a website that is materially the same yet occasionally diverging from another website means spending a meaningful amount of time maintaining parity between the two. In our case, the effort of keeping Storefront up to the latest changes implemented on DoorDash required significant effort. We began to reason that we could minimize this effort by running both sites from a combined codebase. 

Identifying the differences

A website is an orchestration of content, styling, and behavior. To scope this project, we needed to identify where those three things diverge on the Storefront experience relative to DoorDash’s. Those divergences, spanning about 25 different files, fell into the following four categories supporting: 

  • A new menu banner showing basic information about the current session, such as where a customer will need to go to pickup an order, as well as a link that takes them back to the business landing page, if needed. Hiding DoorDash-specific elements, such as disclaimers at the bottom of the menu page, DashPass icons, and the group order button. Enabling support for setting the fulfillment type toggle to pickup from a URL parameter.
  • The experience provider facilitating switching on the Storefront experience throughout the app.
  • Custom headers and footers with Storefront-specific content, such as copyright information. Bypassing the login page that a guest user on the DoorDash site would be directed to.
  • Guest checkout as well as adding contact and payment method information. Giving consumers the ability to opt-in to marketing on the checkout page. 

Serving new logic on the Storefront website 

Implementing the features identified above required enabling both functional and visual elements that could be served dynamically. We first moved guest checkout, a unique feature of Storefront, and then proceeded to enable other visual differences with our experience provider. Guest checkout, which lets customers place an order without creating an account, is a feature unique to Storefront. After migrating this functionality, we moved the visual pieces into production one at a time. 

One of the ways that DoorDash, Caviar, and Storefront are able to share the same codebase is through the use of a mechanism called an “experience provider”, which conditionally shows or hides rendered elements to consumers. The following example shows how we serve specific graphical elements for different web experiences:

  <DashpassIcon />
  <CaviarIcon />

The experience provider lets us show a specific brand experience depending on which site is being visited. Furthermore, the experience provider exposes a set of boolean values that can be used to switch behavior depending on which version of the codebase that’s being browsed.

Creating dynamic business logic

The differing business logic between DoorDash and Storefront meant we had to support branching behavior between the experiences. For example, the navigation between a restaurant’s menu page and the checkout page required different logic depending on the web experience being used. Both the DoorDash and Caviar experiences check that the current user is authenticated when they select items from a menu then click the checkout button. If they are not, they are redirected to a login page before the checkout page. 

By contrast, Storefront supports guest users. As a result, if the navigation behavior matched that of DoorDash and Caviar, the experience would be broken. To enable guest users on Storefront, we used our experience provider’s support for boolean values to switch behavior based on the experience the current user is viewing: isStorefront, isCaviar, and isDoorDash. The condition to navigate a user to the login page looks something like this:

const shouldRedirectToLogin = !isStorefront && consumer.isGuest

If the current user is not already logged in and is not viewing the Storefront experience, then shouldRedirectToLogin will evaluate to true. Conversely, if the user is on Storefront, this condition will evaluate to false regardless of anything else and thus the behavior stemming from shouldRedirectToLogin is circumvented. 

In all, there are seven instances of ShowOnlyOnStorefront, 21 instances of HideOnlyFromStorefront, and a few dozen instances where behavior is switched based on the isStorefront boolean.

Setting the visual style

On the visual side, we leveraged the experience provider to serve distinct web experiences. Going from having two experiences, DoorDash and Caviar, to three, with the addition of Storefront, led us to realize that we needed not just a new <ShowOnlyOnStorefront> element, but a <HideOnlyFromExperience> element as well. 

By adding the new <ShowOnlyOnStorefront> along with the <HideOnlyFromStorefront>, <HideOnlyFromCaviar>, and <HideOnlyFromDoorDash> elements, we were able to granularly control every element of the website where conditionally showing or hiding visual elements was required. These new elements made developing Storefront much easier because we removed the risk of impacting the other website experiences.


We took a partial quote from HappyFunCorp, “focus on the part that makes the application different rather than the stuff that makes it the same”, as an axiom for this project. With this project wrapped up in December, 2020, we no longer have to worry about maintaining a fork of the DoorDash web experience, and thus are free to, as the quote suggests, focus on what makes the Storefront experience different from DoorDash’s, rather than what makes it the same. 

With the implementation of this project, there is no longer a second set of APIs who’s contracts need to be maintained, which is a huge time saver for both the marketplace and Storefront teams. Additionally, a lot of new features that are created for the marketplace are available for Storefront by default. We also chalked up a big win for cross-functional collaboration with this project. In collaboration with another team, the Storefront folks were able to bring the long-requested feature of merchant tips to both sites simultaneously.

Companies serving retail clients at scale, such as DoorDash, need to offer branding capabilities appropriate for everything from a neighborhood shop to a national chain. Our experience shows how a single platform can not only offer unique visual experiences, but functional differences as well.


My co-captain on the project, Mayur Sirwani, as well as Omendra Rathor, Giorgi Pilpani, Max Presman, Maria Chung, Frankie Liu, from the Storefront team, and Hana Um, Keith Chu, and Patrick El-Hage from Caviar and the marketplace teams deserve explicit shoutouts. Thanks so much for everything you did!

Header photo by Michael Dziedzic on Unsplash.

Related Jobs

San Francisco, CA; Seattle, WA; Sunnyvale, CA
San Francisco, CA; Seattle, WA
San Francisco, CA; Sunnyvale, CA; Los Angeles, CA; Seattle, WA; New York, NY
San Francisco, CA; Sunnyvale, CA; Seattle, WA
San Francisco, CA; Sunnyvale, CA