Helper functions for Sitecore front-end development
Practical TypeScript helpers that keep Sitecore front-end code clean, consistent, and easy to work with.
Start typing to search...
While working on Front End Development, specifically with Sitecore, there can be some instances where there are a few common code snippets or small blocks of logic that repeatedly show up across components. Other times it's simply a matter of cleaning the code and making it tidier for a fellow dev who will eventually maintain or update the work. Throughout different projects, we've put together a handful of simple helper functions that help us internally deal with these scenarios more efficiently. They reduce repetitive logic, encourage consistency, and give developers a smoother way to handle data transformations, styling, or common UI patterns. This blog goes over a compilation of these simple TypeScript functions that improve quality of life while coding on Sitecore Front-End Development and make the development process smoother and easier to read. Most of the functions here help simplify the code within a file and make logic reusable across multiple components, making the implementation more compact and improving its readability. Below each description you will find the code snippets on how to set them up and right below that, an example on how to use them in the code. Although small, these helpers can add a noticeable layer of polish to your codebase and make everyday development a little more comfortable.
This function for JSX files combines multiple class names and merges CSS classes intelligently. It uses the clsx and tailwind-merge libraries, and it takes an array of class values to be merged, returning a deduplicated final class string. The great thing about this simple function is that it allows you to work with dynamic and conditional classes within the HTML elements in your JSX file without cluttering your markup. For instance, it's a straightforward and easy way to set Boolean variables that add or remove a class from an element depending on some condition.
/* SET UP */
import clsx, { ClassValue } from 'clsx';
import { twMerge } from 'tailwind-merge';
// With Tailwind
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs));
}
// Without Tailwind
export function cn(...inputs: ClassValue[]) {
return clsx(inputs);
}
/* USAGE */
const isConditionTrue = true;
const dynamicClasses = 'additional-classes';
// ...
<div classsName={cn('static-class', isConditionTrue && 'dynamic-class', dynamicClasses)} >
<p>Some text</p>
</div>
This works beautifully with Tailwind classes, since Tailwind often encourages long utility chains, but it can just as easily be used in non-Tailwind setups to keep conditional class logic clean, expressive, and predictable. At the end we end up with JSX code that is intuitive, and allows other developers at first glance to understand which classes are static and which ones are dynamic and dependent on variable values.
This function is an extension of what was used in another blog about how to use the Styling and Advanced Styling sections in the Page Builder, which you can check out here. When setting a value on a styling item with a specific pattern, this function can break that value apart within a rendering and return it as an object that is easier to manipulate throughout the code. It essentially takes the string values generated from all the styling applied to the rendering either through the Page Builder or directly in the Content Editor and bundles them into an object whose keys and values match the dynamic properties you've configured in Sitecore.
/* SET UP */
export type SitecoreStylesProps = {
params?: {
Styles: string;
};
Styles?: string;
};
export type SitecoreStyles = { [key: string]: string | string[] };
export const getStyles = (props: SitecoreStylesProps): SitecoreStyles => {
let styles = props?.params?.Styles;
if (!styles) styles = props?.Styles;
const stylesObj: SitecoreStyles = {};
styles?.split(' ').forEach((style: string) => {
const [key, value] = style.split(':');
if (stylesObj[key]) {
stylesObj[key] = Array.isArray(stylesObj[key])
? [...stylesObj[key], value]
: [stylesObj[key] as string, value];
} else {
stylesObj[key] = value;
}
});
return stylesObj;
};
/* USAGE */
// When setting the value to a background styling item as "backgroundColor:blue" in Sitecore
import { getStyles, SitecoreStylesProps } from '.../sitecore-styles';
const styles = getStyles(props as unknown as SitecoreStylesProps);
const backgroundColor = styles.backgroundColor; // Output: "blue"
/*
Due to the dynamic nature of setting the open-ended options as Styling items
in Sitecore, the unknown keyword is needed to bind the properties type from
the rendering into SitecoreStylesProps used in the helper function.
*/
This structure makes it far more intuitive to work with styles programmatically and simplifies logic that might otherwise involve repeated string parsing. The function also supports cases where a multiple-choice field is used in Sitecore, returning an array of values for that style. For example, if you allow editors to independently set padding for the left, right, top, and bottom of a component, each selected value is captured cleanly without requiring extra handling in your component.
This set of string helpers inside the tool function simply called s is aimed at handling small but common operations that show up repeatedly across a project. Starting with prefix and suffix functions, these helpers come in handy for situations where strings need consistent formatting, such as naming variables, files, or adding symbols or punctuation in text. These utilities first detect whether the input already contains the required prefix or suffix to prevent accidental duplication due to unpredictable authoring or varying input formats. You can then easily add or remove both prefixes and suffixes as needed.
/* SET UP */
export const s = {
prefix: (char: string) => ({
add: (str: string | undefined) => (!str ? '' : str?.startsWith(char) ? str : `${char}${str}`),
remove: (str: string | undefined) => (!str ? '' : str?.startsWith(char) ? str?.slice(1) : str),
}),
suffix: (char: string) => ({
add: (str: string | undefined) => (!str ? '' : str?.endsWith(char) ? str : `${str}${char}`),
remove: (str: string | undefined) => (!str ? '' : str?.endsWith(char) ? str?.slice(0, -1) : str),
}),
truncate: (text: string, maxLength: number, suffix = '...') => {
if (!text || text.length <= maxLength) return text;
return text.substring(0, maxLength).trim() + suffix;
}
}
/* USAGE */
const text1 = 'Date';
const text2 = 'test_name';
const text3 = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Cras vestibulum eget erat vitae scelerisque';
const example1 = s.suffix(':').add(text1); // Output = "Date:"
const example2 = s.prefix('test_').remove(text2); // Output = "name"
const example3 = s.truncate(text3, 5); // Output = "Lorem..."
The final function in this group helps truncate text to a specific number of characters, which is particularly useful when design requirements prevent enforcing strict limits through CSS alone. It offers a quick way to ensure long content doesn't overflow UI boundaries or break layouts, all while giving you control over the truncation indicator. This tool could also be expanded with custom functionality specific to your project needs.
This function simply centralizes the logic needed to generate the placeholder name string for dynamic placeholders in Sitecore. Each placeholder is identified by a key and a Dynamic Placeholder ID, which is passed down to a rendering through its parameters. By passing these parameters to the function, along with the key that identifies the placeholder, you get the fully formatted name returned and ready to be used in the <Placeholder /> JSS component.
/* SET UP */
export const placeholderGenerator = (params: ComponentParams, placeholderName: string) =>
`${placeholderName}-${params.DynamicPlaceholderId}`;
/* USAGE */
<Placeholder
name={placeholderGenerator(params, 'key')}
rendering={rendering} />
The overall idea behind this helper is to avoid repeating string concatenation logic directly inside the component, keeping the markup leaner and reducing the risk of typos or inconsistent formatting across different renderings.
In this last case, more than a function, this is an example showing how to use constant string values as both runtime values and TypeScript types which has proven to be really helpful in multiple scenarios. The benefit of this pattern is that your constants double as the canonical strings used in the code, avoiding typos and enforcing consistency across all components that reference them. In this specific example, we apply this approach to Headless Variants, specifically for a Tabs component that supports multiple layouts, such as a horizontal version and two different vertical layouts. Using this structure, we allow the developer that sets it up to control all the variables especially on a team with multiple developers where different mindsets on how to approach a task.
/* SET UP */
export const TAB_LAYOUTS = {
HORIZONTAL: 'horizontal',
VERTICAL_LEFT: 'vertical-left',
VERTICAL_RIGHT: 'vertical-right',
} as const;
export type TabsLayout = (typeof TAB_LAYOUTS)[keyof typeof TAB_LAYOUTS];
/* USAGE */
const TabsContainerComponent = (props: TabsContainerProps): JSX.Element => {
return (
<Frame params={props.params}>
<ContainedWrapper>
<TabsContainer {...props} />
</ContainedWrapper>
</Frame>
);
};
export const Default = (props: ComponentProps): JSX.Element => (
<TabsContainerComponent {...props} layout={TAB_LAYOUTS.HORIZONTAL} />
);
export const VerticalLeft = (props: ComponentProps): JSX.Element => (
<TabsContainerComponent {...props} layout={TAB_LAYOUTS.VERTICAL_LEFT} />
);
export const VerticalRight = (props: ComponentProps): JSX.Element => (
<TabsContainerComponent {...props} layout={TAB_LAYOUTS.VERTICAL_RIGHT} />
);
export type TabsContainerProps = ComponentProps & {
layout: TabsLayout;
};
With this type of approach, when a new variant needs to be introduced later down the line, the developer would simply need to add another entry to the constant object; the associated type updates automatically because it's derived from that constant, minimizing room for human error and ensuring TypeScript enforces the expected layout values wherever they're used. These constants are passed down into the component to determine which tab layout should render, and the generated type is used in the component props so only valid constant strings can be passed in. As mentioned previously, while this example uses tabs, this same pattern is flexible and can be used in many scenarios involving variant logic or configuration options.
There is an increasing number of libraries and built-in functionality that already take on much of the heavy lifting in modern development, especially today, when even complex scenarios can sometimes be solved with a single AI prompt. These functions are not intended to be a be-all and end-all solution, but rather a look at the small tools that have genuinely helped us improve everyday tasks while coding. They encourage cleaner and simpler solutions, reduce repetition, and make it easier for developers to leave codebases in a good state for the next person. If anything, the hope is that these examples offer inspiration to adopt similar approaches and make your own development workflow a bit more enjoyable.