diff --git a/.circleci/config.yml b/.circleci/config.yml
index 3ecdeec47a8a4d1e872751969e49d52ac01ef225..0c4a2f6f8683ba731daf2980d2cd54f9382ba328 100644
--- a/.circleci/config.yml
+++ b/.circleci/config.yml
@@ -236,7 +236,7 @@ jobs:
 
   e2e:
     docker:
-      - image: cypress/base:14
+      - image: cypress/base:14.16.0
     steps:
       - checkout
 
diff --git a/.eslintignore b/.eslintignore
index 3024b09851685149ea1e633a117890f83f187203..170a29b89224433b4299517451527a9561ef7438 100644
--- a/.eslintignore
+++ b/.eslintignore
@@ -2,6 +2,6 @@
 /build
 /coverage
 /__snapshots__
-/public
+public
 badge-maker/node_modules/
 !.github/
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 3662cf5b3bb1f8c4d70911302f0cbb99ff2f3420..0614f9a0134aff5c9e857e66a02f2091641c9134 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -136,7 +136,6 @@ rules:
   # Shields additions.
   no-var: 'error'
   prefer-const: 'error'
-  strict: 'error'
   arrow-body-style: ['error', 'as-needed']
   no-extension-in-require/main: 'error'
   object-shorthand: ['error', 'properties']
diff --git a/.gitignore b/.gitignore
index 4f1faad2b1729a69f7ea7a88cb0c9c22eaeb5ffb..771e46a75d298409a83b0cc71b78d425714c0715 100644
--- a/.gitignore
+++ b/.gitignore
@@ -104,7 +104,8 @@ service-definitions.yml
 !/config/local*.template.yml
 
 # Gatsby
-/.cache
+/frontend/.cache
+/frontend/public
 /public
 
 # Cypress
diff --git a/.mocharc-frontend.yml b/.mocharc-frontend.yml
index 8a85e65d938f1a64387d4fe5790db934e722d202..0e076ba900ada45862573c50f9fb2dc4674628d7 100644
--- a/.mocharc-frontend.yml
+++ b/.mocharc-frontend.yml
@@ -3,4 +3,3 @@ require:
   - '@babel/polyfill'
   - '@babel/register'
   - mocha-yaml-loader
-  - frontend/mocha-ignore-pngs
diff --git a/.prettierignore b/.prettierignore
index 66e7a5e5bf2eb47a2a7f83dbcfe8e4c0e2d82e9d..9f913cee41ec1cb0f76cbcb2b7cbf3c227c47b95 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -2,10 +2,10 @@ package.json
 package-lock.json
 /__snapshots__
 /.next
-/.cache
+.cache
 /api-docs
 /build
-/public
+public
 /coverage
 private/*.json
 /.nyc_output
diff --git a/core/badge-urls/make-badge-url.js b/core/badge-urls/make-badge-url.js
index 42c09f91689f2fc31bf7a32d1682dbbce78248f2..82e3f5fa251240453945a9814af32d13fdbd37fc 100644
--- a/core/badge-urls/make-badge-url.js
+++ b/core/badge-urls/make-badge-url.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const { URL } = require('url')
-const queryString = require('query-string')
-const { compile } = require('path-to-regexp')
+// Avoid "Attempted import error: 'URL' is not exported from 'url'" in frontend.
+import url from 'url'
+import queryString from 'query-string'
+import { compile } from 'path-to-regexp'
 
 function badgeUrlFromPath({
   baseUrl = '',
@@ -147,13 +146,13 @@ function dynamicBadgeUrl({
 function rasterRedirectUrl({ rasterUrl }, badgeUrl) {
   // Ensure we're always using the `rasterUrl` by using just the path from
   // the request URL.
-  const { pathname, search } = new URL(badgeUrl, 'https://bogus.test')
-  const result = new URL(pathname, rasterUrl)
+  const { pathname, search } = new url.URL(badgeUrl, 'https://bogus.test')
+  const result = new url.URL(pathname, rasterUrl)
   result.search = search
   return result
 }
 
-module.exports = {
+export {
   badgeUrlFromPath,
   badgeUrlFromPattern,
   encodeField,
diff --git a/core/badge-urls/make-badge-url.spec.js b/core/badge-urls/make-badge-url.spec.js
index 94642db1f85c5a48adb48d39772dab61a505e23e..da0b156d5ea71d93608e9e66b30551e955b8a843 100644
--- a/core/badge-urls/make-badge-url.spec.js
+++ b/core/badge-urls/make-badge-url.spec.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const {
+import { test, given } from 'sazerac'
+import {
   badgeUrlFromPath,
   badgeUrlFromPattern,
   encodeField,
   staticBadgeUrl,
   queryStringStaticBadgeUrl,
   dynamicBadgeUrl,
-} = require('./make-badge-url')
+} from './make-badge-url.js'
 
 describe('Badge URL generation functions', function () {
   test(badgeUrlFromPath, () => {
diff --git a/core/badge-urls/path-helpers.js b/core/badge-urls/path-helpers.js
index b7b3bded44880ced78f5f5265b9113f4b266744a..74c1004f30e42c2f751234dfb18bcae41df1c4f9 100644
--- a/core/badge-urls/path-helpers.js
+++ b/core/badge-urls/path-helpers.js
@@ -1,5 +1,3 @@
-'use strict'
-
 // Escapes `t` using the format specified in
 // <https://github.com/espadrine/gh-badges/issues/12#issuecomment-31518129>
 function escapeFormat(t) {
@@ -13,6 +11,4 @@ function escapeFormat(t) {
   )
 }
 
-module.exports = {
-  escapeFormat,
-}
+export { escapeFormat }
diff --git a/core/badge-urls/path-helpers.spec.js b/core/badge-urls/path-helpers.spec.js
index ef7a0068e1cc275daccb858b065561c9919d001b..88de5a4869ebdd106c0d617fc68c26f0724189b2 100644
--- a/core/badge-urls/path-helpers.spec.js
+++ b/core/badge-urls/path-helpers.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { escapeFormat } = require('./path-helpers')
+import { test, given } from 'sazerac'
+import { escapeFormat } from './path-helpers.js'
 
 describe('Badge URL helper functions', function () {
   test(escapeFormat, () => {
diff --git a/core/base-service/auth-helper.js b/core/base-service/auth-helper.js
index f4ce18102614c11997a2be22f511c5fe53f284d4..8c9c7976be9722f2e54cee84beb58b2a58c5f42b 100644
--- a/core/base-service/auth-helper.js
+++ b/core/base-service/auth-helper.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { URL } = require('url')
-const { InvalidParameter } = require('./errors')
+import { URL } from 'url'
+import { InvalidParameter } from './errors.js'
 
 class AuthHelper {
   constructor(
@@ -207,4 +205,4 @@ class AuthHelper {
   }
 }
 
-module.exports = { AuthHelper }
+export { AuthHelper }
diff --git a/core/base-service/auth-helper.spec.js b/core/base-service/auth-helper.spec.js
index 2666c818aa909658e1f4593ff582c9be3d4e1bb7..fd36f950575acdd157eb5902de763490d59254ec 100644
--- a/core/base-service/auth-helper.spec.js
+++ b/core/base-service/auth-helper.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const { test, given, forCases } = require('sazerac')
-const { AuthHelper } = require('./auth-helper')
-const { InvalidParameter } = require('./errors')
+import { expect } from 'chai'
+import { test, given, forCases } from 'sazerac'
+import { AuthHelper } from './auth-helper.js'
+import { InvalidParameter } from './errors.js'
 
 describe('AuthHelper', function () {
   describe('constructor checks', function () {
diff --git a/core/base-service/base-graphql.js b/core/base-service/base-graphql.js
index 9d70fcf52ce664c41ff3dd08582f0cce1b1c1e88..bbdcb9224802c2a2a8c9e2e3c4608bd9e46e7a1c 100644
--- a/core/base-service/base-graphql.js
+++ b/core/base-service/base-graphql.js
@@ -2,12 +2,10 @@
  * @module
  */
 
-'use strict'
-
-const { print } = require('graphql/language/printer')
-const BaseService = require('./base')
-const { InvalidResponse, ShieldsRuntimeError } = require('./errors')
-const { parseJson } = require('./json')
+import { print } from 'graphql/language/printer.js'
+import BaseService from './base.js'
+import { InvalidResponse, ShieldsRuntimeError } from './errors.js'
+import { parseJson } from './json.js'
 
 function defaultTransformErrors(errors) {
   return new InvalidResponse({ prettyMessage: errors[0].message })
@@ -93,4 +91,4 @@ class BaseGraphqlService extends BaseService {
   }
 }
 
-module.exports = BaseGraphqlService
+export default BaseGraphqlService
diff --git a/core/base-service/base-graphql.spec.js b/core/base-service/base-graphql.spec.js
index 187063c88da698bc812a95694a7ad13d3b674573..ee59b8ddecd87ba9061be0c341b64f2f9544a8fb 100644
--- a/core/base-service/base-graphql.spec.js
+++ b/core/base-service/base-graphql.spec.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const Joi = require('joi')
-const { expect } = require('chai')
-const gql = require('graphql-tag')
-const sinon = require('sinon')
-const BaseGraphqlService = require('./base-graphql')
-const { InvalidResponse } = require('./errors')
+import Joi from 'joi'
+import { expect } from 'chai'
+import gql from 'graphql-tag'
+import sinon from 'sinon'
+import BaseGraphqlService from './base-graphql.js'
+import { InvalidResponse } from './errors.js'
 
 const dummySchema = Joi.object({
   requiredString: Joi.string().required(),
diff --git a/core/base-service/base-json.js b/core/base-service/base-json.js
index 3d786df49aaccc82f90ac202624583819bdef7b2..7f4730d2d2058f368fea4e43166cbd73da50d37f 100644
--- a/core/base-service/base-json.js
+++ b/core/base-service/base-json.js
@@ -2,10 +2,8 @@
  * @module
  */
 
-'use strict'
-
-const BaseService = require('./base')
-const { parseJson } = require('./json')
+import BaseService from './base.js'
+import { parseJson } from './json.js'
 
 /**
  * Services which query a JSON endpoint should extend BaseJsonService
@@ -54,4 +52,4 @@ class BaseJsonService extends BaseService {
   }
 }
 
-module.exports = BaseJsonService
+export default BaseJsonService
diff --git a/core/base-service/base-json.spec.js b/core/base-service/base-json.spec.js
index 464b3800e6f04d34972aef423e6a42754f3883a0..45665e470289369b6cfc87530881e0c9a73f9bbf 100644
--- a/core/base-service/base-json.spec.js
+++ b/core/base-service/base-json.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { expect } = require('chai')
-const sinon = require('sinon')
-const BaseJsonService = require('./base-json')
+import Joi from 'joi'
+import { expect } from 'chai'
+import sinon from 'sinon'
+import BaseJsonService from './base-json.js'
 
 const dummySchema = Joi.object({
   requiredString: Joi.string().required(),
diff --git a/core/base-service/base-static.js b/core/base-service/base-static.js
index 3781d450e3578b3081487ae13868592502887c17..df9eae5efb953105f05da6d555cc3fcfa1f65c4f 100644
--- a/core/base-service/base-static.js
+++ b/core/base-service/base-static.js
@@ -1,17 +1,15 @@
-'use strict'
-
-const makeBadge = require('../../badge-maker/lib/make-badge')
-const BaseService = require('./base')
-const {
+import makeBadge from '../../badge-maker/lib/make-badge.js'
+import BaseService from './base.js'
+import {
   serverHasBeenUpSinceResourceCached,
   setCacheHeadersForStaticResource,
-} = require('./cache-headers')
-const { makeSend } = require('./legacy-result-sender')
-const { MetricHelper } = require('./metric-helper')
-const coalesceBadge = require('./coalesce-badge')
-const { prepareRoute, namedParamsForMatch } = require('./route')
+} from './cache-headers.js'
+import { makeSend } from './legacy-result-sender.js'
+import { MetricHelper } from './metric-helper.js'
+import coalesceBadge from './coalesce-badge.js'
+import { prepareRoute, namedParamsForMatch } from './route.js'
 
-module.exports = class BaseStaticService extends BaseService {
+export default class BaseStaticService extends BaseService {
   static register({ camp, metricInstance }, serviceConfig) {
     const { regex, captureNames } = prepareRoute(this.route)
 
diff --git a/core/base-service/base-svg-scraping.js b/core/base-service/base-svg-scraping.js
index a79caeca8280106bbb2ae62114db48129bcfe75f..993e0b584bdc50463bb2b5e25b67c0af9345baf3 100644
--- a/core/base-service/base-svg-scraping.js
+++ b/core/base-service/base-svg-scraping.js
@@ -2,13 +2,11 @@
  * @module
  */
 
-'use strict'
-
 // See available emoji at http://emoji.muan.co/
-const emojic = require('emojic')
-const BaseService = require('./base')
-const trace = require('./trace')
-const { InvalidResponse } = require('./errors')
+import emojic from 'emojic'
+import BaseService from './base.js'
+import trace from './trace.js'
+import { InvalidResponse } from './errors.js'
 
 const defaultValueMatcher = />([^<>]+)<\/text><\/g>/
 const leadingWhitespace = /(?:\r\n\s*|\r\s*|\n\s*)/g
@@ -90,4 +88,4 @@ class BaseSvgScrapingService extends BaseService {
   }
 }
 
-module.exports = BaseSvgScrapingService
+export default BaseSvgScrapingService
diff --git a/core/base-service/base-svg-scraping.spec.js b/core/base-service/base-svg-scraping.spec.js
index 25b0a33e82608b1fa4049f88163d716f3b3bc5ca..728f3bd188c7b3de07a5156d926207139f745cf4 100644
--- a/core/base-service/base-svg-scraping.spec.js
+++ b/core/base-service/base-svg-scraping.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { expect } = require('chai')
-const sinon = require('sinon')
-const Joi = require('joi')
-const makeBadge = require('../../badge-maker/lib/make-badge')
-const BaseSvgScrapingService = require('./base-svg-scraping')
+import { expect } from 'chai'
+import sinon from 'sinon'
+import Joi from 'joi'
+import makeBadge from '../../badge-maker/lib/make-badge.js'
+import BaseSvgScrapingService from './base-svg-scraping.js'
 
 const schema = Joi.object({
   message: Joi.string().required(),
diff --git a/core/base-service/base-xml.js b/core/base-service/base-xml.js
index d42a54e11d9a04c43266b6b957f3d1c79d7a5d8a..ee0c5e9020a0b5b0a0e7d95581d09c8422403029 100644
--- a/core/base-service/base-xml.js
+++ b/core/base-service/base-xml.js
@@ -2,14 +2,12 @@
  * @module
  */
 
-'use strict'
-
 // See available emoji at http://emoji.muan.co/
-const emojic = require('emojic')
-const fastXmlParser = require('fast-xml-parser')
-const BaseService = require('./base')
-const trace = require('./trace')
-const { InvalidResponse } = require('./errors')
+import emojic from 'emojic'
+import fastXmlParser from 'fast-xml-parser'
+import BaseService from './base.js'
+import trace from './trace.js'
+import { InvalidResponse } from './errors.js'
 
 /**
  * Services which query a XML endpoint should extend BaseXmlService
@@ -68,4 +66,4 @@ class BaseXmlService extends BaseService {
   }
 }
 
-module.exports = BaseXmlService
+export default BaseXmlService
diff --git a/core/base-service/base-xml.spec.js b/core/base-service/base-xml.spec.js
index 42ca1505fb31453b61750455e614ad0f582f1443..8db8dfc6f7a10e581128c20949d029aa308d4188 100644
--- a/core/base-service/base-xml.spec.js
+++ b/core/base-service/base-xml.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { expect } = require('chai')
-const sinon = require('sinon')
-const BaseXmlService = require('./base-xml')
+import Joi from 'joi'
+import { expect } from 'chai'
+import sinon from 'sinon'
+import BaseXmlService from './base-xml.js'
 
 const dummySchema = Joi.object({
   requiredString: Joi.string().required(),
diff --git a/core/base-service/base-yaml.js b/core/base-service/base-yaml.js
index 3f16ea0c8192c59febffb4b8ac58d132d749a994..0dd75930cac429ad05bb5f2eafbe68f8d0592eb5 100644
--- a/core/base-service/base-yaml.js
+++ b/core/base-service/base-yaml.js
@@ -2,13 +2,11 @@
  * @module
  */
 
-'use strict'
-
-const emojic = require('emojic')
-const yaml = require('js-yaml')
-const BaseService = require('./base')
-const { InvalidResponse } = require('./errors')
-const trace = require('./trace')
+import emojic from 'emojic'
+import yaml from 'js-yaml'
+import BaseService from './base.js'
+import { InvalidResponse } from './errors.js'
+import trace from './trace.js'
 
 /**
  * Services which query a YAML endpoint should extend BaseYamlService
@@ -72,4 +70,4 @@ class BaseYamlService extends BaseService {
   }
 }
 
-module.exports = BaseYamlService
+export default BaseYamlService
diff --git a/core/base-service/base-yaml.spec.js b/core/base-service/base-yaml.spec.js
index 781c76f1303047155c751449e425652260e053d9..50b42990c1701290318c47e5d971ba7180847a49 100644
--- a/core/base-service/base-yaml.spec.js
+++ b/core/base-service/base-yaml.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { expect } = require('chai')
-const sinon = require('sinon')
-const BaseYamlService = require('./base-yaml')
+import Joi from 'joi'
+import { expect } from 'chai'
+import sinon from 'sinon'
+import BaseYamlService from './base-yaml.js'
 
 const dummySchema = Joi.object({
   requiredString: Joi.string().required(),
diff --git a/core/base-service/base.js b/core/base-service/base.js
index 332c7ca8380d1268dbacf2487f6a1beb8a04014e..0a22086601bcebb11dea8ed9478f727167aad062 100644
--- a/core/base-service/base.js
+++ b/core/base-service/base.js
@@ -1,36 +1,35 @@
-'use strict'
 /**
  * @module
  */
 
 // See available emoji at http://emoji.muan.co/
-const emojic = require('emojic')
-const Joi = require('joi')
-const log = require('../server/log')
-const { AuthHelper } = require('./auth-helper')
-const { MetricHelper, MetricNames } = require('./metric-helper')
-const { assertValidCategory } = require('./categories')
-const checkErrorResponse = require('./check-error-response')
-const coalesceBadge = require('./coalesce-badge')
-const {
+import emojic from 'emojic'
+import Joi from 'joi'
+import log from '../server/log.js'
+import { AuthHelper } from './auth-helper.js'
+import { MetricHelper, MetricNames } from './metric-helper.js'
+import { assertValidCategory } from './categories.js'
+import checkErrorResponse from './check-error-response.js'
+import coalesceBadge from './coalesce-badge.js'
+import {
   NotFound,
   InvalidResponse,
   Inaccessible,
   ImproperlyConfigured,
   InvalidParameter,
   Deprecated,
-} = require('./errors')
-const { validateExample, transformExample } = require('./examples')
-const {
+} from './errors.js'
+import { validateExample, transformExample } from './examples.js'
+import {
   makeFullUrl,
   assertValidRoute,
   prepareRoute,
   namedParamsForMatch,
   getQueryParamNames,
-} = require('./route')
-const { assertValidServiceDefinition } = require('./service-definitions')
-const trace = require('./trace')
-const validate = require('./validate')
+} from './route.js'
+import { assertValidServiceDefinition } from './service-definitions.js'
+import trace from './trace.js'
+import validate from './validate.js'
 
 const defaultBadgeDataSchema = Joi.object({
   label: Joi.string(),
@@ -565,4 +564,4 @@ class BaseService {
  *    An HTML string that is included in the badge popup.
  */
 
-module.exports = BaseService
+export default BaseService
diff --git a/core/base-service/base.spec.js b/core/base-service/base.spec.js
index 9fa7e7e1a29068af2a4314654a7ae97f03e934cb..ac58c86598203fcf1db28d30dd2c9a86fb39380c 100644
--- a/core/base-service/base.spec.js
+++ b/core/base-service/base.spec.js
@@ -1,23 +1,22 @@
-'use strict'
-
-const Joi = require('joi')
-const chai = require('chai')
-const { expect } = chai
-const sinon = require('sinon')
-const prometheus = require('prom-client')
-const PrometheusMetrics = require('../server/prometheus-metrics')
-const trace = require('./trace')
-const {
+import Joi from 'joi'
+import chai from 'chai'
+import sinon from 'sinon'
+import prometheus from 'prom-client'
+import chaiAsPromised from 'chai-as-promised'
+import PrometheusMetrics from '../server/prometheus-metrics.js'
+import trace from './trace.js'
+import {
   NotFound,
   Inaccessible,
   InvalidResponse,
   InvalidParameter,
   Deprecated,
-} = require('./errors')
-const BaseService = require('./base')
-const { MetricHelper, MetricNames } = require('./metric-helper')
-require('../register-chai-plugins.spec')
-chai.use(require('chai-as-promised'))
+} from './errors.js'
+import BaseService from './base.js'
+import { MetricHelper, MetricNames } from './metric-helper.js'
+import '../register-chai-plugins.spec.js'
+const { expect } = chai
+chai.use(chaiAsPromised)
 
 const queryParamSchema = Joi.object({
   queryParamA: Joi.string(),
diff --git a/core/base-service/cache-headers.js b/core/base-service/cache-headers.js
index 999867aa22b0499ce35ab91c7b10181e2f0daf78..14a707efae7e39afa5477db3acbb96c5646f0bb6 100644
--- a/core/base-service/cache-headers.js
+++ b/core/base-service/cache-headers.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const assert = require('assert')
-const Joi = require('joi')
-const coalesce = require('./coalesce')
+import assert from 'assert'
+import Joi from 'joi'
+import coalesce from './coalesce.js'
 
 const serverStartTimeGMTString = new Date().toGMTString()
 const serverStartTimestamp = Date.now()
@@ -104,7 +102,7 @@ function serverHasBeenUpSinceResourceCached(req) {
   )
 }
 
-module.exports = {
+export {
   coalesceCacheLength,
   setCacheHeaders,
   setHeadersForCacheLength,
diff --git a/core/base-service/cache-headers.spec.js b/core/base-service/cache-headers.spec.js
index c6f5d6afb5c51eac0634add220e9deab8e9b6884..9c705116a2fe786702de7d8ddec412e30d347c64 100644
--- a/core/base-service/cache-headers.spec.js
+++ b/core/base-service/cache-headers.spec.js
@@ -1,19 +1,16 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const chai = require('chai')
-const { expect } = require('chai')
-const sinon = require('sinon')
-const httpMocks = require('node-mocks-http')
-const {
+import { test, given } from 'sazerac'
+import chai, { expect } from 'chai'
+import sinon from 'sinon'
+import httpMocks from 'node-mocks-http'
+import chaiDatetime from 'chai-datetime'
+import {
   coalesceCacheLength,
   setHeadersForCacheLength,
   setCacheHeaders,
   setCacheHeadersForStaticResource,
   serverHasBeenUpSinceResourceCached,
-} = require('./cache-headers')
-
-chai.use(require('chai-datetime'))
+} from './cache-headers.js'
+chai.use(chaiDatetime)
 
 describe('Cache header functions', function () {
   let res
diff --git a/core/base-service/categories.js b/core/base-service/categories.js
index d1bb0028fa5c416a1a8e1b5e0aa0d0f4ef0c6af2..14042f9a4d7eddc3220e51d8a10c96b8d242be2b 100644
--- a/core/base-service/categories.js
+++ b/core/base-service/categories.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const categories = require('../../services/categories')
+import Joi from 'joi'
+import categories from '../../services/categories.js'
 
 const isRealCategory = Joi.equal(...categories.map(({ id }) => id)).required()
 
@@ -13,7 +11,4 @@ function assertValidCategory(category, message = undefined) {
   Joi.assert(category, isValidCategory, message)
 }
 
-module.exports = {
-  isValidCategory,
-  assertValidCategory,
-}
+export { isValidCategory, assertValidCategory }
diff --git a/core/base-service/check-error-response.js b/core/base-service/check-error-response.js
index 1c4816b1117b79c9c5e6e75605e7ae71f0fca999..ea21344f3639f67970061424e9a5ae00d35b424e 100644
--- a/core/base-service/check-error-response.js
+++ b/core/base-service/check-error-response.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { NotFound, InvalidResponse, Inaccessible } = require('./errors')
+import { NotFound, InvalidResponse, Inaccessible } from './errors.js'
 
 const defaultErrorMessages = {
   404: 'not found',
 }
 
-module.exports = function checkErrorResponse(errorMessages = {}) {
+export default function checkErrorResponse(errorMessages = {}) {
   return async function ({ buffer, res }) {
     let error
     errorMessages = { ...defaultErrorMessages, ...errorMessages }
diff --git a/core/base-service/check-error-response.spec.js b/core/base-service/check-error-response.spec.js
index 34404aa658d726d300c7275006cb8033fa557043..82d239bec1ceca2e993b150de26f7bc4bcf629a2 100644
--- a/core/base-service/check-error-response.spec.js
+++ b/core/base-service/check-error-response.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { expect } = require('chai')
-const { NotFound, InvalidResponse, Inaccessible } = require('./errors')
-const checkErrorResponse = require('./check-error-response')
+import { expect } from 'chai'
+import { NotFound, InvalidResponse, Inaccessible } from './errors.js'
+import checkErrorResponse from './check-error-response.js'
 
 describe('async error handler', function () {
   const buffer = Buffer.from('some stuff')
diff --git a/core/base-service/coalesce-badge.js b/core/base-service/coalesce-badge.js
index 9a94cb2752e266bc87c3b2e387da46fb0aad6b85..db171fee347b4b13bfbd829169bfd9a6920133fa 100644
--- a/core/base-service/coalesce-badge.js
+++ b/core/base-service/coalesce-badge.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const {
+import {
   decodeDataUrlFromQueryParam,
   prepareNamedLogo,
-} = require('../../lib/logos')
-const { svg2base64 } = require('../../lib/svg-helpers')
-const coalesce = require('./coalesce')
-const toArray = require('./to-array')
+} from '../../lib/logos.js'
+import { svg2base64 } from '../../lib/svg-helpers.js'
+import coalesce from './coalesce.js'
+import toArray from './to-array.js'
 
 // Translate modern badge data to the legacy schema understood by the badge
 // maker. Allow the user to override the label, color, logo, etc. through the
@@ -34,7 +32,7 @@ const toArray = require('./to-array')
 // 3. In the case of the `social` style only, the last precedence is the
 //    service's default logo. The `logoColor` can be overridden by the query
 //    string.
-module.exports = function coalesceBadge(
+export default function coalesceBadge(
   overrides,
   serviceData,
   // These two parameters were kept separate to make tests clearer.
diff --git a/core/base-service/coalesce-badge.spec.js b/core/base-service/coalesce-badge.spec.js
index 195926d74adb4a330b6ffb74ab6b021be1864a94..07ffedbe2010c6789942d5ee30e310a6813f1202 100644
--- a/core/base-service/coalesce-badge.spec.js
+++ b/core/base-service/coalesce-badge.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { expect } = require('chai')
-const { getShieldsIcon, getSimpleIcon } = require('../../lib/logos')
-const coalesceBadge = require('./coalesce-badge')
+import { expect } from 'chai'
+import { getShieldsIcon, getSimpleIcon } from '../../lib/logos.js'
+import coalesceBadge from './coalesce-badge.js'
 
 describe('coalesceBadge', function () {
   describe('Label', function () {
diff --git a/core/base-service/coalesce.js b/core/base-service/coalesce.js
index 4875b409c7925377f9eaefd3a0d6770145181b49..8a55ff4c89dd790316ea4fd5b609e5f4e8f23e2f 100644
--- a/core/base-service/coalesce.js
+++ b/core/base-service/coalesce.js
@@ -1,5 +1,3 @@
-'use strict'
-
-module.exports = function coalesce(...candidates) {
+export default function coalesce(...candidates) {
   return candidates.find(c => c !== undefined && c !== null)
 }
diff --git a/core/base-service/coalesce.spec.js b/core/base-service/coalesce.spec.js
index b83b458caf3e3fd1a99379f4891787af61b2dca5..361f2bd8a7d32fce46346c75a303732fc8dca8c3 100644
--- a/core/base-service/coalesce.spec.js
+++ b/core/base-service/coalesce.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const coalesce = require('./coalesce')
+import { test, given } from 'sazerac'
+import coalesce from './coalesce.js'
 
 // Sticking with our one-line spread implementation, and defaulting to
 // `undefined` instead of `null`, though h/t to
diff --git a/core/base-service/deprecated-service.js b/core/base-service/deprecated-service.js
index a2c4796a5831968f0a833cfa3ffabf6fa66899c9..03ce5b2485e7415c43ce14a8653b72414e079c73 100644
--- a/core/base-service/deprecated-service.js
+++ b/core/base-service/deprecated-service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const Joi = require('joi')
-const camelcase = require('camelcase')
-const BaseService = require('./base')
-const { isValidCategory } = require('./categories')
-const { Deprecated } = require('./errors')
-const { isValidRoute } = require('./route')
+import Joi from 'joi'
+import camelcase from 'camelcase'
+import BaseService from './base.js'
+import { isValidCategory } from './categories.js'
+import { Deprecated } from './errors.js'
+import { isValidRoute } from './route.js'
 
 const attrSchema = Joi.object({
   route: isValidRoute,
@@ -44,4 +42,4 @@ function deprecatedService(attrs) {
   }
 }
 
-module.exports = deprecatedService
+export default deprecatedService
diff --git a/core/base-service/deprecated-service.spec.js b/core/base-service/deprecated-service.spec.js
index 3cc321efe32a4356f40dbb4c8a8dd58d0459d7a5..58ca62b6d9a125e4f90b45316e4115eb8d463660 100644
--- a/core/base-service/deprecated-service.spec.js
+++ b/core/base-service/deprecated-service.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { expect } = require('chai')
-const deprecatedService = require('./deprecated-service')
+import { expect } from 'chai'
+import deprecatedService from './deprecated-service.js'
 
 describe('DeprecatedService', function () {
   const route = {
diff --git a/core/base-service/errors.js b/core/base-service/errors.js
index 5bbd709089df19bb1de900c1821a2121e05e498e..a1c897ff6d0e90f657e41c1f7d9f55efc91be85b 100644
--- a/core/base-service/errors.js
+++ b/core/base-service/errors.js
@@ -4,8 +4,6 @@
  * @module
  */
 
-'use strict'
-
 /**
  * Base error class
  *
@@ -210,7 +208,7 @@ class Deprecated extends ShieldsRuntimeError {
  * badge when we catch and render the exception (Optional)
  */
 
-module.exports = {
+export {
   ShieldsRuntimeError,
   NotFound,
   ImproperlyConfigured,
diff --git a/core/base-service/examples.js b/core/base-service/examples.js
index 99200d6564eebab2c2a84d5273a5989766f4a5eb..6aa9ff03ed891c2869f0e18ed666103cd5009e4e 100644
--- a/core/base-service/examples.js
+++ b/core/base-service/examples.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { pathToRegexp, compile } = require('path-to-regexp')
-const categories = require('../../services/categories')
-const coalesceBadge = require('./coalesce-badge')
-const { makeFullUrl } = require('./route')
+import Joi from 'joi'
+import { pathToRegexp, compile } from 'path-to-regexp'
+import categories from '../../services/categories.js'
+import coalesceBadge from './coalesce-badge.js'
+import { makeFullUrl } from './route.js'
 
 const optionalObjectOfKeyValues = Joi.object().pattern(
   /./,
@@ -155,7 +153,4 @@ function transformExample(inExample, index, ServiceClass) {
   }
 }
 
-module.exports = {
-  validateExample,
-  transformExample,
-}
+export { validateExample, transformExample }
diff --git a/core/base-service/examples.spec.js b/core/base-service/examples.spec.js
index 3428771bfbc9c54db3068b9f3e4561136f3e570c..770b2571659999d827f0ced500406fb0528fca41 100644
--- a/core/base-service/examples.spec.js
+++ b/core/base-service/examples.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { expect } = require('chai')
-const { test, given } = require('sazerac')
-const { validateExample, transformExample } = require('./examples')
+import { expect } from 'chai'
+import { test, given } from 'sazerac'
+import { validateExample, transformExample } from './examples.js'
 
 describe('validateExample function', function () {
   it('passes valid examples', function () {
diff --git a/core/base-service/graphql.js b/core/base-service/graphql.js
index 3a78deb09a6d8eb688fdb400f03ad18f5df6dfc7..416fc735d760242e4728f238115f71d717b9910e 100644
--- a/core/base-service/graphql.js
+++ b/core/base-service/graphql.js
@@ -1,4 +1,3 @@
-'use strict'
 /**
  * @module
  */
@@ -49,4 +48,4 @@ function mergeQueries(...queries) {
   return merged
 }
 
-module.exports = { mergeQueries }
+export { mergeQueries }
diff --git a/core/base-service/graphql.spec.js b/core/base-service/graphql.spec.js
index 202dd052c6982dfe32b467eb5c6e10f78b3f636a..2267ecf41b7226ae7c65022c60a9f3452aa6e716 100644
--- a/core/base-service/graphql.spec.js
+++ b/core/base-service/graphql.spec.js
@@ -1,11 +1,9 @@
-'use strict'
+import { expect } from 'chai'
+import gql from 'graphql-tag'
+import { print } from 'graphql/language/printer.js'
+import { mergeQueries } from './graphql.js'
 
-const { expect } = require('chai')
-const gql = require('graphql-tag')
-const { print } = require('graphql/language/printer')
-const { mergeQueries } = require('./graphql')
-
-require('../register-chai-plugins.spec')
+import '../register-chai-plugins.spec.js'
 
 describe('mergeQueries function', function () {
   it('merges valid gql queries', function () {
diff --git a/core/base-service/index.js b/core/base-service/index.js
index ef99fdb296494663d677f32474fdd4eab3ec5f53..502ede424bd316a6d0da08ea455c9edf71710ae7 100644
--- a/core/base-service/index.js
+++ b/core/base-service/index.js
@@ -1,23 +1,21 @@
-'use strict'
-
-const BaseService = require('./base')
-const BaseJsonService = require('./base-json')
-const BaseGraphqlService = require('./base-graphql')
-const BaseStaticService = require('./base-static')
-const BaseSvgScrapingService = require('./base-svg-scraping')
-const BaseXmlService = require('./base-xml')
-const BaseYamlService = require('./base-yaml')
-const deprecatedService = require('./deprecated-service')
-const redirector = require('./redirector')
-const {
+import BaseService from './base.js'
+import BaseJsonService from './base-json.js'
+import BaseGraphqlService from './base-graphql.js'
+import BaseStaticService from './base-static.js'
+import BaseSvgScrapingService from './base-svg-scraping.js'
+import BaseXmlService from './base-xml.js'
+import BaseYamlService from './base-yaml.js'
+import deprecatedService from './deprecated-service.js'
+import redirector from './redirector.js'
+import {
   NotFound,
   InvalidResponse,
   Inaccessible,
   InvalidParameter,
   Deprecated,
-} = require('./errors')
+} from './errors.js'
 
-module.exports = {
+export {
   BaseService,
   BaseJsonService,
   BaseGraphqlService,
diff --git a/core/base-service/json.js b/core/base-service/json.js
index 6186b1e6b0b5704effd3c92734798c5c266e1976..f7b549e1512eb235f1a3764c5bf97b00b3b554ce 100644
--- a/core/base-service/json.js
+++ b/core/base-service/json.js
@@ -1,9 +1,7 @@
-'use strict'
-
 // See available emoji at http://emoji.muan.co/
-const emojic = require('emojic')
-const { InvalidResponse } = require('./errors')
-const trace = require('./trace')
+import emojic from 'emojic'
+import { InvalidResponse } from './errors.js'
+import trace from './trace.js'
 
 function parseJson(buffer) {
   const logTrace = (...args) => trace.logTrace('fetch', ...args)
@@ -23,6 +21,4 @@ function parseJson(buffer) {
   return json
 }
 
-module.exports = {
-  parseJson,
-}
+export { parseJson }
diff --git a/core/base-service/legacy-request-handler.js b/core/base-service/legacy-request-handler.js
index f048ec55bdcc7a830793c016a87b85830131e3bf..725b1d66179e1c9df8bc1580032afa5308865dd3 100644
--- a/core/base-service/legacy-request-handler.js
+++ b/core/base-service/legacy-request-handler.js
@@ -1,15 +1,9 @@
-'use strict'
-
-const request = require('request')
-const makeBadge = require('../../badge-maker/lib/make-badge')
-const { setCacheHeaders } = require('./cache-headers')
-const {
-  Inaccessible,
-  InvalidResponse,
-  ShieldsRuntimeError,
-} = require('./errors')
-const { makeSend } = require('./legacy-result-sender')
-const coalesceBadge = require('./coalesce-badge')
+import request from 'request'
+import makeBadge from '../../badge-maker/lib/make-badge.js'
+import { setCacheHeaders } from './cache-headers.js'
+import { Inaccessible, InvalidResponse, ShieldsRuntimeError } from './errors.js'
+import { makeSend } from './legacy-result-sender.js'
+import coalesceBadge from './coalesce-badge.js'
 
 const userAgent = 'Shields.io/2003a'
 
@@ -206,8 +200,4 @@ function handleRequest(cacheHeaderConfig, handlerOptions) {
   }
 }
 
-module.exports = {
-  handleRequest,
-  promisify,
-  userAgent,
-}
+export { handleRequest, promisify, userAgent }
diff --git a/core/base-service/legacy-request-handler.spec.js b/core/base-service/legacy-request-handler.spec.js
index a4cd21bbd32f45510fb6f87fd86e01e70100750f..1ea498f72a2f205e98cabdfac00fa4e1d0b6ee77 100644
--- a/core/base-service/legacy-request-handler.spec.js
+++ b/core/base-service/legacy-request-handler.spec.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const portfinder = require('portfinder')
-const Camp = require('@shields_io/camp')
-const got = require('../got-test-client')
-const coalesceBadge = require('./coalesce-badge')
-const { handleRequest } = require('./legacy-request-handler')
+import { expect } from 'chai'
+import nock from 'nock'
+import portfinder from 'portfinder'
+import Camp from '@shields_io/camp'
+import got from '../got-test-client.js'
+import coalesceBadge from './coalesce-badge.js'
+import { handleRequest } from './legacy-request-handler.js'
 
 async function performTwoRequests(baseUrl, first, second) {
   expect((await got(`${baseUrl}${first}`)).statusCode).to.equal(200)
diff --git a/core/base-service/legacy-result-sender.js b/core/base-service/legacy-result-sender.js
index 01ffc800cc6d9c7427b74796070101fd90eeea7f..90ee870e4b9ca7086185bcf0a4c4a0e3b0463e1e 100644
--- a/core/base-service/legacy-result-sender.js
+++ b/core/base-service/legacy-result-sender.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const stream = require('stream')
+import stream from 'stream'
 
 function streamFromString(str) {
   const newStream = new stream.Readable()
@@ -32,6 +30,4 @@ function makeSend(format, askres, end) {
   }
 }
 
-module.exports = {
-  makeSend,
-}
+export { makeSend }
diff --git a/core/base-service/loader-test-fixtures/empty-array.fixture.js b/core/base-service/loader-test-fixtures/empty-array.fixture.js
index d0c6276a37eb45cce91973c46d2786c88a32bf8d..9859f0797256b2e0c9d3e4e994a8303efa853e80 100644
--- a/core/base-service/loader-test-fixtures/empty-array.fixture.js
+++ b/core/base-service/loader-test-fixtures/empty-array.fixture.js
@@ -1,3 +1 @@
-'use strict'
-
-module.exports = []
+export default []
diff --git a/core/base-service/loader-test-fixtures/empty-no-export.fixture.js b/core/base-service/loader-test-fixtures/empty-no-export.fixture.js
index 883cb52b674f6773c150a40737f8499e2ee27438..e4e8dbb5a412931a5746ae0d83cabbcf4ec1ff36 100644
--- a/core/base-service/loader-test-fixtures/empty-no-export.fixture.js
+++ b/core/base-service/loader-test-fixtures/empty-no-export.fixture.js
@@ -1,4 +1,2 @@
 /* eslint-disable */
-'use strict'
-
-class BadService {}
+class BadService {} // lgtm [js/unused-local-variable]
diff --git a/core/base-service/loader-test-fixtures/empty-object.fixture.js b/core/base-service/loader-test-fixtures/empty-object.fixture.js
index 545992ebbbabedfec2a24afbb9a82cade3da94c7..336ce12bb9106afdf843063ee67c0c1970f70d37 100644
--- a/core/base-service/loader-test-fixtures/empty-object.fixture.js
+++ b/core/base-service/loader-test-fixtures/empty-object.fixture.js
@@ -1,3 +1 @@
-'use strict'
-
-module.exports = {}
+export {}
diff --git a/core/base-service/loader-test-fixtures/empty-undefined.fixture.js b/core/base-service/loader-test-fixtures/empty-undefined.fixture.js
index 3ad27782bc55c8a434e0117e65d492ef51e7f21c..edb72725b9e7c6da9b38ca291f67938faf293069 100644
--- a/core/base-service/loader-test-fixtures/empty-undefined.fixture.js
+++ b/core/base-service/loader-test-fixtures/empty-undefined.fixture.js
@@ -1,3 +1 @@
-'use strict'
-
-module.exports = undefined
+export default undefined
diff --git a/core/base-service/loader-test-fixtures/invalid-mixed.fixture.js b/core/base-service/loader-test-fixtures/invalid-mixed.fixture.js
index 7cacacc9033edb9b4e0e6ea42e8afde7aa5e940c..40096a3065399a16771c105f32fa1dc6af0f6824 100644
--- a/core/base-service/loader-test-fixtures/invalid-mixed.fixture.js
+++ b/core/base-service/loader-test-fixtures/invalid-mixed.fixture.js
@@ -1,9 +1,10 @@
-'use strict'
-
-const BaseJsonService = require('../base-json')
+import BaseJsonService from '../base-json.js'
 
 class BadBaseService {}
-class GoodService extends BaseJsonService {}
+class GoodService extends BaseJsonService {
+  static category = 'build'
+  static route = { base: 'it/is', pattern: 'good' }
+}
 class BadService extends BadBaseService {}
 
-module.exports = [GoodService, BadService]
+export default [GoodService, BadService]
diff --git a/core/base-service/loader-test-fixtures/invalid-no-base.fixture.js b/core/base-service/loader-test-fixtures/invalid-no-base.fixture.js
index 2a8a55c48effb6be0435b6c5315db7130ad81d9a..4651b17bfef86100381665fba470f8e99447df35 100644
--- a/core/base-service/loader-test-fixtures/invalid-no-base.fixture.js
+++ b/core/base-service/loader-test-fixtures/invalid-no-base.fixture.js
@@ -1,5 +1,3 @@
-'use strict'
-
 class BadService {}
 
-module.exports = BadService
+export default BadService
diff --git a/core/base-service/loader-test-fixtures/invalid-wrong-base.fixture.js b/core/base-service/loader-test-fixtures/invalid-wrong-base.fixture.js
index 89b1451d9616fa1f92e80b10faa6bab48434e4c2..9ca5e17cb45c981739be7f5ae80096550b6e306e 100644
--- a/core/base-service/loader-test-fixtures/invalid-wrong-base.fixture.js
+++ b/core/base-service/loader-test-fixtures/invalid-wrong-base.fixture.js
@@ -1,6 +1,4 @@
-'use strict'
-
 class BadBaseService {}
 class BadService extends BadBaseService {}
 
-module.exports = BadService
+export default BadService
diff --git a/core/base-service/loader-test-fixtures/valid-array.fixture.js b/core/base-service/loader-test-fixtures/valid-array.fixture.js
index ee8e213954d81a7236f4a051be67cb99f15f5102..c820022a8a9af778b6aea8778537a37407760fbe 100644
--- a/core/base-service/loader-test-fixtures/valid-array.fixture.js
+++ b/core/base-service/loader-test-fixtures/valid-array.fixture.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const BaseJsonService = require('../base-json')
+import BaseJsonService from '../base-json.js'
 
 class GoodServiceOne extends BaseJsonService {
   static category = 'build'
@@ -11,4 +9,4 @@ class GoodServiceTwo extends BaseJsonService {
   static route = { base: 'good', pattern: 'two' }
 }
 
-module.exports = [GoodServiceOne, GoodServiceTwo]
+export default [GoodServiceOne, GoodServiceTwo]
diff --git a/core/base-service/loader-test-fixtures/valid-class.fixture.js b/core/base-service/loader-test-fixtures/valid-class.fixture.js
index 41ae5ed9054c26ad52f2482a4442100696eeb7fb..0b193a9405df7e8d35e30b10bf1b9344eefe87d5 100644
--- a/core/base-service/loader-test-fixtures/valid-class.fixture.js
+++ b/core/base-service/loader-test-fixtures/valid-class.fixture.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const BaseJsonService = require('../base-json')
+import BaseJsonService from '../base-json.js'
 
 class GoodService extends BaseJsonService {
   static category = 'build'
   static route = { base: 'it/is', pattern: 'good' }
 }
 
-module.exports = GoodService
+export default GoodService
diff --git a/core/base-service/loader-test-fixtures/valid-object.fixture.js b/core/base-service/loader-test-fixtures/valid-object.fixture.js
index 4bf828f9cc99bb30a5ae4e9bb145aad5adbf4cd0..5a312db98f48ca95a16aa7de43a2bed8e8218546 100644
--- a/core/base-service/loader-test-fixtures/valid-object.fixture.js
+++ b/core/base-service/loader-test-fixtures/valid-object.fixture.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const BaseJsonService = require('../base-json')
+import BaseJsonService from '../base-json.js'
 
 class GoodServiceOne extends BaseJsonService {
   static category = 'build'
@@ -11,4 +9,4 @@ class GoodServiceTwo extends BaseJsonService {
   static route = { base: 'good', pattern: 'two' }
 }
 
-module.exports = { GoodServiceOne, GoodServiceTwo }
+export { GoodServiceOne, GoodServiceTwo }
diff --git a/core/base-service/loader.js b/core/base-service/loader.js
index c2404b8c38da88d54f6a5b26bf15a039c02da504..cf499eca1560f5e68220203c0dde252756317d27 100644
--- a/core/base-service/loader.js
+++ b/core/base-service/loader.js
@@ -1,13 +1,17 @@
-'use strict'
-
-const path = require('path')
-const glob = require('glob')
-const countBy = require('lodash.countby')
-const categories = require('../../services/categories')
-const BaseService = require('./base')
-const { assertValidServiceDefinitionExport } = require('./service-definitions')
-
-const serviceDir = path.join(__dirname, '..', '..', 'services')
+import path from 'path'
+import { fileURLToPath } from 'url'
+import glob from 'glob'
+import countBy from 'lodash.countby'
+import categories from '../../services/categories.js'
+import BaseService from './base.js'
+import { assertValidServiceDefinitionExport } from './service-definitions.js'
+
+const serviceDir = path.join(
+  path.dirname(fileURLToPath(import.meta.url)),
+  '..',
+  '..',
+  'services'
+)
 
 class InvalidService extends Error {
   constructor(message) {
@@ -16,54 +20,38 @@ class InvalidService extends Error {
   }
 }
 
-function loadServiceClasses(servicePaths) {
+async function loadServiceClasses(servicePaths) {
   if (!servicePaths) {
     servicePaths = glob.sync(path.join(serviceDir, '**', '*.service.js'))
   }
 
-  let serviceClasses = []
-  servicePaths.forEach(servicePath => {
-    const module = require(servicePath)
+  const serviceClasses = []
+  for await (const servicePath of servicePaths) {
+    const currentServiceClasses = Object.values(
+      await import(`file://${servicePath}`)
+    ).flatMap(element =>
+      typeof element === 'object' ? Object.values(element) : element
+    )
 
-    const theseServiceClasses = []
-    if (
-      !module ||
-      (module.constructor === Array && module.length === 0) ||
-      (module.constructor === Object && Object.keys(module).length === 0)
-    ) {
+    if (currentServiceClasses.length === 0) {
       throw new InvalidService(
         `Expected ${servicePath} to export a service or a collection of services`
       )
-    } else if (module.prototype instanceof BaseService) {
-      theseServiceClasses.push(module)
-    } else if (module.constructor === Array || module.constructor === Object) {
-      for (const key in module) {
-        const serviceClass = module[key]
-        if (serviceClass.prototype instanceof BaseService) {
-          theseServiceClasses.push(serviceClass)
-        } else {
-          throw new InvalidService(
-            `Expected ${servicePath} to export a service or a collection of services; one of them was ${serviceClass}`
-          )
-        }
+    }
+    currentServiceClasses.forEach(serviceClass => {
+      if (serviceClass && serviceClass.prototype instanceof BaseService) {
+        // Decorate each service class with the directory that contains it.
+        serviceClass.serviceFamily = servicePath
+          .replace(serviceDir, '')
+          .split(path.sep)[1]
+        serviceClass.validateDefinition()
+        return serviceClasses.push(serviceClass)
       }
-    } else {
       throw new InvalidService(
-        `Expected ${servicePath} to export a service or a collection of services; got ${module}`
+        `Expected ${servicePath} to export a service or a collection of services; one of them was ${serviceClass}`
       )
-    }
-
-    // Decorate each service class with the directory that contains it.
-    theseServiceClasses.forEach(serviceClass => {
-      serviceClass.serviceFamily = servicePath
-        .replace(serviceDir, '')
-        .split(path.sep)[1]
     })
-
-    serviceClasses = serviceClasses.concat(theseServiceClasses)
-  })
-
-  serviceClasses.forEach(ServiceClass => ServiceClass.validateDefinition())
+  }
 
   return serviceClasses
 }
@@ -80,8 +68,8 @@ function assertNamesUnique(names, { message }) {
   }
 }
 
-function checkNames() {
-  const services = loadServiceClasses()
+async function checkNames() {
+  const services = await loadServiceClasses()
   assertNamesUnique(
     services.map(({ name }) => name),
     {
@@ -90,8 +78,8 @@ function checkNames() {
   )
 }
 
-function collectDefinitions() {
-  const services = loadServiceClasses()
+async function collectDefinitions() {
+  const services = (await loadServiceClasses())
     // flatMap.
     .map(ServiceClass => ServiceClass.getDefinition())
     .reduce((accum, these) => accum.concat(these), [])
@@ -103,13 +91,15 @@ function collectDefinitions() {
   return result
 }
 
-function loadTesters() {
-  return glob
-    .sync(path.join(serviceDir, '**', '*.tester.js'))
-    .map(path => require(path))
+async function loadTesters() {
+  return Promise.all(
+    glob
+      .sync(path.join(serviceDir, '**', '*.tester.js'))
+      .map(async path => await import(`file://${path}`))
+  )
 }
 
-module.exports = {
+export {
   InvalidService,
   loadServiceClasses,
   checkNames,
diff --git a/core/base-service/loader.spec.js b/core/base-service/loader.spec.js
index 374c17cb004e051a257f885ac2a59a754fbdff3e..e26c28fc1e0ec10ac049a7dbbe2f832a8d59099a 100644
--- a/core/base-service/loader.spec.js
+++ b/core/base-service/loader.spec.js
@@ -1,59 +1,67 @@
-'use strict'
+import path from 'path'
+import { fileURLToPath } from 'url'
+import chai from 'chai'
+import chaiAsPromised from 'chai-as-promised'
+import { loadServiceClasses, InvalidService } from './loader.js'
+chai.use(chaiAsPromised)
 
-const { expect } = require('chai')
-const { loadServiceClasses, InvalidService } = require('./loader')
+const { expect } = chai
+const fixturesDir = path.join(
+  path.dirname(fileURLToPath(import.meta.url)),
+  'loader-test-fixtures'
+)
 
 describe('loadServiceClasses function', function () {
-  it('throws if module exports empty', function () {
-    expect(() =>
-      loadServiceClasses(['./loader-test-fixtures/empty-undefined.fixture.js'])
-    ).to.throw(InvalidService)
-    expect(() =>
-      loadServiceClasses(['./loader-test-fixtures/empty-array.fixture.js'])
-    ).to.throw()
-    expect(() =>
-      loadServiceClasses(['./loader-test-fixtures/empty-object.fixture.js'])
-    ).to.throw(InvalidService)
-    expect(() =>
-      loadServiceClasses(['./loader-test-fixtures/empty-no-export.fixture.js'])
-    ).to.throw(InvalidService)
-    expect(() =>
+  it('throws if module exports empty', async function () {
+    await expect(
+      loadServiceClasses([path.join(fixturesDir, 'empty-undefined.fixture.js')])
+    ).to.be.rejectedWith(InvalidService)
+    await expect(
+      loadServiceClasses([path.join(fixturesDir, 'empty-array.fixture.js')])
+    ).to.be.rejectedWith(InvalidService)
+    await expect(
+      loadServiceClasses([path.join(fixturesDir, 'empty-object.fixture.js')])
+    ).to.be.rejectedWith(InvalidService)
+    await expect(
+      loadServiceClasses([path.join(fixturesDir, 'empty-no-export.fixture.js')])
+    ).to.be.rejectedWith(InvalidService)
+    await expect(
       loadServiceClasses([
-        './loader-test-fixtures/valid-array.fixture.js',
-        './loader-test-fixtures/valid-class.fixture.js',
-        './loader-test-fixtures/empty-array.fixture.js',
+        path.join(fixturesDir, 'valid-array.fixture.js'),
+        path.join(fixturesDir, 'valid-class.fixture.js'),
+        path.join(fixturesDir, 'empty-array.fixture.js'),
       ])
-    ).to.throw(InvalidService)
+    ).to.be.rejectedWith(InvalidService)
   })
 
-  it('throws if module exports invalid', function () {
-    expect(() =>
-      loadServiceClasses(['./loader-test-fixtures/invalid-no-base.fixture.js'])
-    ).to.throw(InvalidService)
-    expect(() =>
+  it('throws if module exports invalid', async function () {
+    await expect(
+      loadServiceClasses([path.join(fixturesDir, 'invalid-no-base.fixture.js')])
+    ).to.be.rejectedWith(InvalidService)
+    await expect(
       loadServiceClasses([
-        './loader-test-fixtures/invalid-wrong-base.fixture.js',
+        path.join(fixturesDir, 'invalid-wrong-base.fixture.js'),
       ])
-    ).to.throw(InvalidService)
-    expect(() =>
-      loadServiceClasses(['./loader-test-fixtures/invalid-mixed.fixture.js'])
-    ).to.throw(InvalidService)
-    expect(() =>
+    ).to.be.rejectedWith(InvalidService)
+    await expect(
+      loadServiceClasses([path.join(fixturesDir, 'invalid-mixed.fixture.js')])
+    ).to.be.rejectedWith(InvalidService)
+    await expect(
       loadServiceClasses([
-        './loader-test-fixtures/valid-array.fixture.js',
-        './loader-test-fixtures/valid-class.fixture.js',
-        './loader-test-fixtures/invalid-no-base.fixture.js',
+        path.join(fixturesDir, 'valid-array.fixture.js'),
+        path.join(fixturesDir, 'valid-class.fixture.js'),
+        path.join(fixturesDir, 'invalid-no-base.fixture.js'),
       ])
-    ).to.throw(InvalidService)
+    ).to.be.rejectedWith(InvalidService)
   })
 
-  it('registers services if module exports valid service classes', function () {
-    expect(
+  it('registers services if module exports valid service classes', async function () {
+    await expect(
       loadServiceClasses([
-        './loader-test-fixtures/valid-array.fixture.js',
-        './loader-test-fixtures/valid-object.fixture.js',
-        './loader-test-fixtures/valid-class.fixture.js',
+        path.join(fixturesDir, 'valid-array.fixture.js'),
+        path.join(fixturesDir, 'valid-object.fixture.js'),
+        path.join(fixturesDir, 'valid-class.fixture.js'),
       ])
-    ).to.have.length(5)
+    ).to.eventually.have.length(5)
   })
 })
diff --git a/core/base-service/metric-helper.js b/core/base-service/metric-helper.js
index 33f472b02d45e2acd7c35fe8875a8da1c886cc17..646aa721b5a28f1d94c7721c03d1d6d26e8b14ee 100644
--- a/core/base-service/metric-helper.js
+++ b/core/base-service/metric-helper.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { performance } = require('perf_hooks')
+import { performance } from 'perf_hooks'
 
 class MetricHelper {
   constructor({ metricInstance }, { category, serviceFamily, name }) {
@@ -59,4 +57,4 @@ const MetricNames = Object.freeze({
   SERVICE_RESPONSE_SIZE: Symbol('service-response-size'),
 })
 
-module.exports = { MetricHelper, MetricNames }
+export { MetricHelper, MetricNames }
diff --git a/core/base-service/redirector.js b/core/base-service/redirector.js
index 5d499e9dad59b85726c2a5e880407c1004389e62..094e3af07f48590f0d9f24f0b6705668b13f4a12 100644
--- a/core/base-service/redirector.js
+++ b/core/base-service/redirector.js
@@ -1,18 +1,16 @@
-'use strict'
-
-const camelcase = require('camelcase')
-const emojic = require('emojic')
-const Joi = require('joi')
-const queryString = require('query-string')
-const BaseService = require('./base')
-const {
+import camelcase from 'camelcase'
+import emojic from 'emojic'
+import Joi from 'joi'
+import queryString from 'query-string'
+import BaseService from './base.js'
+import {
   serverHasBeenUpSinceResourceCached,
   setCacheHeadersForStaticResource,
-} = require('./cache-headers')
-const { isValidCategory } = require('./categories')
-const { MetricHelper } = require('./metric-helper')
-const { isValidRoute, prepareRoute, namedParamsForMatch } = require('./route')
-const trace = require('./trace')
+} from './cache-headers.js'
+import { isValidCategory } from './categories.js'
+import { MetricHelper } from './metric-helper.js'
+import { isValidRoute, prepareRoute, namedParamsForMatch } from './route.js'
+import trace from './trace.js'
 
 const attrSchema = Joi.object({
   name: Joi.string().min(3),
@@ -32,7 +30,7 @@ const attrSchema = Joi.object({
   overrideTransformedQueryParams: Joi.bool().optional(),
 }).required()
 
-module.exports = function redirector(attrs) {
+export default function redirector(attrs) {
   const {
     name,
     category,
diff --git a/core/base-service/redirector.spec.js b/core/base-service/redirector.spec.js
index 1f81913c6fba1343e7b873103ef95af211c5f5df..4b1912d2305e44c472dc3fce37ad7c495a99038f 100644
--- a/core/base-service/redirector.spec.js
+++ b/core/base-service/redirector.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Camp = require('@shields_io/camp')
-const portfinder = require('portfinder')
-const { expect } = require('chai')
-const got = require('../got-test-client')
-const redirector = require('./redirector')
+import Camp from '@shields_io/camp'
+import portfinder from 'portfinder'
+import { expect } from 'chai'
+import got from '../got-test-client.js'
+import redirector from './redirector.js'
 
 describe('Redirector', function () {
   const route = {
diff --git a/core/base-service/route.js b/core/base-service/route.js
index 9d60b495af0478079fae02032a5ba2ca274007fc..24a7801ed14793501f06cf4db53fbe74d9a399a4 100644
--- a/core/base-service/route.js
+++ b/core/base-service/route.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const escapeStringRegexp = require('escape-string-regexp')
-const Joi = require('joi')
-const { pathToRegexp } = require('path-to-regexp')
+import escapeStringRegexp from 'escape-string-regexp'
+import Joi from 'joi'
+import { pathToRegexp } from 'path-to-regexp'
 
 function makeFullUrl(base, partialUrl) {
   return `/${[base, partialUrl].filter(Boolean).join('/')}`
@@ -74,7 +72,7 @@ function getQueryParamNames({ queryParamSchema }) {
   }
 }
 
-module.exports = {
+export {
   makeFullUrl,
   isValidRoute,
   assertValidRoute,
diff --git a/core/base-service/route.spec.js b/core/base-service/route.spec.js
index 612a0d5cc27f1aa6b1c9ebe8acfa8a94486a798d..42326d8745d8b1efacfb500aace6c02ddccaa43a 100644
--- a/core/base-service/route.spec.js
+++ b/core/base-service/route.spec.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const { expect } = require('chai')
-const Joi = require('joi')
-const { test, given, forCases } = require('sazerac')
-const {
+import { expect } from 'chai'
+import Joi from 'joi'
+import { test, given, forCases } from 'sazerac'
+import {
   prepareRoute,
   namedParamsForMatch,
   getQueryParamNames,
-} = require('./route')
+} from './route.js'
 
 describe('Route helpers', function () {
   context('A `pattern` with a named param is declared', function () {
diff --git a/core/base-service/service-definitions.js b/core/base-service/service-definitions.js
index 3f931458276cf07c2d4353bae36a96708a7ed172..1d66f4e91446c71f3b65c1d650686f0bdccc5b10 100644
--- a/core/base-service/service-definitions.js
+++ b/core/base-service/service-definitions.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const Joi = require('joi')
+import Joi from 'joi'
 
 // This should be kept in sync with the schema in
 // `frontend/lib/service-definitions/index.ts`.
@@ -72,7 +70,7 @@ function assertValidServiceDefinitionExport(examples, message = undefined) {
   Joi.assert(examples, serviceDefinitionExport, message)
 }
 
-module.exports = {
+export {
   serviceDefinition,
   assertValidServiceDefinition,
   serviceDefinitionExport,
diff --git a/core/base-service/to-array.js b/core/base-service/to-array.js
index e22a7227b39dd5a7e3fa04a861baad1c0662a253..f2131490cf6a6e0b5c2a8c89f73effa8f4c30ba4 100644
--- a/core/base-service/to-array.js
+++ b/core/base-service/to-array.js
@@ -1,6 +1,4 @@
-'use strict'
-
-module.exports = function toArray(val) {
+export default function toArray(val) {
   if (val === undefined) {
     return []
   } else if (Object(val) instanceof Array) {
diff --git a/core/base-service/trace.js b/core/base-service/trace.js
index 97ef96c66cbb888d99cfe568f73552eb6977343e..7eda5881c52c8dc4d2a0cbd23d732ff8435dba08 100644
--- a/core/base-service/trace.js
+++ b/core/base-service/trace.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const chalk = require('chalk')
-const config = require('config').util.toObject()
+import chalk from 'chalk'
+import config from 'config'
+const objectConfig = config.util.toObject()
 
 // Config is loaded globally but it would be better to inject it. To do that,
 // there needs to be one instance of the service created at registration time,
@@ -10,7 +9,7 @@ const config = require('config').util.toObject()
 // thereby gaining access to the injected config.
 const {
   services: { trace: enableTraceLogging },
-} = config.public
+} = objectConfig.public
 
 function _formatLabelForStage(stage, label) {
   const colorFn = {
@@ -37,6 +36,6 @@ function logTrace(stage, symbol, label, content, { deep = false } = {}) {
   }
 }
 
-module.exports = {
+export default {
   logTrace,
 }
diff --git a/core/base-service/validate.js b/core/base-service/validate.js
index a2da0e922da020f4ae2d3b2c0d86ab6d16588b0a..23990b15dd58e1601f5b78befef4295bfb066bda 100644
--- a/core/base-service/validate.js
+++ b/core/base-service/validate.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const emojic = require('emojic')
-const Joi = require('joi')
-const trace = require('./trace')
+import emojic from 'emojic'
+import Joi from 'joi'
+import trace from './trace.js'
 
 function validate(
   {
@@ -50,4 +48,4 @@ function validate(
   }
 }
 
-module.exports = validate
+export default validate
diff --git a/core/base-service/validate.spec.js b/core/base-service/validate.spec.js
index c51f7710703857bed08be6d83ca07f05cec9797c..78f6c46f5ceeb8904df9b1de0671d35051724595 100644
--- a/core/base-service/validate.spec.js
+++ b/core/base-service/validate.spec.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const Joi = require('joi')
-const { expect } = require('chai')
-const sinon = require('sinon')
-const trace = require('./trace')
-const { InvalidParameter } = require('./errors')
-const validate = require('./validate')
+import Joi from 'joi'
+import { expect } from 'chai'
+import sinon from 'sinon'
+import trace from './trace.js'
+import { InvalidParameter } from './errors.js'
+import validate from './validate.js'
 
 describe('validate', function () {
   const schema = Joi.object({
diff --git a/core/got-test-client.js b/core/got-test-client.js
index 70af889af97bcaff531f6ef6a716fb859f508fc1..d8800f46173c162774dfae36c7f896429810439b 100644
--- a/core/got-test-client.js
+++ b/core/got-test-client.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const got = require('got')
+import got from 'got'
 
 // https://github.com/nock/nock/issues/1523
-module.exports = got.extend({ retry: 0 })
+export default got.extend({ retry: 0 })
diff --git a/core/legacy/regular-update.js b/core/legacy/regular-update.js
index e32e05c412d1fe8165092c9585ad33bcf93cc1dc..d60d89112f7e41126312e08f95c3d1e58bc5c114 100644
--- a/core/legacy/regular-update.js
+++ b/core/legacy/regular-update.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const { Inaccessible, InvalidResponse } = require('../base-service/errors')
+import requestModule from 'request'
+import { Inaccessible, InvalidResponse } from '../base-service/errors.js'
 
 // Map from URL to { timestamp: last fetch time, data: data }.
 let regularUpdateCache = Object.create(null)
@@ -11,8 +10,8 @@ let regularUpdateCache = Object.create(null)
 //
 // To use this from a service:
 //
-// const { promisify } = require('util')
-// const { regularUpdate } = require('../../core/legacy/regular-update')
+// import { promisify } from 'util'
+// import { regularUpdate } from '../../core/legacy/regular-update.js'
 //
 // function getThing() {
 //   return promisify(regularUpdate)({
@@ -32,7 +31,7 @@ function regularUpdate(
     json = true,
     scraper = buffer => buffer,
     options = {},
-    request = require('request'),
+    request = requestModule,
   },
   cb
 ) {
@@ -95,7 +94,4 @@ function clearRegularUpdateCache() {
   regularUpdateCache = Object.create(null)
 }
 
-module.exports = {
-  regularUpdate,
-  clearRegularUpdateCache,
-}
+export { regularUpdate, clearRegularUpdateCache }
diff --git a/core/register-chai-plugins.spec.js b/core/register-chai-plugins.spec.js
index 0873f4c86344f6fbbcb7edfe7e21efa05694ec9a..7b38803d7b8d0faf105f608d86d0b229167f7745 100644
--- a/core/register-chai-plugins.spec.js
+++ b/core/register-chai-plugins.spec.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const { use } = require('chai')
-
-use(require('chai-string'))
-use(require('sinon-chai'))
+import { use } from 'chai'
+import chaiString from 'chai-string'
+import sinonChai from 'sinon-chai'
+use(chaiString)
+use(sinonChai)
diff --git a/core/server/in-process-server-test-helpers.js b/core/server/in-process-server-test-helpers.js
index 85280a1a316292c5ec132b890c53c0eb47ae7e13..f27bc447c20314abe8d9dea8434fd90935cdfa3d 100644
--- a/core/server/in-process-server-test-helpers.js
+++ b/core/server/in-process-server-test-helpers.js
@@ -1,18 +1,14 @@
-'use strict'
-
-const merge = require('deepmerge')
-const config = require('config').util.toObject()
-const portfinder = require('portfinder')
-const Server = require('./server')
+import merge from 'deepmerge'
+import config from 'config'
+import portfinder from 'portfinder'
+import Server from './server.js'
 
 async function createTestServer(customConfig = {}) {
-  const mergedConfig = merge(config, customConfig)
+  const mergedConfig = merge(config.util.toObject(), customConfig)
   if (!mergedConfig.public.bind.port) {
     mergedConfig.public.bind.port = await portfinder.getPortPromise()
   }
   return new Server(mergedConfig)
 }
 
-module.exports = {
-  createTestServer,
-}
+export { createTestServer }
diff --git a/core/server/influx-metrics.js b/core/server/influx-metrics.js
index 2d87cc56d5af9a6b77ceb2dffb29471122627a55..eae365f9e0cc663e7a950189bff49067ce7af4e7 100644
--- a/core/server/influx-metrics.js
+++ b/core/server/influx-metrics.js
@@ -1,11 +1,10 @@
-'use strict'
-const os = require('os')
-const got = require('got')
-const generateInstanceId = require('./instance-id-generator')
-const { promClientJsonToInfluxV2 } = require('./metrics/format-converters')
-const log = require('./log')
+import os from 'os'
+import got from 'got'
+import generateInstanceId from './instance-id-generator.js'
+import { promClientJsonToInfluxV2 } from './metrics/format-converters.js'
+import log from './log.js'
 
-module.exports = class InfluxMetrics {
+export default class InfluxMetrics {
   constructor(metricInstance, config) {
     this._metricInstance = metricInstance
     this._config = config
diff --git a/core/server/influx-metrics.spec.js b/core/server/influx-metrics.spec.js
index 4b91b055230bcc21899c3cd9ea512fb4ac4dd65d..529edeaaeb1325a815ada3df50a144ccaa927ac3 100644
--- a/core/server/influx-metrics.spec.js
+++ b/core/server/influx-metrics.spec.js
@@ -1,11 +1,10 @@
-'use strict'
-const os = require('os')
-const nock = require('nock')
-const sinon = require('sinon')
-const { expect } = require('chai')
-const log = require('./log')
-const InfluxMetrics = require('./influx-metrics')
-require('../register-chai-plugins.spec')
+import os from 'os'
+import nock from 'nock'
+import sinon from 'sinon'
+import { expect } from 'chai'
+import log from './log.js'
+import InfluxMetrics from './influx-metrics.js'
+import '../register-chai-plugins.spec.js'
 describe('Influx metrics', function () {
   const metricInstance = {
     metrics() {
diff --git a/core/server/instance-id-generator.js b/core/server/instance-id-generator.js
index e156070161ec559e8dd54b8d8e62c52822bdb324..63ad06d09a3870ef554b3874d97682c9658a53c4 100644
--- a/core/server/instance-id-generator.js
+++ b/core/server/instance-id-generator.js
@@ -1,8 +1,6 @@
-'use strict'
-
 function generateInstanceId() {
   // from https://gist.github.com/gordonbrander/2230317
   return Math.random().toString(36).substr(2, 9)
 }
 
-module.exports = generateInstanceId
+export default generateInstanceId
diff --git a/core/server/log.js b/core/server/log.js
index 46cb98a24ac1e02b0c0adb7c0e5c9ca3eee8833e..c89aae419a606f4d0aa2e421a893adf560aa3bfb 100644
--- a/core/server/log.js
+++ b/core/server/log.js
@@ -1,5 +1,4 @@
-'use strict'
-const Sentry = require('@sentry/node')
+import Sentry from '@sentry/node'
 
 const listeners = []
 
@@ -23,27 +22,32 @@ function date() {
   )
 }
 
-module.exports = function log(...msg) {
+const log = (...msg) => {
   const d = date()
   listeners.forEach(f => f(d, ...msg))
   console.log(d, ...msg)
 }
 
-module.exports.error = function error(err) {
+const error = err => {
   const d = date()
   listeners.forEach(f => f(d, err))
   Sentry.captureException(err)
   console.error(d, err)
 }
 
-module.exports.addListener = function addListener(func) {
-  listeners.push(func)
-}
+const addListener = func => listeners.push(func)
 
-module.exports.removeListener = function removeListener(func) {
+const removeListener = func => {
   const index = listeners.indexOf(func)
   if (index < 0) {
     return
   }
   listeners.splice(index, 1)
 }
+
+export default {
+  log,
+  error,
+  addListener,
+  removeListener,
+}
diff --git a/core/server/metrics/format-converters.js b/core/server/metrics/format-converters.js
index bb3903a68422b18a307b72259ff2062a8b578012..53a60b0f546305dd9e129350d9943ec341fca3f4 100644
--- a/core/server/metrics/format-converters.js
+++ b/core/server/metrics/format-converters.js
@@ -1,5 +1,4 @@
-'use strict'
-const groupBy = require('lodash.groupby')
+import groupBy from 'lodash.groupby'
 
 function promClientJsonToInfluxV2(metrics, extraLabels = {}) {
   return metrics
@@ -24,4 +23,4 @@ function promClientJsonToInfluxV2(metrics, extraLabels = {}) {
     .join('\n')
 }
 
-module.exports = { promClientJsonToInfluxV2 }
+export { promClientJsonToInfluxV2 }
diff --git a/core/server/metrics/format-converters.spec.js b/core/server/metrics/format-converters.spec.js
index f4f238142978039235a0bffe8434fa47794c3651..3ea4a51028cdc2df3e39b2feb8ba160e5f6ae6bc 100644
--- a/core/server/metrics/format-converters.spec.js
+++ b/core/server/metrics/format-converters.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { expect } = require('chai')
-const prometheus = require('prom-client')
-const { promClientJsonToInfluxV2 } = require('./format-converters')
+import { expect } from 'chai'
+import prometheus from 'prom-client'
+import { promClientJsonToInfluxV2 } from './format-converters.js'
 
 describe('Metric format converters', function () {
   describe('prom-client JSON to InfluxDB line protocol (version 2)', function () {
diff --git a/core/server/prometheus-metrics.js b/core/server/prometheus-metrics.js
index a19c916d920d50bff842a807318483c589374272..072a497c1bafb3dd05d111cf9f0830abc341a8f1 100644
--- a/core/server/prometheus-metrics.js
+++ b/core/server/prometheus-metrics.js
@@ -1,9 +1,7 @@
-'use strict'
+import decamelize from 'decamelize'
+import prometheus from 'prom-client'
 
-const decamelize = require('decamelize')
-const prometheus = require('prom-client')
-
-module.exports = class PrometheusMetrics {
+export default class PrometheusMetrics {
   constructor({ register } = {}) {
     this.register = register || new prometheus.Registry()
     this.counters = {
diff --git a/core/server/prometheus-metrics.spec.js b/core/server/prometheus-metrics.spec.js
index 22cffbaef78f8bb91b72ada694d1379fd6bfc6b6..31fa40afb0bad236bcb4084d8fcc74e059ecd1ce 100644
--- a/core/server/prometheus-metrics.spec.js
+++ b/core/server/prometheus-metrics.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { expect } = require('chai')
-const Camp = require('@shields_io/camp')
-const portfinder = require('portfinder')
-const got = require('../got-test-client')
-const Metrics = require('./prometheus-metrics')
+import { expect } from 'chai'
+import Camp from '@shields_io/camp'
+import portfinder from 'portfinder'
+import got from '../got-test-client.js'
+import Metrics from './prometheus-metrics.js'
 
 describe('Prometheus metrics route', function () {
   let port, baseUrl, camp, metrics
diff --git a/core/server/secret-is-valid.js b/core/server/secret-is-valid.js
index d00118969add8647f11a6d3dfd018e01c1c627d5..c8b87ffda123fbee838e1f46146a11f9dbef69df 100644
--- a/core/server/secret-is-valid.js
+++ b/core/server/secret-is-valid.js
@@ -1,5 +1,3 @@
-'use strict'
-
 function constEq(a, b) {
   if (a.length !== b.length) {
     return false
@@ -17,4 +15,4 @@ function makeSecretIsValid(shieldsSecret) {
   }
 }
 
-module.exports = { makeSecretIsValid }
+export { makeSecretIsValid }
diff --git a/core/server/server.js b/core/server/server.js
index 36e9d57d738099fc1ae25558ed634dc70a71188a..b19278b04996324886f9ef02a6d75c9711926280 100644
--- a/core/server/server.js
+++ b/core/server/server.js
@@ -1,27 +1,26 @@
-'use strict'
 /**
  * @module
  */
 
-const path = require('path')
-const url = require('url')
+import path from 'path'
+import url, { fileURLToPath } from 'url'
+import cloudflareMiddleware from 'cloudflare-middleware'
+import bytes from 'bytes'
+import Camp from '@shields_io/camp'
+import originalJoi from 'joi'
+import makeBadge from '../../badge-maker/lib/make-badge.js'
+import GithubConstellation from '../../services/github/github-constellation.js'
+import { setRoutes } from '../../services/suggest.js'
+import { loadServiceClasses } from '../base-service/loader.js'
+import { makeSend } from '../base-service/legacy-result-sender.js'
+import { handleRequest } from '../base-service/legacy-request-handler.js'
+import { clearRegularUpdateCache } from '../legacy/regular-update.js'
+import { rasterRedirectUrl } from '../badge-urls/make-badge-url.js'
+import { nonNegativeInteger } from '../../services/validators.js'
+import log from './log.js'
+import PrometheusMetrics from './prometheus-metrics.js'
+import InfluxMetrics from './influx-metrics.js'
 const { URL } = url
-const cloudflareMiddleware = require('cloudflare-middleware')
-const bytes = require('bytes')
-const Camp = require('@shields_io/camp')
-const originalJoi = require('joi')
-const makeBadge = require('../../badge-maker/lib/make-badge')
-const GithubConstellation = require('../../services/github/github-constellation')
-const suggest = require('../../services/suggest')
-const { loadServiceClasses } = require('../base-service/loader')
-const { makeSend } = require('../base-service/legacy-result-sender')
-const { handleRequest } = require('../base-service/legacy-request-handler')
-const { clearRegularUpdateCache } = require('../legacy/regular-update')
-const { rasterRedirectUrl } = require('../badge-urls/make-badge-url')
-const { nonNegativeInteger } = require('../../services/validators')
-const log = require('./log')
-const PrometheusMetrics = require('./prometheus-metrics')
-const InfluxMetrics = require('./influx-metrics')
 
 const Joi = originalJoi
   .extend(base => ({
@@ -143,7 +142,12 @@ const publicConfigSchema = Joi.object({
   requestTimeoutSeconds: nonNegativeInteger,
   requestTimeoutMaxAgeSeconds: nonNegativeInteger,
   documentRoot: Joi.string().default(
-    path.resolve(__dirname, '..', '..', 'public')
+    path.resolve(
+      path.dirname(fileURLToPath(import.meta.url)),
+      '..',
+      '..',
+      'public'
+    )
   ),
   requireCloudflare: Joi.boolean().required(),
 }).required()
@@ -399,11 +403,11 @@ class Server {
    * Iterate all the service classes defined in /services,
    * load each service and register a Scoutcamp route for each service.
    */
-  registerServices() {
+  async registerServices() {
     const { config, camp, metricInstance } = this
     const { apiProvider: githubApiProvider } = this.githubConstellation
 
-    loadServiceClasses().forEach(serviceClass =>
+    ;(await loadServiceClasses()).forEach(serviceClass =>
       serviceClass.register(
         { camp, handleRequest, githubApiProvider, metricInstance },
         {
@@ -432,7 +436,7 @@ class Server {
       requireCloudflare,
     } = this.config.public
 
-    log(`Server is starting up: ${this.baseUrl}`)
+    log.log(`Server is starting up: ${this.baseUrl}`)
 
     const camp = (this.camp = Camp.create({
       documentRoot: this.config.public.documentRoot,
@@ -460,11 +464,11 @@ class Server {
     }
 
     const { apiProvider: githubApiProvider } = this.githubConstellation
-    suggest.setRoutes(allowedOrigin, githubApiProvider, camp)
+    setRoutes(allowedOrigin, githubApiProvider, camp)
 
     this.registerErrorHandlers()
     this.registerRedirects()
-    this.registerServices()
+    await this.registerServices()
 
     camp.timeout = this.config.public.requestTimeoutSeconds * 1000
     if (this.config.public.requestTimeoutSeconds > 0) {
@@ -522,4 +526,4 @@ class Server {
   }
 }
 
-module.exports = Server
+export default Server
diff --git a/core/server/server.spec.js b/core/server/server.spec.js
index 3955561034f461ad244ceb3ced7734dcdc87807f..dc43db3f5607db1182e76f7fda7e5716ed771cfe 100644
--- a/core/server/server.spec.js
+++ b/core/server/server.spec.js
@@ -1,14 +1,13 @@
-'use strict'
-
-const path = require('path')
-const { expect } = require('chai')
-const isSvg = require('is-svg')
-const config = require('config')
-const nock = require('nock')
-const sinon = require('sinon')
-const got = require('../got-test-client')
-const Server = require('./server')
-const { createTestServer } = require('./in-process-server-test-helpers')
+import path from 'path'
+import { fileURLToPath } from 'url'
+import { expect } from 'chai'
+import isSvg from 'is-svg'
+import config from 'config'
+import nock from 'nock'
+import sinon from 'sinon'
+import got from '../got-test-client.js'
+import Server from './server.js'
+import { createTestServer } from './in-process-server-test-helpers.js'
 
 describe('The server', function () {
   describe('running', function () {
@@ -18,7 +17,10 @@ describe('The server', function () {
       this.timeout(10000)
       server = await createTestServer({
         public: {
-          documentRoot: path.resolve(__dirname, 'test-public'),
+          documentRoot: path.resolve(
+            path.dirname(fileURLToPath(import.meta.url)),
+            'test-public'
+          ),
         },
       })
       baseUrl = server.baseUrl
diff --git a/core/service-test-runner/cli.js b/core/service-test-runner/cli.js
index d63be95a0d3559e1e2439f13c156dea537037b51..917c1f859b499c4cc063c6b5d9e095bb77c0672a 100644
--- a/core/service-test-runner/cli.js
+++ b/core/service-test-runner/cli.js
@@ -54,19 +54,31 @@
 //    Relying on npm scripts is safer. Using "pre" makes it impossible to run
 //    the second step without the first.
 
-'use strict'
+import minimist from 'minimist'
+import envFlag from 'node-env-flag'
+import readAllStdinSync from 'read-all-stdin-sync'
+import { createTestServer } from '../server/in-process-server-test-helpers.js'
+import Runner from './runner.js'
 
-const minimist = require('minimist')
-const envFlag = require('node-env-flag')
-const readAllStdinSync = require('read-all-stdin-sync')
-const { createTestServer } = require('../server/in-process-server-test-helpers')
-const Runner = require('./runner')
-
-require('../unhandled-rejection.spec')
+import('../unhandled-rejection.spec.js')
 
 const retry = {}
 retry.count = parseInt(process.env.RETRY_COUNT) || 0
 retry.backoff = parseInt(process.env.RETRY_BACKOFF) || 0
+
+const args = minimist(process.argv.slice(3))
+const stdinOption = args.stdin
+const onlyOption = args.only
+let onlyServices
+if (stdinOption && onlyOption) {
+  console.error('Do not use --only with --stdin')
+} else if (stdinOption) {
+  const allStdin = readAllStdinSync().trim()
+  onlyServices = allStdin ? allStdin.split('\n') : []
+} else if (onlyOption) {
+  onlyServices = onlyOption.split(',')
+}
+
 let baseUrl, server
 if (process.env.TESTED_SERVER_URL) {
   baseUrl = process.env.TESTED_SERVER_URL
@@ -81,7 +93,7 @@ if (process.env.TESTED_SERVER_URL) {
         },
       },
     })
-    server.start()
+    await server.start()
   })
   after('Shut down the server', async function () {
     if (server) {
@@ -92,7 +104,7 @@ if (process.env.TESTED_SERVER_URL) {
 
 const skipIntercepted = envFlag(process.env.SKIP_INTERCEPTED, false)
 const runner = new Runner({ baseUrl, skipIntercepted, retry })
-runner.prepare()
+await runner.prepare()
 
 // The server's request cache causes side effects between tests.
 if (!process.env.TESTED_SERVER_URL) {
@@ -101,21 +113,6 @@ if (!process.env.TESTED_SERVER_URL) {
   }
 }
 
-const args = minimist(process.argv.slice(3))
-const stdinOption = args.stdin
-const onlyOption = args.only
-
-let onlyServices
-
-if (stdinOption && onlyOption) {
-  console.error('Do not use --only with --stdin')
-} else if (stdinOption) {
-  const allStdin = readAllStdinSync().trim()
-  onlyServices = allStdin ? allStdin.split('\n') : []
-} else if (onlyOption) {
-  onlyServices = onlyOption.split(',')
-}
-
 if (typeof onlyServices === 'undefined' || onlyServices.includes('*****')) {
   console.info('Running all service tests.')
 } else if (onlyServices.length === 0) {
diff --git a/core/service-test-runner/create-service-tester.js b/core/service-test-runner/create-service-tester.js
index 4f90a614c4300ee618aff499ab09b8fc7c950cbd..17246b6693374427c4e8d590bf8cccf502a7b569 100644
--- a/core/service-test-runner/create-service-tester.js
+++ b/core/service-test-runner/create-service-tester.js
@@ -1,11 +1,10 @@
-'use strict'
 /**
  * @module
  */
 
-const caller = require('caller')
-const BaseService = require('../base-service/base')
-const ServiceTester = require('./service-tester')
+import caller from 'caller'
+import BaseService from '../base-service/base.js'
+import ServiceTester from './service-tester.js'
 
 /**
  * Automatically create a ServiceTester.
@@ -19,9 +18,9 @@ const ServiceTester = require('./service-tester')
  * @returns {module:core/service-test-runner/service-tester~ServiceTester}
  *    ServiceTester instance
  */
-function createServiceTester() {
+async function createServiceTester() {
   const servicePath = caller().replace('.tester.js', '.service.js')
-  const ServiceClass = require(servicePath)
+  const ServiceClass = Object.values(await import(servicePath))[0]
   if (!(ServiceClass.prototype instanceof BaseService)) {
     throw Error(
       `${servicePath} does not export a single service. Invoke new ServiceTester() directly.`
@@ -30,4 +29,4 @@ function createServiceTester() {
   return ServiceTester.forServiceClass(ServiceClass)
 }
 
-module.exports = createServiceTester
+export default createServiceTester
diff --git a/core/service-test-runner/icedfrisby-shields.js b/core/service-test-runner/icedfrisby-shields.js
index f4a99b7b720b7b1fc05bdc117b9e80fa180d6b0b..947b7f2eb08bacfd9271b30eb785d1d524c2cbe0 100644
--- a/core/service-test-runner/icedfrisby-shields.js
+++ b/core/service-test-runner/icedfrisby-shields.js
@@ -1,10 +1,9 @@
-'use strict'
 /**
  * @module
  */
 
-const Joi = require('joi')
-const { expect } = require('chai')
+import Joi from 'joi'
+import { expect } from 'chai'
 
 /**
  * Factory which wraps an "icedfrisby-nock" with some additional functionality:
@@ -85,4 +84,4 @@ const factory = superclass =>
     }
   }
 
-module.exports = factory
+export default factory
diff --git a/core/service-test-runner/infer-pull-request.js b/core/service-test-runner/infer-pull-request.js
index c9c4695fbeeef4884edfca031b6a74e37b8af8e0..91a46cadb857d711d38c0ae5710eef3765f8ccbc 100644
--- a/core/service-test-runner/infer-pull-request.js
+++ b/core/service-test-runner/infer-pull-request.js
@@ -1,9 +1,8 @@
-'use strict'
 /**
  * @module
  */
 
-const { URL, format: urlFormat } = require('url')
+import { URL, format as urlFormat } from 'url'
 
 function formatSlug(owner, repo, pullRequest) {
   return `${owner}/${repo}#${pullRequest}`
@@ -98,8 +97,4 @@ function inferPullRequest(env = process.env) {
  * @property {string} slug owner/repo/#pullRequest
  */
 
-module.exports = {
-  parseGithubPullRequestUrl,
-  parseGithubRepoSlug,
-  inferPullRequest,
-}
+export { parseGithubPullRequestUrl, parseGithubRepoSlug, inferPullRequest }
diff --git a/core/service-test-runner/infer-pull-request.spec.js b/core/service-test-runner/infer-pull-request.spec.js
index 610c258eebb6e8a56754c128682a5b805352e9a8..c2050d533e4062ddc23fe811e9b0da718fe37be7 100644
--- a/core/service-test-runner/infer-pull-request.spec.js
+++ b/core/service-test-runner/infer-pull-request.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { test, given, forCases } = require('sazerac')
-const {
+import { test, given, forCases } from 'sazerac'
+import {
   parseGithubPullRequestUrl,
   inferPullRequest,
-} = require('./infer-pull-request')
+} from './infer-pull-request.js'
 
 describe('Pull request inference', function () {
   test(parseGithubPullRequestUrl, () => {
diff --git a/core/service-test-runner/pull-request-services-cli.js b/core/service-test-runner/pull-request-services-cli.js
index 0a23f638edb12f08777c555c77318867efe28d7b..34d8d20993c784515a8dee0cc58ce515b11bd4ef 100644
--- a/core/service-test-runner/pull-request-services-cli.js
+++ b/core/service-test-runner/pull-request-services-cli.js
@@ -13,11 +13,9 @@
 //
 // TRAVIS=1 TRAVIS_REPO_SLUG=badges/shields TRAVIS_PULL_REQUEST=1108 npm run test:services:pr:prepare
 
-'use strict'
-
-const got = require('got')
-const { inferPullRequest } = require('./infer-pull-request')
-const servicesForTitle = require('./services-for-title')
+import got from 'got'
+import { inferPullRequest } from './infer-pull-request.js'
+import servicesForTitle from './services-for-title.js'
 
 async function getTitle(owner, repo, pullRequest) {
   const {
diff --git a/core/service-test-runner/runner.js b/core/service-test-runner/runner.js
index 44e4718267414c5dfd576aff6c83af421f7326ae..4b6cf47f898638975f8f77103ca1f0ae82250ee3 100644
--- a/core/service-test-runner/runner.js
+++ b/core/service-test-runner/runner.js
@@ -1,9 +1,8 @@
-'use strict'
 /**
  * @module
  */
 
-const { loadTesters } = require('../base-service/loader')
+import { loadTesters } from '../base-service/loader.js'
 
 /**
  * Load a collection of ServiceTester objects and register them with Mocha.
@@ -24,8 +23,10 @@ class Runner {
   /**
    * Prepare the runner by loading up all the ServiceTester objects.
    */
-  prepare() {
-    this.testers = loadTesters()
+  async prepare() {
+    this.testers = (await loadTesters()).flatMap(testerModule =>
+      Object.values(testerModule)
+    )
     this.testers.forEach(tester => {
       tester.beforeEach = () => {
         this.beforeEach()
@@ -72,4 +73,4 @@ class Runner {
     testers.forEach(tester => tester.toss({ baseUrl, skipIntercepted, retry }))
   }
 }
-module.exports = Runner
+export default Runner
diff --git a/core/service-test-runner/service-tester.js b/core/service-test-runner/service-tester.js
index 4aa282f8535c4a007606af027816484653fdc9b9..3cc94c5d55f3bd236c2121ed915ae8e4412b9623 100644
--- a/core/service-test-runner/service-tester.js
+++ b/core/service-test-runner/service-tester.js
@@ -1,14 +1,13 @@
-'use strict'
 /**
  * @module
  */
 
-const emojic = require('emojic')
-const trace = require('../base-service/trace')
-const frisby = require('./icedfrisby-shields')(
-  // eslint-disable-next-line import/order
-  require('icedfrisby-nock')(require('icedfrisby'))
-)
+import emojic from 'emojic'
+import icedfrisbyNockModule from 'icedfrisby-nock'
+import icedfrisbyModule from 'icedfrisby'
+import trace from '../base-service/trace.js'
+import icedfrisbyShieldsModule from './icedfrisby-shields.js'
+const frisby = icedfrisbyShieldsModule(icedfrisbyNockModule(icedfrisbyModule))
 
 /**
  * Encapsulate a suite of tests. Create new tests using create() and register
@@ -140,4 +139,4 @@ class ServiceTester {
   }
 }
 
-module.exports = ServiceTester
+export default ServiceTester
diff --git a/core/service-test-runner/services-for-title.js b/core/service-test-runner/services-for-title.js
index f5c6fcb46c23b5bc4b7105141730782bafccfa66..862198fcea013f63bd24b8d51b9951a7e36426fa 100644
--- a/core/service-test-runner/services-for-title.js
+++ b/core/service-test-runner/services-for-title.js
@@ -1,9 +1,8 @@
-'use strict'
 /**
  * @module
  */
 
-const difference = require('lodash.difference')
+import difference from 'lodash.difference'
 
 /**
  * Given a pull request title like
@@ -31,4 +30,4 @@ function servicesForTitle(title) {
   return difference(services, ignored)
 }
 
-module.exports = servicesForTitle
+export default servicesForTitle
diff --git a/core/service-test-runner/services-for-title.spec.js b/core/service-test-runner/services-for-title.spec.js
index 40d216d8968a4f67b3ae669afa6b7a9a11b9653d..f89f23d8f5af289cb9529fb6e6e5fa64fc8ff4cd 100644
--- a/core/service-test-runner/services-for-title.spec.js
+++ b/core/service-test-runner/services-for-title.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const servicesForTitle = require('./services-for-title')
+import { test, given } from 'sazerac'
+import servicesForTitle from './services-for-title.js'
 
 describe('Services from PR title', function () {
   test(servicesForTitle, () => {
diff --git a/core/token-pooling/redis-token-persistence.integration.js b/core/token-pooling/redis-token-persistence.integration.js
index a852e28515a14ebab63de7ccdcac8d4c7f553dc5..ca1d65cd9b4a4730d4aa12553c725e847cf223a5 100644
--- a/core/token-pooling/redis-token-persistence.integration.js
+++ b/core/token-pooling/redis-token-persistence.integration.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const RedisServer = require('redis-server')
-const Redis = require('ioredis')
-const { expect } = require('chai')
-const RedisTokenPersistence = require('./redis-token-persistence')
+import RedisServer from 'redis-server'
+import Redis from 'ioredis'
+import { expect } from 'chai'
+import RedisTokenPersistence from './redis-token-persistence.js'
 
 describe('Redis token persistence', function () {
   let server
diff --git a/core/token-pooling/redis-token-persistence.js b/core/token-pooling/redis-token-persistence.js
index 05a5ee3fbc724ea5688c291f95d00ef030d2dcbb..dd0b6fb3067020aa12359845e58c9bbd55bdd706 100644
--- a/core/token-pooling/redis-token-persistence.js
+++ b/core/token-pooling/redis-token-persistence.js
@@ -1,10 +1,8 @@
-'use strict'
+import { URL } from 'url'
+import Redis from 'ioredis'
+import log from '../server/log.js'
 
-const { URL } = require('url')
-const Redis = require('ioredis')
-const log = require('../server/log')
-
-module.exports = class RedisTokenPersistence {
+export default class RedisTokenPersistence {
   constructor({ url, key }) {
     this.url = url
     this.key = key
diff --git a/core/token-pooling/token-pool.js b/core/token-pooling/token-pool.js
index 54e4cfb8a951bf1870adb33c438056cc11ed850e..7dcf64ad5abdf93263fdcaa3690be54e203a1d04 100644
--- a/core/token-pooling/token-pool.js
+++ b/core/token-pooling/token-pool.js
@@ -1,10 +1,9 @@
-'use strict'
 /**
  * @module
  */
 
-const crypto = require('crypto')
-const PriorityQueue = require('priorityqueuejs')
+import crypto from 'crypto'
+import PriorityQueue from 'priorityqueuejs'
 
 /**
  * Compute a one-way hash of the input string.
@@ -354,8 +353,4 @@ class TokenPool {
   }
 }
 
-module.exports = {
-  sanitizeToken,
-  Token,
-  TokenPool,
-}
+export { sanitizeToken, Token, TokenPool }
diff --git a/core/token-pooling/token-pool.spec.js b/core/token-pooling/token-pool.spec.js
index 8780b17e6f74e039a1b1119aaaa56bbdb9d98489..fdfa937d200a1f3412559c09a30f457458042221 100644
--- a/core/token-pooling/token-pool.spec.js
+++ b/core/token-pooling/token-pool.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const sinon = require('sinon')
-const times = require('lodash.times')
-const { Token, TokenPool } = require('./token-pool')
+import { expect } from 'chai'
+import sinon from 'sinon'
+import times from 'lodash.times'
+import { Token, TokenPool } from './token-pool.js'
 
 function expectPoolToBeExhausted(pool) {
   expect(() => {
diff --git a/core/unhandled-rejection.spec.js b/core/unhandled-rejection.spec.js
index b155793b9b04f0caa45853cbc948e72efea41441..17c42ac09beb1f53d31e3e12e93eaecbbab7a1a6 100644
--- a/core/unhandled-rejection.spec.js
+++ b/core/unhandled-rejection.spec.js
@@ -1,5 +1,3 @@
-'use strict'
-
 // Cause unhandled promise rejections to fail unit tests, and print with stack
 // traces.
 process.on('unhandledRejection', error => {
diff --git a/cypress/integration/main-page.spec.js b/cypress/integration/main-page.spec.js
index 412c50e37584e01d83d9ab7c88886f86cd11fd6e..009371ecffb80641197e524c97f3f64cf08774b3 100644
--- a/cypress/integration/main-page.spec.js
+++ b/cypress/integration/main-page.spec.js
@@ -1,5 +1,3 @@
-'use strict'
-
 describe('Main page', function () {
   const backendUrl = Cypress.env('backend_url')
   const SEARCH_INPUT = 'input[placeholder="search / project URL"]'
diff --git a/dangerfile.js b/dangerfile.js
index 94b4185945dd4e3efa47c0ccba89c6e2ebbbb428..f59f587886e72a66ef75aee1c0707c6b38442337 100644
--- a/dangerfile.js
+++ b/dangerfile.js
@@ -131,7 +131,7 @@ if (allFiles.length > 100) {
         )
       }
 
-      if (diff.includes("require('@hapi/joi')")) {
+      if (diff.includes("from '@hapi/joi'")) {
         fail(
           [
             `Found import of '@hapi/joi' in \`${file}\`. <br>`,
diff --git a/doc/TUTORIAL.md b/doc/TUTORIAL.md
index 9d8bb05371f75d20fd75215735658de55767741b..b107a385b24e580d9f85b655ed4472b177c09c50 100644
--- a/doc/TUTORIAL.md
+++ b/doc/TUTORIAL.md
@@ -109,19 +109,17 @@ As a first step we will look at the code for an example which generates a badge
 
 ```js
 // (1)
-'use strict'
-// (2)
-const { BaseService } = require('..')
+import { BaseService } from '../index.js'
 
-// (3)
-module.exports = class Example extends BaseService {
-  // (4)
+// (2)
+export default class Example extends BaseService {
+  // (3)
   static category = 'build'
 
-  // (5)
+  // (4)
   static route = { base: 'example', pattern: ':text' }
 
-  // (6)
+  // (5)
   async handle({ text }) {
     return {
       label: 'example',
@@ -134,18 +132,17 @@ module.exports = class Example extends BaseService {
 
 Description of the code:
 
-1. We declare strict mode at the start of each file. This prevents certain classes of error such as undeclared variables.
-2. Our service badge class will extend `BaseService` so we need to require it. Variables are declared with `const` and `let` in preference to `var`.
-3. Our module must export a class which extends `BaseService`.
-4. Returns the name of the category to sort this badge into (eg. "build"). Used to sort the examples on the main [shields.io](https://shields.io) website. [Here](https://github.com/badges/shields/blob/master/services/categories.js) is the list of the valid categories. See [section 4.4](#44-adding-an-example-to-the-front-page) for more details on examples.
-5. `route()` declares the URL path at which the service operates. It also maps components of the URL path to handler parameters.
+1. Our service badge class will extend `BaseService` so we need to require it. Variables are declared with `const` and `let` in preference to `var`.
+2. Our module must export a class which extends `BaseService`.
+3. Returns the name of the category to sort this badge into (eg. "build"). Used to sort the examples on the main [shields.io](https://shields.io) website. [Here](https://github.com/badges/shields/blob/master/services/categories.js) is the list of the valid categories. See [section 4.4](#44-adding-an-example-to-the-front-page) for more details on examples.
+4. `route()` declares the URL path at which the service operates. It also maps components of the URL path to handler parameters.
    - `base` defines the first part of the URL that doesn't change, e.g. `/example/`.
    - `pattern` defines the variable part of the route, everything that comes after `/example/`. It can include any
      number of named parameters. These are converted into
      regular expressions by [`path-to-regexp`][path-to-regexp].
      Because a service instance won't be created until it's time to handle a request, the route and other metadata must be obtained by examining the classes themselves. [That's why they're marked `static`.][static]
    - There is additional documentation on conventions for [designing badge URLs](./badge-urls.md)
-6. All badges must implement the `async handle()` function that receives parameters to render the badge. Parameters of `handle()` will match the name defined in `route()` Because we're capturing a single variable called `text` our function signature is `async handle({ text })`. `async` is needed to let JavaScript do other things while we are waiting for result from external API. Although in this simple case, we don't make any external calls. Our `handle()` function should return an object with 3 properties:
+5. All badges must implement the `async handle()` function that receives parameters to render the badge. Parameters of `handle()` will match the name defined in `route()` Because we're capturing a single variable called `text` our function signature is `async handle({ text })`. `async` is needed to let JavaScript do other things while we are waiting for result from external API. Although in this simple case, we don't make any external calls. Our `handle()` function should return an object with 3 properties:
    - `label`: the text on the left side of the badge
    - `message`: the text on the right side of the badge - here we are passing through the parameter we captured in the route regex
    - `color`: the background color of the right side of the badge
@@ -171,36 +168,33 @@ This example is based on the [Ruby Gems version](https://github.com/badges/shiel
 
 ```js
 // (1)
-'use strict'
-
+import { renderVersionBadge } from '../version.js'
 // (2)
-const { renderVersionBadge } = require('..//version')
-// (3)
-const { BaseJsonService } = require('..')
+import { BaseJsonService } from '../index.js'
 
-// (4)
-const Joi = require('joi')
+// (3)
+import Joi from 'joi'
 const schema = Joi.object({
   version: Joi.string().required(),
 }).required()
 
-// (5)
-module.exports = class GemVersion extends BaseJsonService {
-  // (6)
+// (4)
+export default class GemVersion extends BaseJsonService {
+  // (5)
   static category = 'version'
 
-  // (7)
+  // (6)
   static route = { base: 'gem/v', pattern: ':gem' }
 
-  // (8)
+  // (7)
   static defaultBadgeData = { label: 'gem' }
 
-  // (11)
+  // (10)
   static render({ version }) {
     return renderVersionBadge({ version })
   }
 
-  // (10)
+  // (9)
   async fetch({ gem }) {
     return this._requestJson({
       schema,
@@ -208,7 +202,7 @@ module.exports = class GemVersion extends BaseJsonService {
     })
   }
 
-  // (9)
+  // (8)
   async handle({ gem }) {
     const { version } = await this.fetch({ gem })
     return this.constructor.render({ version })
@@ -218,39 +212,38 @@ module.exports = class GemVersion extends BaseJsonService {
 
 Description of the code:
 
-1. As with the first example, we declare strict mode at the start of each file.
-2. In this case we are making a version badge, which is a common pattern. Instead of directly returning an object in this badge we will use a helper function to format our data consistently. There are a variety of helper functions to help with common tasks in `/services`. Some useful generic helpers can be found in:
+1. In this case we are making a version badge, which is a common pattern. Instead of directly returning an object in this badge we will use a helper function to format our data consistently. There are a variety of helper functions to help with common tasks in `/services`. Some useful generic helpers can be found in:
    - [build-status.js](https://github.com/badges/shields/blob/master/services/build-status.js)
    - [color-formatters.js](https://github.com/badges/shields/blob/master/services/color-formatters.js)
    - [licenses.js](https://github.com/badges/shields/blob/master/services/licenses.js)
    - [text-formatters.js](https://github.com/badges/shields/blob/master/services/text-formatters.js)
    - [version.js](https://github.com/badges/shields/blob/master/services/version.js)
-3. Our badge will query a JSON API so we will extend `BaseJsonService` instead of `BaseService`. This contains some helpers to reduce the need for boilerplate when calling a JSON API.
-4. We perform input validation by defining a schema which we expect the JSON we receive to conform to. This is done using [Joi](https://github.com/hapijs/joi). Defining a schema means we can ensure the JSON we receive meets our expectations and throw an error if we receive unexpected input without having to explicitly code validation checks. The schema also acts as a filter on the JSON object. Any properties we're going to reference need to be validated, otherwise they will be filtered out. In this case our schema declares that we expect to receive an object which must have a property called 'version', which is a string. There is further documentation on [input validation](input-validation.md).
-5. Our module exports a class which extends `BaseJsonService`
-6. Returns the name of the category to sort this badge into (eg. "build"). Used to sort the examples on the main [shields.io](https://shields.io) website. [Here](https://github.com/badges/shields/blob/master/services/categories.js) is the list of the valid categories. See [section 4.4](#44-adding-an-example-to-the-front-page) for more details on examples.
-7. As with our previous badge, we need to declare a route. This time we will capture a variable called `gem`.
-8. We can use `defaultBadgeData()` to set a default `color`, `logo` and/or `label`. If `handle()` doesn't return any of these keys, we'll use the default. Instead of explicitly setting the label text when we return a badge object, we'll use `defaultBadgeData()` here to define it declaratively.
-9. We now jump to the bottom of the example code to the function all badges must implement: `async handle()`. This is the function the server will invoke to handle an incoming request. Because our URL pattern captures a variable called `gem`, our function signature is `async handle({ gem })`. We usually separate the process of generating a badge into 2 stages or concerns: fetch and render. The `fetch()` function is responsible for calling an API endpoint to get data. The `render()` function formats the data for display. In a case where there is a lot of calculation or intermediate steps, this pattern may be thought of as fetch, transform, render and it might be necessary to define some helper functions to assist with the 'transform' step.
-10. Working our way upward, the `async fetch()` method is responsible for calling an API endpoint to get data. Extending `BaseJsonService` gives us the helper function `_requestJson()`. Note here that we pass the schema we defined in step 4 as an argument. `_requestJson()` will deal with validating the response against the schema and throwing an error if necessary.
-
-    - `_requestJson()` automatically adds an Accept header, checks the status code, parses the response as JSON, and returns the parsed response.
-    - `_requestJson()` uses [request](https://github.com/request/request) to perform the HTTP request. Options can be passed to request, including method, query string, and headers. If headers are provided they will override the ones automatically set by `_requestJson()`. There is no need to specify json, as the JSON parsing is handled by `_requestJson()`. See the `request` docs for [supported options](https://github.com/request/request#requestoptions-callback).
-    - Error messages corresponding to each status code can be returned by passing a dictionary of status codes -> messages in `errorMessages`.
-    - A more complex call to `_requestJson()` might look like this:
-      ```js
-      return this._requestJson({
-        schema: mySchema,
-        url,
-        options: { qs: { branch: 'master' } },
-        errorMessages: {
-          401: 'private application not supported',
-          404: 'application not found',
-        },
-      })
-      ```
-
-11. Upward still, the `static render()` method is responsible for formatting the data for display. `render()` is a pure function so we can make it a `static` method. By convention we declare functions which don't reference `this` as `static`. We could explicitly return an object here, as we did in the previous example. In this case, we will hand the version string off to `renderVersionBadge()` which will format it consistently and set an appropriate color. Because `renderVersionBadge()` doesn't return a `label` key, the default label we defined in `defaultBadgeData()` will be used when we generate the badge.
+2. Our badge will query a JSON API so we will extend `BaseJsonService` instead of `BaseService`. This contains some helpers to reduce the need for boilerplate when calling a JSON API.
+3. We perform input validation by defining a schema which we expect the JSON we receive to conform to. This is done using [Joi](https://github.com/hapijs/joi). Defining a schema means we can ensure the JSON we receive meets our expectations and throw an error if we receive unexpected input without having to explicitly code validation checks. The schema also acts as a filter on the JSON object. Any properties we're going to reference need to be validated, otherwise they will be filtered out. In this case our schema declares that we expect to receive an object which must have a property called 'version', which is a string. There is further documentation on [input validation](input-validation.md).
+4. Our module exports a class which extends `BaseJsonService`
+5. Returns the name of the category to sort this badge into (eg. "build"). Used to sort the examples on the main [shields.io](https://shields.io) website. [Here](https://github.com/badges/shields/blob/master/services/categories.js) is the list of the valid categories. See [section 4.4](#44-adding-an-example-to-the-front-page) for more details on examples.
+6. As with our previous badge, we need to declare a route. This time we will capture a variable called `gem`.
+7. We can use `defaultBadgeData()` to set a default `color`, `logo` and/or `label`. If `handle()` doesn't return any of these keys, we'll use the default. Instead of explicitly setting the label text when we return a badge object, we'll use `defaultBadgeData()` here to define it declaratively.
+8. We now jump to the bottom of the example code to the function all badges must implement: `async handle()`. This is the function the server will invoke to handle an incoming request. Because our URL pattern captures a variable called `gem`, our function signature is `async handle({ gem })`. We usually separate the process of generating a badge into 2 stages or concerns: fetch and render. The `fetch()` function is responsible for calling an API endpoint to get data. The `render()` function formats the data for display. In a case where there is a lot of calculation or intermediate steps, this pattern may be thought of as fetch, transform, render and it might be necessary to define some helper functions to assist with the 'transform' step.
+9. Working our way upward, the `async fetch()` method is responsible for calling an API endpoint to get data. Extending `BaseJsonService` gives us the helper function `_requestJson()`. Note here that we pass the schema we defined in step 4 as an argument. `_requestJson()` will deal with validating the response against the schema and throwing an error if necessary.
+
+   - `_requestJson()` automatically adds an Accept header, checks the status code, parses the response as JSON, and returns the parsed response.
+   - `_requestJson()` uses [request](https://github.com/request/request) to perform the HTTP request. Options can be passed to request, including method, query string, and headers. If headers are provided they will override the ones automatically set by `_requestJson()`. There is no need to specify json, as the JSON parsing is handled by `_requestJson()`. See the `request` docs for [supported options](https://github.com/request/request#requestoptions-callback).
+   - Error messages corresponding to each status code can be returned by passing a dictionary of status codes -> messages in `errorMessages`.
+   - A more complex call to `_requestJson()` might look like this:
+     ```js
+     return this._requestJson({
+       schema: mySchema,
+       url,
+       options: { qs: { branch: 'master' } },
+       errorMessages: {
+         401: 'private application not supported',
+         404: 'application not found',
+       },
+     })
+     ```
+
+10. Upward still, the `static render()` method is responsible for formatting the data for display. `render()` is a pure function so we can make it a `static` method. By convention we declare functions which don't reference `this` as `static`. We could explicitly return an object here, as we did in the previous example. In this case, we will hand the version string off to `renderVersionBadge()` which will format it consistently and set an appropriate color. Because `renderVersionBadge()` doesn't return a `label` key, the default label we defined in `defaultBadgeData()` will be used when we generate the badge.
 
 This code allows us to call this URL <https://img.shields.io/gem/v/formatador> to generate this badge: ![](https://img.shields.io/gem/v/formatador)
 
@@ -269,7 +262,7 @@ non-standard error condition. If so, there are several standard exceptions that
 and can be imported via the import shortcut and then thrown:
 
 ```js
-const { NotFound } = require('..')
+import { NotFound } from '../index.js'
 
 throw new NotFound({ prettyMessage: 'package not found' })
 ```
@@ -279,7 +272,7 @@ throw new NotFound({ prettyMessage: 'package not found' })
 Once we have implemented our badge, we can add it to the index so that users can discover it. We will do this by adding an additional method `examples()` to our class.
 
 ```js
-module.exports = class GemVersion extends BaseJsonService {
+export default class GemVersion extends BaseJsonService {
   // ...
 
   // (1)
diff --git a/doc/deprecating-badges.md b/doc/deprecating-badges.md
index 353b56de6b5a69919f906240997f74c61a5349cc..8f8b72749099bee35572c732ef560c61b3edd60c 100644
--- a/doc/deprecating-badges.md
+++ b/doc/deprecating-badges.md
@@ -14,11 +14,9 @@ Locate the source file(s) for the service, which can be found in `*.service.js`
 Replace the existing service class implementation with the `DeprecatedService` class from `./core/base-service/deprecated-service.js` using the respective `category`, `route`, and `label` values for that service. For example:
 
 ```js
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'size',
   route: {
     base: 'imagelayers',
@@ -36,12 +34,12 @@ Locate the test file(s) for the service, which can be found in `*.tester.js` fil
 With `DeprecatedService` classes we cannot use `createServiceTester()` so you will need to create the `ServiceTester` class directly. For example:
 
 ```js
-const { ServiceTester } = require('../tester')
+import { ServiceTester } from '../tester.js'
 
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'imagelayers',
   title: 'ImageLayers',
-}))
+})
 ```
 
 Next you will need to replace/refactor the existing tests to validate the new deprecated badge behavior for this service. Deprecated badges always return a message of `no longer available` (such as `imagelayers | no longer available`) so the tests need to be updated to reflect that message value. For example:
@@ -60,14 +58,12 @@ Make sure to have a live (non-mocked) test for each badge the service provides t
 Here is an example of what the final result would look like for a test file:
 
 ```js
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'imagelayers',
   title: 'ImageLayers',
-}))
+})
 
 t.create('no longer available (previously image size)')
   .get('/image-size/_/ubuntu/latest.json')
diff --git a/doc/service-tests.md b/doc/service-tests.md
index a7816e7c18c36281327e4a3a1ee0cba96bd7565c..0a332806bc9e6a4af4353a884e1f38e8e2bb05fb 100644
--- a/doc/service-tests.md
+++ b/doc/service-tests.md
@@ -33,13 +33,13 @@ The code for our badge is in `services/wercker/wercker.service.js`. Tests for th
 We'll start by adding some boilerplate to our file:
 
 ```js
-'use strict'
+import { createServiceTester } from '../tester.js'
 
-const t = (module.exports = require('../tester').createServiceTester())
+export const t = await createServiceTester()
 ```
 
 If our `.service.js` module exports a single class, we can
-`require('../tester').createServiceTester()`, which uses convention to create a
+`createServiceTester`, which uses convention to create a
 `ServiceTester` object. Calling this inside
 `services/wercker/wercker.tester.js` will create a `ServiceTester` object
 configured for the service exported in `services/wercker/wercker.service.js`.
@@ -51,7 +51,7 @@ from the module.
 First we'll add a test for the typical case:
 
 ```js
-const { isBuildStatus } = require('../test-validators')
+import { isBuildStatus } from '../test-validators.js'
 
 t.create('Build status')
   .get('/build/wercker/go-wercker-api.json')
diff --git a/entrypoint.spec.js b/entrypoint.spec.js
index c52368d162184fdee3e8fca0ee710903406e12d3..4325c0365ab81a95144fb56d002009ea99fc49ad 100644
--- a/entrypoint.spec.js
+++ b/entrypoint.spec.js
@@ -1,23 +1,22 @@
-'use strict'
+import { expect } from 'chai'
+import isSvg from 'is-svg'
+import got from './core/got-test-client.js'
 
-const { expect } = require('chai')
-const isSvg = require('is-svg')
-const got = require('./core/got-test-client')
-
-let server
-before(function () {
-  this.timeout('5s')
+let serverModule
+before(async function () {
+  this.timeout('30s')
   // remove args coming from mocha
   // https://github.com/badges/shields/issues/3365
   process.argv = []
-  server = require('./server')
+  serverModule = await import('./server.js')
 })
 
 after('shut down the server', async function () {
-  await server.stop()
+  await serverModule.server.stop()
 })
 
 it('should render a badge', async function () {
+  this.timeout('30s')
   const { statusCode, body } = await got(
     'http://localhost:1111/badge/fruit-apple-green.svg'
   )
diff --git a/gatsby-browser.js b/frontend/gatsby-browser.js
similarity index 84%
rename from gatsby-browser.js
rename to frontend/gatsby-browser.js
index 2a973fd4f1d19da1b0682d6cc96dc40f4cc7ff74..0e83d9aa210ed8b088fbbcf1525835f2f87991a2 100644
--- a/gatsby-browser.js
+++ b/frontend/gatsby-browser.js
@@ -1,4 +1,4 @@
-import redirectLegacyRoutes from './frontend/lib/redirect-legacy-routes'
+import redirectLegacyRoutes from './lib/redirect-legacy-routes'
 
 // Adapted from https://github.com/gatsbyjs/gatsby/issues/8413
 function scrollToElementId(id) {
diff --git a/gatsby-config.js b/frontend/gatsby-config.js
similarity index 94%
rename from gatsby-config.js
rename to frontend/gatsby-config.js
index ebf6b46e081387172b6df7c45dece84b1818d455..e363cb3cbd01f0e96e48588adb999185443fe855 100644
--- a/gatsby-config.js
+++ b/frontend/gatsby-config.js
@@ -13,7 +13,7 @@ module.exports = {
     {
       resolve: 'gatsby-plugin-page-creator',
       options: {
-        path: path.join(__dirname, 'frontend', 'pages'),
+        path: path.join(__dirname, 'pages'),
       },
     },
     'gatsby-plugin-react-helmet',
diff --git a/gatsby-node.js b/frontend/gatsby-node.js
similarity index 80%
rename from gatsby-node.js
rename to frontend/gatsby-node.js
index 0b6e5fa44d83f04ffb78c0ede589cb259df0bb2a..1d90adebb709e8f9a37ad30ea891f2ccd4b07c9f 100644
--- a/gatsby-node.js
+++ b/frontend/gatsby-node.js
@@ -23,15 +23,11 @@ async function createPages({ actions: { createPage } }) {
   if (includeDevPages) {
     createPage({
       path: '/dev/styles',
-      component: require.resolve(
-        './frontend/components/development/style-page.tsx'
-      ),
+      component: require.resolve('./components/development/style-page.tsx'),
     })
     createPage({
       path: '/dev/logos',
-      component: require.resolve(
-        './frontend/components/development/logo-page.tsx'
-      ),
+      component: require.resolve('./components/development/logo-page.tsx'),
     })
   }
 
@@ -39,7 +35,7 @@ async function createPages({ actions: { createPage } }) {
     const { id } = category
     createPage({
       path: `/category/${id}`,
-      component: require.resolve('./frontend/components/main.tsx'),
+      component: require.resolve('./components/main.tsx'),
       // `context` provided here becomes `props.pageContext` on the page.
       context: { category },
     })
diff --git a/frontend/lib/service-definitions/index.ts b/frontend/lib/service-definitions/index.ts
index e358139614a91e6ca61d497cf8bfc7c0a1e9ecc8..31fe5ed8b4250a0870165c763e24244c4c336979 100644
--- a/frontend/lib/service-definitions/index.ts
+++ b/frontend/lib/service-definitions/index.ts
@@ -1,6 +1,6 @@
 import groupBy from 'lodash.groupby'
 // load using js-yaml-loader
-import definitions from '../../../service-definitions.yml'
+import definitions from '../../service-definitions.yml'
 
 export interface Category {
   id: string
diff --git a/frontend/lib/supported-features.ts b/frontend/lib/supported-features.ts
index 65ef3d3dc93f88af180ad625618b3c2547563e3c..275b5cd88662a6be5fa8eb129ea669a0c77b90a9 100644
--- a/frontend/lib/supported-features.ts
+++ b/frontend/lib/supported-features.ts
@@ -1,4 +1,4 @@
-import supportedFeatures from '../../supported-features.json'
+import supportedFeatures from '../supported-features.json'
 
 export const shieldsLogos = supportedFeatures.shieldsLogos as string[]
 export const simpleIcons = supportedFeatures.simpleIcons as string[]
diff --git a/frontend/mocha-ignore-pngs.js b/frontend/mocha-ignore-pngs.js
deleted file mode 100644
index cefd367d9fb629b0bf3e52c424b7515ac3cd143e..0000000000000000000000000000000000000000
--- a/frontend/mocha-ignore-pngs.js
+++ /dev/null
@@ -1,5 +0,0 @@
-import requireHacker from 'require-hacker'
-
-// https://diessi.ca/blog/how-to-exclude-css-images-anything-from-unit-tests/
-
-requireHacker.hook('png', () => 'module.exports = ""')
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 0000000000000000000000000000000000000000..deaac236c6b0231638547542753ab90d14d8ee76
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,32 @@
+{
+  "name": "badge-frontend",
+  "version": "0.0.0",
+  "description": "Shields.io frontend",
+  "private": true,
+  "homepage": "http://shields.io",
+  "license": "CC0-1.0",
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/badges/shields.git",
+    "directory": "frontend"
+  },
+  "scripts": {
+    "test": "echo 'Run tests from parent dir'; false"
+  },
+  "devDependencies": {
+    "gatsby": "*"
+  },
+  "babel": {
+    "plugins": [
+      [
+        "inline-react-svg",
+        {
+          "svgo": false
+        }
+      ]
+    ],
+    "presets": [
+      "babel-preset-gatsby"
+    ]
+  }
+}
diff --git a/lib/load-logos.js b/lib/load-logos.js
index 7a9efbfdbfa54647d5462d43829e878656d9427b..f48f32d0d939865d044679c238d864e0092d627f 100644
--- a/lib/load-logos.js
+++ b/lib/load-logos.js
@@ -1,13 +1,16 @@
-'use strict'
-
-const fs = require('fs')
-const path = require('path')
-const { svg2base64 } = require('./svg-helpers')
+import fs from 'fs'
+import path from 'path'
+import { fileURLToPath } from 'url'
+import { svg2base64 } from './svg-helpers.js'
 
 function loadLogos() {
   // Cache svg logos from disk in base64 string
   const logos = {}
-  const logoDir = path.join(__dirname, '..', 'logo')
+  const logoDir = path.join(
+    path.dirname(fileURLToPath(import.meta.url)),
+    '..',
+    'logo'
+  )
   const logoFiles = fs.readdirSync(logoDir)
   logoFiles.forEach(filename => {
     if (filename[0] === '.') {
@@ -30,4 +33,4 @@ function loadLogos() {
   return logos
 }
 
-module.exports = loadLogos
+export default loadLogos
diff --git a/lib/load-simple-icons.js b/lib/load-simple-icons.js
index 86f9b8e3563a75ebcbadbbcb97df5bf5e8206331..a17b7ce8a2426c3530e08c6014e3f5cac4d38ea6 100644
--- a/lib/load-simple-icons.js
+++ b/lib/load-simple-icons.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const originalSimpleIcons = require('simple-icons')
-const { svg2base64 } = require('./svg-helpers')
+import originalSimpleIcons from 'simple-icons'
+import { svg2base64 } from './svg-helpers.js'
 
 function loadSimpleIcons() {
   const simpleIcons = {}
@@ -40,4 +38,4 @@ function loadSimpleIcons() {
   return simpleIcons
 }
 
-module.exports = loadSimpleIcons
+export default loadSimpleIcons
diff --git a/lib/load-simple-icons.spec.js b/lib/load-simple-icons.spec.js
index d32f95bb93c2cf00bfb62340f70c915c479ea02d..da64c20d34a807896f8c363b543de6164e5f2946 100644
--- a/lib/load-simple-icons.spec.js
+++ b/lib/load-simple-icons.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { expect } = require('chai')
-const loadSimpleIcons = require('./load-simple-icons')
+import { expect } from 'chai'
+import loadSimpleIcons from './load-simple-icons.js'
 
 describe('loadSimpleIcons', function () {
   let simpleIcons
diff --git a/lib/logos.js b/lib/logos.js
index 26000732e50ef86fff00044b7fe111d24720528b..a64f716c3b449f62f307fde3724c3d6c0d6fd05a 100644
--- a/lib/logos.js
+++ b/lib/logos.js
@@ -1,15 +1,15 @@
-'use strict'
-
-const Joi = require('joi')
-const {
+import Joi from 'joi'
+import {
   toSvgColor,
   brightness,
   normalizeColor,
-} = require('../badge-maker/lib/color')
-const coalesce = require('../core/base-service/coalesce')
-const { svg2base64 } = require('./svg-helpers')
-const logos = require('./load-logos')()
-const simpleIcons = require('./load-simple-icons')()
+} from '../badge-maker/lib/color.js'
+import coalesce from '../core/base-service/coalesce.js'
+import { svg2base64 } from './svg-helpers.js'
+import loadLogos from './load-logos.js'
+import loadSimpleIcons from './load-simple-icons.js'
+const logos = loadLogos()
+const simpleIcons = loadSimpleIcons()
 
 // for backwards-compatibility with deleted logos
 const logoAliases = {
@@ -131,7 +131,7 @@ function makeLogo(defaultNamedLogo, overrides) {
   }
 }
 
-module.exports = {
+export {
   prependPrefix,
   isDataUrl,
   decodeDataUrlFromQueryParam,
diff --git a/lib/logos.spec.js b/lib/logos.spec.js
index 38964fa37b99183b9a58bff084b06cd6e3bb7b1a..0d6eaae40067c90509af466c4f1d760f1865c0e2 100644
--- a/lib/logos.spec.js
+++ b/lib/logos.spec.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const { expect } = require('chai')
-const { test, given, forCases } = require('sazerac')
-const {
+import { expect } from 'chai'
+import { test, given, forCases } from 'sazerac'
+import {
   prependPrefix,
   isDataUrl,
   prepareNamedLogo,
   getSimpleIcon,
   makeLogo,
-} = require('./logos')
+} from './logos.js'
 
 describe('Logo helpers', function () {
   test(prependPrefix, () => {
diff --git a/lib/svg-helpers.js b/lib/svg-helpers.js
index 7011c156aed7245f54217acd7a73c9d976ccac08..040df8a503f8e48ee14c3bddbb55bf4a81db0316 100644
--- a/lib/svg-helpers.js
+++ b/lib/svg-helpers.js
@@ -1,7 +1,5 @@
-'use strict'
-
 function svg2base64(svg) {
   return `data:image/svg+xml;base64,${Buffer.from(svg).toString('base64')}`
 }
 
-module.exports = { svg2base64 }
+export { svg2base64 }
diff --git a/lib/svg-helpers.spec.js b/lib/svg-helpers.spec.js
index c36fe39ffe7b47326dc0b2b646190f5c3f5c519f..6434f661f89dd00e4d0674964c0e4e2cc4ca2784 100644
--- a/lib/svg-helpers.spec.js
+++ b/lib/svg-helpers.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { svg2base64 } = require('./svg-helpers')
+import { test, given } from 'sazerac'
+import { svg2base64 } from './svg-helpers.js'
 
 describe('SVG helpers', function () {
   test(svg2base64, () => {
diff --git a/package-lock.json b/package-lock.json
index 3f90cbf780233b660d16160ade91e6642c924484..5866174a9326f9902e69771b66c9d70a0b9b65a6 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -140,7 +140,6 @@
         "react-select": "^4.3.1",
         "read-all-stdin-sync": "^1.0.5",
         "redis-server": "^1.2.2",
-        "require-hacker": "^3.0.1",
         "rimraf": "^3.0.2",
         "sazerac": "^2.0.0",
         "sinon": "^11.1.1",
@@ -5955,30 +5954,6 @@
         "core-js": "^3.0.0"
       }
     },
-    "node_modules/babel-runtime": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
-      "dev": true,
-      "dependencies": {
-        "core-js": "^2.4.0",
-        "regenerator-runtime": "^0.11.0"
-      }
-    },
-    "node_modules/babel-runtime/node_modules/core-js": {
-      "version": "2.6.12",
-      "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
-      "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
-      "deprecated": "core-js@<3 is no longer maintained and not recommended for usage due to the number of issues. Please, upgrade your dependencies to the actual version of core-js@3.",
-      "dev": true,
-      "hasInstallScript": true
-    },
-    "node_modules/babel-runtime/node_modules/regenerator-runtime": {
-      "version": "0.11.1",
-      "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
-      "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
-      "dev": true
-    },
     "node_modules/backo2": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
@@ -25432,16 +25407,6 @@
         "node": ">=0.10.0"
       }
     },
-    "node_modules/require-hacker": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/require-hacker/-/require-hacker-3.0.1.tgz",
-      "integrity": "sha1-CHm+Bn/PBnUwZlvM5MiayBqHBHc=",
-      "dev": true,
-      "dependencies": {
-        "babel-runtime": "^6.6.1",
-        "colors": "^1.1.2"
-      }
-    },
     "node_modules/require-main-filename": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
@@ -36340,30 +36305,6 @@
         "gatsby-legacy-polyfills": "^1.8.0"
       }
     },
-    "babel-runtime": {
-      "version": "6.26.0",
-      "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
-      "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=",
-      "dev": true,
-      "requires": {
-        "core-js": "^2.4.0",
-        "regenerator-runtime": "^0.11.0"
-      },
-      "dependencies": {
-        "core-js": {
-          "version": "2.6.12",
-          "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
-          "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
-          "dev": true
-        },
-        "regenerator-runtime": {
-          "version": "0.11.1",
-          "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
-          "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==",
-          "dev": true
-        }
-      }
-    },
     "backo2": {
       "version": "1.0.2",
       "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
@@ -51647,16 +51588,6 @@
       "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
       "dev": true
     },
-    "require-hacker": {
-      "version": "3.0.1",
-      "resolved": "https://registry.npmjs.org/require-hacker/-/require-hacker-3.0.1.tgz",
-      "integrity": "sha1-CHm+Bn/PBnUwZlvM5MiayBqHBHc=",
-      "dev": true,
-      "requires": {
-        "babel-runtime": "^6.6.1",
-        "colors": "^1.1.2"
-      }
-    },
     "require-main-filename": {
       "version": "2.0.0",
       "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
diff --git a/package.json b/package.json
index 04a09f2b8233c5354316d17100f8e700d8473529..234168c42ab93eb92caddd4e54b4f57c583a09bb 100644
--- a/package.json
+++ b/package.json
@@ -99,9 +99,9 @@
     "check-types:frontend": "tsc --noEmit --project .",
     "depcheck": "check-node-version --node \">= 12.0\"",
     "prebuild": "run-s --silent depcheck",
-    "features": "node scripts/export-supported-features-cli.js > supported-features.json",
-    "defs": "node scripts/export-service-definitions-cli.js > service-definitions.yml",
-    "build": "run-s defs features && gatsby build",
+    "features": "node scripts/export-supported-features-cli.js > ./frontend/supported-features.json",
+    "defs": "node scripts/export-service-definitions-cli.js > ./frontend/service-definitions.yml",
+    "build": "run-s defs features && cd frontend && gatsby build && mv public ..",
     "heroku-postbuild": "run-s --silent build",
     "start:server:prod": "node server",
     "now-start": "npm run start:server:prod",
@@ -111,7 +111,7 @@
     "profile:server": "cross-env NODE_CONFIG_ENV=development node --prof server 8080",
     "benchmark:badge": "cross-env NODE_CONFIG_ENV=test node scripts/benchmark-performance.js --iterations 10100 | node scripts/capture-timings.js --warmup-iterations 100",
     "prestart": "run-s --silent depcheck defs features",
-    "start": "concurrently --names server,frontend \"npm run start:server\" \"cross-env GATSBY_BASE_URL=http://localhost:8080 gatsby develop --port 3000\"",
+    "start": "concurrently --names server,frontend \"npm run start:server\" \"cd frontend && cross-env GATSBY_BASE_URL=http://localhost:8080 gatsby develop --port 3000\"",
     "e2e": "start-server-and-test start http://localhost:3000 test:e2e",
     "e2e-on-build": "cross-env CYPRESS_baseUrl=http://localhost:8080 start-server-and-test start:server:e2e-on-build http://localhost:8080 test:e2e",
     "badge": "cross-env NODE_CONFIG_ENV=test TRACE_SERVICES=true node scripts/badge-cli.js",
@@ -135,7 +135,6 @@
       "**/*.tester.js",
       "**/*.integration.js",
       "frontend/",
-      "public/",
       "build/",
       "cypress/"
     ]
@@ -228,7 +227,6 @@
     "react-select": "^4.3.1",
     "read-all-stdin-sync": "^1.0.5",
     "redis-server": "^1.2.2",
-    "require-hacker": "^3.0.1",
     "rimraf": "^3.0.2",
     "sazerac": "^2.0.0",
     "sinon": "^11.1.1",
@@ -244,18 +242,8 @@
     "node": "^14.17.1",
     "npm": ">=7.0.0"
   },
+  "type": "module",
   "babel": {
-    "plugins": [
-      [
-        "inline-react-svg",
-        {
-          "svgo": false
-        }
-      ]
-    ],
-    "presets": [
-      "babel-preset-gatsby"
-    ],
     "env": {
       "test": {
         "plugins": [
diff --git a/scripts/badge-cli.js b/scripts/badge-cli.js
index 9e29ad246cf739afa70cf15ca3d9ab2037987561..bf8e94382819941a44f7ce4735fc4c54be5bf492 100644
--- a/scripts/badge-cli.js
+++ b/scripts/badge-cli.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { URL } = require('url')
-const config = require('config').util.toObject()
-const got = require('got')
-const emojic = require('emojic')
-const Server = require('../core/server/server')
-const trace = require('../core/base-service/trace')
+import { fileURLToPath, URL } from 'url'
+import config from 'config'
+import got from 'got'
+import emojic from 'emojic'
+import Server from '../core/server/server.js'
+import trace from '../core/base-service/trace.js'
 
 function normalizeBadgeUrl(url) {
   // Provide a base URL in order to accept fragments.
@@ -18,7 +16,7 @@ function normalizeBadgeUrl(url) {
 }
 
 async function traceBadge(badgeUrl) {
-  const server = new Server(config)
+  const server = new Server(config.util.toObject())
   await server.start()
   const body = await got(
     `${server.baseUrl.replace(/\/$/, '')}${badgeUrl}`
@@ -29,7 +27,7 @@ async function traceBadge(badgeUrl) {
 
 async function main() {
   if (process.argv.length < 3) {
-    console.error(`Usage: node ${__filename} badge-url`)
+    console.error(`Usage: node ${fileURLToPath(import.meta.url)} badge-url`)
     process.exit(1)
   }
   const [, , url] = process.argv
diff --git a/scripts/benchmark-performance.js b/scripts/benchmark-performance.js
index 7686138f7ceac4b5eff84a4c68d67c3ac65d65b8..addbdedb81dce32eba73dc851560e71edf4020fe 100644
--- a/scripts/benchmark-performance.js
+++ b/scripts/benchmark-performance.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const config = require('config').util.toObject()
-const got = require('got')
-const minimist = require('minimist')
-const Server = require('../core/server/server')
+import config from 'config'
+import got from 'got'
+import minimist from 'minimist'
+import Server from '../core/server/server.js'
 
 async function main() {
-  const server = new Server(config)
+  const server = new Server(config.util.toObject())
   await server.start()
   const args = minimist(process.argv)
   const iterations = parseInt(args.iterations) || 10000
diff --git a/scripts/capture-timings.js b/scripts/capture-timings.js
index fee8bf24a27a0aa75a196f0c3bb976c566f8eead..4b60fa89259b64b6f35e3ed5c6f67a88e0b9ac9d 100644
--- a/scripts/capture-timings.js
+++ b/scripts/capture-timings.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const readline = require('readline')
-const minimist = require('minimist')
+import readline from 'readline'
+import minimist from 'minimist'
 
 async function captureTimings(warmupIterations) {
   const rl = readline.createInterface({
diff --git a/scripts/export-service-definitions-cli.js b/scripts/export-service-definitions-cli.js
index fc411431398e7af738a05b8729ff67061a9430ce..e019bbcd175cbd29956c509e740ab9c51c7838c5 100644
--- a/scripts/export-service-definitions-cli.js
+++ b/scripts/export-service-definitions-cli.js
@@ -1,12 +1,11 @@
-'use strict'
+import yaml from 'js-yaml'
+import { collectDefinitions } from '../core/base-service/loader.js'
+;(async () => {
+  const definitions = await collectDefinitions()
 
-const yaml = require('js-yaml')
-const { collectDefinitions } = require('../core/base-service/loader')
+  // Omit undefined
+  // https://github.com/nodeca/js-yaml/issues/356#issuecomment-312430599
+  const cleaned = JSON.parse(JSON.stringify(definitions))
 
-const definitions = collectDefinitions()
-
-// Omit undefined
-// https://github.com/nodeca/js-yaml/issues/356#issuecomment-312430599
-const cleaned = JSON.parse(JSON.stringify(definitions))
-
-process.stdout.write(yaml.dump(cleaned, { flowLevel: 5 }))
+  process.stdout.write(yaml.dump(cleaned, { flowLevel: 5 }))
+})()
diff --git a/scripts/export-supported-features-cli.js b/scripts/export-supported-features-cli.js
index a3dfb61486d58f84c93c3d9e3b2d180d0bb8577c..bf84d46ea8d564556e3f18fe7f6f5a20e76b27de 100644
--- a/scripts/export-supported-features-cli.js
+++ b/scripts/export-supported-features-cli.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const logos = require('../lib/load-logos')()
-const simpleIcons = require('../lib/load-simple-icons')()
-
-const shieldsLogos = Object.keys(logos)
+import loadLogos from '../lib/load-logos.js'
+import loadSimpleIcons from '../lib/load-simple-icons.js'
+const shieldsLogos = Object.keys(loadLogos())
+const simpleIcons = loadSimpleIcons()
 
 const simpleIconSet = new Set(Object.keys(simpleIcons))
 shieldsLogos.forEach(logo => simpleIconSet.delete(logo))
diff --git a/scripts/redis-connectivity-test.js b/scripts/redis-connectivity-test.js
index de161e029a8913e26456d008e523c5598090690b..5e61fd5cdf5d762aaf4f3961033aca6e32b9d77c 100644
--- a/scripts/redis-connectivity-test.js
+++ b/scripts/redis-connectivity-test.js
@@ -1,12 +1,11 @@
-'use strict'
-
-const config = require('config').util.toObject()
-console.log(config)
-const GithubConstellation = require('../services/github/github-constellation')
+import config from 'config'
+import GithubConstellation from '../services/github/github-constellation.js'
+const objectConfig = config.util.toObject()
+console.log(objectConfig)
 
 const { persistence } = new GithubConstellation({
-  service: config.public.services.github,
-  private: config.private,
+  service: objectConfig.public.services.github,
+  private: objectConfig.private,
 })
 
 async function main() {
diff --git a/server.js b/server.js
index 7eb2bbc6f8f13651b27ef6872371374126021fd7..ea2caef701b032d558357f4eff689366eb133b4c 100644
--- a/server.js
+++ b/server.js
@@ -1,12 +1,15 @@
-'use strict'
 /* eslint-disable import/order */
 
-const fs = require('fs')
-const path = require('path')
+import fs from 'fs'
+import path from 'path'
+import { fileURLToPath } from 'url'
 
 // Set up Sentry reporting as early in the process as possible.
-const config = require('config').util.toObject()
-const Sentry = require('@sentry/node')
+import configModule from 'config'
+import Sentry from '@sentry/node'
+
+import Server from './core/server/server.js'
+const config = configModule.util.toObject()
 const disabledIntegrations = ['Console', 'Http']
 Sentry.init({
   dsn: process.env.SENTRY_DSN || config.private.sentry_dsn,
@@ -42,22 +45,17 @@ if (fs.existsSync('.env')) {
   process.exit(1)
 }
 
-const legacySecretsPath = path.join(__dirname, 'private', 'secret.json')
+const legacySecretsPath = path.join(
+  path.dirname(fileURLToPath(import.meta.url)),
+  'private',
+  'secret.json'
+)
 if (fs.existsSync(legacySecretsPath)) {
   console.error(
     `Legacy secrets file found at ${legacySecretsPath}. It should be deleted and secrets replaced with environment variables or config/local.yml`
   )
   process.exit(1)
 }
+export const server = new Server(config)
 
-const Server = require('./core/server/server')
-const server = (module.exports = new Server(config))
-
-;(async () => {
-  try {
-    await server.start()
-  } catch (e) {
-    console.error(e)
-    process.exit(1)
-  }
-})()
+await server.start()
diff --git a/services/amo/amo-base.js b/services/amo/amo-base.js
index 090221348fd678b695b8eeebe88a2b32b0e81219..d23b35458665da160fbe6492d4726f704f2a035f 100644
--- a/services/amo/amo-base.js
+++ b/services/amo/amo-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const keywords = ['amo', 'firefox']
 
@@ -28,4 +26,4 @@ class BaseAmoService extends BaseJsonService {
   }
 }
 
-module.exports = { BaseAmoService, keywords }
+export { BaseAmoService, keywords }
diff --git a/services/amo/amo-downloads.service.js b/services/amo/amo-downloads.service.js
index ad3012d4fd61f5adf501dc6af5669054fda60d7b..89e50dbbdbdd3c9a5a3c8275c531fb765c323b2e 100644
--- a/services/amo/amo-downloads.service.js
+++ b/services/amo/amo-downloads.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const { redirector } = require('..')
-const { BaseAmoService, keywords } = require('./amo-base')
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import { redirector } from '../index.js'
+import { BaseAmoService, keywords } from './amo-base.js'
 
 const documentation = `
 <p>
@@ -54,7 +52,4 @@ const AmoLegacyRedirect = redirector({
   dateAdded: new Date('2019-02-23'),
 })
 
-module.exports = {
-  AmoWeeklyDownloads,
-  AmoLegacyRedirect,
-}
+export { AmoWeeklyDownloads, AmoLegacyRedirect }
diff --git a/services/amo/amo-downloads.tester.js b/services/amo/amo-downloads.tester.js
index 9ad91c29056be24ad6b3a9e824cf019d339c41ba..b181673ec53739431b3d81800ab00c231c104680 100644
--- a/services/amo/amo-downloads.tester.js
+++ b/services/amo/amo-downloads.tester.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { ServiceTester } = require('../tester')
-const { isMetricOverTimePeriod } = require('../test-validators')
-const t = (module.exports = new ServiceTester({
+import { ServiceTester } from '../tester.js'
+import { isMetricOverTimePeriod } from '../test-validators.js'
+export const t = new ServiceTester({
   id: 'AmoDownloads',
   title: 'AmoDownloads',
   pathPrefix: '/amo',
-}))
+})
 
 t.create('Weekly Downloads')
   .get('/dw/duckduckgo-for-firefox.json')
diff --git a/services/amo/amo-rating.service.js b/services/amo/amo-rating.service.js
index 9943176473f7ed2008de348d04c96788416d0dff..1f26f9127cf0dbc9c76258a0991a2010e98fe2b2 100644
--- a/services/amo/amo-rating.service.js
+++ b/services/amo/amo-rating.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { starRating } from '../text-formatters.js'
+import { floorCount as floorCountColor } from '../color-formatters.js'
+import { BaseAmoService, keywords } from './amo-base.js'
 
-const { starRating } = require('../text-formatters')
-const { floorCount: floorCountColor } = require('../color-formatters')
-const { BaseAmoService, keywords } = require('./amo-base')
-
-module.exports = class AmoRating extends BaseAmoService {
+export default class AmoRating extends BaseAmoService {
   static category = 'rating'
   static route = { base: 'amo', pattern: ':format(stars|rating)/:addonId' }
 
diff --git a/services/amo/amo-rating.tester.js b/services/amo/amo-rating.tester.js
index f17a90656f67ee0b20d190bbdf340063c3d9d264..98432737415858a911f128f66c1179ede3f168cc 100644
--- a/services/amo/amo-rating.tester.js
+++ b/services/amo/amo-rating.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isStarRating } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isStarRating } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Rating')
   .get('/rating/IndieGala-Helper.json')
diff --git a/services/amo/amo-users.service.js b/services/amo/amo-users.service.js
index 91a774279b16b2b5e76baacce338d40064a04bbf..0d42ee8731b354db44d56b137095bdad585cf6d9 100644
--- a/services/amo/amo-users.service.js
+++ b/services/amo/amo-users.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { BaseAmoService, keywords } from './amo-base.js'
 
-const { metric } = require('../text-formatters')
-const { BaseAmoService, keywords } = require('./amo-base')
-
-module.exports = class AmoUsers extends BaseAmoService {
+export default class AmoUsers extends BaseAmoService {
   static category = 'downloads'
   static route = { base: 'amo/users', pattern: ':addonId' }
 
diff --git a/services/amo/amo-users.tester.js b/services/amo/amo-users.tester.js
index a0f168ad0fa37b9c1e4f997e08b1d8d7d6a289a0..5355be2ce1c2543935ea6552de332c8903ba2fc4 100644
--- a/services/amo/amo-users.tester.js
+++ b/services/amo/amo-users.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Users')
   .get('/IndieGala-Helper.json')
diff --git a/services/amo/amo-version.service.js b/services/amo/amo-version.service.js
index 33bf27b85c5c80d877a856775a4f5b4d5e97d04d..96394bba7fc44949b1f68f6276141d3882150cda 100644
--- a/services/amo/amo-version.service.js
+++ b/services/amo/amo-version.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import { BaseAmoService, keywords } from './amo-base.js'
 
-const { renderVersionBadge } = require('../version')
-const { BaseAmoService, keywords } = require('./amo-base')
-
-module.exports = class AmoVersion extends BaseAmoService {
+export default class AmoVersion extends BaseAmoService {
   static category = 'version'
   static route = { base: 'amo/v', pattern: ':addonId' }
 
diff --git a/services/amo/amo-version.tester.js b/services/amo/amo-version.tester.js
index 9f63c1b0b0e6496b84061651b0e06fbe4292f153..e900a589a6484132afda76e2a9d511c02c468541 100644
--- a/services/amo/amo-version.tester.js
+++ b/services/amo/amo-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Version').get('/IndieGala-Helper.json').expectBadge({
   label: 'mozilla add-on',
diff --git a/services/ansible/ansible-quality.service.js b/services/ansible/ansible-quality.service.js
index 43da34f60d477f6055282ae212c86c755565f8b8..6af7ae16ca588f1a45f468c1b9bd4fe67d1740a5 100644
--- a/services/ansible/ansible-quality.service.js
+++ b/services/ansible/ansible-quality.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { floorCount } = require('../color-formatters')
-const { BaseJsonService, InvalidResponse } = require('..')
+import Joi from 'joi'
+import { floorCount } from '../color-formatters.js'
+import { BaseJsonService, InvalidResponse } from '../index.js'
 
 const ansibleContentSchema = Joi.object({
   quality_score: Joi.number().allow(null).required(),
@@ -18,9 +16,7 @@ class AnsibleGalaxyContent extends BaseJsonService {
   }
 }
 
-module.exports = class AnsibleGalaxyContentQualityScore extends (
-  AnsibleGalaxyContent
-) {
+export default class AnsibleGalaxyContentQualityScore extends AnsibleGalaxyContent {
   static category = 'analysis'
   static route = { base: 'ansible/quality', pattern: ':projectId' }
 
diff --git a/services/ansible/ansible-quality.tester.js b/services/ansible/ansible-quality.tester.js
index f9dd14a4d611b17ded5266bbc403c8465cb45e86..4ac15bff0c845c76b283bfa1659830739abc3e85 100644
--- a/services/ansible/ansible-quality.tester.js
+++ b/services/ansible/ansible-quality.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { nonNegativeInteger } = require('../validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { nonNegativeInteger } from '../validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('quality score (valid)')
   .get('/432.json')
diff --git a/services/ansible/ansible-role.service.js b/services/ansible/ansible-role.service.js
index c447859782cb6d2ffb7960e194b163e0cd2d0283..aa1cdcb7731c9c58549ad0a13a989d6bfaaf914e 100644
--- a/services/ansible/ansible-role.service.js
+++ b/services/ansible/ansible-role.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { downloadCount } = require('../color-formatters')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { downloadCount } from '../color-formatters.js'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const ansibleRoleSchema = Joi.object({
   download_count: nonNegativeInteger,
@@ -80,7 +78,4 @@ class AnsibleGalaxyRoleName extends AnsibleGalaxyRole {
   }
 }
 
-module.exports = {
-  AnsibleGalaxyRoleDownloads,
-  AnsibleGalaxyRoleName,
-}
+export { AnsibleGalaxyRoleDownloads, AnsibleGalaxyRoleName }
diff --git a/services/ansible/ansible-role.tester.js b/services/ansible/ansible-role.tester.js
index ac1a3980d4585029a62343c4e88c5cad04fd10b1..8679789fa0a833e4494be89194763764585576d9 100644
--- a/services/ansible/ansible-role.tester.js
+++ b/services/ansible/ansible-role.tester.js
@@ -1,13 +1,10 @@
-'use strict'
-
-const { ServiceTester } = require('../tester')
-const { isMetric } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+import { isMetric } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'AnsibleRole',
   title: 'AnsibleRole',
   pathPrefix: '/ansible/role',
-}))
+})
 
 t.create('role name (valid)')
   .get('/14542.json')
diff --git a/services/apm/apm.service.js b/services/apm/apm.service.js
index 9b52cfe7ed2d786fc182f2ff94c12344e5817314..681bd0d46504b804ebe40e098d97f2732aba2cef 100644
--- a/services/apm/apm.service.js
+++ b/services/apm/apm.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderLicenseBadge } = require('../licenses')
-const { renderVersionBadge } = require('../version')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService, InvalidResponse } = require('..')
+import Joi from 'joi'
+import { renderLicenseBadge } from '../licenses.js'
+import { renderVersionBadge } from '../version.js'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService, InvalidResponse } from '../index.js'
 
 const keywords = ['atom']
 
@@ -116,8 +114,4 @@ class APMLicense extends BaseAPMService {
   }
 }
 
-module.exports = {
-  APMDownloads,
-  APMVersion,
-  APMLicense,
-}
+export { APMDownloads, APMVersion, APMLicense }
diff --git a/services/apm/apm.tester.js b/services/apm/apm.tester.js
index c7553a491e750a145dc24d6ef44f466c7d516283..ed6f7c861e54af30d62c504692d464ef6c3c4b23 100644
--- a/services/apm/apm.tester.js
+++ b/services/apm/apm.tester.js
@@ -1,13 +1,11 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { invalidJSON } from '../response-fixtures.js'
+import { isMetric, isVPlusTripleDottedVersion } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { invalidJSON } = require('../response-fixtures')
-const { isMetric, isVPlusTripleDottedVersion } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'apm',
   title: 'Atom Package Manager',
-}))
+})
 
 t.create('Downloads')
   .get('/dm/vim-mode.json')
diff --git a/services/appveyor/appveyor-base.js b/services/appveyor/appveyor-base.js
index 015612c43c3c0067950e6a39a54986f22ef2b042..923b718466cbf1f71b71539b9adafb32a5efd045 100644
--- a/services/appveyor/appveyor-base.js
+++ b/services/appveyor/appveyor-base.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { isBuildStatus } = require('../build-status')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { isBuildStatus } from '../build-status.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   build: Joi.object({
@@ -20,7 +18,7 @@ const schema = Joi.object({
   }),
 }).required()
 
-module.exports = class AppVeyorBase extends BaseJsonService {
+export default class AppVeyorBase extends BaseJsonService {
   static category = 'build'
 
   async fetch({ user, repo, branch }) {
diff --git a/services/appveyor/appveyor-build-redirect.service.js b/services/appveyor/appveyor-build-redirect.service.js
index df723459997c072db6baf32a209992d4b0c87ca4..61e43b31b2ccb685fd33ed2e43dbdad53251fc55 100644
--- a/services/appveyor/appveyor-build-redirect.service.js
+++ b/services/appveyor/appveyor-build-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   redirector({
     category: 'build',
     route: {
diff --git a/services/appveyor/appveyor-build-redirect.tester.js b/services/appveyor/appveyor-build-redirect.tester.js
index 625a1f1a169e88e9ddc7d1c483cebe5d55a4f65a..40ad8049d48c8cee027bd3fd569b3a377f4c1572 100644
--- a/services/appveyor/appveyor-build-redirect.tester.js
+++ b/services/appveyor/appveyor-build-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'AppveyorBuildRedirect',
   title: 'AppveyorBuildRedirect',
   pathPrefix: '/appveyor/ci',
-}))
+})
 
 t.create('Appveyor CI')
   .get('/gruntjs/grunt', {
diff --git a/services/appveyor/appveyor-build.service.js b/services/appveyor/appveyor-build.service.js
index 352a9e7ec836e3697c8a032e6d2d088f3a4ba09b..29cb3958353943bc2d415c6c8e14277b89c43c94 100644
--- a/services/appveyor/appveyor-build.service.js
+++ b/services/appveyor/appveyor-build.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { renderBuildStatusBadge } from '../build-status.js'
+import AppVeyorBase from './appveyor-base.js'
 
-const { renderBuildStatusBadge } = require('../build-status')
-const AppVeyorBase = require('./appveyor-base')
-
-module.exports = class AppVeyorBuild extends AppVeyorBase {
+export default class AppVeyorBuild extends AppVeyorBase {
   static route = this.buildRoute('appveyor/build')
 
   static examples = [
diff --git a/services/appveyor/appveyor-build.tester.js b/services/appveyor/appveyor-build.tester.js
index 9858a91f17385b918b86742e2e9dea2e0ccfc287..b1141067e49b09252117c7ec4f809b56982f375d 100644
--- a/services/appveyor/appveyor-build.tester.js
+++ b/services/appveyor/appveyor-build.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('CI status')
   .timeout(10000)
diff --git a/services/appveyor/appveyor-job-build.service.js b/services/appveyor/appveyor-job-build.service.js
index dc389cbde67f4beb0c3936f29d23b29ca7729192..fc856aa7f25a2a17cf15263f6dcce9525ac2d1f4 100644
--- a/services/appveyor/appveyor-job-build.service.js
+++ b/services/appveyor/appveyor-job-build.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { renderBuildStatusBadge } from '../build-status.js'
+import { NotFound } from '../index.js'
+import AppVeyorBase from './appveyor-base.js'
 
-const { renderBuildStatusBadge } = require('../build-status')
-const { NotFound } = require('..')
-const AppVeyorBase = require('./appveyor-base')
-
-module.exports = class AppVeyorJobBuild extends AppVeyorBase {
+export default class AppVeyorJobBuild extends AppVeyorBase {
   static route = {
     base: 'appveyor/job/build',
     pattern: ':user/:repo/:job/:branch*',
diff --git a/services/appveyor/appveyor-job-build.spec.js b/services/appveyor/appveyor-job-build.spec.js
index 5d539a72cd3403c053d3a486d6c77ff32a0a34e5..4e83a26fd427d17334d5feadc6f6e8cb07171812 100644
--- a/services/appveyor/appveyor-job-build.spec.js
+++ b/services/appveyor/appveyor-job-build.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const { test, given } = require('sazerac')
-const { NotFound } = require('..')
-const AppveyorJobBuild = require('./appveyor-job-build.service')
+import { expect } from 'chai'
+import { test, given } from 'sazerac'
+import { NotFound } from '../index.js'
+import AppveyorJobBuild from './appveyor-job-build.service.js'
 
 describe('AppveyorJobBuild', function () {
   test(AppveyorJobBuild.prototype.transform, () => {
diff --git a/services/appveyor/appveyor-job-build.tester.js b/services/appveyor/appveyor-job-build.tester.js
index 81cccb39f252a79bb0fada62008da91a9fde8a4e..a31306e30ec00f86637e6865bbcd95d38ab36af0 100644
--- a/services/appveyor/appveyor-job-build.tester.js
+++ b/services/appveyor/appveyor-job-build.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Job CI status')
   .timeout(10000)
diff --git a/services/appveyor/appveyor-tests.service.js b/services/appveyor/appveyor-tests.service.js
index c3efa4e636d2e04f7eb0f75d8e1d8f362aa5b420..465130445eb497cdc42e496e58f053f43421dd1f 100644
--- a/services/appveyor/appveyor-tests.service.js
+++ b/services/appveyor/appveyor-tests.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const {
+import {
   testResultQueryParamSchema,
   renderTestResultBadge,
-} = require('../test-results')
-const AppVeyorBase = require('./appveyor-base')
+} from '../test-results.js'
+import AppVeyorBase from './appveyor-base.js'
 
 const documentation = `
 <p>
@@ -36,7 +34,7 @@ const commonPreviewProps = {
   isCompact: false,
 }
 
-module.exports = class AppVeyorTests extends AppVeyorBase {
+export default class AppVeyorTests extends AppVeyorBase {
   static route = {
     ...this.buildRoute('appveyor/tests'),
     queryParamSchema: testResultQueryParamSchema,
diff --git a/services/appveyor/appveyor-tests.tester.js b/services/appveyor/appveyor-tests.tester.js
index df81a2de2e521254e73835008387b352311f360a..102f532d29958b934c40aaeb53290f399de31996 100644
--- a/services/appveyor/appveyor-tests.tester.js
+++ b/services/appveyor/appveyor-tests.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const queryString = require('querystring')
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import queryString from 'querystring'
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isAppveyorTestTotals = Joi.string().regex(
   /^[0-9]+ passed(, [0-9]+ failed)?(, [0-9]+ skipped)?$/
diff --git a/services/archlinux/archlinux.service.js b/services/archlinux/archlinux.service.js
index f06a5003a8fded2e0d7e2b28dfbf1da82ed52543..c3ee192b13fdcf49bf7c5e18fc517e35a67bcd72 100644
--- a/services/archlinux/archlinux.service.js
+++ b/services/archlinux/archlinux.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   pkgver: Joi.string().required(),
 }).required()
 
-module.exports = class ArchLinux extends BaseJsonService {
+export default class ArchLinux extends BaseJsonService {
   static category = 'version'
   static route = {
     base: 'archlinux/v',
diff --git a/services/archlinux/archlinux.tester.js b/services/archlinux/archlinux.tester.js
index 379e8133c6f8dc846e1bc45006cf26e508ffc833..d92b65464b2cdf65508085a05662d15a38d5ae25 100644
--- a/services/archlinux/archlinux.tester.js
+++ b/services/archlinux/archlinux.tester.js
@@ -1,9 +1,6 @@
-'use strict'
-
-const {
-  isVPlusDottedVersionNClausesWithOptionalSuffixAndEpoch,
-} = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionNClausesWithOptionalSuffixAndEpoch } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Arch Linux package (valid)')
   .get('/core/x86_64/pacman.json')
diff --git a/services/aur/aur.service.js b/services/aur/aur.service.js
index dbab2748a04cbb591ec30a570c3b70fe3745d253..901e8e0bf991593f8909a0f32525e633f3ee5fc8 100644
--- a/services/aur/aur.service.js
+++ b/services/aur/aur.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { floorCount: floorCountColor } = require('../color-formatters')
-const { addv, metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService, NotFound } = require('..')
-const { formatDate } = require('../text-formatters')
-const { age: ageColor } = require('../color-formatters')
-const { InvalidResponse } = require('..')
+import Joi from 'joi'
+import {
+  floorCount as floorCountColor,
+  age as ageColor,
+} from '../color-formatters.js'
+import { addv, metric, formatDate } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService, NotFound, InvalidResponse } from '../index.js'
 
 const aurSchema = Joi.object({
   resultcount: nonNegativeInteger,
@@ -198,10 +196,4 @@ class AurLastModified extends BaseAurService {
   }
 }
 
-module.exports = {
-  AurLicense,
-  AurVersion,
-  AurVotes,
-  AurMaintainer,
-  AurLastModified,
-}
+export { AurLicense, AurVersion, AurVotes, AurMaintainer, AurLastModified }
diff --git a/services/aur/aur.spec.js b/services/aur/aur.spec.js
index 93fd0a8a70bf8eb74b6d61b2c22f1e463aed0f17..0bdc44bec721b8289aa2582d6b3cd2bc5e493a87 100644
--- a/services/aur/aur.spec.js
+++ b/services/aur/aur.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { AurVersion } = require('./aur.service')
+import { test, given } from 'sazerac'
+import { AurVersion } from './aur.service.js'
 
 describe('AurVersion', function () {
   test(AurVersion.render, () => {
diff --git a/services/aur/aur.tester.js b/services/aur/aur.tester.js
index 51b176a4cca0676defc277e23900be9f87529183..c6026d4f351af02ea153850beabadc104c5bad80 100644
--- a/services/aur/aur.tester.js
+++ b/services/aur/aur.tester.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const { ServiceTester } = require('../tester')
-const {
+import { ServiceTester } from '../tester.js'
+import {
   isVPlusDottedVersionNClausesWithOptionalSuffix,
   isMetric,
-} = require('../test-validators')
-const { isFormattedDate } = require('../test-validators')
+  isFormattedDate,
+} from '../test-validators.js'
 
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'aur',
   title: 'Arch Linux AUR',
-}))
+})
 
 // version tests
 
diff --git a/services/azure-devops/azure-devops-base.js b/services/azure-devops/azure-devops-base.js
index 37d0702bd9bd994639611c148c65ced7580e583d..184530bde7c5b8c4457e2606ca9d9df8b55d7bf7 100644
--- a/services/azure-devops/azure-devops-base.js
+++ b/services/azure-devops/azure-devops-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const latestBuildSchema = Joi.object({
   count: Joi.number().required(),
@@ -14,7 +12,7 @@ const latestBuildSchema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class AzureDevOpsBase extends BaseJsonService {
+export default class AzureDevOpsBase extends BaseJsonService {
   static auth = {
     passKey: 'azure_devops_token',
     authorizedOrigins: ['https://dev.azure.com'],
diff --git a/services/azure-devops/azure-devops-build.service.js b/services/azure-devops/azure-devops-build.service.js
index 5159c86408231ed956f2b73e71594ae1eabcadd8..8485fa49fe502d6960f9a9bea8d4d081588bcc42 100644
--- a/services/azure-devops/azure-devops-build.service.js
+++ b/services/azure-devops/azure-devops-build.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderBuildStatusBadge } = require('../build-status')
-const { BaseSvgScrapingService, NotFound } = require('..')
-const { keywords, fetch } = require('./azure-devops-helpers')
+import Joi from 'joi'
+import { renderBuildStatusBadge } from '../build-status.js'
+import { BaseSvgScrapingService, NotFound } from '../index.js'
+import { keywords, fetch } from './azure-devops-helpers.js'
 
 const queryParamSchema = Joi.object({
   stage: Joi.string(),
@@ -33,7 +31,7 @@ const documentation = `
   alt="PROJECT_ID is in the id property of the API response." />
 `
 
-module.exports = class AzureDevOpsBuild extends BaseSvgScrapingService {
+export default class AzureDevOpsBuild extends BaseSvgScrapingService {
   static category = 'build'
 
   static route = {
diff --git a/services/azure-devops/azure-devops-build.tester.js b/services/azure-devops/azure-devops-build.tester.js
index 871d2a89b4d5d011248a5e73a6aa05c3d3c0b66a..73027411170a8339fd52dacdf7c22b6bd853929c 100644
--- a/services/azure-devops/azure-devops-build.tester.js
+++ b/services/azure-devops/azure-devops-build.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // https://dev.azure.com/totodem/Shields.io is a public Azure DevOps project
 // solely created for Shields.io testing.
diff --git a/services/azure-devops/azure-devops-coverage.service.js b/services/azure-devops/azure-devops-coverage.service.js
index f2c28adeae9e6c351c436cafcb4cfb14ef2a99a4..4234b36f48d6a112cca2006b1bb773ea4350cbad 100644
--- a/services/azure-devops/azure-devops-coverage.service.js
+++ b/services/azure-devops/azure-devops-coverage.service.js
@@ -1,11 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const {
-  coveragePercentage: coveragePercentageColor,
-} = require('../color-formatters')
-const AzureDevOpsBase = require('./azure-devops-base')
-const { keywords } = require('./azure-devops-helpers')
+import Joi from 'joi'
+import { coveragePercentage as coveragePercentageColor } from '../color-formatters.js'
+import AzureDevOpsBase from './azure-devops-base.js'
+import { keywords } from './azure-devops-helpers.js'
 
 const documentation = `
 <p>
@@ -46,7 +42,7 @@ const buildCodeCoverageSchema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class AzureDevOpsCoverage extends AzureDevOpsBase {
+export default class AzureDevOpsCoverage extends AzureDevOpsBase {
   static category = 'coverage'
 
   static route = {
diff --git a/services/azure-devops/azure-devops-coverage.tester.js b/services/azure-devops/azure-devops-coverage.tester.js
index 3de650324fc177193fd3279990dfae3ca83639bd..2177d9077c8bfe7300cb54a31fe3099c673b3692 100644
--- a/services/azure-devops/azure-devops-coverage.tester.js
+++ b/services/azure-devops/azure-devops-coverage.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const org = 'swellaby'
 const project = 'opensource'
diff --git a/services/azure-devops/azure-devops-helpers.js b/services/azure-devops/azure-devops-helpers.js
index 9b841bb0772ee9770686230fba265509274bea4b..67b457352a303063122b7eea247bd0f5e6b15867 100644
--- a/services/azure-devops/azure-devops-helpers.js
+++ b/services/azure-devops/azure-devops-helpers.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus } = require('../build-status')
+import Joi from 'joi'
+import { isBuildStatus } from '../build-status.js'
 
 const keywords = ['vso', 'vsts', 'azure-devops']
 
@@ -28,4 +26,4 @@ async function fetch(serviceInstance, { url, qs = {}, errorMessages }) {
   return { status }
 }
 
-module.exports = { keywords, fetch }
+export { keywords, fetch }
diff --git a/services/azure-devops/azure-devops-release.service.js b/services/azure-devops/azure-devops-release.service.js
index eccbfc90c5d15399a9c8eaaa3ffdebbe23972c5e..96393ad4b0d9467a24f0baacff3d9a9c4bd2cf6d 100644
--- a/services/azure-devops/azure-devops-release.service.js
+++ b/services/azure-devops/azure-devops-release.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { renderBuildStatusBadge } = require('../build-status')
-const { BaseSvgScrapingService } = require('..')
-const { keywords, fetch } = require('./azure-devops-helpers')
+import { renderBuildStatusBadge } from '../build-status.js'
+import { BaseSvgScrapingService } from '../index.js'
+import { keywords, fetch } from './azure-devops-helpers.js'
 
 const documentation = `
 <p>
@@ -22,7 +20,7 @@ const documentation = `
 </p>
 `
 
-module.exports = class AzureDevOpsRelease extends BaseSvgScrapingService {
+export default class AzureDevOpsRelease extends BaseSvgScrapingService {
   static category = 'build'
 
   static route = {
diff --git a/services/azure-devops/azure-devops-release.tester.js b/services/azure-devops/azure-devops-release.tester.js
index c161bd618b83431fbd187f032f85286e59c66432..7ffa1d94e327518da4aca6e95a43dcd315d06fe0 100644
--- a/services/azure-devops/azure-devops-release.tester.js
+++ b/services/azure-devops/azure-devops-release.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // https://dev.azure.com/totodem/Shields.io is a public Azure DevOps project
 // solely created for Shields.io testing.
diff --git a/services/azure-devops/azure-devops-tests.service.js b/services/azure-devops/azure-devops-tests.service.js
index 5b373a3fe7e1c248606d7cdf793dffbb02f87caf..a2939b95aebfcbe7342190b7369088b3d12605b8 100644
--- a/services/azure-devops/azure-devops-tests.service.js
+++ b/services/azure-devops/azure-devops-tests.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const Joi = require('joi')
-const {
+import Joi from 'joi'
+import {
   testResultQueryParamSchema,
   renderTestResultBadge,
-} = require('../test-results')
-const AzureDevOpsBase = require('./azure-devops-base')
+} from '../test-results.js'
+import AzureDevOpsBase from './azure-devops-base.js'
 
 const commonAttrs = {
   keywords: ['vso', 'vsts', 'azure-devops'],
@@ -61,7 +59,7 @@ const buildTestResultSummarySchema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class AzureDevOpsTests extends AzureDevOpsBase {
+export default class AzureDevOpsTests extends AzureDevOpsBase {
   static category = 'build'
 
   static route = {
diff --git a/services/azure-devops/azure-devops-tests.tester.js b/services/azure-devops/azure-devops-tests.tester.js
index eb3425b89c3b402ab60a4ccdf034b4a9e88a2b7c..d708183ac8fa52920d2d864578826ddcd864d74d 100644
--- a/services/azure-devops/azure-devops-tests.tester.js
+++ b/services/azure-devops/azure-devops-tests.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const org = 'azuredevops-powershell'
 const project = 'azuredevops-powershell'
diff --git a/services/azure-devops/vso-redirect.service.js b/services/azure-devops/vso-redirect.service.js
index a8b5d8435f7f9f298bbd831e6e8fb840a295fc39..e67c703dd8eacf0ea61f5cc1b7273b5d9c202abc 100644
--- a/services/azure-devops/vso-redirect.service.js
+++ b/services/azure-devops/vso-redirect.service.js
@@ -1,31 +1,27 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
-  redirector({
-    category: 'build',
-    route: {
-      base: 'vso/build',
-      pattern: ':organization/:projectId/:definitionId/:branch*',
-    },
-    transformPath: ({ organization, projectId, definitionId, branch }) => {
-      let path = `/azure-devops/build/${organization}/${projectId}/${definitionId}`
-      if (branch) {
-        path += `/${branch}`
-      }
-      return path
-    },
-    dateAdded: new Date('2019-02-08'),
-  }),
-  redirector({
-    category: 'build',
-    route: {
-      base: 'vso/release',
-      pattern: ':organization/:projectId/:definitionId/:environmentId',
-    },
-    transformPath: ({ organization, projectId, definitionId, environmentId }) =>
-      `/azure-devops/release/${organization}/${projectId}/${definitionId}/${environmentId}`,
-    dateAdded: new Date('2019-02-08'),
-  }),
-]
+export const VsoBuildRedirector = redirector({
+  category: 'build',
+  route: {
+    base: 'vso/build',
+    pattern: ':organization/:projectId/:definitionId/:branch*',
+  },
+  transformPath: ({ organization, projectId, definitionId, branch }) => {
+    let path = `/azure-devops/build/${organization}/${projectId}/${definitionId}`
+    if (branch) {
+      path += `/${branch}`
+    }
+    return path
+  },
+  dateAdded: new Date('2019-02-08'),
+})
+export const VsoReleaseRedirector = redirector({
+  category: 'build',
+  route: {
+    base: 'vso/release',
+    pattern: ':organization/:projectId/:definitionId/:environmentId',
+  },
+  transformPath: ({ organization, projectId, definitionId, environmentId }) =>
+    `/azure-devops/release/${organization}/${projectId}/${definitionId}/${environmentId}`,
+  dateAdded: new Date('2019-02-08'),
+})
diff --git a/services/azure-devops/vso-redirect.tester.js b/services/azure-devops/vso-redirect.tester.js
index 7cd544b7d9421d19d005d752a700b0a15dd14cb3..d36f81ca2779e1518cbf1d38e3119a460d459756 100644
--- a/services/azure-devops/vso-redirect.tester.js
+++ b/services/azure-devops/vso-redirect.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'vso',
   title: 'VSO',
-}))
+})
 
 t.create('Build: default branch')
   .get('/build/totodem/8cf3ec0e-d0c2-4fcd-8206-ad204f254a96/2.svg')
diff --git a/services/beerpay/beerpay.service.js b/services/beerpay/beerpay.service.js
index 287eb9296a1de5dd9e125779f74fa43150c1347c..19b8620e24efa57108dbff842a946cd36d370eb0 100644
--- a/services/beerpay/beerpay.service.js
+++ b/services/beerpay/beerpay.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'build',
   route: {
     base: 'beerpay',
diff --git a/services/beerpay/beerpay.tester.js b/services/beerpay/beerpay.tester.js
index 3901ec29def3d58f533b66223c6ec8b6112900d2..a4360440e1f21f87267a1643a2836905a7b5bb12 100644
--- a/services/beerpay/beerpay.tester.js
+++ b/services/beerpay/beerpay.tester.js
@@ -1,10 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'beerpay',
   title: 'Beerpay',
-}))
+})
 
 t.create('no longer available (previously beerpay)')
   .get('/hashdog/scrapfy-chrome-extension.json')
diff --git a/services/bintray/bintray.service.js b/services/bintray/bintray.service.js
index fd19d8e82b39b376afeed535ba6ff966e8baad82..f181fb2c2535468664cae2da6f7dcb011da673f6 100644
--- a/services/bintray/bintray.service.js
+++ b/services/bintray/bintray.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = [
+export default [
   deprecatedService({
     category: 'downloads',
     route: {
diff --git a/services/bintray/bintray.tester.js b/services/bintray/bintray.tester.js
index a16e2413c8ae44da0841430ab615f8ff227f4789..cc55f5bdba1ca246e716df02eadbb5fad7ec92ee 100644
--- a/services/bintray/bintray.tester.js
+++ b/services/bintray/bintray.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'bintray',
   title: 'Bintray',
-}))
+})
 
 t.create('no longer available (previously downloads)')
   .get('/dt/asciidoctor/maven/asciidoctorj.json')
diff --git a/services/bit/bit-components.service.js b/services/bit/bit-components.service.js
index 3b852d46e626309e99e779373c4acd8bf50c3bb1..e2236639034b75514b535123fa7e2f3da6c1e49b 100644
--- a/services/bit/bit-components.service.js
+++ b/services/bit/bit-components.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { downloadCount } = require('../color-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { downloadCount } from '../color-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const collectionSchema = Joi.object({
   payload: Joi.object({
@@ -12,7 +10,7 @@ const collectionSchema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class BitComponents extends BaseJsonService {
+export default class BitComponents extends BaseJsonService {
   static category = 'other'
   static route = {
     base: 'bit/collection/total-components',
diff --git a/services/bit/bit-components.tester.js b/services/bit/bit-components.tester.js
index 9a51426dd12cbdc3218c91b12c084eae5064cc22..2f6dee749d2f74dd56a1d998a886b528550b3784 100644
--- a/services/bit/bit-components.tester.js
+++ b/services/bit/bit-components.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isMetric } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('collection (valid)').get('/ramda/ramda.json').expectBadge({
   label: 'components',
diff --git a/services/bitbucket/bitbucket-issues.service.js b/services/bitbucket/bitbucket-issues.service.js
index f2399d66cfbb4c73d3f511a8c7905730aa953ff7..9bcf5a5b92fbdcc599ea4a77b8cb22d852c52ab5 100644
--- a/services/bitbucket/bitbucket-issues.service.js
+++ b/services/bitbucket/bitbucket-issues.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const bitbucketIssuesSchema = Joi.object({
   size: nonNegativeInteger,
@@ -59,4 +57,5 @@ function issueClassGenerator(raw) {
   }
 }
 
-module.exports = [true, false].map(issueClassGenerator)
+export const BitbucketRawIssues = issueClassGenerator(true)
+export const BitbucketNonRawIssues = issueClassGenerator(false)
diff --git a/services/bitbucket/bitbucket-issues.tester.js b/services/bitbucket/bitbucket-issues.tester.js
index 4f05579b3577aeb806f89b965b7544187e6e14cf..4bdb300b52e057f53d9639b9acca992b111e3313 100644
--- a/services/bitbucket/bitbucket-issues.tester.js
+++ b/services/bitbucket/bitbucket-issues.tester.js
@@ -1,13 +1,11 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isMetric, isMetricOpenIssues } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isMetric, isMetricOpenIssues } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'BitbucketIssues',
   title: 'Bitbucket Issues',
   pathPrefix: '/bitbucket',
-}))
+})
 
 t.create('issues-raw (valid)')
   .get('/issues-raw/atlassian/python-bitbucket.json')
diff --git a/services/bitbucket/bitbucket-pipelines.service.js b/services/bitbucket/bitbucket-pipelines.service.js
index 347e1d97cbf079ac1a67593032a8028c89af8e16..dc28820bcdb1ac08444cc73be757d44d6ddae792 100644
--- a/services/bitbucket/bitbucket-pipelines.service.js
+++ b/services/bitbucket/bitbucket-pipelines.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderBuildStatusBadge } = require('../build-status')
-const { BaseJsonService, redirector } = require('..')
+import Joi from 'joi'
+import { renderBuildStatusBadge } from '../build-status.js'
+import { BaseJsonService, redirector } from '../index.js'
 
 const bitbucketPipelinesSchema = Joi.object({
   values: Joi.array()
@@ -96,7 +94,4 @@ const BitbucketPipelinesRedirector = redirector({
   dateAdded: new Date('2020-07-12'),
 })
 
-module.exports = {
-  BitbucketPipelines,
-  BitbucketPipelinesRedirector,
-}
+export { BitbucketPipelines, BitbucketPipelinesRedirector }
diff --git a/services/bitbucket/bitbucket-pipelines.tester.js b/services/bitbucket/bitbucket-pipelines.tester.js
index 2eeec523f91ad31bf933db26345a2aef4476cca4..1fe7293a8a7cb44896a37732a88ac23d9dd20033 100644
--- a/services/bitbucket/bitbucket-pipelines.tester.js
+++ b/services/bitbucket/bitbucket-pipelines.tester.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import { isBuildStatus } from '../build-status.js'
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'BitbucketPipelines',
   title: 'Bitbucket Pipelines',
   pathPrefix: '/bitbucket/pipelines',
-}))
+})
 
 function bitbucketApiResponse(status) {
   return JSON.stringify({
diff --git a/services/bitbucket/bitbucket-pull-request.service.js b/services/bitbucket/bitbucket-pull-request.service.js
index 3ecc0028997331e42fc79379a542970e2daa58ae..add3ad820f96b056534473f6d190da21d328bf51 100644
--- a/services/bitbucket/bitbucket-pull-request.service.js
+++ b/services/bitbucket/bitbucket-pull-request.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { AuthHelper } = require('../../core/base-service/auth-helper')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger, optionalUrl } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { AuthHelper } from '../../core/base-service/auth-helper.js'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger, optionalUrl } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   size: nonNegativeInteger,
@@ -128,4 +126,5 @@ function pullRequestClassGenerator(raw) {
   }
 }
 
-module.exports = [true, false].map(pullRequestClassGenerator)
+export const BitbucketRawPullRequests = pullRequestClassGenerator(true)
+export const BitbucketNonRawPullRequests = pullRequestClassGenerator(false)
diff --git a/services/bitbucket/bitbucket-pull-request.spec.js b/services/bitbucket/bitbucket-pull-request.spec.js
index 39aefaea118af0f11cc70679bb00712904e15f44..565a2c1634777277a238fb2816ab9d054dfa60ff 100644
--- a/services/bitbucket/bitbucket-pull-request.spec.js
+++ b/services/bitbucket/bitbucket-pull-request.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const [BitbucketPullRequest] = require('./bitbucket-pull-request.service')
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import { BitbucketRawPullRequests } from './bitbucket-pull-request.service.js'
 
 describe('BitbucketPullRequest', function () {
   cleanUpNockAfterEach()
@@ -18,7 +16,7 @@ describe('BitbucketPullRequest', function () {
       .reply(200, { size: 42 })
 
     expect(
-      await BitbucketPullRequest.invoke(
+      await BitbucketRawPullRequests.invoke(
         defaultContext,
         {
           public: {
@@ -47,7 +45,7 @@ describe('BitbucketPullRequest', function () {
       .reply(200, { size: 42 })
 
     expect(
-      await BitbucketPullRequest.invoke(
+      await BitbucketRawPullRequests.invoke(
         defaultContext,
         {
           public: {
diff --git a/services/bitbucket/bitbucket-pull-request.tester.js b/services/bitbucket/bitbucket-pull-request.tester.js
index 9e9f48ba85f3c295cde67f77af529ee8e49a99b4..c9ab932578836f5367f7899322f524b3afa6b9e3 100644
--- a/services/bitbucket/bitbucket-pull-request.tester.js
+++ b/services/bitbucket/bitbucket-pull-request.tester.js
@@ -1,13 +1,11 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isMetric, isMetricOpenIssues } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isMetric, isMetricOpenIssues } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'BitbucketPullRequest',
   title: 'Bitbucket Pull Request',
   pathPrefix: '/bitbucket',
-}))
+})
 
 t.create('pr-raw (valid)')
   .get('/pr-raw/atlassian/python-bitbucket.json')
diff --git a/services/bithound/bithound.service.js b/services/bithound/bithound.service.js
index 0a36660e956a61d5843989abc0f1406fa11882c6..1898317b547af8d480912266f84c73ef3723cb10 100644
--- a/services/bithound/bithound.service.js
+++ b/services/bithound/bithound.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'dependencies',
   route: {
     base: 'bithound',
diff --git a/services/bithound/bithound.tester.js b/services/bithound/bithound.tester.js
index f4c70181654b1ce62f9a14a71ee262729d85e34b..03bbf3c049bcd7008ed61645186a35c696e497c7 100644
--- a/services/bithound/bithound.tester.js
+++ b/services/bithound/bithound.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'bithound',
   title: 'BitHound',
-}))
+})
 
 t.create('no longer available (code)')
   .get('/code/github/rexxars/sse-channel.json')
diff --git a/services/bitrise/bitrise.service.js b/services/bitrise/bitrise.service.js
index c3a27f68388c751cb69d8ab0b0374b593aeb70b1..ee76f55972efb66c3e56c22da0b1c0272fc75b10 100644
--- a/services/bitrise/bitrise.service.js
+++ b/services/bitrise/bitrise.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 // https://devcenter.bitrise.io/api/app-status-badge/
 const schema = Joi.object({
@@ -12,7 +10,7 @@ const queryParamSchema = Joi.object({
   token: Joi.string().required(),
 }).required()
 
-module.exports = class Bitrise extends BaseJsonService {
+export default class Bitrise extends BaseJsonService {
   static category = 'build'
   static route = {
     base: 'bitrise',
diff --git a/services/bitrise/bitrise.tester.js b/services/bitrise/bitrise.tester.js
index b31ba9f78ea99b6704a78d04bc8c95ddce607ca5..26c2b238ad96e6233dc4d34f77763dba9e46827d 100644
--- a/services/bitrise/bitrise.tester.js
+++ b/services/bitrise/bitrise.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('deploy status')
   .get('/cde737473028420d.json?token=GCIdEzacE4GW32jLVrZb7A')
diff --git a/services/bountysource/bountysource.service.js b/services/bountysource/bountysource.service.js
index 9834fdd8e66eb88ab8ecdc3bf6366966af6e9e31..1bb4b81aff9f9dff6b5cd8f0afeac25ab3ac9758 100644
--- a/services/bountysource/bountysource.service.js
+++ b/services/bountysource/bountysource.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { metric } = require('../text-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { metric } from '../text-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({ activity_total: nonNegativeInteger })
 
-module.exports = class Bountysource extends BaseJsonService {
+export default class Bountysource extends BaseJsonService {
   static category = 'funding'
   static route = { base: 'bountysource/team', pattern: ':team/activity' }
 
diff --git a/services/bountysource/bountysource.tester.js b/services/bountysource/bountysource.tester.js
index 634b8adbbc76401c3e78a3df3b2262f240537cfe..cec68a500c333d06b9a856646b2ae1eb8c289213 100644
--- a/services/bountysource/bountysource.tester.js
+++ b/services/bountysource/bountysource.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { isMetric } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
 
-const { isMetric } = require('../test-validators')
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'bountysource',
   title: 'Bountysource',
-}))
+})
 
 t.create('bounties (valid)')
   .get('/team/mozilla-core/activity.json')
diff --git a/services/bower/bower-base.js b/services/bower/bower-base.js
index 12438ceff84c339301d89952b71b1177506d90d5..43a70542895cae8db6b61e31f830e9d2583ba7bf 100644
--- a/services/bower/bower-base.js
+++ b/services/bower/bower-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object()
   .keys({
@@ -19,7 +17,7 @@ const schema = Joi.object()
   })
   .required()
 
-module.exports = class BaseBowerService extends BaseJsonService {
+export default class BaseBowerService extends BaseJsonService {
   async fetch({ packageName }) {
     return this._requestJson({
       schema,
diff --git a/services/bower/bower-license.service.js b/services/bower/bower-license.service.js
index 2c454ba11ff6f40c7a6412064d02b34f4e60b02d..24476a20d60d23c5923705217cfda37024f9bd74 100644
--- a/services/bower/bower-license.service.js
+++ b/services/bower/bower-license.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { renderLicenseBadge } from '../licenses.js'
+import BaseBowerService from './bower-base.js'
 
-const { renderLicenseBadge } = require('../licenses')
-const BaseBowerService = require('./bower-base')
-
-module.exports = class BowerLicense extends BaseBowerService {
+export default class BowerLicense extends BaseBowerService {
   static category = 'license'
   static route = { base: 'bower/l', pattern: ':packageName' }
 
diff --git a/services/bower/bower-license.tester.js b/services/bower/bower-license.tester.js
index dc89bdaf962795ad13e104e32a7a7aa97c03ba88..18ba64b7602106a82a95b4aab48deb056513c8c8 100644
--- a/services/bower/bower-license.tester.js
+++ b/services/bower/bower-license.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('licence')
   .timeout(10000)
diff --git a/services/bower/bower-version.service.js b/services/bower/bower-version.service.js
index aa34d2ece85bfbc952f3d94c4d1235886931b65f..277d704021d883df71cb9582f695b1474fb470a5 100644
--- a/services/bower/bower-version.service.js
+++ b/services/bower/bower-version.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { InvalidResponse, redirector } = require('..')
-const BaseBowerService = require('./bower-base')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { InvalidResponse, redirector } from '../index.js'
+import BaseBowerService from './bower-base.js'
 
 const queryParamSchema = Joi.object({
   include_prereleases: Joi.equal(''),
@@ -57,4 +55,4 @@ const BowerVersionRedirect = redirector({
   dateAdded: new Date('2019-12-15'),
 })
 
-module.exports = { BowerVersion, BowerVersionRedirect }
+export { BowerVersion, BowerVersionRedirect }
diff --git a/services/bower/bower-version.tester.js b/services/bower/bower-version.tester.js
index 2f7129b438b91842ea1fedcfccdabbd04eccfe05..acccf3a756fec586d1710ea351b4a2b5055d75c4 100644
--- a/services/bower/bower-version.tester.js
+++ b/services/bower/bower-version.tester.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import Joi from 'joi'
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'BowerVersion',
   title: 'Bower Version',
   pathPrefix: '/bower',
-}))
+})
 
 const isBowerPrereleaseVersion = Joi.string().regex(
   /^v\d+(\.\d+)?(\.\d+)?(-?[.\w\d])+?$/
diff --git a/services/bstats/bstats-players.service.js b/services/bstats/bstats-players.service.js
index 855875c46754e1d0d20d8480b5d75c2652253e45..5b8eccd36f7410b1cd5d9f63afca43ab6373ac2b 100644
--- a/services/bstats/bstats-players.service.js
+++ b/services/bstats/bstats-players.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.array()
   .items(Joi.array().items(Joi.number().required(), Joi.number().required()))
   .required()
 
-module.exports = class BStatsPlayers extends BaseJsonService {
+export default class BStatsPlayers extends BaseJsonService {
   static category = 'other'
   static route = { base: 'bstats/players', pattern: ':pluginid' }
 
diff --git a/services/bstats/bstats-players.tester.js b/services/bstats/bstats-players.tester.js
index c4d7a7064e028b3ea6d75c71502d18db631d85d1..31b84be9fd645c2004caff39e29772ce967207e3 100644
--- a/services/bstats/bstats-players.tester.js
+++ b/services/bstats/bstats-players.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Players').get('/1.json').expectBadge({
   label: 'players',
diff --git a/services/bstats/bstats-servers.service.js b/services/bstats/bstats-servers.service.js
index 156458798b8098354e1f00138e8f90059b94f9c7..f90f95397acd62c695bf4ea042c3842f7621be47 100644
--- a/services/bstats/bstats-servers.service.js
+++ b/services/bstats/bstats-servers.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.array()
   .items(Joi.array().items(Joi.number().required(), Joi.number().required()))
   .required()
 
-module.exports = class BStatsServers extends BaseJsonService {
+export default class BStatsServers extends BaseJsonService {
   static category = 'other'
   static route = { base: 'bstats/servers', pattern: ':pluginid' }
 
diff --git a/services/bstats/bstats-servers.tester.js b/services/bstats/bstats-servers.tester.js
index 8fee06bcc6af294619532cd3740c41a235586417..c673891b67cc65239b685dc567d26cdde31035d0 100644
--- a/services/bstats/bstats-servers.tester.js
+++ b/services/bstats/bstats-servers.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Servers').get('/1.json').expectBadge({
   label: 'servers',
diff --git a/services/bugzilla/bugzilla.service.js b/services/bugzilla/bugzilla.service.js
index e0acfd608f5a0243378ca5843e00d107f954bf0d..aadc849eedd0df4a9b369add519da883435459fa 100644
--- a/services/bugzilla/bugzilla.service.js
+++ b/services/bugzilla/bugzilla.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const queryParamSchema = Joi.object({
   baseUrl: optionalUrl,
@@ -26,7 +24,7 @@ const documentation = `
 </p>
 `
 
-module.exports = class Bugzilla extends BaseJsonService {
+export default class Bugzilla extends BaseJsonService {
   static category = 'issue-tracking'
   static route = { base: 'bugzilla', pattern: ':bugNumber', queryParamSchema }
 
diff --git a/services/bugzilla/bugzilla.spec.js b/services/bugzilla/bugzilla.spec.js
index 64b50f94316bedbaa58daab9b7d58ebf1edc970c..114e29fa429e0022f7458f9e63b246a255f1c9a7 100644
--- a/services/bugzilla/bugzilla.spec.js
+++ b/services/bugzilla/bugzilla.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const Bugzilla = require('./bugzilla.service')
+import { test, given } from 'sazerac'
+import Bugzilla from './bugzilla.service.js'
 
 describe('getDisplayStatus function', function () {
   it('formats status correctly', async function () {
diff --git a/services/bugzilla/bugzilla.tester.js b/services/bugzilla/bugzilla.tester.js
index 3bdffa120a12f5803520c9f32f36d81b997f54c2..f3489bfee520dbea7db1cd0377b0fb751313cc93 100644
--- a/services/bugzilla/bugzilla.tester.js
+++ b/services/bugzilla/bugzilla.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const bzBugStatus = Joi.equal(
   'unconfirmed',
diff --git a/services/build-status.js b/services/build-status.js
index 4a088eee453742a6851bcca0ed5d5cd223c6ac80..9b33b6c2be907ebb9c4ed98b92e2a26e8e37aa01 100644
--- a/services/build-status.js
+++ b/services/build-status.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const Joi = require('joi')
+import Joi from 'joi'
 
 const greenStatuses = [
   'fixed',
@@ -74,4 +72,4 @@ function renderBuildStatusBadge({ label, status }) {
   }
 }
 
-module.exports = { isBuildStatus, renderBuildStatusBadge }
+export { isBuildStatus, renderBuildStatusBadge }
diff --git a/services/build-status.spec.js b/services/build-status.spec.js
index 69b19d216559978deeae6bd95b4306eb3adc10f1..07cf9be308657199775aacb45d68b4303fce5e89 100644
--- a/services/build-status.spec.js
+++ b/services/build-status.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { expect } = require('chai')
-const { test, given, forCases } = require('sazerac')
-const { renderBuildStatusBadge } = require('./build-status')
+import { expect } from 'chai'
+import { test, given, forCases } from 'sazerac'
+import { renderBuildStatusBadge } from './build-status.js'
 
 test(renderBuildStatusBadge, () => {
   given({ label: 'build', status: 'passed' }).expect({
diff --git a/services/buildkite/buildkite.service.js b/services/buildkite/buildkite.service.js
index 16b298b0cf9c4a589875d569820b6f11997e50af..c9cfb31648f7c2c2e327ea799a69bb3b1450a9f2 100644
--- a/services/buildkite/buildkite.service.js
+++ b/services/buildkite/buildkite.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { BaseJsonService } from '../index.js'
 
 // unknown is a valid 'other' status for Buildkite
 const schema = Joi.object({
   status: Joi.alternatives().try(isBuildStatus, Joi.equal('unknown')),
 }).required()
 
-module.exports = class Buildkite extends BaseJsonService {
+export default class Buildkite extends BaseJsonService {
   static category = 'build'
   static route = { base: 'buildkite', pattern: ':identifier/:branch*' }
 
diff --git a/services/buildkite/buildkite.tester.js b/services/buildkite/buildkite.tester.js
index bca5c506e74e6ff7f2552696c4af6e6e7e2420ce..d2819659f97d07431b6b3797e79969cbc0bbbe96 100644
--- a/services/buildkite/buildkite.tester.js
+++ b/services/buildkite/buildkite.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('buildkite invalid pipeline')
   .get('/unknown-identifier/unknown-branch.json')
diff --git a/services/bundlephobia/bundlephobia.service.js b/services/bundlephobia/bundlephobia.service.js
index fbc4eb5e6892fc6ff583674fe085903a99d826ab..5609e0880ab72fd891ef3e485ae81e0ef1350dfb 100644
--- a/services/bundlephobia/bundlephobia.service.js
+++ b/services/bundlephobia/bundlephobia.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const prettyBytes = require('pretty-bytes')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import prettyBytes from 'pretty-bytes'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   size: nonNegativeInteger,
@@ -12,7 +10,7 @@ const schema = Joi.object({
 
 const keywords = ['node', 'bundlephobia']
 
-module.exports = class Bundlephobia extends BaseJsonService {
+export default class Bundlephobia extends BaseJsonService {
   static category = 'size'
 
   static route = {
diff --git a/services/bundlephobia/bundlephobia.tester.js b/services/bundlephobia/bundlephobia.tester.js
index a4ec4d6f29ff9f90fc3e91a45b022125e526dba7..525bff0e026b32e005f164a209574031b6c8ebbb 100644
--- a/services/bundlephobia/bundlephobia.tester.js
+++ b/services/bundlephobia/bundlephobia.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isFileSize } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isFileSize } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const formats = {
   A: '/bundlephobia/:type/:package.:format',
diff --git a/services/categories.js b/services/categories.js
index fc45a33520bd7d39fa6c026f7977d5772b782576..a17077b32db2365e099308a28d1db2e6297c7eb7 100644
--- a/services/categories.js
+++ b/services/categories.js
@@ -1,6 +1,4 @@
-'use strict'
-
-module.exports = [
+export default [
   { id: 'build', name: 'Build', keywords: ['build'] },
   { id: 'coverage', name: 'Code Coverage', keywords: ['coverage'] },
   { id: 'analysis', name: 'Analysis', keywords: ['analysis'] },
diff --git a/services/cauditor/cauditor.service.js b/services/cauditor/cauditor.service.js
index 64cfbf49dd2f3a0feed9905ed257383418662849..85b64cab521091c3ce779772b8de8abf0393f90e 100644
--- a/services/cauditor/cauditor.service.js
+++ b/services/cauditor/cauditor.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'other',
   route: {
     base: 'cauditor',
diff --git a/services/cauditor/cauditor.tester.js b/services/cauditor/cauditor.tester.js
index aa23655b92df4eff9dab625a47cc56485c1124e1..14c96f7e3e1e6d90e2f33155c5d9ddb00af8829e 100644
--- a/services/cauditor/cauditor.tester.js
+++ b/services/cauditor/cauditor.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'cauditor',
   title: 'Cauditor',
-}))
+})
 
 t.create('no longer available')
   .get('/mi/matthiasmullie/scrapbook/master.json')
diff --git a/services/cdnjs/cdnjs.service.js b/services/cdnjs/cdnjs.service.js
index 4e3503de27f1ed7c276e30f9a8ab51d249b620ac..d1d9e967f59b2350d6023400e4f0b47badec8e3f 100644
--- a/services/cdnjs/cdnjs.service.js
+++ b/services/cdnjs/cdnjs.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const cdnjsSchema = Joi.object({
   // optional due to non-standard 'not found' condition
   version: Joi.string(),
 }).required()
 
-module.exports = class Cdnjs extends BaseJsonService {
+export default class Cdnjs extends BaseJsonService {
   static category = 'version'
   static route = { base: 'cdnjs/v', pattern: ':library' }
 
diff --git a/services/cdnjs/cdnjs.tester.js b/services/cdnjs/cdnjs.tester.js
index 6f7a3139d24ce7a08569378b44e46d539f329247..a2da7ec37576cdd28078eb47c9b8fa3d4898933d 100644
--- a/services/cdnjs/cdnjs.tester.js
+++ b/services/cdnjs/cdnjs.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusTripleDottedVersion } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusTripleDottedVersion } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('cdnjs (valid)').get('/jquery.json').expectBadge({
   label: 'cdnjs',
diff --git a/services/check-services.spec.js b/services/check-services.spec.js
index a564c340a3e50838ffdf10650c4fce5e59fbaecc..8ee0365156ac78b6abe1538cf36f52480341a131 100644
--- a/services/check-services.spec.js
+++ b/services/check-services.spec.js
@@ -1,18 +1,13 @@
-'use strict'
-
-const {
-  checkNames,
-  collectDefinitions,
-} = require('../core/base-service/loader')
+import { checkNames, collectDefinitions } from '../core/base-service/loader.js'
 
 // When these tests fail, they will throw AssertionErrors. Wrapping them in an
 // `expect().not.to.throw()` makes the error output unreadable.
 
-it('Services have unique names', function () {
+it('Services have unique names', async function () {
   this.timeout(30000)
-  checkNames()
+  await checkNames()
 })
 
-it('Can collect the service definitions', function () {
-  collectDefinitions()
+it('Can collect the service definitions', async function () {
+  await collectDefinitions()
 })
diff --git a/services/chocolatey/chocolatey.service.js b/services/chocolatey/chocolatey.service.js
index c03f3d1a7cda87517767b341755b618daaee36cf..584c6c9f14c50d9c710455050e4a04d43aa12ed8 100644
--- a/services/chocolatey/chocolatey.service.js
+++ b/services/chocolatey/chocolatey.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { createServiceFamily } from '../nuget/nuget-v2-service-family.js'
 
-const { createServiceFamily } = require('../nuget/nuget-v2-service-family')
-
-module.exports = createServiceFamily({
+export default createServiceFamily({
   defaultLabel: 'chocolatey',
   serviceBaseUrl: 'chocolatey',
   apiBaseUrl: 'https://www.chocolatey.org/api/v2',
diff --git a/services/chocolatey/chocolatey.tester.js b/services/chocolatey/chocolatey.tester.js
index f7ac3e99100856c15f03aff8716e2038876a0a3e..6c2a3a18decd159e14c9e39abc1590170cdb8b63 100644
--- a/services/chocolatey/chocolatey.tester.js
+++ b/services/chocolatey/chocolatey.tester.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const {
+import {
   isMetric,
   isVPlusDottedVersionNClauses,
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators')
-const { ServiceTester } = require('../tester')
+} from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
 
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'chocolatey',
   title: 'Chocolatey',
-}))
+})
 
 // downloads
 
diff --git a/services/chrome-web-store/chrome-web-store-base.js b/services/chrome-web-store/chrome-web-store-base.js
index ac0049d37295cbb537db9a3ce5cddfd4e5eb2169..77e917c2b71a4f9690e5f791053e2e04ad3cae6d 100644
--- a/services/chrome-web-store/chrome-web-store-base.js
+++ b/services/chrome-web-store/chrome-web-store-base.js
@@ -1,10 +1,8 @@
-'use strict'
+import ChromeWebStore from 'webextension-store-meta/lib/chrome-web-store/index.js'
+import checkErrorResponse from '../../core/base-service/check-error-response.js'
+import { BaseService, Inaccessible } from '../index.js'
 
-const ChromeWebStore = require('webextension-store-meta/lib/chrome-web-store')
-const checkErrorResponse = require('../../core/base-service/check-error-response')
-const { BaseService, Inaccessible } = require('..')
-
-module.exports = class BaseChromeWebStoreService extends BaseService {
+export default class BaseChromeWebStoreService extends BaseService {
   async fetch({ storeId }) {
     try {
       return await ChromeWebStore.load({ id: storeId })
diff --git a/services/chrome-web-store/chrome-web-store-price.service.js b/services/chrome-web-store/chrome-web-store-price.service.js
index e2faa0d67976f0124797b6dd668946f5b8fee808..99068389d04b6ba01a96e74dbf07e52d0564c86f 100644
--- a/services/chrome-web-store/chrome-web-store-price.service.js
+++ b/services/chrome-web-store/chrome-web-store-price.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { currencyFromCode } from '../text-formatters.js'
+import { NotFound } from '../index.js'
+import BaseChromeWebStoreService from './chrome-web-store-base.js'
 
-const { currencyFromCode } = require('../text-formatters')
-const { NotFound } = require('..')
-const BaseChromeWebStoreService = require('./chrome-web-store-base')
-
-module.exports = class ChromeWebStorePrice extends BaseChromeWebStoreService {
+export default class ChromeWebStorePrice extends BaseChromeWebStoreService {
   static category = 'funding'
   static route = { base: 'chrome-web-store/price', pattern: ':storeId' }
 
diff --git a/services/chrome-web-store/chrome-web-store-price.tester.js b/services/chrome-web-store/chrome-web-store-price.tester.js
index cc2ffaa587f181b4ae3677e3403b1be7ef015593..8c017faf5774c0702b86971315c6a38a56c170c0 100644
--- a/services/chrome-web-store/chrome-web-store-price.tester.js
+++ b/services/chrome-web-store/chrome-web-store-price.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Price')
   .get('/alhjnofcnnpeaphgeakdhkebafjcpeae.json')
diff --git a/services/chrome-web-store/chrome-web-store-rating.service.js b/services/chrome-web-store/chrome-web-store-rating.service.js
index 95bbe0009bef5372d30389f4945e7ece335cedac..5c273b5357961d2e96a4c225ba9455db0e5a7052 100644
--- a/services/chrome-web-store/chrome-web-store-rating.service.js
+++ b/services/chrome-web-store/chrome-web-store-rating.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { floorCount: floorCountColor } = require('../color-formatters')
-const { metric, starRating } = require('../text-formatters')
-const { NotFound } = require('..')
-const BaseChromeWebStoreService = require('./chrome-web-store-base')
+import { floorCount as floorCountColor } from '../color-formatters.js'
+import { metric, starRating } from '../text-formatters.js'
+import { NotFound } from '../index.js'
+import BaseChromeWebStoreService from './chrome-web-store-base.js'
 
 class BaseChromeWebStoreRating extends BaseChromeWebStoreService {
   static category = 'rating'
@@ -108,7 +106,7 @@ class ChromeWebStoreRatingStars extends BaseChromeWebStoreRating {
   }
 }
 
-module.exports = {
+export {
   ChromeWebStoreRating,
   ChromeWebStoreRatingCount,
   ChromeWebStoreRatingStars,
diff --git a/services/chrome-web-store/chrome-web-store-rating.tester.js b/services/chrome-web-store/chrome-web-store-rating.tester.js
index bf5d670442cc642504236bc985c9b7e9eb96abfa..3d4f20c1d5f32020161e0cc14e30f875db28f3cc 100644
--- a/services/chrome-web-store/chrome-web-store-rating.tester.js
+++ b/services/chrome-web-store/chrome-web-store-rating.tester.js
@@ -1,14 +1,12 @@
-'use strict'
+import Joi from 'joi'
+import { isStarRating } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
 
-const Joi = require('joi')
-const { isStarRating } = require('../test-validators')
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'ChromeWebStoreRating',
   title: 'Chrome Web Store Rating',
   pathPrefix: '/chrome-web-store',
-}))
+})
 
 t.create('Rating')
   .get('/rating/alhjnofcnnpeaphgeakdhkebafjcpeae.json')
diff --git a/services/chrome-web-store/chrome-web-store-users.service.js b/services/chrome-web-store/chrome-web-store-users.service.js
index 12f5130e9aabfe6e45653eb72e557eb9cb7e4fd6..7e8341c9694e2eb8d07399affe8ef86ef04d8a51 100644
--- a/services/chrome-web-store/chrome-web-store-users.service.js
+++ b/services/chrome-web-store/chrome-web-store-users.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const { redirector, NotFound } = require('..')
-const BaseChromeWebStoreService = require('./chrome-web-store-base')
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import { redirector, NotFound } from '../index.js'
+import BaseChromeWebStoreService from './chrome-web-store-base.js'
 
 class ChromeWebStoreUsers extends BaseChromeWebStoreService {
   static category = 'downloads'
@@ -46,7 +44,4 @@ const ChromeWebStoreDownloads = redirector({
   dateAdded: new Date('2019-02-27'),
 })
 
-module.exports = {
-  ChromeWebStoreDownloads,
-  ChromeWebStoreUsers,
-}
+export { ChromeWebStoreDownloads, ChromeWebStoreUsers }
diff --git a/services/chrome-web-store/chrome-web-store-users.tester.js b/services/chrome-web-store/chrome-web-store-users.tester.js
index a0f3f5cef538c78f4058e49076f5c0048be49687..d00b6c3c13217f8dbba59e0b32ddd5140da6d4e5 100644
--- a/services/chrome-web-store/chrome-web-store-users.tester.js
+++ b/services/chrome-web-store/chrome-web-store-users.tester.js
@@ -1,13 +1,11 @@
-'use strict'
+import { isMetric } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
 
-const { isMetric } = require('../test-validators')
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'ChromeWebStoreUsers',
   title: 'Chrome Web Store Users',
   pathPrefix: '/chrome-web-store',
-}))
+})
 
 t.create('Downloads (redirect)')
   .get('/d/alhjnofcnnpeaphgeakdhkebafjcpeae.svg')
diff --git a/services/chrome-web-store/chrome-web-store-version.service.js b/services/chrome-web-store/chrome-web-store-version.service.js
index ea9082779b37dcfa154444c480918caedc9c3d51..e9e42af9596a07f6f1e96704d0696be22aabf246 100644
--- a/services/chrome-web-store/chrome-web-store-version.service.js
+++ b/services/chrome-web-store/chrome-web-store-version.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import { NotFound } from '../index.js'
+import BaseChromeWebStoreService from './chrome-web-store-base.js'
 
-const { renderVersionBadge } = require('../version')
-const { NotFound } = require('..')
-const BaseChromeWebStoreService = require('./chrome-web-store-base')
-
-module.exports = class ChromeWebStoreVersion extends BaseChromeWebStoreService {
+export default class ChromeWebStoreVersion extends BaseChromeWebStoreService {
   static category = 'version'
   static route = { base: 'chrome-web-store/v', pattern: ':storeId' }
 
diff --git a/services/chrome-web-store/chrome-web-store-version.tester.js b/services/chrome-web-store/chrome-web-store-version.tester.js
index 09d49442d4059adf5d5b1609e19d1b26ee2de8cf..cccf0b95e14be2b1363af6faedb1238034a7db85 100644
--- a/services/chrome-web-store/chrome-web-store-version.tester.js
+++ b/services/chrome-web-store/chrome-web-store-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Version').get('/alhjnofcnnpeaphgeakdhkebafjcpeae.json').expectBadge({
   label: 'chrome web store',
diff --git a/services/cii-best-practices/cii-best-practices.service.js b/services/cii-best-practices/cii-best-practices.service.js
index 7a38690077940e132bf7f91770203060883b5606..4aefbf8af72a56dfb25d4f73b6681323a91faf59 100644
--- a/services/cii-best-practices/cii-best-practices.service.js
+++ b/services/cii-best-practices/cii-best-practices.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { colorScale, coveragePercentage } = require('../color-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { colorScale, coveragePercentage } from '../color-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   badge_level: Joi.string().required(),
@@ -30,7 +28,7 @@ const summaryColorScale = colorScale(
   ]
 )
 
-module.exports = class CIIBestPracticesService extends BaseJsonService {
+export default class CIIBestPracticesService extends BaseJsonService {
   static category = 'analysis'
   static route = {
     base: 'cii',
diff --git a/services/cii-best-practices/cii-best-practices.tester.js b/services/cii-best-practices/cii-best-practices.tester.js
index b90897663780626d98eec73e14cfe021cfc2bcc9..ba62ffaa11fa103cedc96b2ea44ceca0764ad398 100644
--- a/services/cii-best-practices/cii-best-practices.tester.js
+++ b/services/cii-best-practices/cii-best-practices.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('level known project')
   .get(`/level/1.json`)
diff --git a/services/circleci/circleci.service.js b/services/circleci/circleci.service.js
index 84efe01135c19b1cd330472ffa947876bb759a00..2087af453136aa5043c1840ab1ba78db8ce8ee1c 100644
--- a/services/circleci/circleci.service.js
+++ b/services/circleci/circleci.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { BaseSvgScrapingService, redirector } = require('..')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { BaseSvgScrapingService, redirector } from '../index.js'
 
 const circleSchema = Joi.object({ message: isBuildStatus }).required()
 const queryParamSchema = Joi.object({ token: Joi.string() }).required()
@@ -98,4 +96,4 @@ const legacyRoutes = [
   }),
 ]
 
-module.exports = [...legacyRoutes, CircleCi]
+export default { ...legacyRoutes, CircleCi }
diff --git a/services/circleci/circleci.tester.js b/services/circleci/circleci.tester.js
index ecdded2b10e9af814aa8327b9f1ca904cdca1275..8cbda6b312e33dd5af8ae35256c8e78043e4d1a5 100644
--- a/services/circleci/circleci.tester.js
+++ b/services/circleci/circleci.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { isBuildStatus } from '../build-status.js'
+import { ServiceTester } from '../tester.js'
 
-const { isBuildStatus } = require('../build-status')
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'circleci',
   title: 'Circle CI',
-}))
+})
 
 t.create('circle ci (valid, without branch)')
   .get('/build/gh/RedSparr0w/node-csgo-parser.json')
diff --git a/services/cirrus/cirrus.service.js b/services/cirrus/cirrus.service.js
index 7e4b9d07bbaeba44407052972f999ea8b8218fe2..437f2d630ab3c2a859bae2e359d36599cce98588 100644
--- a/services/cirrus/cirrus.service.js
+++ b/services/cirrus/cirrus.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   subject: Joi.string().required(),
@@ -15,7 +13,7 @@ const queryParamSchema = Joi.object({
   script: Joi.string(),
 }).required()
 
-module.exports = class Cirrus extends BaseJsonService {
+export default class Cirrus extends BaseJsonService {
   static category = 'build'
   static route = {
     base: 'cirrus',
diff --git a/services/cirrus/cirrus.tester.js b/services/cirrus/cirrus.tester.js
index a23d9cc8ce8d4e86653e5627e938550169642c5c..a3f6e396fb01b067759a7d282c39c7c8c5689393 100644
--- a/services/cirrus/cirrus.tester.js
+++ b/services/cirrus/cirrus.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('cirrus bad repo')
   .get('/github/unknown-identifier/unknown-repo.json')
diff --git a/services/clojars/clojars-base.js b/services/clojars/clojars-base.js
index 9a89c9e6ddadfb01849d627b077d82990e376a7c..15996eebb37974f38e8e828ebb6f91725efbcbfe 100644
--- a/services/clojars/clojars-base.js
+++ b/services/clojars/clojars-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const clojarsSchema = Joi.object({
   downloads: nonNegativeInteger,
@@ -21,4 +19,4 @@ class BaseClojarsService extends BaseJsonService {
   }
 }
 
-module.exports = { BaseClojarsService }
+export { BaseClojarsService }
diff --git a/services/clojars/clojars-downloads.service.js b/services/clojars/clojars-downloads.service.js
index 3925de5f1e74abf5048a949bc491f88a891f256a..1a5932354daa715ee8199c94774d91adfe2ac93f 100644
--- a/services/clojars/clojars-downloads.service.js
+++ b/services/clojars/clojars-downloads.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { downloadCount as downloadsColor } from '../color-formatters.js'
+import { BaseClojarsService } from './clojars-base.js'
 
-const { metric } = require('../text-formatters')
-const { downloadCount: downloadsColor } = require('../color-formatters')
-const { BaseClojarsService } = require('./clojars-base')
-
-module.exports = class ClojarsDownloads extends BaseClojarsService {
+export default class ClojarsDownloads extends BaseClojarsService {
   static category = 'downloads'
   static route = { base: 'clojars/dt', pattern: ':clojar+' }
 
diff --git a/services/clojars/clojars-downloads.tester.js b/services/clojars/clojars-downloads.tester.js
index 94ec0aad260b4299b0feb85287643cfe6553b46a..afb116f46d3e0f78a48e622d76c2ffe6ba9fba1e 100644
--- a/services/clojars/clojars-downloads.tester.js
+++ b/services/clojars/clojars-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('clojars downloads (valid)').get('/prismic.json').expectBadge({
   label: 'downloads',
diff --git a/services/clojars/clojars-version.service.js b/services/clojars/clojars-version.service.js
index 048161a8ff9ef40137202c4cba00a9b43b623bfd..344eddc90110dbb1f15a71e5f27ac4b9525ea770 100644
--- a/services/clojars/clojars-version.service.js
+++ b/services/clojars/clojars-version.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { version: versionColor } = require('../color-formatters')
-const { redirector } = require('..')
-const { BaseClojarsService } = require('./clojars-base')
+import Joi from 'joi'
+import { version as versionColor } from '../color-formatters.js'
+import { redirector } from '../index.js'
+import { BaseClojarsService } from './clojars-base.js'
 
 const queryParamSchema = Joi.object({
   include_prereleases: Joi.equal(''),
@@ -63,4 +61,4 @@ const ClojarsVersionRedirector = redirector({
   dateAdded: new Date('2019-12-15'),
 })
 
-module.exports = { ClojarsVersionService, ClojarsVersionRedirector }
+export { ClojarsVersionService, ClojarsVersionRedirector }
diff --git a/services/clojars/clojars-version.tester.js b/services/clojars/clojars-version.tester.js
index ee495b9c7e77abe3abba8cf7277a7c0252c5b523..5d7e23cd35844f90f21f1e31c2beb1327864cd83 100644
--- a/services/clojars/clojars-version.tester.js
+++ b/services/clojars/clojars-version.tester.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'ClojarsVersion',
   title: 'Clojars Version',
   pathPrefix: '/clojars',
-}))
+})
 
 t.create('clojars version (valid)')
   .get('/v/prismic.json')
diff --git a/services/cocoapods/cocoapods-apps.service.js b/services/cocoapods/cocoapods-apps.service.js
index 277cc6a43cdefce51b6847f23e16034e0085677d..b0b65a80bd5db07667a354d22e505b93cc349c15 100644
--- a/services/cocoapods/cocoapods-apps.service.js
+++ b/services/cocoapods/cocoapods-apps.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   name: 'CocoapodsApps',
   category: 'other',
   route: {
diff --git a/services/cocoapods/cocoapods-apps.tester.js b/services/cocoapods/cocoapods-apps.tester.js
index 07c8e865211610c014f86b7cc5483a0cdc925aa0..cba658950f4010ed3dc2aec7aa6d9c3620a897b1 100644
--- a/services/cocoapods/cocoapods-apps.tester.js
+++ b/services/cocoapods/cocoapods-apps.tester.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'CocoapodsApps',
   title: 'CocoapodsApps',
   pathPrefix: '/cocoapods',
-}))
+})
 
 t.create('apps (valid, weekly)')
   .get('/aw/AFNetworking.json')
diff --git a/services/cocoapods/cocoapods-base.js b/services/cocoapods/cocoapods-base.js
index e0ae168661fa0c1bbe0a0989b93ee4a5a36c35aa..98bcbf49ded2c899fb650aecd5315424322a8b50 100644
--- a/services/cocoapods/cocoapods-base.js
+++ b/services/cocoapods/cocoapods-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   version: Joi.string().required(),
@@ -16,7 +14,7 @@ const schema = Joi.object({
   platforms: Joi.object().default({ ios: '5.0', osx: '10.7' }),
 }).required()
 
-module.exports = class BaseCocoaPodsService extends BaseJsonService {
+export default class BaseCocoaPodsService extends BaseJsonService {
   async fetch({ spec }) {
     return this._requestJson({
       schema,
diff --git a/services/cocoapods/cocoapods-docs.service.js b/services/cocoapods/cocoapods-docs.service.js
index 3f942a24ffbbab1d694e422f7dde005ff193afb0..a25403ad65efb5776fce15a08181b66afd7d250d 100644
--- a/services/cocoapods/cocoapods-docs.service.js
+++ b/services/cocoapods/cocoapods-docs.service.js
@@ -1,10 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const {
-  coveragePercentage: coveragePercentageColor,
-} = require('../color-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { coveragePercentage as coveragePercentageColor } from '../color-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   cocoadocs: Joi.object({
@@ -12,7 +8,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class CocoapodsDocs extends BaseJsonService {
+export default class CocoapodsDocs extends BaseJsonService {
   static category = 'analysis'
   static route = { base: 'cocoapods/metrics/doc-percent', pattern: ':spec' }
 
diff --git a/services/cocoapods/cocoapods-docs.tester.js b/services/cocoapods/cocoapods-docs.tester.js
index 7fe160e207cf376ffe74c732e2899674034f195d..746505bc21e7f124bc2fbc2a232f94efa215f302 100644
--- a/services/cocoapods/cocoapods-docs.tester.js
+++ b/services/cocoapods/cocoapods-docs.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('doc percent (valid)').get('/AFNetworking.json').expectBadge({
   label: 'docs',
diff --git a/services/cocoapods/cocoapods-downloads.service.js b/services/cocoapods/cocoapods-downloads.service.js
index c0caf8da6be81ad43a64cf86173048d14bc0048a..e54056deed34ec3dbe09b42eedec17ec38538491 100644
--- a/services/cocoapods/cocoapods-downloads.service.js
+++ b/services/cocoapods/cocoapods-downloads.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   name: 'CocoapodsDownloads',
   category: 'downloads',
   route: {
diff --git a/services/cocoapods/cocoapods-downloads.tester.js b/services/cocoapods/cocoapods-downloads.tester.js
index 8e66b7470ed5b0dcfe27f749ef32edce96c800e9..b7dbf18ba8fbf78d3baf872d012604315825471a 100644
--- a/services/cocoapods/cocoapods-downloads.tester.js
+++ b/services/cocoapods/cocoapods-downloads.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'CocoapodsDownloads',
   title: 'CocoapodsDownloads',
   pathPrefix: '/cocoapods',
-}))
+})
 
 t.create('downloads (valid, monthly)')
   .get('/dm/AFNetworking.json')
diff --git a/services/cocoapods/cocoapods-license.service.js b/services/cocoapods/cocoapods-license.service.js
index 65d3c02bc33ddeb51c3e0ea8a799fcb44d729123..95f401b054c8f9b6d509ef92931a0279e108b2ba 100644
--- a/services/cocoapods/cocoapods-license.service.js
+++ b/services/cocoapods/cocoapods-license.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import BaseCocoaPodsService from './cocoapods-base.js'
 
-const BaseCocoaPodsService = require('./cocoapods-base')
-
-module.exports = class CocoapodsLicense extends BaseCocoaPodsService {
+export default class CocoapodsLicense extends BaseCocoaPodsService {
   static category = 'license'
   static route = { base: 'cocoapods/l', pattern: ':spec' }
 
diff --git a/services/cocoapods/cocoapods-license.tester.js b/services/cocoapods/cocoapods-license.tester.js
index 3f6c633192482f2bcbd5eb9031dcfa287e25c506..c4eba4f9ff26e0b912ed45ffa25739f53e82a560 100644
--- a/services/cocoapods/cocoapods-license.tester.js
+++ b/services/cocoapods/cocoapods-license.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('license (valid)')
   .get('/AFNetworking.json')
diff --git a/services/cocoapods/cocoapods-platform.service.js b/services/cocoapods/cocoapods-platform.service.js
index dc2b4fb4d16ff443faa252bd93ceedcf71f16c5c..83cb468d84191c14b3cbc99a6ddf37a671afc8da 100644
--- a/services/cocoapods/cocoapods-platform.service.js
+++ b/services/cocoapods/cocoapods-platform.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import BaseCocoaPodsService from './cocoapods-base.js'
 
-const BaseCocoaPodsService = require('./cocoapods-base')
-
-module.exports = class CocoapodsPlatform extends BaseCocoaPodsService {
+export default class CocoapodsPlatform extends BaseCocoaPodsService {
   static category = 'platform-support'
   static route = { base: 'cocoapods/p', pattern: ':spec' }
 
diff --git a/services/cocoapods/cocoapods-platform.tester.js b/services/cocoapods/cocoapods-platform.tester.js
index c05aa58bb5b0e6167e327b463f31b9fd2b2383a3..f2d176f97355f0f6c97cc9a1373648a4eda73972 100644
--- a/services/cocoapods/cocoapods-platform.tester.js
+++ b/services/cocoapods/cocoapods-platform.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isPlatform = Joi.string().regex(
   /^(osx|ios|tvos|watchos)( \| (osx|ios|tvos|watchos))*$/
diff --git a/services/cocoapods/cocoapods-version.service.js b/services/cocoapods/cocoapods-version.service.js
index f82fccf2cb85df3cb4211f960f495fa1061dbcc6..bc55f8306361d14b166470cea81448dfc831e958 100644
--- a/services/cocoapods/cocoapods-version.service.js
+++ b/services/cocoapods/cocoapods-version.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import BaseCocoaPodsService from './cocoapods-base.js'
 
-const { renderVersionBadge } = require('../version')
-const BaseCocoaPodsService = require('./cocoapods-base')
-
-module.exports = class CocoapodsVersion extends BaseCocoaPodsService {
+export default class CocoapodsVersion extends BaseCocoaPodsService {
   static category = 'version'
   static route = { base: 'cocoapods/v', pattern: ':spec' }
 
diff --git a/services/cocoapods/cocoapods-version.tester.js b/services/cocoapods/cocoapods-version.tester.js
index 468ea4fa2ff8261963973d960d5041b7d59de048..e4e934abf569365905c156fbe27e225409d9297f 100644
--- a/services/cocoapods/cocoapods-version.tester.js
+++ b/services/cocoapods/cocoapods-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('version (valid)').get('/AFNetworking.json').expectBadge({
   label: 'pod',
diff --git a/services/codacy/codacy-coverage.service.js b/services/codacy/codacy-coverage.service.js
index 3c0b4b082e766caa215ed41215d6e07ffcc06924..04da6a9b74774d933d23a42ac23568621a39b705 100644
--- a/services/codacy/codacy-coverage.service.js
+++ b/services/codacy/codacy-coverage.service.js
@@ -1,11 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const {
-  coveragePercentage: coveragePercentageColor,
-} = require('../color-formatters')
-const { BaseSvgScrapingService } = require('..')
-const { NotFound } = require('..')
+import Joi from 'joi'
+import { coveragePercentage as coveragePercentageColor } from '../color-formatters.js'
+import { BaseSvgScrapingService, NotFound } from '../index.js'
 
 const schema = Joi.object({
   message: Joi.alternatives()
@@ -13,7 +8,7 @@ const schema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class CodacyCoverage extends BaseSvgScrapingService {
+export default class CodacyCoverage extends BaseSvgScrapingService {
   static category = 'coverage'
   static route = { base: 'codacy/coverage', pattern: ':projectId/:branch*' }
 
diff --git a/services/codacy/codacy-coverage.tester.js b/services/codacy/codacy-coverage.tester.js
index 580018b2b49f04b6c0d37991a2d77e2e7b0e790c..ab0c24fed26a7c96c77bd1bd559a5bbc98838aeb 100644
--- a/services/codacy/codacy-coverage.tester.js
+++ b/services/codacy/codacy-coverage.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Coverage').get('/59d607d0e311408885e418004068ea58.json').expectBadge({
   label: 'coverage',
diff --git a/services/codacy/codacy-grade.service.js b/services/codacy/codacy-grade.service.js
index 7f417bd26e771eac5d75c7400f10f109068cdbfe..4c4d35d76d96a8187e35800c1804d59678fa8bd0 100644
--- a/services/codacy/codacy-grade.service.js
+++ b/services/codacy/codacy-grade.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseSvgScrapingService } = require('..')
-const { codacyGrade } = require('./codacy-helpers')
+import Joi from 'joi'
+import { BaseSvgScrapingService } from '../index.js'
+import { codacyGrade } from './codacy-helpers.js'
 
 const schema = Joi.object({ message: codacyGrade }).required()
 
-module.exports = class CodacyGrade extends BaseSvgScrapingService {
+export default class CodacyGrade extends BaseSvgScrapingService {
   static category = 'analysis'
   static route = { base: 'codacy/grade', pattern: ':projectId/:branch*' }
 
diff --git a/services/codacy/codacy-grade.tester.js b/services/codacy/codacy-grade.tester.js
index cc8020e2104de943418aee89a9b98507ad724b33..be97c7eae00c51a95f8eb3f49623ebb9341bf9b9 100644
--- a/services/codacy/codacy-grade.tester.js
+++ b/services/codacy/codacy-grade.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { codacyGrade } = require('./codacy-helpers')
+import { createServiceTester } from '../tester.js'
+import { codacyGrade } from './codacy-helpers.js'
+export const t = await createServiceTester()
 
 t.create('Code quality')
   .get('/e27821fb6289410b8f58338c7e0bc686.json')
diff --git a/services/codacy/codacy-helpers.js b/services/codacy/codacy-helpers.js
index 9c222194c34c9752ad5ef1571e8e4c1f88890760..8408c492ad7e00b900b9fe037106253ed9ce90d3 100644
--- a/services/codacy/codacy-helpers.js
+++ b/services/codacy/codacy-helpers.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
+import Joi from 'joi'
 
 const codacyGrade = Joi.equal('A', 'B', 'C', 'D', 'E', 'F')
 
-module.exports = { codacyGrade }
+export { codacyGrade }
diff --git a/services/codeclimate/codeclimate-analysis-redirector.service.js b/services/codeclimate/codeclimate-analysis-redirector.service.js
index e70062db79129ba94a84854cccea884b837ecf76..d2b68b56defce43f624f6fce40ab6cedb7bab6c3 100644
--- a/services/codeclimate/codeclimate-analysis-redirector.service.js
+++ b/services/codeclimate/codeclimate-analysis-redirector.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   // http://github.com/badges/shields/issues/1387
   // https://github.com/badges/shields/pull/3320#issuecomment-483795000
   redirector({
diff --git a/services/codeclimate/codeclimate-analysis-redirector.tester.js b/services/codeclimate/codeclimate-analysis-redirector.tester.js
index 2e6eb7e42c8fe0a7d8f82421f69e1c585c38b1a3..38531168c81bc917d53c9d730bb7d4962695b80b 100644
--- a/services/codeclimate/codeclimate-analysis-redirector.tester.js
+++ b/services/codeclimate/codeclimate-analysis-redirector.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'CodeclimateCoverageRedirector',
   title: 'Code Climate Coverage Redirector',
   pathPrefix: '/codeclimate',
-}))
+})
 
 t.create('Maintainability letter alias')
   .get('/maintainability-letter/jekyll/jekyll.svg')
diff --git a/services/codeclimate/codeclimate-analysis.service.js b/services/codeclimate/codeclimate-analysis.service.js
index 2de65a67a1be47016d7b27f45194b4d37cc39e48..811ceb6db1f97fcdfe54e0938ffebd809b28cb6e 100644
--- a/services/codeclimate/codeclimate-analysis.service.js
+++ b/services/codeclimate/codeclimate-analysis.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { colorScale, letterScore } = require('../color-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService, NotFound } = require('..')
-const { keywords, isLetterGrade, fetchRepo } = require('./codeclimate-common')
+import Joi from 'joi'
+import { colorScale, letterScore } from '../color-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService, NotFound } from '../index.js'
+import { keywords, isLetterGrade, fetchRepo } from './codeclimate-common.js'
 
 const schema = Joi.object({
   data: Joi.object({
@@ -87,7 +85,7 @@ const variantMap = {
   },
 }
 
-module.exports = class CodeclimateAnalysis extends BaseJsonService {
+export default class CodeclimateAnalysis extends BaseJsonService {
   static category = 'analysis'
   static route = {
     base: 'codeclimate',
diff --git a/services/codeclimate/codeclimate-analysis.tester.js b/services/codeclimate/codeclimate-analysis.tester.js
index 33ee8fd13156a7f8b3809c327bb59851389292a1..9bab1043d13103fd77308568354f3c3f590cacae 100644
--- a/services/codeclimate/codeclimate-analysis.tester.js
+++ b/services/codeclimate/codeclimate-analysis.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // Examples for this service can be found through the explore page:
 // https://codeclimate.com/explore
diff --git a/services/codeclimate/codeclimate-common.js b/services/codeclimate/codeclimate-common.js
index 94c441a5ca5e236adc4bbbba345d09b0ee75301d..b987317b0bf1d38e09e533e226d1d51ab5fd61c1 100644
--- a/services/codeclimate/codeclimate-common.js
+++ b/services/codeclimate/codeclimate-common.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { NotFound } = require('..')
+import Joi from 'joi'
+import { NotFound } from '../index.js'
 
 const keywords = ['codeclimate']
 
@@ -44,8 +42,4 @@ async function fetchRepo(serviceInstance, { user, repo }) {
   return repoInfo
 }
 
-module.exports = {
-  keywords,
-  isLetterGrade,
-  fetchRepo,
-}
+export { keywords, isLetterGrade, fetchRepo }
diff --git a/services/codeclimate/codeclimate-coverage-redirector.service.js b/services/codeclimate/codeclimate-coverage-redirector.service.js
index 57b440c855aaf31e28a8c543310ea4b0a9320f15..49997961887ad4da86e2ea1cd0b7d18270499543 100644
--- a/services/codeclimate/codeclimate-coverage-redirector.service.js
+++ b/services/codeclimate/codeclimate-coverage-redirector.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   // http://github.com/badges/shields/issues/1387
   // https://github.com/badges/shields/pull/3320#issuecomment-483795000
   redirector({
diff --git a/services/codeclimate/codeclimate-coverage-redirector.tester.js b/services/codeclimate/codeclimate-coverage-redirector.tester.js
index 2ea8184631a30d7befcb43010f38e498915f9bfb..cc0ead2a188ee45abf8ca63e83f95aa39fe0c846 100644
--- a/services/codeclimate/codeclimate-coverage-redirector.tester.js
+++ b/services/codeclimate/codeclimate-coverage-redirector.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'CodeclimateCoverageRedirector',
   title: 'Code Climate Coverage Redirector',
   pathPrefix: '/codeclimate',
-}))
+})
 
 t.create('Top-level coverage shortcut')
   .get('/jekyll/jekyll.svg')
diff --git a/services/codeclimate/codeclimate-coverage.service.js b/services/codeclimate/codeclimate-coverage.service.js
index a58bce7b6db7f524a4f80a3628ba24c1d68f613c..9b7f81eb8a4166ffb6eb423e079f10539cef4f3f 100644
--- a/services/codeclimate/codeclimate-coverage.service.js
+++ b/services/codeclimate/codeclimate-coverage.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { coveragePercentage, letterScore } = require('../color-formatters')
-const { BaseJsonService, NotFound } = require('..')
-const { keywords, isLetterGrade, fetchRepo } = require('./codeclimate-common')
+import Joi from 'joi'
+import { coveragePercentage, letterScore } from '../color-formatters.js'
+import { BaseJsonService, NotFound } from '../index.js'
+import { keywords, isLetterGrade, fetchRepo } from './codeclimate-common.js'
 
 const schema = Joi.object({
   data: Joi.object({
@@ -16,7 +14,7 @@ const schema = Joi.object({
   }).allow(null),
 }).required()
 
-module.exports = class CodeclimateCoverage extends BaseJsonService {
+export default class CodeclimateCoverage extends BaseJsonService {
   static category = 'coverage'
   static route = {
     base: 'codeclimate',
diff --git a/services/codeclimate/codeclimate-coverage.tester.js b/services/codeclimate/codeclimate-coverage.tester.js
index de7c9acdc9a995fcdcd3e9ef4686b1574509b6e6..66ca3045126e17071e3dfca00d49070f200b81f9 100644
--- a/services/codeclimate/codeclimate-coverage.tester.js
+++ b/services/codeclimate/codeclimate-coverage.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // Examples for this service can be found through the explore page:
 // https://codeclimate.com/explore
diff --git a/services/codecov/codecov-redirect.service.js b/services/codecov/codecov-redirect.service.js
index 9d56de406e9b0d89b4e42df6c6d22aa901c1a3c9..2707d2e180253546ca91331458337225381dc0a1 100644
--- a/services/codecov/codecov-redirect.service.js
+++ b/services/codecov/codecov-redirect.service.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { redirector } = require('..')
+import { redirector } from '../index.js'
 
 const vcsSNameShortFormMap = {
   bb: 'bitbucket',
@@ -8,7 +6,7 @@ const vcsSNameShortFormMap = {
   gl: 'gitlab',
 }
 
-module.exports = [
+export default [
   redirector({
     category: 'coverage',
     route: {
diff --git a/services/codecov/codecov-redirect.tester.js b/services/codecov/codecov-redirect.tester.js
index 1a9154db681c21133db33b58a30d264a4be4d2af..4e23c04550b7fba3985fde5e599b773ab86d21b7 100644
--- a/services/codecov/codecov-redirect.tester.js
+++ b/services/codecov/codecov-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'CodecovTokenRedirect',
   title: 'CodecovTokenRedirect',
   pathPrefix: '/codecov',
-}))
+})
 
 t.create('codecov token')
   .get('/c/token/abc123def456/gh/codecov/private-example.svg')
diff --git a/services/codecov/codecov.service.js b/services/codecov/codecov.service.js
index c5fb7d07619105732f1f1278a3018ef63748f052..ecafc48cf9d8ff3eed618be745d9d91c9492ca05 100644
--- a/services/codecov/codecov.service.js
+++ b/services/codecov/codecov.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { coveragePercentage } = require('../color-formatters')
-const { BaseSvgScrapingService } = require('..')
-const { parseJson } = require('../../core/base-service/json')
+import Joi from 'joi'
+import { coveragePercentage } from '../color-formatters.js'
+import { BaseSvgScrapingService } from '../index.js'
+import { parseJson } from '../../core/base-service/json.js'
 
 // https://docs.codecov.io/reference#totals
 // A new repository that's been added but never had any coverage reports
@@ -46,7 +44,7 @@ const documentation = `
   </p>
 `
 
-module.exports = class Codecov extends BaseSvgScrapingService {
+export default class Codecov extends BaseSvgScrapingService {
   static category = 'coverage'
   static route = {
     base: 'codecov/c',
diff --git a/services/codecov/codecov.spec.js b/services/codecov/codecov.spec.js
index ed54900d27360f73532146b4038c0c71fa25aacd..d0f599a3fa0f67da3be74f2a0232db535c65bef9 100644
--- a/services/codecov/codecov.spec.js
+++ b/services/codecov/codecov.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, forCases, given } = require('sazerac')
-const Codecov = require('./codecov.service')
+import { test, forCases, given } from 'sazerac'
+import Codecov from './codecov.service.js'
 
 describe('Codecov', function () {
   test(Codecov.prototype.legacyTransform, () => {
diff --git a/services/codecov/codecov.tester.js b/services/codecov/codecov.tester.js
index e7e317007311b477eba0f7cbfdf9d2f4ff3d4621..4eeea1c609c43177f5a03b4722ad1c9f917b1b53 100644
--- a/services/codecov/codecov.tester.js
+++ b/services/codecov/codecov.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('gets coverage status')
   .get('/github/codecov/example-python.json')
diff --git a/services/codefactor/codefactor-grade.service.js b/services/codefactor/codefactor-grade.service.js
index 613efb13062bbd0c4bdd6e11cc4414a1c737ba4a..748a87950b671e04d1d1ef2ce653086fa4142e89 100644
--- a/services/codefactor/codefactor-grade.service.js
+++ b/services/codefactor/codefactor-grade.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseSvgScrapingService } = require('..')
-const { isValidGrade, gradeColor } = require('./codefactor-helpers')
+import Joi from 'joi'
+import { BaseSvgScrapingService } from '../index.js'
+import { isValidGrade, gradeColor } from './codefactor-helpers.js'
 
 const schema = Joi.object({
   message: isValidGrade,
 }).required()
 
-module.exports = class CodeFactorGrade extends BaseSvgScrapingService {
+export default class CodeFactorGrade extends BaseSvgScrapingService {
   static category = 'analysis'
   static route = {
     base: 'codefactor/grade',
diff --git a/services/codefactor/codefactor-grade.spec.js b/services/codefactor/codefactor-grade.spec.js
index d9b1a80f0d9d509f4a7ccd4b3a6e64f4cde6f85e..a4ba4d95e8928b3f2668357af5a8f5637fd2cce4 100644
--- a/services/codefactor/codefactor-grade.spec.js
+++ b/services/codefactor/codefactor-grade.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const CodeFactorGrade = require('./codefactor-grade.service')
+import { test, given } from 'sazerac'
+import CodeFactorGrade from './codefactor-grade.service.js'
 
 describe('CodeFactorGrade', function () {
   test(CodeFactorGrade.render, () => {
diff --git a/services/codefactor/codefactor-grade.tester.js b/services/codefactor/codefactor-grade.tester.js
index 1df7970214bb578d63cb7f15e54a9786ccf815a6..56be9a4fd3849b3a93956562de7362f243d6b496 100644
--- a/services/codefactor/codefactor-grade.tester.js
+++ b/services/codefactor/codefactor-grade.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isValidGrade } = require('./codefactor-helpers')
+import { createServiceTester } from '../tester.js'
+import { isValidGrade } from './codefactor-helpers.js'
+export const t = await createServiceTester()
 
 t.create('Grade').get('/github/google/guava.json').expectBadge({
   label: 'code quality',
diff --git a/services/codefactor/codefactor-helpers.js b/services/codefactor/codefactor-helpers.js
index 1672c89c96814e3d84118e484a7b3f7790ace1bb..d110eabdfb591a24fa5c698dfccd12098b5ed324 100644
--- a/services/codefactor/codefactor-helpers.js
+++ b/services/codefactor/codefactor-helpers.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const Joi = require('joi')
+import Joi from 'joi'
 
 // https://support.codefactor.io/i14-glossary
 // https://github.com/badges/shields/issues/4269
@@ -31,4 +29,4 @@ function gradeColor(grade) {
   return color
 }
 
-module.exports = { isValidGrade, gradeColor }
+export { isValidGrade, gradeColor }
diff --git a/services/codeship/codeship.service.js b/services/codeship/codeship.service.js
index 1cac77ef25c4626421569a1e22701a74a9030c51..d9a8bde1d6637dc0d463133d6a3ccec7fb086b7e 100644
--- a/services/codeship/codeship.service.js
+++ b/services/codeship/codeship.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { BaseSvgScrapingService } = require('..')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { BaseSvgScrapingService } from '../index.js'
 
 const schema = Joi.object({
   message: Joi.alternatives()
@@ -26,7 +24,7 @@ const statusMap = {
   infrastructure_failure: 'failed',
 }
 
-module.exports = class Codeship extends BaseSvgScrapingService {
+export default class Codeship extends BaseSvgScrapingService {
   static category = 'build'
   static route = { base: 'codeship', pattern: ':projectId/:branch*' }
 
diff --git a/services/codeship/codeship.spec.js b/services/codeship/codeship.spec.js
index 37fbe1cd75673d46f4da88a7e96b53ee7fd0c3f5..0b0f52f5db6b9f7be51d74628162d18f430faced 100644
--- a/services/codeship/codeship.spec.js
+++ b/services/codeship/codeship.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const Codeship = require('./codeship.service')
+import { test, given } from 'sazerac'
+import Codeship from './codeship.service.js'
 
 const pending = { message: 'pending', label: undefined, color: undefined }
 const notBuilt = { message: 'not built', label: undefined, color: undefined }
diff --git a/services/codeship/codeship.tester.js b/services/codeship/codeship.tester.js
index dce57d7ee4ce92c61f55c0898d0e16f54b406f63..ffd179a44f0ba4d3c2dc96d8fc770946bb27378a 100644
--- a/services/codeship/codeship.tester.js
+++ b/services/codeship/codeship.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('codeship (valid, no branch)')
   .get('/d6c1ddd0-16a3-0132-5f85-2e35c05e22b1.json')
diff --git a/services/codetally/codetally.service.js b/services/codetally/codetally.service.js
index 54716697ec882469cfd46ed666bd87447081b468..118c55251ae306c28ba89c3241edaa43efcd67e7 100644
--- a/services/codetally/codetally.service.js
+++ b/services/codetally/codetally.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = [
+export default [
   deprecatedService({
     category: 'funding',
     label: 'codetally',
diff --git a/services/codetally/codetally.tester.js b/services/codetally/codetally.tester.js
index 4aab0ce96c60832e708d39a80e7a7bb89ec2c2a3..130451f9b026e19deeac035e46e47464a0d80fba 100644
--- a/services/codetally/codetally.tester.js
+++ b/services/codetally/codetally.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'Codetally',
   title: 'Codetally',
   pathPrefix: '/codetally',
-}))
+})
 
 t.create('no longer available')
   .get('/triggerman722/colorstrap.json')
diff --git a/services/color-formatters.js b/services/color-formatters.js
index ce9fa6e78b76b5c2b08e43f8da2375028fdf5ebb..de45ed9e3ebb220e3fbdbe12e26b07f122dee3b2 100644
--- a/services/color-formatters.js
+++ b/services/color-formatters.js
@@ -2,9 +2,7 @@
  * Commonly-used functions for determining the colour to use for a badge,
  * including colours based off download count, version number, etc.
  */
-'use strict'
-
-const moment = require('moment')
+import moment from 'moment'
 
 function version(version) {
   if (typeof version !== 'string' && typeof version !== 'number') {
@@ -106,7 +104,7 @@ function age(date) {
   return colorByAge(daysElapsed)
 }
 
-module.exports = {
+export {
   version,
   downloadCount,
   coveragePercentage,
diff --git a/services/color-formatters.spec.js b/services/color-formatters.spec.js
index 265b5094b957db947990f2aee0f6c68722795ee6..049c5fd2a18178cef39cbcfd4ed585e36da012f6 100644
--- a/services/color-formatters.spec.js
+++ b/services/color-formatters.spec.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const { test, given, forCases } = require('sazerac')
-const { expect } = require('chai')
-const {
+import { test, given, forCases } from 'sazerac'
+import { expect } from 'chai'
+import {
   coveragePercentage,
   colorScale,
   letterScore,
   age,
   version,
-} = require('./color-formatters')
+} from './color-formatters.js'
 
 describe('Color formatters', function () {
   const byPercentage = colorScale([Number.EPSILON, 80, 90, 100])
diff --git a/services/conda/conda-base.js b/services/conda/conda-base.js
index 939cee58de9846703a8e802b41a91f523b6b0864..d7cd3f7a0011b433e8cc7897547789e947f848c2 100644
--- a/services/conda/conda-base.js
+++ b/services/conda/conda-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const condaSchema = Joi.object({
   latest_version: Joi.string().required(),
@@ -16,7 +14,7 @@ const condaSchema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class BaseCondaService extends BaseJsonService {
+export default class BaseCondaService extends BaseJsonService {
   static defaultBadgeData = { label: 'conda' }
 
   async fetch({ channel, pkg }) {
diff --git a/services/conda/conda-downloads.service.js b/services/conda/conda-downloads.service.js
index 6fa6962ef7239fe5940b9f07ca17f7c4cea69eae..8b7f54b4a62d75c45d1b494e07c98fc613b0f1fc 100644
--- a/services/conda/conda-downloads.service.js
+++ b/services/conda/conda-downloads.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import BaseCondaService from './conda-base.js'
 
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const BaseCondaService = require('./conda-base')
-
-module.exports = class CondaDownloads extends BaseCondaService {
+export default class CondaDownloads extends BaseCondaService {
   static category = 'downloads'
   static route = { base: 'conda', pattern: ':variant(d|dn)/:channel/:pkg' }
 
diff --git a/services/conda/conda-downloads.tester.js b/services/conda/conda-downloads.tester.js
index 1d86806051437d539b2a4f7b2d5bca2bad6d6a08..796cb38551b4d7c6fc5530b9ac43f972dd44e4ae 100644
--- a/services/conda/conda-downloads.tester.js
+++ b/services/conda/conda-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('downloads').get('/d/conda-forge/zlib.json').expectBadge({
   label: 'conda|downloads',
diff --git a/services/conda/conda-license.service.js b/services/conda/conda-license.service.js
index d2ecf978701743233ba34d16975bae01f01ca698..b6e936cbc11a737611adf8e6b67813ca07be679e 100644
--- a/services/conda/conda-license.service.js
+++ b/services/conda/conda-license.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderLicenseBadge } = require('../licenses')
-const toArray = require('../../core/base-service/to-array')
-const BaseCondaService = require('./conda-base')
+import Joi from 'joi'
+import { renderLicenseBadge } from '../licenses.js'
+import toArray from '../../core/base-service/to-array.js'
+import BaseCondaService from './conda-base.js'
 
 const schema = Joi.object({
   license: Joi.string().required(),
 }).required()
 
-module.exports = class CondaLicense extends BaseCondaService {
+export default class CondaLicense extends BaseCondaService {
   static category = 'license'
   static route = { base: 'conda', pattern: 'l/:channel/:pkg' }
 
diff --git a/services/conda/conda-license.tester.js b/services/conda/conda-license.tester.js
index 7cffa6ca27f3920422a1f5e44139c8cef93185fa..cfafec49a8b5b5e90a2b94c1387d999859d14a25 100644
--- a/services/conda/conda-license.tester.js
+++ b/services/conda/conda-license.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('license')
   .get('/l/conda-forge/setuptools.json')
diff --git a/services/conda/conda-platform.service.js b/services/conda/conda-platform.service.js
index 73444a7be4da3401c54a3d44a2cdb483bf90320c..fdf7cc13aa322cc9b6d9dc54fca9540232c05f9c 100644
--- a/services/conda/conda-platform.service.js
+++ b/services/conda/conda-platform.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import BaseCondaService from './conda-base.js'
 
-const BaseCondaService = require('./conda-base')
-
-module.exports = class CondaPlatform extends BaseCondaService {
+export default class CondaPlatform extends BaseCondaService {
   static category = 'platform-support'
   static route = { base: 'conda', pattern: ':variant(p|pn)/:channel/:pkg' }
 
diff --git a/services/conda/conda-platform.tester.js b/services/conda/conda-platform.tester.js
index aa06463aaf1161928d172cc476d25460bcae2727..31545824142adf383dcc2a7c29cf88692cba11a3 100644
--- a/services/conda/conda-platform.tester.js
+++ b/services/conda/conda-platform.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
 const isCondaPlatform = Joi.string().regex(/^\w+-[\w\d]+( \| \w+-[\w\d]+)*$/)
-const t = (module.exports = require('../tester').createServiceTester())
+export const t = await createServiceTester()
 
 t.create('platform').get('/p/conda-forge/zlib.json').expectBadge({
   label: 'conda|platform',
diff --git a/services/conda/conda-version.service.js b/services/conda/conda-version.service.js
index 9491912ab5d64ad8693b0b7bb81fd74f5e21f32a..486dba8a0d8c867a9ba7aa6736c234d2613eb9aa 100644
--- a/services/conda/conda-version.service.js
+++ b/services/conda/conda-version.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { addv as versionText } from '../text-formatters.js'
+import { version as versionColor } from '../color-formatters.js'
+import BaseCondaService from './conda-base.js'
 
-const { addv: versionText } = require('../text-formatters')
-const { version: versionColor } = require('../color-formatters')
-const BaseCondaService = require('./conda-base')
-
-module.exports = class CondaVersion extends BaseCondaService {
+export default class CondaVersion extends BaseCondaService {
   static category = 'version'
   static route = { base: 'conda', pattern: ':variant(v|vn)/:channel/:pkg' }
 
diff --git a/services/conda/conda-version.tester.js b/services/conda/conda-version.tester.js
index 4ffc6516a251e5546e97819622fdd643843eda42..90d9af9f0ad69ac2e4a7773a04420aad273771c9 100644
--- a/services/conda/conda-version.tester.js
+++ b/services/conda/conda-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusTripleDottedVersion } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusTripleDottedVersion } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('version').get('/v/conda-forge/zlib.json').expectBadge({
   label: 'conda|conda-forge',
diff --git a/services/continuousphp/continuousphp.service.js b/services/continuousphp/continuousphp.service.js
index 01883e775fdfe6d07e6c15da34357a005b8a06fa..6d7d147f5eb66a783895bc7221e85ebc3a4e5d8d 100644
--- a/services/continuousphp/continuousphp.service.js
+++ b/services/continuousphp/continuousphp.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'build',
   route: {
     base: 'continuousphp',
diff --git a/services/continuousphp/continuousphp.tester.js b/services/continuousphp/continuousphp.tester.js
index fe2e36560bf5f06d5a3b5cdb27f6a563130c4af7..c68eb20beaf0a6f2679e1d15930fea203cdeb3a4 100644
--- a/services/continuousphp/continuousphp.tester.js
+++ b/services/continuousphp/continuousphp.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'continuousphp',
   title: 'Continuousphp',
-}))
+})
 
 t.create('no longer available (previously build status on default branch)')
   .get('/git-hub/doctrine/dbal.json')
diff --git a/services/contributor-count.js b/services/contributor-count.js
index 523a5ace78235ad0a634f22a92d5eeba5b816dcd..60c866476629f1b678e7309355889c6a0ff03b90 100644
--- a/services/contributor-count.js
+++ b/services/contributor-count.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { metric } = require('./text-formatters')
+import { metric } from './text-formatters.js'
 
 function contributorColor(contributorCount) {
   if (contributorCount > 2) {
@@ -20,7 +18,4 @@ function renderContributorBadge({ label, contributorCount }) {
   }
 }
 
-module.exports = {
-  contributorColor,
-  renderContributorBadge,
-}
+export { contributorColor, renderContributorBadge }
diff --git a/services/contributor-count.spec.js b/services/contributor-count.spec.js
index 1ebdf4d31e32ba402f1f12a501bb786c7b3b4d57..ba4e0fe6cbfb8b95356d933963b0c552505dfad5 100644
--- a/services/contributor-count.spec.js
+++ b/services/contributor-count.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { renderContributorBadge } = require('./contributor-count')
+import { test, given } from 'sazerac'
+import { renderContributorBadge } from './contributor-count.js'
 
 describe('Contributor count helpers', function () {
   test(renderContributorBadge, () => {
diff --git a/services/cookbook/cookbook.service.js b/services/cookbook/cookbook.service.js
index 0e45f12abcada8d1dc36713ada299f04128d7a95..4b6604d5315247b5342a5d623d14ebb184053866 100644
--- a/services/cookbook/cookbook.service.js
+++ b/services/cookbook/cookbook.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({ version: Joi.string().required() }).required()
 
-module.exports = class Cookbook extends BaseJsonService {
+export default class Cookbook extends BaseJsonService {
   static category = 'version'
   static route = { base: 'cookbook/v', pattern: ':cookbook' }
 
diff --git a/services/cookbook/cookbook.tester.js b/services/cookbook/cookbook.tester.js
index 9fa5eba654e401e556fe2704d4f762754fca97ea..2cecfad4678b8fadbdff61d0ff56b4c31c33ef05 100644
--- a/services/cookbook/cookbook.tester.js
+++ b/services/cookbook/cookbook.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('version').get('/chef-sugar.json').expectBadge({
   label: 'cookbook',
diff --git a/services/coveralls/coveralls-redirector.service.js b/services/coveralls/coveralls-redirector.service.js
index b1eb9550f2409b588204833be91553d66d38acdf..1fd09fef647f9f6da564e86e4bbbf5f5ca2fc98f 100644
--- a/services/coveralls/coveralls-redirector.service.js
+++ b/services/coveralls/coveralls-redirector.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   redirector({
     name: 'CoverallsGitHubRedirect',
     category: 'coverage',
diff --git a/services/coveralls/coveralls-redirector.tester.js b/services/coveralls/coveralls-redirector.tester.js
index 48af1e33569151f823c71115012aeac6f8d701b8..de826f7cd7aef0836c4f096a5a97fea200c81f71 100644
--- a/services/coveralls/coveralls-redirector.tester.js
+++ b/services/coveralls/coveralls-redirector.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'CoverallsGitHubRedirect',
   title: 'Coveralls GitHub Redirector',
   pathPrefix: '/coveralls',
-}))
+})
 
 t.create('Coveralls VCS type missing')
   .get('/lemurheavy/coveralls-ruby.svg')
diff --git a/services/coveralls/coveralls.service.js b/services/coveralls/coveralls.service.js
index 235927a6b3082431046979dc904d9672e47c0c38..46b0d556a72a9b7c5fb69d35df409b8da6ba4cd0 100644
--- a/services/coveralls/coveralls.service.js
+++ b/services/coveralls/coveralls.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { coveragePercentage } = require('../color-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { coveragePercentage } from '../color-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   covered_percent: Joi.number().min(0).max(100).required(),
 }).required()
 
-module.exports = class Coveralls extends BaseJsonService {
+export default class Coveralls extends BaseJsonService {
   static category = 'coverage'
   static route = {
     base: 'coveralls',
diff --git a/services/coveralls/coveralls.tester.js b/services/coveralls/coveralls.tester.js
index d530078cb53c73a43c3ea2e9b1a6ca0ed7c75f65..415dfa6857136cf04400ee0487996180c7d06dc8 100644
--- a/services/coveralls/coveralls.tester.js
+++ b/services/coveralls/coveralls.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('github coverage')
   .get('/github/jekyll/jekyll.json')
diff --git a/services/coverity/coverity-on-demand.service.js b/services/coverity/coverity-on-demand.service.js
index 6f6d0b52b4a4f139e7075f102cccfa6669e24e13..3b2705ecc725548bb80ee07e7ba6f48acf792d33 100644
--- a/services/coverity/coverity-on-demand.service.js
+++ b/services/coverity/coverity-on-demand.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   route: {
     base: 'coverity/ondemand',
     pattern: ':various+',
diff --git a/services/coverity/coverity-on-demand.tester.js b/services/coverity/coverity-on-demand.tester.js
index 09199d915029aec7af789f6b137c4eb2c98579b3..cdc0f561b88c352f358956f3d6f1a1f6a9271a06 100644
--- a/services/coverity/coverity-on-demand.tester.js
+++ b/services/coverity/coverity-on-demand.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'CoverityOnDemand',
   title: 'Coverity On Demand',
   pathPrefix: '/coverity/ondemand',
-}))
+})
 
 t.create('no longer available (streams)')
   .get('/streams/44b25sjc9l3ntc2ngfi29tngro.json')
diff --git a/services/coverity/coverity-scan.service.js b/services/coverity/coverity-scan.service.js
index 1643786e91ea224a9359f5afdd51376f1f744007..a28e7d4f1da36c53728907f879d1d1c50378bae3 100644
--- a/services/coverity/coverity-scan.service.js
+++ b/services/coverity/coverity-scan.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const messageRegex = /passed|passed .* new defects|pending|failed/
 const schema = Joi.object({
   message: Joi.string().regex(messageRegex).required(),
 }).required()
 
-module.exports = class CoverityScan extends BaseJsonService {
+export default class CoverityScan extends BaseJsonService {
   static category = 'analysis'
   static route = { base: 'coverity/scan', pattern: ':projectId' }
 
diff --git a/services/coverity/coverity-scan.tester.js b/services/coverity/coverity-scan.tester.js
index e8a997cacde5eb0afcba09dc0506296656a3bc0f..83aa2b092eda32be11bfd582980e1ab5f928b66c 100644
--- a/services/coverity/coverity-scan.tester.js
+++ b/services/coverity/coverity-scan.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('known project id')
   .get('/3997.json')
diff --git a/services/cpan/cpan-license.service.js b/services/cpan/cpan-license.service.js
index bcf2433863fd83f6373e8d591ded8762ad98afb9..53ea4f4a5f3bb731a5b91979e45d56becd5fa33d 100644
--- a/services/cpan/cpan-license.service.js
+++ b/services/cpan/cpan-license.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import BaseCpanService from './cpan.js'
 
-const BaseCpanService = require('./cpan')
-
-module.exports = class CpanLicense extends BaseCpanService {
+export default class CpanLicense extends BaseCpanService {
   static category = 'license'
   static route = { base: 'cpan/l', pattern: ':packageName' }
 
diff --git a/services/cpan/cpan-license.tester.js b/services/cpan/cpan-license.tester.js
index fb9f4dfa76dd0708f8037229c36a6686a9192ed4..8cfba3c5e1960713ce80f01b8dae4c40985a24b0 100644
--- a/services/cpan/cpan-license.tester.js
+++ b/services/cpan/cpan-license.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('license (valid)').get('/Config-Augeas.json').expectBadge({
   label: 'license',
diff --git a/services/cpan/cpan-version.service.js b/services/cpan/cpan-version.service.js
index b54ec9c98899edb52b32edbbd123a64c3708bd59..92cba8d08472020023a42494a8bbfff593edf7c0 100644
--- a/services/cpan/cpan-version.service.js
+++ b/services/cpan/cpan-version.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import BaseCpanService from './cpan.js'
 
-const { renderVersionBadge } = require('../version')
-const BaseCpanService = require('./cpan')
-
-module.exports = class CpanVersion extends BaseCpanService {
+export default class CpanVersion extends BaseCpanService {
   static category = 'version'
   static route = { base: 'cpan/v', pattern: ':packageName' }
 
diff --git a/services/cpan/cpan-version.tester.js b/services/cpan/cpan-version.tester.js
index a9f6c31c3218c7d07317cef2427b0656948c2511..402601004d6f104a7bc028e1537496b8d8029af8 100644
--- a/services/cpan/cpan-version.tester.js
+++ b/services/cpan/cpan-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('version (valid)').get('/Config-Augeas.json').expectBadge({
   label: 'cpan',
diff --git a/services/cpan/cpan.js b/services/cpan/cpan.js
index 56af7786617a3f07dd5e50775f0ea3463d3f6711..96d0c4c941332abc22127ebc395a3d401ea22301 100644
--- a/services/cpan/cpan.js
+++ b/services/cpan/cpan.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   version: Joi.alternatives(Joi.string().required(), Joi.number().required()),
   license: Joi.array().items(Joi.string()).min(1).required(),
 }).required()
 
-module.exports = class BaseCpanService extends BaseJsonService {
+export default class BaseCpanService extends BaseJsonService {
   static defaultBadgeData = { label: 'cpan' }
 
   async fetch({ packageName }) {
diff --git a/services/cran/cran.service.js b/services/cran/cran.service.js
index 850d6e976cdd49cd5734923b1fe2794ea9fef134..bb25656e21809c09dbc701f66facf28f60ce85a1 100644
--- a/services/cran/cran.service.js
+++ b/services/cran/cran.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   License: Joi.string().required(),
@@ -66,4 +64,4 @@ class CranVersion extends BaseCranService {
   }
 }
 
-module.exports = { CranLicense, CranVersion }
+export { CranLicense, CranVersion }
diff --git a/services/cran/cran.tester.js b/services/cran/cran.tester.js
index 3a1161e97ca345a2740836cadb2f653b6b5d8e8e..1581c8a7ddc70741478d354a7bc8622083ddcc7a 100644
--- a/services/cran/cran.tester.js
+++ b/services/cran/cran.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isVPlusTripleDottedVersion } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isVPlusTripleDottedVersion } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'cran',
   title: 'CRAN/METACRAN',
-}))
+})
 
 t.create('version (valid)').get('/v/devtools.json').expectBadge({
   label: 'cran',
diff --git a/services/crates/crates-base.js b/services/crates/crates-base.js
index 855072761c4f62d1ba3783d5542242a7ccff0be1..e87fe5cea875fa77489af238d621d5ced75ea6ba 100644
--- a/services/crates/crates-base.js
+++ b/services/crates/crates-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const keywords = ['Rust']
 
@@ -51,4 +49,4 @@ class BaseCratesService extends BaseJsonService {
   }
 }
 
-module.exports = { BaseCratesService, keywords }
+export { BaseCratesService, keywords }
diff --git a/services/crates/crates-downloads.service.js b/services/crates/crates-downloads.service.js
index fd89ebcb5311714c2543effc5b29c04b572befc8..ec442f83657a25dac61d91923b581a7b9ddda958 100644
--- a/services/crates/crates-downloads.service.js
+++ b/services/crates/crates-downloads.service.js
@@ -1,11 +1,9 @@
-'use strict'
+import { downloadCount as downloadCountColor } from '../color-formatters.js'
+import { metric } from '../text-formatters.js'
+import { InvalidParameter, NotFound } from '../index.js'
+import { BaseCratesService, keywords } from './crates-base.js'
 
-const { downloadCount: downloadCountColor } = require('../color-formatters')
-const { metric } = require('../text-formatters')
-const { InvalidParameter, NotFound } = require('..')
-const { BaseCratesService, keywords } = require('./crates-base')
-
-module.exports = class CratesDownloads extends BaseCratesService {
+export default class CratesDownloads extends BaseCratesService {
   static category = 'downloads'
   static route = {
     base: 'crates',
diff --git a/services/crates/crates-downloads.tester.js b/services/crates/crates-downloads.tester.js
index da064bf9547596d2ec614241956b2614f807b4bd..9e2e13ccf47aa5a3a146917679e190bd486779f8 100644
--- a/services/crates/crates-downloads.tester.js
+++ b/services/crates/crates-downloads.tester.js
@@ -1,13 +1,11 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isMetric } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'crates',
   title: 'crates.io',
   pathPrefix: '/crates',
-}))
+})
 
 t.create('total downloads')
   .get('/d/libc.json')
diff --git a/services/crates/crates-license.service.js b/services/crates/crates-license.service.js
index bb12937c09bf486ddb3fd887245b9ecfff2453be..c32ab9517bd8f5da138fef06106187a5deb709bb 100644
--- a/services/crates/crates-license.service.js
+++ b/services/crates/crates-license.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseCratesService, keywords } from './crates-base.js'
 
-const { BaseCratesService, keywords } = require('./crates-base')
-
-module.exports = class CratesLicense extends BaseCratesService {
+export default class CratesLicense extends BaseCratesService {
   static category = 'license'
   static route = { base: 'crates/l', pattern: ':crate/:version?' }
 
diff --git a/services/crates/crates-license.tester.js b/services/crates/crates-license.tester.js
index 79d711034ea09fb578a74dfba637778d5ab2dc70..390295433b0bdf645b0e87680dff568aa11bb746 100644
--- a/services/crates/crates-license.tester.js
+++ b/services/crates/crates-license.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'crates',
   title: 'crates.io',
   pathPrefix: '/crates/l',
-}))
+})
 
 t.create('license')
   .get('/libc.json')
diff --git a/services/crates/crates-version.service.js b/services/crates/crates-version.service.js
index 4f631dae9ecc9db65f6b60328f0c91274c3afbbb..be7a6d1c186823d778daf9fdfc63c61243e5bdec 100644
--- a/services/crates/crates-version.service.js
+++ b/services/crates/crates-version.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import { InvalidResponse } from '../index.js'
+import { BaseCratesService, keywords } from './crates-base.js'
 
-const { renderVersionBadge } = require('../version')
-const { InvalidResponse } = require('..')
-const { BaseCratesService, keywords } = require('./crates-base')
-
-module.exports = class CratesVersion extends BaseCratesService {
+export default class CratesVersion extends BaseCratesService {
   static category = 'version'
   static route = { base: 'crates/v', pattern: ':crate' }
 
diff --git a/services/crates/crates-version.spec.js b/services/crates/crates-version.spec.js
index 97898f6b8a4a3ac8c4b9a054c9eb1a2b51236e51..7ceba9f3ba733df24b73253976b4e32ba2615796 100644
--- a/services/crates/crates-version.spec.js
+++ b/services/crates/crates-version.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { expect } = require('chai')
-const { InvalidResponse } = require('..')
-const CratesVersion = require('./crates-version.service')
+import { test, given } from 'sazerac'
+import { expect } from 'chai'
+import { InvalidResponse } from '../index.js'
+import CratesVersion from './crates-version.service.js'
 
 describe('CratesVersion', function () {
   test(CratesVersion.prototype.transform, () => {
diff --git a/services/crates/crates-version.tester.js b/services/crates/crates-version.tester.js
index 4fc19952d8bd054970729cac60105a9971bb90a1..3242c1cd5a82edb1e0889f6981b70909202a56a3 100644
--- a/services/crates/crates-version.tester.js
+++ b/services/crates/crates-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isSemver } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isSemver } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('version')
   .get('/libc.json')
diff --git a/services/criterion/constants.js b/services/criterion/constants.js
index 15d2c3041e4be463b2833e785827db6fa3b8cd12..440bb822c85d435b492448633d9dfdbe77e44393 100644
--- a/services/criterion/constants.js
+++ b/services/criterion/constants.js
@@ -1,8 +1,4 @@
-'use strict'
-
-module.exports = Object.freeze({
-  IMPROVED_STATUS: 'improved',
-  REGRESSED_STATUS: 'regressed',
-  NO_CHANGE_STATUS: 'no change',
-  NOT_FOUND_STATUS: 'no status found',
-})
+export const IMPROVED_STATUS = 'improved'
+export const REGRESSED_STATUS = 'regressed'
+export const NO_CHANGE_STATUS = 'no change'
+export const NOT_FOUND_STATUS = 'no status found'
diff --git a/services/criterion/criterion.service.js b/services/criterion/criterion.service.js
index 0fd70f95db4104fdcceb787d636faa72c208eea6..6df7615a94fa9bf8061fbf12ee1747dc9b4882ca 100644
--- a/services/criterion/criterion.service.js
+++ b/services/criterion/criterion.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
-const {
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
+import {
   IMPROVED_STATUS,
   NOT_FOUND_STATUS,
   REGRESSED_STATUS,
   NO_CHANGE_STATUS,
-} = require('./constants')
+} from './constants.js'
 
 const schema = Joi.string()
   .allow(IMPROVED_STATUS, REGRESSED_STATUS, NO_CHANGE_STATUS)
@@ -22,7 +20,7 @@ const schema = Joi.string()
  * API Documentation:
  * - https://app.swaggerhub.com/apis-docs/chmoder/Criterion.dev
  */
-module.exports = class Criterion extends BaseJsonService {
+export default class Criterion extends BaseJsonService {
   static category = 'analysis'
   static route = { base: 'criterion', pattern: ':user/:repo' }
 
diff --git a/services/criterion/criterion.tester.js b/services/criterion/criterion.tester.js
index f297d44d2492e5bc5a114aeb6f7d81956a8149b1..9e476514d822cfd8bf99a435a82480ef0075bd09 100644
--- a/services/criterion/criterion.tester.js
+++ b/services/criterion/criterion.tester.js
@@ -1,13 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const {
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import {
   IMPROVED_STATUS,
   REGRESSED_STATUS,
   NO_CHANGE_STATUS,
   NOT_FOUND_STATUS,
-} = require('./constants')
+} from './constants.js'
+export const t = await createServiceTester()
 
 const isStatus = Joi.string()
   .allow(IMPROVED_STATUS, REGRESSED_STATUS, NOT_FOUND_STATUS, NO_CHANGE_STATUS)
diff --git a/services/ctan/ctan.service.js b/services/ctan/ctan.service.js
index 4e8d95c3ee1fc4b9cb90c7ca1e8e2eb991b8db49..e6a97345cf26afbc5cf1de93ee8de11340aa0193 100644
--- a/services/ctan/ctan.service.js
+++ b/services/ctan/ctan.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderLicenseBadge } = require('../licenses')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderLicenseBadge } from '../licenses.js'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   license: Joi.array().items(Joi.string()).single(),
@@ -73,7 +71,4 @@ class CtanVersion extends BaseCtanService {
   }
 }
 
-module.exports = {
-  CtanLicense,
-  CtanVersion,
-}
+export { CtanLicense, CtanVersion }
diff --git a/services/ctan/ctan.tester.js b/services/ctan/ctan.tester.js
index 29268a604e2db2c6f8b5bb2dc969a993fccb680c..10f4386a2b7c4bfd96b3b7a86954a7f5c16dfcaa 100644
--- a/services/ctan/ctan.tester.js
+++ b/services/ctan/ctan.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'ctan',
   title: 'Comprehensive TEX Archive Network',
-}))
+})
 
 t.create('license').get('/l/novel.json').expectBadge({
   label: 'license',
diff --git a/services/date/date.service.js b/services/date/date.service.js
index d01f3f973ef5c599cc47d3f299efd0a41593a0db..32fda7de30e4fd33dc2288aac9d5100758b6dc9f 100644
--- a/services/date/date.service.js
+++ b/services/date/date.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { formatRelativeDate } = require('../text-formatters')
-const { BaseService } = require('..')
+import { formatRelativeDate } from '../text-formatters.js'
+import { BaseService } from '../index.js'
 
 const documentation = `
 <p>
@@ -9,7 +7,7 @@ const documentation = `
 </p>
 `
 
-module.exports = class Date extends BaseService {
+export default class Date extends BaseService {
   static category = 'other'
   static route = { base: 'date', pattern: ':timestamp([0-9]+)' }
 
diff --git a/services/date/date.tester.js b/services/date/date.tester.js
index 3e0135bd01d53a250e31ae37a7410ebfa899bd5b..ec5000da23e665dbf54c03e1e7fe655906afd73f 100644
--- a/services/date/date.tester.js
+++ b/services/date/date.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isRelativeFormattedDate } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isRelativeFormattedDate } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'date',
   title: 'Relative Date Tests',
-}))
+})
 
 t.create('Relative date')
   .get('/1540814400.json')
diff --git a/services/david/david.service.js b/services/david/david.service.js
index 18f499aa8d47165dd2814c307c9f97e871bc8e12..67e171d93b08eb4b59bcf56af6a7969bb638ad21 100644
--- a/services/david/david.service.js
+++ b/services/david/david.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   status: Joi.allow(
@@ -40,7 +38,7 @@ const statusMap = {
   },
 }
 
-module.exports = class David extends BaseJsonService {
+export default class David extends BaseJsonService {
   static category = 'dependencies'
   static route = {
     base: 'david',
diff --git a/services/david/david.tester.js b/services/david/david.tester.js
index 275e702ab17e248203dea762412e47b40db912da..b7e4ac0761c245e3d468f1fd438ea230db6d821a 100644
--- a/services/david/david.tester.js
+++ b/services/david/david.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isDependencyStatus = Joi.string().valid(
   'insecure',
diff --git a/services/debian/debian.service.js b/services/debian/debian.service.js
index c113ca13e0d114f924d6120f830e6b5f2f943df0..404cc75b3d4692eba9f02796db88d4ec4c45f3ee 100644
--- a/services/debian/debian.service.js
+++ b/services/debian/debian.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { latest, renderVersionBadge } = require('../version')
-const { BaseJsonService, NotFound, InvalidResponse } = require('..')
+import Joi from 'joi'
+import { latest, renderVersionBadge } from '../version.js'
+import { BaseJsonService, NotFound, InvalidResponse } from '../index.js'
 
 const schema = Joi.array()
   .items(
@@ -18,7 +16,7 @@ const schema = Joi.array()
 
 const defaultDistribution = 'stable'
 
-module.exports = class Debian extends BaseJsonService {
+export default class Debian extends BaseJsonService {
   static category = 'version'
   static route = {
     base: 'debian/v',
diff --git a/services/debian/debian.tester.js b/services/debian/debian.tester.js
index 046c31d1e184b556415e4fccfd2a07053ca1f9c0..d56026c476516069c32c48c3b163e06ff317434d 100644
--- a/services/debian/debian.tester.js
+++ b/services/debian/debian.tester.js
@@ -1,9 +1,6 @@
-'use strict'
-
-const {
-  isVPlusDottedVersionNClausesWithOptionalSuffixAndEpoch,
-} = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionNClausesWithOptionalSuffixAndEpoch } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Debian package (default distribution, valid)')
   .get('/apt.json')
diff --git a/services/debug/debug.service.js b/services/debug/debug.service.js
index b24d61c671068fd83ae51aaa3143cb31035aa0ee..93dc625deaf3a72db45f13315641ec0f4b868d62 100644
--- a/services/debug/debug.service.js
+++ b/services/debug/debug.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { BaseService } = require('..')
+import { BaseService } from '../index.js'
 
 const serverStartTime = new Date(new Date().toGMTString())
 let bitFlip = false
 
-module.exports = class Debug extends BaseService {
+export default class Debug extends BaseService {
   static category = 'debug'
   static route = { base: 'debug', pattern: ':variant(time|starttime|flip)' }
 
diff --git a/services/debug/debug.tester.js b/services/debug/debug.tester.js
index 2885b9479d1852a352d1a7570f8cceb1e8e0c176..f57dcaf34141e21ad43c1d51dc6ed59a334e667c 100644
--- a/services/debug/debug.tester.js
+++ b/services/debug/debug.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('start time')
   .get('/starttime.json')
diff --git a/services/dependabot/dependabot.service.js b/services/dependabot/dependabot.service.js
index f3e121f28d578dfb48d3eaf84e095886cf67e97b..57d2cf3a311063e9b40358e5ffb90f2151304833 100644
--- a/services/dependabot/dependabot.service.js
+++ b/services/dependabot/dependabot.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   status: Joi.string().required(),
   colour: Joi.string().required(),
 })
 
-module.exports = class DependabotSemverCompatibility extends BaseJsonService {
+export default class DependabotSemverCompatibility extends BaseJsonService {
   static category = 'analysis'
   static route = {
     base: 'dependabot/semver',
diff --git a/services/dependabot/dependabot.tester.js b/services/dependabot/dependabot.tester.js
index aa920d84d5276076217b6c86f2ea6c666c8153da..9ac85a9e1ee0b20a71f1a051f2f8e55244fe502f 100644
--- a/services/dependabot/dependabot.tester.js
+++ b/services/dependabot/dependabot.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('semver stability (valid)').get('/bundler/puma.json').expectBadge({
   label: 'semver stability',
diff --git a/services/depfu/depfu.service.js b/services/depfu/depfu.service.js
index 8be46d36a41eadec1c876888351101aeac39059f..b35daf9f904f31a78ddf2243f3933457dd80e450 100644
--- a/services/depfu/depfu.service.js
+++ b/services/depfu/depfu.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const depfuSchema = Joi.object({
   text: Joi.string().required(),
   colorscheme: Joi.string().required(),
 }).required()
 
-module.exports = class Depfu extends BaseJsonService {
+export default class Depfu extends BaseJsonService {
   static category = 'dependencies'
   static route = { base: 'depfu', pattern: ':user/:repo' }
   static examples = [
diff --git a/services/depfu/depfu.tester.js b/services/depfu/depfu.tester.js
index 957704f3c47cbe4072e801402d068bbdea2efe35..04aeaf2b02cf952cc59caa83264481d38acdcb5b 100644
--- a/services/depfu/depfu.tester.js
+++ b/services/depfu/depfu.tester.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
 
 const isDependencyStatus = Joi.string().valid(
   'insecure',
@@ -10,7 +8,7 @@ const isDependencyStatus = Joi.string().valid(
   'stale'
 )
 
-const t = (module.exports = new ServiceTester({ id: 'depfu', title: 'Depfu' }))
+export const t = new ServiceTester({ id: 'depfu', title: 'Depfu' })
 
 t.create('depfu dependencies (valid)')
   .get('/depfu/example-ruby.json')
diff --git a/services/deprecation-helpers.js b/services/deprecation-helpers.js
index d01055bd004d80f5fa4515725c72ea92410ed2f9..fb6ecc6b7968b30b352271eddbfb243befe13570 100644
--- a/services/deprecation-helpers.js
+++ b/services/deprecation-helpers.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { Deprecated } = require('.')
+import { Deprecated } from './index.js'
 
 function enforceDeprecation(effectiveDate) {
   if (Date.now() >= effectiveDate.getTime()) {
@@ -8,6 +6,4 @@ function enforceDeprecation(effectiveDate) {
   }
 }
 
-module.exports = {
-  enforceDeprecation,
-}
+export { enforceDeprecation }
diff --git a/services/deprecation-helpers.spec.js b/services/deprecation-helpers.spec.js
index 63632cc7e0243d1ea4a2e94cd081be82c66cd1e6..34779dad7f9a35f288174eebea5b39cfe12a5b60 100644
--- a/services/deprecation-helpers.spec.js
+++ b/services/deprecation-helpers.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { expect } = require('chai')
-const { Deprecated } = require('../core/base-service/errors')
-const { enforceDeprecation } = require('./deprecation-helpers')
+import { expect } from 'chai'
+import { Deprecated } from '../core/base-service/errors.js'
+import { enforceDeprecation } from './deprecation-helpers.js'
 
 describe('enforceDeprecation', function () {
   it('throws Deprecated for a date in the past', function () {
diff --git a/services/discord/discord.service.js b/services/discord/discord.service.js
index 7e510d0cad04731b4dae190d5eda847ee833466b..65837b9a35004c79d153a179dcbd6586d12a0535 100644
--- a/services/discord/discord.service.js
+++ b/services/discord/discord.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   presence_count: nonNegativeInteger,
@@ -24,7 +22,7 @@ const documentation = `
 <iframe src="https://player.vimeo.com/video/364220040" width="640" height="210" frameborder="0" allow="autoplay; fullscreen" allowfullscreen></iframe>
 `
 
-module.exports = class Discord extends BaseJsonService {
+export default class Discord extends BaseJsonService {
   static category = 'chat'
 
   static route = {
diff --git a/services/discord/discord.spec.js b/services/discord/discord.spec.js
index 926ac9859da3540b67a943ac250877b48038db1c..4dbbeae36b8581ff9c825084fc9c388d649259e2 100644
--- a/services/discord/discord.spec.js
+++ b/services/discord/discord.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const Discord = require('./discord.service')
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import Discord from './discord.service.js'
 
 describe('Discord', function () {
   cleanUpNockAfterEach()
diff --git a/services/discord/discord.tester.js b/services/discord/discord.tester.js
index 694775133a684d9c1c7b47b87691297fa76575ad..4e9ca9d6d627adaaaf6c5d8b0f6211eb8586fb6b 100644
--- a/services/discord/discord.tester.js
+++ b/services/discord/discord.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('gets status for Reactiflux')
   .get('/102860784329052160.json')
diff --git a/services/discourse/discourse-redirect.service.js b/services/discourse/discourse-redirect.service.js
index 72d265fe109e7328da0d2dc39e5473827b3de6d2..f1285eba110b880301ab62adf5e0ab5297d5e902 100644
--- a/services/discourse/discourse-redirect.service.js
+++ b/services/discourse/discourse-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   redirector({
     category: 'chat',
     route: {
diff --git a/services/discourse/discourse-redirect.tester.js b/services/discourse/discourse-redirect.tester.js
index 772eb3465873a9b3fcfbff6500f27dea3595f656..6dce032f5b32178d5357aaa6cd1d760fa3bcf46a 100644
--- a/services/discourse/discourse-redirect.tester.js
+++ b/services/discourse/discourse-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'DiscourseRedirect',
   title: 'DiscourseRedirect',
   pathPrefix: '/discourse',
-}))
+})
 
 t.create('discourse status')
   .get('/https/meta.discourse.org/status.svg')
diff --git a/services/discourse/discourse.service.js b/services/discourse/discourse.service.js
index 7037fca298b97233dd24ccf76e7dc01ba022e08c..e6c1322c38300ad40107a756c9840b77d38147eb 100644
--- a/services/discourse/discourse.service.js
+++ b/services/discourse/discourse.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const camelcase = require('camelcase')
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger, optionalUrl } = require('../validators')
-const { BaseJsonService } = require('..')
+import camelcase from 'camelcase'
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger, optionalUrl } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   topic_count: nonNegativeInteger,
@@ -105,4 +103,4 @@ const metricIntegrations = [
   { metricName: 'likes', property: 'like_count' },
 ].map(DiscourseMetricIntegrationFactory)
 
-module.exports = [...metricIntegrations, DiscourseStatus]
+export default [...metricIntegrations, DiscourseStatus]
diff --git a/services/discourse/discourse.tester.js b/services/discourse/discourse.tester.js
index a074fe85e8dab807fa4679d2a2425e8eab09d145..dc779eb291a455895452b85cf7f9f75272617c2e 100644
--- a/services/discourse/discourse.tester.js
+++ b/services/discourse/discourse.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
 
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'discourse',
   title: 'Discourse',
-}))
+})
 
 const data = {
   topic_count: 22513,
diff --git a/services/dockbit/dockbit.service.js b/services/dockbit/dockbit.service.js
index f8b2e9028487b70fa8a8502571bcdd6c9998b77a..c9ecc64ddcc0ef2dfed085aa4d55a97f8f83a20d 100644
--- a/services/dockbit/dockbit.service.js
+++ b/services/dockbit/dockbit.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'build',
   route: {
     base: 'dockbit',
diff --git a/services/dockbit/dockbit.tester.js b/services/dockbit/dockbit.tester.js
index 4d9ef389a832183154ce2846a3bd813cb64cb321..76029da3c424c215533c142ed5150e4ad1ba6625 100644
--- a/services/dockbit/dockbit.tester.js
+++ b/services/dockbit/dockbit.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'dockbit',
   title: 'Dockbit',
-}))
+})
 
 t.create('no longer available (previously image size)')
   .get('/image-size/_/ubuntu/latest.json')
diff --git a/services/docker/docker-automated.service.js b/services/docker/docker-automated.service.js
index c48a57d63a730624eb6734c5161b669c13d9c258..ba28af299052068a9614e1df6c3d863ed855ec7d 100644
--- a/services/docker/docker-automated.service.js
+++ b/services/docker/docker-automated.service.js
@@ -1,18 +1,16 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
-const {
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
+import {
   dockerBlue,
   buildDockerUrl,
   getDockerHubUser,
-} = require('./docker-helpers')
+} from './docker-helpers.js'
 
 const automatedBuildSchema = Joi.object({
   is_automated: Joi.boolean().required(),
 }).required()
 
-module.exports = class DockerAutomatedBuild extends BaseJsonService {
+export default class DockerAutomatedBuild extends BaseJsonService {
   static category = 'build'
   static route = buildDockerUrl('automated')
   static examples = [
diff --git a/services/docker/docker-automated.tester.js b/services/docker/docker-automated.tester.js
index 4cc144d7ceb9ac87ad9d3a237e35d8facf743663..f52ae96d0db69a1c609ded4c7002c702a7198308 100644
--- a/services/docker/docker-automated.tester.js
+++ b/services/docker/docker-automated.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const { dockerBlue } = require('./docker-helpers')
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import { dockerBlue } from './docker-helpers.js'
+export const t = await createServiceTester()
 
 const isAutomatedBuildStatus = Joi.string().valid('automated', 'manual')
 
diff --git a/services/docker/docker-build.service.js b/services/docker/docker-build.service.js
index c98d5ada68863f8dc27b09b83a8428171d588990..7c4d0985f35f59a5ba951d4b5e91d6222af55012 100644
--- a/services/docker/docker-build.service.js
+++ b/services/docker/docker-build.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'build',
   route: {
     base: 'docker/build',
diff --git a/services/docker/docker-build.tester.js b/services/docker/docker-build.tester.js
index efc4fb259791f6acf84fa105dd85100d441b1d46..9d5876845948da658b7dcfed73e36820a13eba7d 100644
--- a/services/docker/docker-build.tester.js
+++ b/services/docker/docker-build.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'dockerbuild',
   title: 'DockerBuild',
   pathPrefix: '/docker/build',
-}))
+})
 
 t.create('no longer available').get('/jrottenberg/ffmpeg.json').expectBadge({
   label: 'docker build',
diff --git a/services/docker/docker-cloud-automated.service.js b/services/docker/docker-cloud-automated.service.js
index 8fc27256d2d89191c9ea0e1df4b83530c02166ed..a4692a643583b8794018cc1f507a271b9269ceac 100644
--- a/services/docker/docker-cloud-automated.service.js
+++ b/services/docker/docker-cloud-automated.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { BaseJsonService } from '../index.js'
+import { dockerBlue, buildDockerUrl } from './docker-helpers.js'
+import { fetchBuild } from './docker-cloud-common-fetch.js'
 
-const { BaseJsonService } = require('..')
-const { dockerBlue, buildDockerUrl } = require('./docker-helpers')
-const { fetchBuild } = require('./docker-cloud-common-fetch')
-
-module.exports = class DockerCloudAutomatedBuild extends BaseJsonService {
+export default class DockerCloudAutomatedBuild extends BaseJsonService {
   static category = 'build'
   static route = buildDockerUrl('cloud/automated')
   static examples = [
diff --git a/services/docker/docker-cloud-automated.tester.js b/services/docker/docker-cloud-automated.tester.js
index 22d508dcc3be25ee681d6f82ab4dbc9848ddee10..936451900d4486fc38b365a41d0678a596f09614 100644
--- a/services/docker/docker-cloud-automated.tester.js
+++ b/services/docker/docker-cloud-automated.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const { dockerBlue } = require('./docker-helpers')
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import { dockerBlue } from './docker-helpers.js'
+export const t = await createServiceTester()
 
 const isAutomatedBuildStatus = Joi.string().valid('automated', 'manual')
 
diff --git a/services/docker/docker-cloud-build.service.js b/services/docker/docker-cloud-build.service.js
index d40b058250729843efc0e1bed4e854e594ea056a..8fd3aa8b45f3e85230d03f6994724ac62a9025b8 100644
--- a/services/docker/docker-cloud-build.service.js
+++ b/services/docker/docker-cloud-build.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { BaseJsonService } from '../index.js'
+import { dockerBlue, buildDockerUrl } from './docker-helpers.js'
+import { fetchBuild } from './docker-cloud-common-fetch.js'
 
-const { BaseJsonService } = require('..')
-const { dockerBlue, buildDockerUrl } = require('./docker-helpers')
-const { fetchBuild } = require('./docker-cloud-common-fetch')
-
-module.exports = class DockerCloudBuild extends BaseJsonService {
+export default class DockerCloudBuild extends BaseJsonService {
   static category = 'build'
   static route = buildDockerUrl('cloud/build')
   static examples = [
diff --git a/services/docker/docker-cloud-build.tester.js b/services/docker/docker-cloud-build.tester.js
index 59a8f8ef7223d5dbcbeea0dbe83c2f89ec32c64f..9335af250124dfec39bed06cf4880e37258c10b7 100644
--- a/services/docker/docker-cloud-build.tester.js
+++ b/services/docker/docker-cloud-build.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
-const { dockerBlue } = require('./docker-helpers')
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+import { dockerBlue } from './docker-helpers.js'
+export const t = await createServiceTester()
 
 t.create('docker cloud build status (valid, user)')
   .get('/jrottenberg/ffmpeg.json')
diff --git a/services/docker/docker-cloud-common-fetch.js b/services/docker/docker-cloud-common-fetch.js
index 8ac3db1fa4f69ab30c8d7398d893fbb061b89169..51a5317348a6a6522fe50912a5e09384de1caeda 100644
--- a/services/docker/docker-cloud-common-fetch.js
+++ b/services/docker/docker-cloud-common-fetch.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const Joi = require('joi')
+import Joi from 'joi'
 
 const cloudBuildSchema = Joi.object({
   objects: Joi.array()
@@ -22,6 +20,4 @@ async function fetchBuild(serviceInstance, { user, repo }) {
   })
 }
 
-module.exports = {
-  fetchBuild,
-}
+export { fetchBuild }
diff --git a/services/docker/docker-fixtures.js b/services/docker/docker-fixtures.js
index de97cf00b8c3a16938bb93e68d59d48ee016139d..26218ca350c12de91be1f0622705005e95449d42 100644
--- a/services/docker/docker-fixtures.js
+++ b/services/docker/docker-fixtures.js
@@ -1,5 +1,3 @@
-'use strict'
-
 const sizeDataNoTagSemVerSort = [
   { name: 'master', full_size: 13449470 },
   { name: 'feature-smtps-support', full_size: 13449638 },
@@ -3035,7 +3033,7 @@ const versionDataWithVaryingArchitectures = [
   { name: '2.6', images: [] },
 ]
 
-module.exports = {
+export {
   sizeDataNoTagSemVerSort,
   versionDataNoTagDateSort,
   versionPagedDataNoTagDateSort,
diff --git a/services/docker/docker-helpers.js b/services/docker/docker-helpers.js
index 87908b00f436a07fd007b01367df651d6a30dc87..0b9b1d6879494dc4bcb3cb043db05c9d0904a634 100644
--- a/services/docker/docker-helpers.js
+++ b/services/docker/docker-helpers.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const dockerBlue = '066da5' // see https://github.com/badges/shields/pull/1690
-const { NotFound } = require('..')
+// see https://github.com/badges/shields/pull/1690
+import { NotFound } from '../index.js'
+const dockerBlue = '066da5'
 
 function buildDockerUrl(badgeName, includeTagRoute) {
   if (includeTagRoute) {
@@ -55,7 +54,7 @@ function getDigestSemVerMatches({ data, digest }) {
   return version
 }
 
-module.exports = {
+export {
   dockerBlue,
   buildDockerUrl,
   getDockerHubUser,
diff --git a/services/docker/docker-pulls.service.js b/services/docker/docker-pulls.service.js
index 5749215cac8ca113151cd5322e171ff6b3b193ee..9d741f8f96158f86eb60ce4416a43ee4146fba57 100644
--- a/services/docker/docker-pulls.service.js
+++ b/services/docker/docker-pulls.service.js
@@ -1,20 +1,18 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
-const {
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
+import {
   dockerBlue,
   buildDockerUrl,
   getDockerHubUser,
-} = require('./docker-helpers')
+} from './docker-helpers.js'
 
 const pullsSchema = Joi.object({
   pull_count: nonNegativeInteger,
 }).required()
 
-module.exports = class DockerPulls extends BaseJsonService {
+export default class DockerPulls extends BaseJsonService {
   static category = 'downloads'
   static route = buildDockerUrl('pulls')
   static examples = [
diff --git a/services/docker/docker-pulls.tester.js b/services/docker/docker-pulls.tester.js
index cdf55b257441a300b66dd84f37a141d8e65a787c..2482edea4acd7f58a0c1e672e970c733251e390d 100644
--- a/services/docker/docker-pulls.tester.js
+++ b/services/docker/docker-pulls.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
-const { dockerBlue } = require('./docker-helpers')
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+import { dockerBlue } from './docker-helpers.js'
+export const t = await createServiceTester()
 
 t.create('docker pulls (valid, library)')
   .get('/_/ubuntu.json')
diff --git a/services/docker/docker-size.service.js b/services/docker/docker-size.service.js
index 14ed46232fc10ceab39afbf25d7559f3b9ea302c..16c7ea49467cea5086ddeede2f6b11cf5fd42248 100644
--- a/services/docker/docker-size.service.js
+++ b/services/docker/docker-size.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const prettyBytes = require('pretty-bytes')
-const { nonNegativeInteger } = require('../validators')
-const { latest } = require('../version')
-const { BaseJsonService, NotFound } = require('..')
-const {
+import Joi from 'joi'
+import prettyBytes from 'pretty-bytes'
+import { nonNegativeInteger } from '../validators.js'
+import { latest } from '../version.js'
+import { BaseJsonService, NotFound } from '../index.js'
+import {
   buildDockerUrl,
   getDockerHubUser,
   getMultiPageData,
-} = require('./docker-helpers')
+} from './docker-helpers.js'
 
 const buildSchema = Joi.object({
   name: Joi.string().required(),
@@ -30,7 +28,7 @@ const queryParamSchema = Joi.object({
   sort: Joi.string().valid('date', 'semver').default('date'),
 }).required()
 
-module.exports = class DockerSize extends BaseJsonService {
+export default class DockerSize extends BaseJsonService {
   static category = 'size'
   static route = { ...buildDockerUrl('image-size', true), queryParamSchema }
   static examples = [
diff --git a/services/docker/docker-size.spec.js b/services/docker/docker-size.spec.js
index 56857c5fa7e61858e9a12b91a5b33a2cb79c9ec9..946e0d161b668a4fadc1d9c7a71b9c089103cfd2 100644
--- a/services/docker/docker-size.spec.js
+++ b/services/docker/docker-size.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const DockerSize = require('./docker-size.service')
-const { sizeDataNoTagSemVerSort } = require('./docker-fixtures')
+import { test, given } from 'sazerac'
+import DockerSize from './docker-size.service.js'
+import { sizeDataNoTagSemVerSort } from './docker-fixtures.js'
 
 describe('DockerSize', function () {
   test(DockerSize.prototype.transform, () => {
diff --git a/services/docker/docker-size.tester.js b/services/docker/docker-size.tester.js
index 6707e88967ab8f55014924c855f518a9127f47ed..c476a773f32c8d836aa47e00285a622ed17046c7 100644
--- a/services/docker/docker-size.tester.js
+++ b/services/docker/docker-size.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isFileSize } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isFileSize } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('docker image size (valid, library)')
   .get('/_/alpine.json')
diff --git a/services/docker/docker-stars.service.js b/services/docker/docker-stars.service.js
index aec79700c9b9d1b9951838986b30164de3388241..92cc8eb81e85b8cdb57b568cd629c76d86d556d5 100644
--- a/services/docker/docker-stars.service.js
+++ b/services/docker/docker-stars.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseService } = require('..')
-const {
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseService } from '../index.js'
+import {
   dockerBlue,
   buildDockerUrl,
   getDockerHubUser,
-} = require('./docker-helpers')
+} from './docker-helpers.js'
 
-module.exports = class DockerStars extends BaseService {
+export default class DockerStars extends BaseService {
   static category = 'rating'
   static route = buildDockerUrl('stars')
   static examples = [
diff --git a/services/docker/docker-stars.tester.js b/services/docker/docker-stars.tester.js
index 9a732e8564316ea256c832fac7a7bb08623248a7..ebd715c3372e385052f96b7c8f73842111447907 100644
--- a/services/docker/docker-stars.tester.js
+++ b/services/docker/docker-stars.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
-const { dockerBlue } = require('./docker-helpers')
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+import { dockerBlue } from './docker-helpers.js'
+export const t = await createServiceTester()
 
 t.create('docker stars (valid, library)')
   .get('/_/ubuntu.json')
diff --git a/services/docker/docker-version.service.js b/services/docker/docker-version.service.js
index 88eabde175b42101a4bf515c357cad116ffa1d2c..00bb00e9856981fdce3eb77d3cb29a0fbe959e6f 100644
--- a/services/docker/docker-version.service.js
+++ b/services/docker/docker-version.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { latest, renderVersionBadge } = require('../version')
-const { BaseJsonService, NotFound, InvalidResponse } = require('..')
-const {
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { latest, renderVersionBadge } from '../version.js'
+import { BaseJsonService, NotFound, InvalidResponse } from '../index.js'
+import {
   buildDockerUrl,
   getDockerHubUser,
   getMultiPageData,
   getDigestSemVerMatches,
-} = require('./docker-helpers')
+} from './docker-helpers.js'
 
 const buildSchema = Joi.object({
   count: nonNegativeInteger.required(),
@@ -47,7 +45,7 @@ const queryParamSchema = Joi.object({
     .default('amd64'),
 }).required()
 
-module.exports = class DockerVersion extends BaseJsonService {
+export default class DockerVersion extends BaseJsonService {
   static category = 'version'
   static route = { ...buildDockerUrl('v', true), queryParamSchema }
   static examples = [
diff --git a/services/docker/docker-version.spec.js b/services/docker/docker-version.spec.js
index 15fdab400f5fc2677983673f44baa9ecb186698f..bd1681c27b0dabad3057a20414a4ad39fe5e2e7b 100644
--- a/services/docker/docker-version.spec.js
+++ b/services/docker/docker-version.spec.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const { expect } = require('chai')
-const { test, given } = require('sazerac')
-const { InvalidResponse } = require('..')
-const DockerVersion = require('./docker-version.service')
-const {
+import { expect } from 'chai'
+import { test, given } from 'sazerac'
+import { InvalidResponse } from '../index.js'
+import DockerVersion from './docker-version.service.js'
+import {
   versionDataNoTagDateSort,
   versionPagedDataNoTagDateSort,
   versionDataNoTagSemVerSort,
   versionDataWithTag,
   versionDataWithVaryingArchitectures,
-} = require('./docker-fixtures')
+} from './docker-fixtures.js'
 
 describe('DockerVersion', function () {
   test(DockerVersion.prototype.transform, () => {
diff --git a/services/docker/docker-version.tester.js b/services/docker/docker-version.tester.js
index 46ebefdac650ab8813a293cbedb910c456dbcaa0..097ccc0c5349bc6603678f820f9b60e7d9ee73e7 100644
--- a/services/docker/docker-version.tester.js
+++ b/services/docker/docker-version.tester.js
@@ -1,32 +1,31 @@
-'use strict'
-
-const { isSemVer } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isSemver } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('docker version (valid, library)').get('/_/alpine.json').expectBadge({
   label: 'version',
-  message: isSemVer,
+  message: isSemver,
 })
 
 t.create('docker version (valid, library with tag)')
   .get('/_/alpine/latest.json')
   .expectBadge({
     label: 'version',
-    message: isSemVer,
+    message: isSemver,
   })
 
 t.create('docker version (valid, user)')
   .get('/jrottenberg/ffmpeg.json')
   .expectBadge({
     label: 'version',
-    message: isSemVer,
+    message: isSemver,
   })
 
 t.create('docker version (valid, user with tag)')
   .get('/jrottenberg/ffmpeg/3.2-alpine.json')
   .expectBadge({
     label: 'version',
-    message: isSemVer,
+    message: isSemver,
   })
 
 t.create('docker version (invalid, incorrect tag)')
diff --git a/services/docsrs/docsrs.service.js b/services/docsrs/docsrs.service.js
index 309eb6ba414685f21b29ba1d819466e07b78e7ad..ca88f67e49259f374af938ea2f91a2f68c2485a1 100644
--- a/services/docsrs/docsrs.service.js
+++ b/services/docsrs/docsrs.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.array()
   .items(
@@ -12,7 +10,7 @@ const schema = Joi.array()
   .min(1)
   .required()
 
-module.exports = class DocsRs extends BaseJsonService {
+export default class DocsRs extends BaseJsonService {
   static category = 'build'
   static route = { base: 'docsrs', pattern: ':crate/:version?' }
   static examples = [
diff --git a/services/docsrs/docsrs.tester.js b/services/docsrs/docsrs.tester.js
index 0e7c566bfcbc749fcb1f33ddc53dadad404494e6..0bd6157bdc6ff2875282d39998bcdef85f49b276 100644
--- a/services/docsrs/docsrs.tester.js
+++ b/services/docsrs/docsrs.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Passing docs')
   .get('/tokio/0.3.0.json')
diff --git a/services/dotnetstatus/dotnetstatus.service.js b/services/dotnetstatus/dotnetstatus.service.js
index 11a7918cc980134a7277cfafb55608d3f2d71d96..7e243fd9c07aba284bb5f1909560e19a28285854 100644
--- a/services/dotnetstatus/dotnetstatus.service.js
+++ b/services/dotnetstatus/dotnetstatus.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'dependencies',
   route: {
     base: 'dotnetstatus',
diff --git a/services/dotnetstatus/dotnetstatus.tester.js b/services/dotnetstatus/dotnetstatus.tester.js
index e2b0ea1b335202611360b20dfa0fd97e12332fa6..f15285b3bb461e567fdd84f2a492df892193574f 100644
--- a/services/dotnetstatus/dotnetstatus.tester.js
+++ b/services/dotnetstatus/dotnetstatus.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'dotnetstatus',
   title: 'dotnet-status',
-}))
+})
 
 t.create('no longer available (previously get package status)')
   .get('/gh/jaredcnance/dotnet-status/API.json')
diff --git a/services/drone/drone-build.service.js b/services/drone/drone-build.service.js
index 13aaa0721d5d655aa4e5cc20a54838766e4beb76..5b5986efb6dc3f429b65db41f39d40c6f2b60d65 100644
--- a/services/drone/drone-build.service.js
+++ b/services/drone/drone-build.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { optionalUrl } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { optionalUrl } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   status: Joi.alternatives()
@@ -15,7 +13,7 @@ const queryParamSchema = Joi.object({
   server: optionalUrl,
 }).required()
 
-module.exports = class DroneBuild extends BaseJsonService {
+export default class DroneBuild extends BaseJsonService {
   static category = 'build'
   static route = {
     base: 'drone/build',
diff --git a/services/drone/drone-build.spec.js b/services/drone/drone-build.spec.js
index dc0b914fa521ff00bbd05777a5963310deb20a44..0cb15273618a23434323d7c6b6bcd51451f41d62 100644
--- a/services/drone/drone-build.spec.js
+++ b/services/drone/drone-build.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const DroneBuild = require('./drone-build.service')
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import DroneBuild from './drone-build.service.js'
 
 describe('DroneBuild', function () {
   cleanUpNockAfterEach()
diff --git a/services/drone/drone-build.tester.js b/services/drone/drone-build.tester.js
index 59882a0089139e4234865039a73fba8e3e316a42..abd50e8feeb971bd7484b4f9aac9a557055c9c02 100644
--- a/services/drone/drone-build.tester.js
+++ b/services/drone/drone-build.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isDroneBuildStatus = Joi.alternatives().try(
   isBuildStatus,
diff --git a/services/dub/dub-download.service.js b/services/dub/dub-download.service.js
index 3c050bc5d901bdcd2fd3da52e95ff8043e8e0991..e82bf59d6eae66f13334399114f81b2e6fa8a9b1 100644
--- a/services/dub/dub-download.service.js
+++ b/services/dub/dub-download.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { downloadCount: downloadCountColor } = require('../color-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { downloadCount as downloadCountColor } from '../color-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   downloads: Joi.object({
@@ -34,7 +32,7 @@ const intervalMap = {
   },
 }
 
-module.exports = class DubDownloads extends BaseJsonService {
+export default class DubDownloads extends BaseJsonService {
   static category = 'downloads'
   static route = {
     base: 'dub',
diff --git a/services/dub/dub-download.tester.js b/services/dub/dub-download.tester.js
index 423c091513206d81afa82d1d1678c512af4dee24..4733e5343a2b9d9b0a6207c276760e2aac272d6f 100644
--- a/services/dub/dub-download.tester.js
+++ b/services/dub/dub-download.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isMetric, isMetricOverTimePeriod } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isMetric, isMetricOverTimePeriod } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isDownloadsColor = Joi.equal(
   'red',
diff --git a/services/dub/dub-license.service.js b/services/dub/dub-license.service.js
index 62f99a0cf2823882ff482e1b66b10b6800ac9486..52608f43d3e2659127e6c759be866c244af24b04 100644
--- a/services/dub/dub-license.service.js
+++ b/services/dub/dub-license.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderLicenseBadge } = require('../licenses')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderLicenseBadge } from '../licenses.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   info: Joi.object({ license: Joi.string().required() }).required(),
 })
 
-module.exports = class DubLicense extends BaseJsonService {
+export default class DubLicense extends BaseJsonService {
   static category = 'license'
   static route = { base: 'dub/l', pattern: ':packageName' }
   static examples = [
diff --git a/services/dub/dub-license.tester.js b/services/dub/dub-license.tester.js
index f40797ac530f0b8eddfab1c9f8e67f664e6919b0..0da04e2a2411fbffc4d1ee0419244eaeeae8904d 100644
--- a/services/dub/dub-license.tester.js
+++ b/services/dub/dub-license.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('license (valid)')
   .get('/vibe-d.json')
diff --git a/services/dub/dub-version.service.js b/services/dub/dub-version.service.js
index 8aeced3af473913e7d60f0f08e07397b1f624208..19c2c1626f0dc4ea92aae743a9185f9c25b94fce 100644
--- a/services/dub/dub-version.service.js
+++ b/services/dub/dub-version.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.string().required()
 
-module.exports = class DubVersion extends BaseJsonService {
+export default class DubVersion extends BaseJsonService {
   static category = 'version'
   static route = { base: 'dub/v', pattern: ':packageName' }
   static examples = [
diff --git a/services/dub/dub-version.tester.js b/services/dub/dub-version.tester.js
index 972c7256e377ce99e316ab40d55c44504c16233c..88015d7660e5a1dcf805dfb668a50fb7c8719768 100644
--- a/services/dub/dub-version.tester.js
+++ b/services/dub/dub-version.tester.js
@@ -1,10 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const {
-  isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isVPlusDottedVersionNClausesWithOptionalSuffix } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('version (valid)')
   .get('/vibe-d.json')
diff --git a/services/dynamic-common.js b/services/dynamic-common.js
index 292c84964e11574aa2eb2ba81acd1044d3266121..7cacafa41123396697d4530b88997d3dac6ea04f 100644
--- a/services/dynamic-common.js
+++ b/services/dynamic-common.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const toArray = require('../core/base-service/to-array')
-const validate = require('../core/base-service/validate')
-const { InvalidResponse } = require('.')
+import Joi from 'joi'
+import toArray from '../core/base-service/to-array.js'
+import validate from '../core/base-service/validate.js'
+import { InvalidResponse } from './index.js'
 
 const errorMessages = {
   404: 'resource not found',
@@ -48,7 +46,7 @@ function renderDynamicBadge({
   }
 }
 
-module.exports = {
+export {
   errorMessages,
   individualValueSchema,
   transformAndValidate,
diff --git a/services/dynamic/dynamic-helpers.js b/services/dynamic/dynamic-helpers.js
index 6921857674490eaa1153794bebe07aced9bd62d8..cb3b6c6ebe3d855856627e602d2f2edf764458e5 100644
--- a/services/dynamic/dynamic-helpers.js
+++ b/services/dynamic/dynamic-helpers.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
 
 const queryParamSchema = Joi.object({
   url: optionalUrl.required(),
@@ -20,6 +18,4 @@ function createRoute(which) {
   }
 }
 
-module.exports = {
-  createRoute,
-}
+export { createRoute }
diff --git a/services/dynamic/dynamic-json.service.js b/services/dynamic/dynamic-json.service.js
index 337fe66d2ded018d57d3939c089df92c7d9fdff3..5e01de94d1cde560ac1fb2eb234826cbc7db6347 100644
--- a/services/dynamic/dynamic-json.service.js
+++ b/services/dynamic/dynamic-json.service.js
@@ -1,11 +1,9 @@
-'use strict'
+import { MetricNames } from '../../core/base-service/metric-helper.js'
+import { BaseJsonService } from '../index.js'
+import { createRoute } from './dynamic-helpers.js'
+import jsonPath from './json-path.js'
 
-const { MetricNames } = require('../../core/base-service/metric-helper')
-const { BaseJsonService } = require('..')
-const { createRoute } = require('./dynamic-helpers')
-const jsonPath = require('./json-path')
-
-module.exports = class DynamicJson extends jsonPath(BaseJsonService) {
+export default class DynamicJson extends jsonPath(BaseJsonService) {
   static enabledMetrics = [MetricNames.SERVICE_RESPONSE_SIZE]
   static route = createRoute('json')
 
diff --git a/services/dynamic/dynamic-json.tester.js b/services/dynamic/dynamic-json.tester.js
index d36dda48a30e40b59add4997b1c85a7ab6dac7c3..38bb48ee7479469da0e9b133713b56bcd996bc9c 100644
--- a/services/dynamic/dynamic-json.tester.js
+++ b/services/dynamic/dynamic-json.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { expect } = require('chai')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { expect } from 'chai'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('No URL specified')
   .get('.json?query=$.name&label=Package Name')
diff --git a/services/dynamic/dynamic-response-fixtures.js b/services/dynamic/dynamic-response-fixtures.js
index 25af9ff15ad5624a1c7eac49e945dbce5eb49d0d..774483608e89b5e327d0eb9169cf0f29a3a78644 100644
--- a/services/dynamic/dynamic-response-fixtures.js
+++ b/services/dynamic/dynamic-response-fixtures.js
@@ -1,7 +1,4 @@
-'use strict'
-
-module.exports = {
-  exampleXml: `<?xml version="1.0"?>
+export const exampleXml = `<?xml version="1.0"?>
 <catalog>
    <book id="bk101">
       <author>Gambardella, Matthew</author>
@@ -121,5 +118,4 @@ module.exports = {
       environment.</description>
    </book>
 </catalog>
-`,
-}
+`
diff --git a/services/dynamic/dynamic-xml.service.js b/services/dynamic/dynamic-xml.service.js
index 9c14c59649740949cc45c7ae8c4090bb813796d6..2278f7260a30565efad52cc07860394933d0a8dd 100644
--- a/services/dynamic/dynamic-xml.service.js
+++ b/services/dynamic/dynamic-xml.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { DOMParser } = require('xmldom')
-const xpath = require('xpath')
-const { MetricNames } = require('../../core/base-service/metric-helper')
-const { renderDynamicBadge, errorMessages } = require('../dynamic-common')
-const { BaseService, InvalidResponse, InvalidParameter } = require('..')
-const { createRoute } = require('./dynamic-helpers')
+import { DOMParser } from 'xmldom'
+import xpath from 'xpath'
+import { MetricNames } from '../../core/base-service/metric-helper.js'
+import { renderDynamicBadge, errorMessages } from '../dynamic-common.js'
+import { BaseService, InvalidResponse, InvalidParameter } from '../index.js'
+import { createRoute } from './dynamic-helpers.js'
 
 // This service extends BaseService because it uses a different XML parser
 // than BaseXmlService which can be used with xpath.
@@ -13,7 +11,7 @@ const { createRoute } = require('./dynamic-helpers')
 // One way to create a more performant version would be to use the BaseXml
 // JSON parser and write the queries in jsonpath instead. Then eventually
 // deprecate the old version.
-module.exports = class DynamicXml extends BaseService {
+export default class DynamicXml extends BaseService {
   static category = 'dynamic'
   static enabledMetrics = [MetricNames.SERVICE_RESPONSE_SIZE]
   static route = createRoute('xml')
diff --git a/services/dynamic/dynamic-xml.spec.js b/services/dynamic/dynamic-xml.spec.js
index 7987164cacb2adae3774091e92bda654f0ce2945..ca233d2c0abeb9829828c42fa37f1b42a4d79ca8 100644
--- a/services/dynamic/dynamic-xml.spec.js
+++ b/services/dynamic/dynamic-xml.spec.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { expect } = require('chai')
-const sinon = require('sinon')
-const xpath = require('xpath')
-const { test, given } = require('sazerac')
-const { InvalidResponse } = require('..')
-const DynamicXml = require('./dynamic-xml.service')
+import { expect } from 'chai'
+import sinon from 'sinon'
+import xpath from 'xpath'
+import { test, given } from 'sazerac'
+import { InvalidResponse } from '../index.js'
+import DynamicXml from './dynamic-xml.service.js'
 
 const exampleXml = `<?xml version="1.0"?>
 <catalog>
diff --git a/services/dynamic/dynamic-xml.tester.js b/services/dynamic/dynamic-xml.tester.js
index d0b76cef41e0d2d94365e95f866fdf5e742a7899..a35d303c3ec41c924f2c8425e1716540dec9f847 100644
--- a/services/dynamic/dynamic-xml.tester.js
+++ b/services/dynamic/dynamic-xml.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const queryString = require('query-string')
-const t = (module.exports = require('../tester').createServiceTester())
-const { exampleXml } = require('./dynamic-response-fixtures')
+import queryString from 'query-string'
+import { createServiceTester } from '../tester.js'
+import { exampleXml } from './dynamic-response-fixtures.js'
+export const t = await createServiceTester()
 
 const exampleUrl = 'https://example.test/example.xml'
 const withExampleXml = nock =>
diff --git a/services/dynamic/dynamic-yaml.service.js b/services/dynamic/dynamic-yaml.service.js
index a77471708606b6bb122f606caefc8503a4354229..1c606f90334ea1678af4d6ee5a2fc27ef244f2d2 100644
--- a/services/dynamic/dynamic-yaml.service.js
+++ b/services/dynamic/dynamic-yaml.service.js
@@ -1,11 +1,9 @@
-'use strict'
+import { MetricNames } from '../../core/base-service/metric-helper.js'
+import { BaseYamlService } from '../index.js'
+import { createRoute } from './dynamic-helpers.js'
+import jsonPath from './json-path.js'
 
-const { MetricNames } = require('../../core/base-service/metric-helper')
-const { BaseYamlService } = require('..')
-const { createRoute } = require('./dynamic-helpers')
-const jsonPath = require('./json-path')
-
-module.exports = class DynamicYaml extends jsonPath(BaseYamlService) {
+export default class DynamicYaml extends jsonPath(BaseYamlService) {
   static enabledMetrics = [MetricNames.SERVICE_RESPONSE_SIZE]
   static route = createRoute('yaml')
 
diff --git a/services/dynamic/dynamic-yaml.tester.js b/services/dynamic/dynamic-yaml.tester.js
index cb04be8bcf2e2e0cb2c617c945c84ae059fe2171..e3d5cce1fcae3597a36eebe250edc4c6d4c0dfa3 100644
--- a/services/dynamic/dynamic-yaml.tester.js
+++ b/services/dynamic/dynamic-yaml.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('No URL specified')
   .get('.json?query=$.name&label=Package Name')
diff --git a/services/dynamic/json-path.js b/services/dynamic/json-path.js
index 9797e81673650d063e87601987126bc2ae062b98..ed242c944aaf4367de566954d668a33912f4b019 100644
--- a/services/dynamic/json-path.js
+++ b/services/dynamic/json-path.js
@@ -2,12 +2,10 @@
  * @module
  */
 
-'use strict'
-
-const Joi = require('joi')
-const jp = require('jsonpath')
-const { renderDynamicBadge, errorMessages } = require('../dynamic-common')
-const { InvalidParameter, InvalidResponse } = require('..')
+import Joi from 'joi'
+import jp from 'jsonpath'
+import { renderDynamicBadge, errorMessages } from '../dynamic-common.js'
+import { InvalidParameter, InvalidResponse } from '../index.js'
 
 /**
  * Dynamic service class factory which wraps {@link module:core/base-service/base~BaseService} with support of {@link https://jsonpath.com/|JSONPath}.
@@ -15,7 +13,7 @@ const { InvalidParameter, InvalidResponse } = require('..')
  * @param {Function} superclass class to extend
  * @returns {Function} wrapped class
  */
-module.exports = superclass =>
+export default superclass =>
   class extends superclass {
     static category = 'dynamic'
     static defaultBadgeData = { label: 'custom badge' }
diff --git a/services/dynamic/json-path.spec.js b/services/dynamic/json-path.spec.js
index ca30499f8ec3187723209549df927d582f44be33..7e309dba653f69b408c5b89e8c20dc8d4e04ccba 100644
--- a/services/dynamic/json-path.spec.js
+++ b/services/dynamic/json-path.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const chai = require('chai')
+import chai from 'chai'
+import chaiAsPromised from 'chai-as-promised'
+import jsonPath from './json-path.js'
 const { expect } = chai
-const jsonPath = require('./json-path')
-
-chai.use(require('chai-as-promised'))
+chai.use(chaiAsPromised)
 
 describe('JSON Path service factory', function () {
   describe('fetch()', function () {
diff --git a/services/eclipse-marketplace/eclipse-marketplace-base.js b/services/eclipse-marketplace/eclipse-marketplace-base.js
index fd8c5387b04f0b427523cbbe48e8b607a3595a0c..a4276731b9582f03c1affc8c4b72bab192af9dfd 100644
--- a/services/eclipse-marketplace/eclipse-marketplace-base.js
+++ b/services/eclipse-marketplace/eclipse-marketplace-base.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseXmlService } from '../index.js'
 
-const { BaseXmlService } = require('..')
-
-module.exports = class EclipseMarketplaceBase extends BaseXmlService {
+export default class EclipseMarketplaceBase extends BaseXmlService {
   static buildRoute(base) {
     return {
       base,
diff --git a/services/eclipse-marketplace/eclipse-marketplace-downloads.service.js b/services/eclipse-marketplace/eclipse-marketplace-downloads.service.js
index ae4fb3fa39242d3825f3c32095e0f098860dffb6..c7cbaf118379cd1e977bfdd2b90df97fcdb70f9e 100644
--- a/services/eclipse-marketplace/eclipse-marketplace-downloads.service.js
+++ b/services/eclipse-marketplace/eclipse-marketplace-downloads.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { downloadCount: downloadCountColor } = require('../color-formatters')
-const { nonNegativeInteger } = require('../validators')
-const EclipseMarketplaceBase = require('./eclipse-marketplace-base')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { downloadCount as downloadCountColor } from '../color-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import EclipseMarketplaceBase from './eclipse-marketplace-base.js'
 
 const monthlyResponseSchema = Joi.object({
   marketplace: Joi.object({
@@ -72,4 +70,4 @@ function DownloadsForInterval(interval) {
   }
 }
 
-module.exports = ['month', 'total'].map(DownloadsForInterval)
+export default ['month', 'total'].map(DownloadsForInterval)
diff --git a/services/eclipse-marketplace/eclipse-marketplace-downloads.tester.js b/services/eclipse-marketplace/eclipse-marketplace-downloads.tester.js
index 878fe844c08161c332621397ef3d5bfacdf7b163..a73862ee73271fd3c49887dd88ff8b0e10a8f841 100644
--- a/services/eclipse-marketplace/eclipse-marketplace-downloads.tester.js
+++ b/services/eclipse-marketplace/eclipse-marketplace-downloads.tester.js
@@ -1,13 +1,11 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isMetric, isMetricOverTimePeriod } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isMetric, isMetricOverTimePeriod } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'EclipseMarketplaceDownloads',
   title: 'EclipseMarketplaceDownloads',
   pathPrefix: '/eclipse-marketplace',
-}))
+})
 
 t.create('total marketplace downloads').get('/dt/notepad4e.json').expectBadge({
   label: 'downloads',
diff --git a/services/eclipse-marketplace/eclipse-marketplace-favorites.service.js b/services/eclipse-marketplace/eclipse-marketplace-favorites.service.js
index 0b648a91ce73c52b3e1eba4097736802087adbc2..1f004bad2262f652cff4d152ececc068c8210771 100644
--- a/services/eclipse-marketplace/eclipse-marketplace-favorites.service.js
+++ b/services/eclipse-marketplace/eclipse-marketplace-favorites.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const EclipseMarketplaceBase = require('./eclipse-marketplace-base')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import EclipseMarketplaceBase from './eclipse-marketplace-base.js'
 
 const favoritesResponseSchema = Joi.object({
   marketplace: Joi.object({
@@ -12,9 +10,7 @@ const favoritesResponseSchema = Joi.object({
   }),
 }).required()
 
-module.exports = class EclipseMarketplaceFavorites extends (
-  EclipseMarketplaceBase
-) {
+export default class EclipseMarketplaceFavorites extends EclipseMarketplaceBase {
   static category = 'other'
   static route = this.buildRoute('eclipse-marketplace/favorites')
   static examples = [
diff --git a/services/eclipse-marketplace/eclipse-marketplace-favorites.tester.js b/services/eclipse-marketplace/eclipse-marketplace-favorites.tester.js
index 4322263077a893ec11196c6b79e20baf232f1bb1..74ceb06d6ab78e277b8a485441a1b562987c4588 100644
--- a/services/eclipse-marketplace/eclipse-marketplace-favorites.tester.js
+++ b/services/eclipse-marketplace/eclipse-marketplace-favorites.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('favorites count').get('/notepad4e.json').expectBadge({
   label: 'favorites',
diff --git a/services/eclipse-marketplace/eclipse-marketplace-license.service.js b/services/eclipse-marketplace/eclipse-marketplace-license.service.js
index 4faf06a48617cc702a056833ed6d47db91a437d8..b25b0ac223c18847ac199599a8c5f7ec5c723b4f 100644
--- a/services/eclipse-marketplace/eclipse-marketplace-license.service.js
+++ b/services/eclipse-marketplace/eclipse-marketplace-license.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const EclipseMarketplaceBase = require('./eclipse-marketplace-base')
+import Joi from 'joi'
+import EclipseMarketplaceBase from './eclipse-marketplace-base.js'
 
 const licenseResponseSchema = Joi.object({
   marketplace: Joi.object({
@@ -11,9 +9,7 @@ const licenseResponseSchema = Joi.object({
   }),
 }).required()
 
-module.exports = class EclipseMarketplaceLicense extends (
-  EclipseMarketplaceBase
-) {
+export default class EclipseMarketplaceLicense extends EclipseMarketplaceBase {
   static category = 'license'
   static route = this.buildRoute('eclipse-marketplace/l')
   static examples = [
diff --git a/services/eclipse-marketplace/eclipse-marketplace-license.tester.js b/services/eclipse-marketplace/eclipse-marketplace-license.tester.js
index f7b9d8be1a6b5e0cd12e0e5ec47709419d48e54a..471651696b29519cd0203b2783a7339daacfb305 100644
--- a/services/eclipse-marketplace/eclipse-marketplace-license.tester.js
+++ b/services/eclipse-marketplace/eclipse-marketplace-license.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('license').get('/notepad4e.json').expectBadge({
   label: 'license',
diff --git a/services/eclipse-marketplace/eclipse-marketplace-update.service.js b/services/eclipse-marketplace/eclipse-marketplace-update.service.js
index 68361338e7c87d81e69900fc54dca63143c0c2d1..a13b7d0d03ddc419d20283950ee6319f7ab5d27b 100644
--- a/services/eclipse-marketplace/eclipse-marketplace-update.service.js
+++ b/services/eclipse-marketplace/eclipse-marketplace-update.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { formatDate } = require('../text-formatters')
-const { age: ageColor } = require('../color-formatters')
-const { nonNegativeInteger } = require('../validators')
-const EclipseMarketplaceBase = require('./eclipse-marketplace-base')
+import Joi from 'joi'
+import { formatDate } from '../text-formatters.js'
+import { age as ageColor } from '../color-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import EclipseMarketplaceBase from './eclipse-marketplace-base.js'
 
 const updateResponseSchema = Joi.object({
   marketplace: Joi.object({
@@ -14,7 +12,7 @@ const updateResponseSchema = Joi.object({
   }),
 }).required()
 
-module.exports = class EclipseMarketplaceUpdate extends EclipseMarketplaceBase {
+export default class EclipseMarketplaceUpdate extends EclipseMarketplaceBase {
   static category = 'activity'
   static route = this.buildRoute('eclipse-marketplace/last-update')
   static examples = [
diff --git a/services/eclipse-marketplace/eclipse-marketplace-update.tester.js b/services/eclipse-marketplace/eclipse-marketplace-update.tester.js
index af1b8628d8eed756ef302a36bd703f996fb9acc7..fd0d6e756bd51f10474241df7dc788831d303c3a 100644
--- a/services/eclipse-marketplace/eclipse-marketplace-update.tester.js
+++ b/services/eclipse-marketplace/eclipse-marketplace-update.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isFormattedDate } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isFormattedDate } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('last update date').get('/notepad4e.json').expectBadge({
   label: 'updated',
diff --git a/services/eclipse-marketplace/eclipse-marketplace-version.service.js b/services/eclipse-marketplace/eclipse-marketplace-version.service.js
index 6f15d0b2e305ed94760d363df3cfd3808697d534..0e367fa12595da011f2afd61a9ea3b21f7366095 100644
--- a/services/eclipse-marketplace/eclipse-marketplace-version.service.js
+++ b/services/eclipse-marketplace/eclipse-marketplace-version.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const EclipseMarketplaceBase = require('./eclipse-marketplace-base')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import EclipseMarketplaceBase from './eclipse-marketplace-base.js'
 
 const versionResponseSchema = Joi.object({
   marketplace: Joi.object({
@@ -12,9 +10,7 @@ const versionResponseSchema = Joi.object({
   }),
 }).required()
 
-module.exports = class EclipseMarketplaceVersion extends (
-  EclipseMarketplaceBase
-) {
+export default class EclipseMarketplaceVersion extends EclipseMarketplaceBase {
   static category = 'version'
   static route = this.buildRoute('eclipse-marketplace/v')
   static examples = [
diff --git a/services/eclipse-marketplace/eclipse-marketplace-version.tester.js b/services/eclipse-marketplace/eclipse-marketplace-version.tester.js
index b3e58b9bc816452371adfda7f2d0ad86a00df317..c47a95c8eea689b2ef46a955b151c99b13426d8f 100644
--- a/services/eclipse-marketplace/eclipse-marketplace-version.tester.js
+++ b/services/eclipse-marketplace/eclipse-marketplace-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('marketplace version').get('/notepad4e.json').expectBadge({
   label: 'eclipse marketplace',
diff --git a/services/ecologi/ecologi-carbon.service.js b/services/ecologi/ecologi-carbon.service.js
index b2eb4040e015779058cb896447eb2f6846ec6d18..4aac425d1e60870bf5f08c55afc975fd18bd648a 100644
--- a/services/ecologi/ecologi-carbon.service.js
+++ b/services/ecologi/ecologi-carbon.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { floorCount } = require('../color-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { floorCount } from '../color-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const apiSchema = Joi.object({
   total: Joi.number().positive().required(),
 }).required()
 
-module.exports = class EcologiCarbonOffset extends BaseJsonService {
+export default class EcologiCarbonOffset extends BaseJsonService {
   static category = 'other'
   static route = { base: 'ecologi/carbon', pattern: ':username' }
   static examples = [
diff --git a/services/ecologi/ecologi-carbon.tester.js b/services/ecologi/ecologi-carbon.tester.js
index 55cacdf10306dc6f077b9ef212ab37e6f3098186..17394e5e293b77d40edba316af00efbdb375a2a9 100644
--- a/services/ecologi/ecologi-carbon.tester.js
+++ b/services/ecologi/ecologi-carbon.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { withRegex } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { withRegex } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('request for existing username')
   .get('/ecologi.json')
diff --git a/services/ecologi/ecologi-trees.service.js b/services/ecologi/ecologi-trees.service.js
index d2e0a98f485b6135808c4dd7c5f460fb39b4a783..46d41b2f00f191b02dbd26bf2055a67b27d910c7 100644
--- a/services/ecologi/ecologi-trees.service.js
+++ b/services/ecologi/ecologi-trees.service.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { floorCount } = require('../color-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { floorCount } from '../color-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const apiSchema = Joi.object({
   total: nonNegativeInteger,
 }).required()
 
-module.exports = class EcologiTrees extends BaseJsonService {
+export default class EcologiTrees extends BaseJsonService {
   static category = 'other'
   static route = { base: 'ecologi/trees', pattern: ':username' }
   static examples = [
diff --git a/services/ecologi/ecologi-trees.tester.js b/services/ecologi/ecologi-trees.tester.js
index 3627695a489864302cfc952466df3ea9b6e83379..01d776263a396e81a67b3cee6fb32512d217245b 100644
--- a/services/ecologi/ecologi-trees.tester.js
+++ b/services/ecologi/ecologi-trees.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isMetric } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('request for existing username').get('/ecologi.json').expectBadge({
   label: 'trees',
diff --git a/services/elm-package/elm-package.service.js b/services/elm-package/elm-package.service.js
index f2f7e45736a3b99105092f21d42d83a931342cc0..dd606d090c0ffacb130a027dd813b7148e9775b7 100644
--- a/services/elm-package/elm-package.service.js
+++ b/services/elm-package/elm-package.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { semver } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { semver } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({ version: semver }).required()
 
-module.exports = class ElmPackage extends BaseJsonService {
+export default class ElmPackage extends BaseJsonService {
   static category = 'version'
   static route = { base: 'elm-package/v', pattern: ':user/:packageName' }
   static examples = [
diff --git a/services/elm-package/elm-package.tester.js b/services/elm-package/elm-package.tester.js
index d432de124705f6f36f5a7f512647391420d4fab5..b1c07737a607cf8f99117521f0a5ab75f52566e2 100644
--- a/services/elm-package/elm-package.tester.js
+++ b/services/elm-package/elm-package.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isSemver } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isSemver } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('gets the package version of elm/core')
   .get('/elm/core.json')
diff --git a/services/endpoint-common.js b/services/endpoint-common.js
index 81e159bf57e0f9f72c7a50aaeb051a2f5ee3a42c..1f3cf8d00cff6ab75627794efa099078e715646e 100644
--- a/services/endpoint-common.js
+++ b/services/endpoint-common.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const validate = require('../core/base-service/validate')
-const { InvalidResponse } = require('.')
+import Joi from 'joi'
+import validate from '../core/base-service/validate.js'
+import { InvalidResponse } from './index.js'
 
 const optionalStringWhenNamedLogoPresent = Joi.alternatives().conditional(
   'namedLogo',
@@ -74,7 +72,4 @@ async function fetchEndpointData(
   })
 }
 
-module.exports = {
-  validateEndpointData,
-  fetchEndpointData,
-}
+export { validateEndpointData, fetchEndpointData }
diff --git a/services/endpoint/endpoint-redirect.service.js b/services/endpoint/endpoint-redirect.service.js
index 4501e3e6a378ca8f7c14947a0ea188dac172d6cb..c8db8c7de1f32bcd4de6eeff9efcc454ea26ada0 100644
--- a/services/endpoint/endpoint-redirect.service.js
+++ b/services/endpoint/endpoint-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = redirector({
+export default redirector({
   category: 'other',
   route: {
     base: 'badge/endpoint',
diff --git a/services/endpoint/endpoint-redirect.tester.js b/services/endpoint/endpoint-redirect.tester.js
index 097c083fe40215588473f19d8d970160f80f0fcb..e0c6de4a5865e7edb355273a96877add5ee98032 100644
--- a/services/endpoint/endpoint-redirect.tester.js
+++ b/services/endpoint/endpoint-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'EndpointRedirect',
   title: 'EndpointRedirect',
   pathPrefix: '/badge/endpoint',
-}))
+})
 
 t.create('Build: default branch')
   .get('.svg?url=https://example.com/badge.json')
diff --git a/services/endpoint/endpoint.service.js b/services/endpoint/endpoint.service.js
index 007fc40a07fde6e57c4d4cb62dc7ea33581eaf31..8a64ccc74ca88dbb509b4fd7091830ba47a4eae1 100644
--- a/services/endpoint/endpoint.service.js
+++ b/services/endpoint/endpoint.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { URL } = require('url')
-const Joi = require('joi')
-const { errorMessages } = require('../dynamic-common')
-const { optionalUrl } = require('../validators')
-const { fetchEndpointData } = require('../endpoint-common')
-const { BaseJsonService, InvalidParameter } = require('..')
+import { URL } from 'url'
+import Joi from 'joi'
+import { errorMessages } from '../dynamic-common.js'
+import { optionalUrl } from '../validators.js'
+import { fetchEndpointData } from '../endpoint-common.js'
+import { BaseJsonService, InvalidParameter } from '../index.js'
 
 const blockedDomains = ['github.com', 'shields.io']
 
@@ -13,7 +11,7 @@ const queryParamSchema = Joi.object({
   url: optionalUrl.required(),
 }).required()
 
-module.exports = class Endpoint extends BaseJsonService {
+export default class Endpoint extends BaseJsonService {
   static category = 'dynamic'
   static route = {
     base: 'endpoint',
diff --git a/services/endpoint/endpoint.tester.js b/services/endpoint/endpoint.tester.js
index 2001439674cf91e7889de8c555124fa0a4b6f47e..3be249e02cea0aec77c1d8c353320f6453a02d7d 100644
--- a/services/endpoint/endpoint.tester.js
+++ b/services/endpoint/endpoint.tester.js
@@ -1,9 +1,8 @@
-'use strict'
-
-const zlib = require('zlib')
-const { expect } = require('chai')
-const { getShieldsIcon } = require('../../lib/logos')
-const t = (module.exports = require('../tester').createServiceTester())
+import zlib from 'zlib'
+import { expect } from 'chai'
+import { getShieldsIcon } from '../../lib/logos.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Valid schema')
   .get('.json?url=https://example.com/badge')
diff --git a/services/f-droid/f-droid.service.js b/services/f-droid/f-droid.service.js
index 127e426269df7911690675c07cc53ecc45b8eb28..3ce765eb202c2013e5e3fce0b588db448158d3fc 100644
--- a/services/f-droid/f-droid.service.js
+++ b/services/f-droid/f-droid.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const {
+import Joi from 'joi'
+import {
   optionalNonNegativeInteger,
   nonNegativeInteger,
-} = require('../validators')
-const { addv } = require('../text-formatters')
-const { version: versionColor } = require('../color-formatters')
-const { BaseJsonService, NotFound } = require('..')
+} from '../validators.js'
+import { addv } from '../text-formatters.js'
+import { version as versionColor } from '../color-formatters.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const schema = Joi.object({
   packageName: Joi.string().required(),
@@ -22,7 +20,7 @@ const queryParamSchema = Joi.object({
   include_prereleases: Joi.equal(''),
 }).required()
 
-module.exports = class FDroid extends BaseJsonService {
+export default class FDroid extends BaseJsonService {
   static category = 'version'
   static route = { base: 'f-droid/v', pattern: ':appId', queryParamSchema }
   static examples = [
diff --git a/services/f-droid/f-droid.tester.js b/services/f-droid/f-droid.tester.js
index 5d77c54eb2f2b3cb282011948c1bc679c3ef2181..ea63f06ee635d306499dcd3db9a1c423b4d4c077 100644
--- a/services/f-droid/f-droid.tester.js
+++ b/services/f-droid/f-droid.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'f-droid',
   title: 'F-Droid',
-}))
+})
 
 const testPkg = 'org.fdroid.fdroid.privileged'
 const testJson = `
diff --git a/services/fedora/fedora.service.js b/services/fedora/fedora.service.js
index 80e39535411a1a37083d65d6dc547a031289014b..d869bcd6efef1d8335efa7e81abe41b49661c9fe 100644
--- a/services/fedora/fedora.service.js
+++ b/services/fedora/fedora.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   version: Joi.string().required(),
@@ -11,7 +9,7 @@ const schema = Joi.object({
 // No way to permalink to current "stable", https://pagure.io/mdapi/issue/69
 const defaultBranch = 'rawhide'
 
-module.exports = class Fedora extends BaseJsonService {
+export default class Fedora extends BaseJsonService {
   static category = 'version'
   static route = { base: 'fedora/v', pattern: ':packageName/:branch?' }
   static examples = [
diff --git a/services/fedora/fedora.tester.js b/services/fedora/fedora.tester.js
index 134b5e84a25950ad78d5a992a6295271bf86527c..51f0d38c5165b46608c7b0e41c16d4ad45a590d6 100644
--- a/services/fedora/fedora.tester.js
+++ b/services/fedora/fedora.tester.js
@@ -1,9 +1,6 @@
-'use strict'
-
-const {
-  isVPlusDottedVersionNClausesWithOptionalSuffixAndEpoch,
-} = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionNClausesWithOptionalSuffixAndEpoch } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Fedora package (default branch, valid)')
   .get('/rpm.json')
diff --git a/services/feedz/feedz.service.js b/services/feedz/feedz.service.js
index 0e6563558836014edddb567d6c3059a555e52208..54d237de38116ad9d6b7e47f57b928435f07696f 100644
--- a/services/feedz/feedz.service.js
+++ b/services/feedz/feedz.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService, NotFound } = require('..')
-const {
+import Joi from 'joi'
+import { BaseJsonService, NotFound } from '../index.js'
+import {
   renderVersionBadge,
   searchServiceUrl,
   stripBuildMetadata,
   selectVersion,
-} = require('../nuget/nuget-helpers')
+} from '../nuget/nuget-helpers.js'
 
 const schema = Joi.object({
   items: Joi.array()
@@ -105,6 +103,4 @@ class FeedzVersionService extends BaseJsonService {
   }
 }
 
-module.exports = {
-  FeedzVersionService,
-}
+export { FeedzVersionService }
diff --git a/services/feedz/feedz.service.spec.js b/services/feedz/feedz.service.spec.js
index 47189d6e2c39e99c524fa738674bfab1f6d66d0d..c6f1444c39f8cdafd5e16ad466f16d7903e6eeeb 100644
--- a/services/feedz/feedz.service.spec.js
+++ b/services/feedz/feedz.service.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { FeedzVersionService } = require('./feedz.service')
+import { test, given } from 'sazerac'
+import { FeedzVersionService } from './feedz.service.js'
 
 function json(versions) {
   return {
diff --git a/services/feedz/feedz.tester.js b/services/feedz/feedz.tester.js
index 70980d3a5dcbad1b9c80fbe6a2ae9b39c25484ab..99133e102535277796a6716f54a441c761d726bb 100644
--- a/services/feedz/feedz.tester.js
+++ b/services/feedz/feedz.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'feedz',
   title: 'Feedz',
   pathPrefix: '',
-}))
+})
 
 // The `shieldstests/public` repo is specifically made for these tests. It contains following packages:
 //  - Shields.NoV1: 0.1.0
diff --git a/services/flathub/flathub.service.js b/services/flathub/flathub.service.js
index 6f5b9ad89f3176bbab822502c45cc96b5090a990..1b46191ebb9f8f77cce44b230ee9f77dceedfeea 100644
--- a/services/flathub/flathub.service.js
+++ b/services/flathub/flathub.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   currentReleaseVersion: Joi.string().required(),
 }).required()
 
-module.exports = class Flathub extends BaseJsonService {
+export default class Flathub extends BaseJsonService {
   static category = 'version'
   static route = { base: 'flathub/v', pattern: ':packageName' }
   static examples = [
diff --git a/services/flathub/flathub.tester.js b/services/flathub/flathub.tester.js
index ce276ab7b490086c3d538518d3c1b5c0ee1141f9..727497013dea64cc9d9c573c4e15d6f7dbaf4bca 100644
--- a/services/flathub/flathub.tester.js
+++ b/services/flathub/flathub.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionNClauses } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionNClauses } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Flathub (valid)').get('/org.mozilla.firefox.json').expectBadge({
   label: 'flathub',
diff --git a/services/gem/gem-downloads.service.js b/services/gem/gem-downloads.service.js
index f2e697cde370b95fe0dedb471eb7b18f55612b3a..fc72bb3519d6b24ba2c528f25e4ecac03bf25aaa 100644
--- a/services/gem/gem-downloads.service.js
+++ b/services/gem/gem-downloads.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const semver = require('semver')
-const Joi = require('joi')
-const { downloadCount } = require('../color-formatters')
-const { metric } = require('../text-formatters')
-const { latest: latestVersion } = require('../version')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService, InvalidParameter, InvalidResponse } = require('..')
+import semver from 'semver'
+import Joi from 'joi'
+import { downloadCount } from '../color-formatters.js'
+import { metric } from '../text-formatters.js'
+import { latest as latestVersion } from '../version.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService, InvalidParameter, InvalidResponse } from '../index.js'
 
 const keywords = ['ruby']
 
@@ -26,7 +24,7 @@ const versionSchema = Joi.array()
   .min(1)
   .required()
 
-module.exports = class GemDownloads extends BaseJsonService {
+export default class GemDownloads extends BaseJsonService {
   static category = 'downloads'
   static route = { base: 'gem', pattern: ':variant(dt|dtv|dv)/:gem/:version?' }
   static examples = [
diff --git a/services/gem/gem-downloads.tester.js b/services/gem/gem-downloads.tester.js
index bb3ccfed0681927b7b3cca127bfd5d1f3eee60d6..cd709bb4bfe1c81044a13711ad1eb7e9b9d7441e 100644
--- a/services/gem/gem-downloads.tester.js
+++ b/services/gem/gem-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('total downloads (valid)').get('/dt/rails.json').expectBadge({
   label: 'downloads',
diff --git a/services/gem/gem-owner.service.js b/services/gem/gem-owner.service.js
index 1be79b524505cf8e600a91f7ac1a4756c1e85ca1..5ed9d0df7dd4017d25e32c41ee084bcd13d10d4b 100644
--- a/services/gem/gem-owner.service.js
+++ b/services/gem/gem-owner.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const { floorCount: floorCountColor } = require('../color-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { floorCount as floorCountColor } from '../color-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const ownerSchema = Joi.array().required()
 
-module.exports = class GemOwner extends BaseJsonService {
+export default class GemOwner extends BaseJsonService {
   static category = 'other'
   static route = { base: 'gem/u', pattern: ':user' }
   static examples = [
diff --git a/services/gem/gem-owner.tester.js b/services/gem/gem-owner.tester.js
index 80d1d9286c8d7fbb2caca23af47363ef0269f0aa..9156752cb3553eb20ed53b5bd008006f66334994 100644
--- a/services/gem/gem-owner.tester.js
+++ b/services/gem/gem-owner.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('users (valid)')
   .get('/raphink.json')
diff --git a/services/gem/gem-rank.service.js b/services/gem/gem-rank.service.js
index 1a78371e9212ee0fbeba23e95bb88218133abfa2..de46d4933649d5834652e5eea508d3bfef03c39e 100644
--- a/services/gem/gem-rank.service.js
+++ b/services/gem/gem-rank.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { floorCount } = require('../color-formatters')
-const { ordinalNumber } = require('../text-formatters')
-const { BaseJsonService, InvalidResponse } = require('..')
+import Joi from 'joi'
+import { floorCount } from '../color-formatters.js'
+import { ordinalNumber } from '../text-formatters.js'
+import { BaseJsonService, InvalidResponse } from '../index.js'
 
 const keywords = ['ruby']
 
@@ -24,7 +22,7 @@ const dailySchema = Joi.array()
   .min(1)
   .required()
 
-module.exports = class GemRank extends BaseJsonService {
+export default class GemRank extends BaseJsonService {
   static category = 'downloads'
   static route = { base: 'gem', pattern: ':period(rt|rd)/:gem' }
   static examples = [
diff --git a/services/gem/gem-rank.tester.js b/services/gem/gem-rank.tester.js
index 4cc5d89fcd82170f2ff414f0ca420044ad8b20b3..73626c7b9c926fe63398abe0ee0844a52b40b919 100644
--- a/services/gem/gem-rank.tester.js
+++ b/services/gem/gem-rank.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isOrdinalNumber = Joi.string().regex(/^[1-9][0-9]+(ᵗʰ|ˢᵗ|ⁿᵈ|ʳᵈ)$/)
 const isOrdinalNumberDaily = Joi.string().regex(
diff --git a/services/gem/gem-version.service.js b/services/gem/gem-version.service.js
index fba13f7d933d4f6e2e2d2e77205b822f6ea26de0..d122c625c6a465b93f07c7c168fec02622edb2ac 100644
--- a/services/gem/gem-version.service.js
+++ b/services/gem/gem-version.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge, latest } = require('../version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge, latest } from '../version.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   // In most cases `version` will be a SemVer but the registry doesn't
@@ -23,7 +21,7 @@ const queryParamSchema = Joi.object({
   include_prereleases: Joi.equal(''),
 }).required()
 
-module.exports = class GemVersion extends BaseJsonService {
+export default class GemVersion extends BaseJsonService {
   static category = 'version'
   static route = { base: 'gem/v', pattern: ':gem', queryParamSchema }
   static examples = [
diff --git a/services/gem/gem-version.tester.js b/services/gem/gem-version.tester.js
index 6877777e14c33f91ce900184363bee9f1d07f5db..0043e2ff9be924dc82186046837dabdf158c2bb8 100644
--- a/services/gem/gem-version.tester.js
+++ b/services/gem/gem-version.tester.js
@@ -1,10 +1,9 @@
-'use strict'
-
-const {
+import {
   isVPlusDottedVersionAtLeastOne,
   withRegex,
-} = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+} from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('version (valid)').get('/formatador.json').expectBadge({
   label: 'gem',
diff --git a/services/gemnasium/gemnasium.service.js b/services/gemnasium/gemnasium.service.js
index b3a76ac147a962503b960633480e696431873303..ddcaeba5fedb07d4ad1a84ddc8ef005d99f2a5ff 100644
--- a/services/gemnasium/gemnasium.service.js
+++ b/services/gemnasium/gemnasium.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'dependencies',
   route: {
     base: 'gemnasium',
diff --git a/services/gemnasium/gemnasium.tester.js b/services/gemnasium/gemnasium.tester.js
index 152a1ed98577c5088ca3bb3c7be5dc0c6849c763..9e5431424fcf818daca42f6ef9ab1c90df38894a 100644
--- a/services/gemnasium/gemnasium.tester.js
+++ b/services/gemnasium/gemnasium.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'gemnasium',
   title: 'gemnasium',
-}))
+})
 
 t.create('no longer available (previously dependencies)')
   .get('/mathiasbynens/he.json')
diff --git a/services/gerrit/gerrit.service.js b/services/gerrit/gerrit.service.js
index 4a3c4df77ed1eebda0f4441037fa15d5e656472f..04ebca37578d278f72e7ce6528ef5880d6de4a94 100644
--- a/services/gerrit/gerrit.service.js
+++ b/services/gerrit/gerrit.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const queryParamSchema = Joi.object({
   baseUrl: optionalUrl.required(),
@@ -12,7 +10,7 @@ const schema = Joi.object({
   status: Joi.equal('NEW', 'MERGED', 'ABANDONED').required(),
 }).required()
 
-module.exports = class Gerrit extends BaseJsonService {
+export default class Gerrit extends BaseJsonService {
   static category = 'issue-tracking'
   static route = { base: 'gerrit', pattern: ':changeId', queryParamSchema }
   static examples = [
diff --git a/services/gerrit/gerrit.tester.js b/services/gerrit/gerrit.tester.js
index b4468af421a727fedf1e34892c07600bf08e2acf..2b80baf7cc5de4111f77174b916ea8f29a711f61 100644
--- a/services/gerrit/gerrit.tester.js
+++ b/services/gerrit/gerrit.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // Change open since December 2010, hopefully won't get merged or abandoned anytime soon.
 t.create('Gerrit new change')
diff --git a/services/github/auth/acceptor.js b/services/github/auth/acceptor.js
index 2b6145ea22d0af2112b16fd45b9bbbb9a2a440ac..80347be581ca2f31bded9d33059fda4108cb6465 100644
--- a/services/github/auth/acceptor.js
+++ b/services/github/auth/acceptor.js
@@ -1,11 +1,7 @@
-'use strict'
-
-const queryString = require('query-string')
-const request = require('request')
-const {
-  userAgent,
-} = require('../../../core/base-service/legacy-request-handler')
-const log = require('../../../core/server/log')
+import queryString from 'query-string'
+import request from 'request'
+import { userAgent } from '../../../core/base-service/legacy-request-handler.js'
+import log from '../../../core/server/log.js'
 
 function setRoutes({ server, authHelper, onTokenAccepted }) {
   const baseUrl = process.env.GATSBY_BASE_URL || 'https://img.shields.io'
@@ -29,7 +25,7 @@ function setRoutes({ server, authHelper, onTokenAccepted }) {
 
   server.route(/^\/github-auth\/done$/, (data, match, end, ask) => {
     if (!data.code) {
-      log(`GitHub OAuth data: ${JSON.stringify(data)}`)
+      log.log(`GitHub OAuth data: ${JSON.stringify(data)}`)
       return end('GitHub OAuth authentication failed to provide a code.')
     }
 
@@ -85,4 +81,4 @@ function setRoutes({ server, authHelper, onTokenAccepted }) {
   })
 }
 
-module.exports = { setRoutes }
+export { setRoutes }
diff --git a/services/github/auth/acceptor.spec.js b/services/github/auth/acceptor.spec.js
index 523d3589f73e86fc47309fb659ca85a9dfa28cd8..2d6cab6e24d839e76a8155c076bb33d84302b089 100644
--- a/services/github/auth/acceptor.spec.js
+++ b/services/github/auth/acceptor.spec.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const { expect } = require('chai')
-const Camp = require('@shields_io/camp')
-const FormData = require('form-data')
-const sinon = require('sinon')
-const portfinder = require('portfinder')
-const queryString = require('query-string')
-const nock = require('nock')
-const got = require('../../../core/got-test-client')
-const GithubConstellation = require('../github-constellation')
-const acceptor = require('./acceptor')
+import { expect } from 'chai'
+import Camp from '@shields_io/camp'
+import FormData from 'form-data'
+import sinon from 'sinon'
+import portfinder from 'portfinder'
+import queryString from 'query-string'
+import nock from 'nock'
+import got from '../../../core/got-test-client.js'
+import GithubConstellation from '../github-constellation.js'
+import { setRoutes } from './acceptor.js'
 
 const fakeClientId = 'githubdabomb'
 
@@ -39,7 +37,7 @@ describe('Github token acceptor', function () {
   let onTokenAccepted
   beforeEach(function () {
     onTokenAccepted = sinon.stub()
-    acceptor.setRoutes({
+    setRoutes({
       server: camp,
       authHelper: oauthHelper,
       onTokenAccepted,
diff --git a/services/github/auth/admin.js b/services/github/auth/admin.js
index 52a8dbd8feb3514b0d470e9a64352290b5842590..9ffea4d0564156b5987f7c1f52732fbc186614c4 100644
--- a/services/github/auth/admin.js
+++ b/services/github/auth/admin.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { makeSecretIsValid } = require('../../../core/server/secret-is-valid')
+import { makeSecretIsValid } from '../../../core/server/secret-is-valid.js'
 
 function setRoutes({ shieldsSecret }, { apiProvider, server }) {
   const secretIsValid = makeSecretIsValid(shieldsSecret)
@@ -31,4 +29,4 @@ function setRoutes({ shieldsSecret }, { apiProvider, server }) {
   })
 }
 
-module.exports = { setRoutes }
+export { setRoutes }
diff --git a/services/github/auth/admin.spec.js b/services/github/auth/admin.spec.js
index 438c8386d87a691082fa946c0e175ef9c68a2a44..fb751498e02706892b7d9d41aa2f98a843b0b519 100644
--- a/services/github/auth/admin.spec.js
+++ b/services/github/auth/admin.spec.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { expect } = require('chai')
-const Camp = require('@shields_io/camp')
-const portfinder = require('portfinder')
-const got = require('../../../core/got-test-client')
-const GithubApiProvider = require('../github-api-provider')
-const { setRoutes } = require('./admin')
+import { expect } from 'chai'
+import Camp from '@shields_io/camp'
+import portfinder from 'portfinder'
+import got from '../../../core/got-test-client.js'
+import GithubApiProvider from '../github-api-provider.js'
+import { setRoutes } from './admin.js'
 
 describe('GitHub admin route', function () {
   const shieldsSecret = '7'.repeat(40)
diff --git a/services/github/github-all-contributors.service.js b/services/github/github-all-contributors.service.js
index a2f2d9fa6a022016b0c79e1e969fe39ae66ed268..ed54e6f2ea548e4b30c4cd7f0119165d7b7f2fe5 100644
--- a/services/github/github-all-contributors.service.js
+++ b/services/github/github-all-contributors.service.js
@@ -1,18 +1,14 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderContributorBadge } = require('../contributor-count')
-const { ConditionalGithubAuthV3Service } = require('./github-auth-service')
-const { fetchJsonFromRepo } = require('./github-common-fetch')
-const { documentation } = require('./github-helpers')
+import Joi from 'joi'
+import { renderContributorBadge } from '../contributor-count.js'
+import { ConditionalGithubAuthV3Service } from './github-auth-service.js'
+import { fetchJsonFromRepo } from './github-common-fetch.js'
+import { documentation } from './github-helpers.js'
 
 const schema = Joi.object({
   contributors: Joi.array().required(),
 }).required()
 
-module.exports = class GithubAllContributorsService extends (
-  ConditionalGithubAuthV3Service
-) {
+export default class GithubAllContributorsService extends ConditionalGithubAuthV3Service {
   static category = 'activity'
   static route = {
     base: 'github/all-contributors',
diff --git a/services/github/github-all-contributors.tester.js b/services/github/github-all-contributors.tester.js
index dea4dd6d01f63aadf010614e2a47cd54873630f1..f2656b3cc6b4ecc9640482253b25b191cd7fff64 100644
--- a/services/github/github-all-contributors.tester.js
+++ b/services/github/github-all-contributors.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isMetric } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('all-contributors repo')
   .get('/all-contributors/all-contributors.json')
diff --git a/services/github/github-api-provider.integration.js b/services/github/github-api-provider.integration.js
index 0caf068b130da0f4a9b56b14e0dee44e2492dd0d..26f9a0ac177158ebe19d6fc7a1ec86f4aa097740 100644
--- a/services/github/github-api-provider.integration.js
+++ b/services/github/github-api-provider.integration.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const config = require('config').util.toObject()
-const GithubApiProvider = require('./github-api-provider')
+import { expect } from 'chai'
+import config from 'config'
+import request from 'request'
+import GithubApiProvider from './github-api-provider.js'
 
 describe('Github API provider', function () {
   const baseUrl = process.env.GITHUB_URL || 'https://api.github.com'
@@ -10,7 +9,7 @@ describe('Github API provider', function () {
 
   let token
   before(function () {
-    token = config.private.gh_token
+    token = config.util.toObject().private.gh_token
     if (!token) {
       throw Error('The integration tests require a gh_token to be set')
     }
@@ -32,7 +31,7 @@ describe('Github API provider', function () {
       this.timeout('20s')
       for (let i = 0; i < 10; ++i) {
         await githubApiProvider.requestAsPromise(
-          require('request'),
+          request,
           '/repos/rust-lang/rust',
           {}
         )
@@ -54,7 +53,7 @@ describe('Github API provider', function () {
     const headers = []
     async function performOneRequest() {
       const { res } = await githubApiProvider.requestAsPromise(
-        require('request'),
+        request,
         '/repos/rust-lang/rust',
         {}
       )
diff --git a/services/github/github-api-provider.js b/services/github/github-api-provider.js
index 74d3607a5a8a82b9180eec0a1710cb738ba7f079..eefbe1b96689236123b90c0bbbe2c95f5d634fa9 100644
--- a/services/github/github-api-provider.js
+++ b/services/github/github-api-provider.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const log = require('../../core/server/log')
-const { TokenPool } = require('../../core/token-pooling/token-pool')
-const { userAgent } = require('../../core/base-service/legacy-request-handler')
-const { nonNegativeInteger } = require('../validators')
+import Joi from 'joi'
+import log from '../../core/server/log.js'
+import { TokenPool } from '../../core/token-pooling/token-pool.js'
+import { userAgent } from '../../core/base-service/legacy-request-handler.js'
+import { nonNegativeInteger } from '../validators.js'
 
 const headerSchema = Joi.object({
   'x-ratelimit-limit': nonNegativeInteger,
@@ -214,4 +212,4 @@ class GithubApiProvider {
   }
 }
 
-module.exports = GithubApiProvider
+export default GithubApiProvider
diff --git a/services/github/github-api-provider.spec.js b/services/github/github-api-provider.spec.js
index cd2d173f8ea43fff2c2414d9bb9215fc6d6a501b..dbb59d68e055245a736be37bba18867cc3d1f173 100644
--- a/services/github/github-api-provider.spec.js
+++ b/services/github/github-api-provider.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { expect } = require('chai')
-const sinon = require('sinon')
-const GithubApiProvider = require('./github-api-provider')
+import { expect } from 'chai'
+import sinon from 'sinon'
+import GithubApiProvider from './github-api-provider.js'
 
 describe('Github API provider', function () {
   const baseUrl = 'https://github-api.example.com'
diff --git a/services/github/github-auth-service.js b/services/github/github-auth-service.js
index 16aa35deba9bfbfaaab9b4376aa5b8dad59d24e3..826ab3990d5ab635862158bca0eb5b326d9341cb 100644
--- a/services/github/github-auth-service.js
+++ b/services/github/github-auth-service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const gql = require('graphql-tag')
-const { mergeQueries } = require('../../core/base-service/graphql')
-const { BaseGraphqlService, BaseJsonService } = require('..')
+import gql from 'graphql-tag'
+import { mergeQueries } from '../../core/base-service/graphql.js'
+import { BaseGraphqlService, BaseJsonService } from '../index.js'
 
 function createRequestFetcher(context, config) {
   const { sendAndCacheRequestWithCallbacks, githubApiProvider } = context
@@ -89,7 +87,7 @@ All other things being equal, a graphql query will almost always be a smaller
 number of bytes over the wire and a smaller/simpler object to parse.
 */
 
-module.exports = {
+export {
   GithubAuthV3Service,
   ConditionalGithubAuthV3Service,
   GithubAuthV4Service,
diff --git a/services/github/github-checks-status.service.js b/services/github/github-checks-status.service.js
index 79c68724c20663fac0e66d311a8ccfe27c70285b..35097f7b5a04291c6662f854bc9ed7b648fe14f7 100644
--- a/services/github/github-checks-status.service.js
+++ b/services/github/github-checks-status.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.object({
   state: isBuildStatus,
 }).required()
 
-module.exports = class GithubChecksStatus extends GithubAuthV3Service {
+export default class GithubChecksStatus extends GithubAuthV3Service {
   static category = 'build'
   static route = {
     base: 'github/checks-status',
diff --git a/services/github/github-checks-status.tester.js b/services/github/github-checks-status.tester.js
index 5b6f6c9e6a0bc368298aee28caaeca8dc2f1abf0..80cfe34bdd3ac58fface8968c5571d1c571ba85b 100644
--- a/services/github/github-checks-status.tester.js
+++ b/services/github/github-checks-status.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isBuildStatus } = require('../build-status')
+import { createServiceTester } from '../tester.js'
+import { isBuildStatus } from '../build-status.js'
+export const t = await createServiceTester()
 
 t.create('branch checks (branch)')
   .get('/badges/shields/master.json')
diff --git a/services/github/github-code-size.service.js b/services/github/github-code-size.service.js
index e8f1a3548620dc8ffb785c57e92678b3fb61b5c3..c5b394fbcea1de038edac31766918199821ddd4c 100644
--- a/services/github/github-code-size.service.js
+++ b/services/github/github-code-size.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import prettyBytes from 'pretty-bytes'
+import { BaseGithubLanguage } from './github-languages-base.js'
+import { documentation } from './github-helpers.js'
 
-const prettyBytes = require('pretty-bytes')
-const { BaseGithubLanguage } = require('./github-languages-base')
-const { documentation } = require('./github-helpers')
-
-module.exports = class GithubCodeSize extends BaseGithubLanguage {
+export default class GithubCodeSize extends BaseGithubLanguage {
   static category = 'size'
   static route = {
     base: 'github/languages/code-size',
diff --git a/services/github/github-code-size.tester.js b/services/github/github-code-size.tester.js
index 8a6e52e13c63cdd07c4d8bdfb9676cb869423568..39ec144e802f53b261cc068fa5f75f3ce25ea290 100644
--- a/services/github/github-code-size.tester.js
+++ b/services/github/github-code-size.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isFileSize } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isFileSize } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('code size in bytes for all languages')
   .get('/badges/shields.json')
diff --git a/services/github/github-commit-activity.service.js b/services/github/github-commit-activity.service.js
index d9190659c2856239671e32d47b13b330494488d7..ee7ad583ac849bd239a26f1cc7013d6b00a0c3a6 100644
--- a/services/github/github-commit-activity.service.js
+++ b/services/github/github-commit-activity.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { errorMessagesFor, documentation } = require('./github-helpers')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { errorMessagesFor, documentation } from './github-helpers.js'
 
 const schema = Joi.array()
   .items(
@@ -14,7 +12,7 @@ const schema = Joi.array()
   )
   .required()
 
-module.exports = class GithubCommitActivity extends GithubAuthV3Service {
+export default class GithubCommitActivity extends GithubAuthV3Service {
   static category = 'activity'
   static route = {
     base: 'github/commit-activity',
diff --git a/services/github/github-commit-activity.tester.js b/services/github/github-commit-activity.tester.js
index 3a401e9bc9547ca9746581ec4c6a64dfe428bfc8..bd18f2d68821ea44a69d65378caae9f73668656c 100644
--- a/services/github/github-commit-activity.tester.js
+++ b/services/github/github-commit-activity.tester.js
@@ -1,11 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const {
+import Joi from 'joi'
+import {
   isMetricOverTimePeriod,
   isZeroOverTimePeriod,
-} = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+} from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isCommitActivity = Joi.alternatives().try(
   isMetricOverTimePeriod,
diff --git a/services/github/github-commit-status.service.js b/services/github/github-commit-status.service.js
index 613d1f90d8621243a7900bdbbf1959a10dbfe991..46aae3410a8d4b8b5aa205446327d4b4606c388e 100644
--- a/services/github/github-commit-status.service.js
+++ b/services/github/github-commit-status.service.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const Joi = require('joi')
-const { NotFound, InvalidParameter } = require('..')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { NotFound, InvalidParameter } from '../index.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.object({
   // https://stackoverflow.com/a/23969867/893113
   status: Joi.equal('identical', 'ahead', 'behind', 'diverged'),
 }).required()
 
-module.exports = class GithubCommitStatus extends GithubAuthV3Service {
+export default class GithubCommitStatus extends GithubAuthV3Service {
   static category = 'issue-tracking'
   static route = {
     base: 'github/commit-status',
diff --git a/services/github/github-commit-status.tester.js b/services/github/github-commit-status.tester.js
index baeb41a6150e22b7a7947fdbd213145886df0f38..5e6f9f9fdc19d5c40a5390691675828b36cfcf96 100644
--- a/services/github/github-commit-status.tester.js
+++ b/services/github/github-commit-status.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { invalidJSONString } = require('../response-fixtures')
-const t = (module.exports = require('../tester').createServiceTester())
+import { invalidJSONString } from '../response-fixtures.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('commit status - commit in branch')
   .get('/badges/shields/master/5d4ab86b1b5ddfb3c4a70a70bd19932c52603b8c.json')
diff --git a/services/github/github-commits-since.service.js b/services/github/github-commits-since.service.js
index bda397e8094939a1932e1eee2967f0805b3e0963..7fd0cc924b51393cd9ed5a05eb7c1f00ac0b0091 100644
--- a/services/github/github-commits-since.service.js
+++ b/services/github/github-commits-since.service.js
@@ -1,18 +1,16 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const {
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import {
   fetchLatestRelease,
   queryParamSchema,
-} = require('./github-common-release')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+} from './github-common-release.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.object({ ahead_by: nonNegativeInteger }).required()
 
-module.exports = class GithubCommitsSince extends GithubAuthV3Service {
+export default class GithubCommitsSince extends GithubAuthV3Service {
   static category = 'activity'
   static route = {
     base: 'github/commits-since',
diff --git a/services/github/github-commits-since.tester.js b/services/github/github-commits-since.tester.js
index 4ba6e65c292c36e687fd0b1421ecd2f08fbdcf73..a16a093d9cebbe48703e0d28164f022ca0ff86fa 100644
--- a/services/github/github-commits-since.tester.js
+++ b/services/github/github-commits-since.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex, isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex, isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isCommitsSince = withRegex(/^(commits since){1}[\s\S]+$/)
 
diff --git a/services/github/github-common-fetch.js b/services/github/github-common-fetch.js
index 0ddd022a5e15b64bad9887ebb4076d4d948507de..1cf6c72fd1f94ca6c872e4a2bbe86ec58bd054a7 100644
--- a/services/github/github-common-fetch.js
+++ b/services/github/github-common-fetch.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { InvalidResponse } = require('..')
-const { errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { InvalidResponse } from '../index.js'
+import { errorMessagesFor } from './github-helpers.js'
 
 const issueSchema = Joi.object({
   head: Joi.object({
@@ -77,8 +75,4 @@ async function fetchJsonFromRepo(
   }
 }
 
-module.exports = {
-  fetchIssue,
-  fetchRepoContent,
-  fetchJsonFromRepo,
-}
+export { fetchIssue, fetchRepoContent, fetchJsonFromRepo }
diff --git a/services/github/github-common-release.js b/services/github/github-common-release.js
index 58bbd2489eb4e1697d1f18a69432d080992e858d..81e4f97d925345a6eeb690e51605f52097779c70 100644
--- a/services/github/github-common-release.js
+++ b/services/github/github-common-release.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { latest } = require('../version')
-const { NotFound } = require('..')
-const { errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { latest } from '../version.js'
+import { NotFound } from '../index.js'
+import { errorMessagesFor } from './github-helpers.js'
 
 const releaseInfoSchema = Joi.object({
   assets: Joi.array()
@@ -96,8 +94,5 @@ async function fetchLatestRelease(
   return latestRelease
 }
 
-module.exports = {
-  fetchLatestRelease,
-  queryParamSchema,
-  _getLatestRelease: getLatestRelease, // currently only used for tests
-}
+export { fetchLatestRelease, queryParamSchema }
+export const _getLatestRelease = getLatestRelease // currently only used for tests
diff --git a/services/github/github-common-release.spec.js b/services/github/github-common-release.spec.js
index 0ecd46fbe4afcd9a2d755708acb74af8958dbaad..ed927180ac3f94762cd7c86ecf62b94afba20acf 100644
--- a/services/github/github-common-release.spec.js
+++ b/services/github/github-common-release.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { _getLatestRelease } = require('./github-common-release')
+import { test, given } from 'sazerac'
+import { _getLatestRelease } from './github-common-release.js'
 
 describe('GithubRelease', function () {
   test(_getLatestRelease, () => {
diff --git a/services/github/github-constellation.js b/services/github/github-constellation.js
index 7b8d32242e085ed94af5ddf17b86c6efd5421743..e74114e7a46f964fd50042fac114d7ab26873c2d 100644
--- a/services/github/github-constellation.js
+++ b/services/github/github-constellation.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { AuthHelper } = require('../../core/base-service/auth-helper')
-const RedisTokenPersistence = require('../../core/token-pooling/redis-token-persistence')
-const log = require('../../core/server/log')
-const GithubApiProvider = require('./github-api-provider')
-const { setRoutes: setAdminRoutes } = require('./auth/admin')
-const { setRoutes: setAcceptorRoutes } = require('./auth/acceptor')
+import { AuthHelper } from '../../core/base-service/auth-helper.js'
+import RedisTokenPersistence from '../../core/token-pooling/redis-token-persistence.js'
+import log from '../../core/server/log.js'
+import GithubApiProvider from './github-api-provider.js'
+import { setRoutes as setAdminRoutes } from './auth/admin.js'
+import { setRoutes as setAcceptorRoutes } from './auth/acceptor.js'
 
 // Convenience class with all the stuff related to the Github API and its
 // authorization tokens, to simplify server initialization.
@@ -29,7 +27,7 @@ class GithubConstellation {
 
     const { redis_url: redisUrl, gh_token: globalToken } = config.private
     if (redisUrl) {
-      log('Token persistence configured with redisUrl')
+      log.log('Token persistence configured with redisUrl')
       this.persistence = new RedisTokenPersistence({
         url: redisUrl,
         key: 'githubUserTokens',
@@ -49,7 +47,7 @@ class GithubConstellation {
   scheduleDebugLogging() {
     if (this._debugEnabled) {
       this.debugInterval = setInterval(() => {
-        log(this.apiProvider.getTokenDebugInfo())
+        log.log(this.apiProvider.getTokenDebugInfo())
       }, 1000 * this._debugIntervalSeconds)
     }
   }
@@ -130,4 +128,4 @@ class GithubConstellation {
   }
 }
 
-module.exports = GithubConstellation
+export default GithubConstellation
diff --git a/services/github/github-contributors.service.js b/services/github/github-contributors.service.js
index 0103295624dcc61e5ad66794ecccae54fa91b898..6ad4c713e0a4ecca3d5541eb17c0f7c5e840e303 100644
--- a/services/github/github-contributors.service.js
+++ b/services/github/github-contributors.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const parseLinkHeader = require('parse-link-header')
-const { renderContributorBadge } = require('../contributor-count')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import parseLinkHeader from 'parse-link-header'
+import { renderContributorBadge } from '../contributor-count.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 // All we do is check its length.
 const schema = Joi.array().items(Joi.object())
 
-module.exports = class GithubContributors extends GithubAuthV3Service {
+export default class GithubContributors extends GithubAuthV3Service {
   static category = 'activity'
   static route = {
     base: 'github',
diff --git a/services/github/github-contributors.tester.js b/services/github/github-contributors.tester.js
index 15bebff1019e4ee402eef27cb34e94d9e171ad3e..4495d3b473e5b0c9d4679cf323d59a65a836b5df 100644
--- a/services/github/github-contributors.tester.js
+++ b/services/github/github-contributors.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isMetric } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('Contributors').get('/contributors/badges/shields.json').expectBadge({
   label: 'contributors',
diff --git a/services/github/github-deployments.service.js b/services/github/github-deployments.service.js
index 04dfc21cbcb51057c711712764c183030c886149..eed495401cfbbeec2cc1f1b21e798a78bdc7733d 100644
--- a/services/github/github-deployments.service.js
+++ b/services/github/github-deployments.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const gql = require('graphql-tag')
-const Joi = require('joi')
-const { NotFound } = require('..')
-const { GithubAuthV4Service } = require('./github-auth-service')
-const { documentation, transformErrors } = require('./github-helpers')
+import gql from 'graphql-tag'
+import Joi from 'joi'
+import { NotFound } from '../index.js'
+import { GithubAuthV4Service } from './github-auth-service.js'
+import { documentation, transformErrors } from './github-helpers.js'
 
 const greenStates = ['SUCCESS']
 const redStates = ['ERROR', 'FAILURE']
@@ -44,7 +42,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class GithubDeployments extends GithubAuthV4Service {
+export default class GithubDeployments extends GithubAuthV4Service {
   static category = 'other'
   static route = {
     base: 'github/deployments',
diff --git a/services/github/github-deployments.spec.js b/services/github/github-deployments.spec.js
index 9f7307c85a81e0c9e34667836c52a55f39e48142..d3221706c5740d354acf714b4632b3b89841133e 100644
--- a/services/github/github-deployments.spec.js
+++ b/services/github/github-deployments.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const GithubDeployments = require('./github-deployments.service')
+import { test, given } from 'sazerac'
+import GithubDeployments from './github-deployments.service.js'
 
 describe('GithubDeployments', function () {
   test(GithubDeployments.render, () => {
diff --git a/services/github/github-deployments.tester.js b/services/github/github-deployments.tester.js
index 753dd2d390bfb595f0cb4521ea7bc8ade0bb4025..325ae34faad9bafcb06f2e6ebee3cde86c16afca 100644
--- a/services/github/github-deployments.tester.js
+++ b/services/github/github-deployments.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const validMessages = [
   'success',
diff --git a/services/github/github-directory-file-count.service.js b/services/github/github-directory-file-count.service.js
index 7b0e4885b0007f3e3b5611308917d9c2783eb564..24aabaa34e870c163787251a217c1667a6e43e99 100644
--- a/services/github/github-directory-file-count.service.js
+++ b/services/github/github-directory-file-count.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const path = require('path')
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { InvalidParameter } = require('..')
-const { ConditionalGithubAuthV3Service } = require('./github-auth-service')
-const {
-  documentation: commonDocumentation,
+import path from 'path'
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { InvalidParameter } from '../index.js'
+import { ConditionalGithubAuthV3Service } from './github-auth-service.js'
+import {
+  documentation as commonDocumentation,
   errorMessagesFor,
-} = require('./github-helpers')
+} from './github-helpers.js'
 
 const documentation = `${commonDocumentation}
 <p>
@@ -45,9 +43,7 @@ const queryParamSchema = Joi.object({
   extension: Joi.string(),
 })
 
-module.exports = class GithubDirectoryFileCount extends (
-  ConditionalGithubAuthV3Service
-) {
+export default class GithubDirectoryFileCount extends ConditionalGithubAuthV3Service {
   static category = 'size'
 
   static route = {
diff --git a/services/github/github-directory-file-count.spec.js b/services/github/github-directory-file-count.spec.js
index 721691ad5bd61e19b1d1a1ec04d4d5443f45da0b..056a9622a0a8ad2c39df25487d1d486cc7ebb455 100644
--- a/services/github/github-directory-file-count.spec.js
+++ b/services/github/github-directory-file-count.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const { test, given } = require('sazerac')
-const { InvalidParameter } = require('..')
-const GithubDirectoryFileCount = require('./github-directory-file-count.service')
+import { expect } from 'chai'
+import { test, given } from 'sazerac'
+import { InvalidParameter } from '../index.js'
+import GithubDirectoryFileCount from './github-directory-file-count.service.js'
 
 describe('GithubDirectoryFileCount', function () {
   const contents = [
diff --git a/services/github/github-directory-file-count.tester.js b/services/github/github-directory-file-count.tester.js
index 2ea38495e371bb23924edcfc3116ed3f9eb8e9f2..b4ac6c6f2c6c420b7b32978e80c27502259c675e 100644
--- a/services/github/github-directory-file-count.tester.js
+++ b/services/github/github-directory-file-count.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('directory file count').get('/badges/shields.json').expectBadge({
   label: 'files',
diff --git a/services/github/github-discussions-total.service.js b/services/github/github-discussions-total.service.js
index 88bc5c335643808dc848c271585c1d72c48035c8..425563c220a90c865ca512cb96be5909accd096c 100644
--- a/services/github/github-discussions-total.service.js
+++ b/services/github/github-discussions-total.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { default: gql } = require('graphql-tag')
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV4Service } = require('./github-auth-service')
-const { transformErrors } = require('./github-helpers')
+import gql from 'graphql-tag'
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV4Service } from './github-auth-service.js'
+import { transformErrors } from './github-helpers.js'
 
 const schema = Joi.object({
   data: Joi.object({
@@ -16,7 +14,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class GithubTotalDiscussions extends GithubAuthV4Service {
+export default class GithubTotalDiscussions extends GithubAuthV4Service {
   static category = 'other'
   static route = {
     base: 'github/discussions',
diff --git a/services/github/github-discussions-total.tester.js b/services/github/github-discussions-total.tester.js
index 737419d48537828b4eddbb602d1453fab676c77f..7a347876685ce2421cdf7e6eddcd2ebb94bfa56f 100644
--- a/services/github/github-discussions-total.tester.js
+++ b/services/github/github-discussions-total.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('GitHub Total Discussions (repo not found)')
   .get('/not-a-user/not-a-repo.json')
diff --git a/services/github/github-downloads.service.js b/services/github/github-downloads.service.js
index cb22a498c428afc7afb8b659c60490ff547aa047..d544a91e743d83a2b6a2f37811152b75c39d39a3 100644
--- a/services/github/github-downloads.service.js
+++ b/services/github/github-downloads.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { downloadCount: downloadCountColor } = require('../color-formatters')
-const { NotFound } = require('..')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { fetchLatestRelease } = require('./github-common-release')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { downloadCount as downloadCountColor } from '../color-formatters.js'
+import { NotFound } from '../index.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { fetchLatestRelease } from './github-common-release.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const queryParamSchema = Joi.object({
   sort: Joi.string().valid('date', 'semver').default('date'),
@@ -27,7 +25,7 @@ const releaseArraySchema = Joi.alternatives().try(
   Joi.array().length(0)
 )
 
-module.exports = class GithubDownloads extends GithubAuthV3Service {
+export default class GithubDownloads extends GithubAuthV3Service {
   static category = 'downloads'
   static route = {
     base: 'github',
diff --git a/services/github/github-downloads.tester.js b/services/github/github-downloads.tester.js
index 099092af952851eca2d64be05f97f4b350beb9c5..e002516906684d8114e2c34778b08bf4cf2f73d4 100644
--- a/services/github/github-downloads.tester.js
+++ b/services/github/github-downloads.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const mockLatestRelease = release => nock =>
   nock('https://api.github.com')
diff --git a/services/github/github-followers.service.js b/services/github/github-followers.service.js
index f39bf32cbb8f5f293dd4fb1733457266e19db89b..71b3d01b05c9fac8f16b6a33d17ac1120f3dd826 100644
--- a/services/github/github-followers.service.js
+++ b/services/github/github-followers.service.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.object({
   followers: nonNegativeInteger,
 }).required()
 
-module.exports = class GithubFollowers extends GithubAuthV3Service {
+export default class GithubFollowers extends GithubAuthV3Service {
   static category = 'social'
   static route = { base: 'github/followers', pattern: ':user' }
   static examples = [
diff --git a/services/github/github-followers.tester.js b/services/github/github-followers.tester.js
index c0db38a83915ab9a5f31666c642a4e1767df4794..4e1babb264c26996225651b82c88bd44e6e00871 100644
--- a/services/github/github-followers.tester.js
+++ b/services/github/github-followers.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Followers').get('/webcaetano.json').expectBadge({
   label: 'followers',
diff --git a/services/github/github-forks.service.js b/services/github/github-forks.service.js
index 67bac545b8003421de829651c6ec2d2010f2260b..0c60e03c67ba771ce6d6ea537e6dce9b774372f2 100644
--- a/services/github/github-forks.service.js
+++ b/services/github/github-forks.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const gql = require('graphql-tag')
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV4Service } = require('./github-auth-service')
-const { documentation, transformErrors } = require('./github-helpers')
+import gql from 'graphql-tag'
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV4Service } from './github-auth-service.js'
+import { documentation, transformErrors } from './github-helpers.js'
 
 const schema = Joi.object({
   data: Joi.object({
@@ -15,7 +13,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class GithubForks extends GithubAuthV4Service {
+export default class GithubForks extends GithubAuthV4Service {
   static category = 'social'
   static route = { base: 'github/forks', pattern: ':user/:repo' }
   static examples = [
diff --git a/services/github/github-forks.tester.js b/services/github/github-forks.tester.js
index 9656b806dda09c9539d7d4c906a8a5d407a2ab88..31ad83fbbf8c78c57cec66e4e41b6534ab5a6819 100644
--- a/services/github/github-forks.tester.js
+++ b/services/github/github-forks.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Forks')
   .get('/badges/shields.json')
diff --git a/services/github/github-go-mod.service.js b/services/github/github-go-mod.service.js
index cb45aa2a4ce4dcff08f9a97f3b5b9b8326376f85..9feded9bae79d9b8fd5adf70b0a140c442c86bb4 100644
--- a/services/github/github-go-mod.service.js
+++ b/services/github/github-go-mod.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { InvalidResponse } = require('..')
-const { ConditionalGithubAuthV3Service } = require('./github-auth-service')
-const { fetchRepoContent } = require('./github-common-fetch')
-const { documentation } = require('./github-helpers')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { InvalidResponse } from '../index.js'
+import { ConditionalGithubAuthV3Service } from './github-auth-service.js'
+import { fetchRepoContent } from './github-common-fetch.js'
+import { documentation } from './github-helpers.js'
 
 const queryParamSchema = Joi.object({
   filename: Joi.string(),
@@ -15,9 +13,7 @@ const goVersionRegExp = /^go (.+)$/m
 
 const keywords = ['golang']
 
-module.exports = class GithubGoModGoVersion extends (
-  ConditionalGithubAuthV3Service
-) {
+export default class GithubGoModGoVersion extends ConditionalGithubAuthV3Service {
   static category = 'version'
   static route = {
     base: 'github/go-mod/go-version',
diff --git a/services/github/github-go-mod.tester.js b/services/github/github-go-mod.tester.js
index e83e4a1d8990d384e92fe5ceab88d0877314650b..d42378079cc10f1d7b7c758965b1b3f929dba9c9 100644
--- a/services/github/github-go-mod.tester.js
+++ b/services/github/github-go-mod.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Go version').get('/gohugoio/hugo.json').expectBadge({
   label: 'Go',
diff --git a/services/github/github-hacktoberfest.service.js b/services/github/github-hacktoberfest.service.js
index 85339bd39a8dfa60be03aa38235776a5e583852e..bf8782c17a5bf740f2b0b0584de571de8c0578b1 100644
--- a/services/github/github-hacktoberfest.service.js
+++ b/services/github/github-hacktoberfest.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const gql = require('graphql-tag')
-const Joi = require('joi')
-const moment = require('moment')
-const { metric, maybePluralize } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV4Service } = require('./github-auth-service')
-const {
-  documentation: githubDocumentation,
+import gql from 'graphql-tag'
+import Joi from 'joi'
+import moment from 'moment'
+import { metric, maybePluralize } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV4Service } from './github-auth-service.js'
+import {
+  documentation as githubDocumentation,
   transformErrors,
-} = require('./github-helpers')
+} from './github-helpers.js'
 
 const documentation = `
   <p>
@@ -58,9 +56,7 @@ const queryParamSchema = Joi.object({
   suggestion_label: Joi.string(),
 }).required()
 
-module.exports = class GithubHacktoberfestCombinedStatus extends (
-  GithubAuthV4Service
-) {
+export default class GithubHacktoberfestCombinedStatus extends GithubAuthV4Service {
   static category = 'issue-tracking'
   static route = {
     base: 'github/hacktoberfest',
diff --git a/services/github/github-hacktoberfest.spec.js b/services/github/github-hacktoberfest.spec.js
index 01916b5a8a2f65ae59f9ee8b2bd49cba5d65d667..c872f7ab64bf71bd5b5e56951e73205bdd7a4406 100644
--- a/services/github/github-hacktoberfest.spec.js
+++ b/services/github/github-hacktoberfest.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const GitHubHacktoberfest = require('./github-hacktoberfest.service')
+import { test, given } from 'sazerac'
+import GitHubHacktoberfest from './github-hacktoberfest.service.js'
 
 describe('GitHubHacktoberfest', function () {
   test(GitHubHacktoberfest.render, () => {
diff --git a/services/github/github-hacktoberfest.tester.js b/services/github/github-hacktoberfest.tester.js
index b11b1526d08806798e976f354651c2a7b6996a17..5fb0212a9f7104fea611dbf7699b786f543c9160 100644
--- a/services/github/github-hacktoberfest.tester.js
+++ b/services/github/github-hacktoberfest.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isHacktoberfestNoIssuesStatus = Joi.string().regex(
   /^[0-9]+ PRs?(, [0-9]+ days? left)?$/
diff --git a/services/github/github-helpers.js b/services/github/github-helpers.js
index eb11e24fff32185877f7b5565ca5dd1225ec5cc7..9bbeda52c6961ff49d6a2c51910805409c830d8f 100644
--- a/services/github/github-helpers.js
+++ b/services/github/github-helpers.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { colorScale } = require('../color-formatters')
-const { InvalidResponse, NotFound } = require('..')
+import { colorScale } from '../color-formatters.js'
+import { InvalidResponse, NotFound } from '../index.js'
 
 const documentation = `
 <p>
@@ -33,7 +31,7 @@ function transformErrors(errors, entity = 'repo') {
 
 const commentsColor = colorScale([1, 3, 10, 25], undefined, true)
 
-module.exports = {
+export {
   documentation,
   stateColor,
   commentsColor,
diff --git a/services/github/github-issue-detail-redirect.service.js b/services/github/github-issue-detail-redirect.service.js
index 40be57b51b99c8987df8ba4a111858fb1835f254..8bf174f7b67d9a91adbf83e91ca08987cfe57c8f 100644
--- a/services/github/github-issue-detail-redirect.service.js
+++ b/services/github/github-issue-detail-redirect.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const { redirector } = require('..')
+import { redirector } from '../index.js'
 
 const variantMap = {
   s: 'state',
   u: 'author',
 }
 
-module.exports = [
+export default [
   redirector({
     category: 'issue-tracking',
     route: {
diff --git a/services/github/github-issue-detail-redirect.tester.js b/services/github/github-issue-detail-redirect.tester.js
index da07a159e6f0ceb19279a7d56a836b6177450cc7..1be7ba22c6b96ba255c9fc2065dd1242064edfdf 100644
--- a/services/github/github-issue-detail-redirect.tester.js
+++ b/services/github/github-issue-detail-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'GithubIssueDetailRedirect',
   title: 'GithubIssueDetailRedirect',
   pathPrefix: '/github',
-}))
+})
 
 t.create('github issue detail (s shorthand)')
   .get('/issues/detail/s/badges/shields/979.svg')
diff --git a/services/github/github-issue-detail.service.js b/services/github/github-issue-detail.service.js
index 8fca29bee68664b546584877a39edeb6f449b800..48359527c6793ab7921910d4e88b2ee34e024131 100644
--- a/services/github/github-issue-detail.service.js
+++ b/services/github/github-issue-detail.service.js
@@ -1,17 +1,15 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { formatDate, metric } = require('../text-formatters')
-const { age } = require('../color-formatters')
-const { InvalidResponse } = require('..')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const {
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { formatDate, metric } from '../text-formatters.js'
+import { age } from '../color-formatters.js'
+import { InvalidResponse } from '../index.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import {
   documentation,
   errorMessagesFor,
   stateColor,
   commentsColor,
-} = require('./github-helpers')
+} from './github-helpers.js'
 
 const commonSchemaFields = {
   number: nonNegativeInteger,
@@ -152,7 +150,7 @@ const propertyMap = {
   'last-update': ageUpdateMap,
 }
 
-module.exports = class GithubIssueDetail extends GithubAuthV3Service {
+export default class GithubIssueDetail extends GithubAuthV3Service {
   static category = 'issue-tracking'
   static route = {
     base: 'github',
diff --git a/services/github/github-issue-detail.spec.js b/services/github/github-issue-detail.spec.js
index 3d5ef086f30dd32e30f126a4ee9e0c1bcb44e624..e639bbd4cca42d8bfe45f052cd061dc5b8d5a462 100644
--- a/services/github/github-issue-detail.spec.js
+++ b/services/github/github-issue-detail.spec.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { expect } = require('chai')
-const { test, given } = require('sazerac')
-const { age } = require('../color-formatters')
-const { formatDate, metric } = require('../text-formatters')
-const { InvalidResponse } = require('..')
-const GithubIssueDetail = require('./github-issue-detail.service')
-const { stateColor, commentsColor } = require('./github-helpers')
+import { expect } from 'chai'
+import { test, given } from 'sazerac'
+import { age } from '../color-formatters.js'
+import { formatDate, metric } from '../text-formatters.js'
+import { InvalidResponse } from '../index.js'
+import GithubIssueDetail from './github-issue-detail.service.js'
+import { stateColor, commentsColor } from './github-helpers.js'
 
 describe('GithubIssueDetail', function () {
   test(GithubIssueDetail.render, () => {
diff --git a/services/github/github-issue-detail.tester.js b/services/github/github-issue-detail.tester.js
index 0a9de66414ee365918ca664d22a3801613d62daf..bb0103e48ca4838ad1e88df77e41ae9df5a6fac6 100644
--- a/services/github/github-issue-detail.tester.js
+++ b/services/github/github-issue-detail.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isFormattedDate } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isFormattedDate } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('github issue state')
   .get('/issues/detail/state/badges/shields/979.json')
diff --git a/services/github/github-issues-search.service.js b/services/github/github-issues-search.service.js
index 979345af9ef6ea23b31a02348227aee98e3a5604..68e1b2a5eb76691ea5b5e1eee7a8656e03e5f6e6 100644
--- a/services/github/github-issues-search.service.js
+++ b/services/github/github-issues-search.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const gql = require('graphql-tag')
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV4Service } = require('./github-auth-service')
-const { documentation, transformErrors } = require('./github-helpers')
+import gql from 'graphql-tag'
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV4Service } from './github-auth-service.js'
+import { documentation, transformErrors } from './github-helpers.js'
 
 const issueCountSchema = Joi.object({
   data: Joi.object({
@@ -106,7 +104,4 @@ class GithubRepoIssuesSearch extends BaseGithubIssuesSearch {
   }
 }
 
-module.exports = {
-  GithubIssuesSearch,
-  GithubRepoIssuesSearch,
-}
+export { GithubIssuesSearch, GithubRepoIssuesSearch }
diff --git a/services/github/github-issues-search.tester.js b/services/github/github-issues-search.tester.js
index 04c88c2f24a8919542a68e076bcc5061b8a6fe4d..57bd0c11a778b4f6ee1bbfde91d3efc7e3f2713e 100644
--- a/services/github/github-issues-search.tester.js
+++ b/services/github/github-issues-search.tester.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import { isMetric } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'GithubIssuesSearch',
   title: 'Github Issues Search',
   pathPrefix: '/github',
-}))
+})
 
 t.create('GitHub issue search (valid query string)')
   .get(
diff --git a/services/github/github-issues.service.js b/services/github/github-issues.service.js
index 9f7b37ed2be447e23797d80124fc7a8f51463beb..d9bfe3d2adecc98a6966514d973756e27674aac8 100644
--- a/services/github/github-issues.service.js
+++ b/services/github/github-issues.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const gql = require('graphql-tag')
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV4Service } = require('./github-auth-service')
-const { documentation, transformErrors } = require('./github-helpers')
+import gql from 'graphql-tag'
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV4Service } from './github-auth-service.js'
+import { documentation, transformErrors } from './github-helpers.js'
 
 const issueCountSchema = Joi.object({
   data: Joi.object({
@@ -37,7 +35,7 @@ const isClosedVariant = {
   'issues-pr-closed': true,
 }
 
-module.exports = class GithubIssues extends GithubAuthV4Service {
+export default class GithubIssues extends GithubAuthV4Service {
   static category = 'issue-tracking'
   static route = {
     base: 'github',
diff --git a/services/github/github-issues.tester.js b/services/github/github-issues.tester.js
index bb25a88dab518e6501a990772e28fb51c7dc05a0..f84a99f432ac596bb2983ef5503d43d1295cfc1d 100644
--- a/services/github/github-issues.tester.js
+++ b/services/github/github-issues.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isMetric, isMetricOpenIssues } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isMetric, isMetricOpenIssues } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('GitHub closed pull requests')
   .get('/issues-pr-closed/badges/shields.json')
diff --git a/services/github/github-labels.service.js b/services/github/github-labels.service.js
index 1bed157eaa96d3db0d2a8986cb9d769a8bdfc9a7..70176517bf507a7117401f448632f4da05a3bad8 100644
--- a/services/github/github-labels.service.js
+++ b/services/github/github-labels.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.object({
   color: Joi.string().hex().required(),
 }).required()
 
-module.exports = class GithubLabels extends GithubAuthV3Service {
+export default class GithubLabels extends GithubAuthV3Service {
   static category = 'issue-tracking'
   static route = { base: 'github/labels', pattern: ':user/:repo/:name' }
   static examples = [
diff --git a/services/github/github-labels.tester.js b/services/github/github-labels.tester.js
index 1cf89586cf731dc53f0a5e36308d2c0d88604284..d493e03ffd8509bcb24eb945898e3f50c4fee447 100644
--- a/services/github/github-labels.tester.js
+++ b/services/github/github-labels.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('labels').get('/badges/shields/bug.json').expectBadge({
   message: 'bug',
diff --git a/services/github/github-language-count.service.js b/services/github/github-language-count.service.js
index 311a097271e0924111c1b507bd1ec5d5a65fd454..b7303722215179f995a014754dc9589ba32c13d4 100644
--- a/services/github/github-language-count.service.js
+++ b/services/github/github-language-count.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { BaseGithubLanguage } from './github-languages-base.js'
+import { documentation } from './github-helpers.js'
 
-const { BaseGithubLanguage } = require('./github-languages-base')
-const { documentation } = require('./github-helpers')
-
-module.exports = class GithubLanguageCount extends BaseGithubLanguage {
+export default class GithubLanguageCount extends BaseGithubLanguage {
   static category = 'analysis'
   static route = { base: 'github/languages/count', pattern: ':user/:repo' }
   static examples = [
diff --git a/services/github/github-language-count.tester.js b/services/github/github-language-count.tester.js
index f7277d884baaa221211e1bf90c5d51f78f7b67cf..b7464402995f4579a11daa946aafc6d23de7d8f7 100644
--- a/services/github/github-language-count.tester.js
+++ b/services/github/github-language-count.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('language count').get('/badges/shields.json').expectBadge({
   label: 'languages',
diff --git a/services/github/github-languages-base.js b/services/github/github-languages-base.js
index aa6dc250a606dea17d254d8072a26d6ad72082a4..92427519feb910ea36184032b24a689fc4ed7dc1 100644
--- a/services/github/github-languages-base.js
+++ b/services/github/github-languages-base.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { errorMessagesFor } from './github-helpers.js'
 
 /*
 We're expecting a response like { "Python": 39624, "Shell": 104 }
@@ -25,4 +23,4 @@ class BaseGithubLanguage extends GithubAuthV3Service {
   }
 }
 
-module.exports = { BaseGithubLanguage }
+export { BaseGithubLanguage }
diff --git a/services/github/github-last-commit.service.js b/services/github/github-last-commit.service.js
index 76f92fe72a159b395faa9482391ab731f7034721..b452fbe96b6d4176cf0bc81c89f3911a09f4db40 100644
--- a/services/github/github-last-commit.service.js
+++ b/services/github/github-last-commit.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { formatDate } = require('../text-formatters')
-const { age: ageColor } = require('../color-formatters')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { formatDate } from '../text-formatters.js'
+import { age as ageColor } from '../color-formatters.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 const commonExampleAttrs = {
   keywords: ['latest'],
   documentation,
@@ -22,7 +20,7 @@ const schema = Joi.array()
   )
   .required()
 
-module.exports = class GithubLastCommit extends GithubAuthV3Service {
+export default class GithubLastCommit extends GithubAuthV3Service {
   static category = 'activity'
   static route = { base: 'github/last-commit', pattern: ':user/:repo/:branch*' }
   static examples = [
diff --git a/services/github/github-last-commit.tester.js b/services/github/github-last-commit.tester.js
index 5ee66e832de3ecf9dd6c4d92270b723ff9b1ae91..23eed9fb37bb6c9975021b6edcec6f9e6199bc3e 100644
--- a/services/github/github-last-commit.tester.js
+++ b/services/github/github-last-commit.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isFormattedDate } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isFormattedDate } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('last commit (recent)')
   .get('/eslint/eslint.json')
diff --git a/services/github/github-lerna-json.service.js b/services/github/github-lerna-json.service.js
index 9fabd62df00c8e049a3dd1ceeb284da47738d4af..f306563a5912fa831f03291f34ee23f63270d903 100644
--- a/services/github/github-lerna-json.service.js
+++ b/services/github/github-lerna-json.service.js
@@ -1,17 +1,15 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { semver } = require('../validators')
-const { ConditionalGithubAuthV3Service } = require('./github-auth-service')
-const { fetchJsonFromRepo } = require('./github-common-fetch')
-const { documentation } = require('./github-helpers')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { semver } from '../validators.js'
+import { ConditionalGithubAuthV3Service } from './github-auth-service.js'
+import { fetchJsonFromRepo } from './github-common-fetch.js'
+import { documentation } from './github-helpers.js'
 
 const versionSchema = Joi.object({
   version: Joi.alternatives().try(semver, Joi.equal('independent').required()),
 }).required()
 
-module.exports = class GithubLernaJson extends ConditionalGithubAuthV3Service {
+export default class GithubLernaJson extends ConditionalGithubAuthV3Service {
   static category = 'version'
   static route = {
     base: 'github/lerna-json/v',
diff --git a/services/github/github-lerna-json.tester.js b/services/github/github-lerna-json.tester.js
index 907d16942b8352507f0222a9161dcebcbb8d6f95..c86f97bcdb82614df492f39c184e1ab5dd7eb87c 100644
--- a/services/github/github-lerna-json.tester.js
+++ b/services/github/github-lerna-json.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isSemver } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isSemver } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Lerna version').get('/facebook/jest.json').expectBadge({
   label: 'lerna',
diff --git a/services/github/github-license.service.js b/services/github/github-license.service.js
index 0a628700f2fd0b0851195d85538974466910fb3a..360153f29e61f1cf3c067f2d39b031f2f1714321 100644
--- a/services/github/github-license.service.js
+++ b/services/github/github-license.service.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderLicenseBadge } = require('../licenses')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { renderLicenseBadge } from '../licenses.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.object({
   // Some repos do not have a license, in which case GitHub returns `{ license: null }`.
   license: Joi.object({ spdx_id: Joi.string().required() }).allow(null),
 }).required()
 
-module.exports = class GithubLicense extends GithubAuthV3Service {
+export default class GithubLicense extends GithubAuthV3Service {
   static category = 'license'
   static route = { base: 'github/license', pattern: ':user/:repo' }
   static examples = [
diff --git a/services/github/github-license.spec.js b/services/github/github-license.spec.js
index 82359204cc8db6fb0561d981a120446e9620ff71..87167fc26d516611d1be30d9337c9d5e368ee9ba 100644
--- a/services/github/github-license.spec.js
+++ b/services/github/github-license.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const GithubLicense = require('./github-license.service')
+import { test, given } from 'sazerac'
+import GithubLicense from './github-license.service.js'
 
 test(GithubLicense.render, () => {
   given({ license: undefined }).expect({ message: 'not specified' })
diff --git a/services/github/github-license.tester.js b/services/github/github-license.tester.js
index 261b4b4126616c1d0530bcf9008e3036887d21f9..0cef52f4c75b8e9f4bf26d4254d6211f4a970052 100644
--- a/services/github/github-license.tester.js
+++ b/services/github/github-license.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { licenseToColor } = require('../licenses')
-const t = (module.exports = require('../tester').createServiceTester())
+import { licenseToColor } from '../licenses.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const publicDomainLicenseColor = licenseToColor('CC0-1.0')
 const unknownLicenseColor = licenseToColor()
diff --git a/services/github/github-manifest.service.js b/services/github/github-manifest.service.js
index 248397a730faaa4249b473702c8a1fe0454f5dda..59195073985974787409fac24d3f886cf2f5d74b 100644
--- a/services/github/github-manifest.service.js
+++ b/services/github/github-manifest.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const {
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import {
   individualValueSchema,
   transformAndValidate,
   renderDynamicBadge,
-} = require('../dynamic-common')
-const { ConditionalGithubAuthV3Service } = require('./github-auth-service')
-const { fetchJsonFromRepo } = require('./github-common-fetch')
-const { documentation } = require('./github-helpers')
+} from '../dynamic-common.js'
+import { ConditionalGithubAuthV3Service } from './github-auth-service.js'
+import { fetchJsonFromRepo } from './github-common-fetch.js'
+import { documentation } from './github-helpers.js'
 
 const schema = Joi.object({
   version: individualValueSchema,
@@ -204,7 +202,4 @@ class DynamicGithubManifest extends ConditionalGithubAuthV3Service {
   }
 }
 
-module.exports = {
-  GithubManifestVersion,
-  DynamicGithubManifest,
-}
+export { GithubManifestVersion, DynamicGithubManifest }
diff --git a/services/github/github-manifest.tester.js b/services/github/github-manifest.tester.js
index 77c1beb32df472e41a6be25fe58ed14bcb19dcb0..a1e9849f9779e08a5c9a3dceb84dd89e239f9a79 100644
--- a/services/github/github-manifest.tester.js
+++ b/services/github/github-manifest.tester.js
@@ -1,14 +1,12 @@
-'use strict'
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
 
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'GithubManifest',
   title: 'GithubManifest',
   pathPrefix: '/github/manifest-json',
-}))
+})
 
 t.create('Manifest version')
   .get('/v/sindresorhus/show-all-github-issues.json')
diff --git a/services/github/github-milestone-detail.service.js b/services/github/github-milestone-detail.service.js
index c70aa58f705c3d9ccb701731549aa901668c2c19..ac3b071c5dd6c6a0a0a727354693e9f4b6ee5060 100644
--- a/services/github/github-milestone-detail.service.js
+++ b/services/github/github-milestone-detail.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.object({
   open_issues: nonNegativeInteger,
@@ -12,7 +10,7 @@ const schema = Joi.object({
   title: Joi.string().required(),
 }).required()
 
-module.exports = class GithubMilestoneDetail extends GithubAuthV3Service {
+export default class GithubMilestoneDetail extends GithubAuthV3Service {
   static category = 'issue-tracking'
   static route = {
     base: 'github/milestones',
diff --git a/services/github/github-milestone-detail.tester.js b/services/github/github-milestone-detail.tester.js
index e1ed8b5003247f0e1a4b95ac8aebd5fdcb5095fb..4305a6074b19d6859ed0b6e33ab483e04a39c965 100644
--- a/services/github/github-milestone-detail.tester.js
+++ b/services/github/github-milestone-detail.tester.js
@@ -1,11 +1,10 @@
-'use strict'
-
-const {
+import {
   isMetric,
   isMetricOverMetric,
   isIntegerPercentage,
-} = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+} from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Milestone Open Issues')
   .get('/issues-open/MacroPower/milestone-test/1.json')
diff --git a/services/github/github-milestone.service.js b/services/github/github-milestone.service.js
index d345f4ca2a527bd050715c0ed85d68cc91a240a6..62b623aed7fd43f6b8fab8b6b21ac2fc2b7ef3d8 100644
--- a/services/github/github-milestone.service.js
+++ b/services/github/github-milestone.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.array()
   .items(
@@ -13,7 +11,7 @@ const schema = Joi.array()
   )
   .required()
 
-module.exports = class GithubMilestone extends GithubAuthV3Service {
+export default class GithubMilestone extends GithubAuthV3Service {
   static category = 'issue-tracking'
   static route = {
     base: 'github/milestones',
diff --git a/services/github/github-milestone.tester.js b/services/github/github-milestone.tester.js
index 30565326578aee6996bea87f478f14e9e145e427..dd9b92234ad72ae59c1380531993f84b20b96c5c 100644
--- a/services/github/github-milestone.tester.js
+++ b/services/github/github-milestone.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('All Milestones')
   .get('/all/MacroPower/milestone-test.json')
diff --git a/services/github/github-package-json.service.js b/services/github/github-package-json.service.js
index 9b8dc0004bac2170ecff4db70c8d74e8878cc261..dc2663069f22f3b81d44fc88e0d4f9e1bb1caca7 100644
--- a/services/github/github-package-json.service.js
+++ b/services/github/github-package-json.service.js
@@ -1,19 +1,14 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const {
-  transformAndValidate,
-  renderDynamicBadge,
-} = require('../dynamic-common')
-const {
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { transformAndValidate, renderDynamicBadge } from '../dynamic-common.js'
+import {
   isPackageJsonWithDependencies,
   getDependencyVersion,
-} = require('../package-json-helpers')
-const { semver } = require('../validators')
-const { ConditionalGithubAuthV3Service } = require('./github-auth-service')
-const { fetchJsonFromRepo } = require('./github-common-fetch')
-const { documentation } = require('./github-helpers')
+} from '../package-json-helpers.js'
+import { semver } from '../validators.js'
+import { ConditionalGithubAuthV3Service } from './github-auth-service.js'
+import { fetchJsonFromRepo } from './github-common-fetch.js'
+import { documentation } from './github-helpers.js'
 
 const keywords = ['npm', 'node']
 
@@ -247,7 +242,7 @@ class DynamicGithubPackageJson extends ConditionalGithubAuthV3Service {
   }
 }
 
-module.exports = [
+export default [
   GithubPackageJsonVersion,
   GithubPackageJsonDependencyVersion,
   DynamicGithubPackageJson,
diff --git a/services/github/github-package-json.tester.js b/services/github/github-package-json.tester.js
index 5a15ccd3be1bfc28616fdd6732a846828d717ab8..eb16fb42b01478e1758014feb8a2b3de7d726778 100644
--- a/services/github/github-package-json.tester.js
+++ b/services/github/github-package-json.tester.js
@@ -1,15 +1,13 @@
-'use strict'
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
+import { isSemver } from '../test-validators.js'
+import { semverRange } from '../validators.js'
 
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-const { isSemver } = require('../test-validators')
-const { semverRange } = require('../validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'GithubPackageJson',
   title: 'GithubPackageJson',
   pathPrefix: '/github/package-json',
-}))
+})
 
 t.create('Package version').get('/v/badges/shields.json').expectBadge({
   label: 'version',
diff --git a/services/github/github-pipenv.service.js b/services/github/github-pipenv.service.js
index a36b3cc92789de207bd797520f8c67db03ce0f93..758903747a49ddcc25163bfa8318849f2e29a173 100644
--- a/services/github/github-pipenv.service.js
+++ b/services/github/github-pipenv.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { renderVersionBadge } = require('../version')
-const { isLockfile, getDependencyVersion } = require('../pipenv-helpers')
-const { addv } = require('../text-formatters')
-const { NotFound } = require('..')
-const { ConditionalGithubAuthV3Service } = require('./github-auth-service')
-const { fetchJsonFromRepo } = require('./github-common-fetch')
-const { documentation: githubDocumentation } = require('./github-helpers')
+import { renderVersionBadge } from '../version.js'
+import { isLockfile, getDependencyVersion } from '../pipenv-helpers.js'
+import { addv } from '../text-formatters.js'
+import { NotFound } from '../index.js'
+import { ConditionalGithubAuthV3Service } from './github-auth-service.js'
+import { fetchJsonFromRepo } from './github-common-fetch.js'
+import { documentation as githubDocumentation } from './github-helpers.js'
 
 const keywords = ['pipfile']
 
@@ -174,7 +172,7 @@ class GithubPipenvLockedDependencyVersion extends ConditionalGithubAuthV3Service
   }
 }
 
-module.exports = [
+export default [
   GithubPipenvLockedPythonVersion,
   GithubPipenvLockedDependencyVersion,
 ]
diff --git a/services/github/github-pipenv.tester.js b/services/github/github-pipenv.tester.js
index 9161c206258056a304c345fba4c6ced8ca74b44c..c3fa864748eb332defb4e778c73089d24a26c2d5 100644
--- a/services/github/github-pipenv.tester.js
+++ b/services/github/github-pipenv.tester.js
@@ -1,21 +1,19 @@
-'use strict'
-
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-const {
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
+import {
   isVPlusDottedVersionAtLeastOne,
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators')
+} from '../test-validators.js'
 
 // e.g. v19.3b0
 const isBlackVersion = Joi.string().regex(/^v\d+(\.\d+)*(.*)?$/)
 const isShortSha = Joi.string().regex(/[0-9a-f]{7}/)
 
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'GithubPipenv',
   title: 'GithubPipenv',
   pathPrefix: '/github/pipenv',
-}))
+})
 
 t.create('Locked Python version')
   .get('/locked/python-version/metabolize/rq-dashboard-on-heroku.json')
diff --git a/services/github/github-pull-request-check-state.service.js b/services/github/github-pull-request-check-state.service.js
index 4e0d1c861b685c6c619f11b7593d49e4c3d59888..969c75d91be9d9b5e4cd9951d67bcb122a92eee1 100644
--- a/services/github/github-pull-request-check-state.service.js
+++ b/services/github/github-pull-request-check-state.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const countBy = require('lodash.countby')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { fetchIssue } = require('./github-common-fetch')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import countBy from 'lodash.countby'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { fetchIssue } from './github-common-fetch.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.object({
   state: Joi.equal('failure', 'pending', 'success').required(),
@@ -19,7 +17,7 @@ const schema = Joi.object({
 
 const keywords = ['pullrequest', 'detail']
 
-module.exports = class GithubPullRequestCheckState extends GithubAuthV3Service {
+export default class GithubPullRequestCheckState extends GithubAuthV3Service {
   static category = 'build'
   static route = {
     base: 'github/status',
diff --git a/services/github/github-pull-request-check-state.tester.js b/services/github/github-pull-request-check-state.tester.js
index c1215a18c76d6970742fe4e0be4aeba93cf52c53..9095f266f95a11ace918417138d8ff64b3a7d3e4 100644
--- a/services/github/github-pull-request-check-state.tester.js
+++ b/services/github/github-pull-request-check-state.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('github pull request check state')
   .get('/s/pulls/badges/shields/1110.json')
diff --git a/services/github/github-r-package.service.js b/services/github/github-r-package.service.js
index 449a23e2bb0c966a827a3bccd13303aa03734949..837abf6151c94e00502de5672bf7ba4412ecbd9f 100644
--- a/services/github/github-r-package.service.js
+++ b/services/github/github-r-package.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { InvalidResponse } = require('..')
-const { ConditionalGithubAuthV3Service } = require('./github-auth-service')
-const { fetchRepoContent } = require('./github-common-fetch')
-const { documentation } = require('./github-helpers')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { InvalidResponse } from '../index.js'
+import { ConditionalGithubAuthV3Service } from './github-auth-service.js'
+import { fetchRepoContent } from './github-common-fetch.js'
+import { documentation } from './github-helpers.js'
 
 const queryParamSchema = Joi.object({
   filename: Joi.string(),
@@ -13,9 +11,7 @@ const queryParamSchema = Joi.object({
 
 const versionRegExp = /^Version:[\s]*(.+)$/m
 
-module.exports = class GithubRPackageVersion extends (
-  ConditionalGithubAuthV3Service
-) {
+export default class GithubRPackageVersion extends ConditionalGithubAuthV3Service {
   static category = 'version'
 
   static route = {
diff --git a/services/github/github-r-package.spec.js b/services/github/github-r-package.spec.js
index 8bf77d87287129660113533d2f29310183002540..cc6516685e4411de32f0d1e61eb3d905a7a7f2e8 100644
--- a/services/github/github-r-package.spec.js
+++ b/services/github/github-r-package.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const { test, given } = require('sazerac')
-const { InvalidResponse } = require('..')
-const GithubRPackageVersion = require('./github-r-package.service')
+import { expect } from 'chai'
+import { test, given } from 'sazerac'
+import { InvalidResponse } from '../index.js'
+import GithubRPackageVersion from './github-r-package.service.js'
 
 describe('GithubRPackageVersion', function () {
   const content = versionLine =>
diff --git a/services/github/github-r-package.tester.js b/services/github/github-r-package.tester.js
index 01d1511674610125dedbd1e587c71292f57e0ac3..18247e1918a2d551de6a3fa95f695503943456fa 100644
--- a/services/github/github-r-package.tester.js
+++ b/services/github/github-r-package.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('R package version').get('/mixOmicsTeam/mixOmics.json').expectBadge({
   label: 'R',
diff --git a/services/github/github-release-date.service.js b/services/github/github-release-date.service.js
index acca83b2c0e60b2495a5d592045f2db9c62600b1..098bb7c11cc845b50a9e53b6f731dc9849958b3b 100644
--- a/services/github/github-release-date.service.js
+++ b/services/github/github-release-date.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const moment = require('moment')
-const Joi = require('joi')
-const { age } = require('../color-formatters')
-const { formatDate } = require('../text-formatters')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import moment from 'moment'
+import Joi from 'joi'
+import { age } from '../color-formatters.js'
+import { formatDate } from '../text-formatters.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.alternatives(
   Joi.object({
@@ -20,7 +18,7 @@ const schema = Joi.alternatives(
     .min(1)
 )
 
-module.exports = class GithubReleaseDate extends GithubAuthV3Service {
+export default class GithubReleaseDate extends GithubAuthV3Service {
   static category = 'activity'
   static route = {
     base: 'github',
diff --git a/services/github/github-release-date.tester.js b/services/github/github-release-date.tester.js
index 314edaca0ae3cf993167330605ef786e1df6ce6c..3cf255fb731ee321503c5deb934dcc91fa29de9e 100644
--- a/services/github/github-release-date.tester.js
+++ b/services/github/github-release-date.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isFormattedDate } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isFormattedDate } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Release Date. e.g release date|today')
   .get('/release-date/mochajs/mocha.json')
diff --git a/services/github/github-release.service.js b/services/github/github-release.service.js
index 1329ab06ce80b354bf7cacd0a273c2a90fb17d04..94343ad530a7dc36057e88e71a0db750bc3e4646 100644
--- a/services/github/github-release.service.js
+++ b/services/github/github-release.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const { addv } = require('../text-formatters')
-const { version: versionColor } = require('../color-formatters')
-const { redirector } = require('..')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const {
+import { addv } from '../text-formatters.js'
+import { version as versionColor } from '../color-formatters.js'
+import { redirector } from '../index.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import {
   fetchLatestRelease,
   queryParamSchema,
-} = require('./github-common-release')
-const { documentation } = require('./github-helpers')
+} from './github-common-release.js'
+import { documentation } from './github-helpers.js'
 
 class GithubRelease extends GithubAuthV3Service {
   static category = 'version'
@@ -122,7 +120,4 @@ const redirects = {
   }),
 }
 
-module.exports = {
-  GithubRelease,
-  ...redirects,
-}
+export { GithubRelease, redirects }
diff --git a/services/github/github-release.tester.js b/services/github/github-release.tester.js
index 6fa28a54853de19c3fde6bc3a0c8e4e2a99bf003..629eafeecb50f20a76976ffbace93c5d4f279687 100644
--- a/services/github/github-release.tester.js
+++ b/services/github/github-release.tester.js
@@ -1,14 +1,12 @@
-'use strict'
+import Joi from 'joi'
+import { isSemver } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
 
-const Joi = require('joi')
-const { isSemver } = require('../test-validators')
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'GithubRelease',
   title: 'Github Release',
   pathPrefix: '/github',
-}))
+})
 
 t.create('Release')
   .get('/v/release/expressjs/express.json')
diff --git a/services/github/github-repo-size.service.js b/services/github/github-repo-size.service.js
index f581076bf307a4a69d0dda94f12b828318c9d2a2..774ddad426399dd2bcb1496e6928795181ca3f6d 100644
--- a/services/github/github-repo-size.service.js
+++ b/services/github/github-repo-size.service.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const Joi = require('joi')
-const prettyBytes = require('pretty-bytes')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import prettyBytes from 'pretty-bytes'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.object({
   size: nonNegativeInteger,
 }).required()
 
-module.exports = class GithubRepoSize extends GithubAuthV3Service {
+export default class GithubRepoSize extends GithubAuthV3Service {
   static category = 'size'
   static route = { base: 'github/repo-size', pattern: ':user/:repo' }
   static examples = [
diff --git a/services/github/github-repo-size.tester.js b/services/github/github-repo-size.tester.js
index 5d1e43da211716901b247329dc16964c9ee09605..c39f5c700f4a2c088eddeff101d267878d9843e5 100644
--- a/services/github/github-repo-size.tester.js
+++ b/services/github/github-repo-size.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isFileSize } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isFileSize } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('repository size').get('/badges/shields.json').expectBadge({
   label: 'repo size',
diff --git a/services/github/github-search.service.js b/services/github/github-search.service.js
index f8f9d9ddd9d51b276e1ac32abbb7fbe58ba58a2f..361d1b9eb737a959ef1a2f6198334946021849bd 100644
--- a/services/github/github-search.service.js
+++ b/services/github/github-search.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { errorMessagesFor, documentation } = require('./github-helpers')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { errorMessagesFor, documentation } from './github-helpers.js'
 
 const schema = Joi.object({ total_count: nonNegativeInteger }).required()
 
-module.exports = class GithubSearch extends GithubAuthV3Service {
+export default class GithubSearch extends GithubAuthV3Service {
   static category = 'analysis'
 
   static route = {
diff --git a/services/github/github-search.tester.js b/services/github/github-search.tester.js
index 83dd403194404c39f4392da0d9d330697bb64a68..cb3fa80564a1c234f4af720a32d518785fc160e8 100644
--- a/services/github/github-search.tester.js
+++ b/services/github/github-search.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('hit counter')
   .get('/badges/shields/async%20handle.json')
diff --git a/services/github/github-size.service.js b/services/github/github-size.service.js
index 97237a81579f7261c03e78f836f795bf8ff37f27..b932faf17e21a0eb3ec9da6142de183f7041a431 100644
--- a/services/github/github-size.service.js
+++ b/services/github/github-size.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const Joi = require('joi')
-const prettyBytes = require('pretty-bytes')
-const { nonNegativeInteger } = require('../validators')
-const { NotFound } = require('..')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import prettyBytes from 'pretty-bytes'
+import { nonNegativeInteger } from '../validators.js'
+import { NotFound } from '../index.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.alternatives(
   Joi.object({
@@ -14,7 +12,7 @@ const schema = Joi.alternatives(
   Joi.array().required()
 )
 
-module.exports = class GithubSize extends GithubAuthV3Service {
+export default class GithubSize extends GithubAuthV3Service {
   static category = 'size'
 
   static route = {
diff --git a/services/github/github-size.tester.js b/services/github/github-size.tester.js
index 9645a469eee22ebdd021b1a47a4b5d7d3cbe1b6a..db61aa9ac9211eec724ba6feef27d4c626714c5f 100644
--- a/services/github/github-size.tester.js
+++ b/services/github/github-size.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isFileSize } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isFileSize } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('File size')
   .get('/webcaetano/craft/build/phaser-craft.min.js.json')
diff --git a/services/github/github-sponsors.service.js b/services/github/github-sponsors.service.js
index 6a465bdceb0d5241f2e2c0fcb86d47e05736aba8..825104094c7aa0b40c20ca54be86a112c1633ef5 100644
--- a/services/github/github-sponsors.service.js
+++ b/services/github/github-sponsors.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const gql = require('graphql-tag')
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { NotFound } = require('..')
-const { GithubAuthV4Service } = require('./github-auth-service')
-const { documentation, transformErrors } = require('./github-helpers')
+import gql from 'graphql-tag'
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { NotFound } from '../index.js'
+import { GithubAuthV4Service } from './github-auth-service.js'
+import { documentation, transformErrors } from './github-helpers.js'
 
 const schema = Joi.object({
   data: Joi.object({
@@ -18,7 +16,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class GithubSponsors extends GithubAuthV4Service {
+export default class GithubSponsors extends GithubAuthV4Service {
   static category = 'funding'
   static route = { base: 'github/sponsors', pattern: ':user' }
   static examples = [
diff --git a/services/github/github-sponsors.tester.js b/services/github/github-sponsors.tester.js
index ebe0cd50c175992f3ae5b4d89df1d138c59fef28..dc5247cc4e1d57046b569a1d954bb83f8b260729 100644
--- a/services/github/github-sponsors.tester.js
+++ b/services/github/github-sponsors.tester.js
@@ -1,13 +1,11 @@
-'use strict'
+import { isMetric } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
 
-const { isMetric } = require('../test-validators')
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'GithubSponsors',
   title: 'Github Sponsors',
   pathPrefix: '/github',
-}))
+})
 
 t.create('Sponsors').get('/sponsors/Homebrew.json').expectBadge({
   label: 'sponsors',
diff --git a/services/github/github-stars.service.js b/services/github/github-stars.service.js
index 49ce51208672423165b460e54ffa1c2b6e62df51..c790da3f23815b410756ed0900f343465e43bc35 100644
--- a/services/github/github-stars.service.js
+++ b/services/github/github-stars.service.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.object({
   stargazers_count: nonNegativeInteger,
 }).required()
 
-module.exports = class GithubStars extends GithubAuthV3Service {
+export default class GithubStars extends GithubAuthV3Service {
   static category = 'social'
 
   static route = {
diff --git a/services/github/github-stars.tester.js b/services/github/github-stars.tester.js
index fda46a39d1c276e4e5b43853395fdaa60393a781..6155dd553baeb29d8b041be0926d0a4b4f0d83f0 100644
--- a/services/github/github-stars.tester.js
+++ b/services/github/github-stars.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Stars')
   .get('/badges/shields.json')
diff --git a/services/github/github-tag.service.js b/services/github/github-tag.service.js
index c0475651a43cc010551133b0e581e6b44cf653c6..d97201d518853080f44bb252b8b6088dc3124323 100644
--- a/services/github/github-tag.service.js
+++ b/services/github/github-tag.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const gql = require('graphql-tag')
-const Joi = require('joi')
-const { addv } = require('../text-formatters')
-const { version: versionColor } = require('../color-formatters')
-const { latest } = require('../version')
-const { NotFound, redirector } = require('..')
-const { GithubAuthV4Service } = require('./github-auth-service')
-const { queryParamSchema } = require('./github-common-release')
-const { documentation, transformErrors } = require('./github-helpers')
+import gql from 'graphql-tag'
+import Joi from 'joi'
+import { addv } from '../text-formatters.js'
+import { version as versionColor } from '../color-formatters.js'
+import { latest } from '../version.js'
+import { NotFound, redirector } from '../index.js'
+import { GithubAuthV4Service } from './github-auth-service.js'
+import { queryParamSchema } from './github-common-release.js'
+import { documentation, transformErrors } from './github-helpers.js'
 
 const schema = Joi.object({
   data: Joi.object({
@@ -163,7 +161,4 @@ const redirects = {
   }),
 }
 
-module.exports = {
-  GithubTag,
-  ...redirects,
-}
+export { GithubTag, redirects }
diff --git a/services/github/github-tag.spec.js b/services/github/github-tag.spec.js
index 88ebf8b83889aa35f15f2adf513a01e670c28149..c0fbd51e1b14eed8b88dee47e6c4756d634453e5 100644
--- a/services/github/github-tag.spec.js
+++ b/services/github/github-tag.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { GithubTag } = require('./github-tag.service')
+import { test, given } from 'sazerac'
+import { GithubTag } from './github-tag.service.js'
 
 describe('GithubTag', function () {
   test(GithubTag.getLatestTag, () => {
diff --git a/services/github/github-tag.tester.js b/services/github/github-tag.tester.js
index 030eb3283e27c9886ab73b653d0d91c4480830e8..1a804c288621d0a6a44b193f552ff015e99f930d 100644
--- a/services/github/github-tag.tester.js
+++ b/services/github/github-tag.tester.js
@@ -1,14 +1,12 @@
-'use strict'
+import Joi from 'joi'
+import { isSemver } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
 
-const Joi = require('joi')
-const { isSemver } = require('../test-validators')
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'GithubTag',
   title: 'Github Tag',
   pathPrefix: '/github',
-}))
+})
 
 t.create('Tag')
   .get('/v/tag/expressjs/express.json')
diff --git a/services/github/github-top-language.service.js b/services/github/github-top-language.service.js
index 9c96e95b64b7197356026756c9fbe4b22e37138a..21aac8211353141fe5fe8ed5908dff087ebde5fa 100644
--- a/services/github/github-top-language.service.js
+++ b/services/github/github-top-language.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { BaseGithubLanguage } from './github-languages-base.js'
+import { documentation } from './github-helpers.js'
 
-const { BaseGithubLanguage } = require('./github-languages-base')
-const { documentation } = require('./github-helpers')
-
-module.exports = class GithubTopLanguage extends BaseGithubLanguage {
+export default class GithubTopLanguage extends BaseGithubLanguage {
   static category = 'analysis'
 
   static route = {
diff --git a/services/github/github-top-language.tester.js b/services/github/github-top-language.tester.js
index 348d0dbf2c5d5d00cc8cdb04d0ba26819e644094..5bfea8d71299ab6c9520c33d56325fe2456ea70b 100644
--- a/services/github/github-top-language.tester.js
+++ b/services/github/github-top-language.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('top language')
   .get('/badges/shields.json')
diff --git a/services/github/github-total-star.service.js b/services/github/github-total-star.service.js
index 705f5123545e5a80f451c4726d55fed90bab5227..70461fe72c64f406cffafc10ab323135cd662369 100644
--- a/services/github/github-total-star.service.js
+++ b/services/github/github-total-star.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const gql = require('graphql-tag')
-const { nonNegativeInteger } = require('../validators')
-const { metric } = require('../text-formatters')
-const { GithubAuthV4Service } = require('./github-auth-service')
-const {
-  documentation: commonDocumentation,
+import Joi from 'joi'
+import gql from 'graphql-tag'
+import { nonNegativeInteger } from '../validators.js'
+import { metric } from '../text-formatters.js'
+import { GithubAuthV4Service } from './github-auth-service.js'
+import {
+  documentation as commonDocumentation,
   transformErrors,
-} = require('./github-helpers')
+} from './github-helpers.js'
 
 const MAX_REPO_LIMIT = 200
 
@@ -133,7 +131,7 @@ const queryParamSchema = Joi.object({
   affiliations: Joi.string().default('OWNER').custom(validateAffiliations),
 }).required()
 
-module.exports = class GithubTotalStarService extends GithubAuthV4Service {
+export default class GithubTotalStarService extends GithubAuthV4Service {
   static defaultLabel = 'stars'
   static category = 'social'
 
diff --git a/services/github/github-total-star.tester.js b/services/github/github-total-star.tester.js
index 3f4e10674645384b28661eba9633366a936f628f..e67516275fe2f9d241eaa4be41fc52e7aab10976 100644
--- a/services/github/github-total-star.tester.js
+++ b/services/github/github-total-star.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Stars (User)')
   .get('/hemantsonu20.json')
diff --git a/services/github/github-watchers.service.js b/services/github/github-watchers.service.js
index 84b1797c23f45bfcb121cfba664f7bc080f51772..088757ff93a50e1224d240a4fc3b4eb676f26025 100644
--- a/services/github/github-watchers.service.js
+++ b/services/github/github-watchers.service.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { GithubAuthV3Service } = require('./github-auth-service')
-const { documentation, errorMessagesFor } = require('./github-helpers')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { GithubAuthV3Service } from './github-auth-service.js'
+import { documentation, errorMessagesFor } from './github-helpers.js'
 
 const schema = Joi.object({
   subscribers_count: nonNegativeInteger,
 }).required()
 
-module.exports = class GithubWatchers extends GithubAuthV3Service {
+export default class GithubWatchers extends GithubAuthV3Service {
   static category = 'social'
 
   static route = {
diff --git a/services/github/github-watchers.tester.js b/services/github/github-watchers.tester.js
index 6d58e6ed85b14836b2318a28f357dd4d9400d4fd..606b9e53c8a376c7c5fba0c37f933facfe953ecb 100644
--- a/services/github/github-watchers.tester.js
+++ b/services/github/github-watchers.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Watchers')
   .get('/badges/shields.json')
diff --git a/services/github/github-workflow-status.service.js b/services/github/github-workflow-status.service.js
index bdcbd4056870fffbb624828ea1f9743d1e4888ab..f5467d7b2aac81cdfef509e0a48f7b224a7b14e6 100644
--- a/services/github/github-workflow-status.service.js
+++ b/services/github/github-workflow-status.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { BaseSvgScrapingService } = require('..')
-const { documentation } = require('./github-helpers')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { BaseSvgScrapingService } from '../index.js'
+import { documentation } from './github-helpers.js'
 
 const schema = Joi.object({
   message: Joi.alternatives()
@@ -17,7 +15,7 @@ const queryParamSchema = Joi.object({
 
 const keywords = ['action', 'actions']
 
-module.exports = class GithubWorkflowStatus extends BaseSvgScrapingService {
+export default class GithubWorkflowStatus extends BaseSvgScrapingService {
   static category = 'build'
 
   static route = {
diff --git a/services/github/github-workflow-status.tester.js b/services/github/github-workflow-status.tester.js
index 380823e4b59f95fcf5dd1b5fe60225232cf2bea7..573a16e7b18f10df338c5d2abab892a4c9df5012 100644
--- a/services/github/github-workflow-status.tester.js
+++ b/services/github/github-workflow-status.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isWorkflowStatus = Joi.alternatives()
   .try(isBuildStatus, Joi.equal('no status'))
diff --git a/services/gitlab/gitlab-coverage.service.js b/services/gitlab/gitlab-coverage.service.js
index 8f69c62c848730ea00add13ae4d0579970e8a865..f7b4c045d8b9bde273c1dffc14a37ac027c83949 100644
--- a/services/gitlab/gitlab-coverage.service.js
+++ b/services/gitlab/gitlab-coverage.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { coveragePercentage } = require('../color-formatters')
-const { optionalUrl } = require('../validators')
-const { BaseSvgScrapingService, NotFound } = require('..')
+import Joi from 'joi'
+import { coveragePercentage } from '../color-formatters.js'
+import { optionalUrl } from '../validators.js'
+import { BaseSvgScrapingService, NotFound } from '../index.js'
 
 const schema = Joi.object({
   message: Joi.string()
@@ -38,7 +36,7 @@ Also make sure you have set up code covrage parsing as described <a href="https:
 </p>
 `
 
-module.exports = class GitlabCoverage extends BaseSvgScrapingService {
+export default class GitlabCoverage extends BaseSvgScrapingService {
   static category = 'coverage'
 
   static route = {
diff --git a/services/gitlab/gitlab-coverage.tester.js b/services/gitlab/gitlab-coverage.tester.js
index e655e39211b29aa4772eed7360b28a1191ec8cf2..576c5a89728078335e851e933bd20f6a94099a5d 100644
--- a/services/gitlab/gitlab-coverage.tester.js
+++ b/services/gitlab/gitlab-coverage.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Coverage (branch)')
   .get('/gitlab-org/gitlab-runner/12-0-stable.json')
diff --git a/services/gitlab/gitlab-pipeline-status.service.js b/services/gitlab/gitlab-pipeline-status.service.js
index 084b1a9fbe87c3e0e09add5ad43e44ad75f064e0..70494b1a6c21c27802ce9e2bf2042246606ed6b0 100644
--- a/services/gitlab/gitlab-pipeline-status.service.js
+++ b/services/gitlab/gitlab-pipeline-status.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { optionalUrl } = require('../validators')
-const { BaseSvgScrapingService, NotFound, redirector } = require('..')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { optionalUrl } from '../validators.js'
+import { BaseSvgScrapingService, NotFound, redirector } from '../index.js'
 
 const badgeSchema = Joi.object({
   message: Joi.alternatives()
@@ -99,7 +97,4 @@ const GitlabPipelineStatusRedirector = redirector({
   dateAdded: new Date('2020-07-12'),
 })
 
-module.exports = {
-  GitlabPipelineStatus,
-  GitlabPipelineStatusRedirector,
-}
+export { GitlabPipelineStatus, GitlabPipelineStatusRedirector }
diff --git a/services/gitlab/gitlab-pipeline-status.tester.js b/services/gitlab/gitlab-pipeline-status.tester.js
index 0ab56554a6f1a8a21b29dab25587185d60e92089..db8ee99ed77fd03cb3208f166c171d86f9ed37ff 100644
--- a/services/gitlab/gitlab-pipeline-status.tester.js
+++ b/services/gitlab/gitlab-pipeline-status.tester.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import { isBuildStatus } from '../build-status.js'
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'GitlabPipeline',
   title: 'Gitlab Pipeline',
   pathPrefix: '/gitlab/pipeline',
-}))
+})
 
 t.create('Pipeline status').get('/gitlab-org/gitlab/v10.7.6.json').expectBadge({
   label: 'build',
diff --git a/services/gitter/gitter.service.js b/services/gitter/gitter.service.js
index 53a8f3bf6d1a7eaeba80baebaf2b1f2c7630c6a3..55e5d119f7ce72ddf8e334048e013a205736eac3 100644
--- a/services/gitter/gitter.service.js
+++ b/services/gitter/gitter.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseStaticService } from '../index.js'
 
-const { BaseStaticService } = require('..')
-
-module.exports = class Gitter extends BaseStaticService {
+export default class Gitter extends BaseStaticService {
   static category = 'chat'
 
   static route = {
diff --git a/services/gitter/gitter.tester.js b/services/gitter/gitter.tester.js
index 488c6224e28df255782f4f0e984676659872a900..53c8a9cdd9138a1d5949a69998ef7a1c5f5ff29d 100644
--- a/services/gitter/gitter.tester.js
+++ b/services/gitter/gitter.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('on gitter').get('/nwjs/nw.js.json').expectBadge({
   label: 'chat',
diff --git a/services/gradle-plugin-portal/gradle-plugin-portal.service.js b/services/gradle-plugin-portal/gradle-plugin-portal.service.js
index ffa94cbd96087e566e020981e664d439be8c49f2..c1602647f25e23e59a91379a82a5ec1d0cb120f9 100644
--- a/services/gradle-plugin-portal/gradle-plugin-portal.service.js
+++ b/services/gradle-plugin-portal/gradle-plugin-portal.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { redirector } from '../index.js'
+import { documentation } from '../maven-metadata/maven-metadata.js'
 
-const { redirector } = require('..')
-const { documentation } = require('../maven-metadata/maven-metadata')
-
-module.exports = redirector({
+export default redirector({
   category: 'version',
   isDeprecated: false,
   route: {
diff --git a/services/gradle-plugin-portal/gradle-plugin-portal.tester.js b/services/gradle-plugin-portal/gradle-plugin-portal.tester.js
index 8b360b1cb21f9cb9731b21d071bcc7e0fac8a434..a662dc4f197e241b73a8f2ba01a06e766462e5b1 100644
--- a/services/gradle-plugin-portal/gradle-plugin-portal.tester.js
+++ b/services/gradle-plugin-portal/gradle-plugin-portal.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('gradle plugin portal')
   .get('/com.gradle.plugin-publish')
diff --git a/services/gratipay/gratipay.service.js b/services/gratipay/gratipay.service.js
index 3ad1964d72d0a327ae9039a2c15795507e1454db..8ea38b6e9555ec305e9da03e21a2b360a6a80745 100644
--- a/services/gratipay/gratipay.service.js
+++ b/services/gratipay/gratipay.service.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { deprecatedService } = require('..')
+import { deprecatedService } from '../index.js'
 
 const commonAttrs = {
   category: 'funding',
@@ -8,7 +6,7 @@ const commonAttrs = {
   dateAdded: new Date('2017-12-29'),
 }
 
-module.exports = [
+export default [
   deprecatedService({
     route: {
       base: 'gittip',
diff --git a/services/gratipay/gratipay.tester.js b/services/gratipay/gratipay.tester.js
index 57a7130fa722d391daf6f82f99cbd2946d62fca3..f7684a05de39f59995b3f9e7286762fef1e19b72 100644
--- a/services/gratipay/gratipay.tester.js
+++ b/services/gratipay/gratipay.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'gratipay',
   title: 'Gratipay',
-}))
+})
 
 t.create('Receiving').get('/Gratipay.json').expectBadge({
   label: 'gratipay',
diff --git a/services/hackage/hackage-deps.service.js b/services/hackage/hackage-deps.service.js
index b2b5939a40829dbfbe41d4e07a486de18dec626a..f3cbd1deb996b2a9e0b47fc20d1b7d9e12b2f273 100644
--- a/services/hackage/hackage-deps.service.js
+++ b/services/hackage/hackage-deps.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseService } from '../index.js'
 
-const { BaseService } = require('..')
-
-module.exports = class HackageDeps extends BaseService {
+export default class HackageDeps extends BaseService {
   static category = 'dependencies'
 
   static route = {
diff --git a/services/hackage/hackage-deps.tester.js b/services/hackage/hackage-deps.tester.js
index caab395b12f29b8234cf4cb1d0dc17400ef996d1..6133b776e60999bfed6d416c7fd28d47d09dd4db 100644
--- a/services/hackage/hackage-deps.tester.js
+++ b/services/hackage/hackage-deps.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('hackage deps (valid)')
   .get('/lens.json')
diff --git a/services/hackage/hackage-version.service.js b/services/hackage/hackage-version.service.js
index b86f2e4d655f97f44bc8dacbc75bf15edd1dffe7..e1333a14e65106aec8a42751bbacf1069214af8b 100644
--- a/services/hackage/hackage-version.service.js
+++ b/services/hackage/hackage-version.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import { BaseService, InvalidResponse } from '../index.js'
 
-const { renderVersionBadge } = require('../version')
-const { BaseService, InvalidResponse } = require('..')
-
-module.exports = class HackageVersion extends BaseService {
+export default class HackageVersion extends BaseService {
   static category = 'version'
 
   static route = {
diff --git a/services/hackage/hackage-version.tester.js b/services/hackage/hackage-version.tester.js
index 5349195ccd6da329c058cdc5daa2867554b57636..f4074ec9c1a99cfb98594622586d0b6b437ac66b 100644
--- a/services/hackage/hackage-version.tester.js
+++ b/services/hackage/hackage-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('hackage version (valid)').get('/lens.json').expectBadge({
   label: 'hackage',
diff --git a/services/hexpm/hexpm.service.js b/services/hexpm/hexpm.service.js
index 9e0e9d06988530d42da7260f93d2c7e1ce46ed54..fe03981abe80eabdcf4b8069bf0c261cc1fec378 100644
--- a/services/hexpm/hexpm.service.js
+++ b/services/hexpm/hexpm.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric, addv, maybePluralize } = require('../text-formatters')
-const { downloadCount, version: versionColor } = require('../color-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric, addv, maybePluralize } from '../text-formatters.js'
+import { downloadCount, version as versionColor } from '../color-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const hexSchema = Joi.object({
   downloads: Joi.object({
@@ -149,4 +147,4 @@ function DownloadsForInterval(interval) {
 
 const downloadsServices = ['day', 'week', 'all'].map(DownloadsForInterval)
 
-module.exports = [...downloadsServices, HexPmLicense, HexPmVersion]
+export default [...downloadsServices, HexPmLicense, HexPmVersion]
diff --git a/services/hexpm/hexpm.tester.js b/services/hexpm/hexpm.tester.js
index 936f74b1df70284bc6951fdd15c7e40f04e253cd..d7f1d661b77f2b3c111393df89fee7a2e7c80bb5 100644
--- a/services/hexpm/hexpm.tester.js
+++ b/services/hexpm/hexpm.tester.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-const { isMetric, isMetricOverTimePeriod } = require('../test-validators')
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
+import { isMetric, isMetricOverTimePeriod } from '../test-validators.js'
 
 const isHexpmVersion = Joi.string().regex(/^v\d+.\d+.?\d?$/)
 
-const t = (module.exports = new ServiceTester({ id: 'hexpm', title: 'Hex.pm' }))
+export const t = new ServiceTester({ id: 'hexpm', title: 'Hex.pm' })
 
 t.create('downloads per week')
   .get('/dw/cowboy.json')
diff --git a/services/homebrew/homebrew-cask.service.js b/services/homebrew/homebrew-cask.service.js
index 93310bd31ce74e587da00c8497e12bddafc48ed7..bb08a435b4ed10ad7d2d5b2c6f775134cff45d4c 100644
--- a/services/homebrew/homebrew-cask.service.js
+++ b/services/homebrew/homebrew-cask.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   version: Joi.string().required(),
 }).required()
 
-module.exports = class HomebrewCask extends BaseJsonService {
+export default class HomebrewCask extends BaseJsonService {
   static category = 'version'
   static route = { base: 'homebrew/cask/v', pattern: ':cask' }
 
diff --git a/services/homebrew/homebrew-cask.tester.js b/services/homebrew/homebrew-cask.tester.js
index c192510cf7a4673e363bac80a08905567a017e2c..7535c3a8e5cc1b99345a9770e489ce745d92eb53 100644
--- a/services/homebrew/homebrew-cask.tester.js
+++ b/services/homebrew/homebrew-cask.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusTripleDottedVersion } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusTripleDottedVersion } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('homebrew cask (valid)').get('/iterm2.json').expectBadge({
   label: 'homebrew cask',
diff --git a/services/homebrew/homebrew-downloads.service.js b/services/homebrew/homebrew-downloads.service.js
index 201b5c7bf523e48ca0450d755cb76a05e405f3ed..b4e39cbee8a2075c25a7f8cd3339c9a533153181 100644
--- a/services/homebrew/homebrew-downloads.service.js
+++ b/services/homebrew/homebrew-downloads.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { downloadCount } = require('../color-formatters')
-const { metric } = require('../text-formatters')
-const { BaseJsonService } = require('..')
-const { nonNegativeInteger } = require('../validators')
+import Joi from 'joi'
+import { downloadCount } from '../color-formatters.js'
+import { metric } from '../text-formatters.js'
+import { BaseJsonService } from '../index.js'
+import { nonNegativeInteger } from '../validators.js'
 
 function getSchema({ formula }) {
   return Joi.object({
@@ -33,7 +31,7 @@ const periodMap = {
   },
 }
 
-module.exports = class HomebrewDownloads extends BaseJsonService {
+export default class HomebrewDownloads extends BaseJsonService {
   static category = 'downloads'
 
   static route = {
diff --git a/services/homebrew/homebrew-downloads.tester.js b/services/homebrew/homebrew-downloads.tester.js
index 5f612ace9f6ab3745f7e41e12aa4fd256582f26c..972df583f38c9f427e686a08e14d75dfc7f35f97 100644
--- a/services/homebrew/homebrew-downloads.tester.js
+++ b/services/homebrew/homebrew-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isMetricOverTimePeriod } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isMetricOverTimePeriod } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('daily downloads (valid)')
   .get('/installs/dm/cake.json')
diff --git a/services/homebrew/homebrew-version.service.js b/services/homebrew/homebrew-version.service.js
index 02d0f8f925205537d0d8048b43421410f1cc862e..f32e77e518d76caf72c6c184c68bab4600b7cf75 100644
--- a/services/homebrew/homebrew-version.service.js
+++ b/services/homebrew/homebrew-version.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   versions: Joi.object({
@@ -10,7 +8,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class HomebrewVersion extends BaseJsonService {
+export default class HomebrewVersion extends BaseJsonService {
   static category = 'version'
 
   static route = { base: 'homebrew/v', pattern: ':formula' }
diff --git a/services/homebrew/homebrew-version.tester.js b/services/homebrew/homebrew-version.tester.js
index 13fbd91b4e01fa34b01743f7a187e06b772248a2..1e69f15cfb6b98d7b6db316e46085ce68306cbc1 100644
--- a/services/homebrew/homebrew-version.tester.js
+++ b/services/homebrew/homebrew-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusTripleDottedVersion } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusTripleDottedVersion } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('homebrew (valid)').get('/cake.json').expectBadge({
   label: 'homebrew',
diff --git a/services/hsts/hsts.service.js b/services/hsts/hsts.service.js
index 9361eb7e675315469e7f0957a1b2fe63604d938b..c768815d5639e23aa1da41ccf7a2ef93bb793c01 100644
--- a/services/hsts/hsts.service.js
+++ b/services/hsts/hsts.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 const label = 'hsts preloaded'
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
 const schema = Joi.object({
   status: Joi.string().required(),
 }).required()
@@ -21,7 +19,7 @@ const documentation = `
 </p>
 `
 
-module.exports = class HSTS extends BaseJsonService {
+export default class HSTS extends BaseJsonService {
   static category = 'monitoring'
 
   static route = {
diff --git a/services/hsts/hsts.tester.js b/services/hsts/hsts.tester.js
index ce04eb25906bb063196f8e0d0c0f99324a7c9b16..0f55a07b79359185181f979a3f222d637d136be9 100644
--- a/services/hsts/hsts.tester.js
+++ b/services/hsts/hsts.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 const label = 'hsts preloaded'
 
 t.create('gets the hsts status of github').get('/github.com.json').expectBadge({
diff --git a/services/imagelayers/imagelayers.service.js b/services/imagelayers/imagelayers.service.js
index 8e948c17ab435daf503b01037d54a9b386d9af7b..1ae1d3f1e30322fbe406460f765f5defdbd3f5a1 100644
--- a/services/imagelayers/imagelayers.service.js
+++ b/services/imagelayers/imagelayers.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'size',
   route: {
     base: 'imagelayers',
diff --git a/services/imagelayers/imagelayers.tester.js b/services/imagelayers/imagelayers.tester.js
index 35234ace9ed26b87bee947c2d3d8dd73031413fc..7e4b7808172f02eb554165baeadf06fc39f20092 100644
--- a/services/imagelayers/imagelayers.tester.js
+++ b/services/imagelayers/imagelayers.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'imagelayers',
   title: 'ImageLayers',
-}))
+})
 
 t.create('no longer available (previously image size)')
   .get('/image-size/_/ubuntu/latest.json')
diff --git a/services/index.js b/services/index.js
index 14d418b6df2fe4ad701b3fce4a2b706077bc9653..1ba849b1b8f42e1990f72385e7bd2f784353c0f5 100644
--- a/services/index.js
+++ b/services/index.js
@@ -1,7 +1 @@
-'use strict'
-
-const base = require('../core/base-service')
-
-module.exports = {
-  ...base,
-}
+export * from '../core/base-service/index.js'
diff --git a/services/issuestats/issuestats.service.js b/services/issuestats/issuestats.service.js
index ed1bb6af8db6f94faef41c54a338c30e26df6382..1ab375a8c5c62377b7e7428087695ad91623249c 100644
--- a/services/issuestats/issuestats.service.js
+++ b/services/issuestats/issuestats.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'issue-tracking',
   route: { base: 'issuestats', pattern: ':various+' },
   label: 'issue stats',
diff --git a/services/issuestats/issuestats.tester.js b/services/issuestats/issuestats.tester.js
index 1eab93c18a6c516ed0c9991ed7c19f8a7f07fd29..3f4853bdad4f3e9825f5ac6af7786bb2966c2704 100644
--- a/services/issuestats/issuestats.tester.js
+++ b/services/issuestats/issuestats.tester.js
@@ -1,9 +1,6 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = new ServiceTester({ id: 'issuestats', title: 'Issue Stats' })
-module.exports = t
+export const t = new ServiceTester({ id: 'issuestats', title: 'Issue Stats' })
 
 t.create('no longer available (previously issue analysis)')
   .get('/i/github/expressjs/express.json')
diff --git a/services/itunes/itunes.service.js b/services/itunes/itunes.service.js
index 2f82a9580fa7b786eca6b7f288baed946932767d..bcb367bc8abd0ceaac387d2e634227796ef1c880 100644
--- a/services/itunes/itunes.service.js
+++ b/services/itunes/itunes.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const schema = Joi.object({
   resultCount: nonNegativeInteger,
@@ -12,7 +10,7 @@ const schema = Joi.object({
     .min(0),
 }).required()
 
-module.exports = class Itunes extends BaseJsonService {
+export default class Itunes extends BaseJsonService {
   static category = 'version'
 
   static route = {
diff --git a/services/itunes/itunes.tester.js b/services/itunes/itunes.tester.js
index cc34225498118a52e71cf7e82aeed7c98d5ad61e..2499ed3f9702dd910f5f24dc7b4bac94d3e73ca8 100644
--- a/services/itunes/itunes.tester.js
+++ b/services/itunes/itunes.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('iTunes version (valid)').get('/324684580.json').expectBadge({
   label: 'itunes app store',
diff --git a/services/jenkins/jenkins-base.js b/services/jenkins/jenkins-base.js
index 762278b58415709a37c6749d949874d0c3b3dcd6..f7243d0b377d76c13071bd5f50508b157e4524b5 100644
--- a/services/jenkins/jenkins-base.js
+++ b/services/jenkins/jenkins-base.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseJsonService } from '../index.js'
 
-const { BaseJsonService } = require('..')
-
-module.exports = class JenkinsBase extends BaseJsonService {
+export default class JenkinsBase extends BaseJsonService {
   static auth = {
     userKey: 'jenkins_user',
     passKey: 'jenkins_pass',
diff --git a/services/jenkins/jenkins-build-redirect.service.js b/services/jenkins/jenkins-build-redirect.service.js
index b26738b726d15463ea70ece8c911162abe91e3e8..b7666291c7152bda943499a3c9b9cf49d4adcde6 100644
--- a/services/jenkins/jenkins-build-redirect.service.js
+++ b/services/jenkins/jenkins-build-redirect.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { redirector } = require('..')
-const { buildRedirectUrl } = require('./jenkins-common')
+import { redirector } from '../index.js'
+import { buildRedirectUrl } from './jenkins-common.js'
 
 const commonProps = {
   category: 'build',
@@ -11,7 +9,7 @@ const commonProps = {
   }),
 }
 
-module.exports = [
+export default [
   redirector({
     route: {
       base: 'jenkins-ci/s',
diff --git a/services/jenkins/jenkins-build-redirect.tester.js b/services/jenkins/jenkins-build-redirect.tester.js
index 33a0168837a1a4115995a61bba216284bc8d4392..3e5e76aa0cf2d12a3415b9cc549c6cad1be8f367 100644
--- a/services/jenkins/jenkins-build-redirect.tester.js
+++ b/services/jenkins/jenkins-build-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'JenkinsBuildRedirect',
   title: 'JenkinsBuildRedirect',
   pathPrefix: '/',
-}))
+})
 
 t.create('old jenkins ci prefix + job url in path')
   .get('jenkins-ci/s/https/updates.jenkins-ci.org/job/foo.svg')
diff --git a/services/jenkins/jenkins-build.service.js b/services/jenkins/jenkins-build.service.js
index b0051963addc899a1b4b7479ae90e9e563671c70..667d42bb376c6ac2f1ba59e3a1423513f06012fd 100644
--- a/services/jenkins/jenkins-build.service.js
+++ b/services/jenkins/jenkins-build.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderBuildStatusBadge } = require('../build-status')
-const JenkinsBase = require('./jenkins-base')
-const {
+import Joi from 'joi'
+import { renderBuildStatusBadge } from '../build-status.js'
+import JenkinsBase from './jenkins-base.js'
+import {
   buildTreeParamQueryString,
   buildUrl,
   queryParamSchema,
-} = require('./jenkins-common')
+} from './jenkins-common.js'
 
 // https://github.com/jenkinsci/jenkins/blob/master/core/src/main/java/hudson/model/BallColor.java#L56
 const colorStatusMap = {
@@ -33,7 +31,7 @@ const schema = Joi.object({
   color: Joi.allow(...Object.keys(colorStatusMap)).required(),
 }).required()
 
-module.exports = class JenkinsBuild extends JenkinsBase {
+export default class JenkinsBuild extends JenkinsBase {
   static category = 'build'
 
   static route = {
diff --git a/services/jenkins/jenkins-build.spec.js b/services/jenkins/jenkins-build.spec.js
index 6223e51eaa6068f740489bc5c67e36f6d90c15ab..a821f272709f346254d71ea02c37aec2e55ec243 100644
--- a/services/jenkins/jenkins-build.spec.js
+++ b/services/jenkins/jenkins-build.spec.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { test, forCases, given } = require('sazerac')
-const { renderBuildStatusBadge } = require('../build-status')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const JenkinsBuild = require('./jenkins-build.service')
+import { expect } from 'chai'
+import nock from 'nock'
+import { test, forCases, given } from 'sazerac'
+import { renderBuildStatusBadge } from '../build-status.js'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import JenkinsBuild from './jenkins-build.service.js'
 
 describe('JenkinsBuild', function () {
   test(JenkinsBuild.prototype.transform, () => {
diff --git a/services/jenkins/jenkins-build.tester.js b/services/jenkins/jenkins-build.tester.js
index 440e309c272616add842857727752b22f6b50906..7ebfb5df861f5c900a5113f55a5866aa8dd9170a 100644
--- a/services/jenkins/jenkins-build.tester.js
+++ b/services/jenkins/jenkins-build.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isJenkinsBuildStatus = Joi.alternatives(
   isBuildStatus,
diff --git a/services/jenkins/jenkins-common.js b/services/jenkins/jenkins-common.js
index 5656bdb12e2f8a2150dcfbb1795929f2609b45eb..c9c6b771be6d8da37d2b69c353aedd55db9c089d 100644
--- a/services/jenkins/jenkins-common.js
+++ b/services/jenkins/jenkins-common.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
 
 const queryParamSchema = Joi.object({
   disableStrictSSL: Joi.equal(''),
@@ -21,9 +19,5 @@ const buildUrl = ({ jobUrl, lastCompletedBuild = true, plugin }) => {
   return `${jobUrl}/${lastCompletedBuildElement}${pluginElement}api/json`
 }
 
-module.exports = {
-  queryParamSchema,
-  buildTreeParamQueryString: tree => ({ tree }),
-  buildUrl,
-  buildRedirectUrl,
-}
+export { queryParamSchema, buildUrl, buildRedirectUrl }
+export const buildTreeParamQueryString = tree => ({ tree })
diff --git a/services/jenkins/jenkins-common.spec.js b/services/jenkins/jenkins-common.spec.js
index 8a639a1ee55fb2e05223871e58978a8a1007cae0..ae1e2e998359febd0ef672607677ce2409932314 100644
--- a/services/jenkins/jenkins-common.spec.js
+++ b/services/jenkins/jenkins-common.spec.js
@@ -1,6 +1,5 @@
-'use strict'
-const { expect } = require('chai')
-const { buildRedirectUrl, buildUrl } = require('./jenkins-common')
+import { expect } from 'chai'
+import { buildRedirectUrl, buildUrl } from './jenkins-common.js'
 
 describe('jenkins-common', function () {
   describe('buildUrl', function () {
diff --git a/services/jenkins/jenkins-coverage-redirector.service.js b/services/jenkins/jenkins-coverage-redirector.service.js
index 7658977c15c3b41a13c9100ed8e8f48cdb8a1225..05b828f870a40c4d02a3fc066d175a3d2b89d267 100644
--- a/services/jenkins/jenkins-coverage-redirector.service.js
+++ b/services/jenkins/jenkins-coverage-redirector.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { redirector } = require('..')
-const { buildRedirectUrl } = require('./jenkins-common')
+import { redirector } from '../index.js'
+import { buildRedirectUrl } from './jenkins-common.js'
 
 const commonProps = {
   category: 'coverage',
@@ -10,7 +8,7 @@ const commonProps = {
   }),
 }
 
-module.exports = [
+export default [
   redirector({
     route: {
       base: 'jenkins',
diff --git a/services/jenkins/jenkins-coverage-redirector.tester.js b/services/jenkins/jenkins-coverage-redirector.tester.js
index fd67cf389da05480f357d07106bd697e71275947..d6475017c59e96e1be0789b6cbbf9a4d39f4d066 100644
--- a/services/jenkins/jenkins-coverage-redirector.tester.js
+++ b/services/jenkins/jenkins-coverage-redirector.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'JenkinsCoverageRedirector',
   title: 'JenkinsCoverageRedirector',
   pathPrefix: '/jenkins',
-}))
+})
 
 t.create('old Jacoco prefix + job url in path')
   .get(
diff --git a/services/jenkins/jenkins-coverage.service.js b/services/jenkins/jenkins-coverage.service.js
index aefa814a855f79c74109f483954d862c5662b602..1d918b4216e25a91af7981dce5c7e318f0df6ed2 100644
--- a/services/jenkins/jenkins-coverage.service.js
+++ b/services/jenkins/jenkins-coverage.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { coveragePercentage } = require('../color-formatters')
-const JenkinsBase = require('./jenkins-base')
-const {
+import Joi from 'joi'
+import { coveragePercentage } from '../color-formatters.js'
+import JenkinsBase from './jenkins-base.js'
+import {
   buildTreeParamQueryString,
   buildUrl,
   queryParamSchema,
-} = require('./jenkins-common')
+} from './jenkins-common.js'
 
 const formatMap = {
   jacoco: {
@@ -81,7 +79,7 @@ const documentation = `
 </p>
 `
 
-module.exports = class JenkinsCoverage extends JenkinsBase {
+export default class JenkinsCoverage extends JenkinsBase {
   static category = 'coverage'
 
   static route = {
diff --git a/services/jenkins/jenkins-coverage.tester.js b/services/jenkins/jenkins-coverage.tester.js
index 525187cd5856564a109f1821404cdadfbe03ee2d..fae3f9b4d95d34673c1ed4e02e7a2658d2ad5b3e 100644
--- a/services/jenkins/jenkins-coverage.tester.js
+++ b/services/jenkins/jenkins-coverage.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // The below page includes links to various publicly accessible Jenkins instances
 // although many of the links are dead, it is is still a helpful resource for finding
diff --git a/services/jenkins/jenkins-plugin-installs.service.js b/services/jenkins/jenkins-plugin-installs.service.js
index 1c9620109a50cd617327b85b4e2b067c49d71bbc..ef24d19e7221cd872ec2fa45948cf2c15ba3e230 100644
--- a/services/jenkins/jenkins-plugin-installs.service.js
+++ b/services/jenkins/jenkins-plugin-installs.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { downloadCount: downloadCountColor } = require('../color-formatters')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { downloadCount as downloadCountColor } from '../color-formatters.js'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const schemaInstallations = Joi.object()
   .keys({
@@ -24,7 +22,7 @@ const schemaInstallationsPerVersion = Joi.object()
   })
   .required()
 
-module.exports = class JenkinsPluginInstalls extends BaseJsonService {
+export default class JenkinsPluginInstalls extends BaseJsonService {
   static _getSchema(version) {
     if (version) {
       return schemaInstallationsPerVersion
diff --git a/services/jenkins/jenkins-plugin-installs.tester.js b/services/jenkins/jenkins-plugin-installs.tester.js
index ece5eaacf0f588aab9eaf7bce53d88131b529758..5c0f0687b801019c376e9f2e1e2bac09bc94b1eb 100644
--- a/services/jenkins/jenkins-plugin-installs.tester.js
+++ b/services/jenkins/jenkins-plugin-installs.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // total installs
 
diff --git a/services/jenkins/jenkins-plugin-version.service.js b/services/jenkins/jenkins-plugin-version.service.js
index 2ab78f32994e75b0c4ac7a14c7200fd24bfb0e2f..98486776bf8a9efc02aaba9124665efff41e8c76 100644
--- a/services/jenkins/jenkins-plugin-version.service.js
+++ b/services/jenkins/jenkins-plugin-version.service.js
@@ -1,11 +1,9 @@
-'use strict'
+import { promisify } from 'util'
+import { regularUpdate } from '../../core/legacy/regular-update.js'
+import { renderVersionBadge } from '../version.js'
+import { BaseService, NotFound } from '../index.js'
 
-const { promisify } = require('util')
-const { regularUpdate } = require('../../core/legacy/regular-update')
-const { renderVersionBadge } = require('../version')
-const { BaseService, NotFound } = require('..')
-
-module.exports = class JenkinsPluginVersion extends BaseService {
+export default class JenkinsPluginVersion extends BaseService {
   static category = 'version'
 
   static route = {
diff --git a/services/jenkins/jenkins-plugin-version.tester.js b/services/jenkins/jenkins-plugin-version.tester.js
index 9a64bcbae05c17768778ff8a481f717c1a62ab0b..f9c4d2dfc946086a1fe5b13bc99e97603e6be560 100644
--- a/services/jenkins/jenkins-plugin-version.tester.js
+++ b/services/jenkins/jenkins-plugin-version.tester.js
@@ -1,14 +1,11 @@
-'use strict'
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
 
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-
-const t = new ServiceTester({
+export const t = new ServiceTester({
   id: 'jenkins-plugin',
   title: 'JenkinsPluginVersion',
   pathPrefix: '/jenkins',
 })
-module.exports = t
 
 t.create('latest version')
   .get('/plugin/v/blueocean.json')
diff --git a/services/jenkins/jenkins-tests-redirector.service.js b/services/jenkins/jenkins-tests-redirector.service.js
index 138ded80bc354f15aca7ff1310533940f625c59c..051b21a81f4edacf01dbae22dd7647bec93a40ea 100644
--- a/services/jenkins/jenkins-tests-redirector.service.js
+++ b/services/jenkins/jenkins-tests-redirector.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { redirector } = require('..')
-const { buildRedirectUrl } = require('./jenkins-common')
+import { redirector } from '../index.js'
+import { buildRedirectUrl } from './jenkins-common.js'
 
 const commonProps = {
   category: 'build',
@@ -11,7 +9,7 @@ const commonProps = {
   }),
 }
 
-module.exports = [
+export default [
   redirector({
     route: {
       base: 'jenkins/t',
diff --git a/services/jenkins/jenkins-tests-redirector.tester.js b/services/jenkins/jenkins-tests-redirector.tester.js
index 3f6cfc9de672b12b75ff6a5a5b971745b5d2ba18..837c9f4b1394d5f0f616574983fcd92fd8b371b3 100644
--- a/services/jenkins/jenkins-tests-redirector.tester.js
+++ b/services/jenkins/jenkins-tests-redirector.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'JenkinsTestsRedirector',
   title: 'JenkinsTestsRedirector',
   pathPrefix: '/jenkins',
-}))
+})
 
 t.create('old tests prefix + job url in path')
   .get(
diff --git a/services/jenkins/jenkins-tests.service.js b/services/jenkins/jenkins-tests.service.js
index a438609dc1175a76a0437b64eef3db111e5432e7..4c9a74767a594eac480d1e466426ad83fa67625f 100644
--- a/services/jenkins/jenkins-tests.service.js
+++ b/services/jenkins/jenkins-tests.service.js
@@ -1,19 +1,17 @@
-'use strict'
-
-const Joi = require('joi')
-const {
+import Joi from 'joi'
+import {
   documentation,
   testResultQueryParamSchema,
   renderTestResultBadge,
-} = require('../test-results')
-const { optionalNonNegativeInteger } = require('../validators')
-const { InvalidResponse } = require('..')
-const JenkinsBase = require('./jenkins-base')
-const {
+} from '../test-results.js'
+import { optionalNonNegativeInteger } from '../validators.js'
+import { InvalidResponse } from '../index.js'
+import JenkinsBase from './jenkins-base.js'
+import {
   buildTreeParamQueryString,
   buildUrl,
   queryParamSchema,
-} = require('./jenkins-common')
+} from './jenkins-common.js'
 
 // In the API response, the `actions` array can be empty, and when it is not empty it will contain a
 // mix of objects. Some will be empty objects, and several will not have the test count properties.
@@ -35,7 +33,7 @@ const schema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class JenkinsTests extends JenkinsBase {
+export default class JenkinsTests extends JenkinsBase {
   static category = 'build'
 
   static route = {
diff --git a/services/jenkins/jenkins-tests.tester.js b/services/jenkins/jenkins-tests.tester.js
index 7b4f490ffbd4a7a94315134159eb3cd7f5e3adfb..a9269c9bd674740b31936d7991f0e017b843be51 100644
--- a/services/jenkins/jenkins-tests.tester.js
+++ b/services/jenkins/jenkins-tests.tester.js
@@ -1,12 +1,11 @@
-'use strict'
-
-const {
+import {
   isDefaultTestTotals,
   isDefaultCompactTestTotals,
   isCustomTestTotals,
   isCustomCompactTestTotals,
-} = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+} from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // The below page includes links to various publicly accessible Jenkins instances
 // although many of the links are dead, it is is still a helpful resource for finding
diff --git a/services/jetbrains/jetbrains-base.js b/services/jetbrains/jetbrains-base.js
index cba934dd42926e3de4241243f38ddcde57c674f0..140a94b2a7559b3fb3f8e9d025165a28c60c2a2d 100644
--- a/services/jetbrains/jetbrains-base.js
+++ b/services/jetbrains/jetbrains-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { BaseXmlService, NotFound } = require('..')
-const { parseJson } = require('../../core/base-service/json')
+import { BaseXmlService, NotFound } from '../index.js'
+import { parseJson } from '../../core/base-service/json.js'
 
 /*
 JetBrains is a bit awkward. Sometimes we want to call an XML API
@@ -10,7 +8,7 @@ When the legacy IntelliJ (XML) API is retired we can simplify all this and
 switch JetbrainsDownloads, JetbrainsRating and JetbrainsVersion to just
 inherit from BaseJsonService directly.
 */
-module.exports = class JetbrainsBase extends BaseXmlService {
+export default class JetbrainsBase extends BaseXmlService {
   static _isLegacyPluginId(pluginId) {
     return !pluginId.match(/^([0-9])+/)
   }
diff --git a/services/jetbrains/jetbrains-downloads.service.js b/services/jetbrains/jetbrains-downloads.service.js
index c2d7f879041c91880754fcceb216ac13a3d76b7a..ab379c5eb7e4deb3a986076e5436574830d71008 100644
--- a/services/jetbrains/jetbrains-downloads.service.js
+++ b/services/jetbrains/jetbrains-downloads.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { downloadCount: downloadCountColor } = require('../color-formatters')
-const { nonNegativeInteger } = require('../validators')
-const JetbrainsBase = require('./jetbrains-base')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { downloadCount as downloadCountColor } from '../color-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import JetbrainsBase from './jetbrains-base.js'
 
 const intelliJschema = Joi.object({
   'plugin-repository': Joi.object({
@@ -24,7 +22,7 @@ const intelliJschema = Joi.object({
 
 const jetbrainsSchema = Joi.object({ downloads: nonNegativeInteger }).required()
 
-module.exports = class JetbrainsDownloads extends JetbrainsBase {
+export default class JetbrainsDownloads extends JetbrainsBase {
   static category = 'downloads'
 
   static route = {
diff --git a/services/jetbrains/jetbrains-downloads.tester.js b/services/jetbrains/jetbrains-downloads.tester.js
index 946f43e517179bac9a3e28e044019995dd473abd..06c30636474e289cb9371251443ebe45c3b36e69 100644
--- a/services/jetbrains/jetbrains-downloads.tester.js
+++ b/services/jetbrains/jetbrains-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('downloads (number as a plugin id)')
   .get('/7495.json')
diff --git a/services/jetbrains/jetbrains-rating.service.js b/services/jetbrains/jetbrains-rating.service.js
index 480d276b6be5cf61b09a67495db8678510ead95a..55ae8696273dd06a753f4f653ceea3ec9c00d89e 100644
--- a/services/jetbrains/jetbrains-rating.service.js
+++ b/services/jetbrains/jetbrains-rating.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { starRating } = require('../text-formatters')
-const { colorScale } = require('../color-formatters')
-const JetbrainsBase = require('./jetbrains-base')
+import Joi from 'joi'
+import { starRating } from '../text-formatters.js'
+import { colorScale } from '../color-formatters.js'
+import JetbrainsBase from './jetbrains-base.js'
 
 const pluginRatingColor = colorScale([2, 3, 4])
 
@@ -27,7 +25,7 @@ const jetbrainsSchema = Joi.object({
   meanRating: Joi.number().min(0).required(),
 }).required()
 
-module.exports = class JetbrainsRating extends JetbrainsBase {
+export default class JetbrainsRating extends JetbrainsBase {
   static category = 'rating'
 
   static route = {
diff --git a/services/jetbrains/jetbrains-rating.tester.js b/services/jetbrains/jetbrains-rating.tester.js
index be721b1c320582358dada608e8bca464c38b3917..b80d03c5ad82429c787fd1cf43f03de41297858f 100644
--- a/services/jetbrains/jetbrains-rating.tester.js
+++ b/services/jetbrains/jetbrains-rating.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex, isStarRating } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex, isStarRating } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isRating = withRegex(/^(([0-4](.?([0-9]))?)|5)\/5$/)
 
diff --git a/services/jetbrains/jetbrains-version.service.js b/services/jetbrains/jetbrains-version.service.js
index 09aa91bf04cbf43e1916381c515648485fabc7f5..2b7d8dd3b2b077a377a96a518fa39a7407d31ea4 100644
--- a/services/jetbrains/jetbrains-version.service.js
+++ b/services/jetbrains/jetbrains-version.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const JetbrainsBase = require('./jetbrains-base')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import JetbrainsBase from './jetbrains-base.js'
 
 const intelliJschema = Joi.object({
   'plugin-repository': Joi.object({
@@ -29,7 +27,7 @@ const jetbrainsSchema = Joi.array()
   )
   .required()
 
-module.exports = class JetbrainsVersion extends JetbrainsBase {
+export default class JetbrainsVersion extends JetbrainsBase {
   static category = 'version'
 
   static route = {
diff --git a/services/jetbrains/jetbrains-version.tester.js b/services/jetbrains/jetbrains-version.tester.js
index 0d5861c17694563d829ecdb134f9dfe1c7718b41..5a4d477e62cd6e64d1e3e2a4c4afb6af0f68156e 100644
--- a/services/jetbrains/jetbrains-version.tester.js
+++ b/services/jetbrains/jetbrains-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionNClauses } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionNClauses } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('version (user friendly plugin id)')
   .get('/1347-scala.json')
diff --git a/services/jira/jira-common.js b/services/jira/jira-common.js
index e8fa67915915c78f875556a68163f20b3f658977..546435a14f4b2aa6202c26f3b086971fa8314eab 100644
--- a/services/jira/jira-common.js
+++ b/services/jira/jira-common.js
@@ -1,9 +1,7 @@
-'use strict'
-
 const authConfig = {
   userKey: 'jira_user',
   passKey: 'jira_pass',
   serviceKey: 'jira',
 }
 
-module.exports = { authConfig }
+export { authConfig }
diff --git a/services/jira/jira-issue-redirect.service.js b/services/jira/jira-issue-redirect.service.js
index 1c98e875c303f429906d4c667f46a775c39597c5..8f7f2b9f587ff4eec755edb0bfe5524c82f61f97 100644
--- a/services/jira/jira-issue-redirect.service.js
+++ b/services/jira/jira-issue-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   redirector({
     category: 'issue-tracking',
     route: {
diff --git a/services/jira/jira-issue-redirect.tester.js b/services/jira/jira-issue-redirect.tester.js
index 412fcccd50ba9190266b494e91305f6b73dfd600..b414839c47ac3bbf54660fc26af1194dc6b4c2fc 100644
--- a/services/jira/jira-issue-redirect.tester.js
+++ b/services/jira/jira-issue-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'JiraIssueRedirect',
   title: 'JiraIssueRedirect',
   pathPrefix: '/jira/issue',
-}))
+})
 
 t.create('jira issue')
   .get('/https/issues.apache.org/jira/kafka-2896.svg')
diff --git a/services/jira/jira-issue.service.js b/services/jira/jira-issue.service.js
index 3d54657f5499dd42f468d9fc369cc7dfa2ba3a4d..35fafa60a3a9baca3373bbab8e85e8dbdb5f40ce 100644
--- a/services/jira/jira-issue.service.js
+++ b/services/jira/jira-issue.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
-const { BaseJsonService } = require('..')
-const { authConfig } = require('./jira-common')
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
+import { BaseJsonService } from '../index.js'
+import { authConfig } from './jira-common.js'
 
 const queryParamSchema = Joi.object({
   baseUrl: optionalUrl.required(),
@@ -20,7 +18,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class JiraIssue extends BaseJsonService {
+export default class JiraIssue extends BaseJsonService {
   static category = 'issue-tracking'
 
   static route = {
diff --git a/services/jira/jira-issue.spec.js b/services/jira/jira-issue.spec.js
index 3b7cdfb3335e4f9da8d3be96e14f5df3de654258..10ff23efd37625c5662b0bd15644edcc8d8145fb 100644
--- a/services/jira/jira-issue.spec.js
+++ b/services/jira/jira-issue.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const JiraIssue = require('./jira-issue.service')
-const { user, pass, host, config } = require('./jira-test-helpers')
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import JiraIssue from './jira-issue.service.js'
+import { user, pass, host, config } from './jira-test-helpers.js'
 
 describe('JiraIssue', function () {
   cleanUpNockAfterEach()
diff --git a/services/jira/jira-issue.tester.js b/services/jira/jira-issue.tester.js
index 649510f939d34b838e394c329ac518f8c00d4740..faab0a4ebbcfc2c4cb436cef2db1df02a60011c1 100644
--- a/services/jira/jira-issue.tester.js
+++ b/services/jira/jira-issue.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('unknown issue')
   .get('/notArealIssue-000.json?baseUrl=https://issues.apache.org/jira')
diff --git a/services/jira/jira-sprint-redirect.service.js b/services/jira/jira-sprint-redirect.service.js
index b3f460b0449962f0442ffde6cc8c0efbaa44c176..54dec2a42f5091d0ea94bd7250c739757d0714d7 100644
--- a/services/jira/jira-sprint-redirect.service.js
+++ b/services/jira/jira-sprint-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   redirector({
     category: 'issue-tracking',
     route: {
diff --git a/services/jira/jira-sprint-redirect.tester.js b/services/jira/jira-sprint-redirect.tester.js
index 7bcf30e33436f24a35262bd97326274f6e734c3b..86c417106a0e6d498156202bc677052e6ba05976 100644
--- a/services/jira/jira-sprint-redirect.tester.js
+++ b/services/jira/jira-sprint-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'JiraSprintRedirect',
   title: 'JiraSprintRedirect',
   pathPrefix: '/jira/sprint',
-}))
+})
 
 t.create('jira sprint')
   .get('/https/jira.spring.io/94.svg')
diff --git a/services/jira/jira-sprint.service.js b/services/jira/jira-sprint.service.js
index 4af49aa13035e70430d60271d046aaf3e6ef8ad3..875a85e92cff8180616788b2b80e584d53fc6973 100644
--- a/services/jira/jira-sprint.service.js
+++ b/services/jira/jira-sprint.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
-const { BaseJsonService } = require('..')
-const { authConfig } = require('./jira-common')
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
+import { BaseJsonService } from '../index.js'
+import { authConfig } from './jira-common.js'
 
 const queryParamSchema = Joi.object({
   baseUrl: optionalUrl.required(),
@@ -32,7 +30,7 @@ const documentation = `
 </p>
 `
 
-module.exports = class JiraSprint extends BaseJsonService {
+export default class JiraSprint extends BaseJsonService {
   static category = 'issue-tracking'
 
   static route = {
diff --git a/services/jira/jira-sprint.spec.js b/services/jira/jira-sprint.spec.js
index 0214f2da004bf79cadfd1192f4790ecf1e886777..8bcead5bb2e27ed09dd562a222288630d69c8fc9 100644
--- a/services/jira/jira-sprint.spec.js
+++ b/services/jira/jira-sprint.spec.js
@@ -1,17 +1,15 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const JiraSprint = require('./jira-sprint.service')
-const {
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import JiraSprint from './jira-sprint.service.js'
+import {
   user,
   pass,
   host,
   config,
   sprintId,
   sprintQueryString,
-} = require('./jira-test-helpers')
+} from './jira-test-helpers.js'
 
 describe('JiraSprint', function () {
   cleanUpNockAfterEach()
diff --git a/services/jira/jira-sprint.tester.js b/services/jira/jira-sprint.tester.js
index fe817f6344d3f747e04e30ff03557a042434ae5b..997b3aaf55c2f91d996b716391fb75321cc0fc6a 100644
--- a/services/jira/jira-sprint.tester.js
+++ b/services/jira/jira-sprint.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isIntegerPercentage } = require('../test-validators')
-const { sprintId, sprintQueryString } = require('./jira-test-helpers')
+import { createServiceTester } from '../tester.js'
+import { isIntegerPercentage } from '../test-validators.js'
+import { sprintId, sprintQueryString } from './jira-test-helpers.js'
+export const t = await createServiceTester()
 
 t.create('unknown sprint')
   .get('/abc.json?baseUrl=https://jira.spring.io')
diff --git a/services/jira/jira-test-helpers.js b/services/jira/jira-test-helpers.js
index 11c01cff674c9dddebaed52303c986f1d59a03bb..e188179146bc526bb8a87e4d6e10503f0fee55ad 100644
--- a/services/jira/jira-test-helpers.js
+++ b/services/jira/jira-test-helpers.js
@@ -1,5 +1,3 @@
-'use strict'
-
 const sprintId = 8
 const sprintQueryString = {
   jql: `sprint=${sprintId} AND type IN (Bug,Improvement,Story,"Technical task")`,
@@ -21,11 +19,4 @@ const config = {
   private: { jira_user: user, jira_pass: pass },
 }
 
-module.exports = {
-  sprintId,
-  sprintQueryString,
-  user,
-  pass,
-  host,
-  config,
-}
+export { sprintId, sprintQueryString, user, pass, host, config }
diff --git a/services/jitpack/jitpack-downloads.service.js b/services/jitpack/jitpack-downloads.service.js
index c3d25e1bcd8bcc15920c1bec6f4ee4a20ba4b5dd..b50ca6b519ad60547a29bcbb4297f881ca22f8b8 100644
--- a/services/jitpack/jitpack-downloads.service.js
+++ b/services/jitpack/jitpack-downloads.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   route: {
     base: 'jitpack',
     pattern: ':interval(dw|dm)/:various*',
diff --git a/services/jitpack/jitpack-downloads.tester.js b/services/jitpack/jitpack-downloads.tester.js
index 2aa58b9fb70e0c5c9d239505fe88de7787b99728..3e7fb42db05ed7bf90533ee1e1892c5574580991 100644
--- a/services/jitpack/jitpack-downloads.tester.js
+++ b/services/jitpack/jitpack-downloads.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'JitPackDownloads',
   title: 'JitPackDownloads',
   pathPrefix: '/jitpack',
-}))
+})
 
 t.create('no longer available (dw)')
   .get('/dw/github/jitpack/maven-simple.json')
diff --git a/services/jitpack/jitpack-version-redirector.service.js b/services/jitpack/jitpack-version-redirector.service.js
index 9fc943c3293fc5da0ebb97cf1a18836ee8b0d2ff..bda5c01485ae09eabdf8c8207433141d4615f85c 100644
--- a/services/jitpack/jitpack-version-redirector.service.js
+++ b/services/jitpack/jitpack-version-redirector.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   redirector({
     category: 'version',
     route: {
diff --git a/services/jitpack/jitpack-version-redirector.tester.js b/services/jitpack/jitpack-version-redirector.tester.js
index 9e19c99e117a25845ab737ea289d5cda86b35532..deb2b820cfe4bb1f0d43a15882e7accdb8184cb9 100644
--- a/services/jitpack/jitpack-version-redirector.tester.js
+++ b/services/jitpack/jitpack-version-redirector.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'JitpackVersionRedirect',
   title: 'JitpackVersionRedirect',
   pathPrefix: '/jitpack/v',
-}))
+})
 
 t.create('jitpack version redirect')
   .get('/jitpack/maven-simple.svg')
diff --git a/services/jitpack/jitpack-version.service.js b/services/jitpack/jitpack-version.service.js
index 3e5fdd2886fc58efe2e74e34bd590d2793189b41..e739e06ce8a4d802123a3cb664a73276f12ba5d4 100644
--- a/services/jitpack/jitpack-version.service.js
+++ b/services/jitpack/jitpack-version.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   version: Joi.string().required(),
   status: Joi.string().valid('ok').required(),
 }).required()
 
-module.exports = class JitPackVersion extends BaseJsonService {
+export default class JitPackVersion extends BaseJsonService {
   static category = 'version'
 
   static route = {
diff --git a/services/jitpack/jitpack-version.tester.js b/services/jitpack/jitpack-version.tester.js
index 695a32d76e52f89600abf4b3e8f36fd76704dc2b..5d7322f8e3dfc9d0c2940a7d120763916ce4ab66 100644
--- a/services/jitpack/jitpack-version.tester.js
+++ b/services/jitpack/jitpack-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // Github allows versions with chars, etc.
 const isAnyV = Joi.string().regex(/^v.+$/)
diff --git a/services/jsdelivr/jsdelivr-base.js b/services/jsdelivr/jsdelivr-base.js
index 65cf5327b1a2547cc81201a9c16726d286f0851a..be2b3495fe3687fa1964800e390fb906f2c150fe 100644
--- a/services/jsdelivr/jsdelivr-base.js
+++ b/services/jsdelivr/jsdelivr-base.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { downloadCount } = require('../color-formatters')
-const { metric } = require('../text-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { downloadCount } from '../color-formatters.js'
+import { metric } from '../text-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   total: Joi.number().required(),
@@ -31,4 +29,4 @@ class BaseJsDelivrService extends BaseJsonService {
   }
 }
 
-module.exports = { schema, periodMap, BaseJsDelivrService }
+export { schema, periodMap, BaseJsDelivrService }
diff --git a/services/jsdelivr/jsdelivr-hits-github.service.js b/services/jsdelivr/jsdelivr-hits-github.service.js
index 69b5a53329839982c4ad3a45c9e162a9a5bf034a..8d760b899266f3b4cf34b9d668f7dfe30619be9e 100644
--- a/services/jsdelivr/jsdelivr-hits-github.service.js
+++ b/services/jsdelivr/jsdelivr-hits-github.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { schema, periodMap, BaseJsDelivrService } from './jsdelivr-base.js'
 
-const { schema, periodMap, BaseJsDelivrService } = require('./jsdelivr-base')
-
-module.exports = class JsDelivrHitsGitHub extends BaseJsDelivrService {
+export default class JsDelivrHitsGitHub extends BaseJsDelivrService {
   static route = {
     base: 'jsdelivr/gh',
     pattern: ':period(hd|hw|hm|hy)/:user/:repo',
diff --git a/services/jsdelivr/jsdelivr-hits-github.tester.js b/services/jsdelivr/jsdelivr-hits-github.tester.js
index ea9a330a2084524b96b8afdf95cfa30fda4e6e3b..48231e1fd84363a19bb9ba958cb00330f5b93814 100644
--- a/services/jsdelivr/jsdelivr-hits-github.tester.js
+++ b/services/jsdelivr/jsdelivr-hits-github.tester.js
@@ -1,11 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const {
+import Joi from 'joi'
+import {
   isMetricOverTimePeriod,
   isZeroOverTimePeriod,
-} = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+} from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isDownloadsOverTimePeriod = Joi.alternatives().try(
   isMetricOverTimePeriod,
diff --git a/services/jsdelivr/jsdelivr-hits-npm.service.js b/services/jsdelivr/jsdelivr-hits-npm.service.js
index 86ecdb2450bc76b209cecd2fbf67502ba3eef646..79db7f7f557d7957f084d3b903fbb3aab4c0f6a9 100644
--- a/services/jsdelivr/jsdelivr-hits-npm.service.js
+++ b/services/jsdelivr/jsdelivr-hits-npm.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { schema, periodMap, BaseJsDelivrService } from './jsdelivr-base.js'
 
-const { schema, periodMap, BaseJsDelivrService } = require('./jsdelivr-base')
-
-module.exports = class JsDelivrHitsNPM extends BaseJsDelivrService {
+export default class JsDelivrHitsNPM extends BaseJsDelivrService {
   static route = {
     base: 'jsdelivr/npm',
     pattern: ':period(hd|hw|hm|hy)/:scope(@[^/]+)?/:packageName',
diff --git a/services/jsdelivr/jsdelivr-hits-npm.tester.js b/services/jsdelivr/jsdelivr-hits-npm.tester.js
index 18d53af0ef7d51b4047980d9c7c62f9b2a40a7fa..2c41ed9fe828bf96f9dc9b85f5746b446dd71fda 100644
--- a/services/jsdelivr/jsdelivr-hits-npm.tester.js
+++ b/services/jsdelivr/jsdelivr-hits-npm.tester.js
@@ -1,11 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const {
+import Joi from 'joi'
+import {
   isMetricOverTimePeriod,
   isZeroOverTimePeriod,
-} = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+} from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isDownloadsOverTimePeriod = Joi.alternatives().try(
   isMetricOverTimePeriod,
diff --git a/services/keybase/keybase-btc.service.js b/services/keybase/keybase-btc.service.js
index c463b208b0b6786eae4033dfd5efe79d042d0c86..1ef7d547ff6c39f943877b77a23ce565f5045568 100644
--- a/services/keybase/keybase-btc.service.js
+++ b/services/keybase/keybase-btc.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const KeybaseProfile = require('./keybase-profile')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import KeybaseProfile from './keybase-profile.js'
 
 const bitcoinAddressSchema = Joi.object({
   status: Joi.object({
@@ -28,7 +26,7 @@ const bitcoinAddressSchema = Joi.object({
     .max(1),
 }).required()
 
-module.exports = class KeybaseBTC extends KeybaseProfile {
+export default class KeybaseBTC extends KeybaseProfile {
   static route = {
     base: 'keybase/btc',
     pattern: ':username',
diff --git a/services/keybase/keybase-btc.tester.js b/services/keybase/keybase-btc.tester.js
index 2728d6625e71dc68bb7e915d0c3178bc7d5d81be..01e4531ad8d6892d564fcbd0d23ba1c3704e55cd 100644
--- a/services/keybase/keybase-btc.tester.js
+++ b/services/keybase/keybase-btc.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('existing bitcoin address')
   .get('/skyplabs.json')
diff --git a/services/keybase/keybase-pgp.service.js b/services/keybase/keybase-pgp.service.js
index 0f73aa229bee28b566eaa4fcd129582e0a88cb7f..117a6f2582f6646deac4725dcd52334b7eb6fd7a 100644
--- a/services/keybase/keybase-pgp.service.js
+++ b/services/keybase/keybase-pgp.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const KeybaseProfile = require('./keybase-profile')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import KeybaseProfile from './keybase-profile.js'
 
 const keyFingerprintSchema = Joi.object({
   status: Joi.object({
@@ -24,7 +22,7 @@ const keyFingerprintSchema = Joi.object({
     .max(1),
 }).required()
 
-module.exports = class KeybasePGP extends KeybaseProfile {
+export default class KeybasePGP extends KeybaseProfile {
   static route = {
     base: 'keybase/pgp',
     pattern: ':username',
diff --git a/services/keybase/keybase-pgp.tester.js b/services/keybase/keybase-pgp.tester.js
index db05abe97be41f3fe61e41bf2415e95af0438998..4a964597d2fa2762739bd3554ce8a9ee015ba730 100644
--- a/services/keybase/keybase-pgp.tester.js
+++ b/services/keybase/keybase-pgp.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('existing key fingerprint')
   .get('/skyplabs.json')
diff --git a/services/keybase/keybase-profile.js b/services/keybase/keybase-profile.js
index f663b2bbba2b4366559dc8555ec47df4041dde2d..1949c524578afe620f4b0361a193b350365d9239 100644
--- a/services/keybase/keybase-profile.js
+++ b/services/keybase/keybase-profile.js
@@ -1,9 +1,6 @@
-'use strict'
+import { BaseJsonService, NotFound } from '../index.js'
 
-const { BaseJsonService } = require('..')
-const { NotFound } = require('..')
-
-module.exports = class KeybaseProfile extends BaseJsonService {
+export default class KeybaseProfile extends BaseJsonService {
   static get apiVersion() {
     throw new Error(`apiVersion() is not implemented for ${this.name}`)
   }
diff --git a/services/keybase/keybase-xlm.service.js b/services/keybase/keybase-xlm.service.js
index e5b0f2ee9be354113c36586391a857338cea33e5..652f0a0b3af9aea0418e74a8ca827739e7e9e647 100644
--- a/services/keybase/keybase-xlm.service.js
+++ b/services/keybase/keybase-xlm.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const KeybaseProfile = require('./keybase-profile')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import KeybaseProfile from './keybase-profile.js'
 
 const stellarAddressSchema = Joi.object({
   status: Joi.object({
@@ -26,7 +24,7 @@ const stellarAddressSchema = Joi.object({
     .max(1),
 }).required()
 
-module.exports = class KeybaseXLM extends KeybaseProfile {
+export default class KeybaseXLM extends KeybaseProfile {
   static route = {
     base: 'keybase/xlm',
     pattern: ':username',
diff --git a/services/keybase/keybase-xlm.tester.js b/services/keybase/keybase-xlm.tester.js
index 79a277862b49eab97e7332e91f734f5514c414dd..ce8b78637cd65d44aa5417cdaac25e4ec8f321cf 100644
--- a/services/keybase/keybase-xlm.tester.js
+++ b/services/keybase/keybase-xlm.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('existing stellar address')
   .get('/skyplabs.json')
diff --git a/services/keybase/keybase-zec.service.js b/services/keybase/keybase-zec.service.js
index b22b6ffab7580e24c4b482f48668259575f399ef..0e367a9dfcae2baa59ac0cbd710bd8204ee62ed3 100644
--- a/services/keybase/keybase-zec.service.js
+++ b/services/keybase/keybase-zec.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const KeybaseProfile = require('./keybase-profile')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import KeybaseProfile from './keybase-profile.js'
 
 const zcachAddressSchema = Joi.object({
   status: Joi.object({
@@ -28,7 +26,7 @@ const zcachAddressSchema = Joi.object({
     .max(1),
 }).required()
 
-module.exports = class KeybaseZEC extends KeybaseProfile {
+export default class KeybaseZEC extends KeybaseProfile {
   static route = {
     base: 'keybase/zec',
     pattern: ':username',
diff --git a/services/keybase/keybase-zec.tester.js b/services/keybase/keybase-zec.tester.js
index 5a2f065b366a34ba1efc717b4b948acf32eb8e80..f38a394116a0a9c636928450fe424f51c3860449 100644
--- a/services/keybase/keybase-zec.tester.js
+++ b/services/keybase/keybase-zec.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('existing zcash address')
   .get('/skyplabs.json')
diff --git a/services/leanpub/leanpub-book-summary.service.js b/services/leanpub/leanpub-book-summary.service.js
index 64ccbd37a061483b8a29de253e8ca9c17f7c218b..8328862ad3265475a66530abf21b31c9969ed6ec 100644
--- a/services/leanpub/leanpub-book-summary.service.js
+++ b/services/leanpub/leanpub-book-summary.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   route: {
     base: 'leanpub/book',
     pattern: ':various+',
diff --git a/services/leanpub/leanpub-book-summary.tester.js b/services/leanpub/leanpub-book-summary.tester.js
index 9ed01c2a0690c3dada92dae7664d4288a5ec7a44..feef7ffd306d9f790dcda77f7b4ad4239844b027 100644
--- a/services/leanpub/leanpub-book-summary.tester.js
+++ b/services/leanpub/leanpub-book-summary.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'LeanPub',
   title: 'LeanPub',
   pathPrefix: '/leanpub/book',
-}))
+})
 
 t.create('no longer available (previously book pages)')
   .get('/pages/juice-shop.json')
diff --git a/services/lgtm/lgtm-alerts.service.js b/services/lgtm/lgtm-alerts.service.js
index 6716d1ab848f5fe10194c0eb43d948027774e95f..814dce1d6352e104fe148c9a7ad287d8d285d40f 100644
--- a/services/lgtm/lgtm-alerts.service.js
+++ b/services/lgtm/lgtm-alerts.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import LgtmBaseService from './lgtm-base.js'
 
-const { metric } = require('../text-formatters')
-const LgtmBaseService = require('./lgtm-base')
-
-module.exports = class LgtmAlerts extends LgtmBaseService {
+export default class LgtmAlerts extends LgtmBaseService {
   static route = {
     base: 'lgtm/alerts',
     pattern: this.pattern,
diff --git a/services/lgtm/lgtm-alerts.tester.js b/services/lgtm/lgtm-alerts.tester.js
index b8e86a13efb278c86a403d7d23c53f69f3261d36..ed747c5a3d419094f95cc6431b167e4c6296fc91 100644
--- a/services/lgtm/lgtm-alerts.tester.js
+++ b/services/lgtm/lgtm-alerts.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const { data } = require('./lgtm-test-helpers')
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import { data } from './lgtm-test-helpers.js'
+export const t = await createServiceTester()
 
 t.create('alerts: total alerts for a project')
   .get('/github/apache/cloudstack.json')
diff --git a/services/lgtm/lgtm-base.js b/services/lgtm/lgtm-base.js
index 969088265180bdf0e11dac89ac95c117769e7366..ed1e12091092d44b3f1b4d0fa2678b9371cb8801 100644
--- a/services/lgtm/lgtm-base.js
+++ b/services/lgtm/lgtm-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   alerts: Joi.number().required(),
@@ -22,7 +20,7 @@ const hostMappings = {
   gitlab: 'gl',
 }
 
-module.exports = class LgtmBaseService extends BaseJsonService {
+export default class LgtmBaseService extends BaseJsonService {
   static category = 'analysis'
 
   static defaultBadgeData = { label: 'lgtm' }
diff --git a/services/lgtm/lgtm-grade.service.js b/services/lgtm/lgtm-grade.service.js
index 81a861924e607a91eb821841bd5a7ffd4d76473a..3f196949b428f6f73c7ea659892d583c67bf202d 100644
--- a/services/lgtm/lgtm-grade.service.js
+++ b/services/lgtm/lgtm-grade.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import LgtmBaseService from './lgtm-base.js'
 
-const LgtmBaseService = require('./lgtm-base')
-
-module.exports = class LgtmGrade extends LgtmBaseService {
+export default class LgtmGrade extends LgtmBaseService {
   static route = {
     base: 'lgtm/grade',
     pattern: `:language/${this.pattern}`,
diff --git a/services/lgtm/lgtm-grade.tester.js b/services/lgtm/lgtm-grade.tester.js
index a9d9971f509ece97a3ecf4611db185cf63950db9..8e8c3ba3f8b5907def49312422f86b48474a94d7 100644
--- a/services/lgtm/lgtm-grade.tester.js
+++ b/services/lgtm/lgtm-grade.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const { data } = require('./lgtm-test-helpers')
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import { data } from './lgtm-test-helpers.js'
+export const t = await createServiceTester()
 
 t.create('grade: missing project')
   .get('/java/github/some-org/this-project-doesnt-exist.json')
diff --git a/services/lgtm/lgtm-redirector.service.js b/services/lgtm/lgtm-redirector.service.js
index b88b3778ee323ec151ecc897632383102916c2cb..bc6bd04806fce13b1d859e27d77e3f7cb2b120a6 100644
--- a/services/lgtm/lgtm-redirector.service.js
+++ b/services/lgtm/lgtm-redirector.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const { redirector } = require('..')
+import { redirector } from '../index.js'
 
 const commonAttrs = {
   category: 'analysis',
   dateAdded: new Date('2019-04-30'),
 }
 
-module.exports = [
+export default [
   redirector({
     route: {
       base: 'lgtm/alerts/g',
diff --git a/services/lgtm/lgtm-redirector.tester.js b/services/lgtm/lgtm-redirector.tester.js
index 449955ad9e391414ad1e4ba9c6736f7f7dca3552..d6d56631813b03e63e79885018b89fccf48d0569 100644
--- a/services/lgtm/lgtm-redirector.tester.js
+++ b/services/lgtm/lgtm-redirector.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'LgtmRedirect',
   title: 'LgtmRedirect',
   pathPrefix: '/lgtm',
-}))
+})
 
 t.create('alerts')
   .get('/alerts/g/badges/shields.svg')
diff --git a/services/lgtm/lgtm-test-helpers.js b/services/lgtm/lgtm-test-helpers.js
index 71154a409a95706ba95dd264477f84aea604784b..e169d4c6ddd34e003a9c93cfefc968b8c9493a70 100644
--- a/services/lgtm/lgtm-test-helpers.js
+++ b/services/lgtm/lgtm-test-helpers.js
@@ -1,5 +1,3 @@
-'use strict'
-
 const data = {
   alerts: 0,
   languages: [
@@ -13,6 +11,4 @@ const data = {
   ],
 }
 
-module.exports = {
-  data,
-}
+export { data }
diff --git a/services/liberapay/liberapay-base.js b/services/liberapay/liberapay-base.js
index 8e47ce60e064b6dae9fc2485c17a93cd09d059ce..a044844150ccd4df1ecb1c16039ba655b0889c2f 100644
--- a/services/liberapay/liberapay-base.js
+++ b/services/liberapay/liberapay-base.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { colorScale } = require('../color-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { colorScale } from '../color-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   npatrons: nonNegativeInteger,
@@ -64,8 +62,4 @@ class LiberapayBase extends BaseJsonService {
   }
 }
 
-module.exports = {
-  renderCurrencyBadge,
-  LiberapayBase,
-  isCurrencyOverTime,
-}
+export { renderCurrencyBadge, LiberapayBase, isCurrencyOverTime }
diff --git a/services/liberapay/liberapay-gives.service.js b/services/liberapay/liberapay-gives.service.js
index e294bd472a2eb0807b5ba070ab00a8ffbfedc2f6..127a3a34e8509a04a8801c5f1330c612e203ff43 100644
--- a/services/liberapay/liberapay-gives.service.js
+++ b/services/liberapay/liberapay-gives.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { InvalidResponse } from '../index.js'
+import { renderCurrencyBadge, LiberapayBase } from './liberapay-base.js'
 
-const { InvalidResponse } = require('..')
-const { renderCurrencyBadge, LiberapayBase } = require('./liberapay-base')
-
-module.exports = class LiberapayGives extends LiberapayBase {
+export default class LiberapayGives extends LiberapayBase {
   static route = this.buildRoute('gives')
 
   static examples = [
diff --git a/services/liberapay/liberapay-gives.tester.js b/services/liberapay/liberapay-gives.tester.js
index b91f47a0455717e03506f04f619839b28adf3ec1..daf77a689f0c34c00d04a7e94a8a8c65c92a46b2 100644
--- a/services/liberapay/liberapay-gives.tester.js
+++ b/services/liberapay/liberapay-gives.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isCurrencyOverTime } = require('./liberapay-base')
+import { createServiceTester } from '../tester.js'
+import { isCurrencyOverTime } from './liberapay-base.js'
+export const t = await createServiceTester()
 
 t.create('Giving (valid)').get('/Changaco.json').expectBadge({
   label: 'gives',
diff --git a/services/liberapay/liberapay-goal.service.js b/services/liberapay/liberapay-goal.service.js
index 3d96cea41ddf2d162c6abed3a1abb6b661884679..4c7ae71e42767b8686720485c265c78d7172d2c3 100644
--- a/services/liberapay/liberapay-goal.service.js
+++ b/services/liberapay/liberapay-goal.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { colorScale } from '../color-formatters.js'
+import { InvalidResponse } from '../index.js'
+import { LiberapayBase } from './liberapay-base.js'
 
-const { colorScale } = require('../color-formatters')
-const { InvalidResponse } = require('..')
-const { LiberapayBase } = require('./liberapay-base')
-
-module.exports = class LiberapayGoal extends LiberapayBase {
+export default class LiberapayGoal extends LiberapayBase {
   static route = this.buildRoute('goal')
 
   static examples = [
diff --git a/services/liberapay/liberapay-goal.spec.js b/services/liberapay/liberapay-goal.spec.js
index 87b8eb4755777e69061fa09f1c37439b58deb9b8..ace4d40c45576a73ae084417b1e373e7ef3adf37 100644
--- a/services/liberapay/liberapay-goal.spec.js
+++ b/services/liberapay/liberapay-goal.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const { test, given } = require('sazerac')
-const { InvalidResponse } = require('..')
-const LiberapayGoal = require('./liberapay-goal.service')
+import { expect } from 'chai'
+import { test, given } from 'sazerac'
+import { InvalidResponse } from '../index.js'
+import LiberapayGoal from './liberapay-goal.service.js'
 
 describe('LiberapayGoal', function () {
   test(LiberapayGoal.prototype.transform, () => {
diff --git a/services/liberapay/liberapay-goal.tester.js b/services/liberapay/liberapay-goal.tester.js
index a340d4d5e5b48d6e63b84c091ac5d5c2b909ef47..518a84b0041077cf76a03d3316735e029305d990 100644
--- a/services/liberapay/liberapay-goal.tester.js
+++ b/services/liberapay/liberapay-goal.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Goal Progress (valid)').get('/Liberapay.json').expectBadge({
   label: 'goal progress',
diff --git a/services/liberapay/liberapay-patrons.service.js b/services/liberapay/liberapay-patrons.service.js
index 0bcb1ac74a4fca7e9fc191ae122d60679a8539ea..dbcf4d8639637d7b77a782cd2327af8092436406 100644
--- a/services/liberapay/liberapay-patrons.service.js
+++ b/services/liberapay/liberapay-patrons.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { colorScale } from '../color-formatters.js'
+import { LiberapayBase } from './liberapay-base.js'
 
-const { metric } = require('../text-formatters')
-const { colorScale } = require('../color-formatters')
-const { LiberapayBase } = require('./liberapay-base')
-
-module.exports = class LiberapayPatrons extends LiberapayBase {
+export default class LiberapayPatrons extends LiberapayBase {
   static route = this.buildRoute('patrons')
 
   static examples = [
diff --git a/services/liberapay/liberapay-patrons.tester.js b/services/liberapay/liberapay-patrons.tester.js
index 5eee881d67bb27fae2294fce1463ca255ed26159..8c7f780c41cf536f36e70063190ef8baef09dc70 100644
--- a/services/liberapay/liberapay-patrons.tester.js
+++ b/services/liberapay/liberapay-patrons.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Patrons (valid)').get('/Liberapay.json').expectBadge({
   label: 'patrons',
diff --git a/services/liberapay/liberapay-receives.service.js b/services/liberapay/liberapay-receives.service.js
index b3cf59d91a414d4c1f7ad3cd49b8ccc5d86ba5c3..7d828f90bd684dfd6ab272a5c9be6acede8ed0ce 100644
--- a/services/liberapay/liberapay-receives.service.js
+++ b/services/liberapay/liberapay-receives.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { InvalidResponse } from '../index.js'
+import { renderCurrencyBadge, LiberapayBase } from './liberapay-base.js'
 
-const { InvalidResponse } = require('..')
-const { renderCurrencyBadge, LiberapayBase } = require('./liberapay-base')
-
-module.exports = class LiberapayReceives extends LiberapayBase {
+export default class LiberapayReceives extends LiberapayBase {
   static route = this.buildRoute('receives')
 
   static examples = [
diff --git a/services/liberapay/liberapay-receives.tester.js b/services/liberapay/liberapay-receives.tester.js
index d2b7a71e4f51d2abac999eca5e5caad393367e50..17988abc7c7a63a71908d751665934b1695adda8 100644
--- a/services/liberapay/liberapay-receives.tester.js
+++ b/services/liberapay/liberapay-receives.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isCurrencyOverTime } = require('./liberapay-base')
+import { createServiceTester } from '../tester.js'
+import { isCurrencyOverTime } from './liberapay-base.js'
+export const t = await createServiceTester()
 
 t.create('Receiving (valid)').get('/Changaco.json').expectBadge({
   label: 'receives',
diff --git a/services/librariesio/librariesio-common.js b/services/librariesio/librariesio-common.js
index 7421be27f05368081f342b5864c6011f8080153b..974060a6888098fd61289b9a2004a9f4e64a9cf1 100644
--- a/services/librariesio/librariesio-common.js
+++ b/services/librariesio/librariesio-common.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger, anyInteger } = require('../validators')
+import Joi from 'joi'
+import { nonNegativeInteger, anyInteger } from '../validators.js'
 
 // API doc: https://libraries.io/api#project
 const projectSchema = Joi.object({
@@ -21,6 +19,4 @@ async function fetchProject(serviceInstance, { platform, scope, packageName }) {
   })
 }
 
-module.exports = {
-  fetchProject,
-}
+export { fetchProject }
diff --git a/services/librariesio/librariesio-dependencies-helpers.js b/services/librariesio/librariesio-dependencies-helpers.js
index f9bf0b1908ca53b164413d28a016a6a0eca3eb6d..7aaaf71536a374d2d413518ad4888c3d44ddceb0 100644
--- a/services/librariesio/librariesio-dependencies-helpers.js
+++ b/services/librariesio/librariesio-dependencies-helpers.js
@@ -1,5 +1,3 @@
-'use strict'
-
 function transform({ dependencies }) {
   return {
     deprecatedCount: dependencies.filter(dep => dep.deprecated).length,
@@ -28,4 +26,4 @@ function renderDependenciesBadge({ deprecatedCount, outdatedCount }) {
   }
 }
 
-module.exports = { transform, renderDependenciesBadge }
+export { transform, renderDependenciesBadge }
diff --git a/services/librariesio/librariesio-dependencies-helpers.spec.js b/services/librariesio/librariesio-dependencies-helpers.spec.js
index e073352b1cbbc3320732029db570d14af1c0f82b..bdc1c3d17a15ed352c9e88bcc6a2c44c3a3c1663 100644
--- a/services/librariesio/librariesio-dependencies-helpers.spec.js
+++ b/services/librariesio/librariesio-dependencies-helpers.spec.js
@@ -1,9 +1,5 @@
-'use strict'
-
-const { test, given, forCases } = require('sazerac')
-const {
-  renderDependenciesBadge,
-} = require('./librariesio-dependencies-helpers')
+import { test, given, forCases } from 'sazerac'
+import { renderDependenciesBadge } from './librariesio-dependencies-helpers.js'
 
 describe('Libraries.io dependency helpers', function () {
   test(renderDependenciesBadge, () => {
diff --git a/services/librariesio/librariesio-dependencies.service.js b/services/librariesio/librariesio-dependencies.service.js
index 2b30e4453c05b8fd38259fc6583b0046f3d25f51..05df0e6ae64204d94d28b3b7f0423cd91a483ca4 100644
--- a/services/librariesio/librariesio-dependencies.service.js
+++ b/services/librariesio/librariesio-dependencies.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
-const {
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
+import {
   transform,
   renderDependenciesBadge,
-} = require('./librariesio-dependencies-helpers')
+} from './librariesio-dependencies-helpers.js'
 
 const schema = Joi.object({
   dependencies: Joi.array()
@@ -134,4 +132,4 @@ class LibrariesIoRepoDependencies extends BaseJsonService {
   }
 }
 
-module.exports = [LibrariesIoProjectDependencies, LibrariesIoRepoDependencies]
+export default [LibrariesIoProjectDependencies, LibrariesIoRepoDependencies]
diff --git a/services/librariesio/librariesio-dependencies.tester.js b/services/librariesio/librariesio-dependencies.tester.js
index 45bcabddbe6d72a56bc22ca086ba74116bdd0a46..6aeb2feda475a59021f6cddea214b493cfaccb41 100644
--- a/services/librariesio/librariesio-dependencies.tester.js
+++ b/services/librariesio/librariesio-dependencies.tester.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { ServiceTester } = require('../tester')
-const { isDependencyState } = require('../test-validators')
-const t = (module.exports = new ServiceTester({
+import { ServiceTester } from '../tester.js'
+import { isDependencyState } from '../test-validators.js'
+export const t = new ServiceTester({
   id: 'LibrariesIoDependencies',
   title: 'LibrariesIoDependencies',
   pathPrefix: '/librariesio',
-}))
+})
 
 t.create('dependencies for package (project name contains dot)')
   .timeout(10000)
diff --git a/services/librariesio/librariesio-dependent-repos.service.js b/services/librariesio/librariesio-dependent-repos.service.js
index 8d19449d58540b0f3ecfa02a6626e9804d3f20d5..0f8217c11bc73d2385fbd7ef5456cec460878cb6 100644
--- a/services/librariesio/librariesio-dependent-repos.service.js
+++ b/services/librariesio/librariesio-dependent-repos.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { metric } = require('../text-formatters')
-const { BaseJsonService } = require('..')
-const { fetchProject } = require('./librariesio-common')
+import { metric } from '../text-formatters.js'
+import { BaseJsonService } from '../index.js'
+import { fetchProject } from './librariesio-common.js'
 
 // https://libraries.io/api#project-dependent-repositories
-module.exports = class LibrariesIoDependentRepos extends BaseJsonService {
+export default class LibrariesIoDependentRepos extends BaseJsonService {
   static category = 'other'
 
   static route = {
diff --git a/services/librariesio/librariesio-dependent-repos.tester.js b/services/librariesio/librariesio-dependent-repos.tester.js
index f15fe079cda71a65c26a7614ece9a7c5408be4c8..2c7df20c70801173261179517755efdb4c1dc57c 100644
--- a/services/librariesio/librariesio-dependent-repos.tester.js
+++ b/services/librariesio/librariesio-dependent-repos.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('dependent repo count')
   .timeout(10000)
diff --git a/services/librariesio/librariesio-dependents.service.js b/services/librariesio/librariesio-dependents.service.js
index 9f849206e0ae04f209aeefe0abd82899294ea35c..ceaf4f5b2781790211caccaab3ca0cab85732bb2 100644
--- a/services/librariesio/librariesio-dependents.service.js
+++ b/services/librariesio/librariesio-dependents.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { metric } = require('../text-formatters')
-const { BaseJsonService } = require('..')
-const { fetchProject } = require('./librariesio-common')
+import { metric } from '../text-formatters.js'
+import { BaseJsonService } from '../index.js'
+import { fetchProject } from './librariesio-common.js'
 
 // https://libraries.io/api#project-dependents
-module.exports = class LibrariesIoDependents extends BaseJsonService {
+export default class LibrariesIoDependents extends BaseJsonService {
   static category = 'other'
 
   static route = {
diff --git a/services/librariesio/librariesio-dependents.tester.js b/services/librariesio/librariesio-dependents.tester.js
index a0b6a24d7ba28df0e84809fddd6375a40f7b24cf..8ca0b4393bd3191c40c3da0459f882f388b6b980 100644
--- a/services/librariesio/librariesio-dependents.tester.js
+++ b/services/librariesio/librariesio-dependents.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('dependent count').timeout(10000).get('/npm/got.json').expectBadge({
   label: 'dependents',
diff --git a/services/librariesio/librariesio-sourcerank.service.js b/services/librariesio/librariesio-sourcerank.service.js
index 98881416b919fe8fd5d076c942fec1f6b9c3576e..351a668eeff7fd0b363e06b8a3ac6f6bf254a07c 100644
--- a/services/librariesio/librariesio-sourcerank.service.js
+++ b/services/librariesio/librariesio-sourcerank.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { colorScale } = require('../color-formatters')
-const { BaseJsonService } = require('..')
-const { fetchProject } = require('./librariesio-common')
+import { colorScale } from '../color-formatters.js'
+import { BaseJsonService } from '../index.js'
+import { fetchProject } from './librariesio-common.js'
 
 const sourceRankColor = colorScale([10, 15, 20, 25, 30])
 
-module.exports = class LibrariesIoSourcerank extends BaseJsonService {
+export default class LibrariesIoSourcerank extends BaseJsonService {
   static category = 'rating'
 
   static route = {
diff --git a/services/librariesio/librariesio-sourcerank.tester.js b/services/librariesio/librariesio-sourcerank.tester.js
index c76d302dc520c443cc576e696f5c7e2f79f49a0f..7135302de37c1d385d25b3790915b3a216b5ab31 100644
--- a/services/librariesio/librariesio-sourcerank.tester.js
+++ b/services/librariesio/librariesio-sourcerank.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { anyInteger } = require('../validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { anyInteger } from '../validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('sourcerank').timeout(10000).get('/npm/got.json').expectBadge({
   label: 'sourcerank',
diff --git a/services/libscore/libscore.service.js b/services/libscore/libscore.service.js
index 6dd0a755a9aaee53ad792420b2eb888ce5c818d7..234d53e38f8db5db554755da1ac81304e03aec4a 100644
--- a/services/libscore/libscore.service.js
+++ b/services/libscore/libscore.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'rating',
   route: {
     base: 'libscore/s',
diff --git a/services/libscore/libscore.tester.js b/services/libscore/libscore.tester.js
index 223e8b3d58962844e15770563c2dbdb7c1919b86..bf5ec44d0ce070833f32527d40d0b80897a81a97 100644
--- a/services/libscore/libscore.tester.js
+++ b/services/libscore/libscore.tester.js
@@ -1,9 +1,6 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = new ServiceTester({ id: 'libscore', title: 'libscore' })
-module.exports = t
+export const t = new ServiceTester({ id: 'libscore', title: 'libscore' })
 
 t.create('no longer available (previously usage statistics)')
   .get('/s/jQuery.json')
diff --git a/services/licenses.js b/services/licenses.js
index b6efcb8ae0d1590815d1520f886effa78d2f42ae..9def600c8f59158193ace58f4e1537647ba062b2 100644
--- a/services/licenses.js
+++ b/services/licenses.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const toArray = require('../core/base-service/to-array')
+import toArray from '../core/base-service/to-array.js'
 
 const licenseTypes = {
   // permissive licenses - not public domain and not copyleft
@@ -130,4 +128,4 @@ function renderLicenseBadge({ license, licenses }) {
   }
 }
 
-module.exports = { licenseToColor, renderLicenseBadge }
+export { licenseToColor, renderLicenseBadge }
diff --git a/services/licenses.spec.js b/services/licenses.spec.js
index 58e95285b6496101cf4dd19f8516e7b34a46aadf..20554dadc73054b29cc22ebc1176fc3e20113fda 100644
--- a/services/licenses.spec.js
+++ b/services/licenses.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given, forCases } = require('sazerac')
-const { licenseToColor, renderLicenseBadge } = require('./licenses')
+import { test, given, forCases } from 'sazerac'
+import { licenseToColor, renderLicenseBadge } from './licenses.js'
 
 describe('license helpers', function () {
   test(licenseToColor, () => {
diff --git a/services/localizely/localizely.service.js b/services/localizely/localizely.service.js
index d29d50d658125226533f69d73b2cc6220e76223e..1e8ac606083294ec2e7b0e91ad104eb40d5f445b 100644
--- a/services/localizely/localizely.service.js
+++ b/services/localizely/localizely.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService, InvalidResponse } = require('..')
-const { coveragePercentage } = require('../color-formatters')
+import Joi from 'joi'
+import { BaseJsonService, InvalidResponse } from '../index.js'
+import { coveragePercentage } from '../color-formatters.js'
 
 const keywords = [
   'l10n',
@@ -51,7 +49,7 @@ const queryParamSchema = Joi.object({
   languageCode: Joi.string().regex(/^[a-z]{2}(-[A-Z][a-z]{3})?(-[A-Z]{2})?$/),
 }).required()
 
-module.exports = class Localizely extends BaseJsonService {
+export default class Localizely extends BaseJsonService {
   static category = 'other'
 
   static route = {
diff --git a/services/localizely/localizely.tester.js b/services/localizely/localizely.tester.js
index 814573a499776d5e4a5a80ce3f7962eaa2f4632f..9f996e287de166ea92bf784c0b85df39d48d215e 100644
--- a/services/localizely/localizely.tester.js
+++ b/services/localizely/localizely.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isIntegerPercentage } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isIntegerPercentage } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('Overall progress')
   .get(
diff --git a/services/luarocks/luarocks-version-helpers.js b/services/luarocks/luarocks-version-helpers.js
index ee1526adc8fd86bdabc131d128f9ab2cfd851914..3523f38a5b5978bf2d9c7142ee65c09d2d6233c2 100644
--- a/services/luarocks/luarocks-version-helpers.js
+++ b/services/luarocks/luarocks-version-helpers.js
@@ -24,9 +24,7 @@
  * https://github.com/luarocks/luarocks/blob/405ee29ba8444d97646f62e72effeaff2bfe3f79/src/luarocks/search.lua#L182
  * https://github.com/luarocks/luarocks/blob/405ee29ba8444d97646f62e72effeaff2bfe3f79/src/luarocks/core/vers.lua#L83
  */
-'use strict'
-
-const { omitv } = require('../text-formatters')
+import { omitv } from '../text-formatters.js'
 
 // Compare two arrays containing split and transformed to
 // positive/negative numbers parts of version strings,
@@ -86,8 +84,4 @@ function latestVersion(versions) {
     .pop()
 }
 
-module.exports = {
-  parseVersion,
-  compareVersionLists,
-  latestVersion,
-}
+export { parseVersion, compareVersionLists, latestVersion }
diff --git a/services/luarocks/luarocks-version-helpers.spec.js b/services/luarocks/luarocks-version-helpers.spec.js
index 22064de414d52119c851a42bb366070712c85a15..fce50d9acf0ffc6a3a71ae1c3e95c9aa90dc3e63 100644
--- a/services/luarocks/luarocks-version-helpers.spec.js
+++ b/services/luarocks/luarocks-version-helpers.spec.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { test, given, forCases } = require('sazerac')
-const {
+import { test, given, forCases } from 'sazerac'
+import {
   parseVersion,
   compareVersionLists,
   latestVersion,
-} = require('./luarocks-version-helpers')
+} from './luarocks-version-helpers.js'
 
 describe('LuaRocks-specific helpers', function () {
   test(compareVersionLists, () => {
diff --git a/services/luarocks/luarocks.service.js b/services/luarocks/luarocks.service.js
index 4ce526f27f2e42169d8c02f66ad29c74c3432476..2ffb68616afad60478c057f290b4ac58fba67ba3 100644
--- a/services/luarocks/luarocks.service.js
+++ b/services/luarocks/luarocks.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { addv } = require('../text-formatters')
-const { BaseJsonService, NotFound } = require('..')
-const { latestVersion } = require('./luarocks-version-helpers')
+import Joi from 'joi'
+import { addv } from '../text-formatters.js'
+import { BaseJsonService, NotFound } from '../index.js'
+import { latestVersion } from './luarocks-version-helpers.js'
 
 const schema = Joi.object({
   repository: Joi.object()
@@ -14,7 +12,7 @@ const schema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class Luarocks extends BaseJsonService {
+export default class Luarocks extends BaseJsonService {
   static category = 'version'
 
   static route = {
diff --git a/services/luarocks/luarocks.spec.js b/services/luarocks/luarocks.spec.js
index ad6479ef7d50110ce4e944149e452227208a4ee6..811ab73ccf72a53ad5034e0d208b29c8c567017d 100644
--- a/services/luarocks/luarocks.spec.js
+++ b/services/luarocks/luarocks.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const Luarocks = require('./luarocks.service')
+import { test, given } from 'sazerac'
+import Luarocks from './luarocks.service.js'
 
 test(Luarocks.render, () => {
   given({ version: 'dev-1' }).expect({ message: 'dev-1', color: 'yellow' })
diff --git a/services/luarocks/luarocks.tester.js b/services/luarocks/luarocks.tester.js
index 0e60caf89637732881af2ac25c196426f6542f45..e82ddcf8eed4f0c4b5a76db5fb855d8c51ba99cd 100644
--- a/services/luarocks/luarocks.tester.js
+++ b/services/luarocks/luarocks.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isLuaVersion = Joi.string()
   .regex(/^v\d+\.\d+\.\d+-\d+$/)
diff --git a/services/magnumci/magnumci.service.js b/services/magnumci/magnumci.service.js
index 5a01a0304b38a10aa6265a1ee1d8374a57e7979d..8830135f3a5f703b812766d7fad39b0fe2b5e08e 100644
--- a/services/magnumci/magnumci.service.js
+++ b/services/magnumci/magnumci.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'build',
   route: {
     base: 'magnumci/ci',
diff --git a/services/magnumci/magnumci.tester.js b/services/magnumci/magnumci.tester.js
index d88d56f757622a08a9e714d0e4682d67c9a4f082..c42c7f3297d98a1574bf645087e35795b50bf226 100644
--- a/services/magnumci/magnumci.tester.js
+++ b/services/magnumci/magnumci.tester.js
@@ -1,9 +1,6 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = new ServiceTester({ id: 'magnumci', title: 'Magnum CI' })
-module.exports = t
+export const t = new ServiceTester({ id: 'magnumci', title: 'Magnum CI' })
 
 t.create('no longer available')
   .get('/ci/96ffb83fa700f069024921b0702e76ff.json')
diff --git a/services/maintenance/maintenance.service.js b/services/maintenance/maintenance.service.js
index e05da9f6bb7b4b6fd459eafc2c58fa5c15bad0cf..c38bc236318ff65c124b3f5ca54654f0b7a09c72 100644
--- a/services/maintenance/maintenance.service.js
+++ b/services/maintenance/maintenance.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseService } from '../index.js'
 
-const { BaseService } = require('..')
-
-module.exports = class Maintenance extends BaseService {
+export default class Maintenance extends BaseService {
   static category = 'other'
 
   static route = {
diff --git a/services/maintenance/maintenance.spec.js b/services/maintenance/maintenance.spec.js
index 460df7fa941ec9ebe1c6688988fab05d96e83665..cb98567746fd11dfd2d317456d0b620549bc0460 100644
--- a/services/maintenance/maintenance.spec.js
+++ b/services/maintenance/maintenance.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const Maintenance = require('./maintenance.service')
+import { test, given } from 'sazerac'
+import Maintenance from './maintenance.service.js'
 
 describe('Maintenance', function () {
   test(Maintenance.prototype.transform, () => {
diff --git a/services/maintenance/maintenance.tester.js b/services/maintenance/maintenance.tester.js
index 04e53ee0bea417116323b99bee87ac9bd06b14b1..1fd3dee957477d2d49a0e8a5495102480fffff77 100644
--- a/services/maintenance/maintenance.tester.js
+++ b/services/maintenance/maintenance.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const currentYear = new Date().getUTCFullYear()
 
diff --git a/services/mastodon/mastodon-follow.service.js b/services/mastodon/mastodon-follow.service.js
index 9e0881b5adfd766201077de9eb5f10b5d3fb5fdb..cea9e509948e752c731e6fc3a2380a0c1b7d1e14 100644
--- a/services/mastodon/mastodon-follow.service.js
+++ b/services/mastodon/mastodon-follow.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { optionalUrl, nonNegativeInteger } = require('../validators')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { optionalUrl, nonNegativeInteger } from '../validators.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const schema = Joi.object({
   username: Joi.string().required(),
@@ -20,7 +18,7 @@ const documentation = `
 <p>Failing that, you can also visit your profile page, where your user ID will be in the header in a tag like this: <code>&lt;link href='https://your.mastodon.server/api/salmon/{your-user-id}' rel='salmon'></code></p>
 `
 
-module.exports = class MastodonFollow extends BaseJsonService {
+export default class MastodonFollow extends BaseJsonService {
   static category = 'social'
 
   static route = {
diff --git a/services/mastodon/mastodon-follow.tester.js b/services/mastodon/mastodon-follow.tester.js
index 4f68ec5df905a804d83b1a0d7f49bdac5b0ad74e..1b792bad8c96298abcf9806cc00afc0402b20e12 100644
--- a/services/mastodon/mastodon-follow.tester.js
+++ b/services/mastodon/mastodon-follow.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Followers - default domain')
   .get('/26471.json')
diff --git a/services/matrix/matrix.service.js b/services/matrix/matrix.service.js
index 55239edfa379fbfda9c08ebf01a33c8ef3a1eecc..d0cdf311e488a47cad86cbf6cbacbd20c13e905e 100644
--- a/services/matrix/matrix.service.js
+++ b/services/matrix/matrix.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService, InvalidParameter } = require('..')
+import Joi from 'joi'
+import { BaseJsonService, InvalidParameter } from '../index.js'
 
 const queryParamSchema = Joi.object({
   server_fqdn: Joi.string().hostname(),
@@ -52,7 +50,7 @@ const documentation = `
   </p>
   `
 
-module.exports = class Matrix extends BaseJsonService {
+export default class Matrix extends BaseJsonService {
   static category = 'chat'
 
   static route = {
diff --git a/services/matrix/matrix.tester.js b/services/matrix/matrix.tester.js
index 564df75ad80b799e75c44b82892b0c6964cdccb1..d87857497a2fc6a2202a8ea3867d9cedf0d78461 100644
--- a/services/matrix/matrix.tester.js
+++ b/services/matrix/matrix.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('get room state as guest')
   .get('/ALIAS:DUMMY.dumb.json')
diff --git a/services/maven-central/maven-central.service.js b/services/maven-central/maven-central.service.js
index 49ad30f08946dabdfc93b78754035cc7390ea506..feccfe07d39a10e3fded68f801355a4eec1ab83c 100644
--- a/services/maven-central/maven-central.service.js
+++ b/services/maven-central/maven-central.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { redirector } from '../index.js'
+import { documentation } from '../maven-metadata/maven-metadata.js'
 
-const { redirector } = require('..')
-const { documentation } = require('../maven-metadata/maven-metadata')
-
-module.exports = redirector({
+export default redirector({
   category: 'version',
   isDeprecated: false,
   route: {
diff --git a/services/maven-central/maven-central.tester.js b/services/maven-central/maven-central.tester.js
index 3facb65da999e2a11bb1a51df5354ac7c46f7d09..ef09147dd50bbd7cb3c5b382bda9e9e2b3698274 100644
--- a/services/maven-central/maven-central.tester.js
+++ b/services/maven-central/maven-central.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('latest version redirection')
   .get('/com.github.fabriziocucci/yacl4j.json') // http://repo1.maven.org/maven2/com/github/fabriziocucci/yacl4j/
diff --git a/services/maven-metadata/maven-metadata-redirect.service.js b/services/maven-metadata/maven-metadata-redirect.service.js
index c713ddd35028bcf160188a7ad65eb8b4a25601d8..a7cffcca7c577ec0e22d9e7ddb8de8ed230c803e 100644
--- a/services/maven-metadata/maven-metadata-redirect.service.js
+++ b/services/maven-metadata/maven-metadata-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = redirector({
+export default redirector({
   category: 'version',
   route: {
     base: 'maven-metadata/v',
diff --git a/services/maven-metadata/maven-metadata-redirect.tester.js b/services/maven-metadata/maven-metadata-redirect.tester.js
index 4694203de109ec43110c10650aef4fa2dbc025bc..ddd053e8bd1298bda96522b7e05fce71e624f6d5 100644
--- a/services/maven-metadata/maven-metadata-redirect.tester.js
+++ b/services/maven-metadata/maven-metadata-redirect.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('maven metadata (badge extension)')
   .get(
diff --git a/services/maven-metadata/maven-metadata.js b/services/maven-metadata/maven-metadata.js
index f96ba9a5a83ad7d5923313628042852d36d68287..b7f9865ea29cbf8b9e2061e448e03ad5af881afe 100644
--- a/services/maven-metadata/maven-metadata.js
+++ b/services/maven-metadata/maven-metadata.js
@@ -2,9 +2,7 @@
 
 // the file contains common constants for badges uses maven-metadata
 
-module.exports = {}
-
-module.exports.documentation = `
+export const documentation = `
 <p>
 <code>versionPrefix</code> and <code>versionSuffix</code> allow narrowing down
 the range of versions the badge will take into account,
diff --git a/services/maven-metadata/maven-metadata.service.js b/services/maven-metadata/maven-metadata.service.js
index 3a495ee69ee737eafd068419290063ae878e8a92..ded8f75965bf5ddb4efaa36c6dbe19bc21e4d7d3 100644
--- a/services/maven-metadata/maven-metadata.service.js
+++ b/services/maven-metadata/maven-metadata.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
-const { renderVersionBadge } = require('../version')
-const { BaseXmlService, NotFound } = require('..')
-const { documentation } = require('./maven-metadata')
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
+import { renderVersionBadge } from '../version.js'
+import { BaseXmlService, NotFound } from '../index.js'
+import { documentation } from './maven-metadata.js'
 
 const queryParamSchema = Joi.object({
   metadataUrl: optionalUrl.required(),
@@ -22,7 +20,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class MavenMetadata extends BaseXmlService {
+export default class MavenMetadata extends BaseXmlService {
   static category = 'version'
 
   static route = {
diff --git a/services/maven-metadata/maven-metadata.tester.js b/services/maven-metadata/maven-metadata.tester.js
index 083c94c5cf030dcd92b69f94403897b983e7591b..4115bd7cdd1365d55b465be5347b6cb1a29da251 100644
--- a/services/maven-metadata/maven-metadata.tester.js
+++ b/services/maven-metadata/maven-metadata.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('valid maven-metadata.xml uri')
   .get(
diff --git a/services/microbadger/microbadger.service.js b/services/microbadger/microbadger.service.js
index ba9196d9fd37e6207b852c2962b333350fc4c5d0..2d1eff78081e78f9c4aa5227381f4b5002663ec4 100644
--- a/services/microbadger/microbadger.service.js
+++ b/services/microbadger/microbadger.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'build',
   route: {
     base: 'microbadger',
diff --git a/services/microbadger/microbadger.tester.js b/services/microbadger/microbadger.tester.js
index 12842da39d2d5a8b2d86f6059af5a0413fa9bc82..ac6b7ce145d2bc3c87abaeec1c52e2a5e4e90335 100644
--- a/services/microbadger/microbadger.tester.js
+++ b/services/microbadger/microbadger.tester.js
@@ -1,10 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'microbadger',
   title: 'Microbadger',
-}))
+})
 
 t.create('no longer available (previously image size)')
   .get('/image-size/fedora/apache.json')
diff --git a/services/mozilla-observatory/mozilla-observatory.service.js b/services/mozilla-observatory/mozilla-observatory.service.js
index 30e9ce43cb8c51f05f3f6a583500f504d2262fa2..8f436056c2d0dfaa9aa6f8ee5de160bf3e7dbf79 100644
--- a/services/mozilla-observatory/mozilla-observatory.service.js
+++ b/services/mozilla-observatory/mozilla-observatory.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   state: Joi.string()
@@ -45,7 +43,7 @@ const documentation = `
 </p>
 `
 
-module.exports = class MozillaObservatory extends BaseJsonService {
+export default class MozillaObservatory extends BaseJsonService {
   // TODO: Once created, change to a more appropriate category,
   // see https://github.com/badges/shields/pull/2926#issuecomment-460777017
   static category = 'monitoring'
diff --git a/services/mozilla-observatory/mozilla-observatory.tester.js b/services/mozilla-observatory/mozilla-observatory.tester.js
index a169bac2fc7dbddcd75450273c80a4ab3b87df41..b3f73f658d51217362a2034eb7585955b436264a 100644
--- a/services/mozilla-observatory/mozilla-observatory.tester.js
+++ b/services/mozilla-observatory/mozilla-observatory.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isMessage = Joi.alternatives()
   .try(
diff --git a/services/myget/myget.service.js b/services/myget/myget.service.js
index 38f17e5c0883a78901f5448c9ce5ce43434e476f..8b654e6ffc31f53b7b0e8970fe44698229a5a78c 100644
--- a/services/myget/myget.service.js
+++ b/services/myget/myget.service.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { createServiceFamily } = require('../nuget/nuget-v3-service-family')
+import { createServiceFamily } from '../nuget/nuget-v3-service-family.js'
 
 const { NugetVersionService: Version, NugetDownloadService: Downloads } =
   createServiceFamily({
@@ -57,7 +55,4 @@ class MyGetDownloadService extends Downloads {
   ]
 }
 
-module.exports = {
-  MyGetVersionService,
-  MyGetDownloadService,
-}
+export { MyGetVersionService, MyGetDownloadService }
diff --git a/services/myget/myget.tester.js b/services/myget/myget.tester.js
index bb9ca7fa2a8ebef2dd6234f78aa9d797bec20a20..7b3e9ec5a6e0875634bc1db0c1a7a91e49049062 100644
--- a/services/myget/myget.tester.js
+++ b/services/myget/myget.tester.js
@@ -1,23 +1,21 @@
-'use strict'
-
-const { ServiceTester } = require('../tester')
-const {
+import { ServiceTester } from '../tester.js'
+import {
   isMetric,
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators')
-const {
+} from '../test-validators.js'
+import {
   queryIndex,
   nuGetV3VersionJsonWithDash,
   nuGetV3VersionJsonFirstCharZero,
   nuGetV3VersionJsonFirstCharNotZero,
-} = require('../nuget-fixtures')
-const { invalidJSON } = require('../response-fixtures')
+} from '../nuget-fixtures.js'
+import { invalidJSON } from '../response-fixtures.js'
 
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'myget',
   title: 'MyGet',
   pathPrefix: '',
-}))
+})
 
 // downloads
 
diff --git a/services/netlify/netlify.service.js b/services/netlify/netlify.service.js
index 37485fde708d2af2098cc8eaba73ac0d995a501a..3feefa4165161dc11433644b1920fb304c9973aa 100644
--- a/services/netlify/netlify.service.js
+++ b/services/netlify/netlify.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { renderBuildStatusBadge } = require('../build-status')
-const { BaseSvgScrapingService } = require('..')
+import { renderBuildStatusBadge } from '../build-status.js'
+import { BaseSvgScrapingService } from '../index.js'
 
 const pendingStatus = 'building'
 const notBuiltStatus = 'not built'
@@ -16,7 +14,7 @@ const statusMap = {
   infrastructure_failure: 'failed',
 }
 
-module.exports = class Netlify extends BaseSvgScrapingService {
+export default class Netlify extends BaseSvgScrapingService {
   static category = 'build'
 
   static route = {
diff --git a/services/netlify/netlify.spec.js b/services/netlify/netlify.spec.js
index faee3111220d951a327f99bcab22cabaf941fb71..c614e5ee62e1be48fe60fa72e58269a053127d42 100644
--- a/services/netlify/netlify.spec.js
+++ b/services/netlify/netlify.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const Netlify = require('./netlify.service')
+import { test, given } from 'sazerac'
+import Netlify from './netlify.service.js'
 
 const building = { message: 'building', label: undefined, color: 'yellow' }
 const notBuilt = { message: 'not built', label: undefined, color: undefined }
diff --git a/services/netlify/netlify.tester.js b/services/netlify/netlify.tester.js
index abea04611958a9a9fdbc65e336eb345f88534dd9..8d9d8a03eab983748cef71004aeed79216e83035 100644
--- a/services/netlify/netlify.tester.js
+++ b/services/netlify/netlify.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('netlify (valid, no branch)')
   .get('/e6d5a4e0-dee1-4261-833e-2f47f509c68f.json')
diff --git a/services/nexus/nexus-redirect.service.js b/services/nexus/nexus-redirect.service.js
index fb194284aefa57ac67fb33495262003ee17470a5..12878567219c8592b53cae1bb0e5125dc4473083 100644
--- a/services/nexus/nexus-redirect.service.js
+++ b/services/nexus/nexus-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   redirector({
     category: 'version',
     route: {
diff --git a/services/nexus/nexus-redirect.tester.js b/services/nexus/nexus-redirect.tester.js
index 7e6b3f56a86d2817e00d6361fbf4b286f28589ac..294b0f67143ad00a310871f909336f4095ce5e76 100644
--- a/services/nexus/nexus-redirect.tester.js
+++ b/services/nexus/nexus-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'NexusRedirect',
   title: 'NexusRedirect',
   pathPrefix: '/nexus',
-}))
+})
 
 t.create('Nexus release')
   .get('/r/https/oss.sonatype.org/com.google.guava/guava.svg')
diff --git a/services/nexus/nexus-version.js b/services/nexus/nexus-version.js
index 89b1f4a66f2c1206bc36a3e030bd8f34d8af5d51..0adb7bf42527fca9e1a32cd36507fa775808ad10 100644
--- a/services/nexus/nexus-version.js
+++ b/services/nexus/nexus-version.js
@@ -1,10 +1,6 @@
-'use strict'
-
 function isSnapshotVersion(version) {
   const pattern = /(\d+\.)*[0-9a-f]-SNAPSHOT/
   return version && version.match(pattern)
 }
 
-module.exports = {
-  isSnapshotVersion,
-}
+export { isSnapshotVersion }
diff --git a/services/nexus/nexus.service.js b/services/nexus/nexus.service.js
index 7906b6933c500f3021eee533850d525ca23477ce..67451ef0c929e528912160f1e818051b01e04e9d 100644
--- a/services/nexus/nexus.service.js
+++ b/services/nexus/nexus.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { version: versionColor } = require('../color-formatters')
-const { addv } = require('../text-formatters')
-const { optionalUrl } = require('../validators')
-const {
+import Joi from 'joi'
+import { version as versionColor } from '../color-formatters.js'
+import { addv } from '../text-formatters.js'
+import {
+  optionalUrl,
   optionalDottedVersionNClausesWithOptionalSuffix,
-} = require('../validators')
-const { BaseJsonService, InvalidResponse, NotFound } = require('..')
-const { isSnapshotVersion } = require('./nexus-version')
+} from '../validators.js'
+import { BaseJsonService, InvalidResponse, NotFound } from '../index.js'
+import { isSnapshotVersion } from './nexus-version.js'
 
 const nexus2SearchApiSchema = Joi.object({
   data: Joi.array()
@@ -53,7 +51,7 @@ const queryParamSchema = Joi.object({
   nexusVersion: Joi.equal('2', '3'),
 }).required()
 
-module.exports = class Nexus extends BaseJsonService {
+export default class Nexus extends BaseJsonService {
   static category = 'version'
 
   static route = {
diff --git a/services/nexus/nexus.spec.js b/services/nexus/nexus.spec.js
index d06c051f2672c7bf7b7f0d8dd0c114808df3bc24..43104b8307da86587d30c2042bf4509d7a164a04 100644
--- a/services/nexus/nexus.spec.js
+++ b/services/nexus/nexus.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const { InvalidResponse, NotFound } = require('..')
-const Nexus = require('./nexus.service')
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import { InvalidResponse, NotFound } from '../index.js'
+import Nexus from './nexus.service.js'
 
 describe('Nexus', function () {
   context('transform2()', function () {
diff --git a/services/nexus/nexus.tester.js b/services/nexus/nexus.tester.js
index f2c37a351be82a5a162ec7e2105bf9c18876af34..f3c7d5c31ec261333ccf7e4313f751da5c430fcb 100644
--- a/services/nexus/nexus.tester.js
+++ b/services/nexus/nexus.tester.js
@@ -1,9 +1,6 @@
-'use strict'
-
-const {
-  isVPlusDottedVersionNClausesWithOptionalSuffix: isVersion,
-} = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionNClausesWithOptionalSuffix as isVersion } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Nexus 2 - search release version valid artifact')
   .timeout(15000)
diff --git a/services/node/node-base.js b/services/node/node-base.js
index 007ad6e4b93af85b39b2cd3a435ed605aa1893c6..61f049595eec91c48b36c04af86842e493c42a6a 100644
--- a/services/node/node-base.js
+++ b/services/node/node-base.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const NPMBase = require('../npm/npm-base')
+import NPMBase from '../npm/npm-base.js'
 
 const keywords = ['npm']
 
-module.exports = class NodeVersionBase extends NPMBase {
+export default class NodeVersionBase extends NPMBase {
   static category = 'platform-support'
 
   static get examples() {
diff --git a/services/node/node-current.service.js b/services/node/node-current.service.js
index cea93959e662e437c83102494d71ed26b2916fdd..4494641fc1f759ea9184d85db59b9a3998026b7a 100644
--- a/services/node/node-current.service.js
+++ b/services/node/node-current.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import NodeVersionBase from './node-base.js'
+import { versionColorForRangeCurrent } from './node-version-color.js'
 
-const NodeVersionBase = require('./node-base')
-const { versionColorForRangeCurrent } = require('./node-version-color')
-
-module.exports = class NodeCurrentVersion extends NodeVersionBase {
+export default class NodeCurrentVersion extends NodeVersionBase {
   static route = this.buildRoute('node/v', { withTag: true })
 
   static defaultBadgeData = {
diff --git a/services/node/node-current.spec.js b/services/node/node-current.spec.js
index 072bf7350dbaddd2b87b241ddaf5a2823cc1acee..11cff97eefaa814abfddf727268037938c646659 100644
--- a/services/node/node-current.spec.js
+++ b/services/node/node-current.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const NodeVersion = require('./node-current.service')
+import { test, given } from 'sazerac'
+import NodeVersion from './node-current.service.js'
 
 describe('node static renderStaticPreview', function () {
   it('should have parity with render()', async function () {
diff --git a/services/node/node-current.tester.js b/services/node/node-current.tester.js
index b9ae1d9e55cb16d193ae12a8f2a730a27c19b476..7d50fa272df0a182b62438e8dfb963f0b5d3a2ae 100644
--- a/services/node/node-current.tester.js
+++ b/services/node/node-current.tester.js
@@ -1,9 +1,9 @@
-'use strict'
-
-const { expect } = require('chai')
-const { Range } = require('semver')
-const t = (module.exports = require('../tester').createServiceTester())
-const { mockPackageData, mockCurrentSha } = require('./testUtils/test-utils')
+import { expect } from 'chai'
+import semverModule from 'semver'
+import { createServiceTester } from '../tester.js'
+import { mockPackageData, mockCurrentSha } from './testUtils/test-utils.js'
+const { Range } = semverModule
+export const t = await createServiceTester()
 
 function expectSemverRange(message) {
   expect(() => new Range(message)).not.to.throw()
diff --git a/services/node/node-lts.service.js b/services/node/node-lts.service.js
index 790e7ea9d2fd2461b21770b73cc280182d7df9eb..934e2ff71912dcabeff75f773d653c770c21dda5 100644
--- a/services/node/node-lts.service.js
+++ b/services/node/node-lts.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import NodeVersionBase from './node-base.js'
+import { versionColorForRangeLts } from './node-version-color.js'
 
-const NodeVersionBase = require('./node-base')
-const { versionColorForRangeLts } = require('./node-version-color')
-
-module.exports = class NodeLtsVersion extends NodeVersionBase {
+export default class NodeLtsVersion extends NodeVersionBase {
   static route = this.buildRoute('node/v-lts', { withTag: true })
 
   static defaultBadgeData = {
diff --git a/services/node/node-lts.spec.js b/services/node/node-lts.spec.js
index f1ca6f100297e5091c1f3cc595d3e87157ccb0ac..cc3711731065dcdc503fffb892ddb0ba794f6b40 100644
--- a/services/node/node-lts.spec.js
+++ b/services/node/node-lts.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const NodeVersion = require('./node-lts.service')
+import { test, given } from 'sazerac'
+import NodeVersion from './node-lts.service.js'
 
 describe('node-lts renderStaticPreview', function () {
   it('should have parity with render()', async function () {
diff --git a/services/node/node-lts.tester.js b/services/node/node-lts.tester.js
index f2d47331fee54fb885158a0576756877ba1b5561..016604c21df7962b3ade63089b00de2bb137c2f3 100644
--- a/services/node/node-lts.tester.js
+++ b/services/node/node-lts.tester.js
@@ -1,13 +1,13 @@
-'use strict'
-
-const { expect } = require('chai')
-const { Range } = require('semver')
-const t = (module.exports = require('../tester').createServiceTester())
-const {
+import { expect } from 'chai'
+import semverModule from 'semver'
+import { createServiceTester } from '../tester.js'
+import {
   mockPackageData,
   mockReleaseSchedule,
   mockVersionsSha,
-} = require('./testUtils/test-utils')
+} from './testUtils/test-utils.js'
+const { Range } = semverModule
+export const t = await createServiceTester()
 
 function expectSemverRange(message) {
   expect(() => new Range(message)).not.to.throw()
diff --git a/services/node/node-version-color.js b/services/node/node-version-color.js
index f13d45e54f4a47d3185d808accadce22293ccae6..44e36984a25ec581a26cd5c3678a2963c5ddefe1 100644
--- a/services/node/node-version-color.js
+++ b/services/node/node-version-color.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { promisify } = require('util')
-const moment = require('moment')
-const semver = require('semver')
-const { regularUpdate } = require('../../core/legacy/regular-update')
+import { promisify } from 'util'
+import moment from 'moment'
+import semver from 'semver'
+import { regularUpdate } from '../../core/legacy/regular-update.js'
 
 const dateFormat = 'YYYY-MM-DD'
 
@@ -84,7 +82,4 @@ async function versionColorForRangeCurrent(range) {
   }
 }
 
-module.exports = {
-  versionColorForRangeCurrent,
-  versionColorForRangeLts,
-}
+export { versionColorForRangeCurrent, versionColorForRangeLts }
diff --git a/services/node/testUtils/test-utils.js b/services/node/testUtils/test-utils.js
index 96b265ee7dac39226d61040515fa6c7f0360fe6c..2a7535ce04cf45ebf126bcfc51a620d274c2705c 100644
--- a/services/node/testUtils/test-utils.js
+++ b/services/node/testUtils/test-utils.js
@@ -1,18 +1,23 @@
-'use strict'
-
-const fs = require('fs')
-const path = require('path')
-const moment = require('moment')
+import fs from 'fs'
+import path from 'path'
+import { fileURLToPath } from 'url'
+import moment from 'moment'
 
 const dateFormat = 'YYYY-MM-DD'
 
 const templates = {
   packageJsonVersionsTemplate: fs.readFileSync(
-    path.join(__dirname, `packageJsonVersionsTemplate.json`),
+    path.join(
+      path.dirname(fileURLToPath(import.meta.url)),
+      `packageJsonVersionsTemplate.json`
+    ),
     'utf-8'
   ),
   packageJsonTemplate: fs.readFileSync(
-    path.join(__dirname, `packageJsonTemplate.json`),
+    path.join(
+      path.dirname(fileURLToPath(import.meta.url)),
+      `packageJsonTemplate.json`
+    ),
     'utf-8'
   ),
 }
@@ -145,9 +150,4 @@ const mockReleaseSchedule = () => nock => {
     .reply(200, schedule)
 }
 
-module.exports = {
-  mockPackageData,
-  mockCurrentSha,
-  mockVersionsSha,
-  mockReleaseSchedule,
-}
+export { mockPackageData, mockCurrentSha, mockVersionsSha, mockReleaseSchedule }
diff --git a/services/nodeping/nodeping-status.service.js b/services/nodeping/nodeping-status.service.js
index 6b85f3a3afef8a8d86ae8998fe32ac312f716745..32d145b995fed840f831c6301502d8e9b68038e6 100644
--- a/services/nodeping/nodeping-status.service.js
+++ b/services/nodeping/nodeping-status.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const {
+import Joi from 'joi'
+import {
   queryParamSchema,
   exampleQueryParams,
   renderWebsiteStatus,
-} = require('../website-status')
-const { BaseJsonService } = require('..')
+} from '../website-status.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.array()
   .items(Joi.object().keys({ su: Joi.boolean() }))
@@ -17,7 +15,7 @@ const schema = Joi.array()
  */
 const exampleCheckUuid = 'jkiwn052-ntpp-4lbb-8d45-ihew6d9ucoei'
 
-module.exports = class NodePingStatus extends BaseJsonService {
+export default class NodePingStatus extends BaseJsonService {
   static category = 'monitoring'
 
   static route = {
diff --git a/services/nodeping/nodeping-status.tester.js b/services/nodeping/nodeping-status.tester.js
index c497f97c8aede6286ca6234434bfa4bedbb540f2..6361cb99ce305d0ba3a96ca0a2eeef28af2a059b 100644
--- a/services/nodeping/nodeping-status.tester.js
+++ b/services/nodeping/nodeping-status.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('NodePing status')
   .get('/jkiwn052-ntpp-4lbb-8d45-ihew6d9ucoei.json')
diff --git a/services/nodeping/nodeping-uptime.service.js b/services/nodeping/nodeping-uptime.service.js
index 1c2c428cc9ce204c5b4b7824693ab7e7dbb8a262..827ac7b6a826db6a694fd4722acac0c9ed815819 100644
--- a/services/nodeping/nodeping-uptime.service.js
+++ b/services/nodeping/nodeping-uptime.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { colorScale } = require('../color-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { colorScale } from '../color-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const colorFormatter = colorScale([99, 99.5, 100])
 
@@ -23,7 +21,7 @@ const sampleCheckUuid = 'jkiwn052-ntpp-4lbb-8d45-ihew6d9ucoei'
 // TODO: support for custom '100%' label
 // TODO: support for custom # of decimal places
 
-module.exports = class NodePingUptime extends BaseJsonService {
+export default class NodePingUptime extends BaseJsonService {
   static category = 'monitoring'
 
   static route = { base: 'nodeping/uptime', pattern: ':checkUuid' }
diff --git a/services/nodeping/nodeping-uptime.tester.js b/services/nodeping/nodeping-uptime.tester.js
index 21a02ad42e4284f1e07aa78b187ad4d6b8652110..5e09a52eca4aca8023a3ad4f5e5b24825044b099 100644
--- a/services/nodeping/nodeping-uptime.tester.js
+++ b/services/nodeping/nodeping-uptime.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isPercentage } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isPercentage } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('NodePing uptime')
   .get('/jkiwn052-ntpp-4lbb-8d45-ihew6d9ucoei.json')
diff --git a/services/npm/npm-base.js b/services/npm/npm-base.js
index dc334d45f726600353e41bc906816e297145481a..7f8ed6cbc2ca3941d05014f45f240e2716201668 100644
--- a/services/npm/npm-base.js
+++ b/services/npm/npm-base.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
-const { isDependencyMap } = require('../package-json-helpers')
-const { BaseJsonService, InvalidResponse, NotFound } = require('..')
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
+import { isDependencyMap } from '../package-json-helpers.js'
+import { BaseJsonService, InvalidResponse, NotFound } from '../index.js'
 
 const deprecatedLicenseObjectSchema = Joi.object({
   type: Joi.string().required(),
@@ -32,13 +30,13 @@ const packageDataSchema = Joi.object({
   files: Joi.array().items(Joi.string()).default([]),
 }).required()
 
-const queryParamSchema = Joi.object({
+export const queryParamSchema = Joi.object({
   registry_uri: optionalUrl,
 }).required()
 
 // Abstract class for NPM badges which display data about the latest version
 // of a package.
-module.exports = class NpmBase extends BaseJsonService {
+export default class NpmBase extends BaseJsonService {
   static auth = {
     passKey: 'npm_token',
     serviceKey: 'npm',
@@ -143,5 +141,3 @@ module.exports = class NpmBase extends BaseJsonService {
     return this.constructor._validate(packageData, packageDataSchema)
   }
 }
-
-module.exports.queryParamSchema = queryParamSchema
diff --git a/services/npm/npm-base.spec.js b/services/npm/npm-base.spec.js
index 710dee6217b2ee4e1a9eb9b3eb963c87a10d4695..1d68e226d027cdd16e62d3482b0242581d1c22f0 100644
--- a/services/npm/npm-base.spec.js
+++ b/services/npm/npm-base.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
 // use NPM Version as an example implementation of NpmBase for this test
-const NpmVersion = require('./npm-version.service')
+import NpmVersion from './npm-version.service.js'
 
 describe('npm', function () {
   describe('auth', function () {
diff --git a/services/npm/npm-collaborators.service.js b/services/npm/npm-collaborators.service.js
index 0071abc3c8a6ddaa6a2dfc8068592294b74c5fcc..3c277b58c6f0fe0e3744a3c55fca123bd796d28c 100644
--- a/services/npm/npm-collaborators.service.js
+++ b/services/npm/npm-collaborators.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { renderContributorBadge } = require('../contributor-count')
-const NpmBase = require('./npm-base')
+import { renderContributorBadge } from '../contributor-count.js'
+import NpmBase from './npm-base.js'
 
 const keywords = ['node']
 
-module.exports = class NpmCollaborators extends NpmBase {
+export default class NpmCollaborators extends NpmBase {
   static category = 'activity'
 
   static route = this.buildRoute('npm/collaborators', { withTag: false })
diff --git a/services/npm/npm-collaborators.tester.js b/services/npm/npm-collaborators.tester.js
index 45f6c9bab680a7bdfb66e32ef75ce24621050a2b..90488d5e853662f8382232c235988e6e35db49b4 100644
--- a/services/npm/npm-collaborators.tester.js
+++ b/services/npm/npm-collaborators.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { nonNegativeInteger } = require('../validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { nonNegativeInteger } from '../validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('gets the contributor count')
   .get('/prettier.json')
diff --git a/services/npm/npm-dependency-version.service.js b/services/npm/npm-dependency-version.service.js
index 83b1e352c6f0bf5bc549e7e41c5c8054c615190e..916a5d7e0a0a9d6c9b23c7e6eda72114c14776f8 100644
--- a/services/npm/npm-dependency-version.service.js
+++ b/services/npm/npm-dependency-version.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { getDependencyVersion } = require('../package-json-helpers')
-const NpmBase = require('./npm-base')
+import { getDependencyVersion } from '../package-json-helpers.js'
+import NpmBase from './npm-base.js'
 
 const { queryParamSchema } = NpmBase
 const keywords = ['node']
 
-module.exports = class NpmDependencyVersion extends NpmBase {
+export default class NpmDependencyVersion extends NpmBase {
   static category = 'platform-support'
 
   static route = {
diff --git a/services/npm/npm-dependency-version.tester.js b/services/npm/npm-dependency-version.tester.js
index f72f598b1ed3af0ac3f27502c5b0e5fc5773035e..864c4d6b15e7fea8c5b007d5f30431c982637b6a 100644
--- a/services/npm/npm-dependency-version.tester.js
+++ b/services/npm/npm-dependency-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { semverRange } = require('../validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { semverRange } from '../validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('gets the peer dependency version')
   .get('/react-boxplot/peer/react.json')
diff --git a/services/npm/npm-downloads.service.js b/services/npm/npm-downloads.service.js
index d263c1f1e4cc7cfb2b26674cd161315365f8b171..ca01fae33f147e7180904bda84d3869b20ff61d6 100644
--- a/services/npm/npm-downloads.service.js
+++ b/services/npm/npm-downloads.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 // https://github.com/npm/registry/blob/master/docs/download-counts.md#output
 const pointResponseSchema = Joi.object({
@@ -45,7 +43,7 @@ const intervalMap = {
 
 // This hits an entirely different API from the rest of the NPM services, so
 // it does not use NpmBase.
-module.exports = class NpmDownloads extends BaseJsonService {
+export default class NpmDownloads extends BaseJsonService {
   static category = 'downloads'
 
   static route = {
diff --git a/services/npm/npm-downloads.spec.js b/services/npm/npm-downloads.spec.js
index 4c94a7d2c16fcea6e3b4aa88897532d393b4a5de..edb9854226272c10e9131d541df598429ba42b72 100644
--- a/services/npm/npm-downloads.spec.js
+++ b/services/npm/npm-downloads.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const NpmDownloads = require('./npm-downloads.service')
+import { test, given } from 'sazerac'
+import NpmDownloads from './npm-downloads.service.js'
 
 describe('NpmDownloads', function () {
   test(NpmDownloads._intervalMap.dt.transform, () => {
diff --git a/services/npm/npm-downloads.tester.js b/services/npm/npm-downloads.tester.js
index e3a9c46d7eee884df36f0a1c682c70489b24b3b6..4ff67bad94be10c9a06bc81b0581732fd681570e 100644
--- a/services/npm/npm-downloads.tester.js
+++ b/services/npm/npm-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetricOverTimePeriod, isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetricOverTimePeriod, isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('weekly downloads of left-pad').get('/dw/left-pad.json').expectBadge({
   label: 'downloads',
diff --git a/services/npm/npm-license.service.js b/services/npm/npm-license.service.js
index 45394ea3e4581f8c0d76fd504b05e19e07d3bb38..ed354e28b8e0330bb2d15e0bda4b0f33b90fbbe5 100644
--- a/services/npm/npm-license.service.js
+++ b/services/npm/npm-license.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { renderLicenseBadge } from '../licenses.js'
+import toArray from '../../core/base-service/to-array.js'
+import NpmBase from './npm-base.js'
 
-const { renderLicenseBadge } = require('../licenses')
-const toArray = require('../../core/base-service/to-array')
-const NpmBase = require('./npm-base')
-
-module.exports = class NpmLicense extends NpmBase {
+export default class NpmLicense extends NpmBase {
   static category = 'license'
 
   static route = this.buildRoute('npm/l', { withTag: false })
diff --git a/services/npm/npm-license.tester.js b/services/npm/npm-license.tester.js
index d30c5783b34b39d0722ace78c43aac6b6acfce00..a06aef4774ae153989762bc9f1c4875058908050 100644
--- a/services/npm/npm-license.tester.js
+++ b/services/npm/npm-license.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('gets the license of express')
   .get('/express.json')
diff --git a/services/npm/npm-type-definitions.service.js b/services/npm/npm-type-definitions.service.js
index ff314e75aba5c74405dd345a852a2b016f769a11..9120b24593cae32442990aee200becd591afaf55 100644
--- a/services/npm/npm-type-definitions.service.js
+++ b/services/npm/npm-type-definitions.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const NpmBase = require('./npm-base')
+import NpmBase from './npm-base.js'
 
 // For this badge to correctly detect type definitions, either the relevant
 // dependencies must be declared, or the `types` key must be set in
 // package.json.
-module.exports = class NpmTypeDefinitions extends NpmBase {
+export default class NpmTypeDefinitions extends NpmBase {
   static category = 'platform-support'
 
   static route = this.buildRoute('npm/types', { withTag: false })
diff --git a/services/npm/npm-type-definitions.spec.js b/services/npm/npm-type-definitions.spec.js
index 98cefb2e5331049c692ed6ada8e3321d40c6d71f..69c4f3d45af9f7a16cd7fd4f516334c4bc898562 100644
--- a/services/npm/npm-type-definitions.spec.js
+++ b/services/npm/npm-type-definitions.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given, forCases } = require('sazerac')
-const NpmTypeDefinitions = require('./npm-type-definitions.service')
+import { test, given, forCases } from 'sazerac'
+import NpmTypeDefinitions from './npm-type-definitions.service.js'
 
 describe('NPM type definitions badge', function () {
   test(NpmTypeDefinitions.transform, () => {
diff --git a/services/npm/npm-type-definitions.tester.js b/services/npm/npm-type-definitions.tester.js
index accd7292cb3886c3d35b5bdd2dd32001daccf0c6..60cadb61fac11aad660432f2d007cbaa9c75e4c8 100644
--- a/services/npm/npm-type-definitions.tester.js
+++ b/services/npm/npm-type-definitions.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isTypeDefinition = Joi.string().regex(
   /^((Flow|TypeScript)|(Flow \| TypeScript))$/
diff --git a/services/npm/npm-version.service.js b/services/npm/npm-version.service.js
index ab517815f3df8e0e005fd54677426d7cc807acdc..95abd88a6c8257f46bdad485d8766773c11bd782 100644
--- a/services/npm/npm-version.service.js
+++ b/services/npm/npm-version.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { NotFound } = require('..')
-const NpmBase = require('./npm-base')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { NotFound } from '../index.js'
+import NpmBase from './npm-base.js'
 
 const keywords = ['node']
 
@@ -13,7 +11,7 @@ const schema = Joi.object()
   .pattern(/./, Joi.string())
   .required()
 
-module.exports = class NpmVersion extends NpmBase {
+export default class NpmVersion extends NpmBase {
   static category = 'version'
 
   static route = this.buildRoute('npm/v', { withTag: true })
diff --git a/services/npm/npm-version.tester.js b/services/npm/npm-version.tester.js
index c0b97b3e63563e32661e7fcf098040dba4777662..a7f3d06a2e5ef91375b089969f2db17434dbfb0a 100644
--- a/services/npm/npm-version.tester.js
+++ b/services/npm/npm-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isSemver } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isSemver } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('gets the package version of left-pad')
   .get('/left-pad.json')
diff --git a/services/npms-io/npms-io-score.service.js b/services/npms-io/npms-io-score.service.js
index 79adf48816e9bc55fd5ce3812698f1c7a80861bc..23f54ac95eb51f5e217d40386754b86a6c359102 100644
--- a/services/npms-io/npms-io-score.service.js
+++ b/services/npms-io/npms-io-score.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
-const { coveragePercentage } = require('../color-formatters')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
+import { coveragePercentage } from '../color-formatters.js'
 
 // https://api-docs.npms.io/#api-Package-GetPackageInfo
 const numberSchema = Joi.number().min(0).max(1).required()
@@ -19,7 +17,7 @@ const responseSchema = Joi.object({
 
 const keywords = ['node', 'npm score']
 
-module.exports = class NpmsIOScore extends BaseJsonService {
+export default class NpmsIOScore extends BaseJsonService {
   static category = 'analysis'
 
   static route = {
diff --git a/services/npms-io/npms-io-score.tester.js b/services/npms-io/npms-io-score.tester.js
index 1c1769ed21f59018364d855eea8ad250619b0108..855efceefad3042a5210bcab88ff28ccbeca8bea 100644
--- a/services/npms-io/npms-io-score.tester.js
+++ b/services/npms-io/npms-io-score.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+import { isPercentage } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('should show final score').get('/final-score/vue.json').expectBadge({
   label: 'score',
diff --git a/services/nsp/nsp.service.js b/services/nsp/nsp.service.js
index ef85af672807f0476055fde0c27f22ccffe06261..63671c181ac0ee21007f4bc305bee8ced3a4f065 100644
--- a/services/nsp/nsp.service.js
+++ b/services/nsp/nsp.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   route: {
     base: 'nsp/npm',
     pattern: ':various*',
diff --git a/services/nsp/nsp.tester.js b/services/nsp/nsp.tester.js
index 11a33eae1b87ce9113926e9cbd6e6edefb940aff..c7c8a198ab554a057e33ebfea2b457b3437e5a64 100644
--- a/services/nsp/nsp.tester.js
+++ b/services/nsp/nsp.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'nsp',
   title: 'nsp',
   pathPrefix: '/nsp/npm',
-}))
+})
 
 t.create('no longer available (previously package)')
   .get('/gh-badges.json')
diff --git a/services/nuget-fixtures.js b/services/nuget-fixtures.js
index c4e0fe30394f92f6bfe46ddf9f81b8255ffdba54..919cdd3b0bcf4b5739f04d77520ca7df20eec0cc 100644
--- a/services/nuget-fixtures.js
+++ b/services/nuget-fixtures.js
@@ -1,5 +1,3 @@
-'use strict'
-
 const queryIndex = JSON.stringify({
   resources: [
     {
@@ -50,7 +48,7 @@ const nuGetV3VersionJsonBuildMetadataWithDash = JSON.stringify({
   ],
 })
 
-module.exports = {
+export {
   queryIndex,
   nuGetV3VersionJsonWithDash,
   nuGetV3VersionJsonFirstCharZero,
diff --git a/services/nuget/nuget-helpers.js b/services/nuget/nuget-helpers.js
index 63603c2d5c7e0febeb4ae6eb775c97eb29bdfac8..d39fbe4348869f42f5eff384f08736522a552634 100644
--- a/services/nuget/nuget-helpers.js
+++ b/services/nuget/nuget-helpers.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { promisify } = require('util')
-const semver = require('semver')
-const { metric, addv } = require('../text-formatters')
-const { downloadCount: downloadCountColor } = require('../color-formatters')
-const { regularUpdate } = require('../../core/legacy/regular-update')
+import { promisify } from 'util'
+import semver from 'semver'
+import { metric, addv } from '../text-formatters.js'
+import { downloadCount as downloadCountColor } from '../color-formatters.js'
+import { regularUpdate } from '../../core/legacy/regular-update.js'
 
 function renderVersionBadge({ version, feed }) {
   let color
@@ -103,7 +101,7 @@ function selectVersion(versions, includePrereleases) {
   }
 }
 
-module.exports = {
+export {
   renderVersionBadge,
   renderDownloadBadge,
   odataToObject,
diff --git a/services/nuget/nuget-helpers.spec.js b/services/nuget/nuget-helpers.spec.js
index a4e40a94e8ca1f843fad5a605c06db81c1ab2509..a5e316490d461ef8cb4903f07961346b100dea04 100644
--- a/services/nuget/nuget-helpers.spec.js
+++ b/services/nuget/nuget-helpers.spec.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const {
+import { test, given } from 'sazerac'
+import {
   renderVersionBadge,
   odataToObject,
   stripBuildMetadata,
   selectVersion,
-} = require('./nuget-helpers')
+} from './nuget-helpers.js'
 
 describe('NuGet helpers', function () {
   test(renderVersionBadge, () => {
diff --git a/services/nuget/nuget-v2-service-family.js b/services/nuget/nuget-v2-service-family.js
index 582771ddf21a45a8e4a28dd2129e7a09ff1b78ce..b950a1ed2b6ea9d353ec567b3ed434a4987a4c16 100644
--- a/services/nuget/nuget-v2-service-family.js
+++ b/services/nuget/nuget-v2-service-family.js
@@ -1,13 +1,16 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService, BaseXmlService, NotFound, redirector } = require('..')
-const {
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import {
+  BaseJsonService,
+  BaseXmlService,
+  NotFound,
+  redirector,
+} from '../index.js'
+import {
   renderVersionBadge,
   renderDownloadBadge,
   odataToObject,
-} = require('./nuget-helpers')
+} from './nuget-helpers.js'
 
 function createFilter({ packageName, includePrereleases }) {
   const releaseTypeFilter = includePrereleases
@@ -224,8 +227,4 @@ function createServiceFamily({
   return { NugetVersionService, NugetVersionRedirector, NugetDownloadService }
 }
 
-module.exports = {
-  createFilter,
-  fetch,
-  createServiceFamily,
-}
+export { createFilter, fetch, createServiceFamily }
diff --git a/services/nuget/nuget-v3-service-family.js b/services/nuget/nuget-v3-service-family.js
index 783cc05a7816deb841cdb91cdbd0228d068c76bf..3a06cd297e84d039bec6d6a3c54f81dcab45c6ad 100644
--- a/services/nuget/nuget-v3-service-family.js
+++ b/services/nuget/nuget-v3-service-family.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const RouteBuilder = require('../route-builder')
-const { BaseJsonService, NotFound } = require('..')
-const {
+import Joi from 'joi'
+import RouteBuilder from '../route-builder.js'
+import { BaseJsonService, NotFound } from '../index.js'
+import {
   renderVersionBadge,
   renderDownloadBadge,
   searchServiceUrl,
   stripBuildMetadata,
   selectVersion,
-} = require('./nuget-helpers')
+} from './nuget-helpers.js'
 
 /*
  * Build the Shields service URL object for the given service configuration. Return
@@ -213,6 +211,4 @@ function createServiceFamily({
   }
 }
 
-module.exports = {
-  createServiceFamily,
-}
+export { createServiceFamily }
diff --git a/services/nuget/nuget-v3-service-family.spec.js b/services/nuget/nuget-v3-service-family.spec.js
index 18b92dccd78992f30796e55028ca4bfffc775d15..a6e49f6b6cb4608ed8562a82394b973c4db28e5e 100644
--- a/services/nuget/nuget-v3-service-family.spec.js
+++ b/services/nuget/nuget-v3-service-family.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { createServiceFamily } = require('./nuget-v3-service-family')
+import { test, given } from 'sazerac'
+import { createServiceFamily } from './nuget-v3-service-family.js'
 
 const { NugetVersionService, NugetDownloadService } = createServiceFamily({
   defaultLabel: 'nuget',
diff --git a/services/nuget/nuget.service.js b/services/nuget/nuget.service.js
index 86c33498f0abc94ed9df10acde771a296af1f9d6..a05bbc3079075efe0eb570517d0c6588f96706cd 100644
--- a/services/nuget/nuget.service.js
+++ b/services/nuget/nuget.service.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { createServiceFamily } = require('./nuget-v3-service-family')
+import { createServiceFamily } from './nuget-v3-service-family.js'
 
 const { NugetVersionService: Version, NugetDownloadService: Downloads } =
   createServiceFamily({
@@ -39,4 +37,4 @@ class NugetDownloadService extends Downloads {
   ]
 }
 
-module.exports = { NugetVersionService, NugetDownloadService }
+export { NugetVersionService, NugetDownloadService }
diff --git a/services/nuget/nuget.tester.js b/services/nuget/nuget.tester.js
index 6bdbf3d663ec17e1da5d122a3ffd3450e665c622..65878d6a11edd1dcf26ce8967fec6210282fd36b 100644
--- a/services/nuget/nuget.tester.js
+++ b/services/nuget/nuget.tester.js
@@ -1,21 +1,19 @@
-'use strict'
-
-const { ServiceTester } = require('../tester')
-const {
+import { ServiceTester } from '../tester.js'
+import {
   isMetric,
   isVPlusDottedVersionNClauses,
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators')
-const {
+} from '../test-validators.js'
+import {
   queryIndex,
   nuGetV3VersionJsonWithDash,
   nuGetV3VersionJsonFirstCharZero,
   nuGetV3VersionJsonFirstCharNotZero,
   nuGetV3VersionJsonBuildMetadataWithDash,
-} = require('../nuget-fixtures')
-const { invalidJSON } = require('../response-fixtures')
+} from '../nuget-fixtures.js'
+import { invalidJSON } from '../response-fixtures.js'
 
-const t = (module.exports = new ServiceTester({ id: 'nuget', title: 'NuGet' }))
+export const t = new ServiceTester({ id: 'nuget', title: 'NuGet' })
 
 // downloads
 
diff --git a/services/nycrc/nycrc.service.js b/services/nycrc/nycrc.service.js
index 016d45f93d2b25118dfbb185c3cf6fe23922c986..1e4405e1b64e83c3e113404f0baef63a25c56d22 100644
--- a/services/nycrc/nycrc.service.js
+++ b/services/nycrc/nycrc.service.js
@@ -1,12 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { coveragePercentage } = require('../color-formatters')
-const {
-  ConditionalGithubAuthV3Service,
-} = require('../github/github-auth-service')
-const { fetchJsonFromRepo } = require('../github/github-common-fetch')
-const { InvalidParameter, InvalidResponse, NotFound } = require('..')
+import Joi from 'joi'
+import { coveragePercentage } from '../color-formatters.js'
+import { ConditionalGithubAuthV3Service } from '../github/github-auth-service.js'
+import { fetchJsonFromRepo } from '../github/github-common-fetch.js'
+import { InvalidParameter, InvalidResponse, NotFound } from '../index.js'
 
 const nycrcSchema = Joi.object({
   branches: Joi.number().min(0).max(100),
@@ -35,7 +31,7 @@ const documentation = `<p>
 
 const validThresholds = ['branches', 'lines', 'functions']
 
-module.exports = class Nycrc extends ConditionalGithubAuthV3Service {
+export default class Nycrc extends ConditionalGithubAuthV3Service {
   static category = 'coverage'
 
   static route = {
diff --git a/services/nycrc/nycrc.tester.js b/services/nycrc/nycrc.tester.js
index 21fed6954f46a6ee81bc52ec31c590f8c8c0a7d6..66894780a8df997c2ca1da02e11c05fa894c25b1 100644
--- a/services/nycrc/nycrc.tester.js
+++ b/services/nycrc/nycrc.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('valid .nycrc')
   .get('/yargs/yargs.json?config=.nycrc')
diff --git a/services/offset-earth/offset-earth-carbon-redirect.service.js b/services/offset-earth/offset-earth-carbon-redirect.service.js
index 0ee89549f742883548583782252429fd89d3ada5..ccbabfab208fce8aa908f7af8d03c188b8ac0415 100644
--- a/services/offset-earth/offset-earth-carbon-redirect.service.js
+++ b/services/offset-earth/offset-earth-carbon-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   // https://github.com/badges/shields/issues/5433
   redirector({
     name: 'OffsetEarthCarbonRedirect',
diff --git a/services/offset-earth/offset-earth-carbon-redirect.tester.js b/services/offset-earth/offset-earth-carbon-redirect.tester.js
index 426efe2eadf596b3bf530a6e100071854f4c0658..66e171d95215becc1e3e04dc58ee6958df7572c7 100644
--- a/services/offset-earth/offset-earth-carbon-redirect.tester.js
+++ b/services/offset-earth/offset-earth-carbon-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'OffsetEarthCarbonRedirect',
   title: 'Offset Earth (Carbon Offset) Redirector',
   pathPrefix: '/offset-earth',
-}))
+})
 
 t.create('Offset Earth carbon alias')
   .get('/carbon/ecologi.svg')
diff --git a/services/offset-earth/offset-earth-trees-redirect.service.js b/services/offset-earth/offset-earth-trees-redirect.service.js
index 7f2567e6eac52cafd855cc551ac2f7f453b1f636..bdc3b16c64d71bff297502015b914bd974a7db04 100644
--- a/services/offset-earth/offset-earth-trees-redirect.service.js
+++ b/services/offset-earth/offset-earth-trees-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   // https://github.com/badges/shields/issues/5433
   redirector({
     name: 'OffsetEarthTreesRedirect',
diff --git a/services/offset-earth/offset-earth-trees-redirect.tester.js b/services/offset-earth/offset-earth-trees-redirect.tester.js
index be8427992bff6966ff19a3eca2c348de8e74de21..eea1a2098e2a4cec120dfb9fea7a0e7065d18503 100644
--- a/services/offset-earth/offset-earth-trees-redirect.tester.js
+++ b/services/offset-earth/offset-earth-trees-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'OffsetEarthTreesRedirect',
   title: 'Offset Earth (Trees) Redirector',
   pathPrefix: '/offset-earth',
-}))
+})
 
 t.create('Offset Earth trees alias')
   .get('/trees/ecologi.svg')
diff --git a/services/open-vsx/open-vsx-base.js b/services/open-vsx/open-vsx-base.js
index 1e0a9049a7f94fd5b9aa7d6ce40a91dae594e86b..d17a1e66a8cf722106bed742b9c2c7888afdd882 100644
--- a/services/open-vsx/open-vsx-base.js
+++ b/services/open-vsx/open-vsx-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalNonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { optionalNonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const extensionQuerySchema = Joi.object({
   error: Joi.string(),
@@ -17,7 +15,7 @@ const extensionQuerySchema = Joi.object({
   }),
 }).required()
 
-module.exports = class OpenVSXBase extends BaseJsonService {
+export default class OpenVSXBase extends BaseJsonService {
   static keywords = [
     'ovsx',
     'open-vsx',
diff --git a/services/open-vsx/open-vsx-downloads.service.js b/services/open-vsx/open-vsx-downloads.service.js
index be6470ba1c3e9ec15dff90aab7ada64ad6f6a21d..b1d86ec4dccad60ceca300a1ad8b28002f2e7af1 100644
--- a/services/open-vsx/open-vsx-downloads.service.js
+++ b/services/open-vsx/open-vsx-downloads.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import OpenVSXBase from './open-vsx-base.js'
 
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const OpenVSXBase = require('./open-vsx-base')
-
-module.exports = class OpenVSXDownloads extends OpenVSXBase {
+export default class OpenVSXDownloads extends OpenVSXBase {
   static category = 'downloads'
 
   static route = {
diff --git a/services/open-vsx/open-vsx-downloads.tester.js b/services/open-vsx/open-vsx-downloads.tester.js
index 7e6797386a11b70ea46f003ec5e58c56ca7af607..72da704337d0f5954f1bf50df963dc0f4c47a7d4 100644
--- a/services/open-vsx/open-vsx-downloads.tester.js
+++ b/services/open-vsx/open-vsx-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { withRegex, isMetric } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { withRegex, isMetric } from '../test-validators.js'
+export const t = await createServiceTester()
 
 const isVersionLabel = withRegex(/^downloads@(\d+\.\d+\.\d+)(\.\d+)?$/)
 
diff --git a/services/open-vsx/open-vsx-rating.service.js b/services/open-vsx/open-vsx-rating.service.js
index f90eefb54e266dc245b2b4d5a593c60171ce4066..ae5702c0f10a073b2f36a7da25a4f982c7ae8e98 100644
--- a/services/open-vsx/open-vsx-rating.service.js
+++ b/services/open-vsx/open-vsx-rating.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { starRating } from '../text-formatters.js'
+import { floorCount } from '../color-formatters.js'
+import OpenVSXBase from './open-vsx-base.js'
 
-const { starRating } = require('../text-formatters')
-const { floorCount } = require('../color-formatters')
-const OpenVSXBase = require('./open-vsx-base')
-
-module.exports = class OpenVSXRating extends OpenVSXBase {
+export default class OpenVSXRating extends OpenVSXBase {
   static category = 'rating'
 
   static route = {
diff --git a/services/open-vsx/open-vsx-rating.spec.js b/services/open-vsx/open-vsx-rating.spec.js
index 9d0bf7f0ca09af5a8211977b38250dfc56990a80..8dc1ec0c286aa59c6a9d6afd07681acdc28cab29 100644
--- a/services/open-vsx/open-vsx-rating.spec.js
+++ b/services/open-vsx/open-vsx-rating.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const OpenVSXRating = require('./open-vsx-rating.service')
+import { test, given } from 'sazerac'
+import OpenVSXRating from './open-vsx-rating.service.js'
 
 describe('OpenVSXRating', function () {
   test(OpenVSXRating.render, () => {
diff --git a/services/open-vsx/open-vsx-rating.tester.js b/services/open-vsx/open-vsx-rating.tester.js
index 71b269ebb702f84711b95eeb067d5d7bf953eb58..a007432b78bb4571c5ecc7de0dfa4c369e999758 100644
--- a/services/open-vsx/open-vsx-rating.tester.js
+++ b/services/open-vsx/open-vsx-rating.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { withRegex, isStarRating } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { withRegex, isStarRating } from '../test-validators.js'
+export const t = await createServiceTester()
 
 const isVscodeRating = withRegex(/[0-5]\.[0-9]{1}\/5?\s*\([0-9]*\)$/)
 
diff --git a/services/open-vsx/open-vsx-release-date.service.js b/services/open-vsx/open-vsx-release-date.service.js
index 4a4343f649eeaa48a395811e99995bca633b1b3f..c201306c8eb6a91f3ee47b341d0c975b51e1c1af 100644
--- a/services/open-vsx/open-vsx-release-date.service.js
+++ b/services/open-vsx/open-vsx-release-date.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { age } from '../color-formatters.js'
+import { formatDate } from '../text-formatters.js'
+import OpenVSXBase from './open-vsx-base.js'
 
-const { age } = require('../color-formatters')
-const { formatDate } = require('../text-formatters')
-const OpenVSXBase = require('./open-vsx-base')
-
-module.exports = class OpenVSXReleaseDate extends OpenVSXBase {
+export default class OpenVSXReleaseDate extends OpenVSXBase {
   static category = 'activity'
 
   static route = {
diff --git a/services/open-vsx/open-vsx-release-date.tester.js b/services/open-vsx/open-vsx-release-date.tester.js
index 5c5e2d111c78d93fac3e39181a06c5281343bb69..2f3649d3ad60e34f9f21956231d0afcb6f6d336e 100644
--- a/services/open-vsx/open-vsx-release-date.tester.js
+++ b/services/open-vsx/open-vsx-release-date.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isFormattedDate } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isFormattedDate } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('release date invalid extension')
   .get('/release-date/badges/shields.json')
diff --git a/services/open-vsx/open-vsx-version.service.js b/services/open-vsx/open-vsx-version.service.js
index eda1ad0f4b7daf8eee1a429e2a63a158307d19f0..45f342a94c4e0be207493b10c7061616ecae6557 100644
--- a/services/open-vsx/open-vsx-version.service.js
+++ b/services/open-vsx/open-vsx-version.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import OpenVSXBase from './open-vsx-base.js'
 
-const { renderVersionBadge } = require('../version')
-const OpenVSXBase = require('./open-vsx-base')
-
-module.exports = class OpenVSXVersion extends OpenVSXBase {
+export default class OpenVSXVersion extends OpenVSXBase {
   static category = 'version'
 
   static route = {
diff --git a/services/open-vsx/open-vsx-version.tester.js b/services/open-vsx/open-vsx-version.tester.js
index 3a0a5e3e73fdbfb36c29d77827878b8507215cbb..ee3bc1a18a161bcf4e9065bcb537a2de829341e1 100644
--- a/services/open-vsx/open-vsx-version.tester.js
+++ b/services/open-vsx/open-vsx-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { withRegex } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { withRegex } from '../test-validators.js'
+export const t = await createServiceTester()
 
 const isVersion = withRegex(/^v(\d+\.\d+\.\d+)(\.\d+)?$/)
 
diff --git a/services/opencollective/opencollective-all.service.js b/services/opencollective/opencollective-all.service.js
index 526eb29d9456eba332796ce850df17318c5f1d4f..dac3229f9779114d37e322167158ded01a6ec5c2 100644
--- a/services/opencollective/opencollective-all.service.js
+++ b/services/opencollective/opencollective-all.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import OpencollectiveBase from './opencollective-base.js'
 
-const OpencollectiveBase = require('./opencollective-base')
-
-module.exports = class OpencollectiveAll extends OpencollectiveBase {
+export default class OpencollectiveAll extends OpencollectiveBase {
   static route = this.buildRoute('all')
 
   static examples = [
diff --git a/services/opencollective/opencollective-all.tester.js b/services/opencollective/opencollective-all.tester.js
index 8ba66a063abce255649cbd68a2cd1c2c85936c6b..d827313c509ad088cd7c0c6d312fa0edff5f6881 100644
--- a/services/opencollective/opencollective-all.tester.js
+++ b/services/opencollective/opencollective-all.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { nonNegativeInteger } = require('../validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { nonNegativeInteger } from '../validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('renders correctly')
   .get('/shields.json')
diff --git a/services/opencollective/opencollective-backers.service.js b/services/opencollective/opencollective-backers.service.js
index ebbc72a717dbeb184af7d1a554d20a53f0d40cd3..3f2b7da4d7541fbd77095d101e7b7190ab973bb4 100644
--- a/services/opencollective/opencollective-backers.service.js
+++ b/services/opencollective/opencollective-backers.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import OpencollectiveBase from './opencollective-base.js'
 
-const OpencollectiveBase = require('./opencollective-base')
-
-module.exports = class OpencollectiveBackers extends OpencollectiveBase {
+export default class OpencollectiveBackers extends OpencollectiveBase {
   static route = this.buildRoute('backers')
 
   static examples = [
diff --git a/services/opencollective/opencollective-backers.tester.js b/services/opencollective/opencollective-backers.tester.js
index e9d2c0601b9103d97c040e02cb4bafb546b427ec..7163f9a5da4ceb37bf838d0e6767d755eb53a0d3 100644
--- a/services/opencollective/opencollective-backers.tester.js
+++ b/services/opencollective/opencollective-backers.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { nonNegativeInteger } = require('../validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { nonNegativeInteger } from '../validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('renders correctly')
   .get('/shields.json')
diff --git a/services/opencollective/opencollective-base.js b/services/opencollective/opencollective-base.js
index 74ae8ec35e586101330f64d6e892feb6873aaf27..ec92f434e280805b6c987083e26e2133fbb1b249 100644
--- a/services/opencollective/opencollective-base.js
+++ b/services/opencollective/opencollective-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 // https://developer.opencollective.com/#/api/collectives?id=get-info
 const collectiveDetailsSchema = Joi.object().keys({
@@ -21,7 +19,7 @@ function buildMembersArraySchema({ userType, tierRequired }) {
   return Joi.array().items(Joi.object().keys(keys))
 }
 
-module.exports = class OpencollectiveBase extends BaseJsonService {
+export default class OpencollectiveBase extends BaseJsonService {
   static category = 'funding'
 
   static buildRoute(base, withTierId) {
diff --git a/services/opencollective/opencollective-by-tier.service.js b/services/opencollective/opencollective-by-tier.service.js
index c2712920d29a21d4ec8f0eef7367f554c553cc79..98acc383f509d56da6d22df439cde12df85411ef 100644
--- a/services/opencollective/opencollective-by-tier.service.js
+++ b/services/opencollective/opencollective-by-tier.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const OpencollectiveBase = require('./opencollective-base')
+import OpencollectiveBase from './opencollective-base.js'
 
 const documentation = `<h3>How to get the tierId</h3>
 <p>According to <a target="_blank" href="https://developer.opencollective.com/#/api/collectives?id=get-members-per-tier">open collectives documentation</a>, you can find the tierId by looking at the URL after clicking on a Tier Card on the collective page. (e.g. tierId for https://opencollective.com/shields/order/2988 is 2988)</p>`
 
-module.exports = class OpencollectiveByTier extends OpencollectiveBase {
+export default class OpencollectiveByTier extends OpencollectiveBase {
   static route = this.buildRoute('tier', true)
 
   static examples = [
diff --git a/services/opencollective/opencollective-by-tier.tester.js b/services/opencollective/opencollective-by-tier.tester.js
index d2b53a8d4e03ed85b7edd3670475217ce3e87f77..c2179fef409a240885df345bfd8c583d2e43e9f1 100644
--- a/services/opencollective/opencollective-by-tier.tester.js
+++ b/services/opencollective/opencollective-by-tier.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { nonNegativeInteger } = require('../validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { nonNegativeInteger } from '../validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('renders correctly')
   .get('/shields/2988.json')
diff --git a/services/opencollective/opencollective-sponsors.service.js b/services/opencollective/opencollective-sponsors.service.js
index 6dface34aa3696a79002d8395c2efcf85c0aa7d9..0f41df6f036577ae7f9a241f387faaaf9302aae1 100644
--- a/services/opencollective/opencollective-sponsors.service.js
+++ b/services/opencollective/opencollective-sponsors.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import OpencollectiveBase from './opencollective-base.js'
 
-const OpencollectiveBase = require('./opencollective-base')
-
-module.exports = class OpencollectiveSponsors extends OpencollectiveBase {
+export default class OpencollectiveSponsors extends OpencollectiveBase {
   static route = this.buildRoute('sponsors')
 
   static examples = [
diff --git a/services/opencollective/opencollective-sponsors.tester.js b/services/opencollective/opencollective-sponsors.tester.js
index 8784501370aadce001279afd109ac3a92b079f82..300af584c42ce190d3aae33a33e045c36c0fe25f 100644
--- a/services/opencollective/opencollective-sponsors.tester.js
+++ b/services/opencollective/opencollective-sponsors.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { nonNegativeInteger } = require('../validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { nonNegativeInteger } from '../validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('renders correctly')
   .get('/shields.json')
diff --git a/services/opm/opm-version.service.js b/services/opm/opm-version.service.js
index 5d84009ce9697a77ac5f3c0a54a346d35b405619..41260c85a3d12b603fbb6e0619d259c67a27f6d5 100644
--- a/services/opm/opm-version.service.js
+++ b/services/opm/opm-version.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import { BaseService, NotFound, InvalidResponse } from '../index.js'
 
-const { renderVersionBadge } = require('../version')
-const { BaseService, NotFound, InvalidResponse } = require('..')
-
-module.exports = class OpmVersion extends BaseService {
+export default class OpmVersion extends BaseService {
   static category = 'version'
 
   static route = {
diff --git a/services/opm/opm-version.tester.js b/services/opm/opm-version.tester.js
index b6ae397047d20e1e5116c36573df4bf59e937cbe..c0e187cf3491a2f8140e76bcc7a8b342764861d7 100644
--- a/services/opm/opm-version.tester.js
+++ b/services/opm/opm-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isValidVersion = Joi.string()
   .regex(/^v[\d+.]+$/)
diff --git a/services/ore/ore-base.js b/services/ore/ore-base.js
index 0158c4d864cdd8a924871add14f7fa6adfc2ec8e..670d92af48e513d1b0c04b5c532a4168f9556946 100644
--- a/services/ore/ore-base.js
+++ b/services/ore/ore-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService, InvalidResponse } = require('..')
+import Joi from 'joi'
+import { BaseJsonService, InvalidResponse } from '../index.js'
 
 const sessionSchema = Joi.object({
   session: Joi.string().required(),
@@ -85,4 +83,4 @@ class BaseOreService extends BaseJsonService {
 
 BaseOreService.sessionToken = null
 
-module.exports = { keywords, documentation, BaseOreService }
+export { keywords, documentation, BaseOreService }
diff --git a/services/ore/ore-category.service.js b/services/ore/ore-category.service.js
index 690dc5397b70f1e661020a19e9da7699c7e14393..ab0e067ce0a6e4017ed3acbca84ae8fe42607485 100644
--- a/services/ore/ore-category.service.js
+++ b/services/ore/ore-category.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseOreService, documentation, keywords } from './ore-base.js'
 
-const { BaseOreService, documentation, keywords } = require('./ore-base')
-
-module.exports = class OreCategory extends BaseOreService {
+export default class OreCategory extends BaseOreService {
   static category = 'other'
 
   static route = {
diff --git a/services/ore/ore-category.spec.js b/services/ore/ore-category.spec.js
index b0572b192ab07b2013b2b1556bae1ec88247e58e..793d38ea346f726bfa68b9bade2e225c2581ca16 100644
--- a/services/ore/ore-category.spec.js
+++ b/services/ore/ore-category.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, forCases, given } = require('sazerac')
-const OreCategory = require('./ore-category.service')
+import { test, forCases, given } from 'sazerac'
+import OreCategory from './ore-category.service.js'
 
 describe('OreCategory', function () {
   test(OreCategory.prototype.transform, () => {
diff --git a/services/ore/ore-category.tester.js b/services/ore/ore-category.tester.js
index 7ff6e39b8a643cb50c11041c305f4a1101740acf..efb62c1324b732f0317223b89c52ad8772f31f22 100644
--- a/services/ore/ore-category.tester.js
+++ b/services/ore/ore-category.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // Taken from https://ore.spongepowered.org/api#/Projects/showProject
 const CATEGORY_ENUM = [
diff --git a/services/ore/ore-downloads.service.js b/services/ore/ore-downloads.service.js
index 6817344c33232ddfee57801fb0816823b92531ed..dd44194804d32ffaa6dbdfc1ce1c1981c6e69ec4 100644
--- a/services/ore/ore-downloads.service.js
+++ b/services/ore/ore-downloads.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import { BaseOreService, documentation, keywords } from './ore-base.js'
 
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const { BaseOreService, documentation, keywords } = require('./ore-base')
-
-module.exports = class OreDownloads extends BaseOreService {
+export default class OreDownloads extends BaseOreService {
   static category = 'downloads'
 
   static route = {
diff --git a/services/ore/ore-downloads.tester.js b/services/ore/ore-downloads.tester.js
index bbe43909138e88ff1e52200054408c57a3811d23..dd2ba54bcfe957aa00ed979e3ec68c94f22a1e90 100644
--- a/services/ore/ore-downloads.tester.js
+++ b/services/ore/ore-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Nucleus (pluginId nucleus)').get('/nucleus.json').expectBadge({
   label: 'downloads',
diff --git a/services/ore/ore-license.service.js b/services/ore/ore-license.service.js
index 397558ca718313a5bf5d540530bf45ff0d94a7fd..362c226aa95d8e7e0d8b7823614c66b184d8662e 100644
--- a/services/ore/ore-license.service.js
+++ b/services/ore/ore-license.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { renderLicenseBadge } from '../licenses.js'
+import { BaseOreService, documentation, keywords } from './ore-base.js'
 
-const { renderLicenseBadge } = require('../licenses')
-const { BaseOreService, documentation, keywords } = require('./ore-base')
-
-module.exports = class OreLicense extends BaseOreService {
+export default class OreLicense extends BaseOreService {
   static category = 'license'
 
   static route = {
diff --git a/services/ore/ore-license.spec.js b/services/ore/ore-license.spec.js
index 166e1c34c2e972cb3c63fcbdef687c4fd59623f9..5e5e922068d750a18caabd75cb5d131fb90e0334 100644
--- a/services/ore/ore-license.spec.js
+++ b/services/ore/ore-license.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const OreLicense = require('./ore-license.service')
+import { test, given } from 'sazerac'
+import OreLicense from './ore-license.service.js'
 
 describe('OreLicense', function () {
   test(OreLicense.prototype.transform, () => {
diff --git a/services/ore/ore-license.tester.js b/services/ore/ore-license.tester.js
index 26617eef67543fa9bacad3b1aba8a1121c98e3cb..dd2c441d594bfb6d0c5f9e2671015b57321e0f3e 100644
--- a/services/ore/ore-license.tester.js
+++ b/services/ore/ore-license.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Nucleus (pluginId nucleus)').get('/nucleus.json').expectBadge({
   label: 'license',
diff --git a/services/ore/ore-sponge-versions.service.js b/services/ore/ore-sponge-versions.service.js
index 12b0d2f194b1ff8dab7579f5c3bb96a31cb3b243..e7689bdc1842bbc9ffa2f13b760f0e3e9c443820 100644
--- a/services/ore/ore-sponge-versions.service.js
+++ b/services/ore/ore-sponge-versions.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseOreService, documentation, keywords } from './ore-base.js'
 
-const { BaseOreService, documentation, keywords } = require('./ore-base')
-
-module.exports = class OreSpongeVersions extends BaseOreService {
+export default class OreSpongeVersions extends BaseOreService {
   static category = 'platform-support'
 
   static route = {
diff --git a/services/ore/ore-sponge-versions.spec.js b/services/ore/ore-sponge-versions.spec.js
index 21710194283e9dd543edf908eb59cea83201450a..b6c7accd798ce3213ed593206bb5dfa4423d81e0 100644
--- a/services/ore/ore-sponge-versions.spec.js
+++ b/services/ore/ore-sponge-versions.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, forCases, given } = require('sazerac')
-const OreSpongeVersions = require('./ore-sponge-versions.service')
+import { test, forCases, given } from 'sazerac'
+import OreSpongeVersions from './ore-sponge-versions.service.js'
 
 const PROMOTED_VERSIONS = [
   {
diff --git a/services/ore/ore-sponge-versions.tester.js b/services/ore/ore-sponge-versions.tester.js
index 7af8fb62a5dd8ba464052b463a3fe45767e11f0c..0d1d6e0570e91cfa069b2a6aa7485804db0bf28c 100644
--- a/services/ore/ore-sponge-versions.tester.js
+++ b/services/ore/ore-sponge-versions.tester.js
@@ -1,6 +1,6 @@
-'use strict'
-
-const Joi = require('joi').extend(joi => ({
+import joiModule from 'joi'
+import { createServiceTester } from '../tester.js'
+const Joi = joiModule.extend(joi => ({
   base: joi.array(),
   coerce: (value, helpers) => ({
     value: value.split ? value.split(' | ') : value,
@@ -8,7 +8,7 @@ const Joi = require('joi').extend(joi => ({
   type: 'versionArray',
 }))
 const isDottedVersionAtLeastOne = Joi.string().regex(/\d+(\.\d+)?(\.\d+)?$/)
-const t = (module.exports = require('../tester').createServiceTester())
+export const t = await createServiceTester()
 
 t.create('Nucleus (pluginId nucleus)')
   .get('/nucleus.json')
diff --git a/services/ore/ore-stars.service.js b/services/ore/ore-stars.service.js
index d24b8df07e7c7397c64b510948c457f62f6e8460..bdc226423b409b58a9f93c8afe1bcba0f19e3d33 100644
--- a/services/ore/ore-stars.service.js
+++ b/services/ore/ore-stars.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { BaseOreService, documentation, keywords } from './ore-base.js'
 
-const { metric } = require('../text-formatters')
-const { BaseOreService, documentation, keywords } = require('./ore-base')
-
-module.exports = class OreStars extends BaseOreService {
+export default class OreStars extends BaseOreService {
   static category = 'rating'
 
   static route = {
diff --git a/services/ore/ore-stars.tester.js b/services/ore/ore-stars.tester.js
index eb01ba380bd6bb565899d28a5050140ee24867a6..c80e67d43d57b14ad5b1005d831acc0db5da6a71 100644
--- a/services/ore/ore-stars.tester.js
+++ b/services/ore/ore-stars.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Nucleus (pluginId nucleus)').get('/nucleus.json').expectBadge({
   label: 'stars',
diff --git a/services/ore/ore-version.service.js b/services/ore/ore-version.service.js
index 5f85de05e1a20204c1f02410c7c56dc12b3d1563..cb7fa47cc4d2f49e2e0b9fcb8180cad2220e55a7 100644
--- a/services/ore/ore-version.service.js
+++ b/services/ore/ore-version.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import { BaseOreService, documentation, keywords } from './ore-base.js'
 
-const { renderVersionBadge } = require('../version')
-const { BaseOreService, documentation, keywords } = require('./ore-base')
-
-module.exports = class OreVersion extends BaseOreService {
+export default class OreVersion extends BaseOreService {
   static category = 'version'
 
   static route = {
diff --git a/services/ore/ore-version.spec.js b/services/ore/ore-version.spec.js
index 4b2cb6656eacfa4f91d679f9f321b1c8ea03a86f..0d50f35acecd5090e51383ec4857011a223f25e4 100644
--- a/services/ore/ore-version.spec.js
+++ b/services/ore/ore-version.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const OreVersion = require('./ore-version.service')
+import { test, given } from 'sazerac'
+import OreVersion from './ore-version.service.js'
 
 describe('OreVersion', function () {
   test(OreVersion.prototype.transform, () => {
diff --git a/services/ore/ore-version.tester.js b/services/ore/ore-version.tester.js
index a1aa7f8cfe06d55fce7289360cb91116254e8526..5f3b3ba4910213a8c4e44c129466c7aae5570b6e 100644
--- a/services/ore/ore-version.tester.js
+++ b/services/ore/ore-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Nucleus (pluginId nucleus)').get('/nucleus.json').expectBadge({
   label: 'version',
diff --git a/services/osslifecycle/osslifecycle.service.js b/services/osslifecycle/osslifecycle.service.js
index 78f110753bf9b59a8fb189b6e93135cff74a7507..114e0e09d75dfa1f05b0b6b75596fba3d80ce450 100644
--- a/services/osslifecycle/osslifecycle.service.js
+++ b/services/osslifecycle/osslifecycle.service.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { BaseService, InvalidResponse } = require('..')
+import { BaseService, InvalidResponse } from '../index.js'
 
 const documentation = `
 <p>
@@ -13,7 +11,7 @@ const documentation = `
 </p>
 `
 
-module.exports = class OssTracker extends BaseService {
+export default class OssTracker extends BaseService {
   static category = 'other'
 
   static route = {
diff --git a/services/osslifecycle/osslifecycle.tester.js b/services/osslifecycle/osslifecycle.tester.js
index a5d40b61d3fa24cb4fd4d90ee9c29a3a8ed7938b..9003d2e778d737aaa9385c26ad029fbc2c191fb8 100644
--- a/services/osslifecycle/osslifecycle.tester.js
+++ b/services/osslifecycle/osslifecycle.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'osslifecycle',
   title: 'OSS Lifecycle',
-}))
+})
 
 t.create('osslifecycle active status').get('/netflix/sureal.json').expectBadge({
   label: 'oss lifecycle',
diff --git a/services/package-json-helpers.js b/services/package-json-helpers.js
index c41d3ca3fa1fa10a574138404c4ed315c765620f..242243ad07dd3b2a063594dce93c5223824db21d 100644
--- a/services/package-json-helpers.js
+++ b/services/package-json-helpers.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { InvalidParameter } = require('.')
+import Joi from 'joi'
+import { InvalidParameter } from './index.js'
 
 const isDependencyMap = Joi.object()
   .pattern(
@@ -45,8 +43,4 @@ function getDependencyVersion({
   return { range }
 }
 
-module.exports = {
-  isDependencyMap,
-  isPackageJsonWithDependencies,
-  getDependencyVersion,
-}
+export { isDependencyMap, isPackageJsonWithDependencies, getDependencyVersion }
diff --git a/services/package-json-helpers.spec.js b/services/package-json-helpers.spec.js
index 7d6437b0e01850d83ef15172320e0e46f188321b..4cdd60741b4a4805f13533152741cd5969ef1d90 100644
--- a/services/package-json-helpers.spec.js
+++ b/services/package-json-helpers.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { getDependencyVersion } = require('./package-json-helpers')
+import { test, given } from 'sazerac'
+import { getDependencyVersion } from './package-json-helpers.js'
 
 describe('Contributor count helpers', function () {
   test(getDependencyVersion, () => {
diff --git a/services/packagecontrol/packagecontrol.service.js b/services/packagecontrol/packagecontrol.service.js
index 595986e13af7ef89eb7b01461ff5b26abfc3e50a..8189054d8b7fa349197507d3056ce959bcaf6219 100644
--- a/services/packagecontrol/packagecontrol.service.js
+++ b/services/packagecontrol/packagecontrol.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const keywords = ['sublime', 'sublimetext', 'packagecontrol']
 
@@ -116,4 +114,4 @@ function DownloadsForInterval(interval) {
   }
 }
 
-module.exports = ['day', 'week', 'month', 'total'].map(DownloadsForInterval)
+export default ['day', 'week', 'month', 'total'].map(DownloadsForInterval)
diff --git a/services/packagecontrol/packagecontrol.tester.js b/services/packagecontrol/packagecontrol.tester.js
index 305811406aea1cef487faf2ed996cae9dfb68dfb..db61cf1251414f55cf7cd4b8fc64ce458f51ce15 100644
--- a/services/packagecontrol/packagecontrol.tester.js
+++ b/services/packagecontrol/packagecontrol.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isMetric, isMetricOverTimePeriod } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isMetric, isMetricOverTimePeriod } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'packagecontrol',
   title: 'Package Control',
-}))
+})
 
 t.create('monthly downloads').get('/dm/GitGutter.json').expectBadge({
   label: 'downloads',
diff --git a/services/packagist/packagist-base.js b/services/packagist/packagist-base.js
index 39e645be688d6235654ab894faec65a7edcd2b3d..083de17bdf102c02c6b3de353a21a9b45753ecd3 100644
--- a/services/packagist/packagist-base.js
+++ b/services/packagist/packagist-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const packageSchema = Joi.object()
   .pattern(
@@ -101,7 +99,7 @@ const cacheDocumentationFragment = `
   </p>
   `
 
-module.exports = {
+export {
   allVersionsSchema,
   keywords,
   BasePackagistService,
diff --git a/services/packagist/packagist-downloads.service.js b/services/packagist/packagist-downloads.service.js
index adf36593fb3a70af00850f88d14dc109a5de0c2e..5d8f133b026ec1f1319b8bfa3fe2e9da72263b38 100644
--- a/services/packagist/packagist-downloads.service.js
+++ b/services/packagist/packagist-downloads.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const { optionalUrl } = require('../validators')
-const {
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import { optionalUrl } from '../validators.js'
+import {
   keywords,
   BasePackagistService,
   customServerDocumentationFragment,
   cacheDocumentationFragment,
-} = require('./packagist-base')
+} from './packagist-base.js'
 
 const periodMap = {
   dm: {
@@ -40,7 +38,7 @@ const queryParamSchema = Joi.object({
   server: optionalUrl,
 }).required()
 
-module.exports = class PackagistDownloads extends BasePackagistService {
+export default class PackagistDownloads extends BasePackagistService {
   static category = 'downloads'
 
   static route = {
diff --git a/services/packagist/packagist-downloads.tester.js b/services/packagist/packagist-downloads.tester.js
index cd23f757232413985aec2725f0938e75dbbea3fb..ee76c04e3f3cb059c3459228bf56c3bfb53954cb 100644
--- a/services/packagist/packagist-downloads.tester.js
+++ b/services/packagist/packagist-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric, isMetricOverTimePeriod } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric, isMetricOverTimePeriod } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('daily downloads (valid, no package version specified)')
   .get('/dd/doctrine/orm.json')
diff --git a/services/packagist/packagist-license.service.js b/services/packagist/packagist-license.service.js
index c7c99533dbe1993c2491d6c469a7bb25dd71289a..241d9a291908e5c1dda20ca356e23750eb07e324 100644
--- a/services/packagist/packagist-license.service.js
+++ b/services/packagist/packagist-license.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderLicenseBadge } = require('../licenses')
-const { optionalUrl } = require('../validators')
-const { NotFound } = require('..')
-const {
+import Joi from 'joi'
+import { renderLicenseBadge } from '../licenses.js'
+import { optionalUrl } from '../validators.js'
+import { NotFound } from '../index.js'
+import {
   keywords,
   BasePackagistService,
   customServerDocumentationFragment,
-} = require('./packagist-base')
+} from './packagist-base.js'
 
 const packageSchema = Joi.object()
   .pattern(
@@ -28,7 +26,7 @@ const queryParamSchema = Joi.object({
   server: optionalUrl,
 }).required()
 
-module.exports = class PackagistLicense extends BasePackagistService {
+export default class PackagistLicense extends BasePackagistService {
   static category = 'license'
 
   static route = {
diff --git a/services/packagist/packagist-license.spec.js b/services/packagist/packagist-license.spec.js
index a9241e10ae78c5a8316b7ed8e1c393c7a5f1a2c4..8c3aaf1d79ea2fcd39de93f3b88423c6f25f7fa4 100644
--- a/services/packagist/packagist-license.spec.js
+++ b/services/packagist/packagist-license.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { expect } = require('chai')
-const { NotFound } = require('..')
-const PackagistLicense = require('./packagist-license.service')
+import { expect } from 'chai'
+import { NotFound } from '../index.js'
+import PackagistLicense from './packagist-license.service.js'
 
 describe('PackagistLicense', function () {
   it('should throw NotFound when default branch is missing', function () {
diff --git a/services/packagist/packagist-license.tester.js b/services/packagist/packagist-license.tester.js
index 983da773e4f9bc21728b34534f1d5c1a53d3e76a..a9f3ef370bcb211fb51becd446c551cc882b2966 100644
--- a/services/packagist/packagist-license.tester.js
+++ b/services/packagist/packagist-license.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('license (valid)')
   .get('/symfony/symfony.json')
diff --git a/services/packagist/packagist-php-version.service.js b/services/packagist/packagist-php-version.service.js
index 2514c2ba460dd5ce1a9787fe2b62515bc8a40fd4..72acd7ad98fce90a5d9140366903805fc68dedfb 100644
--- a/services/packagist/packagist-php-version.service.js
+++ b/services/packagist/packagist-php-version.service.js
@@ -1,19 +1,17 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
-const { NotFound } = require('..')
-const {
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
+import { NotFound } from '../index.js'
+import {
   allVersionsSchema,
   BasePackagistService,
   customServerDocumentationFragment,
-} = require('./packagist-base')
+} from './packagist-base.js'
 
 const queryParamSchema = Joi.object({
   server: optionalUrl,
 }).required()
 
-module.exports = class PackagistPhpVersion extends BasePackagistService {
+export default class PackagistPhpVersion extends BasePackagistService {
   static category = 'platform-support'
 
   static route = {
diff --git a/services/packagist/packagist-php-version.spec.js b/services/packagist/packagist-php-version.spec.js
index 7af1b66996b34d50639210ec7c9c22e0b520172a..1eee30010e1aa1cbabb47c93c9f4e54236cac444 100644
--- a/services/packagist/packagist-php-version.spec.js
+++ b/services/packagist/packagist-php-version.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { expect } = require('chai')
-const { NotFound } = require('..')
-const PackagistPhpVersion = require('./packagist-php-version.service')
+import { expect } from 'chai'
+import { NotFound } from '../index.js'
+import PackagistPhpVersion from './packagist-php-version.service.js'
 
 describe('PackagistPhpVersion', function () {
   const json = {
diff --git a/services/packagist/packagist-php-version.tester.js b/services/packagist/packagist-php-version.tester.js
index 0aa385908892e16c7d9c8e2982bde18af69cd62d..c1c6015c3920a3b4dbf01ff029f3003f17d13d65 100644
--- a/services/packagist/packagist-php-version.tester.js
+++ b/services/packagist/packagist-php-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isComposerVersion } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isComposerVersion } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('gets the package version of symfony')
   .get('/symfony/symfony.json')
diff --git a/services/packagist/packagist-stars.service.js b/services/packagist/packagist-stars.service.js
index 847ee6da2abf6ddf2a58f7d3488fb4a4637188a3..2b3820ffbcddc8a749e91cfafa8d63aa097bb510 100644
--- a/services/packagist/packagist-stars.service.js
+++ b/services/packagist/packagist-stars.service.js
@@ -1,15 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { optionalUrl } = require('../validators')
-const {
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger, optionalUrl } from '../validators.js'
+import {
   keywords,
   BasePackagistService,
   customServerDocumentationFragment,
   cacheDocumentationFragment,
-} = require('./packagist-base')
+} from './packagist-base.js'
 
 const schema = Joi.object({
   package: Joi.object({
@@ -21,7 +18,7 @@ const queryParamSchema = Joi.object({
   server: optionalUrl,
 }).required()
 
-module.exports = class PackagistStars extends BasePackagistService {
+export default class PackagistStars extends BasePackagistService {
   static category = 'rating'
 
   static route = {
diff --git a/services/packagist/packagist-stars.tester.js b/services/packagist/packagist-stars.tester.js
index e8b40b69af4f41fc71ebb3345e1a398d0dc88a28..00b1e0cca071b186c5e93d8dd9fd3757799e7c03 100644
--- a/services/packagist/packagist-stars.tester.js
+++ b/services/packagist/packagist-stars.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Stars (valid package)').get('/guzzlehttp/guzzle.json').expectBadge({
   label: 'stars',
diff --git a/services/packagist/packagist-version.service.js b/services/packagist/packagist-version.service.js
index 900ed33505b48aba42d86411023dd208c742acd7..b20c699206696960384e018d19f45982e2e17ce8 100644
--- a/services/packagist/packagist-version.service.js
+++ b/services/packagist/packagist-version.service.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { compare, isStable, latest } = require('../php-version')
-const { optionalUrl } = require('../validators')
-const { NotFound, redirector } = require('..')
-const {
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { compare, isStable, latest } from '../php-version.js'
+import { optionalUrl } from '../validators.js'
+import { NotFound, redirector } from '../index.js'
+import {
   allVersionsSchema,
   keywords,
   BasePackagistService,
   customServerDocumentationFragment,
-} = require('./packagist-base')
+} from './packagist-base.js'
 
 const packageSchema = Joi.object()
   .pattern(
@@ -148,4 +146,4 @@ const PackagistVersionRedirector = redirector({
   dateAdded: new Date('2019-12-15'),
 })
 
-module.exports = { PackagistVersion, PackagistVersionRedirector }
+export { PackagistVersion, PackagistVersionRedirector }
diff --git a/services/packagist/packagist-version.tester.js b/services/packagist/packagist-version.tester.js
index b01e1b79356795fa131024233d679b1a039b825f..ba2c2797448f2864e547eeaef9733cee1e686599 100644
--- a/services/packagist/packagist-version.tester.js
+++ b/services/packagist/packagist-version.tester.js
@@ -1,15 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const {
-  isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators')
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import Joi from 'joi'
+import { isVPlusDottedVersionNClausesWithOptionalSuffix } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'packagist',
   title: 'Packagist Version',
   pathPrefix: '/packagist',
-}))
+})
 
 /*
   validator for a packagist version number
diff --git a/services/php-eye/php-eye-hhvm.service.js b/services/php-eye/php-eye-hhvm.service.js
index f157de1eeb85389ca9c77a1d349a2ae5a3bb634c..1cb7888a4172ab7911ca0331208c799ca769a149 100644
--- a/services/php-eye/php-eye-hhvm.service.js
+++ b/services/php-eye/php-eye-hhvm.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = [
+export default [
   deprecatedService({
     category: 'platform-support',
     label: 'hhvm',
diff --git a/services/php-eye/php-eye-hhvm.tester.js b/services/php-eye/php-eye-hhvm.tester.js
index ad4e58852df34b9e2053ec516c13595e715ab1b1..c1c7408a945b0eb60056558cf885254038d8037f 100644
--- a/services/php-eye/php-eye-hhvm.tester.js
+++ b/services/php-eye/php-eye-hhvm.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'hhvm',
   title: 'hhvm',
   pathPrefix: '/hhvm',
-}))
+})
 
 t.create('no longer available (previously default branch)')
   .get('/symfony/symfony.json')
diff --git a/services/php-eye/php-eye-php-version.service.js b/services/php-eye/php-eye-php-version.service.js
index e7f13fb857ba186b49b22355c0b22ac39d735167..42e15f8c864a3e006ecafe379fd85d52e46463c6 100644
--- a/services/php-eye/php-eye-php-version.service.js
+++ b/services/php-eye/php-eye-php-version.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = [
+export default [
   deprecatedService({
     category: 'platform-support',
     label: 'php tested',
diff --git a/services/php-eye/php-eye-php-version.tester.js b/services/php-eye/php-eye-php-version.tester.js
index ddf754cf481a28c919993b656cb8e6bfa6ae1778..7806d60f67e0c5d0111846c301964eba19234df3 100644
--- a/services/php-eye/php-eye-php-version.tester.js
+++ b/services/php-eye/php-eye-php-version.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'php-eye',
   title: 'php-eye',
   pathPrefix: '/php-eye',
-}))
+})
 
 t.create('no longer available (previously default branch)')
   .get('/symfony/symfony.json')
diff --git a/services/php-version.js b/services/php-version.js
index 17ede45a6f46d5ff562c50b74c562fe97892a390..091bca3c8b243c3f9efad965068ea7ec8776bfe9 100644
--- a/services/php-version.js
+++ b/services/php-version.js
@@ -3,13 +3,11 @@
  * using the algorithm followed by Composer (see
  * https://getcomposer.org/doc/04-schema.md#version).
  */
-'use strict'
-
-const { promisify } = require('util')
-const request = require('request')
-const { regularUpdate } = require('../core/legacy/regular-update')
-const { listCompare } = require('./version')
-const { omitv } = require('./text-formatters')
+import { promisify } from 'util'
+import request from 'request'
+import { regularUpdate } from '../core/legacy/regular-update.js'
+import { listCompare } from './version.js'
+import { omitv } from './text-formatters.js'
 
 // Return a negative value if v1 < v2,
 // zero if v1 = v2, a positive value otherwise.
@@ -240,7 +238,7 @@ async function getPhpReleases(githubApiProvider) {
   })
 }
 
-module.exports = {
+export {
   compare,
   latest,
   isStable,
diff --git a/services/php-version.spec.js b/services/php-version.spec.js
index 607f302ef7eb21e0ef57a213bc8cea06b9d8fc08..2ccd237dd3b253ee5be5953bc7275185d3eed0c2 100644
--- a/services/php-version.spec.js
+++ b/services/php-version.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { compare, minorVersion, versionReduction } = require('./php-version')
+import { test, given } from 'sazerac'
+import { compare, minorVersion, versionReduction } from './php-version.js'
 
 const phpReleases = [
   '5.0',
diff --git a/services/pingpong/pingpong-status.service.js b/services/pingpong/pingpong-status.service.js
index bdebc42a024de26f8f026b4ab6a90781915a3dfe..7297f52a2e551b5835f774839f6c383acf704929 100644
--- a/services/pingpong/pingpong-status.service.js
+++ b/services/pingpong/pingpong-status.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService, InvalidParameter, InvalidResponse } = require('..')
+import Joi from 'joi'
+import { BaseJsonService, InvalidParameter, InvalidResponse } from '../index.js'
 
 const schema = Joi.object({
   status: Joi.string().required(),
@@ -14,7 +12,7 @@ const pingpongDocumentation = `
 </p>
 `
 
-module.exports = class PingPongStatus extends BaseJsonService {
+export default class PingPongStatus extends BaseJsonService {
   static category = 'monitoring'
   static route = { base: 'pingpong/status', pattern: ':apiKey' }
 
diff --git a/services/pingpong/pingpong-status.tester.js b/services/pingpong/pingpong-status.tester.js
index 9f151cc90967ebc3ab3d1936d3aca258dd522fa0..021e6c18978541833e8438293efcaa9639c441da 100644
--- a/services/pingpong/pingpong-status.tester.js
+++ b/services/pingpong/pingpong-status.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isCorrectStatus = Joi.string().valid(
   'up',
diff --git a/services/pingpong/pingpong-uptime.service.js b/services/pingpong/pingpong-uptime.service.js
index 29878478269e9e10f2755162a5542bbb06c67a28..eb58d7e456b43af45352b326f250d9edb7f9e3ce 100644
--- a/services/pingpong/pingpong-uptime.service.js
+++ b/services/pingpong/pingpong-uptime.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { coveragePercentage } = require('../color-formatters')
-const { BaseJsonService, InvalidParameter } = require('..')
+import Joi from 'joi'
+import { coveragePercentage } from '../color-formatters.js'
+import { BaseJsonService, InvalidParameter } from '../index.js'
 
 const schema = Joi.object({
   uptime: Joi.number().min(0).max(100).required(),
@@ -15,7 +13,7 @@ const pingpongDocumentation = `
 </p>
 `
 
-module.exports = class PingPongUptime extends BaseJsonService {
+export default class PingPongUptime extends BaseJsonService {
   static category = 'monitoring'
   static route = { base: 'pingpong/uptime', pattern: ':apiKey' }
 
diff --git a/services/pingpong/pingpong-uptime.tester.js b/services/pingpong/pingpong-uptime.tester.js
index ea72c86ba3b5572dc24fcd90c6e30b23a42cf668..0128983289ca44575146c4a24d816ec036219710 100644
--- a/services/pingpong/pingpong-uptime.tester.js
+++ b/services/pingpong/pingpong-uptime.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('PingPong: Uptime (valid)')
   .get('/sp_eb705b7c189f42e3b574dc790291c33f.json')
diff --git a/services/pipenv-helpers.js b/services/pipenv-helpers.js
index 4f31f2eaedef75825794d1b0de534b4c9e40da1e..f5663f6b363e807d7e82745ea1e6f0fef40e16ca 100644
--- a/services/pipenv-helpers.js
+++ b/services/pipenv-helpers.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { InvalidParameter } = require('.')
+import Joi from 'joi'
+import { InvalidParameter } from './index.js'
 
 const isDependency = Joi.alternatives(
   Joi.object({
@@ -52,7 +50,4 @@ function getDependencyVersion({
   }
 }
 
-module.exports = {
-  isLockfile,
-  getDependencyVersion,
-}
+export { isLockfile, getDependencyVersion }
diff --git a/services/pkgreview/package-rating.service.js b/services/pkgreview/package-rating.service.js
index fc7045cbc6a1de692c073afcbdd98de5e8bfde58..25dbe0cba4bd519c824102221a2012e3b09cc2a3 100644
--- a/services/pkgreview/package-rating.service.js
+++ b/services/pkgreview/package-rating.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { starRating, metric } = require('../text-formatters')
-const { colorScale } = require('../color-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { starRating, metric } from '../text-formatters.js'
+import { colorScale } from '../color-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const pkgReviewColor = colorScale([2, 3, 4])
 
@@ -15,7 +13,7 @@ const schema = Joi.object({
 
 // Repository for this service is: https://github.com/iqubex-technologies/pkgreview.dev
 // Internally the service leverages the npms.io API (https://api.npms.io/v2)
-module.exports = class PkgreviewRating extends BaseJsonService {
+export default class PkgreviewRating extends BaseJsonService {
   static category = 'rating'
 
   static route = {
diff --git a/services/pkgreview/package-rating.tester.js b/services/pkgreview/package-rating.tester.js
index a9859265224aa78465d906c1e6f1d9de5b85a82d..ad4b483e56d7c935d9ea0880a79f7a328cf3f72d 100644
--- a/services/pkgreview/package-rating.tester.js
+++ b/services/pkgreview/package-rating.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex, isStarRating } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex, isStarRating } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isRatingWithReviews = withRegex(
   /^(([0-4](.?([0-9]))?)|5)\/5?\s*\([0-9]*\)$/
diff --git a/services/poeditor/poeditor.service.js b/services/poeditor/poeditor.service.js
index 3dd84aea534654befb0c6065ca05a3ba7d5fff0d..806d9bfcfca288b3d5ade09dc31cedcd5e8b5cd9 100644
--- a/services/poeditor/poeditor.service.js
+++ b/services/poeditor/poeditor.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { coveragePercentage } = require('../color-formatters')
-const { BaseJsonService, InvalidResponse } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { coveragePercentage } from '../color-formatters.js'
+import { BaseJsonService, InvalidResponse } from '../index.js'
 
 const documentation = `
   <p>
@@ -36,7 +34,7 @@ const queryParamSchema = Joi.object({
   token: Joi.string().required(),
 }).required()
 
-module.exports = class POEditor extends BaseJsonService {
+export default class POEditor extends BaseJsonService {
   static category = 'other'
 
   static route = {
diff --git a/services/poeditor/poeditor.tester.js b/services/poeditor/poeditor.tester.js
index 78db3b1657369f045f517cfbd20d5411855d410c..691f4d816fa4cd97313b4f1ad72a59a7635b4981 100644
--- a/services/poeditor/poeditor.tester.js
+++ b/services/poeditor/poeditor.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('gets POEditor progress online')
   .get('/progress/323337/de.json?token=7a666b44c0985d16a7b59748f488275c')
diff --git a/services/powershellgallery/powershellgallery.service.js b/services/powershellgallery/powershellgallery.service.js
index 60f329ea955213d728d5beaa29a1b415a149f20e..c5e66108deb60d126d1cd7ece30a76707c0ffce9 100644
--- a/services/powershellgallery/powershellgallery.service.js
+++ b/services/powershellgallery/powershellgallery.service.js
@@ -1,10 +1,5 @@
-'use strict'
-
-const {
-  fetch,
-  createServiceFamily,
-} = require('../nuget/nuget-v2-service-family')
-const { BaseXmlService } = require('..')
+import { fetch, createServiceFamily } from '../nuget/nuget-v2-service-family.js'
+import { BaseXmlService } from '../index.js'
 
 const WINDOWS_TAG_NAME = 'windows'
 const MACOS_TAG_NAME = 'macos'
@@ -97,7 +92,7 @@ class PowershellGalleryPlatformSupport extends BaseXmlService {
   }
 }
 
-module.exports = {
+export {
   PowershellGalleryVersion,
   PowershellGalleryVersionRedirector,
   PowershellGalleryDownloads,
diff --git a/services/powershellgallery/powershellgallery.tester.js b/services/powershellgallery/powershellgallery.tester.js
index d9999b919a23a8b3fa62b4e02389e3bb7a79f2e2..14380ca4870de72e5cd7f16df55936637a059862 100644
--- a/services/powershellgallery/powershellgallery.tester.js
+++ b/services/powershellgallery/powershellgallery.tester.js
@@ -1,21 +1,18 @@
-'use strict'
-
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-const {
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
+import {
   isMetric,
   isVPlusDottedVersionNClauses,
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators')
+} from '../test-validators.js'
 const isPlatform = Joi.string().regex(
   /^(windows|linux|macos)( \| (windows|linux|macos))*$/
 )
 
-const t = new ServiceTester({
+export const t = new ServiceTester({
   id: 'powershellgallery',
   title: 'PowerShell Gallery',
 })
-module.exports = t
 
 t.create('total downloads (valid)').get('/dt/ACMESharp.json').expectBadge({
   label: 'downloads',
diff --git a/services/pub/pub.service.js b/services/pub/pub.service.js
index ccc12017b78c53412bd28e7b819c22d73bf71b47..19822dc4d5cbd71244219c34f5f879e409d8d699 100644
--- a/services/pub/pub.service.js
+++ b/services/pub/pub.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { latest, renderVersionBadge } = require('../version')
-const { BaseJsonService, redirector } = require('..')
+import Joi from 'joi'
+import { latest, renderVersionBadge } from '../version.js'
+import { BaseJsonService, redirector } from '../index.js'
 
 const schema = Joi.object({
   versions: Joi.array().items(Joi.string()).required(),
@@ -68,4 +66,4 @@ const PubVersionRedirector = redirector({
   dateAdded: new Date('2019-12-15'),
 })
 
-module.exports = { PubVersion, PubVersionRedirector }
+export { PubVersion, PubVersionRedirector }
diff --git a/services/pub/pub.tester.js b/services/pub/pub.tester.js
index 613447fff620d7240d8f64b1b5ba48a94518db03..63ff3b6fee3aaab44993e23a920ef382faeeae4e 100644
--- a/services/pub/pub.tester.js
+++ b/services/pub/pub.tester.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { isVPlusTripleDottedVersion } = require('../test-validators')
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import { isVPlusTripleDottedVersion } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'PubVersion',
   title: 'Pub Version',
   pathPrefix: '/pub',
-}))
+})
 
 t.create('package version').get('/v/box2d.json').expectBadge({
   label: 'pub',
diff --git a/services/puppetforge/puppetforge-base.js b/services/puppetforge/puppetforge-base.js
index 4e209ca91821f2c1fa03a3ea67fe4cdcfd1f1203..8adb266bec92aac8182a713f7b793580ee3cb077 100644
--- a/services/puppetforge/puppetforge-base.js
+++ b/services/puppetforge/puppetforge-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger, semver } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger, semver } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const usersSchema = Joi.object({
   module_count: nonNegativeInteger,
@@ -44,7 +42,4 @@ class BasePuppetForgeModulesService extends BaseJsonService {
   }
 }
 
-module.exports = {
-  BasePuppetForgeModulesService,
-  BasePuppetForgeUsersService,
-}
+export { BasePuppetForgeModulesService, BasePuppetForgeUsersService }
diff --git a/services/puppetforge/puppetforge-module-downloads.service.js b/services/puppetforge/puppetforge-module-downloads.service.js
index 84eddb3225d2beb5535a401408eaa0c010337389..61a9795ff70ca81ac41cd2abd8644e0ba9be1573 100644
--- a/services/puppetforge/puppetforge-module-downloads.service.js
+++ b/services/puppetforge/puppetforge-module-downloads.service.js
@@ -1,12 +1,8 @@
-'use strict'
+import { downloadCount } from '../color-formatters.js'
+import { metric } from '../text-formatters.js'
+import { BasePuppetForgeModulesService } from './puppetforge-base.js'
 
-const { downloadCount } = require('../color-formatters')
-const { metric } = require('../text-formatters')
-const { BasePuppetForgeModulesService } = require('./puppetforge-base')
-
-module.exports = class PuppetforgeModuleDownloads extends (
-  BasePuppetForgeModulesService
-) {
+export default class PuppetforgeModuleDownloads extends BasePuppetForgeModulesService {
   static category = 'downloads'
 
   static route = {
diff --git a/services/puppetforge/puppetforge-module-downloads.tester.js b/services/puppetforge/puppetforge-module-downloads.tester.js
index f7383969f3d12d057e39073fdcaa18d35f42dbee..ad5e9f10b07e5c6cca2bf2808a5c03a54f4d013b 100644
--- a/services/puppetforge/puppetforge-module-downloads.tester.js
+++ b/services/puppetforge/puppetforge-module-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('module downloads').get('/camptocamp/openssl.json').expectBadge({
   label: 'downloads',
diff --git a/services/puppetforge/puppetforge-module-endorsement.service.js b/services/puppetforge/puppetforge-module-endorsement.service.js
index 4390bff469dd0a56b992cc1c529cda0e2806edac..2ebc258cb7a1d891ce373a6a167977158078208b 100644
--- a/services/puppetforge/puppetforge-module-endorsement.service.js
+++ b/services/puppetforge/puppetforge-module-endorsement.service.js
@@ -1,11 +1,7 @@
-'use strict'
+import { NotFound } from '../index.js'
+import { BasePuppetForgeModulesService } from './puppetforge-base.js'
 
-const { NotFound } = require('..')
-const { BasePuppetForgeModulesService } = require('./puppetforge-base')
-
-module.exports = class PuppetforgeModuleEndorsement extends (
-  BasePuppetForgeModulesService
-) {
+export default class PuppetforgeModuleEndorsement extends BasePuppetForgeModulesService {
   static category = 'rating'
 
   static route = {
diff --git a/services/puppetforge/puppetforge-module-endorsement.tester.js b/services/puppetforge/puppetforge-module-endorsement.tester.js
index 83c5e077585a443ba86672118dd561a5d60cef6d..2f03a591fbbfd27a5806fd9826c884778ba3f003 100644
--- a/services/puppetforge/puppetforge-module-endorsement.tester.js
+++ b/services/puppetforge/puppetforge-module-endorsement.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('module endorsement')
   .get('/camptocamp/openssl.json')
diff --git a/services/puppetforge/puppetforge-module-feedback.service.js b/services/puppetforge/puppetforge-module-feedback.service.js
index ad2e845cacb9e6712d44d03addbcf6b1c4896e1d..041d8b3e87dd0181d4765901aba42a22cbd532f2 100644
--- a/services/puppetforge/puppetforge-module-feedback.service.js
+++ b/services/puppetforge/puppetforge-module-feedback.service.js
@@ -1,14 +1,8 @@
-'use strict'
+import { coveragePercentage as coveragePercentageColor } from '../color-formatters.js'
+import { NotFound } from '../index.js'
+import { BasePuppetForgeModulesService } from './puppetforge-base.js'
 
-const {
-  coveragePercentage: coveragePercentageColor,
-} = require('../color-formatters')
-const { NotFound } = require('..')
-const { BasePuppetForgeModulesService } = require('./puppetforge-base')
-
-module.exports = class PuppetforgeModuleFeedback extends (
-  BasePuppetForgeModulesService
-) {
+export default class PuppetforgeModuleFeedback extends BasePuppetForgeModulesService {
   static category = 'rating'
 
   static route = {
diff --git a/services/puppetforge/puppetforge-module-feedback.tester.js b/services/puppetforge/puppetforge-module-feedback.tester.js
index 1178ab33de086b54c0463877a011660c14db5082..24128bd7e1d9746c41a8c54c2f74027a3b94a0ed 100644
--- a/services/puppetforge/puppetforge-module-feedback.tester.js
+++ b/services/puppetforge/puppetforge-module-feedback.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('module feedback').get('/camptocamp/openssl.json').expectBadge({
   label: 'score',
diff --git a/services/puppetforge/puppetforge-module-pdk-version.service.js b/services/puppetforge/puppetforge-module-pdk-version.service.js
index ced2ff067923fe70e142215380d3ebc467488c0f..69c86542143198c7d7aa11c661b3aea9cdfb04fc 100644
--- a/services/puppetforge/puppetforge-module-pdk-version.service.js
+++ b/services/puppetforge/puppetforge-module-pdk-version.service.js
@@ -1,12 +1,8 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import { NotFound } from '../index.js'
+import { BasePuppetForgeModulesService } from './puppetforge-base.js'
 
-const { renderVersionBadge } = require('../version')
-const { NotFound } = require('..')
-const { BasePuppetForgeModulesService } = require('./puppetforge-base')
-
-module.exports = class PuppetforgeModulePdkVersion extends (
-  BasePuppetForgeModulesService
-) {
+export default class PuppetforgeModulePdkVersion extends BasePuppetForgeModulesService {
   static category = 'platform-support'
 
   static route = {
diff --git a/services/puppetforge/puppetforge-module-pdk-version.tester.js b/services/puppetforge/puppetforge-module-pdk-version.tester.js
index d38efaeb00fa9c814fcf9b1e0448d235d2545a6c..cbcd15d9b5c5ea95fcec545d7e1f3621e5e7c3fc 100644
--- a/services/puppetforge/puppetforge-module-pdk-version.tester.js
+++ b/services/puppetforge/puppetforge-module-pdk-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isSemver } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isSemver } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('PDK version').get('/tragiccode/azure_key_vault.json').expectBadge({
   label: 'pdk version',
diff --git a/services/puppetforge/puppetforge-module-version.service.js b/services/puppetforge/puppetforge-module-version.service.js
index 148a800d8c66a7d3c48980b6ab3192e1c33b0383..b3cb980f7e5944c06a075cf4ec500a99c7e10ce4 100644
--- a/services/puppetforge/puppetforge-module-version.service.js
+++ b/services/puppetforge/puppetforge-module-version.service.js
@@ -1,11 +1,7 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import { BasePuppetForgeModulesService } from './puppetforge-base.js'
 
-const { renderVersionBadge } = require('../version')
-const { BasePuppetForgeModulesService } = require('./puppetforge-base')
-
-module.exports = class PuppetforgeModuleVersion extends (
-  BasePuppetForgeModulesService
-) {
+export default class PuppetforgeModuleVersion extends BasePuppetForgeModulesService {
   static category = 'version'
 
   static route = {
diff --git a/services/puppetforge/puppetforge-module-version.tester.js b/services/puppetforge/puppetforge-module-version.tester.js
index a06132f1c5513d4ad9e8a4809f299abd403ac41d..79117a314e3083c5219793528adc5756acb1f054 100644
--- a/services/puppetforge/puppetforge-module-version.tester.js
+++ b/services/puppetforge/puppetforge-module-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isSemver } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isSemver } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('module version').get('/camptocamp/openssl.json').expectBadge({
   label: 'puppetforge',
diff --git a/services/puppetforge/puppetforge-user-module-count.service.js b/services/puppetforge/puppetforge-user-module-count.service.js
index e45a739a8a2253f21ca4e4f3235177cad982fb5f..1666b110197db02f9bd4d145cb21ce3beb893aa7 100644
--- a/services/puppetforge/puppetforge-user-module-count.service.js
+++ b/services/puppetforge/puppetforge-user-module-count.service.js
@@ -1,12 +1,8 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { floorCount as floorCountColor } from '../color-formatters.js'
+import { BasePuppetForgeUsersService } from './puppetforge-base.js'
 
-const { metric } = require('../text-formatters')
-const { floorCount: floorCountColor } = require('../color-formatters')
-const { BasePuppetForgeUsersService } = require('./puppetforge-base')
-
-module.exports = class PuppetForgeModuleCountService extends (
-  BasePuppetForgeUsersService
-) {
+export default class PuppetForgeModuleCountService extends BasePuppetForgeUsersService {
   static category = 'other'
 
   static route = {
diff --git a/services/puppetforge/puppetforge-user-module-count.tester.js b/services/puppetforge/puppetforge-user-module-count.tester.js
index 1a970d83abb667d0783af016db6baf7846aed203..2d999d10784163dda219ec1c637c866a466d791e 100644
--- a/services/puppetforge/puppetforge-user-module-count.tester.js
+++ b/services/puppetforge/puppetforge-user-module-count.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('modules by user').get('/camptocamp.json').expectBadge({
   label: 'modules',
diff --git a/services/puppetforge/puppetforge-user-release-count.service.js b/services/puppetforge/puppetforge-user-release-count.service.js
index ee2afe4932792283bf54b304795a26ff5554fd4d..d13703dc395f827193a16478f24bd706eca715a4 100644
--- a/services/puppetforge/puppetforge-user-release-count.service.js
+++ b/services/puppetforge/puppetforge-user-release-count.service.js
@@ -1,12 +1,8 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { floorCount as floorCountColor } from '../color-formatters.js'
+import { BasePuppetForgeUsersService } from './puppetforge-base.js'
 
-const { metric } = require('../text-formatters')
-const { floorCount: floorCountColor } = require('../color-formatters')
-const { BasePuppetForgeUsersService } = require('./puppetforge-base')
-
-module.exports = class PuppetForgeReleaseCountService extends (
-  BasePuppetForgeUsersService
-) {
+export default class PuppetForgeReleaseCountService extends BasePuppetForgeUsersService {
   static category = 'other'
 
   static route = {
diff --git a/services/puppetforge/puppetforge-user-release-count.tester.js b/services/puppetforge/puppetforge-user-release-count.tester.js
index 75ec3023d2b89d32e6055ec940fa42bada74ddcb..f8a8d60028c055cf9d09bdbb1aa049eb68916e4a 100644
--- a/services/puppetforge/puppetforge-user-release-count.tester.js
+++ b/services/puppetforge/puppetforge-user-release-count.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('releases by user').get('/camptocamp.json').expectBadge({
   label: 'releases',
diff --git a/services/pypi/pypi-base.js b/services/pypi/pypi-base.js
index 8ca4d87f770756a89867611f162d32cf43669d92..e19d6e23a510cf27df3e4979596032da9ed3ac4c 100644
--- a/services/pypi/pypi-base.js
+++ b/services/pypi/pypi-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   info: Joi.object({
@@ -24,7 +22,7 @@ const schema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class PypiBase extends BaseJsonService {
+export default class PypiBase extends BaseJsonService {
   static buildRoute(base) {
     return {
       base,
diff --git a/services/pypi/pypi-django-versions.service.js b/services/pypi/pypi-django-versions.service.js
index ca6325ad94ae500f21ce361090727185ea663bd6..ffe0fbf1bf37fea556498385a400470ddb2e9ca8 100644
--- a/services/pypi/pypi-django-versions.service.js
+++ b/services/pypi/pypi-django-versions.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import PypiBase from './pypi-base.js'
+import { sortDjangoVersions, parseClassifiers } from './pypi-helpers.js'
 
-const PypiBase = require('./pypi-base')
-const { sortDjangoVersions, parseClassifiers } = require('./pypi-helpers')
-
-module.exports = class PypiDjangoVersions extends PypiBase {
+export default class PypiDjangoVersions extends PypiBase {
   static category = 'platform-support'
 
   static route = this.buildRoute('pypi/djversions')
diff --git a/services/pypi/pypi-django-versions.tester.js b/services/pypi/pypi-django-versions.tester.js
index 8dba69853c5732b3a13293a7ffa97a89357832c9..83fdca15ec086c52792ba4f2114ada2c86b0c0fa 100644
--- a/services/pypi/pypi-django-versions.tester.js
+++ b/services/pypi/pypi-django-versions.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isPipeSeparatedDjangoVersions = Joi.string().regex(
   /^([1-9]\.[0-9]+(?: \| )?)+$/
diff --git a/services/pypi/pypi-downloads.service.js b/services/pypi/pypi-downloads.service.js
index 900dcf614dd5fb99a9483a612c8b4fb28dc73355..21cc1133dd96a1debdb164bbf970dab575c9aa53 100644
--- a/services/pypi/pypi-downloads.service.js
+++ b/services/pypi/pypi-downloads.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { downloadCount } = require('../color-formatters')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { downloadCount } from '../color-formatters.js'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const keywords = ['python']
 
@@ -33,7 +31,7 @@ const periodMap = {
 
 // this badge uses PyPI Stats instead of the PyPI API
 // so it doesn't extend PypiBase
-module.exports = class PypiDownloads extends BaseJsonService {
+export default class PypiDownloads extends BaseJsonService {
   static category = 'downloads'
 
   static route = {
diff --git a/services/pypi/pypi-downloads.tester.js b/services/pypi/pypi-downloads.tester.js
index c8e17b5ea8dcab81d1fa68688e81681a137faa37..5e4b57fe987c22748616f6aae8f76f9bf1b07528 100644
--- a/services/pypi/pypi-downloads.tester.js
+++ b/services/pypi/pypi-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isMetricOverTimePeriod } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isMetricOverTimePeriod } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('daily downloads (valid)')
   .get('/dd/djangorestframework.json')
diff --git a/services/pypi/pypi-format.service.js b/services/pypi/pypi-format.service.js
index b96fc3f4b49e030ca4a3d1d5732566e85c5bffa1..cef3285e4843344f41b128620bc02fdfc00c8afe 100644
--- a/services/pypi/pypi-format.service.js
+++ b/services/pypi/pypi-format.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import PypiBase from './pypi-base.js'
+import { getPackageFormats } from './pypi-helpers.js'
 
-const PypiBase = require('./pypi-base')
-const { getPackageFormats } = require('./pypi-helpers')
-
-module.exports = class PypiFormat extends PypiBase {
+export default class PypiFormat extends PypiBase {
   static category = 'other'
 
   static route = this.buildRoute('pypi/format')
diff --git a/services/pypi/pypi-format.tester.js b/services/pypi/pypi-format.tester.js
index ffc93f9ea58ea28f9a01af086bce6d175a2ac936..af025c67305b8f30329ad3f485867e84e0aaf4b8 100644
--- a/services/pypi/pypi-format.tester.js
+++ b/services/pypi/pypi-format.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('format (wheel, package version in request)')
   .get('/requests/2.18.4.json')
diff --git a/services/pypi/pypi-helpers.js b/services/pypi/pypi-helpers.js
index 5cdf78ced080908518ff9b506928b28faf5adcfc..3d3fa9f9f55a6dc16e19e0136b556fba3682268f 100644
--- a/services/pypi/pypi-helpers.js
+++ b/services/pypi/pypi-helpers.js
@@ -1,5 +1,3 @@
-'use strict'
-
 /*
   Django versions will be specified in the form major.minor
   trying to sort with `semver.compare` will throw e.g:
@@ -105,7 +103,7 @@ function getPackageFormats(packageData) {
   }
 }
 
-module.exports = {
+export {
   parseClassifiers,
   parseDjangoVersionString,
   sortDjangoVersions,
diff --git a/services/pypi/pypi-helpers.spec.js b/services/pypi/pypi-helpers.spec.js
index a236489a8410f785ca658406c7225ea4d5b820d8..eca6fed39b4b40887d3f932a9c92a86cf3cc58e6 100644
--- a/services/pypi/pypi-helpers.spec.js
+++ b/services/pypi/pypi-helpers.spec.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const { test, given, forCases } = require('sazerac')
-const {
+import { test, given, forCases } from 'sazerac'
+import {
   parseClassifiers,
   parseDjangoVersionString,
   sortDjangoVersions,
   getLicenses,
   getPackageFormats,
-} = require('./pypi-helpers')
+} from './pypi-helpers.js'
 
 const classifiersFixture = {
   info: {
diff --git a/services/pypi/pypi-implementation.service.js b/services/pypi/pypi-implementation.service.js
index 4b423855579d7f152f0189a1c8a908450158e531..b5a050fecdd37e1ab00d01babcbcb97c19a16885 100644
--- a/services/pypi/pypi-implementation.service.js
+++ b/services/pypi/pypi-implementation.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import PypiBase from './pypi-base.js'
+import { parseClassifiers } from './pypi-helpers.js'
 
-const PypiBase = require('./pypi-base')
-const { parseClassifiers } = require('./pypi-helpers')
-
-module.exports = class PypiImplementation extends PypiBase {
+export default class PypiImplementation extends PypiBase {
   static category = 'platform-support'
 
   static route = this.buildRoute('pypi/implementation')
diff --git a/services/pypi/pypi-implementation.tester.js b/services/pypi/pypi-implementation.tester.js
index 726d4d2912c589c762d3e7c8af7ba2175baf3dc3..4de094f51205c8e5bf0fab1fb0cab5ef1d8da785 100644
--- a/services/pypi/pypi-implementation.tester.js
+++ b/services/pypi/pypi-implementation.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('implementation (valid, package version in request)')
   .get('/beehive/1.0.json')
diff --git a/services/pypi/pypi-license.service.js b/services/pypi/pypi-license.service.js
index 0844d2a3b86ba40fa12ba5d2053a0d5f0ac33937..c2d2a3228cf0a9fcb9da758c641de1bd0a6ba663 100644
--- a/services/pypi/pypi-license.service.js
+++ b/services/pypi/pypi-license.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { renderLicenseBadge } from '../licenses.js'
+import PypiBase from './pypi-base.js'
+import { getLicenses } from './pypi-helpers.js'
 
-const { renderLicenseBadge } = require('../licenses')
-const PypiBase = require('./pypi-base')
-const { getLicenses } = require('./pypi-helpers')
-
-module.exports = class PypiLicense extends PypiBase {
+export default class PypiLicense extends PypiBase {
   static category = 'license'
 
   static route = this.buildRoute('pypi/l')
diff --git a/services/pypi/pypi-license.tester.js b/services/pypi/pypi-license.tester.js
index 31c66deeac69f64dd87cbdb30981f6f140979b26..74cce2a414425035fcd231d9736b384b71a93032 100644
--- a/services/pypi/pypi-license.tester.js
+++ b/services/pypi/pypi-license.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('license (valid, package version in request)')
   .get('/requests/2.18.4.json')
diff --git a/services/pypi/pypi-python-versions.service.js b/services/pypi/pypi-python-versions.service.js
index 4dcb66a3017960067c42c1140faf740714a820f0..569fc7aa993ecef3a923a48cc21d2678b145de7c 100644
--- a/services/pypi/pypi-python-versions.service.js
+++ b/services/pypi/pypi-python-versions.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import semver from 'semver'
+import PypiBase from './pypi-base.js'
+import { parseClassifiers } from './pypi-helpers.js'
 
-const semver = require('semver')
-const PypiBase = require('./pypi-base')
-const { parseClassifiers } = require('./pypi-helpers')
-
-module.exports = class PypiPythonVersions extends PypiBase {
+export default class PypiPythonVersions extends PypiBase {
   static category = 'platform-support'
 
   static route = this.buildRoute('pypi/pyversions')
diff --git a/services/pypi/pypi-python-versions.spec.js b/services/pypi/pypi-python-versions.spec.js
index 5ce5c07aa13363cf7603a3ec1ac62ad4cc1cdbf8..8a8c483882e9ef0563b5d96597594f0d74f74af6 100644
--- a/services/pypi/pypi-python-versions.spec.js
+++ b/services/pypi/pypi-python-versions.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { render } = require('./pypi-python-versions.service')
+import { test, given } from 'sazerac'
+import PypiPythonVersions from './pypi-python-versions.service.js'
 
 describe('PyPI Python Version', function () {
-  test(render, function () {
+  test(PypiPythonVersions.render, function () {
     // Major versions are hidden if minor are present.
     given({ versions: ['3', '3.4', '3.5', '3.6', '2', '2.7'] }).expect({
       message: '2.7 | 3.4 | 3.5 | 3.6',
diff --git a/services/pypi/pypi-python-versions.tester.js b/services/pypi/pypi-python-versions.tester.js
index efb9308317d5876c094288dfcda81e4c85f93e36..36146ddf92a9777e5d370f156994ce7ff58e6695 100644
--- a/services/pypi/pypi-python-versions.tester.js
+++ b/services/pypi/pypi-python-versions.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isPipeSeparatedPythonVersions = Joi.string().regex(
   /^([1-9]\.[0-9]+(?: \| )?)+$/
diff --git a/services/pypi/pypi-status.service.js b/services/pypi/pypi-status.service.js
index 4df298a03d523394c3c883641b6a5b9114f3a7de..77bff049aace18a544e8c2bef6446dfcede2523e 100644
--- a/services/pypi/pypi-status.service.js
+++ b/services/pypi/pypi-status.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import PypiBase from './pypi-base.js'
+import { parseClassifiers } from './pypi-helpers.js'
 
-const PypiBase = require('./pypi-base')
-const { parseClassifiers } = require('./pypi-helpers')
-
-module.exports = class PypiStatus extends PypiBase {
+export default class PypiStatus extends PypiBase {
   static category = 'other'
 
   static route = this.buildRoute('pypi/status')
diff --git a/services/pypi/pypi-status.tester.js b/services/pypi/pypi-status.tester.js
index 751da746de7b019f4e1f666ab3d7431e96c323fc..764254fe0eba6699fe385f1192d161e12950700b 100644
--- a/services/pypi/pypi-status.tester.js
+++ b/services/pypi/pypi-status.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('status (valid, stable, package version in request)')
   .get('/django/1.11.json')
diff --git a/services/pypi/pypi-version.service.js b/services/pypi/pypi-version.service.js
index 68ae1c5d532bec7f113dfb7d13471a22e85cddad..9a421bd01c444c9c2657f45ae5de95d9c42e1c56 100644
--- a/services/pypi/pypi-version.service.js
+++ b/services/pypi/pypi-version.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import PypiBase from './pypi-base.js'
 
-const { renderVersionBadge } = require('../version')
-const PypiBase = require('./pypi-base')
-
-module.exports = class PypiVersion extends PypiBase {
+export default class PypiVersion extends PypiBase {
   static category = 'version'
 
   static route = this.buildRoute('pypi/v')
diff --git a/services/pypi/pypi-version.tester.js b/services/pypi/pypi-version.tester.js
index 65f881456e841c5da7e00385f671815acba970e9..ed083d92c6504dbdad03d6195c8fe7df168a0ad7 100644
--- a/services/pypi/pypi-version.tester.js
+++ b/services/pypi/pypi-version.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const { isSemver } = require('../test-validators')
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import { isSemver } from '../test-validators.js'
+export const t = await createServiceTester()
 
 const isPsycopg2Version = Joi.string().regex(/^v([0-9][.]?)+$/)
 
diff --git a/services/pypi/pypi-wheel.service.js b/services/pypi/pypi-wheel.service.js
index 47f23b41b2b96d5c52669eb98519cb30374490ca..a81e2e4d42bd59f32678374303cf2596afcca47e 100644
--- a/services/pypi/pypi-wheel.service.js
+++ b/services/pypi/pypi-wheel.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import PypiBase from './pypi-base.js'
+import { getPackageFormats } from './pypi-helpers.js'
 
-const PypiBase = require('./pypi-base')
-const { getPackageFormats } = require('./pypi-helpers')
-
-module.exports = class PypiWheel extends PypiBase {
+export default class PypiWheel extends PypiBase {
   static category = 'platform-support'
 
   static route = this.buildRoute('pypi/wheel')
diff --git a/services/pypi/pypi-wheel.tester.js b/services/pypi/pypi-wheel.tester.js
index d888b6a05df2db339e7cd133f4ea9f71ef76c6df..a70afaf4d4bf5593e34026374fe5e5a554a95b27 100644
--- a/services/pypi/pypi-wheel.tester.js
+++ b/services/pypi/pypi-wheel.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('wheel (has wheel, package version in request)')
   .get('/requests/2.18.4.json')
diff --git a/services/readthedocs/readthedocs.service.js b/services/readthedocs/readthedocs.service.js
index 3b3b15a8a4deb9c7544b9999b71d1d00b7b4cb73..7522e69c3fc5fda2f0abf87a01456752f53d95b4 100644
--- a/services/readthedocs/readthedocs.service.js
+++ b/services/readthedocs/readthedocs.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { BaseSvgScrapingService, NotFound } = require('..')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { BaseSvgScrapingService, NotFound } from '../index.js'
 
 const keywords = ['documentation']
 
@@ -12,7 +10,7 @@ const schema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class ReadTheDocs extends BaseSvgScrapingService {
+export default class ReadTheDocs extends BaseSvgScrapingService {
   static category = 'build'
 
   static route = {
diff --git a/services/readthedocs/readthedocs.tester.js b/services/readthedocs/readthedocs.tester.js
index 2ed6c8bdb45c437f8c7cf51bd42d1fe8519cd1df..5bf83194da2d71cdcf43a32d1901eb0bdafa74ab 100644
--- a/services/readthedocs/readthedocs.tester.js
+++ b/services/readthedocs/readthedocs.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('build status')
   .get('/pip.json')
diff --git a/services/reddit/subreddit-subscribers.service.js b/services/reddit/subreddit-subscribers.service.js
index 992d8668090a6a842e637e44b5420f56deb1b272..2d0ce5c53d7d39fa1dc14b822507fb62988f3aeb 100644
--- a/services/reddit/subreddit-subscribers.service.js
+++ b/services/reddit/subreddit-subscribers.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalNonNegativeInteger } = require('../validators')
-const { metric } = require('../text-formatters')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { optionalNonNegativeInteger } from '../validators.js'
+import { metric } from '../text-formatters.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const schema = Joi.object({
   data: Joi.object({
@@ -11,7 +9,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class RedditSubredditSubscribers extends BaseJsonService {
+export default class RedditSubredditSubscribers extends BaseJsonService {
   static category = 'social'
 
   static route = {
diff --git a/services/reddit/subreddit-subscribers.tester.js b/services/reddit/subreddit-subscribers.tester.js
index b9d4265d5566f530a18a7719080055f674a073b2..1038718d523c8bfec4675053d88fc2a8a5253fc4 100644
--- a/services/reddit/subreddit-subscribers.tester.js
+++ b/services/reddit/subreddit-subscribers.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('subreddit-subscribers (valid subreddit)')
   .get('/drums.json')
diff --git a/services/reddit/user-karma.service.js b/services/reddit/user-karma.service.js
index 35483bb40977158501352d40644b68c7aabb60df..c5595f21e16e4737bf3e2708bf3aabd6409d7d0a 100644
--- a/services/reddit/user-karma.service.js
+++ b/services/reddit/user-karma.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { metric } = require('../text-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { metric } from '../text-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   data: Joi.object({
@@ -12,7 +10,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class RedditUserKarma extends BaseJsonService {
+export default class RedditUserKarma extends BaseJsonService {
   static category = 'social'
 
   static route = {
diff --git a/services/reddit/user-karma.tester.js b/services/reddit/user-karma.tester.js
index e02496e5f28442c8a7d0091d14a3491e4f691489..9023023dbb63075909760f4dd3c0f8b8d2826299 100644
--- a/services/reddit/user-karma.tester.js
+++ b/services/reddit/user-karma.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('user-karma (valid - link)')
   .get('/link/user_simulator.json')
diff --git a/services/redmine/redmine.service.js b/services/redmine/redmine.service.js
index 4de51ca74ad2338f317149193a0320831582579e..288a36ffe471954233b6b3cdfb54e9e362da6165 100644
--- a/services/redmine/redmine.service.js
+++ b/services/redmine/redmine.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { starRating } = require('../text-formatters')
-const { floorCount: floorCountColor } = require('../color-formatters')
-const { BaseXmlService } = require('..')
+import Joi from 'joi'
+import { starRating } from '../text-formatters.js'
+import { floorCount as floorCountColor } from '../color-formatters.js'
+import { BaseXmlService } from '../index.js'
 
 const schema = Joi.object({
   'redmine-plugin': Joi.object({
@@ -78,4 +76,4 @@ class RedminePluginStars extends BaseRedminePluginRating {
   }
 }
 
-module.exports = { RedminePluginRating, RedminePluginStars }
+export { RedminePluginRating, RedminePluginStars }
diff --git a/services/redmine/redmine.tester.js b/services/redmine/redmine.tester.js
index 720d8a77e819dbae61446d5f765c401d987cd963..c69e6e6eceac0275a7f77e433eb1f2f0fb5bf9df 100644
--- a/services/redmine/redmine.tester.js
+++ b/services/redmine/redmine.tester.js
@@ -1,13 +1,11 @@
-'use strict'
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
+import { isStarRating } from '../test-validators.js'
 
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-const { isStarRating } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'redmine',
   title: 'Redmine',
-}))
+})
 
 t.create('plugin rating')
   .get('/plugin/rating/redmine_xlsx_format_issue_exporter.json')
diff --git a/services/repology/repology-repositories.service.js b/services/repology/repology-repositories.service.js
index 7d179bc3f4623b97f2d15d5085b51f01eaf1d131..98b5e3ff55dc6c6e6457a380823685a3959d85ee 100644
--- a/services/repology/repology-repositories.service.js
+++ b/services/repology/repology-repositories.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseSvgScrapingService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseSvgScrapingService } from '../index.js'
 
 const schema = Joi.object({
   message: nonNegativeInteger,
 }).required()
 
-module.exports = class RepologyRepositories extends BaseSvgScrapingService {
+export default class RepologyRepositories extends BaseSvgScrapingService {
   static category = 'platform-support'
 
   static route = {
diff --git a/services/repology/repology-repositories.tester.js b/services/repology/repology-repositories.tester.js
index b300adc44e05e8c5359adf81412601e5ca7ca01e..8250bec843d54a326f9c76880a6bb5e0c51f897b 100644
--- a/services/repology/repology-repositories.tester.js
+++ b/services/repology/repology-repositories.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { nonNegativeInteger } = require('../validators')
+import { createServiceTester } from '../tester.js'
+import { nonNegativeInteger } from '../validators.js'
+export const t = await createServiceTester()
 
 t.create('Existing project').get('/starship.json').expectBadge({
   label: 'repositories',
diff --git a/services/requires/requires.service.js b/services/requires/requires.service.js
index b8528900ec41d252630402a79b9bc44ef4d42eea..03f822231647d0af4cfb007a60028fe7100ac3c5 100644
--- a/services/requires/requires.service.js
+++ b/services/requires/requires.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const statusSchema = Joi.object({
   status: Joi.string().required(),
 }).required()
 
-module.exports = class RequiresIo extends BaseJsonService {
+export default class RequiresIo extends BaseJsonService {
   static category = 'dependencies'
 
   static route = {
diff --git a/services/requires/requires.tester.js b/services/requires/requires.tester.js
index 92545be604469e1fce369c22f784ba850f05ce21..b5dc253ba7087d711584f0f57f765a23b6f47262 100644
--- a/services/requires/requires.tester.js
+++ b/services/requires/requires.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isRequireStatus = Joi.string().regex(
   /^(up to date|outdated|insecure|unknown)$/
diff --git a/services/resharper/resharper.service.js b/services/resharper/resharper.service.js
index 60585f7464721bfc0baa2bc73b76c7e143389860..ef05a293379ac4ca1b1f03fce7386fcf5b53e065 100644
--- a/services/resharper/resharper.service.js
+++ b/services/resharper/resharper.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { createServiceFamily } from '../nuget/nuget-v2-service-family.js'
 
-const { createServiceFamily } = require('../nuget/nuget-v2-service-family')
-
-module.exports = createServiceFamily({
+export default createServiceFamily({
   name: 'ResharperPlugin',
   defaultLabel: 'resharper',
   serviceBaseUrl: 'resharper',
diff --git a/services/resharper/resharper.tester.js b/services/resharper/resharper.tester.js
index bc31157ade833b768c7757c662524505b31f5c5a..d4332f8961cd0d7807c7520660850e6f058c488c 100644
--- a/services/resharper/resharper.tester.js
+++ b/services/resharper/resharper.tester.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const { ServiceTester } = require('../tester')
-const {
+import { ServiceTester } from '../tester.js'
+import {
   isMetric,
   isVPlusDottedVersionNClauses,
   isVPlusDottedVersionNClausesWithOptionalSuffix,
-} = require('../test-validators')
+} from '../test-validators.js'
 
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'resharper',
   title: 'ReSharper',
-}))
+})
 
 // downloads
 
diff --git a/services/response-fixtures.js b/services/response-fixtures.js
index 18d7439e53af1817c46243105c5c0e58c26bba01..90557126f56ad18db7a134a4966b5a670329037e 100644
--- a/services/response-fixtures.js
+++ b/services/response-fixtures.js
@@ -1,12 +1,7 @@
-'use strict'
+export const invalidJSONString = '{{{{{invalid json}}'
 
-const invalidJSONString = '{{{{{invalid json}}'
-
-module.exports = {
-  invalidJSON: () => [
-    200,
-    invalidJSONString,
-    { 'Content-Type': 'application/json' },
-  ],
+export const invalidJSON = () => [
+  200,
   invalidJSONString,
-}
+  { 'Content-Type': 'application/json' },
+]
diff --git a/services/reuse/reuse-compliance-helper.js b/services/reuse/reuse-compliance-helper.js
index bb25653fdf8b28b7537b653c46287cda0e64c891..7503696bb373c0fc3e91284a4c71382d9f74c345 100644
--- a/services/reuse/reuse-compliance-helper.js
+++ b/services/reuse/reuse-compliance-helper.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const Joi = require('joi')
+import Joi from 'joi'
 
 const COLOR_MAP = {
   checking: 'brightgreen',
@@ -13,7 +11,4 @@ const isReuseCompliance = Joi.string()
   .valid('compliant', 'non-compliant', 'checking', 'unregistered')
   .required()
 
-module.exports = {
-  isReuseCompliance,
-  COLOR_MAP,
-}
+export { isReuseCompliance, COLOR_MAP }
diff --git a/services/reuse/reuse-compliance.service.js b/services/reuse/reuse-compliance.service.js
index c33fb3b2f5bc4257e33941bd7c66e3bd6b853fa2..93933f5f9008dc09a2a692a329ea8ac14df56d21 100644
--- a/services/reuse/reuse-compliance.service.js
+++ b/services/reuse/reuse-compliance.service.js
@@ -1,13 +1,12 @@
-'use strict'
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
-const { isReuseCompliance, COLOR_MAP } = require('./reuse-compliance-helper')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
+import { isReuseCompliance, COLOR_MAP } from './reuse-compliance-helper.js'
 
 const responseSchema = Joi.object({
   status: isReuseCompliance,
 }).required()
 
-module.exports = class Reuse extends BaseJsonService {
+export default class Reuse extends BaseJsonService {
   static category = 'license'
 
   static route = {
diff --git a/services/reuse/reuse-compliance.tester.js b/services/reuse/reuse-compliance.tester.js
index a160e6610757153f96c98c11f7223ac4ee30a3c7..de7202f6dbf766e9b59200a9fc26dc7ea5e7a5e0 100644
--- a/services/reuse/reuse-compliance.tester.js
+++ b/services/reuse/reuse-compliance.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isReuseCompliance, COLOR_MAP } = require('./reuse-compliance-helper')
+import { createServiceTester } from '../tester.js'
+import { isReuseCompliance, COLOR_MAP } from './reuse-compliance-helper.js'
+export const t = await createServiceTester()
 
 t.create('valid repo -- live')
   .get('/github.com/fsfe/reuse-tool.json')
diff --git a/services/route-builder.js b/services/route-builder.js
index 99679f316176a87edd9f0c61c6e63b6b6cb2ff2b..a1c894c945a1c04e32de6089bcc5539c3ffb4371 100644
--- a/services/route-builder.js
+++ b/services/route-builder.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const toArray = require('../core/base-service/to-array')
+import toArray from '../core/base-service/to-array.js'
 
 /*
  * Factory class for building a BaseService `route` object. This class is useful
@@ -10,7 +8,7 @@ const toArray = require('../core/base-service/to-array')
  * Patterns based on path-to-regex may obviate the need for this, though they
  * haven't done so yet.
  */
-module.exports = class RouteBuilder {
+export default class RouteBuilder {
   constructor({ base = '' } = {}) {
     this.base = base
 
diff --git a/services/scoop/scoop-version.service.js b/services/scoop/scoop-version.service.js
index a45310785146e2b5156251da4af13addd3eb2922..566a259bf7b8c8005120e6b2cb4f7eb68f5eef7f 100644
--- a/services/scoop/scoop-version.service.js
+++ b/services/scoop/scoop-version.service.js
@@ -1,12 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { NotFound } = require('..')
-const {
-  ConditionalGithubAuthV3Service,
-} = require('../github/github-auth-service')
-const { fetchJsonFromRepo } = require('../github/github-common-fetch')
-const { renderVersionBadge } = require('../version')
+import Joi from 'joi'
+import { NotFound } from '../index.js'
+import { ConditionalGithubAuthV3Service } from '../github/github-auth-service.js'
+import { fetchJsonFromRepo } from '../github/github-common-fetch.js'
+import { renderVersionBadge } from '../version.js'
 
 const gitHubRepoRegExp =
   /https:\/\/github.com\/(?<user>.*?)\/(?<repo>.*?)(\/|$)/
@@ -20,7 +16,7 @@ const queryParamSchema = Joi.object({
   bucket: Joi.string(),
 })
 
-module.exports = class ScoopVersion extends ConditionalGithubAuthV3Service {
+export default class ScoopVersion extends ConditionalGithubAuthV3Service {
   // The buckets file (https://github.com/lukesampson/scoop/blob/master/buckets.json) changes very rarely.
   // Cache it for the lifetime of the current Node.js process.
   buckets = null
diff --git a/services/scoop/scoop-version.tester.js b/services/scoop/scoop-version.tester.js
index 42b89bdeb56c35c49c9457c22f4b63d0b7484a08..6e3950e8a58efc7d06ecd3f1eb1d8965bd63cf85 100644
--- a/services/scoop/scoop-version.tester.js
+++ b/services/scoop/scoop-version.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isVPlusDottedVersionNClauses } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isVPlusDottedVersionNClauses } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'scoop',
   title: 'Scoop',
-}))
+})
 
 // version
 
diff --git a/services/scrutinizer/scrutinizer-base.js b/services/scrutinizer/scrutinizer-base.js
index b2a7c59cab8492f42076cd5f99863a75c7808858..918a9b6dec49da362cf3390c64495686b9f8a49f 100644
--- a/services/scrutinizer/scrutinizer-base.js
+++ b/services/scrutinizer/scrutinizer-base.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseJsonService, NotFound, InvalidResponse } from '../index.js'
 
-const { BaseJsonService, NotFound, InvalidResponse } = require('..')
-
-module.exports = class ScrutinizerBase extends BaseJsonService {
+export default class ScrutinizerBase extends BaseJsonService {
   // https://scrutinizer-ci.com/docs/api/#repository-details
   async fetch({ schema, vcs, slug }) {
     return this._requestJson({
diff --git a/services/scrutinizer/scrutinizer-build.service.js b/services/scrutinizer/scrutinizer-build.service.js
index 71c67312eba676e9de25dc07d5e0af4e189c1b54..44c1f54e44b9e1364dd566554db0c0f9b6ea0718 100644
--- a/services/scrutinizer/scrutinizer-build.service.js
+++ b/services/scrutinizer/scrutinizer-build.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const ScrutinizerBase = require('./scrutinizer-base')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import ScrutinizerBase from './scrutinizer-base.js'
 
 const schema = Joi.object({
   default_branch: Joi.string().required(),
@@ -107,7 +105,7 @@ class ScrutinizerPlainGitBuild extends ScrutinizerBuildBase {
   }
 }
 
-module.exports = [
+export default [
   ScrutinizerBuild,
   ScrutinizerGitLabBuild,
   ScrutinizerPlainGitBuild,
diff --git a/services/scrutinizer/scrutinizer-build.tester.js b/services/scrutinizer/scrutinizer-build.tester.js
index a14498e93933bac7f3fc2c1cb73a837cb11a3fad..37185bf16ba527c7c09a2e1396ef76efaa2d9f86 100644
--- a/services/scrutinizer/scrutinizer-build.tester.js
+++ b/services/scrutinizer/scrutinizer-build.tester.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus } = require('../build-status')
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import Joi from 'joi'
+import { isBuildStatus } from '../build-status.js'
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'ScrutinizerBuild',
   title: 'ScrutinizerBuild',
   pathPrefix: '/scrutinizer/build',
-}))
+})
 
 t.create('build (GitHub)')
   .get('/g/filp/whoops.json')
diff --git a/services/scrutinizer/scrutinizer-coverage.service.js b/services/scrutinizer/scrutinizer-coverage.service.js
index c2b57ba98ea736257860b026ab7b39b6f7bc7e03..cedd137e74203db796a130ff6935af886e9557b7 100644
--- a/services/scrutinizer/scrutinizer-coverage.service.js
+++ b/services/scrutinizer/scrutinizer-coverage.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { colorScale } = require('../color-formatters')
-const { NotFound } = require('..')
-const ScrutinizerBase = require('./scrutinizer-base')
+import Joi from 'joi'
+import { colorScale } from '../color-formatters.js'
+import { NotFound } from '../index.js'
+import ScrutinizerBase from './scrutinizer-base.js'
 
 const schema = Joi.object({
   default_branch: Joi.string().required(),
@@ -139,8 +137,8 @@ class ScrutinizerCoveragePlainGit extends ScrutinizerCoverageBase {
   }
 }
 
-module.exports = [
+export {
   ScrutinizerCoverage,
   ScrutinizerCoverageGitLab,
   ScrutinizerCoveragePlainGit,
-]
+}
diff --git a/services/scrutinizer/scrutinizer-coverage.spec.js b/services/scrutinizer/scrutinizer-coverage.spec.js
index c0308172d42de20bf5e006355d05c1736be2e2b4..2928f54f5f690cb0ca0cf814a0aea4df6a022ee3 100644
--- a/services/scrutinizer/scrutinizer-coverage.spec.js
+++ b/services/scrutinizer/scrutinizer-coverage.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const { test, given } = require('sazerac')
-const { InvalidResponse, NotFound } = require('..')
-const [ScrutinizerCoverage] = require('./scrutinizer-coverage.service')
+import { expect } from 'chai'
+import { test, given } from 'sazerac'
+import { InvalidResponse, NotFound } from '../index.js'
+import { ScrutinizerCoverage } from './scrutinizer-coverage.service.js'
 
 describe('ScrutinizerCoverage', function () {
   test(ScrutinizerCoverage.render, () => {
diff --git a/services/scrutinizer/scrutinizer-coverage.tester.js b/services/scrutinizer/scrutinizer-coverage.tester.js
index ee2ca663b1d3be0feeafdb9b34ea0d0522fd025a..e23e7f59a3fbb7bc88fcbcfc18ca825d9af19d9e 100644
--- a/services/scrutinizer/scrutinizer-coverage.tester.js
+++ b/services/scrutinizer/scrutinizer-coverage.tester.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import { isIntegerPercentage } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'ScrutinizerCoverage',
   title: 'ScrutinizerCoverage',
   pathPrefix: '/scrutinizer/coverage',
-}))
+})
 
 t.create('code coverage (GitHub)').get('/g/filp/whoops.json').expectBadge({
   label: 'coverage',
diff --git a/services/scrutinizer/scrutinizer-quality.service.js b/services/scrutinizer/scrutinizer-quality.service.js
index a5c7406fddcfc7a6bbc9d9935160a969bfc347b2..93939a554da62febb7017ef17a9b595d62ad9f80 100644
--- a/services/scrutinizer/scrutinizer-quality.service.js
+++ b/services/scrutinizer/scrutinizer-quality.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { colorScale } = require('../color-formatters')
-const ScrutinizerBase = require('./scrutinizer-base')
+import Joi from 'joi'
+import { colorScale } from '../color-formatters.js'
+import ScrutinizerBase from './scrutinizer-base.js'
 
 const schema = Joi.object({
   default_branch: Joi.string().required(),
@@ -127,7 +125,7 @@ class ScrutinizerQualityPlainGit extends ScrutinizerQualityBase {
   }
 }
 
-module.exports = [
+export default [
   ScrutinizerQuality,
   ScrutinizerQualityGitLab,
   ScrutinizerQualityPlainGit,
diff --git a/services/scrutinizer/scrutinizer-quality.tester.js b/services/scrutinizer/scrutinizer-quality.tester.js
index d4e14bd1371373ba78057cd94c019aba33d5610b..9009a9d1823a78ecf6938b647dcb4afdd3f71269 100644
--- a/services/scrutinizer/scrutinizer-quality.tester.js
+++ b/services/scrutinizer/scrutinizer-quality.tester.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'ScrutinizerQuality',
   title: 'ScrutinizerQuality',
   pathPrefix: '/scrutinizer/quality',
-}))
+})
 
 const isQualityNumber = Joi.number().positive()
 
diff --git a/services/scrutinizer/scrutinizer-redirect.service.js b/services/scrutinizer/scrutinizer-redirect.service.js
index 4aee6a5ebfa0caeaa98c85d725f2e2ec8e0d2bdc..95a97967c0d541d3de494b83d539a77737971477 100644
--- a/services/scrutinizer/scrutinizer-redirect.service.js
+++ b/services/scrutinizer/scrutinizer-redirect.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const { redirector } = require('..')
+import { redirector } from '../index.js'
 
 const commonAttrs = {
   category: 'analysis',
   dateAdded: new Date('2019-04-24'),
 }
 
-module.exports = [
+export default [
   redirector({
     route: {
       base: 'scrutinizer',
diff --git a/services/scrutinizer/scrutinizer-redirect.tester.js b/services/scrutinizer/scrutinizer-redirect.tester.js
index c9ef3fbd569fc6b42b1cfc3880d7b904c80399b6..b1d8abc51083bd991544ac13b95f8c642ebf5b1c 100644
--- a/services/scrutinizer/scrutinizer-redirect.tester.js
+++ b/services/scrutinizer/scrutinizer-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'ScrutinizerQualityRedirect',
   title: 'ScrutinizerQualityRedirect',
   pathPrefix: '/scrutinizer',
-}))
+})
 
 t.create('scrutinizer quality GitHub')
   .get('/g/doctrine/orm.svg')
diff --git a/services/security-headers/security-headers.service.js b/services/security-headers/security-headers.service.js
index 2816da7adf8ea927598aea4e88f59cfc365a322b..0b935a871eb45f171d406ef45c847fc3115dadba 100644
--- a/services/security-headers/security-headers.service.js
+++ b/services/security-headers/security-headers.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
-const { BaseService, NotFound } = require('..')
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
+import { BaseService, NotFound } from '../index.js'
 
 const queryParamSchema = Joi.object({
   url: optionalUrl.required(),
@@ -20,7 +18,7 @@ const documentation = `
 <p>
 `
 
-module.exports = class SecurityHeaders extends BaseService {
+export default class SecurityHeaders extends BaseService {
   static category = 'monitoring'
 
   static route = {
diff --git a/services/security-headers/security-headers.tester.js b/services/security-headers/security-headers.tester.js
index f3c4e3b1266c31c725f0d96b13eca3b8295c3801..3be2b605117c78dd953604992752437ba5d7619f 100644
--- a/services/security-headers/security-headers.tester.js
+++ b/services/security-headers/security-headers.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('grade of https://shields.io')
   .get('/security-headers.json?url=https://shields.io')
diff --git a/services/shippable/shippable.service.js b/services/shippable/shippable.service.js
index 6d81d15e2e96463eb75becb2af1274f78eb2e5cb..426c773e184164982bfe20e48f972fc354e88c1a 100644
--- a/services/shippable/shippable.service.js
+++ b/services/shippable/shippable.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderBuildStatusBadge } = require('../build-status')
-const { BaseJsonService, NotFound, redirector } = require('..')
+import Joi from 'joi'
+import { renderBuildStatusBadge } from '../build-status.js'
+import { BaseJsonService, NotFound, redirector } from '../index.js'
 
 // source: https://github.com/badges/shields/pull/1362#discussion_r161693830
 const statusCodes = {
@@ -79,4 +77,4 @@ const ShippableRedirect = redirector({
   dateAdded: new Date('2020-07-18'),
 })
 
-module.exports = { Shippable, ShippableRedirect }
+export { Shippable, ShippableRedirect }
diff --git a/services/shippable/shippable.tester.js b/services/shippable/shippable.tester.js
index 0290b2bd24b3a44b8a2563e220cf742f500e2db0..789a357b7d1e4297839394945924a553da2b004f 100644
--- a/services/shippable/shippable.tester.js
+++ b/services/shippable/shippable.tester.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
+import { isBuildStatus } from '../build-status.js'
+import { ServiceTester } from '../tester.js'
+export const t = new ServiceTester({
   id: 'Shippable',
   title: 'Shippable',
   pathPrefix: '/shippable',
-}))
+})
 
 t.create('build status (valid)')
   .get('/5444c5ecb904a4b21567b0ff/master.json')
diff --git a/services/snap-ci/snap-ci.service.js b/services/snap-ci/snap-ci.service.js
index 4b3cf224dc32537d10888afe8ae755287ac44f06..bf23bad848ac7271b3ff78d2a7a38c47c146714c 100644
--- a/services/snap-ci/snap-ci.service.js
+++ b/services/snap-ci/snap-ci.service.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { deprecatedService } = require('..')
+import { deprecatedService } from '../index.js'
 
 const commonAttrs = {
   category: 'build',
@@ -8,7 +6,7 @@ const commonAttrs = {
   dateAdded: new Date('2018-01-23'),
 }
 
-module.exports = [
+export default [
   deprecatedService({
     route: {
       base: 'snap',
diff --git a/services/snap-ci/snap-ci.tester.js b/services/snap-ci/snap-ci.tester.js
index fb9659ee3e17b55fbc6a21c733c6be5d52663bc4..3d8eb809aebecebe66917ffbb57d594d5ec5f203 100644
--- a/services/snap-ci/snap-ci.tester.js
+++ b/services/snap-ci/snap-ci.tester.js
@@ -1,9 +1,6 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = new ServiceTester({ id: 'snap-ci', title: 'Snap CI' })
-module.exports = t
+export const t = new ServiceTester({ id: 'snap-ci', title: 'Snap CI' })
 
 t.create('no longer available (previously build state)')
   .get('/snap-ci/ThoughtWorksStudios/eb_deployer/master.json')
diff --git a/services/snyk/snyk-test-helpers.js b/services/snyk/snyk-test-helpers.js
index 3fea094774e10a551cff16a21f56294ba668d2be..9f37e02ecdbe1cb8ed85f5e63a211f0b029577ce 100644
--- a/services/snyk/snyk-test-helpers.js
+++ b/services/snyk/snyk-test-helpers.js
@@ -1,11 +1,6 @@
-'use strict'
-
 const zeroVulnerabilitiesSvg =
   '<svg id="snyk-badge" data-package="undefined@undefined" width="152" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1" /><stop offset="1" stop-opacity=".1" /></linearGradient><mask id="a"><rect width="152" height="20" rx="3" fill="#fff" /></mask><g mask="url(#a)"><path fill="#555" d="M0 0h90v20H0z" /><path fill="#7B7B7B" d="M90 0h152v20H90z" /><path fill="url(#b)" d="M0 0h152v20H0z" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="45" y="15" fill="#010101" fill-opacity=".3">vulnerabilities</text><text x="45" y="14">vulnerabilities</text><text x="120" y="15" fill="#010101" fill-opacity=".3">0</text><text x="120" y="14">0</text></g></svg>'
 const twoVulnerabilitiesSvg =
   '<svg id="snyk-badge" data-package="undefined@undefined" width="152" height="20"><linearGradient id="b" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1" /><stop offset="1" stop-opacity=".1" /></linearGradient><mask id="a"><rect width="152" height="20" rx="3" fill="#fff" /></mask><g mask="url(#a)"><path fill="#555" d="M0 0h90v20H0z" /><path fill="#7B7B7B" d="M90 0h152v20H90z" /><path fill="url(#b)" d="M0 0h152v20H0z" /></g><g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11"><text x="45" y="15" fill="#010101" fill-opacity=".3">vulnerabilities</text><text x="45" y="14">vulnerabilities</text><text x="120" y="15" fill="#010101" fill-opacity=".3">2</text><text x="120" y="14">2</text></g></svg>'
 
-module.exports = {
-  zeroVulnerabilitiesSvg,
-  twoVulnerabilitiesSvg,
-}
+export { zeroVulnerabilitiesSvg, twoVulnerabilitiesSvg }
diff --git a/services/snyk/snyk-vulnerability-base.js b/services/snyk/snyk-vulnerability-base.js
index 4263c32b97034bf845e0b91700d12ada00783ca9..1316490a714453a5a37e2e832280f31f44d6afa7 100644
--- a/services/snyk/snyk-vulnerability-base.js
+++ b/services/snyk/snyk-vulnerability-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseSvgScrapingService } = require('..')
+import Joi from 'joi'
+import { BaseSvgScrapingService } from '../index.js'
 
 const schema = Joi.object({
   message: Joi.alternatives()
@@ -9,7 +7,7 @@ const schema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class SnykVulnerabilityBase extends BaseSvgScrapingService {
+export default class SnykVulnerabilityBase extends BaseSvgScrapingService {
   static category = 'analysis'
 
   static defaultBadgeData = {
diff --git a/services/snyk/snyk-vulnerability-github.service.js b/services/snyk/snyk-vulnerability-github.service.js
index 445004f5ff1fbfdfbc02572447410f75eb784873..fd187e7fbebce9aa67eec1deff37bdf74576c4f8 100644
--- a/services/snyk/snyk-vulnerability-github.service.js
+++ b/services/snyk/snyk-vulnerability-github.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import SynkVulnerabilityBase from './snyk-vulnerability-base.js'
 
-const SynkVulnerabilityBase = require('./snyk-vulnerability-base')
-
-module.exports = class SnykVulnerabilityGitHub extends SynkVulnerabilityBase {
+export default class SnykVulnerabilityGitHub extends SynkVulnerabilityBase {
   static route = {
     base: 'snyk/vulnerabilities/github',
     pattern: ':user/:repo/:manifestFilePath*',
diff --git a/services/snyk/snyk-vulnerability-github.tester.js b/services/snyk/snyk-vulnerability-github.tester.js
index 32326e9d313e5a20b8403e02b0acc80aae70d332..0601ef2710620cd3420fcfc3ca6568d81b5493b5 100644
--- a/services/snyk/snyk-vulnerability-github.tester.js
+++ b/services/snyk/snyk-vulnerability-github.tester.js
@@ -1,11 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const {
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import {
   twoVulnerabilitiesSvg,
   zeroVulnerabilitiesSvg,
-} = require('./snyk-test-helpers')
+} from './snyk-test-helpers.js'
+export const t = await createServiceTester()
 
 t.create('valid repo').get('/snyk/snyk.json').timeout(20000).expectBadge({
   label: 'vulnerabilities',
diff --git a/services/snyk/snyk-vulnerability-npm.service.js b/services/snyk/snyk-vulnerability-npm.service.js
index 2cbda0c68306fef62033684de3b12dfd39e64494..4e5f99db3e18f40fd9c7b9c8da65feb06a16c581 100644
--- a/services/snyk/snyk-vulnerability-npm.service.js
+++ b/services/snyk/snyk-vulnerability-npm.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { NotFound } from '../index.js'
+import SynkVulnerabilityBase from './snyk-vulnerability-base.js'
 
-const { NotFound } = require('..')
-const SynkVulnerabilityBase = require('./snyk-vulnerability-base')
-
-module.exports = class SnykVulnerabilityNpm extends SynkVulnerabilityBase {
+export default class SnykVulnerabilityNpm extends SynkVulnerabilityBase {
   static route = {
     base: 'snyk/vulnerabilities/npm',
     pattern: ':packageName(.+?)',
diff --git a/services/snyk/snyk-vulnerability-npm.tester.js b/services/snyk/snyk-vulnerability-npm.tester.js
index 859eaacfe82e1532109000342e23883ecdbabc77..5df48e99502e1aaa8e5cb7d24014ac2465c51a88 100644
--- a/services/snyk/snyk-vulnerability-npm.tester.js
+++ b/services/snyk/snyk-vulnerability-npm.tester.js
@@ -1,11 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const {
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import {
   twoVulnerabilitiesSvg,
   zeroVulnerabilitiesSvg,
-} = require('./snyk-test-helpers')
+} from './snyk-test-helpers.js'
+export const t = await createServiceTester()
 
 t.create('valid package latest version')
   .get('/commander.json')
diff --git a/services/sonar/sonar-base.js b/services/sonar/sonar-base.js
index 588be428ce2c8517115a1ad058d96617d72dd281..4e13f25e24d4fb2e4a05307b02cb0245dc6ebfd8 100644
--- a/services/sonar/sonar-base.js
+++ b/services/sonar/sonar-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService, NotFound } = require('..')
-const { isLegacyVersion } = require('./sonar-helpers')
+import Joi from 'joi'
+import { BaseJsonService, NotFound } from '../index.js'
+import { isLegacyVersion } from './sonar-helpers.js'
 
 // It is possible to see HTTP 404 response codes and HTTP 200 responses
 // with empty arrays of metric values, with both the legacy (pre v5.3) and modern APIs.
@@ -51,7 +49,7 @@ const legacySchema = Joi.array()
   )
   .required()
 
-module.exports = class SonarBase extends BaseJsonService {
+export default class SonarBase extends BaseJsonService {
   static auth = { userKey: 'sonarqube_token', serviceKey: 'sonar' }
 
   async fetch({ sonarVersion, server, component, metricName }) {
diff --git a/services/sonar/sonar-coverage.service.js b/services/sonar/sonar-coverage.service.js
index df4edeb9bc18fbfde1a93d25f2888881119211a5..ca71ab8264bc5e7482a2744e5b28713d24a9d7fa 100644
--- a/services/sonar/sonar-coverage.service.js
+++ b/services/sonar/sonar-coverage.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { coveragePercentage } from '../color-formatters.js'
+import SonarBase from './sonar-base.js'
+import { documentation, keywords, queryParamSchema } from './sonar-helpers.js'
 
-const { coveragePercentage } = require('../color-formatters')
-const SonarBase = require('./sonar-base')
-const { documentation, keywords, queryParamSchema } = require('./sonar-helpers')
-
-module.exports = class SonarCoverage extends SonarBase {
+export default class SonarCoverage extends SonarBase {
   static category = 'coverage'
 
   static route = {
diff --git a/services/sonar/sonar-coverage.tester.js b/services/sonar/sonar-coverage.tester.js
index feb31425c22febd0f86452b48ebc201d87e5f92e..6a03fa2171d4db036764d47c067d974c5495b334 100644
--- a/services/sonar/sonar-coverage.tester.js
+++ b/services/sonar/sonar-coverage.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isIntegerPercentage } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isIntegerPercentage } from '../test-validators.js'
+export const t = await createServiceTester()
 
 // The service tests targeting the legacy SonarQube API are mocked
 // because of the lack of publicly accessible, self-hosted, legacy SonarQube instances
diff --git a/services/sonar/sonar-documented-api-density.service.js b/services/sonar/sonar-documented-api-density.service.js
index 684152f5d654fa4f27b1740e72dd6e5a57fdf06a..9c605f94beb5a64626413189f09a95dc58a3fb3e 100644
--- a/services/sonar/sonar-documented-api-density.service.js
+++ b/services/sonar/sonar-documented-api-density.service.js
@@ -1,17 +1,15 @@
-'use strict'
-
-const SonarBase = require('./sonar-base')
-const {
+import SonarBase from './sonar-base.js'
+import {
   queryParamSchema,
   getLabel,
   positiveMetricColorScale,
   keywords,
   documentation,
-} = require('./sonar-helpers')
+} from './sonar-helpers.js'
 
 const metric = 'public_documented_api_density'
 
-module.exports = class SonarDocumentedApiDensity extends SonarBase {
+export default class SonarDocumentedApiDensity extends SonarBase {
   static category = 'analysis'
 
   static route = {
diff --git a/services/sonar/sonar-documented-api-density.spec.js b/services/sonar/sonar-documented-api-density.spec.js
index f2dc4821d210111a9ee51145a6d34e62a8391068..a5ca4fe55267b47ffea139210b391d6fff2ecb72 100644
--- a/services/sonar/sonar-documented-api-density.spec.js
+++ b/services/sonar/sonar-documented-api-density.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const SonarDocumentedApiDensity = require('./sonar-documented-api-density.service')
+import { test, given } from 'sazerac'
+import SonarDocumentedApiDensity from './sonar-documented-api-density.service.js'
 
 describe('SonarDocumentedApiDensity', function () {
   test(SonarDocumentedApiDensity.render, () => {
diff --git a/services/sonar/sonar-documented-api-density.tester.js b/services/sonar/sonar-documented-api-density.tester.js
index b879d6f5b10b0c830cf90739f33e6d951ddc5d99..d1fad44e3b8c1f52c04ab82015764ceeb298eccb 100644
--- a/services/sonar/sonar-documented-api-density.tester.js
+++ b/services/sonar/sonar-documented-api-density.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // The service tests targeting the legacy SonarQube API are mocked
 // because of the lack of publicly accessible, self-hosted, legacy SonarQube instances
diff --git a/services/sonar/sonar-fortify-rating.service.js b/services/sonar/sonar-fortify-rating.service.js
index 74cf396fb24ecdc988b5aefe35b654fb13481914..2e375c18f034523323855f6fc5d9bd55e10f6016 100644
--- a/services/sonar/sonar-fortify-rating.service.js
+++ b/services/sonar/sonar-fortify-rating.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const SonarBase = require('./sonar-base')
-const { queryParamSchema, keywords, documentation } = require('./sonar-helpers')
+import SonarBase from './sonar-base.js'
+import { queryParamSchema, keywords, documentation } from './sonar-helpers.js'
 
 const colorMap = {
   0: 'red',
@@ -12,7 +10,7 @@ const colorMap = {
   5: 'brightgreen',
 }
 
-module.exports = class SonarFortifyRating extends SonarBase {
+export default class SonarFortifyRating extends SonarBase {
   static category = 'analysis'
 
   static route = {
diff --git a/services/sonar/sonar-fortify-rating.spec.js b/services/sonar/sonar-fortify-rating.spec.js
index 2121c484f55a05470f6fd296f4c804cff03ffea9..ba5869b0dc88ebd50412e36db2e90f63ddcc2aed 100644
--- a/services/sonar/sonar-fortify-rating.spec.js
+++ b/services/sonar/sonar-fortify-rating.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const SonarFortifyRating = require('./sonar-fortify-rating.service')
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import SonarFortifyRating from './sonar-fortify-rating.service.js'
 
 const token = 'abc123def456'
 const config = {
diff --git a/services/sonar/sonar-fortify-rating.tester.js b/services/sonar/sonar-fortify-rating.tester.js
index 760ba28d09f59cab05c671f24a25834d73a02c03..c6efb951777e9b665ee9e857fb3239d9e166ac34 100644
--- a/services/sonar/sonar-fortify-rating.tester.js
+++ b/services/sonar/sonar-fortify-rating.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // The service tests targeting the legacy SonarQube API are mocked
 // because of the lack of publicly accessible, self-hosted, legacy SonarQube instances
diff --git a/services/sonar/sonar-generic.service.js b/services/sonar/sonar-generic.service.js
index 6b8498675497db5b663e402ad1b0be577f939ca5..adc6bcd6af36c7b82a447b20444419368fb4beb3 100644
--- a/services/sonar/sonar-generic.service.js
+++ b/services/sonar/sonar-generic.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { metric } = require('../text-formatters')
-const SonarBase = require('./sonar-base')
-const { queryParamSchema, getLabel } = require('./sonar-helpers')
+import { metric } from '../text-formatters.js'
+import SonarBase from './sonar-base.js'
+import { queryParamSchema, getLabel } from './sonar-helpers.js'
 
 // This service is intended to be a temporary solution to avoid breaking
 // any existing users/badges that were utilizing the "other" Sonar metrics
@@ -106,7 +104,7 @@ const metricNames = [
 ]
 const metricNameRouteParam = metricNames.join('|')
 
-module.exports = class SonarGeneric extends SonarBase {
+export default class SonarGeneric extends SonarBase {
   static category = 'analysis'
 
   static route = {
diff --git a/services/sonar/sonar-generic.tester.js b/services/sonar/sonar-generic.tester.js
index 3d5bfffd52834d31759b7fef8cfd2ee86231e641..2c175982227608076a6bbe227ce0c35af5d98c51 100644
--- a/services/sonar/sonar-generic.tester.js
+++ b/services/sonar/sonar-generic.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Security Rating')
   .timeout(10000)
diff --git a/services/sonar/sonar-helpers.js b/services/sonar/sonar-helpers.js
index e5764304ead5c4c6e15f7035ebf0adf16b3a1f30..c5e49b27289527b5edff7764f36c909a49d2e7e8 100644
--- a/services/sonar/sonar-helpers.js
+++ b/services/sonar/sonar-helpers.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { colorScale } = require('../color-formatters')
-const { optionalUrl } = require('../validators')
+import Joi from 'joi'
+import { colorScale } from '../color-formatters.js'
+import { optionalUrl } from '../validators.js'
 
 const ratingPercentageScaleSteps = [10, 20, 50, 100]
 const ratingScaleColors = [
@@ -60,7 +58,7 @@ const documentation = `
   </p
 `
 
-module.exports = {
+export {
   getLabel,
   isLegacyVersion,
   queryParamSchema,
diff --git a/services/sonar/sonar-quality-gate.service.js b/services/sonar/sonar-quality-gate.service.js
index b615c5d5f20b557894ac1ab44c2ef0aafb6c95a8..d2b8a31f0fb9639ce0e949c044e3a0a4f1fb501e 100644
--- a/services/sonar/sonar-quality-gate.service.js
+++ b/services/sonar/sonar-quality-gate.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import SonarBase from './sonar-base.js'
+import { documentation, keywords, queryParamSchema } from './sonar-helpers.js'
 
-const SonarBase = require('./sonar-base')
-const { documentation, keywords, queryParamSchema } = require('./sonar-helpers')
-
-module.exports = class SonarQualityGate extends SonarBase {
+export default class SonarQualityGate extends SonarBase {
   static category = 'analysis'
 
   static route = {
diff --git a/services/sonar/sonar-quality-gate.spec.js b/services/sonar/sonar-quality-gate.spec.js
index a7da68177b2cfb007f324c7243ca7362c3cfded6..aa694ae066ba4f83eaaea6a40e0c5ba855b12378 100644
--- a/services/sonar/sonar-quality-gate.spec.js
+++ b/services/sonar/sonar-quality-gate.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const SonarQualityGate = require('./sonar-quality-gate.service')
+import { test, given } from 'sazerac'
+import SonarQualityGate from './sonar-quality-gate.service.js'
 
 describe('SonarQualityGate', function () {
   test(SonarQualityGate.render, () => {
diff --git a/services/sonar/sonar-quality-gate.tester.js b/services/sonar/sonar-quality-gate.tester.js
index 518ce9451ba18b433304b9bd00b74043c143557b..39975ad07f270d62091424ebf5e5340b58612d63 100644
--- a/services/sonar/sonar-quality-gate.tester.js
+++ b/services/sonar/sonar-quality-gate.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isQualityGateStatus = Joi.allow('passed', 'failed')
 
diff --git a/services/sonar/sonar-redirector.service.js b/services/sonar/sonar-redirector.service.js
index 8698721eb9e0ac7d45040e911bcb930ac826b869..f5289608c68a65ddc4f6b70f671d8949dd1cc179 100644
--- a/services/sonar/sonar-redirector.service.js
+++ b/services/sonar/sonar-redirector.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   redirector({
     name: 'SonarVersionPrefixRedirector',
     category: 'analysis',
diff --git a/services/sonar/sonar-redirector.tester.js b/services/sonar/sonar-redirector.tester.js
index 7d80d667d5e2eccd392ab08ed4138c63f2d3556a..286d92be7a2dfb456402f0272057ef2036c76d33 100644
--- a/services/sonar/sonar-redirector.tester.js
+++ b/services/sonar/sonar-redirector.tester.js
@@ -1,13 +1,11 @@
-'use strict'
+import queryString from 'querystring'
+import { ServiceTester } from '../tester.js'
 
-const queryString = require('querystring')
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'SonarRedirect',
   title: 'SonarRedirect',
   pathPrefix: '/sonar',
-}))
+})
 
 t.create('sonar version')
   .get(
diff --git a/services/sonar/sonar-tech-debt.service.js b/services/sonar/sonar-tech-debt.service.js
index a54952cbb0800ac3d941e4bb022e1b2c82c959f2..b8c1de4cd25ed7829a6e2e508c47cff2ca59115c 100644
--- a/services/sonar/sonar-tech-debt.service.js
+++ b/services/sonar/sonar-tech-debt.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const SonarBase = require('./sonar-base')
-const {
+import SonarBase from './sonar-base.js'
+import {
   negativeMetricColorScale,
   getLabel,
   documentation,
   keywords,
   queryParamSchema,
-} = require('./sonar-helpers')
+} from './sonar-helpers.js'
 
-module.exports = class SonarTechDebt extends SonarBase {
+export default class SonarTechDebt extends SonarBase {
   static category = 'analysis'
 
   static route = {
diff --git a/services/sonar/sonar-tech-debt.spec.js b/services/sonar/sonar-tech-debt.spec.js
index b5c8678e6226a61a0363fb6989db70b79939b1d3..b6ef2009205bd4702e33df704ec5947aecb7eaad 100644
--- a/services/sonar/sonar-tech-debt.spec.js
+++ b/services/sonar/sonar-tech-debt.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const SonarTechDebt = require('./sonar-tech-debt.service')
+import { test, given } from 'sazerac'
+import SonarTechDebt from './sonar-tech-debt.service.js'
 
 describe('SonarTechDebt', function () {
   test(SonarTechDebt.render, () => {
diff --git a/services/sonar/sonar-tech-debt.tester.js b/services/sonar/sonar-tech-debt.tester.js
index 651bc43c8ea23535b9e462ea08c58e97cb091839..f9137fe570a872b1f729ba731249dcf7ba4427c4 100644
--- a/services/sonar/sonar-tech-debt.tester.js
+++ b/services/sonar/sonar-tech-debt.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // The service tests targeting the legacy SonarQube API are mocked
 // because of the lack of publicly accessible, self-hosted, legacy SonarQube instances
diff --git a/services/sonar/sonar-tests.service.js b/services/sonar/sonar-tests.service.js
index 67d12260371055256a651f76a4007680eacae9de..ec10994ba3f7ecfa24a9f5c1624a6f84e460164b 100644
--- a/services/sonar/sonar-tests.service.js
+++ b/services/sonar/sonar-tests.service.js
@@ -1,18 +1,16 @@
-'use strict'
-
-const {
+import {
   testResultQueryParamSchema,
   renderTestResultBadge,
-  documentation: testResultsDocumentation,
-} = require('../test-results')
-const { metric: metricCount } = require('../text-formatters')
-const SonarBase = require('./sonar-base')
-const {
+  documentation as testResultsDocumentation,
+} from '../test-results.js'
+import { metric as metricCount } from '../text-formatters.js'
+import SonarBase from './sonar-base.js'
+import {
   documentation,
   keywords,
   queryParamSchema,
   getLabel,
-} = require('./sonar-helpers')
+} from './sonar-helpers.js'
 
 class SonarTestsSummary extends SonarBase {
   static category = 'build'
@@ -241,4 +239,4 @@ class SonarTests extends SonarBase {
   }
 }
 
-module.exports = [SonarTestsSummary, SonarTests]
+export { SonarTestsSummary, SonarTests }
diff --git a/services/sonar/sonar-tests.spec.js b/services/sonar/sonar-tests.spec.js
index f16dc6137a3326c7f49a65070d26e792c382c8cb..81909602e18d316102c370f79c382067aedd6c47 100644
--- a/services/sonar/sonar-tests.spec.js
+++ b/services/sonar/sonar-tests.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const SonarTests = require('./sonar-tests.service')[1]
+import { test, given } from 'sazerac'
+import { SonarTests } from './sonar-tests.service.js'
 
 describe('SonarTests', function () {
   test(SonarTests.render, () => {
diff --git a/services/sonar/sonar-tests.tester.js b/services/sonar/sonar-tests.tester.js
index 2b66bd9296f271c6e58ee14e6509a78b80592b17..86f26d68a576f0e3fc6d4f2c87553fd3ed79ebaa 100644
--- a/services/sonar/sonar-tests.tester.js
+++ b/services/sonar/sonar-tests.tester.js
@@ -1,19 +1,18 @@
-'use strict'
-
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-const t = (module.exports = new ServiceTester({
-  id: 'SonarTests',
-  title: 'SonarTests',
-  pathPrefix: '/sonar',
-}))
-const {
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
+import {
   isDefaultTestTotals,
   isDefaultCompactTestTotals,
   isCustomTestTotals,
   isCustomCompactTestTotals,
-} = require('../test-validators')
-const { isIntegerPercentage, isMetric } = require('../test-validators')
+  isIntegerPercentage,
+  isMetric,
+} from '../test-validators.js'
+export const t = new ServiceTester({
+  id: 'SonarTests',
+  title: 'SonarTests',
+  pathPrefix: '/sonar',
+})
 const isMetricAllowZero = Joi.alternatives(
   isMetric,
   Joi.number().valid(0).required()
diff --git a/services/sonar/sonar-violations.service.js b/services/sonar/sonar-violations.service.js
index 54de34b9bf5b6e5299bbd82e92358383434a6445..e82364bb9e18401e0a0664466508db27d5c2ca62 100644
--- a/services/sonar/sonar-violations.service.js
+++ b/services/sonar/sonar-violations.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const { colorScale } = require('../color-formatters')
-const { metric } = require('../text-formatters')
-const SonarBase = require('./sonar-base')
-const {
+import { colorScale } from '../color-formatters.js'
+import { metric } from '../text-formatters.js'
+import SonarBase from './sonar-base.js'
+import {
   getLabel,
   documentation,
   keywords,
   queryParamWithFormatSchema,
-} = require('./sonar-helpers')
+} from './sonar-helpers.js'
 
 const violationsColorScale = colorScale(
   [1, 2, 3, 5],
@@ -23,7 +21,7 @@ const violationCategoryColorMap = {
   info_violations: 'green',
 }
 
-module.exports = class SonarViolations extends SonarBase {
+export default class SonarViolations extends SonarBase {
   static category = 'analysis'
 
   static route = {
diff --git a/services/sonar/sonar-violations.spec.js b/services/sonar/sonar-violations.spec.js
index 3509ac0fd33bc4e7d39724c4ab6df8f4ba01437f..08aa8279125a95cbd7cedebd8fda69137e73c6eb 100644
--- a/services/sonar/sonar-violations.spec.js
+++ b/services/sonar/sonar-violations.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { metric } = require('../text-formatters')
-const SonarViolations = require('./sonar-violations.service')
+import { test, given } from 'sazerac'
+import { metric } from '../text-formatters.js'
+import SonarViolations from './sonar-violations.service.js'
 
 describe('SonarViolations', function () {
   test(SonarViolations.render, () => {
diff --git a/services/sonar/sonar-violations.tester.js b/services/sonar/sonar-violations.tester.js
index f5c8095c2e35edb0983d9d3e721163c44170f38e..b757df1712bec79cbed3cb3876a68a29b2183166 100644
--- a/services/sonar/sonar-violations.tester.js
+++ b/services/sonar/sonar-violations.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isMetric, withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isMetric, withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 const isViolationsLongFormMetric = Joi.alternatives(
   Joi.allow(0),
   withRegex(
diff --git a/services/sourceforge/sourceforge-open-tickets.service.js b/services/sourceforge/sourceforge-open-tickets.service.js
index 6ad2cb4cee23184a124d9e3549441eb76b6a5dd9..7cf956105b830153243ff5d99c625dd1ae8c4350 100644
--- a/services/sourceforge/sourceforge-open-tickets.service.js
+++ b/services/sourceforge/sourceforge-open-tickets.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   count: nonNegativeInteger.required(),
 }).required()
 
-module.exports = class SourceforgeOpenTickets extends BaseJsonService {
+export default class SourceforgeOpenTickets extends BaseJsonService {
   static category = 'other'
 
   static route = {
diff --git a/services/sourceforge/sourceforge-open-tickets.tester.js b/services/sourceforge/sourceforge-open-tickets.tester.js
index 807a6c38e8bc32fe005e296478d4599e4eacc85f..4fa123e87b353ca4dccd2a2a6eb4d97938a85664 100644
--- a/services/sourceforge/sourceforge-open-tickets.tester.js
+++ b/services/sourceforge/sourceforge-open-tickets.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('bugs')
   .get('/sevenzip/bugs.json')
diff --git a/services/sourceforge/sourceforge.service.js b/services/sourceforge/sourceforge.service.js
index 674337c7287053a38558b1f23d12d4217454db8a..fb3ed63e604d607f99d1ad1f555d8bdeca8062b2 100644
--- a/services/sourceforge/sourceforge.service.js
+++ b/services/sourceforge/sourceforge.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const Joi = require('joi')
-const moment = require('moment')
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import moment from 'moment'
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   total: nonNegativeInteger,
@@ -31,7 +29,7 @@ const intervalMap = {
   },
 }
 
-module.exports = class Sourceforge extends BaseJsonService {
+export default class Sourceforge extends BaseJsonService {
   static category = 'downloads'
 
   static route = {
diff --git a/services/sourceforge/sourceforge.tester.js b/services/sourceforge/sourceforge.tester.js
index 6ccd13192dc9a476186636fd25fc32651f49eab8..e74de6f6fbf4d6cb5f6564b6f87efd519d3d77ea 100644
--- a/services/sourceforge/sourceforge.tester.js
+++ b/services/sourceforge/sourceforge.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric, isMetricOverTimePeriod } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric, isMetricOverTimePeriod } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('total downloads').get('/dt/sevenzip.json').expectBadge({
   label: 'downloads',
diff --git a/services/sourcegraph/sourcegraph.service.js b/services/sourcegraph/sourcegraph.service.js
index d2a218672d237de306bcaf9adf718c970a9209eb..054685d1b284bc312c208029400c4faae67a9e9a 100644
--- a/services/sourcegraph/sourcegraph.service.js
+++ b/services/sourcegraph/sourcegraph.service.js
@@ -1,14 +1,12 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const projectsCountRegex = /^\s[0-9]*(\.[0-9]k)?\sprojects$/
 const schema = Joi.object({
   value: Joi.string().regex(projectsCountRegex).required(),
 }).required()
 
-module.exports = class Sourcegraph extends BaseJsonService {
+export default class Sourcegraph extends BaseJsonService {
   static category = 'other'
 
   static route = {
diff --git a/services/sourcegraph/sourcegraph.tester.js b/services/sourcegraph/sourcegraph.tester.js
index 1f4bd9a2ee6c499c4db58c0529355a70026aafe2..4d1428674354e00aca67a4846ef9acae4506e926 100644
--- a/services/sourcegraph/sourcegraph.tester.js
+++ b/services/sourcegraph/sourcegraph.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // Matches API responses such as "0 projects", "1 projects", "182 projects", "14.0k projects".
 // There may be other cases not covered by this regex, but hopefully the tested projects won't vary much.
diff --git a/services/spack/spack.service.js b/services/spack/spack.service.js
index fd0ead60d6641dec429f415f83d0fcb26be229e2..54eb60bb7c67df1977cdd842bcd31d91523e2f3f 100644
--- a/services/spack/spack.service.js
+++ b/services/spack/spack.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('..//version')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '..//version.js'
+import { BaseJsonService } from '../index.js'
 const schema = Joi.object({
   latest_version: Joi.string().required(),
 }).required()
 
-module.exports = class SpackVersion extends BaseJsonService {
+export default class SpackVersion extends BaseJsonService {
   static category = 'version'
 
   static route = {
diff --git a/services/spack/spack.tester.js b/services/spack/spack.tester.js
index f72dd327272cb7554c2ac3b62f3119bed263fa09..6a9fe7d38ef14d0e4d3c6162537699d602278fe7 100644
--- a/services/spack/spack.tester.js
+++ b/services/spack/spack.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('version (valid)').get('/adios2.json').expectBadge({
   label: 'spack',
diff --git a/services/spiget/spiget-base.js b/services/spiget/spiget-base.js
index 9a434fe40b7d26bfe608444fc52d61901e816833..0dfb19af624dbbdf4b27eecdba243375aabe7e45 100644
--- a/services/spiget/spiget-base.js
+++ b/services/spiget/spiget-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const resourceSchema = Joi.object({
   downloads: Joi.number().required(),
@@ -36,4 +34,4 @@ class BaseSpigetService extends BaseJsonService {
   }
 }
 
-module.exports = { keywords, documentation, BaseSpigetService }
+export { keywords, documentation, BaseSpigetService }
diff --git a/services/spiget/spiget-download-size.service.js b/services/spiget/spiget-download-size.service.js
index 9f8c34fdff735884cd9dc33fb910cdd1a8e319a4..21966b8d291a7201ed82ffc91e1704eb291c6367 100644
--- a/services/spiget/spiget-download-size.service.js
+++ b/services/spiget/spiget-download-size.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseSpigetService, documentation, keywords } from './spiget-base.js'
 
-const { BaseSpigetService, documentation, keywords } = require('./spiget-base')
-
-module.exports = class SpigetDownloadSize extends BaseSpigetService {
+export default class SpigetDownloadSize extends BaseSpigetService {
   static category = 'size'
 
   static route = {
diff --git a/services/spiget/spiget-download-size.tester.js b/services/spiget/spiget-download-size.tester.js
index debdca96683c0e0b17b1887a1418de73c5c12f68..d1a1b20e1e93caa9223ba0d85075a515c01df0ef 100644
--- a/services/spiget/spiget-download-size.tester.js
+++ b/services/spiget/spiget-download-size.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isFileSize } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isFileSize } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('EssentialsX (id 9089)')
   .get('/9089.json')
diff --git a/services/spiget/spiget-downloads.service.js b/services/spiget/spiget-downloads.service.js
index 379e8fbe5987752d4ed4422fd9d4b7d0927e58b3..8a3a78a19c37257a2ad477add6c85d0bd498b4ea 100644
--- a/services/spiget/spiget-downloads.service.js
+++ b/services/spiget/spiget-downloads.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import { BaseSpigetService, documentation, keywords } from './spiget-base.js'
 
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const { BaseSpigetService, documentation, keywords } = require('./spiget-base')
-
-module.exports = class SpigetDownloads extends BaseSpigetService {
+export default class SpigetDownloads extends BaseSpigetService {
   static category = 'downloads'
 
   static route = {
diff --git a/services/spiget/spiget-downloads.tester.js b/services/spiget/spiget-downloads.tester.js
index e24e7f5d9f75d6a07d328309143559925da53e9f..7b372012b76441782072bfd581b5ee74c0478909 100644
--- a/services/spiget/spiget-downloads.tester.js
+++ b/services/spiget/spiget-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('EssentialsX (id 9089)').get('/9089.json').expectBadge({
   label: 'downloads',
diff --git a/services/spiget/spiget-latest-version.service.js b/services/spiget/spiget-latest-version.service.js
index 87dfbd75a51092ddcc1dd3ece859c18b3d0c55ed..321c03a7aab6b4ff5a227e71161103994e5a14dc 100644
--- a/services/spiget/spiget-latest-version.service.js
+++ b/services/spiget/spiget-latest-version.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseSpigetService, documentation, keywords } = require('./spiget-base')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseSpigetService, documentation, keywords } from './spiget-base.js'
 
 const versionSchema = Joi.object({
   downloads: Joi.number().required(),
   name: Joi.string().required(),
 }).required()
 
-module.exports = class SpigetLatestVersion extends BaseSpigetService {
+export default class SpigetLatestVersion extends BaseSpigetService {
   static category = 'version'
 
   static route = {
diff --git a/services/spiget/spiget-latest-version.tester.js b/services/spiget/spiget-latest-version.tester.js
index a14abc1aaabb7653cba64ab33304c1066bd009a7..bcc8f68fc9f38ef6db362d1d22d2ac84019203f8 100644
--- a/services/spiget/spiget-latest-version.tester.js
+++ b/services/spiget/spiget-latest-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // Note that Spigot versions can be anything (including just a string), so we'll make sure it's not returning 'not found'
 
diff --git a/services/spiget/spiget-rating.service.js b/services/spiget/spiget-rating.service.js
index 1a2962e39fb2a71a0955edc1ae4df9bfaea6b6b8..4d1a41b7c65c5261027a3f8fa248617c77b827b7 100644
--- a/services/spiget/spiget-rating.service.js
+++ b/services/spiget/spiget-rating.service.js
@@ -1,10 +1,8 @@
-'use strict'
+import { starRating, metric } from '../text-formatters.js'
+import { floorCount } from '../color-formatters.js'
+import { BaseSpigetService, documentation, keywords } from './spiget-base.js'
 
-const { starRating, metric } = require('../text-formatters')
-const { floorCount } = require('../color-formatters')
-const { BaseSpigetService, documentation, keywords } = require('./spiget-base')
-
-module.exports = class SpigetRatings extends BaseSpigetService {
+export default class SpigetRatings extends BaseSpigetService {
   static category = 'rating'
 
   static route = {
diff --git a/services/spiget/spiget-rating.tester.js b/services/spiget/spiget-rating.tester.js
index efe5a6b52dd815f5ce3115d23c21367585a85272..7d44add2e58d279fce9eec560059653a3742edbc 100644
--- a/services/spiget/spiget-rating.tester.js
+++ b/services/spiget/spiget-rating.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isStarRating, withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isStarRating, withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Stars - EssentialsX (id 9089)').get('/stars/9089.json').expectBadge({
   label: 'rating',
diff --git a/services/spiget/spiget-tested-versions.service.js b/services/spiget/spiget-tested-versions.service.js
index dbab6240309268333c1c7912823fd2689e57172b..725bf68f34079daed59222f7aa06dba718aa8752 100644
--- a/services/spiget/spiget-tested-versions.service.js
+++ b/services/spiget/spiget-tested-versions.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseSpigetService, documentation, keywords } from './spiget-base.js'
 
-const { BaseSpigetService, documentation, keywords } = require('./spiget-base')
-
-module.exports = class SpigetTestedVersions extends BaseSpigetService {
+export default class SpigetTestedVersions extends BaseSpigetService {
   static category = 'platform-support'
 
   static route = {
diff --git a/services/spiget/spiget-tested-versions.tester.js b/services/spiget/spiget-tested-versions.tester.js
index 8ab77790e4664144e872459c12dacbbbc8ec45db..723164f118912ea4ff1955fea68d1c67017c1859 100644
--- a/services/spiget/spiget-tested-versions.tester.js
+++ b/services/spiget/spiget-tested-versions.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const multipleVersions = withRegex(/^([+]?\d*\.\d+)(-)([+]?\d*\.\d+)$/)
 
diff --git a/services/stackexchange/stackexchange-helpers.js b/services/stackexchange/stackexchange-helpers.js
index edb85404beeef1647f8dbf608b65211e27f1ad01..e86c4064d0160dc46ca835acb80a01e327bfcbff 100644
--- a/services/stackexchange/stackexchange-helpers.js
+++ b/services/stackexchange/stackexchange-helpers.js
@@ -1,9 +1,7 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { floorCount as floorCountColor } from '../color-formatters.js'
 
-const { metric } = require('../text-formatters')
-const { floorCount: floorCountColor } = require('../color-formatters')
-
-module.exports = function renderQuestionsBadge({
+export default function renderQuestionsBadge({
   suffix,
   stackexchangesite,
   query,
diff --git a/services/stackexchange/stackexchange-monthlyquestions.service.js b/services/stackexchange/stackexchange-monthlyquestions.service.js
index 02e2f9f9c05995ecb155556d159b18b8c3b6a9d3..ff0143c63ddbc8f6af0a7a67e22e5fa1f90d468c 100644
--- a/services/stackexchange/stackexchange-monthlyquestions.service.js
+++ b/services/stackexchange/stackexchange-monthlyquestions.service.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const moment = require('moment')
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
-const renderQuestionsBadge = require('./stackexchange-helpers')
+import moment from 'moment'
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
+import renderQuestionsBadge from './stackexchange-helpers.js'
 
 const tagSchema = Joi.object({
   total: nonNegativeInteger,
 }).required()
 
-module.exports = class StackExchangeMonthlyQuestions extends BaseJsonService {
+export default class StackExchangeMonthlyQuestions extends BaseJsonService {
   static category = 'chat'
 
   static route = {
diff --git a/services/stackexchange/stackexchange-monthlyquestions.tester.js b/services/stackexchange/stackexchange-monthlyquestions.tester.js
index 88f8b16622c31645eac7268dab9810e29b21184e..4341b282fd2c87414134485a149822511711a6a2 100644
--- a/services/stackexchange/stackexchange-monthlyquestions.tester.js
+++ b/services/stackexchange/stackexchange-monthlyquestions.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetricOverTimePeriod } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetricOverTimePeriod } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Monthly Questions for StackOverflow Momentjs')
   .get('/stackoverflow/qm/momentjs.json')
diff --git a/services/stackexchange/stackexchange-reputation.service.js b/services/stackexchange/stackexchange-reputation.service.js
index fb0989b412f08b93b74ddc5b3febffbb82580627..ea8b7b36bbac2181aa6281d40561483b5c3ca1da 100644
--- a/services/stackexchange/stackexchange-reputation.service.js
+++ b/services/stackexchange/stackexchange-reputation.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { floorCount: floorCountColor } = require('../color-formatters')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { floorCount as floorCountColor } from '../color-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const reputationSchema = Joi.object({
   items: Joi.array()
@@ -16,7 +14,7 @@ const reputationSchema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class StackExchangeReputation extends BaseJsonService {
+export default class StackExchangeReputation extends BaseJsonService {
   static category = 'chat'
 
   static route = {
diff --git a/services/stackexchange/stackexchange-reputation.tester.js b/services/stackexchange/stackexchange-reputation.tester.js
index b6e3b4a7d4cff11078406326c024c4786b681acb..12c043f10c7f13f0f555540a7c0e255a11ba5b60 100644
--- a/services/stackexchange/stackexchange-reputation.tester.js
+++ b/services/stackexchange/stackexchange-reputation.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Invalid parameters')
   .get('/stackoverflow/r/invalidimage.json')
diff --git a/services/stackexchange/stackexchange-taginfo.service.js b/services/stackexchange/stackexchange-taginfo.service.js
index 72d6377d31ab3bec404d998a5dc143cedfd06649..af3d5d2557e46c0e44bad263dce7278737749b4d 100644
--- a/services/stackexchange/stackexchange-taginfo.service.js
+++ b/services/stackexchange/stackexchange-taginfo.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
-const renderQuestionsBadge = require('./stackexchange-helpers')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
+import renderQuestionsBadge from './stackexchange-helpers.js'
 
 const tagSchema = Joi.object({
   items: Joi.array()
@@ -15,7 +13,7 @@ const tagSchema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class StackExchangeQuestions extends BaseJsonService {
+export default class StackExchangeQuestions extends BaseJsonService {
   static category = 'chat'
 
   static route = {
diff --git a/services/stackexchange/stackexchange-taginfo.tester.js b/services/stackexchange/stackexchange-taginfo.tester.js
index e80b518ce3a0c2c3d6458ac789dea490764e77d0..9c615fb693a493c6e01359957f2cffcc7fd2b81c 100644
--- a/services/stackexchange/stackexchange-taginfo.tester.js
+++ b/services/stackexchange/stackexchange-taginfo.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isMetric } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isMetric } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('JavaScript Questions')
   .get('/stackoverflow/t/javascript.json')
diff --git a/services/static-badge/query-string-static.service.js b/services/static-badge/query-string-static.service.js
index 65afeeaa995e3e0e62d4f3e1e47f66ce97dc21d4..1555e55bcf77734c8afe393767a7368c80b96133 100644
--- a/services/static-badge/query-string-static.service.js
+++ b/services/static-badge/query-string-static.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseStaticService } = require('..')
+import Joi from 'joi'
+import { BaseStaticService } from '../index.js'
 
 const queryParamSchema = Joi.object({
   message: Joi.string().required(),
 }).required()
 
-module.exports = class QueryStringStaticBadge extends BaseStaticService {
+export default class QueryStringStaticBadge extends BaseStaticService {
   static category = 'static'
 
   static route = {
diff --git a/services/static-badge/query-string-static.tester.js b/services/static-badge/query-string-static.tester.js
index 2e1e7602a6bb88108549270a476838871ebb86ce..b6609c250521b7d0c48132081d52af957491b681 100644
--- a/services/static-badge/query-string-static.tester.js
+++ b/services/static-badge/query-string-static.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Missing message')
   .get('/static/v1.json?label=label&message=&color=blue')
diff --git a/services/static-badge/static-badge.service.js b/services/static-badge/static-badge.service.js
index 4ce76a780595e08579c4be86f4df288d46ac6cc3..0bcbe488e3b5f2684363987fed54e5ea56e878b2 100644
--- a/services/static-badge/static-badge.service.js
+++ b/services/static-badge/static-badge.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { escapeFormat } from '../../core/badge-urls/path-helpers.js'
+import { BaseStaticService } from '../index.js'
 
-const { escapeFormat } = require('../../core/badge-urls/path-helpers')
-const { BaseStaticService } = require('..')
-
-module.exports = class StaticBadge extends BaseStaticService {
+export default class StaticBadge extends BaseStaticService {
   static category = 'static'
 
   static route = {
diff --git a/services/static-badge/static-badge.tester.js b/services/static-badge/static-badge.tester.js
index ccbeccc14f33866ea0e8c7dfcbc30703ec261be3..dc0b0218c03486ef23b23bf96add6e14a6805c53 100644
--- a/services/static-badge/static-badge.tester.js
+++ b/services/static-badge/static-badge.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Shields colorscheme color')
   .get('/badge/label-message-blue.json')
diff --git a/services/steam/steam-base.js b/services/steam/steam-base.js
index 4c2951c4c90f80e59098ca04ab04ef143a14d7d4..9ea5cae989cdcf0860c0568451e0eb3db2258baf 100644
--- a/services/steam/steam-base.js
+++ b/services/steam/steam-base.js
@@ -1,9 +1,8 @@
-'use strict'
 /**
  * @module
  */
 
-const { BaseJsonService } = require('..')
+import { BaseJsonService } from '../index.js'
 
 /**
  * The steam api is based like /{interface}/{method}/v{version}/
@@ -54,4 +53,4 @@ class BaseSteamAPI extends BaseJsonService {
   }
 }
 
-module.exports = BaseSteamAPI
+export default BaseSteamAPI
diff --git a/services/steam/steam-workshop.service.js b/services/steam/steam-workshop.service.js
index cd10a7377385b0c893e2bff6673d6af672d9d7a6..23207eb80d9cf766d8e4dd5317942db779a9b5d7 100644
--- a/services/steam/steam-workshop.service.js
+++ b/services/steam/steam-workshop.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const Joi = require('joi')
-const prettyBytes = require('pretty-bytes')
-const { metric, formatDate } = require('../text-formatters')
-const { age: ageColor, downloadCount } = require('../color-formatters')
-const { NotFound } = require('..')
-const BaseSteamAPI = require('./steam-base')
+import Joi from 'joi'
+import prettyBytes from 'pretty-bytes'
+import { metric, formatDate } from '../text-formatters.js'
+import { age as ageColor, downloadCount } from '../color-formatters.js'
+import { NotFound } from '../index.js'
+import BaseSteamAPI from './steam-base.js'
 
 const documentation = `
 <p>
@@ -402,7 +400,7 @@ class SteamFileViews extends SteamFileService {
   }
 }
 
-module.exports = {
+export {
   SteamCollectionSize,
   SteamFileSize,
   SteamFileReleaseDate,
diff --git a/services/steam/steam-workshop.tester.js b/services/steam/steam-workshop.tester.js
index c2963e3828d3973803f04359d2735f1d8eaf0d87..05b424ac9d658adb97612d36961b5ec0ec37c4ae 100644
--- a/services/steam/steam-workshop.tester.js
+++ b/services/steam/steam-workshop.tester.js
@@ -1,10 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isMetric, isFileSize, isFormattedDate } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isMetric, isFileSize, isFormattedDate } = require('../test-validators')
-
-const t = new ServiceTester({ id: 'steam', title: 'Steam Workshop Tests' })
-module.exports = t
+export const t = new ServiceTester({
+  id: 'steam',
+  title: 'Steam Workshop Tests',
+})
 
 t.create('Collection Files')
   .get('/collection-files/180077636.json')
diff --git a/services/suggest.integration.js b/services/suggest.integration.js
index c000ebbb9c090a6a14cf0a751e15e148fca309cd..68efaafcaae4f7bcbc7a3ab999742a69d2a305db 100644
--- a/services/suggest.integration.js
+++ b/services/suggest.integration.js
@@ -1,19 +1,17 @@
-'use strict'
-
-const { expect } = require('chai')
-const Camp = require('@shields_io/camp')
-const portfinder = require('portfinder')
-const config = require('config').util.toObject()
-const got = require('../core/got-test-client')
-const { setRoutes } = require('./suggest')
-const GithubApiProvider = require('./github/github-api-provider')
+import { expect } from 'chai'
+import Camp from '@shields_io/camp'
+import portfinder from 'portfinder'
+import config from 'config'
+import got from '../core/got-test-client.js'
+import { setRoutes } from './suggest.js'
+import GithubApiProvider from './github/github-api-provider.js'
 
 describe('Badge suggestions for', function () {
   const githubApiBaseUrl = process.env.GITHUB_URL || 'https://api.github.com'
 
   let token, apiProvider
   before(function () {
-    token = config.private.gh_token
+    token = config.util.toObject().private.gh_token
     if (!token) {
       throw Error('The integration tests require a gh_token to be set')
     }
diff --git a/services/suggest.js b/services/suggest.js
index 432c0000019748695f19ad8b79e127e191fcad0a..ce23724f9a5d319e48acaa361ebbed763789202d 100644
--- a/services/suggest.js
+++ b/services/suggest.js
@@ -4,10 +4,8 @@
 //
 // This endpoint is called from frontend/components/suggestion-and-search.js.
 
-'use strict'
-
-const { URL } = require('url')
-const request = require('request')
+import { URL } from 'url'
+import request from 'request'
 
 function twitterPage(url) {
   if (url.protocol === null) {
@@ -200,8 +198,4 @@ function setRoutes(allowedOrigin, githubApiProvider, server) {
   })
 }
 
-module.exports = {
-  findSuggestions,
-  githubLicense,
-  setRoutes,
-}
+export { findSuggestions, githubLicense, setRoutes }
diff --git a/services/suggest.spec.js b/services/suggest.spec.js
index 0288dc801a46e6438c96ae32ddb5c1230502a8d5..3e2a9c8f495c11cd56be0222c1385bd9df2cbccb 100644
--- a/services/suggest.spec.js
+++ b/services/suggest.spec.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const Camp = require('@shields_io/camp')
-const { expect } = require('chai')
-const nock = require('nock')
-const portfinder = require('portfinder')
-const got = require('../core/got-test-client')
-const { setRoutes, githubLicense } = require('./suggest')
-const GithubApiProvider = require('./github/github-api-provider')
+import Camp from '@shields_io/camp'
+import { expect } from 'chai'
+import nock from 'nock'
+import portfinder from 'portfinder'
+import got from '../core/got-test-client.js'
+import { setRoutes, githubLicense } from './suggest.js'
+import GithubApiProvider from './github/github-api-provider.js'
 
 describe('Badge suggestions', function () {
   const githubApiBaseUrl = 'https://api.github.test'
diff --git a/services/swagger/swagger-redirect.service.js b/services/swagger/swagger-redirect.service.js
index 954bd131b03655fee89d740fbfb932ffa3e5ec50..091acf5c08c6f283a3223471d7fe8be92c3cab50 100644
--- a/services/swagger/swagger-redirect.service.js
+++ b/services/swagger/swagger-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   redirector({
     category: 'other',
     name: 'SwaggerRedirect',
diff --git a/services/swagger/swagger-redirect.tester.js b/services/swagger/swagger-redirect.tester.js
index 3fec29b7d6a9d6e9892180594f15bd2077a385c4..c4658882236c1e3613ff5a75e987037dd208f828 100644
--- a/services/swagger/swagger-redirect.tester.js
+++ b/services/swagger/swagger-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'SwaggerUrlRedirect',
   title: 'SwaggerUrlRedirect',
   pathPrefix: '/swagger/valid/2.0',
-}))
+})
 
 t.create('swagger json')
   .get('/https/example.com/example.svg')
diff --git a/services/swagger/swagger.service.js b/services/swagger/swagger.service.js
index 422768dd9977cbfc56fdfcee882e39f1f48343f9..be4127345553bd9b6c15c97b63f5d857180739fe 100644
--- a/services/swagger/swagger.service.js
+++ b/services/swagger/swagger.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const schema = Joi.object()
   .keys({
@@ -19,7 +17,7 @@ const queryParamSchema = Joi.object({
   specUrl: optionalUrl.required(),
 }).required()
 
-module.exports = class SwaggerValidatorService extends BaseJsonService {
+export default class SwaggerValidatorService extends BaseJsonService {
   static category = 'other'
 
   static route = {
diff --git a/services/swagger/swagger.tester.js b/services/swagger/swagger.tester.js
index 3f8749e46ff4ebd16fbd87784857bf1c6b1be9a4..6c154b6354223e4dabf9fa3b1c44928f53dc0b17 100644
--- a/services/swagger/swagger.tester.js
+++ b/services/swagger/swagger.tester.js
@@ -1,4 +1,4 @@
-'use strict'
+import { createServiceTester } from '../tester.js'
 
 const getURL = '/3.0.json?specUrl=https://example.com/example.json'
 const getURLBase = '/3.0.json?specUrl='
@@ -7,8 +7,7 @@ const apiGetURL = '/validator/debug'
 const apiGetQueryParams = {
   url: 'https://example.com/example.json',
 }
-
-const t = (module.exports = require('../tester').createServiceTester())
+export const t = await createServiceTester()
 
 t.create('Invalid')
   .get(getURL)
diff --git a/services/symfony/sensiolabs-redirect.service.js b/services/symfony/sensiolabs-redirect.service.js
index 35cdae90c4f13556b45e510abaeec13f598b441b..5196e02b8d4a76623c7ac4e948fefaba3c7c54a1 100644
--- a/services/symfony/sensiolabs-redirect.service.js
+++ b/services/symfony/sensiolabs-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   // The SymfonyInsight service was previously branded as SensioLabs, and
   // accordingly the badge path used to be /sensiolabs/i/projectUuid'.
   redirector({
diff --git a/services/symfony/sensiolabs-redirect.tester.js b/services/symfony/sensiolabs-redirect.tester.js
index b5c409a1af02438e2c32c742e97b7dd8eef9b2c4..fd10afb597236dad596a2a5d44ebba7cc62667e3 100644
--- a/services/symfony/sensiolabs-redirect.tester.js
+++ b/services/symfony/sensiolabs-redirect.tester.js
@@ -1,11 +1,9 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'sensiolabs',
   title: 'SensioLabs',
-}))
+})
 
 t.create('sensiolabs insight')
   .get('/i/825be328-29f8-44f7-a750-f82818ae9111.svg')
diff --git a/services/symfony/symfony-insight-base.js b/services/symfony/symfony-insight-base.js
index 4397492a2cc5f15e8e48afcfe296031b18122805..8cace75a89741201fda240d1f363010229f80b77 100644
--- a/services/symfony/symfony-insight-base.js
+++ b/services/symfony/symfony-insight-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseXmlService, NotFound } = require('..')
+import Joi from 'joi'
+import { BaseXmlService, NotFound } from '../index.js'
 
 const violationSchema = Joi.object({
   severity: Joi.equal('info', 'minor', 'major', 'critical').required(),
@@ -126,8 +124,4 @@ class SymfonyInsightBase extends BaseXmlService {
   }
 }
 
-module.exports = {
-  SymfonyInsightBase,
-  keywords,
-  gradeColors,
-}
+export { SymfonyInsightBase, keywords, gradeColors }
diff --git a/services/symfony/symfony-insight-base.spec.js b/services/symfony/symfony-insight-base.spec.js
index 19cc1cc41c561c2bec69d023cb970d1da6e42633..91af55d63539bb4e1f0331e324e6e289c0e5b760 100644
--- a/services/symfony/symfony-insight-base.spec.js
+++ b/services/symfony/symfony-insight-base.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { expect } = require('chai')
-const { NotFound } = require('..')
-const { SymfonyInsightBase } = require('./symfony-insight-base')
+import { expect } from 'chai'
+import { NotFound } from '../index.js'
+import { SymfonyInsightBase } from './symfony-insight-base.js'
 
 describe('SymfonyInsightBase', function () {
   context('transform()', function () {
diff --git a/services/symfony/symfony-insight-grade.service.js b/services/symfony/symfony-insight-grade.service.js
index 6c0a05594d30cb28b07d96a81f7e1fadf427919f..4e220915373a3b8cc967d26f43d21cdcc37d1b6e 100644
--- a/services/symfony/symfony-insight-grade.service.js
+++ b/services/symfony/symfony-insight-grade.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const {
+import {
   SymfonyInsightBase,
   keywords,
   gradeColors,
-} = require('./symfony-insight-base')
+} from './symfony-insight-base.js'
 
-module.exports = class SymfonyInsightGrade extends SymfonyInsightBase {
+export default class SymfonyInsightGrade extends SymfonyInsightBase {
   static route = {
     base: 'symfony/i/grade',
     pattern: ':projectUuid',
diff --git a/services/symfony/symfony-insight-grade.tester.js b/services/symfony/symfony-insight-grade.tester.js
index 4c0a741b823bfc8bdb7b3d4dd9f8ffb6ec247464..85d4be697c0bc840212bfee8258355df163d5c61 100644
--- a/services/symfony/symfony-insight-grade.tester.js
+++ b/services/symfony/symfony-insight-grade.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const { sampleProjectUuid, noSymfonyToken } = require('./symfony-test-helpers')
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import { sampleProjectUuid, noSymfonyToken } from './symfony-test-helpers.js'
+export const t = await createServiceTester()
 
 t.create('valid project grade')
   .skipWhen(noSymfonyToken)
diff --git a/services/symfony/symfony-insight-stars.service.js b/services/symfony/symfony-insight-stars.service.js
index 78cb0f94bc3342142f03446afc941beab42589e8..1665c255b8d6dffae970fa67292878cbfe1ac8a9 100644
--- a/services/symfony/symfony-insight-stars.service.js
+++ b/services/symfony/symfony-insight-stars.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { starRating } = require('../text-formatters')
-const {
+import { starRating } from '../text-formatters.js'
+import {
   SymfonyInsightBase,
   keywords,
   gradeColors,
-} = require('./symfony-insight-base')
+} from './symfony-insight-base.js'
 
 const gradeStars = {
   none: 0,
@@ -15,7 +13,7 @@ const gradeStars = {
   platinum: 4,
 }
 
-module.exports = class SymfonyInsightStars extends SymfonyInsightBase {
+export default class SymfonyInsightStars extends SymfonyInsightBase {
   static route = {
     base: 'symfony/i/stars',
     pattern: ':projectUuid',
diff --git a/services/symfony/symfony-insight-stars.tester.js b/services/symfony/symfony-insight-stars.tester.js
index 7bc4162ae7968a59a179af09e8c7491a90999a45..0370fb01f205586002d2b7f95c59e62af89be961 100644
--- a/services/symfony/symfony-insight-stars.tester.js
+++ b/services/symfony/symfony-insight-stars.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { withRegex } = require('../test-validators')
-const { sampleProjectUuid, noSymfonyToken } = require('./symfony-test-helpers')
+import { createServiceTester } from '../tester.js'
+import { withRegex } from '../test-validators.js'
+import { sampleProjectUuid, noSymfonyToken } from './symfony-test-helpers.js'
+export const t = await createServiceTester()
 
 t.create('valid project stars')
   .skipWhen(noSymfonyToken)
diff --git a/services/symfony/symfony-insight-violations.service.js b/services/symfony/symfony-insight-violations.service.js
index a00650865a4f200707907b8fc7a1596edeab699a..b620286b254c41b5fe07f79f028ae8c581fd19f0 100644
--- a/services/symfony/symfony-insight-violations.service.js
+++ b/services/symfony/symfony-insight-violations.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { SymfonyInsightBase, keywords } from './symfony-insight-base.js'
 
-const { SymfonyInsightBase, keywords } = require('./symfony-insight-base')
-
-module.exports = class SymfonyInsightViolations extends SymfonyInsightBase {
+export default class SymfonyInsightViolations extends SymfonyInsightBase {
   static route = {
     base: 'symfony/i/violations',
     pattern: ':projectUuid',
diff --git a/services/symfony/symfony-insight-violations.tester.js b/services/symfony/symfony-insight-violations.tester.js
index 5d2e0306dd819dcad2d082296e5d9b445833d3e3..f35a9bbc6376288264b2f5a42dca9f247455a813 100644
--- a/services/symfony/symfony-insight-violations.tester.js
+++ b/services/symfony/symfony-insight-violations.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { withRegex } = require('../test-validators')
-const { sampleProjectUuid, noSymfonyToken } = require('./symfony-test-helpers')
+import { createServiceTester } from '../tester.js'
+import { withRegex } from '../test-validators.js'
+import { sampleProjectUuid, noSymfonyToken } from './symfony-test-helpers.js'
+export const t = await createServiceTester()
 
 t.create('valid project violations')
   .skipWhen(noSymfonyToken)
diff --git a/services/symfony/symfony-insight.spec.js b/services/symfony/symfony-insight.spec.js
index d2c0b1032482977aa45015c880ce2afd0c3a7439..ea9855d96878beb07e549f9ec3cf201fb4f0a79d 100644
--- a/services/symfony/symfony-insight.spec.js
+++ b/services/symfony/symfony-insight.spec.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const SymfonyInsightGrade = require('./symfony-insight-grade.service')
-const SymfonyInsightStars = require('./symfony-insight-stars.service')
-const SymfonyInsightViolations = require('./symfony-insight-violations.service')
-const {
-  sampleProjectUuid: projectUuid,
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import SymfonyInsightGrade from './symfony-insight-grade.service.js'
+import SymfonyInsightStars from './symfony-insight-stars.service.js'
+import SymfonyInsightViolations from './symfony-insight-violations.service.js'
+import {
+  sampleProjectUuid as projectUuid,
   runningMockResponse,
   platinumMockResponse,
   goldMockResponse,
@@ -23,7 +21,7 @@ const {
   user,
   token,
   config,
-} = require('./symfony-test-helpers')
+} from './symfony-test-helpers.js'
 
 // These tests are organized in a fairly unusual way because the service uses
 // XML, so it's difficult to decouple the parsing from the transform + render.
diff --git a/services/symfony/symfony-test-helpers.js b/services/symfony/symfony-test-helpers.js
index 3652fddd7b0db3962a25b776e42c84c2ccc9e6e1..3b8e3f7f64bbb7a804f1e72626e627bd612609d4 100644
--- a/services/symfony/symfony-test-helpers.js
+++ b/services/symfony/symfony-test-helpers.js
@@ -1,4 +1,5 @@
-'use strict'
+import { noToken } from '../test-helpers.js'
+import { SymfonyInsightBase } from './symfony-insight-base.js'
 
 const sampleProjectUuid = '825be328-29f8-44f7-a750-f82818ae9111'
 
@@ -85,12 +86,9 @@ const config = {
     sl_insight_apiToken: token,
   },
 }
-
-const { noToken } = require('../test-helpers')
-const { SymfonyInsightBase } = require('./symfony-insight-base')
 const noSymfonyToken = noToken(SymfonyInsightBase)
 
-module.exports = {
+export {
   sampleProjectUuid,
   runningMockResponse,
   platinumMockResponse,
diff --git a/services/teamcity/teamcity-base.js b/services/teamcity/teamcity-base.js
index 4abbac669b731c23f7f09b5cfbd8f23d5846d48c..1e811a7aef5c6bc37b1a648b082d05d565a8596b 100644
--- a/services/teamcity/teamcity-base.js
+++ b/services/teamcity/teamcity-base.js
@@ -1,8 +1,6 @@
-'use strict'
+import { BaseJsonService } from '../index.js'
 
-const { BaseJsonService } = require('..')
-
-module.exports = class TeamCityBase extends BaseJsonService {
+export default class TeamCityBase extends BaseJsonService {
   static auth = {
     userKey: 'teamcity_user',
     passKey: 'teamcity_pass',
diff --git a/services/teamcity/teamcity-build-redirect.service.js b/services/teamcity/teamcity-build-redirect.service.js
index 09684097b3ba94bf69e5f48709ccc9e1c303c26a..bb63122228c5cda92b946d8e99380cf734ecea66 100644
--- a/services/teamcity/teamcity-build-redirect.service.js
+++ b/services/teamcity/teamcity-build-redirect.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const { redirector } = require('..')
+import { redirector } from '../index.js'
 
 const commonAttrs = {
   dateAdded: new Date('2019-09-15'),
   category: 'build',
 }
 
-module.exports = [
+export default [
   redirector({
     ...commonAttrs,
     name: 'TeamCityBuildLegacyCodeBetterRedirect',
diff --git a/services/teamcity/teamcity-build-redirect.tester.js b/services/teamcity/teamcity-build-redirect.tester.js
index fc1870445c79bbb82bf1067d4dbaaff3dd398c4d..c3f20425bbf247475f9389800071ffac92318c1b 100644
--- a/services/teamcity/teamcity-build-redirect.tester.js
+++ b/services/teamcity/teamcity-build-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'TeamCityBuildRedirect',
   title: 'TeamCityBuildRedirect',
   pathPrefix: '/teamcity',
-}))
+})
 
 t.create('codebetter')
   .get('/codebetter/IntelliJIdeaCe_JavaDecompilerEngineTests.svg')
diff --git a/services/teamcity/teamcity-build.service.js b/services/teamcity/teamcity-build.service.js
index b318decf7f897afb533b406be5c82ffe9e4c189a..bf90c10979a8f817f4b6b615b1fb9c22d994be61 100644
--- a/services/teamcity/teamcity-build.service.js
+++ b/services/teamcity/teamcity-build.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
-const TeamCityBase = require('./teamcity-base')
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
+import TeamCityBase from './teamcity-base.js'
 
 const buildStatusSchema = Joi.object({
   status: Joi.equal('SUCCESS', 'FAILURE', 'ERROR').required(),
@@ -13,7 +11,7 @@ const queryParamSchema = Joi.object({
   server: optionalUrl,
 }).required()
 
-module.exports = class TeamCityBuild extends TeamCityBase {
+export default class TeamCityBuild extends TeamCityBase {
   static category = 'build'
 
   static route = {
diff --git a/services/teamcity/teamcity-build.spec.js b/services/teamcity/teamcity-build.spec.js
index b19b6148801ddcdd2f2a787ddbc7149ec681398a..f81599a62e3b7fde1569908a8f5678762e428fc2 100644
--- a/services/teamcity/teamcity-build.spec.js
+++ b/services/teamcity/teamcity-build.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const TeamCityBuild = require('./teamcity-build.service')
-const { user, pass, host, config } = require('./teamcity-test-helpers')
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import TeamCityBuild from './teamcity-build.service.js'
+import { user, pass, host, config } from './teamcity-test-helpers.js'
 
 describe('TeamCityBuild', function () {
   cleanUpNockAfterEach()
diff --git a/services/teamcity/teamcity-build.tester.js b/services/teamcity/teamcity-build.tester.js
index da29069c4548280362a3b42dfb591eb0d4f4d4e8..3fcbb217e8b1ecdec1fcfa8a1346ba4736a29321 100644
--- a/services/teamcity/teamcity-build.tester.js
+++ b/services/teamcity/teamcity-build.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { withRegex } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { withRegex } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const buildStatusValues = Joi.equal('passing', 'failure', 'error').required()
 const buildStatusTextRegex =
diff --git a/services/teamcity/teamcity-coverage-redirect.service.js b/services/teamcity/teamcity-coverage-redirect.service.js
index d41c37dabc312287c1a77035312c18d03e11bbdc..5c989dea9e647e29755d6f684eb87edb86b81b8b 100644
--- a/services/teamcity/teamcity-coverage-redirect.service.js
+++ b/services/teamcity/teamcity-coverage-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   redirector({
     category: 'coverage',
     route: {
diff --git a/services/teamcity/teamcity-coverage-redirect.tester.js b/services/teamcity/teamcity-coverage-redirect.tester.js
index df0decb3912b7182c14ea66517b3ba2ea5cfd8ca..aeb6ce0068c27d55a97e7b7a347a560ebaf05c63 100644
--- a/services/teamcity/teamcity-coverage-redirect.tester.js
+++ b/services/teamcity/teamcity-coverage-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'TeamCityCoverageRedirect',
   title: 'TeamCityCoverageRedirect',
   pathPrefix: '/teamcity/coverage',
-}))
+})
 
 t.create('coverage')
   .get('/https/teamcity.jetbrains.com/ReactJSNet_PullRequests.svg')
diff --git a/services/teamcity/teamcity-coverage.service.js b/services/teamcity/teamcity-coverage.service.js
index cffb07ee3a1bc72b49946508e951be2e1e6d6f3d..8737da79e91c5174345c486e84731f19d5ae5b39 100644
--- a/services/teamcity/teamcity-coverage.service.js
+++ b/services/teamcity/teamcity-coverage.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { coveragePercentage } = require('../color-formatters')
-const { optionalUrl } = require('../validators')
-const { InvalidResponse } = require('..')
-const TeamCityBase = require('./teamcity-base')
+import Joi from 'joi'
+import { coveragePercentage } from '../color-formatters.js'
+import { optionalUrl } from '../validators.js'
+import { InvalidResponse } from '../index.js'
+import TeamCityBase from './teamcity-base.js'
 
 const buildStatisticsSchema = Joi.object({
   property: Joi.array()
@@ -21,7 +19,7 @@ const queryParamSchema = Joi.object({
   server: optionalUrl,
 }).required()
 
-module.exports = class TeamCityCoverage extends TeamCityBase {
+export default class TeamCityCoverage extends TeamCityBase {
   static category = 'coverage'
 
   static route = {
diff --git a/services/teamcity/teamcity-coverage.spec.js b/services/teamcity/teamcity-coverage.spec.js
index b6bcd35fb7a3e0ed9f657f21239e34c688a21508..f0fc578371af8cde6ebf4569c649cf518bb1c325 100644
--- a/services/teamcity/teamcity-coverage.spec.js
+++ b/services/teamcity/teamcity-coverage.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const TeamCityCoverage = require('./teamcity-coverage.service')
-const { user, pass, host, config } = require('./teamcity-test-helpers')
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import TeamCityCoverage from './teamcity-coverage.service.js'
+import { user, pass, host, config } from './teamcity-test-helpers.js'
 
 describe('TeamCityCoverage', function () {
   cleanUpNockAfterEach()
diff --git a/services/teamcity/teamcity-coverage.tester.js b/services/teamcity/teamcity-coverage.tester.js
index a259d150512ecbe446275268874f1b6ffeea7bde..7a0c0387baab761e1278ef6cb81b9d955ce51ea5 100644
--- a/services/teamcity/teamcity-coverage.tester.js
+++ b/services/teamcity/teamcity-coverage.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isIntegerPercentage } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isIntegerPercentage } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('invalid buildId')
   .get('/btABC999.json')
diff --git a/services/teamcity/teamcity-test-helpers.js b/services/teamcity/teamcity-test-helpers.js
index 21d7a8b3ad89c7f5b2fcb1d999022e1ca6c25414..655a16cbd94fb033b61d0ee571000e02dde7353c 100644
--- a/services/teamcity/teamcity-test-helpers.js
+++ b/services/teamcity/teamcity-test-helpers.js
@@ -1,5 +1,3 @@
-'use strict'
-
 const user = 'admin'
 const pass = 'password'
 const host = 'mycompany.teamcity.com'
@@ -17,9 +15,4 @@ const config = {
   },
 }
 
-module.exports = {
-  user,
-  pass,
-  host,
-  config,
-}
+export { user, pass, host, config }
diff --git a/services/test-helpers.js b/services/test-helpers.js
index cc3013135d4ac9ad048f3c262d580dedae53b30c..0896cf57d5935a15a9e3e88d2f45a4fdefa50ae8 100644
--- a/services/test-helpers.js
+++ b/services/test-helpers.js
@@ -1,9 +1,8 @@
-'use strict'
-
-const nock = require('nock')
-const request = require('request')
-const runnerConfig = require('config').util.toObject()
-const { promisify } = require('../core/base-service/legacy-request-handler')
+import nock from 'nock'
+import request from 'request'
+import config from 'config'
+import { promisify } from '../core/base-service/legacy-request-handler.js'
+const runnerConfig = config.util.toObject()
 
 function cleanUpNockAfterEach() {
   afterEach(function () {
@@ -36,9 +35,4 @@ const sendAndCacheRequest = promisify(request)
 
 const defaultContext = { sendAndCacheRequest }
 
-module.exports = {
-  cleanUpNockAfterEach,
-  noToken,
-  sendAndCacheRequest,
-  defaultContext,
-}
+export { cleanUpNockAfterEach, noToken, sendAndCacheRequest, defaultContext }
diff --git a/services/test-results.js b/services/test-results.js
index a46841939e65ac4cf0b98289e81261fc1bcb1a99..84f683176208786399986bb1fbc83c19bca98a6a 100644
--- a/services/test-results.js
+++ b/services/test-results.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const Joi = require('joi')
+import Joi from 'joi'
 
 const testResultQueryParamSchema = Joi.object({
   compact_message: Joi.equal(''),
@@ -106,7 +104,7 @@ const documentation = `
 </p>
 `
 
-module.exports = {
+export {
   testResultQueryParamSchema,
   renderTestResultMessage,
   renderTestResultBadge,
diff --git a/services/test-results.spec.js b/services/test-results.spec.js
index 5953f51954a31eba51faaad68988d9c91df47ba6..d9c337676092c7c294f42869c1e4868690ea2cb0 100644
--- a/services/test-results.spec.js
+++ b/services/test-results.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const {
+import { test, given } from 'sazerac'
+import {
   renderTestResultMessage,
   renderTestResultBadge,
-} = require('./test-results')
+} from './test-results.js'
 
 describe('Test result helpers', function () {
   function renderBothStyles(props) {
diff --git a/services/test-validators.js b/services/test-validators.js
index b6a30c2cb1e9db3029602a19af166a4ea52b6d8d..b20bf071ab304ec19433bdcbf396820f98d38f01 100644
--- a/services/test-validators.js
+++ b/services/test-validators.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { semver: isSemver } = require('./validators')
+import Joi from 'joi'
+import { semver as isSemver } from './validators.js'
 
 /*
   Note:
@@ -148,7 +146,7 @@ const isCustomCompactTestTotals = makeCompactTestTotalsValidator({
   skipped: '🤷',
 })
 
-module.exports = {
+export {
   isSemver,
   isVPlusTripleDottedVersion,
   isVPlusDottedVersionAtLeastOne,
diff --git a/services/tester.js b/services/tester.js
index c9d230b0f968ccc4cf3303812a7921af58b99161..1eead4670f29d099098fd14ce40da59ca0f0e07d 100644
--- a/services/tester.js
+++ b/services/tester.js
@@ -1,9 +1,4 @@
-'use strict'
+import createServiceTester from '../core/service-test-runner/create-service-tester.js'
+import ServiceTester from '../core/service-test-runner/service-tester.js'
 
-const createServiceTester = require('../core/service-test-runner/create-service-tester')
-const ServiceTester = require('../core/service-test-runner/service-tester')
-
-module.exports = {
-  createServiceTester,
-  ServiceTester,
-}
+export { createServiceTester, ServiceTester }
diff --git a/services/testspace/testspace-base.js b/services/testspace/testspace-base.js
index b35b929f95aebb20d109524ff69c46c0f1a70ca9..1bb0d209a7353e0ee681d5213a9fd0f431b42e95 100644
--- a/services/testspace/testspace-base.js
+++ b/services/testspace/testspace-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 // https://help.testspace.com/docs/reference/web-api#list-results
 // case_counts|array|The contained cases [passed, failed, na, errored]|counters of result
@@ -25,7 +23,7 @@ const schema = Joi.array()
 // Org is owner/account
 // Project is generally a repository
 // Space is a container, often a branch
-module.exports = class TestspaceBase extends BaseJsonService {
+export default class TestspaceBase extends BaseJsonService {
   static category = 'build'
   static defaultBadgeData = { label: 'tests' }
 
diff --git a/services/testspace/testspace-base.spec.js b/services/testspace/testspace-base.spec.js
index 7d46fa8e6c2ea4ccf320d3237eceb5832bc840d6..ff55a819653ce41aa9c836ecd43607cc6d2b6fb1 100644
--- a/services/testspace/testspace-base.spec.js
+++ b/services/testspace/testspace-base.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { expect } = require('chai')
-const { NotFound } = require('..')
-const TestspaceBase = require('./testspace-base')
+import { expect } from 'chai'
+import { NotFound } from '../index.js'
+import TestspaceBase from './testspace-base.js'
 
 describe('TestspaceBase', function () {
   it('throws NotFound when response is missing space results', function () {
diff --git a/services/testspace/testspace-test-count.service.js b/services/testspace/testspace-test-count.service.js
index 38a73558dcc3ad1f1876bb4e248bde7839ebb0fe..0a217254357b844648964c9ced9a03722d169ad7 100644
--- a/services/testspace/testspace-test-count.service.js
+++ b/services/testspace/testspace-test-count.service.js
@@ -1,9 +1,7 @@
-'use strict'
+import { metric as metricCount } from '../text-formatters.js'
+import TestspaceBase from './testspace-base.js'
 
-const { metric: metricCount } = require('../text-formatters')
-const TestspaceBase = require('./testspace-base')
-
-module.exports = class TestspaceTestCount extends TestspaceBase {
+export default class TestspaceTestCount extends TestspaceBase {
   static route = {
     base: 'testspace',
     pattern:
diff --git a/services/testspace/testspace-test-count.spec.js b/services/testspace/testspace-test-count.spec.js
index 9a03d3530ec39c84406a999773b38ddeb162a168..cb6b59b06e0fc66d81d79ba3df27f6d7c45329e1 100644
--- a/services/testspace/testspace-test-count.spec.js
+++ b/services/testspace/testspace-test-count.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const TestspaceTestCount = require('./testspace-test-count.service')
+import { test, given } from 'sazerac'
+import TestspaceTestCount from './testspace-test-count.service.js'
 
 describe('TestspaceTestCount', function () {
   test(TestspaceTestCount.render, () => {
diff --git a/services/testspace/testspace-test-count.tester.js b/services/testspace/testspace-test-count.tester.js
index b57fd9b25f010ce2c3ad7985afa1113d8140689a..2ca45d64860965b4c2291b73607d518bfcf058fb 100644
--- a/services/testspace/testspace-test-count.tester.js
+++ b/services/testspace/testspace-test-count.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const { isMetric } = require('../test-validators')
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+export const t = await createServiceTester()
 const isMetricAllowZero = Joi.alternatives(
   isMetric,
   Joi.number().valid(0).required()
diff --git a/services/testspace/testspace-test-pass-ratio.service.js b/services/testspace/testspace-test-pass-ratio.service.js
index dbe4526cfd5b682001d465a7178f849792ee2d08..ea78e7eaec6c9e608f66a5272d1d2e48c6a30c82 100644
--- a/services/testspace/testspace-test-pass-ratio.service.js
+++ b/services/testspace/testspace-test-pass-ratio.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import TestspaceBase from './testspace-base.js'
 
-const TestspaceBase = require('./testspace-base')
-
-module.exports = class TestspacePassRatio extends TestspaceBase {
+export default class TestspacePassRatio extends TestspaceBase {
   static route = {
     base: 'testspace/pass-ratio',
     pattern: ':org/:project/:space+',
diff --git a/services/testspace/testspace-test-pass-ratio.spec.js b/services/testspace/testspace-test-pass-ratio.spec.js
index 4cf4fe3cd2c491c0706bcb3bf2003045f783d8d9..1aed0d418955e40dfb5ae9927a85d103abb465c1 100644
--- a/services/testspace/testspace-test-pass-ratio.spec.js
+++ b/services/testspace/testspace-test-pass-ratio.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const TestspacePassRatio = require('./testspace-test-pass-ratio.service')
+import { test, given } from 'sazerac'
+import TestspacePassRatio from './testspace-test-pass-ratio.service.js'
 
 describe('TestspacePassRatio', function () {
   test(TestspacePassRatio.render, () => {
diff --git a/services/testspace/testspace-test-pass-ratio.tester.js b/services/testspace/testspace-test-pass-ratio.tester.js
index 42d81db75116160a042c28b320377ec27c0d5c1e..4d0de2d72abb066cade80047bd0a8d7240f25f21 100644
--- a/services/testspace/testspace-test-pass-ratio.tester.js
+++ b/services/testspace/testspace-test-pass-ratio.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isIntegerPercentage } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isIntegerPercentage } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('Non-existent or unauthorized org')
   .get('/swellaby1239017823123/swellaby:testspace-sample/main.json')
diff --git a/services/testspace/testspace-test-summary.service.js b/services/testspace/testspace-test-summary.service.js
index ca5fcd5aed33b9283a502f784b28bdb81f0aa3f3..f5176012a815b1a963a41fa68cfe2a0ac52d8dcb 100644
--- a/services/testspace/testspace-test-summary.service.js
+++ b/services/testspace/testspace-test-summary.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const {
+import {
   documentation,
   testResultQueryParamSchema,
   renderTestResultBadge,
-} = require('../test-results')
-const TestspaceBase = require('./testspace-base')
+} from '../test-results.js'
+import TestspaceBase from './testspace-base.js'
 
-module.exports = class TestspaceTests extends TestspaceBase {
+export default class TestspaceTests extends TestspaceBase {
   static route = {
     base: 'testspace/tests',
     pattern: ':org/:project/:space+',
diff --git a/services/testspace/testspace-test-summary.tester.js b/services/testspace/testspace-test-summary.tester.js
index aaebf6868d7ba74da4e271a904db24b7583c8903..2a4bc4ccf02a57505d6b4a5fafd5c0e1e8dd81a5 100644
--- a/services/testspace/testspace-test-summary.tester.js
+++ b/services/testspace/testspace-test-summary.tester.js
@@ -1,12 +1,11 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const {
+import { createServiceTester } from '../tester.js'
+import {
   isDefaultTestTotals,
   isDefaultCompactTestTotals,
   isCustomTestTotals,
   isCustomCompactTestTotals,
-} = require('../test-validators')
+} from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('Tests')
   .get('/swellaby/swellaby:testspace-sample/main.json')
diff --git a/services/text-formatters.js b/services/text-formatters.js
index 95cb600d4e3d088e3bddc49c0b8f1f85e64b9abd..50525fd6debdab7a76579364d7e3cc6e59447cf1 100644
--- a/services/text-formatters.js
+++ b/services/text-formatters.js
@@ -2,9 +2,7 @@
  * Commonly-used functions for formatting text in badge labels. Includes
  * ordinal numbers, currency codes, star ratings, versions, etc.
  */
-'use strict'
-
-const moment = require('moment')
+import moment from 'moment'
 moment().format()
 
 function starRating(rating, max = 5) {
@@ -124,7 +122,7 @@ function formatRelativeDate(timestamp) {
     .toLowerCase()
 }
 
-module.exports = {
+export {
   starRating,
   currencyFromCode,
   ordinalNumber,
diff --git a/services/text-formatters.spec.js b/services/text-formatters.spec.js
index a1b5d0ae048b8f3597becf21c5f39310ff29e6c5..efcfae4c15b96dd041cae07a7ac875935577e90c 100644
--- a/services/text-formatters.spec.js
+++ b/services/text-formatters.spec.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const sinon = require('sinon')
-const {
+import { test, given } from 'sazerac'
+import sinon from 'sinon'
+import {
   starRating,
   currencyFromCode,
   ordinalNumber,
@@ -12,7 +10,7 @@ const {
   maybePluralize,
   formatDate,
   formatRelativeDate,
-} = require('./text-formatters')
+} from './text-formatters.js'
 
 describe('Text formatters', function () {
   test(starRating, () => {
diff --git a/services/tokei/tokei.service.js b/services/tokei/tokei.service.js
index 97124289aee7c38b7916fc39b8e19e321b9882c6..dd01918b8d40494bd764420b8a0c53b881c0e7ae 100644
--- a/services/tokei/tokei.service.js
+++ b/services/tokei/tokei.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   lines: nonNegativeInteger,
@@ -26,7 +24,7 @@ const documentation = `
 </p>
 `
 
-module.exports = class Tokei extends BaseJsonService {
+export default class Tokei extends BaseJsonService {
   static category = 'size'
 
   static route = { base: 'tokei/lines', pattern: ':provider/:user/:repo' }
diff --git a/services/tokei/tokei.tester.js b/services/tokei/tokei.tester.js
index 0b310c8288ad2acf841cb3394eea23c24352e266..9671c7b58848b90685e3b8de9c697139bfc785b0 100644
--- a/services/tokei/tokei.tester.js
+++ b/services/tokei/tokei.tester.js
@@ -1,10 +1,7 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isMetric } = require('../test-validators')
-
-const t = new ServiceTester({ id: 'tokei', title: 'Tokei LOC Tests' })
-module.exports = t
+export const t = new ServiceTester({ id: 'tokei', title: 'Tokei LOC Tests' })
 
 t.create('GitHub LOC')
   .get('/lines/github/badges/shields.json')
diff --git a/services/travis/travis-build.service.js b/services/travis/travis-build.service.js
index b679ffcdfb59272d2eec27c4fb970cea59f72afc..2c52799588a4ca1d7049ef6b872b1e4d7eb7ff54 100644
--- a/services/travis/travis-build.service.js
+++ b/services/travis/travis-build.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { BaseSvgScrapingService } = require('..')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { BaseSvgScrapingService } from '../index.js'
 
 const schema = Joi.object({
   message: Joi.alternatives()
@@ -10,7 +8,7 @@ const schema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class TravisBuild extends BaseSvgScrapingService {
+export default class TravisBuild extends BaseSvgScrapingService {
   static category = 'build'
 
   static route = {
diff --git a/services/travis/travis-build.tester.js b/services/travis/travis-build.tester.js
index a7d6fcfef7e286621688cf2e131c8ddc443a7491..f6bd4df392f79dbd138605317b31512eccaf82df 100644
--- a/services/travis/travis-build.tester.js
+++ b/services/travis/travis-build.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // Travis (.org) CI
 
diff --git a/services/travis/travis-php-version-redirect.service.js b/services/travis/travis-php-version-redirect.service.js
index 3fc26b116d96e1571d8d038b72952fbe0ec8a19b..a61b4467fcff9566989799208faa4a6a9090d33b 100644
--- a/services/travis/travis-php-version-redirect.service.js
+++ b/services/travis/travis-php-version-redirect.service.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { redirector } = require('..')
+import { redirector } from '../index.js'
 
 const ciRedirect = redirector({
   category: 'platform-support',
@@ -25,4 +23,4 @@ const branchRedirect = redirector({
   dateAdded: new Date('2020-07-12'),
 })
 
-module.exports = { ciRedirect, branchRedirect }
+export { ciRedirect, branchRedirect }
diff --git a/services/travis/travis-php-version-redirect.tester.js b/services/travis/travis-php-version-redirect.tester.js
index adf9fb66695a7fe16d1e25b0253ad71984375891..4326a1175d3dc1fc6b5400c2cc28350eb284ee65 100644
--- a/services/travis/travis-php-version-redirect.tester.js
+++ b/services/travis/travis-php-version-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'TravisPhpVersionRedirect',
   title: 'TravisPhpVersionRedirect',
   pathPrefix: '/',
-}))
+})
 
 t.create('travis-ci no branch')
   .get('travis-ci/php-v/symfony/symfony.svg')
diff --git a/services/travis/travis-php-version.service.js b/services/travis/travis-php-version.service.js
index e11312cb6fe97655b0e10dcf73ebb9cffb8fe323..f8a29a39cd76d57cb19bf594abda9ab3055df1e7 100644
--- a/services/travis/travis-php-version.service.js
+++ b/services/travis/travis-php-version.service.js
@@ -1,12 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const {
+import Joi from 'joi'
+import {
   minorVersion,
   versionReduction,
   getPhpReleases,
-} = require('../php-version')
-const { BaseJsonService } = require('..')
+} from '../php-version.js'
+import { BaseJsonService } from '../index.js'
 
 const optionalNumberOrString = Joi.alternatives(Joi.string(), Joi.number())
 const schema = Joi.object({
@@ -23,7 +21,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class TravisPhpVersion extends BaseJsonService {
+export default class TravisPhpVersion extends BaseJsonService {
   static category = 'platform-support'
 
   static route = {
diff --git a/services/travis/travis-php-version.tester.js b/services/travis/travis-php-version.tester.js
index 4213a167b894d4baec7a04480066324c737a9302..16a23bd0c5183048bcd4cd02ac7eadb8e6335667 100644
--- a/services/travis/travis-php-version.tester.js
+++ b/services/travis/travis-php-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isPhpVersionReduction } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isPhpVersionReduction } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('gets the package version of symfony 5.1')
   .get('/symfony/symfony/5.1.json')
diff --git a/services/treeware/treeware-trees.service.js b/services/treeware/treeware-trees.service.js
index 3e276790323670ad9714fd46ed34f3e303e1aad9..1fcbc10125cfb3875367ae0d67e00bcbf2712922 100644
--- a/services/treeware/treeware-trees.service.js
+++ b/services/treeware/treeware-trees.service.js
@@ -1,16 +1,14 @@
-'use strict'
-
-const crypto = require('crypto')
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { floorCount } = require('../color-formatters')
-const { BaseJsonService } = require('..')
+import crypto from 'crypto'
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { floorCount } from '../color-formatters.js'
+import { BaseJsonService } from '../index.js'
 
 const apiSchema = Joi.object({
   total: Joi.number().required(),
 }).required()
 
-module.exports = class TreewareTrees extends BaseJsonService {
+export default class TreewareTrees extends BaseJsonService {
   static category = 'other'
 
   static route = {
diff --git a/services/treeware/treeware-trees.tester.js b/services/treeware/treeware-trees.tester.js
index bc2d1a84f473655edb7feb9259122b3f8a3521c1..07ada0cf8de39e17a06a21eed5c9a283ec8d00cc 100644
--- a/services/treeware/treeware-trees.tester.js
+++ b/services/treeware/treeware-trees.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isMetric } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('request for existing package')
   .get('/stoplightio/spectral.json')
diff --git a/services/twitch/twitch-base.js b/services/twitch/twitch-base.js
index b6526a50a3553344291af1ddcb6d038df5ced36f..85d4e6b08303f5c2dd72c32dc9315ab29b1f9308 100644
--- a/services/twitch/twitch-base.js
+++ b/services/twitch/twitch-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const tokenSchema = Joi.object({
   access_token: Joi.string().required(),
@@ -16,7 +14,7 @@ function sleep(ms) {
 }
 
 // Abstract class for Twitch badges
-module.exports = class TwitchBase extends BaseJsonService {
+export default class TwitchBase extends BaseJsonService {
   static auth = {
     userKey: 'twitch_client_id',
     passKey: 'twitch_client_secret',
diff --git a/services/twitch/twitch.service.js b/services/twitch/twitch.service.js
index 2bd3f53a320dca175eecde520f2369474c2fb514..402f7e52cc4590c7ebe9b21c84749f4b0849f788 100644
--- a/services/twitch/twitch.service.js
+++ b/services/twitch/twitch.service.js
@@ -1,13 +1,11 @@
-'use strict'
-
-const Joi = require('joi')
-const TwitchBase = require('./twitch-base')
+import Joi from 'joi'
+import TwitchBase from './twitch-base.js'
 
 const helixSchema = Joi.object({
   data: Joi.array().required(),
 })
 
-module.exports = class TwitchStatus extends TwitchBase {
+export default class TwitchStatus extends TwitchBase {
   static category = 'social'
 
   static route = {
diff --git a/services/twitch/twitch.spec.js b/services/twitch/twitch.spec.js
index 7573d5542795d503d51a580026a65fc6960ec845..c3ec31522eb66b7397c7461760ca75100a06eeba 100644
--- a/services/twitch/twitch.spec.js
+++ b/services/twitch/twitch.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const TwitchStatus = require('./twitch.service')
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import TwitchStatus from './twitch.service.js'
 
 describe('TwitchStatus', function () {
   describe('auth', function () {
diff --git a/services/twitch/twitch.tester.js b/services/twitch/twitch.tester.js
index 53f3f68f5904cd646c63a39badda9ed4ba905250..9f68a1d82caae2cb52fdefe5af036d796bbb807b 100644
--- a/services/twitch/twitch.tester.js
+++ b/services/twitch/twitch.tester.js
@@ -1,14 +1,13 @@
-'use strict'
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
+import { noToken } from '../test-helpers.js'
+import _noTwitchToken from './twitch.service.js'
+const noTwitchToken = noToken(_noTwitchToken)
 
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-const { noToken } = require('../test-helpers')
-const noTwitchToken = noToken(require('./twitch.service'))
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'twitch',
   title: 'Twitch',
-}))
+})
 
 // the first request would take longer since we need to wait for a token
 t.create('Status of andyonthewings')
diff --git a/services/twitter/twitter-redirect.service.js b/services/twitter/twitter-redirect.service.js
index b7cacce78661d2d06e66ea3a6655f0bf59d2722f..5291115dbdf43a93b7f9f6f2cdd4155be52635ae 100644
--- a/services/twitter/twitter-redirect.service.js
+++ b/services/twitter/twitter-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   redirector({
     category: 'social',
     name: 'TwitterUrlRedirect',
diff --git a/services/twitter/twitter-redirect.tester.js b/services/twitter/twitter-redirect.tester.js
index 84d0f9a2895c468467347ad548926091d02e8cdb..e777d9a5bee729c99f69605595cb0e245e0d7597 100644
--- a/services/twitter/twitter-redirect.tester.js
+++ b/services/twitter/twitter-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'TwitterUrlRedirect',
   title: 'TwitterUrlRedirect',
   pathPrefix: '/twitter/url',
-}))
+})
 
 t.create('twitter')
   .get('/https/shields.io.svg')
diff --git a/services/twitter/twitter.service.js b/services/twitter/twitter.service.js
index a46c82142149abd13113e04dc2d777494345f66b..2da76486a0846fec9912a25e3d549d8d85d1c189 100644
--- a/services/twitter/twitter.service.js
+++ b/services/twitter/twitter.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { optionalUrl } = require('../validators')
-const { BaseService, BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { optionalUrl } from '../validators.js'
+import { BaseService, BaseJsonService, NotFound } from '../index.js'
 
 const queryParamSchema = Joi.object({
   url: optionalUrl.required(),
@@ -115,4 +113,4 @@ class TwitterFollow extends BaseJsonService {
   }
 }
 
-module.exports = [TwitterUrl, TwitterFollow]
+export default [TwitterUrl, TwitterFollow]
diff --git a/services/twitter/twitter.tester.js b/services/twitter/twitter.tester.js
index 50941c9838176772638f9d906f6e3dfbedddc07a..e15b79f08f4ddb0ca86f147bf36c5a82b81da0e9 100644
--- a/services/twitter/twitter.tester.js
+++ b/services/twitter/twitter.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { isMetric } from '../test-validators.js'
+import { ServiceTester } from '../tester.js'
 
-const { isMetric } = require('../test-validators')
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'twitter',
   title: 'Twitter',
-}))
+})
 
 t.create('Followers')
   .get('/follow/shields_io.json')
diff --git a/services/ubuntu/ubuntu.service.js b/services/ubuntu/ubuntu.service.js
index c4c407da69262a33664952d854bd8194b7dd6f42..c584c95503edc9f3fd8de525339dc55c2066064a 100644
--- a/services/ubuntu/ubuntu.service.js
+++ b/services/ubuntu/ubuntu.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const schema = Joi.object({
   entries: Joi.array()
@@ -14,7 +12,7 @@ const schema = Joi.object({
     .required(),
 }).required()
 
-module.exports = class Ubuntu extends BaseJsonService {
+export default class Ubuntu extends BaseJsonService {
   static category = 'version'
 
   static route = {
diff --git a/services/ubuntu/ubuntu.tester.js b/services/ubuntu/ubuntu.tester.js
index a20217c7416411047f30401c4fea0b56093e9702..c622493075b08960b53d4028f23a858aa70d63ae 100644
--- a/services/ubuntu/ubuntu.tester.js
+++ b/services/ubuntu/ubuntu.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isUbuntuVersion = Joi.string().regex(
   /^v(\d+:)?\d+(\.\d+)*([\w\\.]*)?([-+~].*)?$/
diff --git a/services/uptimerobot/uptimerobot-base.js b/services/uptimerobot/uptimerobot-base.js
index d929863efd3f57d03cd0246e7eab30b6636e18ef..2afa607b9fa70aea0cf67c37eb39249feda79325 100644
--- a/services/uptimerobot/uptimerobot-base.js
+++ b/services/uptimerobot/uptimerobot-base.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService, InvalidParameter, InvalidResponse } = require('..')
+import Joi from 'joi'
+import { BaseJsonService, InvalidParameter, InvalidResponse } from '../index.js'
 
 // https://uptimerobot.com/api
 // POST getMonitors
@@ -38,7 +36,7 @@ const singleMonitorResponseWithUptime = Joi.alternatives(
   }).required()
 )
 
-module.exports = class UptimeRobotBase extends BaseJsonService {
+export default class UptimeRobotBase extends BaseJsonService {
   static category = 'monitoring'
 
   static ensureIsMonitorApiKey(value) {
diff --git a/services/uptimerobot/uptimerobot-ratio.service.js b/services/uptimerobot/uptimerobot-ratio.service.js
index ac7fb2bb16fbcf80d0031c3c697004603aea2d88..fa98e8ed1fd053b73fae87fdb14178d4dd0dfffe 100644
--- a/services/uptimerobot/uptimerobot-ratio.service.js
+++ b/services/uptimerobot/uptimerobot-ratio.service.js
@@ -1,11 +1,9 @@
-'use strict'
-
-const { colorScale } = require('../color-formatters')
-const UptimeRobotBase = require('./uptimerobot-base')
+import { colorScale } from '../color-formatters.js'
+import UptimeRobotBase from './uptimerobot-base.js'
 
 const ratioColor = colorScale([10, 30, 50, 70])
 
-module.exports = class UptimeRobotRatio extends UptimeRobotBase {
+export default class UptimeRobotRatio extends UptimeRobotBase {
   static route = {
     base: 'uptimerobot/ratio',
     pattern: ':numberOfDays(\\d+)?/:monitorSpecificKey',
diff --git a/services/uptimerobot/uptimerobot-ratio.tester.js b/services/uptimerobot/uptimerobot-ratio.tester.js
index 049fc9c05ac05c769a37b9a4f6f3a0bc130fbac4..db6b55c9da933bc2cb34ee6b0dd89c52e09d9e6e 100644
--- a/services/uptimerobot/uptimerobot-ratio.tester.js
+++ b/services/uptimerobot/uptimerobot-ratio.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const { isPercentage } = require('../test-validators')
-const { invalidJSON } = require('../response-fixtures')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isPercentage } from '../test-validators.js'
+import { invalidJSON } from '../response-fixtures.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Uptime Robot: Percentage (valid)')
   .get('/m778918918-3e92c097147760ee39d02d36.json')
diff --git a/services/uptimerobot/uptimerobot-status.service.js b/services/uptimerobot/uptimerobot-status.service.js
index c4b5614201d420a99da146b2d6f6397488b08c76..a468175c42b6257d29af4805b6d4ecce9beef167 100644
--- a/services/uptimerobot/uptimerobot-status.service.js
+++ b/services/uptimerobot/uptimerobot-status.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import UptimeRobotBase from './uptimerobot-base.js'
 
-const UptimeRobotBase = require('./uptimerobot-base')
-
-module.exports = class UptimeRobotStatus extends UptimeRobotBase {
+export default class UptimeRobotStatus extends UptimeRobotBase {
   static route = {
     base: 'uptimerobot/status',
     pattern: ':monitorSpecificKey',
diff --git a/services/uptimerobot/uptimerobot-status.tester.js b/services/uptimerobot/uptimerobot-status.tester.js
index 319d4c0456166ffae2832f04b3088ed48f6e910a..dca7e92554e3d0988f3d18b12587d36833c92cc0 100644
--- a/services/uptimerobot/uptimerobot-status.tester.js
+++ b/services/uptimerobot/uptimerobot-status.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { invalidJSON } = require('../response-fixtures')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { invalidJSON } from '../response-fixtures.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isUptimeStatus = Joi.string().valid(
   'paused',
diff --git a/services/vaadin-directory/vaadin-directory-base.js b/services/vaadin-directory/vaadin-directory-base.js
index fe05d0f1dd2aa98a7fae580943b00baa9dcf0a83..b567df2b3177e0714a4de80961fa3013e419de64 100644
--- a/services/vaadin-directory/vaadin-directory-base.js
+++ b/services/vaadin-directory/vaadin-directory-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   ratingCount: nonNegativeInteger,
@@ -29,4 +27,4 @@ class BaseVaadinDirectoryService extends BaseJsonService {
   }
 }
 
-module.exports = { BaseVaadinDirectoryService }
+export { BaseVaadinDirectoryService }
diff --git a/services/vaadin-directory/vaadin-directory-rating-count.service.js b/services/vaadin-directory/vaadin-directory-rating-count.service.js
index 56518f6c8db726e000511b12f3ef020c412bfbcb..e8af652c66d28f444949725a52e12ae08fb1361f 100644
--- a/services/vaadin-directory/vaadin-directory-rating-count.service.js
+++ b/services/vaadin-directory/vaadin-directory-rating-count.service.js
@@ -1,12 +1,8 @@
-'use strict'
+import { metric } from '../text-formatters.js'
+import { floorCount as floorCountColor } from '../color-formatters.js'
+import { BaseVaadinDirectoryService } from './vaadin-directory-base.js'
 
-const { metric } = require('../text-formatters')
-const { floorCount: floorCountColor } = require('../color-formatters')
-const { BaseVaadinDirectoryService } = require('./vaadin-directory-base')
-
-module.exports = class VaadinDirectoryRatingCount extends (
-  BaseVaadinDirectoryService
-) {
+export default class VaadinDirectoryRatingCount extends BaseVaadinDirectoryService {
   static category = 'rating'
 
   static route = {
diff --git a/services/vaadin-directory/vaadin-directory-rating-count.tester.js b/services/vaadin-directory/vaadin-directory-rating-count.tester.js
index 75942ed7862203624bc1d270cb72f904503c2718..8b43ed993cb71aec1288c3b63c3c04ae1558e6e5 100644
--- a/services/vaadin-directory/vaadin-directory-rating-count.tester.js
+++ b/services/vaadin-directory/vaadin-directory-rating-count.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('rating count of component')
   .get('/rating-count/vaadinvaadin-grid.json')
diff --git a/services/vaadin-directory/vaadin-directory-rating.service.js b/services/vaadin-directory/vaadin-directory-rating.service.js
index a829de8856dbf467ca46f49a4be0ff5224972ce3..c07ddf091b09933ce1b029f6e3ed78b1f508eb87 100644
--- a/services/vaadin-directory/vaadin-directory-rating.service.js
+++ b/services/vaadin-directory/vaadin-directory-rating.service.js
@@ -1,12 +1,8 @@
-'use strict'
+import { starRating } from '../text-formatters.js'
+import { floorCount as floorCountColor } from '../color-formatters.js'
+import { BaseVaadinDirectoryService } from './vaadin-directory-base.js'
 
-const { starRating } = require('../text-formatters')
-const { floorCount: floorCountColor } = require('../color-formatters')
-const { BaseVaadinDirectoryService } = require('./vaadin-directory-base')
-
-module.exports = class VaadinDirectoryRating extends (
-  BaseVaadinDirectoryService
-) {
+export default class VaadinDirectoryRating extends BaseVaadinDirectoryService {
   static category = 'rating'
 
   static route = {
diff --git a/services/vaadin-directory/vaadin-directory-rating.tester.js b/services/vaadin-directory/vaadin-directory-rating.tester.js
index ae2466116d47808ee97a793ce3a26bdf43d5f843..e4074eb1e643096eeaf91fb102295959e2076abf 100644
--- a/services/vaadin-directory/vaadin-directory-rating.tester.js
+++ b/services/vaadin-directory/vaadin-directory-rating.tester.js
@@ -1,8 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { isStarRating } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { isStarRating } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('stars of component displayed in star icons')
   .get('/star/vaadinvaadin-grid.json')
diff --git a/services/vaadin-directory/vaadin-directory-release-date.service.js b/services/vaadin-directory/vaadin-directory-release-date.service.js
index 7d9b9a9f3e5da86dee1dacee68b0944be9b63a0a..d9069ca4c9897d140b1fb42a0f6914e5d1ffb6ff 100644
--- a/services/vaadin-directory/vaadin-directory-release-date.service.js
+++ b/services/vaadin-directory/vaadin-directory-release-date.service.js
@@ -1,12 +1,8 @@
-'use strict'
+import { formatDate } from '../text-formatters.js'
+import { age as ageColor } from '../color-formatters.js'
+import { BaseVaadinDirectoryService } from './vaadin-directory-base.js'
 
-const { formatDate } = require('../text-formatters')
-const { age: ageColor } = require('../color-formatters')
-const { BaseVaadinDirectoryService } = require('./vaadin-directory-base')
-
-module.exports = class VaadinDirectoryReleaseDate extends (
-  BaseVaadinDirectoryService
-) {
+export default class VaadinDirectoryReleaseDate extends BaseVaadinDirectoryService {
   static category = 'activity'
 
   static route = {
diff --git a/services/vaadin-directory/vaadin-directory-release-date.tester.js b/services/vaadin-directory/vaadin-directory-release-date.tester.js
index f5102380ea68b52cba14e8cf9c01dbe6bf60ce84..9c1c68dc64318b4cf7c7ab033cef1872506d39b7 100644
--- a/services/vaadin-directory/vaadin-directory-release-date.tester.js
+++ b/services/vaadin-directory/vaadin-directory-release-date.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isFormattedDate } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isFormattedDate } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('latest release date of the component (format: yyyy-mm-dd)')
   .get('/rd/vaadinvaadin-grid.json')
diff --git a/services/vaadin-directory/vaadin-directory-status.service.js b/services/vaadin-directory/vaadin-directory-status.service.js
index 12263e62859ebccf6d6ac84d46d2224b6e080135..0ad9186faad5b08795e508618e59faf8b264d987 100644
--- a/services/vaadin-directory/vaadin-directory-status.service.js
+++ b/services/vaadin-directory/vaadin-directory-status.service.js
@@ -1,10 +1,6 @@
-'use strict'
+import { BaseVaadinDirectoryService } from './vaadin-directory-base.js'
 
-const { BaseVaadinDirectoryService } = require('./vaadin-directory-base')
-
-module.exports = class VaadinDirectoryStatus extends (
-  BaseVaadinDirectoryService
-) {
+export default class VaadinDirectoryStatus extends BaseVaadinDirectoryService {
   static category = 'other'
 
   static route = {
diff --git a/services/vaadin-directory/vaadin-directory-status.tester.js b/services/vaadin-directory/vaadin-directory-status.tester.js
index 770d35a97a21feb50c29780cce1fda8b5a8429b4..7caa48c2165fa49f439af0f2b3a8d0da7b797472 100644
--- a/services/vaadin-directory/vaadin-directory-status.tester.js
+++ b/services/vaadin-directory/vaadin-directory-status.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('publish status of the component')
   .get('/vaadinvaadin-grid.json')
diff --git a/services/vaadin-directory/vaadin-directory-version.service.js b/services/vaadin-directory/vaadin-directory-version.service.js
index 0ebbaadc1392567d2aa819a9e7f94dfc938ff17b..53af932836ecc64a9b3530396585baf8f1081e8c 100644
--- a/services/vaadin-directory/vaadin-directory-version.service.js
+++ b/services/vaadin-directory/vaadin-directory-version.service.js
@@ -1,11 +1,7 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import { BaseVaadinDirectoryService } from './vaadin-directory-base.js'
 
-const { renderVersionBadge } = require('../version')
-const { BaseVaadinDirectoryService } = require('./vaadin-directory-base')
-
-module.exports = class VaadinDirectoryVersion extends (
-  BaseVaadinDirectoryService
-) {
+export default class VaadinDirectoryVersion extends BaseVaadinDirectoryService {
   static category = 'version'
 
   static route = {
diff --git a/services/vaadin-directory/vaadin-directory-version.tester.js b/services/vaadin-directory/vaadin-directory-version.tester.js
index 51d6c61269e7a702987543f588423832366de2f2..957e6006a5959a44ab9985c6b229b8422554c41a 100644
--- a/services/vaadin-directory/vaadin-directory-version.tester.js
+++ b/services/vaadin-directory/vaadin-directory-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isSemver } = require('../test-validators')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isSemver } from '../test-validators.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('latest version of the component (can have v prefixed or without)')
   .get('/v/vaadinvaadin-grid.json')
diff --git a/services/validators.js b/services/validators.js
index 1017a9988445c2211a5083d0db12a5d4123fa49d..42b89cd1d10e23ed86b072c387884c73053d0711 100644
--- a/services/validators.js
+++ b/services/validators.js
@@ -1,26 +1,19 @@
-'use strict'
-
-const { semver, semverRange } = require('joi-extension-semver')
-const Joi = require('joi').extend(semver).extend(semverRange)
+import {
+  semver as joiSemver,
+  semverRange as joiSemverRange,
+} from 'joi-extension-semver'
+import joi from 'joi'
+const Joi = joi.extend(joiSemver).extend(joiSemverRange)
 
 const optionalNonNegativeInteger = Joi.number().integer().min(0)
 
-module.exports = {
-  optionalNonNegativeInteger,
-
-  nonNegativeInteger: optionalNonNegativeInteger.required(),
-
-  anyInteger: Joi.number().integer().required(),
-
-  semver: Joi.semver().valid().required(),
-
-  semverRange: Joi.semverRange().valid().required(),
-
-  optionalDottedVersionNClausesWithOptionalSuffix: Joi.string().regex(
-    /^\d+(\.\d+)*([-+].*)?$/
-  ),
-
-  // TODO This accepts URLs with query strings and fragments, which for some
-  // purposes should be rejected.
-  optionalUrl: Joi.string().uri({ scheme: ['http', 'https'] }),
-}
+export { optionalNonNegativeInteger }
+export const nonNegativeInteger = optionalNonNegativeInteger.required()
+export const anyInteger = Joi.number().integer().required()
+export const semver = Joi.semver().valid().required()
+export const semverRange = Joi.semverRange().valid().required()
+export const optionalDottedVersionNClausesWithOptionalSuffix =
+  Joi.string().regex(/^\d+(\.\d+)*([-+].*)?$/)
+// TODO This accepts URLs with query strings and fragments, which for some
+// purposes should be rejected.
+export const optionalUrl = Joi.string().uri({ scheme: ['http', 'https'] })
diff --git a/services/version.js b/services/version.js
index bd71881311ba88447a37598af6fba997be36d43f..934b4d8de71d52792289e37c282b4b6093f5b60c 100644
--- a/services/version.js
+++ b/services/version.js
@@ -5,11 +5,9 @@
  *
  * For utilities specific to PHP version ranges, see php-version.js.
  */
-'use strict'
-
-const semver = require('semver')
-const { addv } = require('./text-formatters')
-const { version: versionColor } = require('./color-formatters')
+import semver from 'semver'
+import { addv } from './text-formatters.js'
+import { version as versionColor } from './color-formatters.js'
 
 function listCompare(a, b) {
   const alen = a.length
@@ -162,10 +160,4 @@ function renderVersionBadge({ version, tag, defaultLabel }) {
   }
 }
 
-module.exports = {
-  latest,
-  listCompare,
-  slice,
-  rangeStart,
-  renderVersionBadge,
-}
+export { latest, listCompare, slice, rangeStart, renderVersionBadge }
diff --git a/services/version.spec.js b/services/version.spec.js
index f447f43ac87f3515c0f3e0be92ffd4c85d458491..92b040cfa3090a1e24fbd55a85ef126cff3109b3 100644
--- a/services/version.spec.js
+++ b/services/version.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { latest, slice, rangeStart, renderVersionBadge } = require('./version')
+import { test, given } from 'sazerac'
+import { latest, slice, rangeStart, renderVersionBadge } from './version.js'
 const includePre = true
 
 describe('Version helpers', function () {
diff --git a/services/versioneye/versioneye.service.js b/services/versioneye/versioneye.service.js
index 8fa1d3ce356b795e1da8dc01f177451e0a3c7e53..c248e64c43a990c225e2339a87d4e79464029245 100644
--- a/services/versioneye/versioneye.service.js
+++ b/services/versioneye/versioneye.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   category: 'downloads',
   route: {
     base: 'versioneye/d',
diff --git a/services/versioneye/versioneye.tester.js b/services/versioneye/versioneye.tester.js
index 8523ffa54bfdc7c47a9988fac171f05491bbe0cc..77e17b5dca4e18dff34f637ab28ca6673739aa39 100644
--- a/services/versioneye/versioneye.tester.js
+++ b/services/versioneye/versioneye.tester.js
@@ -1,9 +1,6 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = new ServiceTester({ id: 'versioneye', title: 'VersionEye' })
-module.exports = t
+export const t = new ServiceTester({ id: 'versioneye', title: 'VersionEye' })
 
 t.create('no longer available (previously dependencies status)')
   .get('/d/ruby/rails.json')
diff --git a/services/visual-studio-app-center/visual-studio-app-center-base.js b/services/visual-studio-app-center/visual-studio-app-center-base.js
index a4c10f75da757f5918bd8bf87c3f19fdd1bf4c79..e90a6ee2f368bc9def858be951aa4b3ec74271eb 100644
--- a/services/visual-studio-app-center/visual-studio-app-center-base.js
+++ b/services/visual-studio-app-center/visual-studio-app-center-base.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const { BaseJsonService } = require('..')
+import { BaseJsonService } from '../index.js'
 
 const keywords = [
   'visual-studio',
@@ -37,4 +35,4 @@ class BaseVisualStudioAppCenterService extends BaseJsonService {
   }
 }
 
-module.exports = { keywords, documentation, BaseVisualStudioAppCenterService }
+export { keywords, documentation, BaseVisualStudioAppCenterService }
diff --git a/services/visual-studio-app-center/visual-studio-app-center-builds.service.js b/services/visual-studio-app-center/visual-studio-app-center-builds.service.js
index da790f24d460a91643f0aab2906eeeac5a5172e6..6b70a31a6f7ddee853d08455dde73c3543a84816 100644
--- a/services/visual-studio-app-center/visual-studio-app-center-builds.service.js
+++ b/services/visual-studio-app-center/visual-studio-app-center-builds.service.js
@@ -1,21 +1,17 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { NotFound } = require('..')
-const {
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { NotFound } from '../index.js'
+import {
   BaseVisualStudioAppCenterService,
   keywords,
   documentation,
-} = require('./visual-studio-app-center-base')
+} from './visual-studio-app-center-base.js'
 
 const schema = Joi.array().items({
   result: isBuildStatus.required(),
 })
 
-module.exports = class VisualStudioAppCenterBuilds extends (
-  BaseVisualStudioAppCenterService
-) {
+export default class VisualStudioAppCenterBuilds extends BaseVisualStudioAppCenterService {
   static category = 'build'
 
   static route = {
diff --git a/services/visual-studio-app-center/visual-studio-app-center-builds.tester.js b/services/visual-studio-app-center/visual-studio-app-center-builds.tester.js
index 062285493987c10e0c96e07adbc95a011c3d0cb7..0a70d24e994d56d1f06084c154780049a69636eb 100644
--- a/services/visual-studio-app-center/visual-studio-app-center-builds.tester.js
+++ b/services/visual-studio-app-center/visual-studio-app-center-builds.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // Mocked response rather than real data as old builds are deleted after some time.
 t.create('Valid Build')
diff --git a/services/visual-studio-app-center/visual-studio-app-center-releases-osversion.service.js b/services/visual-studio-app-center/visual-studio-app-center-releases-osversion.service.js
index c7960c4ea62ca49bd701f01421cdc388b1f2aa79..9f51181597afaf757cff47c7b64836cf64708e4c 100644
--- a/services/visual-studio-app-center/visual-studio-app-center-releases-osversion.service.js
+++ b/services/visual-studio-app-center/visual-studio-app-center-releases-osversion.service.js
@@ -1,20 +1,16 @@
-'use strict'
-
-const Joi = require('joi')
-const {
+import Joi from 'joi'
+import {
   BaseVisualStudioAppCenterService,
   keywords,
   documentation,
-} = require('./visual-studio-app-center-base')
+} from './visual-studio-app-center-base.js'
 
 const schema = Joi.object({
   app_os: Joi.string().required(),
   min_os: Joi.string().required(),
 }).required()
 
-module.exports = class VisualStudioAppCenterReleasesOSVersion extends (
-  BaseVisualStudioAppCenterService
-) {
+export default class VisualStudioAppCenterReleasesOSVersion extends BaseVisualStudioAppCenterService {
   static category = 'version'
 
   static route = {
diff --git a/services/visual-studio-app-center/visual-studio-app-center-releases-osversion.tester.js b/services/visual-studio-app-center/visual-studio-app-center-releases-osversion.tester.js
index e2a590794892ab01785a507eb6bf806ad32f62c8..826bcf1ad863bb2b400b430a94387edff47fe681 100644
--- a/services/visual-studio-app-center/visual-studio-app-center-releases-osversion.tester.js
+++ b/services/visual-studio-app-center/visual-studio-app-center-releases-osversion.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // Note:
 // Unfortunately an Invalid user, invalid project, valid API token test is not possible due to the way Microsoft cache their responses.
diff --git a/services/visual-studio-app-center/visual-studio-app-center-releases-size.service.js b/services/visual-studio-app-center/visual-studio-app-center-releases-size.service.js
index 4fff5e2ecb028831e78c4acccf6303f70d5dc748..76dd16ceb6f34b20fabae57b7a485df6b7492292 100644
--- a/services/visual-studio-app-center/visual-studio-app-center-releases-size.service.js
+++ b/services/visual-studio-app-center/visual-studio-app-center-releases-size.service.js
@@ -1,21 +1,17 @@
-'use strict'
-
-const Joi = require('joi')
-const prettyBytes = require('pretty-bytes')
-const { nonNegativeInteger } = require('../validators')
-const {
+import Joi from 'joi'
+import prettyBytes from 'pretty-bytes'
+import { nonNegativeInteger } from '../validators.js'
+import {
   BaseVisualStudioAppCenterService,
   keywords,
   documentation,
-} = require('./visual-studio-app-center-base')
+} from './visual-studio-app-center-base.js'
 
 const schema = Joi.object({
   size: nonNegativeInteger,
 }).required()
 
-module.exports = class VisualStudioAppCenterReleasesSize extends (
-  BaseVisualStudioAppCenterService
-) {
+export default class VisualStudioAppCenterReleasesSize extends BaseVisualStudioAppCenterService {
   static category = 'size'
 
   static route = {
diff --git a/services/visual-studio-app-center/visual-studio-app-center-releases-size.tester.js b/services/visual-studio-app-center/visual-studio-app-center-releases-size.tester.js
index e3b2964e9b743a7e9fd1537ac34db3299cd273be..5a1681a79eab0739c129492affe26a46d012bd39 100644
--- a/services/visual-studio-app-center/visual-studio-app-center-releases-size.tester.js
+++ b/services/visual-studio-app-center/visual-studio-app-center-releases-size.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isFileSize } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isFileSize } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('8368844 bytes to 8.37 megabytes')
   .get('/nock/nock/nock.json')
diff --git a/services/visual-studio-app-center/visual-studio-app-center-releases-version.service.js b/services/visual-studio-app-center/visual-studio-app-center-releases-version.service.js
index 7316fb044819b979a7c52f1ac785971049306ad3..a4f90d3096a93b4c8e49bd45bb53da02083ab537 100644
--- a/services/visual-studio-app-center/visual-studio-app-center-releases-version.service.js
+++ b/services/visual-studio-app-center/visual-studio-app-center-releases-version.service.js
@@ -1,21 +1,17 @@
-'use strict'
-
-const Joi = require('joi')
-const { renderVersionBadge } = require('../version')
-const {
+import Joi from 'joi'
+import { renderVersionBadge } from '../version.js'
+import {
   BaseVisualStudioAppCenterService,
   keywords,
   documentation,
-} = require('./visual-studio-app-center-base')
+} from './visual-studio-app-center-base.js'
 
 const schema = Joi.object({
   version: Joi.string().required(),
   short_version: Joi.string().required(),
 }).required()
 
-module.exports = class VisualStudioAppCenterReleasesVersion extends (
-  BaseVisualStudioAppCenterService
-) {
+export default class VisualStudioAppCenterReleasesVersion extends BaseVisualStudioAppCenterService {
   static category = 'version'
 
   static route = {
diff --git a/services/visual-studio-app-center/visual-studio-app-center-releases-version.tester.js b/services/visual-studio-app-center/visual-studio-app-center-releases-version.tester.js
index 47dd1b650e12db7c77b9126674148986daeffe4f..49f528a0bfbe810501d5378cc669e845bbf346e6 100644
--- a/services/visual-studio-app-center/visual-studio-app-center-releases-version.tester.js
+++ b/services/visual-studio-app-center/visual-studio-app-center-releases-version.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 // Note:
 // Unfortunately an Invalid user, invalid project, valid API token test is not possible due to the way Microsoft cache their responses.
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.service.js b/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.service.js
index 5765adc4033978c309d641851503f22d6c0e3bc0..8cfd950274f296473b5c46124a6164405be91703 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.service.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const VisualStudioMarketplaceBase = require('./visual-studio-marketplace-base')
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import VisualStudioMarketplaceBase from './visual-studio-marketplace-base.js'
 
 const documentation = `
   <p>
@@ -14,9 +12,7 @@ const documentation = `
 // This service exists separately from the other Marketplace downloads badges (in ./visual-studio-marketplace-downloads.js)
 // due differences in how the Marketplace tracks metrics for Azure DevOps extensions vs. other extension types.
 // See https://github.com/badges/shields/pull/2748 for more information on the discussion and decision.
-module.exports = class VisualStudioMarketplaceAzureDevOpsInstalls extends (
-  VisualStudioMarketplaceBase
-) {
+export default class VisualStudioMarketplaceAzureDevOpsInstalls extends VisualStudioMarketplaceBase {
   static category = 'downloads'
 
   static route = {
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.tester.js b/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.tester.js
index 741722d819910209cc14766b3a03e1efda67c60e..f4b209c5460c5b4a8a80647e7b925acd47eacc1f 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.tester.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-azure-devops-installs.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isMetric } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+export const t = await createServiceTester()
 
 const mockResponse = {
   results: [
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-base.js b/services/visual-studio-marketplace/visual-studio-marketplace-base.js
index 12a7218129d21fbdd8388af9e526ec5682abb48a..d25e9c11a2fc7e6b1228f17833c6d4e7312ef443 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-base.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const validate = require('../../core/base-service/validate')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import validate from '../../core/base-service/validate.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const extensionQuerySchema = Joi.object({
   results: Joi.array()
@@ -45,7 +43,7 @@ const statisticSchema = Joi.object().keys({
   ratingcount: Joi.number().default(0),
 })
 
-module.exports = class VisualStudioMarketplaceBase extends BaseJsonService {
+export default class VisualStudioMarketplaceBase extends BaseJsonService {
   static keywords = [
     'vscode',
     'tfs',
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-downloads.service.js b/services/visual-studio-marketplace/visual-studio-marketplace-downloads.service.js
index 71e459f25390dcc64fd8fa60d7601f6b21cbc632..1d90a6275cfa9c120dc6adc66ad3e0c6f705f804 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-downloads.service.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-downloads.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const VisualStudioMarketplaceBase = require('./visual-studio-marketplace-base')
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import VisualStudioMarketplaceBase from './visual-studio-marketplace-base.js'
 
 const documentation = `
 <p>
@@ -13,9 +11,7 @@ const documentation = `
 </p>
 `
 
-module.exports = class VisualStudioMarketplaceDownloads extends (
-  VisualStudioMarketplaceBase
-) {
+export default class VisualStudioMarketplaceDownloads extends VisualStudioMarketplaceBase {
   static category = 'downloads'
 
   static route = {
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-downloads.tester.js b/services/visual-studio-marketplace/visual-studio-marketplace-downloads.tester.js
index 9c6b775de7b0dece17e7a3d67051f6ab88c11517..d74b78cb8747017fc48e20bf8526ea574b37b4ee 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-downloads.tester.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-downloads.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isMetric } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+export const t = await createServiceTester()
 
 const mockResponse = {
   results: [
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-last-updated.service.js b/services/visual-studio-marketplace/visual-studio-marketplace-last-updated.service.js
index db4b5300a7e1e281010c80bf8c85c760429c7be9..5d7106fa58151388189d889039de2dab055ab067 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-last-updated.service.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-last-updated.service.js
@@ -1,12 +1,8 @@
-'use strict'
+import { age } from '../color-formatters.js'
+import { formatDate } from '../text-formatters.js'
+import VisualStudioMarketplaceBase from './visual-studio-marketplace-base.js'
 
-const { age } = require('../color-formatters')
-const { formatDate } = require('../text-formatters')
-const VisualStudioMarketplaceBase = require('./visual-studio-marketplace-base')
-
-module.exports = class VisualStudioMarketplaceLastUpdated extends (
-  VisualStudioMarketplaceBase
-) {
+export default class VisualStudioMarketplaceLastUpdated extends VisualStudioMarketplaceBase {
   static category = 'activity'
 
   static route = {
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-last-updated.tester.js b/services/visual-studio-marketplace/visual-studio-marketplace-last-updated.tester.js
index 5588f0fdbdabaf65db1427263d2a4f8d9e85f88f..cd7e40745a4ff640082e2854064838cce3692ad9 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-last-updated.tester.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-last-updated.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isFormattedDate } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isFormattedDate } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('date')
   .get('/visual-studio-marketplace/last-updated/yasht.terminal-all-in-one.json')
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-rating.service.js b/services/visual-studio-marketplace/visual-studio-marketplace-rating.service.js
index 3c9f4312e56b5f1bad98332e81cbc9e7c7dbdb7b..20de188d7fcd0218fe71cf511d89d41c8ae1eb21 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-rating.service.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-rating.service.js
@@ -1,12 +1,8 @@
-'use strict'
+import { starRating } from '../text-formatters.js'
+import { floorCount } from '../color-formatters.js'
+import VisualStudioMarketplaceBase from './visual-studio-marketplace-base.js'
 
-const { starRating } = require('../text-formatters')
-const { floorCount } = require('../color-formatters')
-const VisualStudioMarketplaceBase = require('./visual-studio-marketplace-base')
-
-module.exports = class VisualStudioMarketplaceRating extends (
-  VisualStudioMarketplaceBase
-) {
+export default class VisualStudioMarketplaceRating extends VisualStudioMarketplaceBase {
   static category = 'rating'
 
   static route = {
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-rating.tester.js b/services/visual-studio-marketplace/visual-studio-marketplace-rating.tester.js
index 7457cbc7539142d493db8dc49558145304e5bfd5..213285adbfda49e756f344a293715121757e59cb 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-rating.tester.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-rating.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { withRegex, isStarRating } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { withRegex, isStarRating } from '../test-validators.js'
+export const t = await createServiceTester()
 
 const isVscodeRating = withRegex(/[0-5]\.[0-9]{1}\/5?\s*\([0-9]*\)$/)
 
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-release-date.service.js b/services/visual-studio-marketplace/visual-studio-marketplace-release-date.service.js
index 4a3bb5d0554fef9b0f8464606a7d19f7ee4a3b23..d604c425c1a84fef4e72ee4f0aea95eb8bff9e4b 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-release-date.service.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-release-date.service.js
@@ -1,12 +1,8 @@
-'use strict'
+import { age } from '../color-formatters.js'
+import { formatDate } from '../text-formatters.js'
+import VisualStudioMarketplaceBase from './visual-studio-marketplace-base.js'
 
-const { age } = require('../color-formatters')
-const { formatDate } = require('../text-formatters')
-const VisualStudioMarketplaceBase = require('./visual-studio-marketplace-base')
-
-module.exports = class VisualStudioMarketplaceReleaseDate extends (
-  VisualStudioMarketplaceBase
-) {
+export default class VisualStudioMarketplaceReleaseDate extends VisualStudioMarketplaceBase {
   static category = 'activity'
 
   static route = {
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-release-date.tester.js b/services/visual-studio-marketplace/visual-studio-marketplace-release-date.tester.js
index 6469ab49c97add05e481acec6cf6a20e2de3df96..acf9da220bd8ffa432a7d2ad26f8d7b7c40c7a13 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-release-date.tester.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-release-date.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isFormattedDate } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isFormattedDate } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('date')
   .get('/visual-studio-marketplace/release-date/yasht.terminal-all-in-one.json')
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-version.service.js b/services/visual-studio-marketplace/visual-studio-marketplace-version.service.js
index 3d4eff80d49209150db7c97fbeb034a5b0b81b5e..e0e8e2458b31e4a8559c30dc25d696f0078e53d8 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-version.service.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-version.service.js
@@ -1,11 +1,7 @@
-'use strict'
+import { renderVersionBadge } from '../version.js'
+import VisualStudioMarketplaceBase from './visual-studio-marketplace-base.js'
 
-const { renderVersionBadge } = require('../version')
-const VisualStudioMarketplaceBase = require('./visual-studio-marketplace-base')
-
-module.exports = class VisualStudioMarketplaceVersion extends (
-  VisualStudioMarketplaceBase
-) {
+export default class VisualStudioMarketplaceVersion extends VisualStudioMarketplaceBase {
   static category = 'version'
 
   static route = {
diff --git a/services/visual-studio-marketplace/visual-studio-marketplace-version.tester.js b/services/visual-studio-marketplace/visual-studio-marketplace-version.tester.js
index 6e026eb69928d938f84c66d6c64a1f9862b4a71d..1b44b3e0e0e268b5a87704d1861960109c05ed51 100644
--- a/services/visual-studio-marketplace/visual-studio-marketplace-version.tester.js
+++ b/services/visual-studio-marketplace/visual-studio-marketplace-version.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { withRegex } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { withRegex } from '../test-validators.js'
+export const t = await createServiceTester()
 
 const isMarketplaceVersion = withRegex(/^v(\d+\.\d+\.\d+)(\.\d+)?$/)
 
diff --git a/services/w3c/w3c-validation-helper.js b/services/w3c/w3c-validation-helper.js
index 3f0a75f4016db4f23f8aefa335cb01b790d33ed0..fef29ef3738118e90c4a0b6a3b51fd87762f6978 100644
--- a/services/w3c/w3c-validation-helper.js
+++ b/services/w3c/w3c-validation-helper.js
@@ -1,5 +1,3 @@
-'use strict'
-
 const html5Expression =
   '^HTML\\s?,\\s?SVG\\s?1\\.1\\s?,\\s?MathML\\s?3\\.0(\\s?,\\s?((ITS\\s?2\\.0)|(RDFa\\s?Lite\\s?1\\.1)))?$'
 const html4Expression =
@@ -147,10 +145,4 @@ const documentation = `
   </p>
 `
 
-module.exports = {
-  documentation,
-  presetRegex,
-  getColor,
-  getMessage,
-  getSchema,
-}
+export { documentation, presetRegex, getColor, getMessage, getSchema }
diff --git a/services/w3c/w3c-validation-helper.spec.js b/services/w3c/w3c-validation-helper.spec.js
index 819f1afd539690181b1cd308eb2b8ce42c060f53..3c024c2bbc89be7e25edba92291f93a00a616a3f 100644
--- a/services/w3c/w3c-validation-helper.spec.js
+++ b/services/w3c/w3c-validation-helper.spec.js
@@ -1,12 +1,11 @@
-'use strict'
-const { expect } = require('chai')
-const { test, given, forCases } = require('sazerac')
-const {
+import { expect } from 'chai'
+import { test, given, forCases } from 'sazerac'
+import {
   presetRegex,
   getMessage,
   getColor,
   getSchema,
-} = require('./w3c-validation-helper')
+} from './w3c-validation-helper.js'
 
 describe('w3c-validation-helper', function () {
   describe('presetRegex', function () {
diff --git a/services/w3c/w3c-validation.service.js b/services/w3c/w3c-validation.service.js
index a0482c5002d21e8f1eaaf45ffae3516bace12ebe..945fd9a27473c9647c05f829522157fa504f0145 100644
--- a/services/w3c/w3c-validation.service.js
+++ b/services/w3c/w3c-validation.service.js
@@ -1,14 +1,13 @@
-'use strict'
-const Joi = require('joi')
-const { optionalUrl } = require('../validators')
-const { BaseJsonService, NotFound } = require('..')
-const {
+import Joi from 'joi'
+import { optionalUrl } from '../validators.js'
+import { BaseJsonService, NotFound } from '../index.js'
+import {
   documentation,
   presetRegex,
   getColor,
   getMessage,
   getSchema,
-} = require('./w3c-validation-helper')
+} from './w3c-validation-helper.js'
 
 const schema = Joi.object({
   url: Joi.string().optional(),
@@ -30,7 +29,7 @@ const queryParamSchema = Joi.object({
   preset: Joi.string().regex(presetRegex).allow(''),
 }).required()
 
-module.exports = class W3cValidation extends BaseJsonService {
+export default class W3cValidation extends BaseJsonService {
   static category = 'analysis'
 
   static route = {
diff --git a/services/w3c/w3c-validation.tester.js b/services/w3c/w3c-validation.tester.js
index 4dc93b6e0d76a8fcf7d557984c2fa8e5abe82d28..75bbae578777565c7702926accb1c8bea43b2ca8 100644
--- a/services/w3c/w3c-validation.tester.js
+++ b/services/w3c/w3c-validation.tester.js
@@ -1,6 +1,6 @@
-'use strict'
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 const isErrorOnly = Joi.string().regex(/^[0-9]+ errors?$/)
 
diff --git a/services/waffle/waffle-label-redirect.service.js b/services/waffle/waffle-label-redirect.service.js
index 0275bc1d5cbf3800f3ca3d5e8848cede29511eff..2a31d3417ce1471772a06813a88a5415bdffbffd 100644
--- a/services/waffle/waffle-label-redirect.service.js
+++ b/services/waffle/waffle-label-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = [
+export default [
   // The WaffleLabel service originally had 'label' as an optional parameter
   // with a default value of 'ready'. However, after some discussion it was
   // agreed that 'ready' didn't make sense as a default, nor was there any other
diff --git a/services/waffle/waffle-label-redirect.tester.js b/services/waffle/waffle-label-redirect.tester.js
index fb1b0cd6cabfafbd1b4f2409864e380b1945dacc..3d6625615be8acd7956f9e98653f93579c2bcaa6 100644
--- a/services/waffle/waffle-label-redirect.tester.js
+++ b/services/waffle/waffle-label-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'WaffleLabelRedirect',
   title: 'WaffleLabelRedirect',
   pathPrefix: '/waffle/label',
-}))
+})
 
 t.create('waffle label redirect')
   .get('/waffleio/waffle.io.svg')
diff --git a/services/waffle/waffle-label.service.js b/services/waffle/waffle-label.service.js
index de28fb92643e2d9ec78ac00e611f94ffbc17c7a3..d5ea4832bbc86346d8a61c33590613ad34cfd899 100644
--- a/services/waffle/waffle-label.service.js
+++ b/services/waffle/waffle-label.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { deprecatedService } from '../index.js'
 
-const { deprecatedService } = require('..')
-
-module.exports = deprecatedService({
+export default deprecatedService({
   route: {
     base: 'waffle/label',
     pattern: ':various*',
diff --git a/services/waffle/waffle-label.tester.js b/services/waffle/waffle-label.tester.js
index 98158d93fc8ff614f521e1a23f1d059b8d3ca5b7..05e9e1bd1d9ed732289cda4a72696adfe1c6f8a3 100644
--- a/services/waffle/waffle-label.tester.js
+++ b/services/waffle/waffle-label.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'Waffle',
   title: 'WaffleLabel',
   pathPrefix: '/waffle/label',
-}))
+})
 
 t.create('no longer available')
   .get('/ritwickdey/vscode-live-server/bug.json')
diff --git a/services/weblate/weblate-component-license.service.js b/services/weblate/weblate-component-license.service.js
index 22e1038979d7b8bab29ed17f13a4d86ba095618a..bd1ce1b3fef8a19a0d329030df4445906674eb5e 100644
--- a/services/weblate/weblate-component-license.service.js
+++ b/services/weblate/weblate-component-license.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
-const { optionalUrl } = require('../validators')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
+import { optionalUrl } from '../validators.js'
 
 const schema = Joi.object({
   license: Joi.string().required(),
@@ -15,7 +13,7 @@ const queryParamSchema = Joi.object({
 /**
  * This badge displays the license of a component on a Weblate instance.
  */
-module.exports = class WeblateComponentLicense extends BaseJsonService {
+export default class WeblateComponentLicense extends BaseJsonService {
   static category = 'license'
   static route = {
     base: 'weblate/license',
diff --git a/services/weblate/weblate-component-license.tester.js b/services/weblate/weblate-component-license.tester.js
index 60ec6c726f032eac461a282243c881d62c7383d9..844aa362c48f2c0d7ff462f509b748a519aabb29 100644
--- a/services/weblate/weblate-component-license.tester.js
+++ b/services/weblate/weblate-component-license.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('License')
   .get('/godot-engine/godot.json?server=https://hosted.weblate.org')
diff --git a/services/weblate/weblate-entity-count.service.js b/services/weblate/weblate-entity-count.service.js
index 3b04ea3f0494b5345a8c37ba15231b306a0d3eb4..8080f97d94c6cb6bc1bcc525a9176579edeba486 100644
--- a/services/weblate/weblate-entity-count.service.js
+++ b/services/weblate/weblate-entity-count.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const camelcase = require('camelcase')
-const { BaseJsonService } = require('..')
-const { nonNegativeInteger, optionalUrl } = require('../validators')
-const { metric } = require('../text-formatters')
+import Joi from 'joi'
+import camelcase from 'camelcase'
+import { BaseJsonService } from '../index.js'
+import { nonNegativeInteger, optionalUrl } from '../validators.js'
+import { metric } from '../text-formatters.js'
 
 const schema = Joi.object({
   count: nonNegativeInteger,
@@ -71,4 +69,4 @@ const entityCounts = [
   { entityName: 'users', exampleValue: 33058 },
 ].map(WeblateEntityCountFactory)
 
-module.exports = [...entityCounts]
+export default [...entityCounts]
diff --git a/services/weblate/weblate-entity-count.tester.js b/services/weblate/weblate-entity-count.tester.js
index a78a5bfc8def731dc6c13e5f6bfd40dcf48518ef..4e5d183aff8639601eec3b0955f8bcffa8324fe0 100644
--- a/services/weblate/weblate-entity-count.tester.js
+++ b/services/weblate/weblate-entity-count.tester.js
@@ -1,13 +1,10 @@
-'use strict'
-
-const { ServiceTester } = require('../tester')
-const { isMetric } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+import { ServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+export const t = new ServiceTester({
   id: 'WeblateEntity',
   title: 'Weblate Entity',
   pathPrefix: '/weblate',
-}))
+})
 
 t.create('Components')
   .get('/components.json?server=https://hosted.weblate.org')
diff --git a/services/weblate/weblate-project-translated-percentage.service.js b/services/weblate/weblate-project-translated-percentage.service.js
index d5bf6bbbfb597f2a95658b8a0222e95963cc5e27..87e073514f4d1c0e19ec5f89ec4455b40cd1102b 100644
--- a/services/weblate/weblate-project-translated-percentage.service.js
+++ b/services/weblate/weblate-project-translated-percentage.service.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
-const { optionalUrl } = require('../validators')
-const { colorScale } = require('../color-formatters')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
+import { optionalUrl } from '../validators.js'
+import { colorScale } from '../color-formatters.js'
 
 const schema = Joi.object({
   translated_percent: Joi.number().required(),
@@ -17,9 +15,7 @@ const queryParamSchema = Joi.object({
  * This badge displays the percentage of strings translated on a project on a
  * Weblate instance.
  */
-module.exports = class WeblateProjectTranslatedPercentage extends (
-  BaseJsonService
-) {
+export default class WeblateProjectTranslatedPercentage extends BaseJsonService {
   static category = 'other'
   static route = { base: 'weblate', pattern: ':project', queryParamSchema }
 
diff --git a/services/weblate/weblate-project-translated-percentage.tester.js b/services/weblate/weblate-project-translated-percentage.tester.js
index 52a8ba67d167d03eb2141b407e6d021d7976e76a..20f9368ac333b49262eb29dd78d8d48299b69015 100644
--- a/services/weblate/weblate-project-translated-percentage.tester.js
+++ b/services/weblate/weblate-project-translated-percentage.tester.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-
-const { isPercentage } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isPercentage } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('License')
   .get('/godot-engine.json?server=https://hosted.weblate.org')
diff --git a/services/weblate/weblate-user-statistics.service.js b/services/weblate/weblate-user-statistics.service.js
index e61cdd881494d714e77e437732b52ef26fbc3386..467b2df76dcc85d4001cf328d0a109607f79a102 100644
--- a/services/weblate/weblate-user-statistics.service.js
+++ b/services/weblate/weblate-user-statistics.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const camelcase = require('camelcase')
-const { BaseJsonService } = require('..')
-const { nonNegativeInteger, optionalUrl } = require('../validators')
-const { metric } = require('../text-formatters')
+import Joi from 'joi'
+import camelcase from 'camelcase'
+import { BaseJsonService } from '../index.js'
+import { nonNegativeInteger, optionalUrl } from '../validators.js'
+import { metric } from '../text-formatters.js'
 
 const schema = Joi.object({
   translated: nonNegativeInteger,
@@ -87,4 +85,4 @@ const userStatistics = [
   { statisticName: 'languages', property: 'languages', exampleValue: 1 },
 ].map(WeblateUserStatisticFactory)
 
-module.exports = [...userStatistics]
+export default [...userStatistics]
diff --git a/services/weblate/weblate-user-statistics.tester.js b/services/weblate/weblate-user-statistics.tester.js
index 42934b072fd714a8c67529375c5939306222231f..1e0848fbd723a870b0c159dd0d9238574b5cdb91 100644
--- a/services/weblate/weblate-user-statistics.tester.js
+++ b/services/weblate/weblate-user-statistics.tester.js
@@ -1,13 +1,10 @@
-'use strict'
-
-const { ServiceTester } = require('../tester')
-const { isMetric } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+import { ServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+export const t = new ServiceTester({
   id: 'WeblateUserStatistic',
   title: 'Weblate User Statistic',
   pathPrefix: '/weblate',
-}))
+})
 
 t.create('Translations')
   .get('/user/nijel/translations.json?server=https://hosted.weblate.org')
diff --git a/services/website-status.js b/services/website-status.js
index c22cf690bde61599952afff479434627f23a4a20..c0fdb252b07b129e8e5c61c00e5cf3102c411562 100644
--- a/services/website-status.js
+++ b/services/website-status.js
@@ -1,6 +1,4 @@
-'use strict'
-
-const Joi = require('joi')
+import Joi from 'joi'
 
 const queryParamSchema = Joi.object({
   up_message: Joi.string(),
@@ -30,8 +28,4 @@ function renderWebsiteStatus({
   }
 }
 
-module.exports = {
-  queryParamSchema,
-  exampleQueryParams,
-  renderWebsiteStatus,
-}
+export { queryParamSchema, exampleQueryParams, renderWebsiteStatus }
diff --git a/services/website-status.spec.js b/services/website-status.spec.js
index d87f33a4a0003eee869706aad6e3509e83370b21..5e73cd774292f94a959ddfaafb8dbcb261b43c8b 100644
--- a/services/website-status.spec.js
+++ b/services/website-status.spec.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { test, given } = require('sazerac')
-const { renderWebsiteStatus } = require('./website-status')
+import { test, given } from 'sazerac'
+import { renderWebsiteStatus } from './website-status.js'
 
 describe('Website status helpers', function () {
   const customOptions = {
diff --git a/services/website/website-redirect.service.js b/services/website/website-redirect.service.js
index f2597dd1ceb7215848d7cd5a9ff22c533fb2ff1a..a7a6b18a64472b5c91445954be731c18fe2b6986 100644
--- a/services/website/website-redirect.service.js
+++ b/services/website/website-redirect.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const { escapeFormat } = require('../../core/badge-urls/path-helpers')
-const { redirector } = require('..')
+import { escapeFormat } from '../../core/badge-urls/path-helpers.js'
+import { redirector } from '../index.js'
 
 function escapeFormatSlashes(t) {
   return (
@@ -51,7 +49,7 @@ Old documentation, for reference:
 </p>
 */
 
-module.exports = [
+export default [
   redirector({
     category: 'monitoring',
     route: {
diff --git a/services/website/website-redirect.tester.js b/services/website/website-redirect.tester.js
index 4e0b27bca2d73ed14cd107ba2d4f1d90dd816ffc..0aeba6b5bc629f7241c5ccf2d3d7d307ea1b5dab 100644
--- a/services/website/website-redirect.tester.js
+++ b/services/website/website-redirect.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
 
-const { ServiceTester } = require('../tester')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'WebsiteRedirect',
   title: 'WebsiteRedirect',
   pathPrefix: '',
-}))
+})
 
 t.create('Website with custom messages')
   .get('/website-up-down/https/www.google.com.svg')
diff --git a/services/website/website.service.js b/services/website/website.service.js
index 0a9b278daa135536941d47dcf5a6c5eeaf43d106..5ac7e4536a0c8f6e1524faf045c4cc021a78f86b 100644
--- a/services/website/website.service.js
+++ b/services/website/website.service.js
@@ -1,15 +1,13 @@
-'use strict'
-
-const Joi = require('joi')
-const emojic = require('emojic')
-const { optionalUrl } = require('../validators')
-const {
+import Joi from 'joi'
+import emojic from 'emojic'
+import { optionalUrl } from '../validators.js'
+import {
   queryParamSchema,
   exampleQueryParams,
   renderWebsiteStatus,
-} = require('../website-status')
-const { BaseService } = require('..')
-const trace = require('../../core/base-service/trace')
+} from '../website-status.js'
+import { BaseService } from '../index.js'
+import trace from '../../core/base-service/trace.js'
 
 const documentation = `
 <p>
@@ -35,7 +33,7 @@ const urlQueryParamSchema = Joi.object({
   url: optionalUrl.required(),
 }).required()
 
-module.exports = class Website extends BaseService {
+export default class Website extends BaseService {
   static category = 'monitoring'
 
   static route = {
diff --git a/services/website/website.tester.js b/services/website/website.tester.js
index f60fafbd2ac89e64e991e80818cfbd5926c0de9a..95d2caeac1c5983d7b1335c58cd002f1958e5f32 100644
--- a/services/website/website.tester.js
+++ b/services/website/website.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('status of http://shields.io')
   .get('/website.json?url=http://shields.io')
diff --git a/services/wercker/wercker.service.js b/services/wercker/wercker.service.js
index 94bb3288ffbd2878ab40609fba863b6cd6989499..7dcb1faa9f417cdede263ce5732f5025133931c5 100644
--- a/services/wercker/wercker.service.js
+++ b/services/wercker/wercker.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { isBuildStatus, renderBuildStatusBadge } = require('../build-status')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { isBuildStatus, renderBuildStatusBadge } from '../build-status.js'
+import { BaseJsonService } from '../index.js'
 
 const werckerSchema = Joi.array()
   .items(
@@ -32,7 +30,7 @@ const werckerCIDocumentation = `
 </p>
 `
 
-module.exports = class Wercker extends BaseJsonService {
+export default class Wercker extends BaseJsonService {
   static category = 'build'
 
   static route = {
diff --git a/services/wercker/wercker.tester.js b/services/wercker/wercker.tester.js
index 28cba83661019a514d13118f50358b5c75428085..bcbd29368db1b0c794c6e98dec2dcae7ce9c9ad4 100644
--- a/services/wercker/wercker.tester.js
+++ b/services/wercker/wercker.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const { isBuildStatus } = require('../build-status')
-const t = (module.exports = require('../tester').createServiceTester())
+import { isBuildStatus } from '../build-status.js'
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Build status')
   .get('/build/wercker/go-wercker-api.json')
diff --git a/services/wheelmap/wheelmap.service.js b/services/wheelmap/wheelmap.service.js
index 1973d0b326c42cbbf17db05e30c437fc38d31e72..c6abf22d8c6cd9cca47b41c7126ef6f4cd106858 100644
--- a/services/wheelmap/wheelmap.service.js
+++ b/services/wheelmap/wheelmap.service.js
@@ -1,7 +1,5 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService } = require('..')
+import Joi from 'joi'
+import { BaseJsonService } from '../index.js'
 
 const schema = Joi.object({
   node: Joi.object({
@@ -9,7 +7,7 @@ const schema = Joi.object({
   }).required(),
 }).required()
 
-module.exports = class Wheelmap extends BaseJsonService {
+export default class Wheelmap extends BaseJsonService {
   static category = 'other'
 
   static route = {
diff --git a/services/wheelmap/wheelmap.spec.js b/services/wheelmap/wheelmap.spec.js
index 41b80594b4afa29498d23e3c529eca14a6dd44c4..80287395c033ddf37563fc4c76f8119c3c6fd131 100644
--- a/services/wheelmap/wheelmap.spec.js
+++ b/services/wheelmap/wheelmap.spec.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const { expect } = require('chai')
-const nock = require('nock')
-const { cleanUpNockAfterEach, defaultContext } = require('../test-helpers')
-const Wheelmap = require('./wheelmap.service')
+import { expect } from 'chai'
+import nock from 'nock'
+import { cleanUpNockAfterEach, defaultContext } from '../test-helpers.js'
+import Wheelmap from './wheelmap.service.js'
 
 describe('Wheelmap', function () {
   cleanUpNockAfterEach()
diff --git a/services/wheelmap/wheelmap.tester.js b/services/wheelmap/wheelmap.tester.js
index 1a618029fd4137d249bb1e4b98578e0cba2e38ed..e4d5e6c49b580d8548ebfa2d9b164d57f6a5304e 100644
--- a/services/wheelmap/wheelmap.tester.js
+++ b/services/wheelmap/wheelmap.tester.js
@@ -1,8 +1,8 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { noToken } = require('../test-helpers')
-const noWheelmapToken = noToken(require('./wheelmap.service'))
+import { createServiceTester } from '../tester.js'
+import { noToken } from '../test-helpers.js'
+import _noWheelmapToken from './wheelmap.service.js'
+export const t = await createServiceTester()
+const noWheelmapToken = noToken(_noWheelmapToken)
 
 t.create('node with accessibility')
   .skipWhen(noWheelmapToken)
diff --git a/services/wikiapiary/wikiapiary-installs.service.js b/services/wikiapiary/wikiapiary-installs.service.js
index 3aa11e110da2a26a26715bdab2d159eec44f2287..222e16c4c875a41f249ef5cb1543a7f6768e01e7 100644
--- a/services/wikiapiary/wikiapiary-installs.service.js
+++ b/services/wikiapiary/wikiapiary-installs.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const documentation = `
   <p>
@@ -48,7 +46,7 @@ const schema = Joi.object({
  *
  * {@link https://www.mediawiki.org/wiki/Manual:Extensions MediaWiki Extensions Manual}
  */
-module.exports = class WikiapiaryInstalls extends BaseJsonService {
+export default class WikiapiaryInstalls extends BaseJsonService {
   static category = 'downloads'
   static route = {
     base: 'wikiapiary',
diff --git a/services/wikiapiary/wikiapiary-installs.tester.js b/services/wikiapiary/wikiapiary-installs.tester.js
index fee38c87645f1c81d75b8a4b872929cbb7b311c7..878ec756dd1632256acaa68ee3659de0e047a8a3 100644
--- a/services/wikiapiary/wikiapiary-installs.tester.js
+++ b/services/wikiapiary/wikiapiary-installs.tester.js
@@ -1,7 +1,6 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { isMetric } = require('../test-validators')
+import { createServiceTester } from '../tester.js'
+import { isMetric } from '../test-validators.js'
+export const t = await createServiceTester()
 
 t.create('Extension')
   .get('/extension/installs/ParserFunctions.json')
diff --git a/services/wordpress/wordpress-base.js b/services/wordpress/wordpress-base.js
index 36a04628e4bfd15ed5507c5c475546e62e289ae8..c11852b4f5e23f41a7e7835d3d37ea050a1ab077 100644
--- a/services/wordpress/wordpress-base.js
+++ b/services/wordpress/wordpress-base.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { nonNegativeInteger } = require('../validators')
-const { BaseJsonService, NotFound } = require('..')
+import Joi from 'joi'
+import { nonNegativeInteger } from '../validators.js'
+import { BaseJsonService, NotFound } from '../index.js'
 
 const stringOrFalse = Joi.alternatives(Joi.string(), Joi.bool())
 
@@ -42,7 +40,7 @@ const notFoundSchema = Joi.object()
 const pluginSchemas = Joi.alternatives(pluginSchema, notFoundSchema)
 const themeSchemas = Joi.alternatives(themeSchema, notFoundSchema)
 
-module.exports = class BaseWordpress extends BaseJsonService {
+export default class BaseWordpress extends BaseJsonService {
   async fetch({ extensionType, slug }) {
     const url = `https://api.wordpress.org/${extensionType}s/info/1.2/`
     let schemas
diff --git a/services/wordpress/wordpress-downloads.service.js b/services/wordpress/wordpress-downloads.service.js
index 81a7ae3e381d0652b85245118a49a0674583d4c2..83979488b5fa4ef0bb6e941a40c39fc1cc50a973 100644
--- a/services/wordpress/wordpress-downloads.service.js
+++ b/services/wordpress/wordpress-downloads.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { downloadCount } = require('../color-formatters')
-const { NotFound } = require('..')
-const BaseWordpress = require('./wordpress-base')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { downloadCount } from '../color-formatters.js'
+import { NotFound } from '../index.js'
+import BaseWordpress from './wordpress-base.js'
 
 const dateSchema = Joi.object()
   .pattern(Joi.date().iso(), Joi.number().integer())
@@ -158,4 +156,4 @@ function InstallsForExtensionType(extensionType) {
 const downloadServices = ['plugin', 'theme'].map(DownloadsForExtensionType)
 const installServices = ['plugin', 'theme'].map(InstallsForExtensionType)
 const modules = [...downloadServices, ...installServices]
-module.exports = modules
+export default modules
diff --git a/services/wordpress/wordpress-downloads.tester.js b/services/wordpress/wordpress-downloads.tester.js
index 21b48fcd085945bcd726652a1c6ddd91c61da88f..05019f0782733af798ae3129752d98820ff1ab39 100644
--- a/services/wordpress/wordpress-downloads.tester.js
+++ b/services/wordpress/wordpress-downloads.tester.js
@@ -1,13 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isMetric, isMetricOverTimePeriod } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isMetric, isMetricOverTimePeriod } = require('../test-validators')
-
-const t = new ServiceTester({
+export const t = new ServiceTester({
   id: 'wordpress',
   title: 'WordPress Download Tests',
 })
-module.exports = t
 
 t.create('Plugin Downloads - Total')
   .get('/plugin/dt/akismet.json')
diff --git a/services/wordpress/wordpress-last-update.service.js b/services/wordpress/wordpress-last-update.service.js
index cbf018d9319a3a71812a910da8dcda9d6cdc49c0..10b48ef92b7e44c229f70826b3df2e9593da062e 100644
--- a/services/wordpress/wordpress-last-update.service.js
+++ b/services/wordpress/wordpress-last-update.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const moment = require('moment')
-const { InvalidResponse } = require('..')
-const { formatDate } = require('../text-formatters')
-const { age: ageColor } = require('../color-formatters')
-const BaseWordpress = require('./wordpress-base')
+import moment from 'moment'
+import { InvalidResponse } from '../index.js'
+import { formatDate } from '../text-formatters.js'
+import { age as ageColor } from '../color-formatters.js'
+import BaseWordpress from './wordpress-base.js'
 
 const extensionData = {
   plugin: {
@@ -76,4 +74,4 @@ function LastUpdateForType(extensionType) {
 }
 
 const lastupdate = ['plugin', 'theme'].map(LastUpdateForType)
-module.exports = [...lastupdate]
+export default [...lastupdate]
diff --git a/services/wordpress/wordpress-last-update.tester.js b/services/wordpress/wordpress-last-update.tester.js
index 9301a0d6267b1f4d1a42b233e1dab260cc565383..d490b6ee72f03819f3a23bae0b9aca658b790c55 100644
--- a/services/wordpress/wordpress-last-update.tester.js
+++ b/services/wordpress/wordpress-last-update.tester.js
@@ -1,13 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isFormattedDate } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isFormattedDate } = require('../test-validators')
-
-const t = new ServiceTester({
+export const t = new ServiceTester({
   id: 'wordpress',
   title: 'WordPress Last Update',
 })
-module.exports = t
 
 t.create('Plugin Last Update')
   .get('/plugin/last-updated/akismet.json')
diff --git a/services/wordpress/wordpress-platform-redirect.service.js b/services/wordpress/wordpress-platform-redirect.service.js
index 10b74f8d99893e7dae95abc73288b910da101917..5f9544e5e1bcf69e0d9f6b859f141adde6a03273 100644
--- a/services/wordpress/wordpress-platform-redirect.service.js
+++ b/services/wordpress/wordpress-platform-redirect.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { redirector } from '../index.js'
 
-const { redirector } = require('..')
-
-module.exports = redirector({
+export default redirector({
   category: 'platform-support',
   route: {
     base: 'wordpress/v',
diff --git a/services/wordpress/wordpress-platform-redirect.tester.js b/services/wordpress/wordpress-platform-redirect.tester.js
index 2e665cadb9266d4205f4214dbb26628b698a05ab..2f0816dea56330082765ac6906ecf66ea814b304 100644
--- a/services/wordpress/wordpress-platform-redirect.tester.js
+++ b/services/wordpress/wordpress-platform-redirect.tester.js
@@ -1,6 +1,5 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
+import { createServiceTester } from '../tester.js'
+export const t = await createServiceTester()
 
 t.create('Plugin Tested WP Version (Alias)')
   .get('/akismet.svg')
diff --git a/services/wordpress/wordpress-platform.service.js b/services/wordpress/wordpress-platform.service.js
index cca782975c55802cbee404c58c94f19b0bbb956f..5c0d1cbd05aa711a89e24132e6d8364cb6f70cd2 100644
--- a/services/wordpress/wordpress-platform.service.js
+++ b/services/wordpress/wordpress-platform.service.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { NotFound } = require('..')
-const { addv } = require('../text-formatters')
-const { version: versionColor } = require('../color-formatters')
-const BaseWordpress = require('./wordpress-base')
-const { versionColorForWordpressVersion } = require('./wordpress-version-color')
+import { NotFound } from '../index.js'
+import { addv } from '../text-formatters.js'
+import { version as versionColor } from '../color-formatters.js'
+import BaseWordpress from './wordpress-base.js'
+import { versionColorForWordpressVersion } from './wordpress-version-color.js'
 
 const extensionData = {
   plugin: {
@@ -164,7 +162,7 @@ function RequiresPHPVersionForType(extensionType) {
 
 const requiredPhp = ['plugin', 'theme'].map(RequiresPHPVersionForType)
 const requiresVersion = ['plugin', 'theme'].map(WordpressRequiresVersion)
-module.exports = [
+export default [
   ...requiredPhp,
   ...requiresVersion,
   WordpressPluginTestedVersion,
diff --git a/services/wordpress/wordpress-platform.tester.js b/services/wordpress/wordpress-platform.tester.js
index 43e7edb27287b378af344d30537faf7bac02e1ee..ded6f1b6b094bd7c0a4f458544ec711a5c275db9 100644
--- a/services/wordpress/wordpress-platform.tester.js
+++ b/services/wordpress/wordpress-platform.tester.js
@@ -1,17 +1,15 @@
-'use strict'
-
-const Joi = require('joi')
-const { ServiceTester } = require('../tester')
-const {
+import Joi from 'joi'
+import { ServiceTester } from '../tester.js'
+import {
   isVPlusDottedVersionAtLeastOne,
   isComposerVersion,
-} = require('../test-validators')
+} from '../test-validators.js'
 
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'WordpressPlatform',
   title: 'WordPress Platform Tests',
   pathPrefix: '/wordpress',
-}))
+})
 
 t.create('Plugin Required WP Version')
   .get('/plugin/wp-version/akismet.json')
diff --git a/services/wordpress/wordpress-rating.service.js b/services/wordpress/wordpress-rating.service.js
index 843915f1e5ab60ca7cc551d0859fd0dd8c4fd2d0..6489fde9dae908736fa3140dfec5e3025f7c799c 100644
--- a/services/wordpress/wordpress-rating.service.js
+++ b/services/wordpress/wordpress-rating.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { starRating, metric } = require('../text-formatters')
-const { floorCount } = require('../color-formatters')
-const BaseWordpress = require('./wordpress-base')
+import { starRating, metric } from '../text-formatters.js'
+import { floorCount } from '../color-formatters.js'
+import BaseWordpress from './wordpress-base.js'
 
 const extensionData = {
   plugin: {
@@ -103,4 +101,4 @@ const ratingsServices = ['plugin', 'theme'].map(RatingForExtensionType)
 const starsServices = ['plugin', 'theme'].map(StarsForExtensionType)
 const modules = [...ratingsServices, ...starsServices]
 
-module.exports = modules
+export default modules
diff --git a/services/wordpress/wordpress-rating.tester.js b/services/wordpress/wordpress-rating.tester.js
index a1e1b8c3bae2baefc1e58836e6c4b3f20f0db1ee..1c686890f16cf6b6ec2b6a0a50e2066ff7900279 100644
--- a/services/wordpress/wordpress-rating.tester.js
+++ b/services/wordpress/wordpress-rating.tester.js
@@ -1,13 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isStarRating } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isStarRating } = require('../test-validators')
-
-const t = new ServiceTester({
+export const t = new ServiceTester({
   id: 'wordpress',
   title: 'WordPress Rating Tests',
 })
-module.exports = t
 
 t.create('Plugin Rating - Stars')
   .get('/plugin/stars/akismet.json')
diff --git a/services/wordpress/wordpress-version-color.js b/services/wordpress/wordpress-version-color.js
index fd46f718987a245e40388a38c43d4c2e775987be..4e15ca3c326534be5c77faa6b3880513b5c7aa62 100644
--- a/services/wordpress/wordpress-version-color.js
+++ b/services/wordpress/wordpress-version-color.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { promisify } = require('util')
-const semver = require('semver')
-const { regularUpdate } = require('../../core/legacy/regular-update')
+import { promisify } from 'util'
+import semver from 'semver'
+import { regularUpdate } from '../../core/legacy/regular-update.js'
 
 // TODO: Incorporate this schema.
 // const schema = Joi.object()
@@ -61,8 +59,4 @@ async function versionColorForWordpressVersion(version) {
   }
 }
 
-module.exports = {
-  toSemver,
-  getOfferedVersions,
-  versionColorForWordpressVersion,
-}
+export { toSemver, getOfferedVersions, versionColorForWordpressVersion }
diff --git a/services/wordpress/wordpress-version-color.spec.js b/services/wordpress/wordpress-version-color.spec.js
index d7d9d8cb8635fb6baa450292e016607e9621fbf1..c428886c553473957558ace2d21b2ec45103083c 100644
--- a/services/wordpress/wordpress-version-color.spec.js
+++ b/services/wordpress/wordpress-version-color.spec.js
@@ -1,10 +1,8 @@
-'use strict'
-
-const { expect } = require('chai')
-const {
+import { expect } from 'chai'
+import {
   toSemver,
   versionColorForWordpressVersion,
-} = require('./wordpress-version-color')
+} from './wordpress-version-color.js'
 
 describe('toSemver() function', function () {
   it('coerces versions', function () {
diff --git a/services/wordpress/wordpress-version.service.js b/services/wordpress/wordpress-version.service.js
index 4980ec7f6a4e275eab0e1809e0a04b01c30fa07d..9f5d62741391efe89ef8533cda0d4d309a62c1ca 100644
--- a/services/wordpress/wordpress-version.service.js
+++ b/services/wordpress/wordpress-version.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const { addv } = require('../text-formatters')
-const { version: versionColor } = require('../color-formatters')
-const BaseWordpress = require('./wordpress-base')
+import { addv } from '../text-formatters.js'
+import { version as versionColor } from '../color-formatters.js'
+import BaseWordpress from './wordpress-base.js'
 
 function VersionForExtensionType(extensionType) {
   const { capt, exampleSlug } = {
@@ -53,4 +51,4 @@ function VersionForExtensionType(extensionType) {
   }
 }
 
-module.exports = ['theme', 'plugin'].map(VersionForExtensionType)
+export default ['theme', 'plugin'].map(VersionForExtensionType)
diff --git a/services/wordpress/wordpress-version.tester.js b/services/wordpress/wordpress-version.tester.js
index e8fc1a94de078be16fcdeb43142227d92020bb86..9abf4a330e7b120739c66b2da5f997677df64e01 100644
--- a/services/wordpress/wordpress-version.tester.js
+++ b/services/wordpress/wordpress-version.tester.js
@@ -1,12 +1,10 @@
-'use strict'
+import { ServiceTester } from '../tester.js'
+import { isVPlusDottedVersionAtLeastOne } from '../test-validators.js'
 
-const { ServiceTester } = require('../tester')
-const { isVPlusDottedVersionAtLeastOne } = require('../test-validators')
-
-const t = (module.exports = new ServiceTester({
+export const t = new ServiceTester({
   id: 'wordpress',
   title: 'WordPress Version Tests',
-}))
+})
 
 t.create('Plugin Version').get('/plugin/v/akismet.json').expectBadge({
   label: 'plugin',
diff --git a/services/youtube/youtube-base.js b/services/youtube/youtube-base.js
index ad2bfd83fc3c681815023ce41d724b549ced1b79..94f14ee6018d2ca33bde18934d4c312d8109dd9d 100644
--- a/services/youtube/youtube-base.js
+++ b/services/youtube/youtube-base.js
@@ -1,9 +1,7 @@
-'use strict'
-
-const Joi = require('joi')
-const { BaseJsonService, NotFound } = require('..')
-const { metric } = require('../text-formatters')
-const { nonNegativeInteger } = require('../validators')
+import Joi from 'joi'
+import { BaseJsonService, NotFound } from '../index.js'
+import { metric } from '../text-formatters.js'
+import { nonNegativeInteger } from '../validators.js'
 
 const documentation = `
 <p>By using the YouTube badges provided by Shields.io, you are agreeing to be bound by the YouTube Terms of Service. These can be found here:
@@ -92,4 +90,4 @@ class YouTubeChannelBase extends YouTubeBase {
   static type = 'channel'
 }
 
-module.exports = { documentation, YouTubeVideoBase, YouTubeChannelBase }
+export { documentation, YouTubeVideoBase, YouTubeChannelBase }
diff --git a/services/youtube/youtube-channel-views.service.js b/services/youtube/youtube-channel-views.service.js
index 27712d5c83ebf9d09ebbaabdcf7b2800cb18f39d..d3f854a920a6f62024241d87b2836c0b4160405f 100644
--- a/services/youtube/youtube-channel-views.service.js
+++ b/services/youtube/youtube-channel-views.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { documentation, YouTubeChannelBase } from './youtube-base.js'
 
-const { documentation, YouTubeChannelBase } = require('./youtube-base')
-
-module.exports = class YouTubeChannelViews extends YouTubeChannelBase {
+export default class YouTubeChannelViews extends YouTubeChannelBase {
   static route = {
     base: 'youtube/channel/views',
     pattern: ':channelId',
diff --git a/services/youtube/youtube-channel-views.tester.js b/services/youtube/youtube-channel-views.tester.js
index eab2689fd0ec73a859eb753f0d675da54183fa95..47501da6781082c291ce14ff8fa507c1a4f44a68 100644
--- a/services/youtube/youtube-channel-views.tester.js
+++ b/services/youtube/youtube-channel-views.tester.js
@@ -1,9 +1,9 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { noToken } = require('../test-helpers')
-const { isMetric } = require('../test-validators')
-const noYouTubeToken = noToken(require('./youtube-channel-views.service'))
+import { createServiceTester } from '../tester.js'
+import { noToken } from '../test-helpers.js'
+import { isMetric } from '../test-validators.js'
+import _noYouTubeToken from './youtube-channel-views.service.js'
+export const t = await createServiceTester()
+const noYouTubeToken = noToken(_noYouTubeToken)
 
 t.create('channel view count')
   .skipWhen(noYouTubeToken)
diff --git a/services/youtube/youtube-comments.service.js b/services/youtube/youtube-comments.service.js
index 679605684cc6ab0442291343126a6b2a4063486d..0f7faf3c7806b25d5ed5b67a966e1064875b7df6 100644
--- a/services/youtube/youtube-comments.service.js
+++ b/services/youtube/youtube-comments.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { documentation, YouTubeVideoBase } from './youtube-base.js'
 
-const { documentation, YouTubeVideoBase } = require('./youtube-base')
-
-module.exports = class YouTubeComments extends YouTubeVideoBase {
+export default class YouTubeComments extends YouTubeVideoBase {
   static route = {
     base: 'youtube/comments',
     pattern: ':videoId',
diff --git a/services/youtube/youtube-comments.tester.js b/services/youtube/youtube-comments.tester.js
index dfdbde45d49c29e0d6a468c8666295a6e0e289f1..dded2be9dfb2889c9b629bcfb93f4c0a76513fe9 100644
--- a/services/youtube/youtube-comments.tester.js
+++ b/services/youtube/youtube-comments.tester.js
@@ -1,9 +1,9 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { noToken } = require('../test-helpers')
-const { isMetric } = require('../test-validators')
-const noYouTubeToken = noToken(require('./youtube-comments.service'))
+import { createServiceTester } from '../tester.js'
+import { noToken } from '../test-helpers.js'
+import { isMetric } from '../test-validators.js'
+import _noYouTubeToken from './youtube-comments.service.js'
+export const t = await createServiceTester()
+const noYouTubeToken = noToken(_noYouTubeToken)
 
 t.create('video comment count')
   .skipWhen(noYouTubeToken)
diff --git a/services/youtube/youtube-likes.service.js b/services/youtube/youtube-likes.service.js
index e2133cd392c1a1a475b217de89b66e9c0ea3bcc8..94e2d7ae66264c4a7a7087b027526f6f7ce17866 100644
--- a/services/youtube/youtube-likes.service.js
+++ b/services/youtube/youtube-likes.service.js
@@ -1,8 +1,6 @@
-'use strict'
-
-const Joi = require('joi')
-const { metric } = require('../text-formatters')
-const { documentation, YouTubeVideoBase } = require('./youtube-base')
+import Joi from 'joi'
+import { metric } from '../text-formatters.js'
+import { documentation, YouTubeVideoBase } from './youtube-base.js'
 
 const documentationWithDislikes = `
   ${documentation}
@@ -16,7 +14,7 @@ const queryParamSchema = Joi.object({
   withDislikes: Joi.equal(''),
 }).required()
 
-module.exports = class YouTubeLikes extends YouTubeVideoBase {
+export default class YouTubeLikes extends YouTubeVideoBase {
   static route = {
     base: 'youtube/likes',
     pattern: ':videoId',
diff --git a/services/youtube/youtube-likes.tester.js b/services/youtube/youtube-likes.tester.js
index 5c266e0987323bafaa8aa6edf2a5734b339afcf7..8f6f8dc8fcac6d22a530f25c626aba289105b2bf 100644
--- a/services/youtube/youtube-likes.tester.js
+++ b/services/youtube/youtube-likes.tester.js
@@ -1,10 +1,10 @@
-'use strict'
-
-const Joi = require('joi')
-const t = (module.exports = require('../tester').createServiceTester())
-const { noToken } = require('../test-helpers')
-const { isMetric } = require('../test-validators')
-const noYouTubeToken = noToken(require('./youtube-likes.service'))
+import Joi from 'joi'
+import { createServiceTester } from '../tester.js'
+import { noToken } from '../test-helpers.js'
+import { isMetric } from '../test-validators.js'
+import _noYouTubeToken from './youtube-likes.service.js'
+export const t = await createServiceTester()
+const noYouTubeToken = noToken(_noYouTubeToken)
 
 t.create('video like count')
   .skipWhen(noYouTubeToken)
diff --git a/services/youtube/youtube-subscribers.service.js b/services/youtube/youtube-subscribers.service.js
index 408b451bae9087539e532cf411fba001e50d3a8e..0c0d1b69aaf702a5789eb710b176f686fe30ce50 100644
--- a/services/youtube/youtube-subscribers.service.js
+++ b/services/youtube/youtube-subscribers.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { documentation, YouTubeChannelBase } from './youtube-base.js'
 
-const { documentation, YouTubeChannelBase } = require('./youtube-base')
-
-module.exports = class YouTubeSubscribes extends YouTubeChannelBase {
+export default class YouTubeSubscribes extends YouTubeChannelBase {
   static route = {
     base: 'youtube/channel/subscribers',
     pattern: ':channelId',
diff --git a/services/youtube/youtube-subscribers.tester.js b/services/youtube/youtube-subscribers.tester.js
index acff789b0c64b4dfa5ee213d870e1474dd3eb17a..d1d1c5175996b9a73bbdd653da1607e5e664323d 100644
--- a/services/youtube/youtube-subscribers.tester.js
+++ b/services/youtube/youtube-subscribers.tester.js
@@ -1,9 +1,9 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { noToken } = require('../test-helpers')
-const { isMetric } = require('../test-validators')
-const noYouTubeToken = noToken(require('./youtube-subscribers.service'))
+import { createServiceTester } from '../tester.js'
+import { noToken } from '../test-helpers.js'
+import { isMetric } from '../test-validators.js'
+import _noYouTubeToken from './youtube-subscribers.service.js'
+export const t = await createServiceTester()
+const noYouTubeToken = noToken(_noYouTubeToken)
 
 t.create('subscriber count')
   .skipWhen(noYouTubeToken)
diff --git a/services/youtube/youtube-views.service.js b/services/youtube/youtube-views.service.js
index 5259e6818add2c7299673ab708f4cd5cd3ea97d0..32c2d6afa92ece56969b329483c8b543612162c9 100644
--- a/services/youtube/youtube-views.service.js
+++ b/services/youtube/youtube-views.service.js
@@ -1,8 +1,6 @@
-'use strict'
+import { documentation, YouTubeVideoBase } from './youtube-base.js'
 
-const { documentation, YouTubeVideoBase } = require('./youtube-base')
-
-module.exports = class YouTubeViews extends YouTubeVideoBase {
+export default class YouTubeViews extends YouTubeVideoBase {
   static route = {
     base: 'youtube/views',
     pattern: ':videoId',
diff --git a/services/youtube/youtube-views.tester.js b/services/youtube/youtube-views.tester.js
index af7c036daff382375d720c302163eb47987255b7..f825e71fb46f88b6c8d375c17a719aa2bb51d786 100644
--- a/services/youtube/youtube-views.tester.js
+++ b/services/youtube/youtube-views.tester.js
@@ -1,9 +1,9 @@
-'use strict'
-
-const t = (module.exports = require('../tester').createServiceTester())
-const { noToken } = require('../test-helpers')
-const { isMetric } = require('../test-validators')
-const noYouTubeToken = noToken(require('./youtube-views.service'))
+import { createServiceTester } from '../tester.js'
+import { noToken } from '../test-helpers.js'
+import { isMetric } from '../test-validators.js'
+import _noYouTubeToken from './youtube-views.service.js'
+export const t = await createServiceTester()
+const noYouTubeToken = noToken(_noYouTubeToken)
 
 t.create('video view count')
   .skipWhen(noYouTubeToken)