ReactOrganizational Conventions

The core building block of Pup's user interface is React components. In Pup, there are several components pre-defined for you that can either be used as-is, or modified to fit the particular needs of your product.

Layout, page, component diagram.
Layout, page, component diagram.

Components in Pup are split into three directories, nested under the /ui directory at the root of the project:

  • /ui/layouts - Components that are responsible for building layouts that combine a set of static elements (e.g., the application's navigation bar) with dynamic elements. In Pup, the <App /> component serves as the main layout component and is used to render every page in the application.
  • /ui/pages - Components that are compositions of other components, rendered within the dynamic portion of a layout component and corresponding to a particular route in the application (e.g., the /login route renders the <Login /> page component). Some page components are wrapped with Apollo component enhancers to provide them with data via GraphQL.
  • /ui/components - Standalone components that can be used independently or composed together with other components in a page.

Organizing Component Directories

While components are split into the three sub-directories outlined above within the /ui directory at the root of the project, all components themselves follow a similar directory structure.

For example, let's consider the <Login /> page component defined at /ui/pages/Login in the app. If we look inside this folder, we'll find a few different files:

  • index.e2e.js - The end-to-end tests for the component, defined using TestCafe.
  • index.js - The actual component definition.
  • styles.js - The CSS styles for the component, defined using styled-components.

This is the recommended pattern for defining components in Pup. Here, our goal is to isolate all of the code related to a single component in its own folder. You're encouraged to place any files specific to a component in this directory (e.g., if you'd like to add unit tests to your components, you could add a file like index.test.js).

The index convention here is adopted from Node.js. When imported into another file, index files are implied, meaning, if we write an import statement like this:

import Login from '/ui/pages/Login';

We're effectively saying "load the index.js file located at /ui/pages/Login/index.js." In other words, including the index.js at the end is optional.