9 Best Customer Service Software for Business in 2021 (Compared)

Are you looking for the best customer service software for your business?

Using the right customer service software can streamline your customer support workflow and help you create better customer relationships.

In this article, we’ve hand picked some of the best customer service software that you can use along with your WordPress site. We’re using these tools in our various businesses to help deliver top-notch customer support.

9 best customer service software for business in 2021 (compared)

Why Use Customer Service Software?

Customer service software makes it easy for your business to provide a great customer experience. This leads to improved customer retention, which means more revenue for your business over the long run.

As your WordPress website or online store grows, it can be hard to maintain high customer satisfaction, but the customer service software makes this easy.

Since customers will make or break your success, investing in the right support software stack can give you a competitive advantage.

The best customer service software:

  • Enables you to deliver a faster and more consistent support experience
  • Lets you gather customer insights and data to improve your business
  • Allows you to scale up your customer support easily as your business grows
  • Helps you build a more efficient customer service team

That being said, let’s take a look at the top customer support software that you can use along with your small business website.

1. Help Scout

Help Scout

Help Scout is one of the best all in one customer support tools. It’s packed with nearly every feature you need to streamline your customer support processes.

Note: we use Help Scout here at WPBeginner and across all of our other businesses for our email support needs.

It lets you simply manage your email and chat support from a single tool. This lets your customers contact you from where they feel the most comfortable, and your team can work from a single support queue.

Your customer support team can create saved replies, so they can quickly respond to common questions and save time.

There’s a knowledge base feature that lets you build your own help center. This makes it easy for your customers to find the answers they need on their own while reducing the number of support requests.

Help Scout also provides detailed reporting data and metrics, so you can quickly get an overview of what’s working and where your team can improve. Their time tracking report helps you see where your agents are spending the most time, so you can improve your product workflows to improve time to resolution.

For business owners who want to add more support channels, there’s a live chat feature available. It’s not as powerful as other market leading live chat software, but it can be a good solution for many businesses.

Help Scout Live chat feature also known as Beacon has a self-service answer feature that recommends articles to your users. If they can’t find an answer, then they can quickly start chatting with your team.

Plus, there are over 40 integrations with tools your business is using like HubSpot, Slack, Google Apps, WooCommerce, and more.

Pricing: An affordable Basic plan starts at $20 per user per month. This provides 3 mailboxes, live chat, and more. Bigger teams can opt for the Plus plan that starts at $35 per user per month.

2. LiveChat

LiveChat

LiveChat is the best live chat software in the market today. It’s very flexible and feature rich, plus there’s a WordPress plugin that makes it easy to integrate with your website.

The LiveChat apps are very easy to use and work across mobile, desktop, and tablet devices. So, you don’t have to be logged in to WordPress to access your customer service hub.

You can set up LiveChat to work during your team’s off hours so that live chat requests will go directly to your support ticket management system.

Note: we use LiveChat across all of our eCommerce businesses to support our pre-sales staff. Their customization options make it easy to match the chat window to our company branding.

One stand out feature of this service is speed. The chat window loads much faster, has a better user experience, and works across every device. A lot of other live chat providers can’t match this.

When it comes to customer support, speed is essential, and this tool shines.

It integrates with nearly all the marketing services you’re already using, like Google Analytics, HelpDesk, and HubSpot.

You’ll find many additional tools to elevate support quality like visitor tracking, smart API that integrates with your knowledge base, and proactive chat.

The thing that we absolutely love about Live Chat is that they focus on sales conversion. They have built-in conversion tracking, and they have additional tools to help you get more leads / sales.

Pricing: You’ll find different plans for all businesses sizes. The starter plan begins at $16 per agent per month for a yearly plan, or $19 monthly. Every plan has a 14 day free trial to test out the service.

Deal: WPBeginner readers can get 30% off the first payment by using our LiveChat coupon code.

3. Nextiva

Nextiva

Nextiva is the best business phone service provider in the market today. They also offer a customer service CRM that’s very simple and easy to use.

It offers your business multichannel support including, email, phone, live chat, social media, and SMS messaging. You can view customer data from every source in a single dashboard.

Plus, you can respond to inquiries from one place, no matter how your customers reach you.

If you’re using other Nextiva services like Nextiva business VoIP or the Sales CRM, then these can integrate instantly.

You’ll find other features like call routing, a self-service knowledge base, canned responses, and a mobile app.

Note: we use Nextiva at WPBeginner for all of our phone support needs. If you need to offer phone support, then it’s the best option available.

There are a ton of other powerful features to help your phone support team as well, like call forwarding, call routing, custom greetings, call analytics, virtual business phone number, and a lot more.

Nextiva is a perfect platform for both small businesses as well as large call centers who’re looking for a customizable solution to help automate their sales and support contact center.

Pricing: The plans start at $18.95 per month for between 20-99 users. If you want support for SMS and additional integrations, then the Pro plan starts at $22.95 per month.

4. ChatBot.com

Chatbot.com

ChatBot.com is the best chatbot software in the market today. It make it easy for small business owners to unlock the power of AI chatbots to improve customer service.

It’s effortless to create your customer service chatbot with the drag and drop interface.

You can also use one of their pre built templates created specifically for your industry. You can use these conversation templates to develop your unique chatbot based on common questions and scenarios.

In the past, making a chatbot was very difficult, but this tool makes it very easy.

Adding a chatbot to your customer service workflow can make your customer support system more effective.

Your chatbot can handle simple requests and ask your users preliminary questions, then forward this to your team for a more detailed response.

Note: we use ChatBot.com in several of our SaaS businesses. It lets us automate portion of our pre-sales questions while seamlessly forwarding our support requests to our live support teams when needed.

ChatBot also integrates easily with both WordPress and WooCommerce. Plus, it integrates with your live chat software of choice, along with dozens of other popular apps.

Pricing: The starter plan is $50 per month and gives you up to 1,000 chats per month. Pricing and the number of chats scale up from here. Every plan has a 14 day free trial, so you can see if it’s right for your business.

5. FreshDesk

Freshdesk

FreshDesk is another very popular customer service solution. It’s packed with features while still being intuitive and easy to use.

It’s an all-in-one tool and can bring all of your support channels together in one place. You’ll find live chat support, chatbots, modern messaging, omnichannel support, automation features, and more.

The ticketing system has features like a team inbox for fast and easy collaboration and problem solving. You can also route support tasks based on team member availability.

You’ll find a wealth of reporting data to help refine your support service over multiple channels, including social media.

There are plenty of additional customer self service tools like a chatbot, help widget, forum support, and more.

For business owners and startups on a budget, a free version of the tool that supports an unlimited number of agents is available. However, it only offers basic ticketing and knowledge base functionality.

Pricing: The basic version of the help desk software starts at $15 per month. Full omnichannel plans start at $79 when billed annually, or $99 when billed monthly.

Note: We have used Freshdesk in the past for few of our businesses, but over time have switched everything to Help Scout, so we can centralize our processes.

6. HelpDesk.com

HelpDesk

HelpDesk is a very easy to use customer support software. The interface is incredibly clean and intuitive.

It can help you and your team manage tickets simply. You can manage emails, customer requests from contact forms, and more, all in one place.

Plus, there are advanced ticketing, sorting, and tagging features to prioritize what’s most important.

The team collaboration features let you create multiple mailboxes, add private notes to ticket threads, and create agent groups.

There are automation features available, like canned responses, automated task assignments, and fully automated workflows.

You can also integrate HelpDesk with LiveChat, so you can solve support tickets and talk to customers in chat from one app.

Beyond that, there are various other integrations like Slack, Zapier, HubSpot, Salesforce, and more that you can use to improve your workflow.

Pricing: The Starter plan is $5 per month per user, while the Team plan is $24 per month and adds the ticketing system and support for larger teams. There’s also a 14 day free trial for you to test out the service.

7. HubSpot

HubSpot

HubSpot offers small business owners a wide range of tools to grow and improve customer interactions. They have one of the best CRMs for small businesses and offer an excellent customer support software solution.

The support software is an all-in-one solution and has a ton of different tools. You’ll find help desk software and a ticketing system to keep track of long-term support requests.

There’s also knowledge base software to help your customers quickly resolve their problems.

On top of that, there’s live chat and chatbot functionality for real-time communication with your customers.

The free plan is free forever and has all the features you need to help your customer support staff.

Plus, everything integrates with the HubSpot CRM, so it’s easy to start using this software if you’re already using the CRM software for managing customer relationships.

Pricing: The entry level plan is free forever. The Starter plan begins at $45 per month and gives you access to more automation tools and support for a bigger team.

8. WPForms

WPForms

WPForms is the best contact form plugin for WordPress used by over 4 million websites. Not only is it the most beginner friendly form plugin, but it’s very powerful and packed with features.

Note: we use WPForms on WPBeginner and all of our other websites.

You can use the drag and drop builder to simply create a contact form for your users to submit a support request.

The free version has basic contact form features, including basic form fields, spam protection, email notifications, and more.

The pro version extends these features and makes it a more helpful customer service tool. You can create forms with conditional logic, geo-location, form abandonment, and much more.

You can see all of your form submissions directly in your WordPress dashboard, making it easy to manage requests. You can even have these requests sent to the right team member in charge of support.

There’s also instant form notification, which will automatically email you when a user submits a form. You can choose to notify yourself or your entire team.

The user journey reports addon lets you see what your visitors did on your site before submitting a request. This can help you resolve their issue faster and see where they got confused.

WPForms lets you connect your forms with over 3000+ other software integrations including most marketing automation tools, project management software, service desk, human resources (HR software), and more. This makes it easy for you to streamline your workflow and save time.

Pricing: For simple form creation, the Basic plan starts at $39.50 per year, however, to get access to advanced integrations, user journey reports, and more the Pro plan is $199.50 per year.

9. Slack

Slack

Slack is a popular communication and team collaboration tool for remote teams, businesses, and bloggers. However, it also can be used as a unique customer service management solution and support channel.

It can be a great way to offer VIP support for your enterprise customers and clients. It provides a very open and collaborative environment, which can help you resolve the issue quickly and move forward on big projects.

Note: we offer VIP support through private Slack channels and receive enterprise support the same way. It’s one of the most effective remote communication tools.

With various integrations available, you can also pair this tool with another support software on this list. You can drop support team issues into Slack to have team members collaborate easily.

You can also integrate Slack with WordPress to receive website notifications, like form entries, directly in Slack. For more details, see our beginner’s guide on how to integrate Slack with WordPress.

There’s an advanced AI powered search feature to find documents and past conversations quickly. You can also bring in team members from different departments all in one place.

Best of all, it’s very cost effective. You can create communication channels for your important clients and customers and add them as guests, which is entirely free.

Pricing: The free plan should be enough for most businesses. The Pro plan is $8 per month and offers more secure outside collaboration. Businesses that require enhanced communication security can opt for the Business plan for $15 per month.

What is the Best Customer Service Software (Expert Pick)?

In our expert opinion, there are a several services that can qualify for the best customer support software title, but it depends entirely on your needs.

If you need the best email support software, then Help Scout is the best option.

If you want a live chat tool to provide instant customer support, then LiveChat is the best choice.

If you are looking for a customer support phone system with addon features like live chat, then Nextiva is perfect.

If you like the idea of live chat support, but would prefer to automate with a chatbot, then ChatBot.com is a great choice.

If you were going to choose just one customer service software to support your business, then we recommend using Help Scout.

Besides the stand out email tools, you can also add live chat, create a knowledge base, plus integrate with popular tools like Slack, WooCommerce, and more.

Aside from the top customer service software on our list, we also looked at other providers like Zendesk, Salesforce, Zoho Desk, LiveAgent, and more.

However, we decided not to list them, so you can avoid choice paralysis and quickly find the best customer service software for your business.

We hoped this article helped you find the best customer service software for your business. You may also want to see our list of the best SEO tools to increase your traffic and our expert picks of the must have WordPress plugins for business websites.

If you liked this article, then please subscribe to our YouTube Channel for WordPress video tutorials. You can also find us on Twitter and Facebook.

The post 9 Best Customer Service Software for Business in 2021 (Compared) appeared first on WPBeginner.

Setup ActiveMQ Artemis on Windows

Overview

ActiveMQ Artemis is an open-source "next generation" broker from Apache with the performance and feature-set to implement high-performance messaging systems. Artemis is the code-name used for the HornetQ code that was donated to the Apache Foundation.

Pre-requisites:

  • Windows 7 or higher
  • Java 7 or higher

Let us start Artemis setup on Windows machine.

Scenarios When Data-Driven Testing Is Useful

In today’s world where ‘data is the new oil’ (as said by Clive Humby), not giving proper attention to data-driven testing is not justified. If you have an application that needs data input in some form then it will require data-driven testing.

Additionally, when during testing your application – there are testing scenarios that require multiple permutations/combinations of input data in your application, then you might have to think of using a test automation tool for automating them.

Drawing Graphics with the CSS Paint API

CSS Paint is an API that allows developers to programatically generate and draw graphics where CSS expects an image.

It is part of CSS Houdini, an umbrella term for seven new low-level APIs that expose different parts of the CSS engine and allows developers to extend CSS by hooking into the styling and layout process of a browser’s rendering engine.

It enables developers to write code the browser can parse as CSS, thereby creating new CSS features without waiting for them to be implemented natively in browsers.

Today we will explore two particular APIs, that are part of the CSS Houdini umbrella:

  1. CSS Paint, which at the time of writing this article, has been fully implemented in Chrome, Opera and Edge and is available in Firefox and Safari via a polyfill.
  2. CSS Properties and Values API, that will allow us to explicitly define our CSS variables, their initial values, what type of values they support and whether these variables can be inherited.

CSS Paint provides us with ability to render graphics using a PaintWorklet, a stripped down version of the CanvasRenderingContext2D. The major differences are:

  • No support for text rendering
  • No direct pixel access / manipulation

With these two omissions in mind, anything you can draw using canvas2d, you can draw on a regular DOM element using the CSS Paint API. For those of you who have done any graphics using canvas2d, you should be right at home.

Furthermore, we as developers have the ability to pass CSS variables as inputs to our PaintWorklet and control its presentation using custom predefined attributes.

This allows for a high degree of customisation, even by design people who may not be necessarily familiar with Javascript.

You can see more examples here and here. And with that out of the way, let’s get to coding!

Simplest example: two diagonal lines

Let’s create a CSS paintlet, that once loaded, will draw two diagonal lines across the surface of the DOM element we apply it to. The paintlet drawing surface size will adapt to the width and height of the DOM element and we will be able to control the diagonal line thickness by passing in a CSS variable.

Creating our PaintWorklet

In order to load a PaintWorklet, we will need to create it as a separate Javascript file (diagonal-lines.js).

const PAINTLET_NAME = 'diagonal-lines'

class CSSPaintlet {

  // 👉 Define the names of the input CSS variables we will support
  static get inputProperties() {
    return [
      `--${PAINTLET_NAME}-line-width`,
    ]
  }

  // 👉 Define names for input CSS arguments supported in paint()
  // ⚠ This part of the API is still experimental and hidden
  //    behind a flag.
  static get inputArguments () {
    return []
  }

  // 👉 paint() will be executed every time:
  //  - any input property changes
  //  - the DOM element we apply our paintlet to changes its dimensions
  paint(ctx, paintSize, props) {
    // 👉 Obtain the numeric value of our line width that is passed
    //    as a CSS variable
    const lineWidth = Number(props.get(`--${PAINTLET_NAME}-line-width`))

    ctx.lineWidth = lineWidth

    // 🎨 Draw diagonal line #1
    ctx.beginPath()
    ctx.moveTo(0, 0)
    ctx.lineTo(paintSize.width, paintSize.height)
    ctx.stroke()

    // 🎨 Draw diagonal line #2
    ctx.beginPath()
    ctx.moveTo(0, paintSize.height)
    ctx.lineTo(paintSize.width, 0)
    ctx.stroke()
  }
}

// 👉 Register our CSS Paintlet with the correct name
//    so we can reference it from our CSS
registerPaint(PAINTLET_NAME, CSSPaintlet)

We define our CSS paintlet as a standalone class. This class needs only one method to work – paint(), which will draw the graphics on top of the surface we assign our CSS paintlet to. It will be executed upon changing any of the CSS variables our paintlet relies on or when our DOM element changes it’s dimensions.

The other static method inputProperties() is optional. It tells the CSS paintlet which input CSS variables exactly does it support. In our case, that would be --diagonal-lines-line-width. We declare it as an input property and consume it for use in our paint() method. It is important we cast it to a number by putting it in a Number to ensure cross-browser support.

There is yet another optional static method supported: inputArguments. It exposes arguments to our paint() method like so:

#myImage {
  background-image: paint(myWorklet, 30px, red, 10deg);
}

However, this part of the CSS paintlet API is still hidden behind a flag and considered experimental. For ease of use and compatability, we will not be covering it in this article, but I encourage you to read up on it on your own. Instead, we will use CSS variables using the inputProperties() method to control all of the inputs to our paintlet.

Registering our CSS PaintWorklet

Afterwards we must reference our CSS paintlet and register it to our main page. It is important we conditionally load the awesome css-paint-polyfill package, which will ensure our paintlets will work in Firefox and Safari.

It should be noted that along our CSS paintlet, we can use the new CSS Properties and Values API, also part of the Houdini umbrella, to explicitly define our CSS variables inputs via CSS.registerProperty(). We can control our CSS variables like so:

  • Their types & syntax
  • Whether this CSS variable inherits from any parent elements
  • What is it’s initial value if the user does not specify one

This API is also not supported in Firefox and Safari, but we can still use it in Chromium browsers. This way we will future-proof our demos and browsers that don’t support it will simply ignore it.

;(async function() {
  // ⚠ Handle Firefox and Safari by importing a polyfill for CSS Pain    
  if (CSS['paintWorklet'] === undefined) {
    await import('https://unpkg.com/css-paint-polyfill')
  }

  // 👉 Explicitly define our custom CSS variable
  //    This is not supported in Safari and Firefox, so they will
  //    ignore it, but we can optionally use it in browsers that 
  //    support it. 
  //    This way we will future-proof our applications so once Safari
  //    and Firefox support it, they will benefit from these
  //    definitions too.
  //
  //    Make sure that the browser treats it as a number
  //    It does not inherit it's value
  //    It's initial value defaults to 1
  if ('registerProperty' in CSS) {
    CSS.registerProperty({
      name: '--diagonal-lines-line-width',
      syntax: '<number>',
      inherits: false,
      initialValue: 1
    })
  }

  // 👉 Include our separate paintlet file
  CSS.paintWorklet.addModule('path/to/our/external/worklet/diagonal-files.js')
})()

Referencing our paintlet as a CSS background

Once we have included our paintlet as a JS file, using it is dead simple. We select our target DOM element we want to style in CSS and apply our paintlet via the paint() CSS command:

#myElement {
   // 👉 Reference our CSS paintlet
   background-image: paint('--diagonal-lines');

   // 👉 Pass in custom CSS variable to be used in our CSS paintlet
   --diagonal-lines-line-width: 10;

   // 👉 Remember - the browser treats this as a regular image
   // referenced in CSS. We can control it's repeat, size, position
   // and any other background related property available
   background-repeat: no-repeat;
   background-size: cover;
   background-position: 50% 50%;

   // Some more styles to make sure we can see our element on the page
   border: 1px solid red;
   width: 200px;
   height: 200px;
   margin: 0 auto;
}

And with this code out of the way, here is what we will get:

Remember, we can apply this CSS paintlet as a background to any DOM element with any dimensions. Let’s blow up our DOM element to fullscreen, lower it’s background-size x and y values and set it’s background-repeat to repeat. Here is our updated example:

We are using the same CSS paintlet from our previous example, but now we have expanded it to cover the whole demo page.

So now that we covered our base example and saw how to organise our code, let’s write some nicer looking demos!

Particle Connections

See the Pen CSS Worklet Particles by Georgi Nikoloff (@gbnikolov) on CodePen.

This paintlet was inspired by the awesome demo by @nucliweb.

Again, for those of you who have used the canvas2d API to draw graphics in the past, this will be pretty straightforward.

We control how many points we are going to render via the `–dots-connections-count` CSS variable. Once we obtain its numeric value in our paintlet, we create an array with the appropriate size and fill it with objects with random x, y and radius properties.

Then we loop each of our items in the array, draw a sphere at its coordinates, find the nearest neighbour to it (the minimum distance is controlled via the `–dots-connections-connection-min-dist` CSS variable) and connect them with a line.

We will also control the spheres fill color and the lines stroke color via the `–dots-connections-fill-color` and --dots-connections-stroke-color CSS variables respectively.

Here is the complete workled code:

const PAINTLET_NAME = 'dots-connections'

class CSSPaintlet {
  // 👉 Define names for input CSS variables we will support
  static get inputProperties() {
    return [
      `--${PAINTLET_NAME}-line-width`,
      `--${PAINTLET_NAME}-stroke-color`,
      `--${PAINTLET_NAME}-fill-color`,
      `--${PAINTLET_NAME}-connection-min-dist`,
      `--${PAINTLET_NAME}-count`,
    ]
  }

  // 👉 Our paint method to be executed when CSS vars change
  paint(ctx, paintSize, props, args) {
    const lineWidth = Number(props.get(`--${PAINTLET_NAME}-line-width`))
    const minDist = Number(props.get(`--${PAINTLET_NAME}-connection-min-dist`))
    const strokeColor = props.get(`--${PAINTLET_NAME}-stroke-color`)
    const fillColor = props.get(`--${PAINTLET_NAME}-fill-color`)
    const numParticles = Number(props.get(`--${PAINTLET_NAME}-count`))
    
    // 👉 Generate particles at random positions
    //    across our DOM element surface
    const particles = new Array(numParticles).fill(null).map(_ => ({
      x: Math.random() * paintSize.width,
      y: Math.random() * paintSize.height,
      radius: 2 + Math.random() * 2,
    }))
    
    // 👉 Assign lineWidth coming from CSS variables and make sure
    //    lineCap and lineWidth are round
    ctx.lineWidth = lineWidth
    ctx.lineJoin = 'round'
    ctx.lineCap = 'round'
    
    // 👉 Loop over the particles with nested loops - O(n^2)
    for (let i = 0; i < numParticles; i++) {
      const particle = particles[i]
      // 👉 Loop second time 
      for (let n = 0; n < numParticles; n++) {
        if (i === n) {
          continue
        }
        const nextParticle = particles[n]
        // 👉 Calculate distance between the current particle
        //    and the particle from the previous loop iteration
        const dx = nextParticle.x - particle.x
        const dy = nextParticle.y - particle.y
        const dist = Math.sqrt(dx * dx + dy * dy)
        // 👉 If the dist is smaller then the minDist specified via
        //    CSS variable, then we will connect them with a line
        if (dist < minDist) {
          ctx.strokeStyle = strokeColor
          ctx.beginPath()
          ctx.moveTo(nextParticle.x, nextParticle.y)
          ctx.lineTo(particle.x, particle.y)
          // 👉 Draw the connecting line
          ctx.stroke()
        }
      }
      // Finally draw the particle at the right position
      ctx.fillStyle = fillColor
      ctx.beginPath()
      ctx.arc(particle.x, particle.y, particle.radius, 0, Math.PI * 2)
      ctx.closePath()
      ctx.fill()
    }
    
  }
}

// 👉 Register our CSS paintlet with a unique name
//    so we can reference it from our CSS
registerPaint(PAINTLET_NAME, CSSPaintlet)

Line Loop

Here is our next example. It expects the following CSS variables as inputs to our paintlet:

--loop-line-width
--loop-stroke-color
--loop-sides
--loop-scale
--loop-rotation

We loop around a full circle (PI * 2) and position them along it’s perimeters based on the --loop-sides count CSS variables. For each position, we loop again around our full circle, and connect it to all other positions via a ctx.lineTo() command:

const PAINTLET_NAME = 'loop'

class CSSPaintlet {
  // 👉 Define names for input CSS variables we will support
  static get inputProperties() {
    return [
      `--${PAINTLET_NAME}-line-width`,
      `--${PAINTLET_NAME}-stroke-color`,
      `--${PAINTLET_NAME}-sides`,
      `--${PAINTLET_NAME}-scale`,
      `--${PAINTLET_NAME}-rotation`,
    ]
  }
  // 👉 Our paint method to be executed when CSS vars change
  paint(ctx, paintSize, props, args) {
    const lineWidth = Number(props.get(`--${PAINTLET_NAME}-line-width`))
    const strokeColor = props.get(`--${PAINTLET_NAME}-stroke-color`)
    const numSides = Number(props.get(`--${PAINTLET_NAME}-sides`))
    const scale = Number(props.get(`--${PAINTLET_NAME}-scale`))
    const rotation = Number(props.get(`--${PAINTLET_NAME}-rotation`))
    
    const angle = Math.PI * 2 / numSides
    const radius = paintSize.width / 2
    ctx.save()
    ctx.lineWidth = lineWidth
    ctx.lineJoin = 'round'
    ctx.lineCap = 'round'
    ctx.strokeStyle = strokeColor
    ctx.translate(paintSize.width / 2, paintSize.height / 2)
    ctx.rotate(rotation * (Math.PI / 180))
    ctx.scale(scale / 100, scale / 100)
    ctx.moveTo(0, radius)

    // 👉 Loop over the numsides twice in nested loop - O(n^2)
    //    Connect each corner with all other corners
    for (let i = 0; i < numSides; i++) {
      const x = Math.sin(i * angle) * radius
      const y = Math.cos(i * angle) * radius
      for (let n = i; n < numSides; n++) {
        const x2 = Math.sin(n * angle) * radius
        const y2 = Math.cos(n * angle) * radius
        ctx.lineTo(x, y)
        ctx.lineTo(x2, y2);
      }
    }
    ctx.closePath()
    ctx.stroke()
    ctx.restore()
  }   
}

// 👉 Register our CSS paintlet with a unique name
//    so we can reference it from our CSS
registerPaint(PAINTLET_NAME, CSSPaintlet)

Noise Button

Here is our next example. It is inspired by this other awesome CSS Paintlet by Jhey Tompkins. It expects the following CSS variables as inputs to our paintlet:

--grid-size
--grid-color
--grid-noise-scale

The paintlet itself uses perlin noise (code courtesy of joeiddon) to control the opacity of each individual cell.

const PAINTLET_NAME = 'grid'

class CSSPaintlet {
  // 👉 Define names for input CSS variables we will support
  static get inputProperties() {
    return [
      `--${PAINTLET_NAME}-size`,
      `--${PAINTLET_NAME}-color`,
      `--${PAINTLET_NAME}-noise-scale`
    ]
  }

  // 👉 Our paint method to be executed when CSS vars change
  paint(ctx, paintSize, props, args) {
    const gridSize = Number(props.get(`--${PAINTLET_NAME}-size`))
    const color = props.get(`--${PAINTLET_NAME}-color`)
    const noiseScale = Number(props.get(`--${PAINTLET_NAME}-noise-scale`))

    ctx.fillStyle = color
    for (let x = 0; x < paintSize.width; x += gridSize) {
      for (let y = 0; y < paintSize.height; y += gridSize) {
        // 👉 Use perlin noise to determine the cell opacity
        ctx.globalAlpha = mapRange(perlin.get(x * noiseScale, y * noiseScale), -1, 1, 0.5, 1)
        ctx.fillRect(x, y, gridSize, gridSize)
      }
    }
  }
}

// 👉 Register our CSS paintlet with a unique name
//    so we can reference it from our CSS
registerPaint(PAINTLET_NAME, CSSPaintlet)

Curvy dividers

As a last example, let’s do something perhaps a bit more useful. We will programatically draw dividers to separate the text content of our page:

And as usual, here is the CSS paintlet code:

const PAINTLET_NAME = 'curvy-dividor'

class CSSPaintlet {
  // 👉 Define names for input CSS variables we will support
  static get inputProperties() {
    return [
      `--${PAINTLET_NAME}-points-count`,
      `--${PAINTLET_NAME}-line-width`,
      `--${PAINTLET_NAME}-stroke-color`
    ]
  }
  // 👉 Our paint method to be executed when CSS vars change
  paint(ctx, paintSize, props, args) {
    const pointsCount = Number(props.get(`--${PAINTLET_NAME}-points-count`))
    const lineWidth = Number(props.get(`--${PAINTLET_NAME}-line-width`))
    const strokeColor = props.get(`--${PAINTLET_NAME}-stroke-color`)
    
    const stepX = paintSize.width / pointsCount
    
    ctx.lineWidth = lineWidth
    ctx.lineJoin = 'round'
    ctx.lineCap = 'round'
    
    ctx.strokeStyle = strokeColor
    
    const offsetUpBound = -paintSize.height / 2
    const offsetDownBound = paintSize.height / 2
    
    // 👉 Draw quadratic bezier curves across the horizontal axies
    //    of our dividers:
    ctx.moveTo(-stepX / 2, paintSize.height / 2)
    for (let i = 0; i < pointsCount; i++) {
      const x = (i + 1) * stepX - stepX / 2
      const y = paintSize.height / 2 + (i % 2 === 0 ? offsetDownBound : offsetUpBound)
      const nextx = (i + 2) * stepX - stepX / 2
      const nexty = paintSize.height / 2 + (i % 2 === 0 ? offsetUpBound : offsetDownBound)
      const ctrlx = (x + nextx) / 2
      const ctrly = (y + nexty) / 2
      ctx.quadraticCurveTo(x, y, ctrlx, ctrly)
    }
    ctx.stroke()
  }
}

// 👉 Register our CSS paintlet with a unique name
//    so we can reference it from our CSS
registerPaint(PAINTLET_NAME, CSSPaintlet)

Conclusion

In this article we went through all the key components and methods of the CSS Paint API. It is pretty easy to setup and very useful if we want to draw more advanced graphics that CSS does not support out-of-the box.

We can easily create a library out of these CSS paintlets and keep reusing them across our projects with minimum setup required.

As a good practice, I encourage you to find cool canvas2d demos and port them to the new CSS Paint API.

The post Drawing Graphics with the CSS Paint API appeared first on Codrops.

Express JS Conditional Routing: How to Route Multiple Payment Gateways

A payment gateway is a commercial service offered by an e-commerce application provider that allows e-business credit cards, online retailing, traditional brick, clicks, and mortar payment processing. A payment gateway may also be provided by banks to its customers and may be supplied by an independent specialist financial service provider such as PayPal, square, stripe, etc.

A payment gateway enables the exchange of payment information between the gateway and the front-end processor (such as a website, mobile phone, or interactive voice response system) or the acquiring bank.

Hybrid Multicloud Adoption

Prelude

  • This blog discusses the importance of hybrid multicloud to accelerate business transformation. 
  • The discussion assumes that the readers are well versed with cloud technology concepts as well as the business value and challenges related to modernizing applications using cloud technologies.
  • This blog focuses only on the concept of multicloud, which adds new dimensions of complexity and value as opposed to leveraging a single cloud provider.

Evolution of Hybrid Multicloud

The evolution of cloud computing started with the utility computing concept. It began from the concept of dedicated resources vs. shared resource platforms. Businesses have embraced cloud platforms including private, public, hybrid, and hybrid multicloud.

In a simple term, a hybrid multicloud is the use of hybrid cloud and multicloud models as depicted in diagram 1.