Skip to content

Best Practices

Site-Build Best Practices

Standards

Site-builds should be built according to our Genesis standards wherever possible

Redis

By default, Genesis is developed with Redis in mind.

If you are new to using Redis, review Our Redis Guide.

Configuration

Ensure Redis is connected by going to the Store Settings > Cache Configuration.

Status should say Connected.

If you are unable to connect, work with TAC to ensure Redis is available on the server.

During development, you will want to turn off Redis Caching. Once live, confirm Redis is connected, and turned on.

Store Settings > Cache Settings

Add the following Settings, if they're not already there:

Name Type Mode Value
utm_campaign Parameter Don't Include in Cache Key
utm_content Parameter Don't Include in Cache Key
utm_medium Parameter Don't Include in Cache Key
utm_source Parameter Don't Include in Cache Key
utm_term Parameter Don't Include in Cache Key

Check with the client to see if there any other parameters they use for tracking purposes. This includes, but is not limited to:

  • Ad Parameters (Google, Bing, etc.)
  • Email Marketing Parameters
  • Affiliate Link/Marketing Parameters

Page Cache

By default, most pages will have a cache level of Empty Baskets (Anonymous).

However, there are some pages that should have their Cache Page setting set to Never Cache This Page:

  • BASK
  • CTUS
  • INVC
  • JAPI
  • MNTN
  • SERT
  • GENESIS_EMPW
  • OAUTH_REDIRECT

Additionally, if you have/add a custom page that is used for API calls, you should consider setting those pages to Cache: Never as well as any pages with a C&L form (ex. CTUS page). An example of an API page would be a page that is loading in "Recently Viewed" items, or trigger an email (like sharing a wishlist).

Search Rule Configuration

By default, The Searchable Fields that will be enabled are:

  • Product Code
  • Product Name
  • Product SKU
  • Product Description

Any module that supports the fields_prod feature, will most likely support the search capability. For 3rd Party Modules, or older modules, this may not be the case.

Be careful with how many Searchable Fields you are enabling. The more you enable, the larger the SQL query becomes.

If you enable 25+ fields, that could cause some degradation when utilizing Miva's Native Search. Work with the client to be selective on what is and is not important to be searched, or see if some fields can be combined into 1.

Depending on the needs of the fields, you will want ensure the Search Type selected makes the best use of the field. By default, these are all set to Contains (Term).

We recommend only using Full Text Search to be used on fields where you don't need an exact string match (Example: Product Description, or Product Name). For all other fields, we recommend Contains (Term).

If you do need an exact match, use Exact Match. An example of this would be if a customer is used to typing in SKUs and is looking to get the exact SKU match in their search.

See more details here: Miva Docs - Expanded Search Rules

JavaScript

webpack

webpack Module Methods

Note

Suggested Reading: webpack > Module Methods

  • Static Imports will include the asset in the current chunk; thus increasing the bundle-size.
    • Example Syntax: import foobar from 'extensions/foobar.js'
    • This is similar to server-side concatenation that used to exist in our all.php or css.php files
    • Use this for assets that you need on-load for all customers, user-journeys, experiences.
  • Alternatively, Dynamic Imports will create a separate chunk for the assets that are being imported and it will asynchronously load in the asset.
    • Example Syntax: import('foobar')
    • This is similar to lazy-loading that we did through the loadScript() methods.
    • Use this if you have scenarios where customers may not experience a feature or where it may be below the fold and can be loaded in later.

Creating Extensions

When building with Genesis, you may need to build new features that are re-used throughout the site on various pages, so our recommendation would be to create a folder for each feature to encapsulate the CSS & JS of the feature. Then use the pages/ directory & files to import the feature on the pages it is needed.

For reference, feel free to review the different extensions that were created for the Duluth Pack build

Building in this method will keep your project code DRY, allow you to leverage Webpack imports/chunking, and eventually make it easy to share features with other projects & re-incorporate them into Genesis after the build is over.

Design Files & Design System

Currently, there is not a 1:1 mapping of what is represented in the design files that Design provides and how Genesis exists today. It is a known issue that we are planning to address in the next 0.7 release of Genesis.

Tons of feedback, notes, changes, & requests have been assembled and outlined, so please review the items described there to understand some potential challenges when styling with the current framework.

In the coming weeks, we will be working with Design and on Genesis to streamline and solve for these issues.

In the mean time, the project/build may experience some challenges & may need to make some compromises on the final output of the design, the amount of time it takes to make the framework match the mock-up, and more, so take note of these tips & ideas

  • Consistency & Acceptable Level of Tolerance
    • The Design files may have inconsistent margins, paddings, font-sizes, etc. where built-in Genesis features do not match the design 100% and are off by a pixel or two here or there. If there is time remaining for you to fix it, then please do. However, if you're low on time, this may be an opportunity for you to communicate the discrepancy to Design to see if a compromise can be made or if the PO will allow you more time to make the change.
  • It's ok to say, "No"
    • Similarly, there are times where Design mocks-up items that are time-consuming, scope-creep, or break the framework and require extra to to achieve.
    • Make every attempt, within the scope of the project's time-estimates, to meet the design-requirements, but notify the Designer & PO about elements that would take you over the estimated time.
    • You can also just describe the scenario & provide an estimate to the PO about what it would take to achieve the functionality and leave the decision about whether or not it is in-scope up to them.

SCSS

Theming & Overriding Variables

The best place to start when theming your site is going to be in the themes/genesis/src/_variables.scss file.

It starts off empty, so you can cherry-pick the variables & items that you want to override. You can reference the variables within the scss/config/_variables.scss file and copy them into your project's src/_variables.scss file as you need to customize/overwrite them.

Creating Mixins

Since there is not a 1:1 mapping of the Design files to Genesis at this time, we recommend creating SCSS mixins & utility classes to represent some of the concepts & components illustrated in the Design System file. For reference, see the Lighting Trendz variables file.

Misc.

Adding Additional Variables & Styles

The variables and styles within a Genesis store should always correspond with that clients UX Style Guide. If the client wants to add or change styles than what is in their style guide the best practice would be to recommend updating their style guide with those changes and define the hierarchy across the site where those variables are used.

Adding Pages

If you need to add some JS or CSS to a new page, then you can:

  1. Copy the themes/genesis/src/pages/_example folder
  2. Paste it in the pages/ directory and rename the folder & files to match the page-code you're adding. For example:
    • The pages/_example/ directory becomes pages/ABUS/
    • pages/_example/_example.js JS file becomes pages/ABUS/ABUS.js
    • pages/_example/_example.scss SCSS file becomes pages/ABUS/ABUS.scss
  3. Update the ABUS.js (previously _example.js)
    • Update import '_example.scss'; to the page-code import 'ABUS.scss';
    • Update export default class PAGECODE extends PageManager { to export default class ABUS extends PageManager {
  4. That's it.
    • Import additional dependencies within your JS file if need be
    • Initialize/execute your JS in the onReady function call.
    • Add your SCSS to the SCSS file too.

Dealing with Alternate Display Pages

If you're creating alternate display pages for PROD pages, then we recommend adding them within the themes/genesis/src/pages/PROD/ folder. Your directory structure might look like this:

Note

The following example also applies to CTGY Alternate Display pages as well

themes/
    genesis/
        src/
            pages/
                PROD/
                    PROD.js
                    PROD.scss
                    PROD_ALT.js
                    PROD_ALT.scss
                CTGY/
                    CTGY.js
                    CTGY.scss
                    CTGY_ALT.js
                    CTGY_ALT.scss

Then within the themes/genesis/src/theme.js file you have some options for importing those files using the screenImports object of the pageCodeImports object:

Alternate Display Pages: Shared Code

If the Alternate Display (ex. PROD_ALT) page shares many of the same features as the regular PROD page, then:

  • You can setup the PROD.js to contain all of the shared functionality for both pages.
  • Keep the PROD.js file in the theme.js file's screenImports section so that it is imported on PROD & PROD_ALT pages.
  • Add the additional/unique-to-PROD_ALT elements to to the PROD_ALT.js file and it to the pageCodeImports section.
  • This will ensure shared code for PROD pages are maintained in one location and extra code is only executed on the PROD_ALT page.

For example, he's an abreviated version of the theme.js showing how code can be shared.:

// ...

bootstrap({

    // ...

    screenImports: {
        // ...
        PROD: () => import( 'pages/PROD/PROD.js' ),
        // ...
    },

    pageCodeImports: {
        PROD_ALT: () => import( 'pages/PROD/PROD_ALT.js' )
    }

    //...

});

Alternate Display Pages: Separate Code

Alternatively, if the PROD and PROD_ALT pages are very different and do not share many of the same features, then:

  • In theme.js, move the PROD.js file from screenImports to the pageCodeImports section
  • Add the PROD_ALT.js file to the pageCodeImports
  • This will ensure each page has it's own unique set of code that will execute independently.

For example, he's an abreviated version of the theme.js showing how code can be separated.:

// ...

bootstrap({

    // ...

    screenImports: {
        // ...
    },

    pageCodeImports: {
        PROD: () => import( 'pages/PROD/PROD.js' ),
        PROD_ALT: () => import( 'pages/PROD/PROD_ALT.js' )
    }

    //...

});

NPM

Overriding, Extending, & Cherry-Picking Files

In themes/genesis/src/pages/Global.scss we import various packages' index files; which in-turn import additional sub-files for various features. There may be times where the scope of all the files that are included is more than you need or they are imported in an order that doesn't work for you. When that is the case, you can pick and chose which files are imported.

For example, by default in Global.scss it has the following imports:

@import "variables";
@import "scss/styles";
@import "extensions/icons/index";
@import "extensions/messages/index";
@import "extensions/transfigure-navigation/index";
@import "extensions/breadcrumbs/index";
@import "extensions/search-preview/index";
@import "extensions/mini-basket/index";
@import "extensions/carousel/index";
If you didn't like all of the imports that occur with in extensions, you could omit that import re-create the import how you want it. For example, (this is not recommended), but if you didn't want to import Genesis' search preview objects and you wanted to use another 3rd-party CSS-layout-framework, then you could do something like this:

@import "variables";
@import "scss/styles";
@import "extensions/icons/index";
@import "extensions/messages/index";
@import "extensions/transfigure-navigation/index";
@import "extensions/breadcrumbs/index";

//@import "extensions/search-preview/index";
@import "custom-extensions/search-preview/index";

@import "extensions/mini-basket/index";
@import "extensions/carousel/index";

Note

The above concept can apply to any extensions/ import for other packages and other SCSS or JS files.

Accessibility

Animations / Transitions for users who prefer reduced motion

When adding a transition or animation, please reference the following below for examples on how to check if a user prefers reduced motion.

SCSS

Add the media query around your transition or animation to only run for users who have no preference on motion/animation.

// Transition Example
@media ( prefers-reduced-motion: no-preference ) {
    transition: all 200ms ease-in;
}

// Animation Example
@media ( prefers-reduced-motion: no-preference ) {
    animation: miniBasketSlideOut 150ms cubic-bezier(0.4,0.01,0.1,1);
}

JS

Detect the media query in javascript to wrap any references to animation (event listeners, and plugins).

// Determine if user want reduced motion. If they do, no animations.
const allowAnimation = window.matchMedia('(prefers-reduced-motion: no-preference)').matches;

if (allowAnimation) {
    const animationHandler = () => {
        this.rootElement.classList.add(this.hiddenClass);
        this.rootElement.removeEventListener('animationend', animationHandler, false);
    };

    this.rootElement.addEventListener('animationend', animationHandler, false);
}

How to Test

Disable animations on your computer. Use one of the following links to turn them off:

Visit your Genesis Development Store and ensure functionality still works with animations turned off.

Production Sync Incremental Commits

Terminal
git add -A && git diff --cached -w | git apply --cached -R && git commit -m "production sync of whitespace changes"
git add \*.json && git commit -m "production sync of json files"
git add -A && git commit -m "production sync of template changes"