DEV Community

Cover image for How are we structuring Front End at Helixa
omar assadi
omar assadi

Posted on • Updated on

How are we structuring Front End at Helixa

Here at Helixa we are at the beginning of a long journey when talking about Front End Development since we are creating the basis for all our future projects.

The goal

We are going to build multiple client side SaaS applications with a central application called Account that will work as an Identity Server.

All future apps will need to share multiple components and look alike but with a custom Palette for visually differencing products one from another.

A common language

In order to share a common language with our UX/UI Designer we follow the Atomic Design principles (check out Brad Frost's post about Atomic Design) and started building Atoms, Molecules and Organisms that we'll need in order to implement our products' front end.

Since we will need to share and reuse components throughout all of our future apps we started from building a components library called hx-react-components that will also work as the source of truth for how every component should look and work.

Stack and Tools

Here's a list of libs and tools the Helixa Front End Team deals with.

React: React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called “components”.

Styled Components: Utilising tagged template literals (a recent addition to JavaScript) and the power of CSS, styled-components allows you to write actual CSS code to style your components.

Storybook: Storybook is an open source tool for developing UI components in isolation for React, Vue, and Angular. It makes building stunning UIs organized and efficient.

Helixa Components Storybook

Storybook: https://storybook.js.org

CirlceCi: CircleCI’s continuous integration and delivery platform makes it easy for teams of all sizes to rapidly build and release quality software at scale.

Helixa Components CircleCi

CircleCi: https://circleci.com

Our own components library

First: why writing a component library ?

Dev Velocity: Don’t impair the library’s adoption, enabling developers to collaborate and evolve the components.

Consistency: Keep consistency but leave room to play when possible.

Maintenance & Standardization: Unify your tech stack and simplify maintenance through smart architectures and tooling.

Performance: Don’t use cross-libraries whenever possible, use individual components instead of the whole library.

Discoverability: Leverage discoverability platforms to help developers find and use the components they need.

The process

This is a common structure of a component folder:

Helixa Component Folder Structure

Every component has:

  • The Component.js Implementation file.
  • A StyledComponent.js file
  • A Component.stories.js file that describes the it's showcase page on Storybook.
  • A Component.spec.js with all the unit tests.

We've set unit tests coverage at 80% minimum.

This is how we work: every task (A new component, a fix etc etc) has it's own branch and goes trough the same flow:

  • Pull Request to Master
  • Review
  • Merge

Every time a new commit comes on any branch our CI (CircleCi) will run a list of unit tests.

On every commit on master branch our CI runs multiple sequential jobs:

  • Runs unit tests
  • Build a Storybook static version
  • Deploys the new version on AWS (http://components.helixa.ai)
  • Updates the package version (via npm version)
  • Publish the new package on NPM
  • Push changes to git

Handling SVGs Icons

All apps need icons and this is how we consume svgs at Helixa.

We have a git repository where UX/UI team can easily add Svg files.
On every push on master branch the amazing husky will run a script for us:

Basically all svgs files added to the /src folder get optimized using svgo and the their svg mono path gets extracted (thanks to extract-svg-path).

An icons.json file is then written like so:

{
  "alert": "M18,26h4v4h-4V26z M20,10c1.1,0,2,0.9,2,2v8c0,1.1-0.9,2-2,2s-2-0.9-2-2v-8C18,10.9,18.9,10,20,10z M20,40c11,0,20-9,20-20 S31,0,20,0S0,9,0,20S9,40,20,40z",
  "add": "M37.1,22.9H22.9v14.3c0,1.6-1.3,2.9-2.9,2.9s-2.9-1.3-2.9-2.9V22.9H2.9C1.3,22.9,0,21.6,0,20s1.3-2.9,2.9-2.9 h14.3V2.9C17.1,1.3,18.4,0,20,0s2.9,1.3,2.9,2.9v14.3h14.3c1.6,0,2.9,1.3,2.9,2.9S38.7,22.9,37.1,22.9",
  "arrow_down": "M1.7,16.5L16.1,32c2.2,2.3,5.7,2.3,7.9,0l14.4-15.5c3.5-3.8,1-10.2-4-10.2H5.5C0.6,6.4-1.9,12.8,1.7,16.5",
  "arrow_up": "M38.3,23.5L23.9,8c-2.2-2.3-5.7-2.3-7.9,0L1.6,23.5c-3.5,3.8-1,10.2,4,10.2h28.9C39.4,33.6,41.9,27.2,38.3,23.5",
  "chevron_down": "M22.5,30.6L39,14.2c1.4-1.4,1.4-3.7,0-5c-1.4-1.4-3.7-1.4-5,0L20,23L6.1,9.2c-1.4-1.4-3.7-1.4-5,0s-1.4,3.7,0,5 l16.4,16.4C18.8,32,21.1,32,22.5,30.6",
  "chevron_up": "M17.6,9.2L1.1,25.6c-1.4,1.4-1.4,3.7,0,5c1.4,1.4,3.7,1.4,5,0l14-13.8L34,30.6c1.4,1.4,3.7,1.4,5,0s1.4-3.7,0-5L22.6,9.2 C21.3,7.8,19,7.8,17.6,9.2",
  "delete": "M6.7,35.6c0,2.4,2,4.4,4.4,4.4h17.8c2.4,0,4.4-2,4.4-4.4V13.3c0-2.4-2-4.4-4.4-4.4H11.1c-2.4,0-4.4,2-4.4,4.4 V35.6z M33.3,2.2h-5.6l-1.6-1.6c-0.4-0.4-1-0.6-1.6-0.6h-9.3c-0.6,0-1.2,0.2-1.6,0.6l-1.6,1.6H6.7c-1.2,0-2.2,1-2.2,2.2 c0,1.2,1,2.2,2.2,2.2h26.7c1.2,0,2.2-1,2.2-2.2C35.6,3.2,34.6,2.2,33.3,2.2z",
  "done": "M12.3,29.3L4.1,21C3.1,20,1.6,20,0.7,21c-0.9,0.9-0.9,2.4,0,3.4l10,10c0.9,0.9,2.4,0.9,3.4,0L39.3,9.1 c0.9-0.9,0.9-2.4,0-3.4c-0.9-0.9-2.4-0.9-3.4,0L12.3,29.3z",
  "download": "M22.2,21.5l4.2-4.2c0.9-0.9,2.3-0.9,3.1,0c0.9,0.9,0.9,2.3,0,3.1l-8,8c-0.9,0.9-2.3,0.9-3.1,0l-8-8c-0.9-0.9-0.9-2.3,0-3.1 c0.9-0.9,2.3-0.9,3.1,0l4.2,4.2V2.2C17.8,1,18.8,0,20,0s2.2,1,2.2,2.2V21.5z M35.6,22.2v11.1c0,1.2-1,2.2-2.2,2.2H6.7 c-1.2,0-2.2-1-2.2-2.2V22.2c0-1.2-1-2.2-2.2-2.2S0,21,0,22.2v13.3C0,38,2,40,4.4,40h31.1c2.4,0,4.4-2,4.4-4.4V22.2 c0-1.2-1-2.2-2.2-2.2S35.6,21,35.6,22.2z",
  "edit": "M0,32.1v6.8C0,39.5,0.5,40,1.1,40h6.8c0.3,0,0.6-0.1,0.8-0.3l24.3-24.2l-8.3-8.3L0.3,31.3 C0.1,31.6,0,31.8,0,32.1 M39.4,9c0.9-0.9,0.9-2.3,0-3.1l-5.2-5.2c-0.9-0.9-2.3-0.9-3.1,0L27,4.7l8.3,8.3L39.4,9",
 ...
}
Enter fullscreen mode Exit fullscreen mode

Now any consuming project will no longer need to point to some hosted svg files but can recreate the svg on the fly by simply passing the path described in the icons.json file:

import React from 'react';
import { StyledIcon } from './StyledIcon';
import icons from 'hx-icons/icons';

const Icon = ({ className, ...rest }) => {
  const fallback =
    'M79.1545988,120.621554 C75.1703482,120.614249...';

  if (!rest.icon) {
    return null;
  }

  const d = icons[rest.icon] ? icons[rest.icon] : fallback;

  return (
    <StyledIcon {...rest}>
      <svg
        xmlns="http://www.w3.org/2000/svg"
        viewBox={`0 0 40 40`}
        className={className}
      >
        <path d={d} />
      </svg>
    </StyledIcon>
  );
};
Enter fullscreen mode Exit fullscreen mode

Next Steps

We are just at the beginning of the path but very excited of what's coming next.

We've started testing the amazing e2e framework Cypress that looks very promising. We'll soon talk about that in a future blog posts so stay in touch.

Do you like this approach? If you are interested in working here at Helixa take a look at our careers page

Top comments (0)