diff --git a/core/badge-urls/make-badge-url.d.ts b/core/badge-urls/make-badge-url.d.ts
index 0da9d898988cb96024beb2409ca0a09c34bc982f..bf925cf72970eebc0fedb8bdbf476d677089fbed 100644
--- a/core/badge-urls/make-badge-url.d.ts
+++ b/core/badge-urls/make-badge-url.d.ts
@@ -14,24 +14,6 @@ export function badgeUrlFromPath({
   longCache?: boolean
 }): string
 
-export function badgeUrlFromPattern({
-  baseUrl,
-  pattern,
-  namedParams,
-  queryParams,
-  style,
-  format,
-  longCache,
-}: {
-  baseUrl?: string
-  pattern: string
-  namedParams: { [k: string]: string }
-  queryParams: { [k: string]: string | number | boolean }
-  style?: string
-  format?: string
-  longCache?: boolean
-}): string
-
 export function encodeField(s: string): string
 
 export function staticBadgeUrl({
diff --git a/core/badge-urls/make-badge-url.js b/core/badge-urls/make-badge-url.js
index 82e3f5fa251240453945a9814af32d13fdbd37fc..8870c9acea44ca736c5480bcc537346fcb35a703 100644
--- a/core/badge-urls/make-badge-url.js
+++ b/core/badge-urls/make-badge-url.js
@@ -1,7 +1,6 @@
 // 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 = '',
@@ -23,33 +22,6 @@ function badgeUrlFromPath({
   return `${baseUrl}${path}${outExt}${suffix}`
 }
 
-function badgeUrlFromPattern({
-  baseUrl = '',
-  pattern,
-  namedParams,
-  queryParams,
-  style,
-  format = '',
-  longCache = false,
-}) {
-  const toPath = compile(pattern, {
-    strict: true,
-    sensitive: true,
-    encode: encodeURIComponent,
-  })
-
-  const path = toPath(namedParams)
-
-  return badgeUrlFromPath({
-    baseUrl,
-    path,
-    queryParams,
-    style,
-    format,
-    longCache,
-  })
-}
-
 function encodeField(s) {
   return encodeURIComponent(s.replace(/-/g, '--').replace(/_/g, '__'))
 }
@@ -154,7 +126,6 @@ function rasterRedirectUrl({ rasterUrl }, badgeUrl) {
 
 export {
   badgeUrlFromPath,
-  badgeUrlFromPattern,
   encodeField,
   staticBadgeUrl,
   queryStringStaticBadgeUrl,
diff --git a/core/badge-urls/make-badge-url.spec.js b/core/badge-urls/make-badge-url.spec.js
index da0b156d5ea71d93608e9e66b30551e955b8a843..c8c3fcbb1bd87fa685a1feff2f02631b3c4f3e06 100644
--- a/core/badge-urls/make-badge-url.spec.js
+++ b/core/badge-urls/make-badge-url.spec.js
@@ -1,7 +1,6 @@
 import { test, given } from 'sazerac'
 import {
   badgeUrlFromPath,
-  badgeUrlFromPattern,
   encodeField,
   staticBadgeUrl,
   queryStringStaticBadgeUrl,
@@ -20,18 +19,6 @@ describe('Badge URL generation functions', function () {
     )
   })
 
-  test(badgeUrlFromPattern, () => {
-    given({
-      baseUrl: 'http://example.com',
-      pattern: '/npm/v/:packageName',
-      namedParams: { packageName: 'gh-badges' },
-      style: 'flat-square',
-      longCache: true,
-    }).expect(
-      'http://example.com/npm/v/gh-badges?cacheSeconds=2592000&style=flat-square'
-    )
-  })
-
   test(encodeField, () => {
     given('foo').expect('foo')
     given('').expect('')
diff --git a/core/server/server.js b/core/server/server.js
index 75c9e176bfb8c7ced8fa29d239a90d4995ee5e70..28aae21c66774b71a6fa4451289754e298183381 100644
--- a/core/server/server.js
+++ b/core/server/server.js
@@ -11,7 +11,6 @@ import originalJoi from 'joi'
 import makeBadge from '../../badge-maker/lib/make-badge.js'
 import GithubConstellation from '../../services/github/github-constellation.js'
 import LibrariesIoConstellation from '../../services/librariesio/librariesio-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'
@@ -113,6 +112,9 @@ const publicConfigSchema = Joi.object({
   redirectUrl: optionalUrl,
   rasterUrl: optionalUrl,
   cors: {
+    // This doesn't actually do anything
+    // TODO: maybe remove in future?
+    // https://github.com/badges/shields/pull/8311#discussion_r945337530
     allowedOrigin: Joi.array().items(optionalUrl).required(),
   },
   services: Joi.object({
@@ -488,7 +490,6 @@ class Server {
     const {
       bind: { port, address: hostname },
       ssl: { isSecure: secure, cert, key },
-      cors: { allowedOrigin },
       requireCloudflare,
     } = this.config.public
 
@@ -521,9 +522,6 @@ class Server {
       }
     }
 
-    const { apiProvider: githubApiProvider } = this.githubConstellation
-    setRoutes(allowedOrigin, githubApiProvider, camp)
-
     // https://github.com/badges/shields/issues/3273
     camp.handle((req, res, next) => {
       res.setHeader('Access-Control-Allow-Origin', '*')
diff --git a/cypress/e2e/main-page.cy.js b/cypress/e2e/main-page.cy.js
index 76d6e33eac493f2c68370ac904280a69a4484178..14a9c216137ad1d88fe9ab4e13b4e5296ba9c9ab 100644
--- a/cypress/e2e/main-page.cy.js
+++ b/cypress/e2e/main-page.cy.js
@@ -4,7 +4,7 @@ registerCommand()
 
 describe('Main page', function () {
   const backendUrl = Cypress.env('backend_url')
-  const SEARCH_INPUT = 'input[placeholder="search / project URL"]'
+  const SEARCH_INPUT = 'input[placeholder="search"]'
 
   function expectBadgeExample(title, previewUrl, pattern) {
     cy.contains('tr', `${title}:`).find('code').should('have.text', pattern)
@@ -36,35 +36,15 @@ describe('Main page', function () {
     )
   })
 
-  it('Suggest badges', function () {
-    const badgeUrl = `${backendUrl}/github/issues/badges/shields`
+  it('Customizate badges', function () {
     visitAndWait('/')
 
-    cy.get(SEARCH_INPUT).type('https://github.com/badges/shields')
-    cy.contains('Suggest badges').click()
+    cy.get(SEARCH_INPUT).type('issues')
 
-    expectBadgeExample('GitHub issues', badgeUrl, badgeUrl)
-  })
-
-  it('Customization form is filled with suggested badge details', function () {
-    const badgeUrl = `${backendUrl}/github/issues/badges/shields`
-    visitAndWait('/')
-    cy.get(SEARCH_INPUT).type('https://github.com/badges/shields')
-    cy.contains('Suggest badges').click()
-
-    cy.contains(badgeUrl).click()
-
-    cy.get('input[name="user"]').should('have.value', 'badges')
-    cy.get('input[name="repo"]').should('have.value', 'shields')
-  })
-
-  it('Customizate suggested badge', function () {
-    const badgeUrl = `${backendUrl}/github/issues/badges/shields`
-    visitAndWait('/')
-    cy.get(SEARCH_INPUT).type('https://github.com/badges/shields')
-    cy.contains('Suggest badges').click()
-    cy.contains(badgeUrl).click()
+    cy.contains('/github/issues/:user/:repo').click()
 
+    cy.get('input[name="user"]').type('badges')
+    cy.get('input[name="repo"]').type('shields')
     cy.get('table input[name="color"]').type('orange')
 
     cy.get(`img[src='${backendUrl}/github/issues/badges/shields?color=orange']`)
diff --git a/doc/code-walkthrough.md b/doc/code-walkthrough.md
index d72a7208d8be87954e820e867d68d91563d74057..0561d9664f82d07b6c5b20a96b0c694f43ed4e30 100644
--- a/doc/code-walkthrough.md
+++ b/doc/code-walkthrough.md
@@ -20,8 +20,6 @@ The Shields codebase is divided into several parts:
     1.  `*.js` in the root of [`services`][services]
 7.  The services themselves (about 80% of the code)
     1.  `*.js` in the folders of [`services`][services]
-8.  The badge suggestion endpoint (Note: it's tested as if it’s a service.)
-    1.  [`lib/suggest.js`][suggest]
 
 [frontend]: https://github.com/badges/shields/tree/master/frontend
 [badge-maker]: https://github.com/badges/shields/tree/master/badge-maker
@@ -29,7 +27,6 @@ The Shields codebase is divided into several parts:
 [server]: https://github.com/badges/shields/tree/master/core/server
 [token-pooling]: https://github.com/badges/shields/tree/master/core/token-pooling
 [services]: https://github.com/badges/shields/tree/master/services
-[suggest]: https://github.com/badges/shields/tree/master/lib/suggest.js
 
 The tests are also divided into several parts:
 
diff --git a/doc/self-hosting.md b/doc/self-hosting.md
index 68843fbf19fa4fb89bee63317680b9c9bf14d63e..3a6d6ec9cb5c5355b314d597f59c6e0f10353293 100644
--- a/doc/self-hosting.md
+++ b/doc/self-hosting.md
@@ -153,15 +153,6 @@ Then copy the contents of the `build/` folder to your static hosting / CDN.
 
 There are also a couple settings you should configure on the server.
 
-If you want to use server suggestions, you should also set `ALLOWED_ORIGIN`:
-
-```sh
-ALLOWED_ORIGIN=http://my-custom-shields.s3.amazonaws.com,https://my-custom-shields.s3.amazonaws.com
-```
-
-This should be a comma-separated list of allowed origin headers. They should
-not have paths or trailing slashes.
-
 To help out users, you can make the Shields server redirect the server root.
 Set the `REDIRECT_URI` environment variable:
 
diff --git a/frontend/components/badge-examples.tsx b/frontend/components/badge-examples.tsx
index 8c7a23bff316d18da92589f0ff03a8c9fa30c882..7d17b81827e2c2b3841e4b0d0526cce74963daca 100644
--- a/frontend/components/badge-examples.tsx
+++ b/frontend/components/badge-examples.tsx
@@ -2,13 +2,11 @@ import React from 'react'
 import styled from 'styled-components'
 import {
   badgeUrlFromPath,
-  badgeUrlFromPattern,
   staticBadgeUrl,
 } from '../../core/badge-urls/make-badge-url'
 import { removeRegexpFromPattern } from '../lib/pattern-helpers'
 import {
   Example as ExampleData,
-  Suggestion,
   RenderableExample,
 } from '../lib/service-definitions'
 import { Badge } from './common'
@@ -36,49 +34,34 @@ function Example({
   baseUrl,
   onClick,
   exampleData,
-  isBadgeSuggestion,
 }: {
   baseUrl?: string
-  onClick: (example: RenderableExample, isSuggestion: boolean) => void
+  onClick: (example: RenderableExample) => void
   exampleData: RenderableExample
-  isBadgeSuggestion: boolean
 }): JSX.Element {
   const handleClick = React.useCallback(
     function (): void {
-      onClick(exampleData, isBadgeSuggestion)
+      onClick(exampleData)
     },
-    [exampleData, isBadgeSuggestion, onClick]
+    [exampleData, onClick]
   )
 
-  let exampleUrl, previewUrl
-  if (isBadgeSuggestion) {
-    const {
-      example: { pattern, namedParams, queryParams },
-    } = exampleData as Suggestion
-    exampleUrl = previewUrl = badgeUrlFromPattern({
-      baseUrl,
-      pattern,
-      namedParams,
-      queryParams,
-    })
-  } else {
-    const {
-      example: { pattern, queryParams },
-      preview: { label, message, color, style, namedLogo },
-    } = exampleData as ExampleData
-    previewUrl = staticBadgeUrl({
-      baseUrl,
-      label: label || '',
-      message,
-      color,
-      style,
-      namedLogo,
-    })
-    exampleUrl = badgeUrlFromPath({
-      path: removeRegexpFromPattern(pattern),
-      queryParams,
-    })
-  }
+  const {
+    example: { pattern, queryParams },
+    preview: { label, message, color, style, namedLogo },
+  } = exampleData as ExampleData
+  const previewUrl = staticBadgeUrl({
+    baseUrl,
+    label: label || '',
+    message,
+    color,
+    style,
+    namedLogo,
+  })
+  const exampleUrl = badgeUrlFromPath({
+    path: removeRegexpFromPattern(pattern),
+    queryParams,
+  })
 
   const { title } = exampleData
   return (
@@ -101,14 +84,12 @@ function Example({
 
 export function BadgeExamples({
   examples,
-  areBadgeSuggestions,
   baseUrl,
   onClick,
 }: {
   examples: RenderableExample[]
-  areBadgeSuggestions: boolean
   baseUrl?: string
-  onClick: (exampleData: RenderableExample, isSuggestion: boolean) => void
+  onClick: (exampleData: RenderableExample) => void
 }): JSX.Element {
   return (
     <ExampleTable>
@@ -117,7 +98,6 @@ export function BadgeExamples({
           <Example
             baseUrl={baseUrl}
             exampleData={exampleData}
-            isBadgeSuggestion={areBadgeSuggestions}
             key={`${exampleData.title} ${exampleData.example.pattern}`}
             onClick={onClick}
           />
diff --git a/frontend/components/customizer/customizer.tsx b/frontend/components/customizer/customizer.tsx
index 663c38cfa08ec12b8872c0f65b1de97e94b4246f..503efc6741978b854217236944fcd35106014faa 100644
--- a/frontend/components/customizer/customizer.tsx
+++ b/frontend/components/customizer/customizer.tsx
@@ -18,8 +18,6 @@ export default function Customizer({
   exampleNamedParams,
   exampleQueryParams,
   initialStyle,
-  isPrefilled,
-  link = '',
 }: {
   baseUrl: string
   title: string
@@ -27,8 +25,6 @@ export default function Customizer({
   exampleNamedParams: { [k: string]: string }
   exampleQueryParams: { [k: string]: string }
   initialStyle?: string
-  isPrefilled: boolean
-  link?: string
 }): JSX.Element {
   // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/35572
   // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/28884#issuecomment-471341041
@@ -75,7 +71,6 @@ export default function Customizer({
       const builtBadgeUrl = generateBuiltBadgeUrl()
       const markup = generateMarkup({
         badgeUrl: builtBadgeUrl,
-        link,
         title,
         markupFormat,
       })
@@ -93,7 +88,7 @@ export default function Customizer({
         indicatorRef.current.trigger()
       }
     },
-    [generateBuiltBadgeUrl, link, title, setMessage, setMarkup]
+    [generateBuiltBadgeUrl, title, setMessage, setMarkup]
   )
 
   function renderMarkupAndLivePreview(): JSX.Element {
@@ -147,7 +142,6 @@ export default function Customizer({
     <form action="">
       <PathBuilder
         exampleParams={exampleNamedParams}
-        isPrefilled={isPrefilled}
         onChange={handlePathChange}
         pattern={pattern}
       />
diff --git a/frontend/components/customizer/path-builder.tsx b/frontend/components/customizer/path-builder.tsx
index 46e7d3cb676524f19f5684e20b44d7987d662cf8..5e4d10f653f9e12aae4b9c8ad6e0349235f6b647 100644
--- a/frontend/components/customizer/path-builder.tsx
+++ b/frontend/components/customizer/path-builder.tsx
@@ -112,7 +112,6 @@ export default function PathBuilder({
   pattern,
   exampleParams,
   onChange,
-  isPrefilled,
 }: {
   pattern: string
   exampleParams: { [k: string]: string }
@@ -123,22 +122,19 @@ export default function PathBuilder({
     path: string
     isComplete: boolean
   }) => void
-  isPrefilled: boolean
 }): JSX.Element {
   const [tokens] = useState(() => parse(pattern))
   const [namedParams, setNamedParams] = useState(() =>
-    isPrefilled
-      ? exampleParams
-      : // `pathToRegexp.parse()` returns a mixed array of strings for literals
-        // and  objects for parameters. Filter out the literals and work with the
-        // objects.
-        tokens
-          .filter(t => typeof t !== 'string')
-          .map(t => t as Key)
-          .reduce((accum, { name }) => {
-            accum[name] = ''
-            return accum
-          }, {} as { [k: string]: string })
+    // `pathToRegexp.parse()` returns a mixed array of strings for literals
+    // and  objects for parameters. Filter out the literals and work with the
+    // objects.
+    tokens
+      .filter(t => typeof t !== 'string')
+      .map(t => t as Key)
+      .reduce((accum, { name }) => {
+        accum[name] = ''
+        return accum
+      }, {} as { [k: string]: string })
   )
 
   useEffect(() => {
@@ -195,11 +191,11 @@ export default function PathBuilder({
           onChange={handleTokenChange}
           value={value}
         >
-          <option disabled={isPrefilled} key="empty" value="">
+          <option key="empty" value="">
             {' '}
           </option>
           {options.map(option => (
-            <option disabled={isPrefilled} key={option} value={option}>
+            <option key={option} value={option}>
               {option}
             </option>
           ))}
@@ -208,7 +204,6 @@ export default function PathBuilder({
     } else {
       return (
         <NamedParamInput
-          disabled={isPrefilled}
           name={name}
           onChange={handleTokenChange}
           type="text"
@@ -239,11 +234,9 @@ export default function PathBuilder({
             {optional ? <BuilderLabel>(optional)</BuilderLabel> : null}
           </NamedParamLabelContainer>
           {renderNamedParamInput(token)}
-          {!isPrefilled && (
-            <NamedParamCaption>
-              {namedParamIndex === 0 ? `e.g. ${exampleValue}` : exampleValue}
-            </NamedParamCaption>
-          )}
+          <NamedParamCaption>
+            {namedParamIndex === 0 ? `e.g. ${exampleValue}` : exampleValue}
+          </NamedParamCaption>
         </PathBuilderColumn>
       </React.Fragment>
     )
diff --git a/frontend/components/main.tsx b/frontend/components/main.tsx
index 99276c5aa494c7608f9149d3f09f85c0cfe787ad..e10acfe242f61e8443ccc5ddc00d2a7841f8a764 100644
--- a/frontend/components/main.tsx
+++ b/frontend/components/main.tsx
@@ -14,7 +14,7 @@ import ServiceDefinitionSetHelper from '../lib/service-definitions/service-defin
 import { getBaseUrl } from '../constants'
 import Meta from './meta'
 import Header from './header'
-import SuggestionAndSearch from './suggestion-and-search'
+import Search from './search'
 import DonateBox from './donate'
 import { MarkupModal } from './markup-modal'
 import Usage from './usage'
@@ -49,8 +49,6 @@ export default function Main({
     [k: string]: ServiceDefinition[]
   }>()
   const [selectedExample, setSelectedExample] = useState<RenderableExample>()
-  const [selectedExampleIsSuggestion, setSelectedExampleIsSuggestion] =
-    useState(false)
   const searchTimeout = useRef(0)
   const baseUrl = getBaseUrl()
 
@@ -92,14 +90,6 @@ export default function Main({
     [setSearchIsInProgress, performSearch]
   )
 
-  const exampleClicked = React.useCallback(
-    function (example: RenderableExample, isSuggestion: boolean): void {
-      setSelectedExample(example)
-      setSelectedExampleIsSuggestion(isSuggestion)
-    },
-    [setSelectedExample, setSelectedExampleIsSuggestion]
-  )
-
   const dismissMarkupModal = React.useCallback(
     function (): void {
       setSelectedExample(undefined)
@@ -123,7 +113,6 @@ export default function Main({
       <div>
         <CategoryHeading category={category} />
         <BadgeExamples
-          areBadgeSuggestions={false}
           baseUrl={baseUrl}
           examples={flattened}
           onClick={setSelectedExample}
@@ -182,15 +171,10 @@ export default function Main({
       <MarkupModal
         baseUrl={baseUrl}
         example={selectedExample}
-        isBadgeSuggestion={selectedExampleIsSuggestion}
         onRequestClose={dismissMarkupModal}
       />
       <section>
-        <SuggestionAndSearch
-          baseUrl={baseUrl}
-          onBadgeClick={exampleClicked}
-          queryChanged={searchQueryChanged}
-        />
+        <Search queryChanged={searchQueryChanged} />
         <DonateBox />
       </section>
       {renderMain()}
diff --git a/frontend/components/markup-modal/index.tsx b/frontend/components/markup-modal/index.tsx
index 238a8e644c79c9c370ce1de8e8e88ac2feb9d4b2..eb23fa05b1b1a04182243a0901ba8e0fb259184d 100644
--- a/frontend/components/markup-modal/index.tsx
+++ b/frontend/components/markup-modal/index.tsx
@@ -11,12 +11,10 @@ const ContentContainer = styled(BaseFont)`
 
 export function MarkupModal({
   example,
-  isBadgeSuggestion,
   baseUrl,
   onRequestClose,
 }: {
   example: RenderableExample | undefined
-  isBadgeSuggestion: boolean
   baseUrl: string
   onRequestClose: () => void
 }): JSX.Element {
@@ -29,11 +27,7 @@ export function MarkupModal({
     >
       {example !== undefined && (
         <ContentContainer>
-          <MarkupModalContent
-            baseUrl={baseUrl}
-            example={example}
-            isBadgeSuggestion={isBadgeSuggestion}
-          />
+          <MarkupModalContent baseUrl={baseUrl} example={example} />
         </ContentContainer>
       )}
     </Modal>
diff --git a/frontend/components/markup-modal/markup-modal-content.tsx b/frontend/components/markup-modal/markup-modal-content.tsx
index 6247e088a28bb6b905a6d983a031144af960a767..3736778807eeaacfb987c53994275ee46a198302 100644
--- a/frontend/components/markup-modal/markup-modal-content.tsx
+++ b/frontend/components/markup-modal/markup-modal-content.tsx
@@ -1,10 +1,6 @@
 import React from 'react'
 import styled from 'styled-components'
-import {
-  Example,
-  Suggestion,
-  RenderableExample,
-} from '../../lib/service-definitions'
+import { Example, RenderableExample } from '../../lib/service-definitions'
 import { H3 } from '../common'
 import Customizer from '../customizer/customizer'
 
@@ -16,20 +12,12 @@ const Documentation = styled.div`
 
 export function MarkupModalContent({
   example,
-  isBadgeSuggestion,
   baseUrl,
 }: {
   example: RenderableExample
-  isBadgeSuggestion: boolean
   baseUrl: string
 }): JSX.Element {
-  let documentation: { __html: string } | undefined
-  let link: string | undefined
-  if (isBadgeSuggestion) {
-    ;({ link } = example as Suggestion)
-  } else {
-    ;({ documentation } = example as Example)
-  }
+  const { documentation } = example as Example
 
   const {
     title,
@@ -48,8 +36,6 @@ export function MarkupModalContent({
         exampleNamedParams={namedParams}
         exampleQueryParams={queryParams}
         initialStyle={initialStyle}
-        isPrefilled={isBadgeSuggestion}
-        link={link}
         pattern={pattern}
         title={title}
       />
diff --git a/frontend/components/search.tsx b/frontend/components/search.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..d440e23c1a0f7ceb4fe0fe4919892636b444c768
--- /dev/null
+++ b/frontend/components/search.tsx
@@ -0,0 +1,37 @@
+import React, { useRef, ChangeEvent } from 'react'
+import debounce from 'lodash.debounce'
+import { BlockInput } from './common'
+
+export default function Search({
+  queryChanged,
+}: {
+  queryChanged: (query: string) => void
+}): JSX.Element {
+  const queryChangedDebounced = useRef(
+    debounce(queryChanged, 50, { leading: true })
+  )
+
+  const onQueryChanged = React.useCallback(
+    function ({
+      target: { value: query },
+    }: ChangeEvent<HTMLInputElement>): void {
+      queryChangedDebounced.current(query)
+    },
+    [queryChangedDebounced]
+  )
+
+  // TODO: Warning: A future version of React will block javascript: URLs as a security precaution
+  // how else to do this?
+  return (
+    <section>
+      <form action="javascript:void 0" autoComplete="off">
+        <BlockInput
+          autoComplete="off"
+          autoFocus
+          onChange={onQueryChanged}
+          placeholder="search"
+        />
+      </form>
+    </section>
+  )
+}
diff --git a/frontend/components/suggestion-and-search.tsx b/frontend/components/suggestion-and-search.tsx
deleted file mode 100644
index 7f62c0f84895897b6051fbf806290bb1ce4b5a96..0000000000000000000000000000000000000000
--- a/frontend/components/suggestion-and-search.tsx
+++ /dev/null
@@ -1,133 +0,0 @@
-import React, { useRef, useState, ChangeEvent } from 'react'
-import fetchPonyfill from 'fetch-ponyfill'
-import debounce from 'lodash.debounce'
-import { RenderableExample } from '../lib/service-definitions'
-import { BadgeExamples } from './badge-examples'
-import { BlockInput } from './common'
-
-interface SuggestionItem {
-  title: string
-  link: string
-  example: {
-    pattern: string
-    namedParams: { [k: string]: string }
-    queryParams?: { [k: string]: string }
-  }
-  preview:
-    | {
-        style?: string
-      }
-    | undefined
-}
-
-interface SuggestionResponse {
-  suggestions: SuggestionItem[]
-}
-
-export default function SuggestionAndSearch({
-  queryChanged,
-  onBadgeClick,
-  baseUrl,
-}: {
-  queryChanged: (query: string) => void
-  onBadgeClick: (example: RenderableExample, isSuggestion: boolean) => void
-  baseUrl: string
-}): JSX.Element {
-  const queryChangedDebounced = useRef(
-    debounce(queryChanged, 50, { leading: true })
-  )
-  const [isUrl, setIsUrl] = useState(false)
-  const [inProgress, setInProgress] = useState(false)
-  const [projectUrl, setProjectUrl] = useState<string>()
-  const [suggestions, setSuggestions] = useState<SuggestionItem[]>([])
-
-  const onQueryChanged = React.useCallback(
-    function ({
-      target: { value: query },
-    }: ChangeEvent<HTMLInputElement>): void {
-      const isUrl = query.startsWith('https://') || query.startsWith('http://')
-      setIsUrl(isUrl)
-      setProjectUrl(isUrl ? query : undefined)
-
-      queryChangedDebounced.current(query)
-    },
-    [setIsUrl, setProjectUrl, queryChangedDebounced]
-  )
-
-  const getSuggestions = React.useCallback(
-    async function (): Promise<void> {
-      if (!projectUrl) {
-        setSuggestions([])
-        return
-      }
-
-      setInProgress(true)
-
-      const fetch = window.fetch || fetchPonyfill
-      const res = await fetch(
-        `${baseUrl}/$suggest/v1?url=${encodeURIComponent(projectUrl)}`
-      )
-      let suggestions = [] as SuggestionItem[]
-      try {
-        const json = (await res.json()) as SuggestionResponse
-        // This doesn't validate the response. The default value here prevents
-        // a crash if the server returns {"err":"Disallowed"}.
-        suggestions = json.suggestions || []
-      } catch (e) {
-        suggestions = []
-      }
-
-      setInProgress(false)
-      setSuggestions(suggestions)
-    },
-    [setSuggestions, setInProgress, baseUrl, projectUrl]
-  )
-
-  function renderSuggestions(): JSX.Element | null {
-    if (suggestions.length === 0) {
-      return null
-    }
-
-    const transformed = suggestions.map(
-      ({ title, link, example, preview }) => ({
-        title,
-        link,
-        example: {
-          ...example,
-          queryParams: example.queryParams || {},
-        },
-        preview: preview || {},
-        isBadgeSuggestion: true,
-      })
-    )
-
-    return (
-      <BadgeExamples
-        areBadgeSuggestions
-        baseUrl={baseUrl}
-        examples={transformed}
-        onClick={onBadgeClick}
-      />
-    )
-  }
-
-  // TODO: Warning: A future version of React will block javascript: URLs as a security precaution
-  // how else to do this?
-  return (
-    <section>
-      <form action="javascript:void 0" autoComplete="off">
-        <BlockInput
-          autoComplete="off"
-          autoFocus
-          onChange={onQueryChanged}
-          placeholder="search / project URL"
-        />
-        <br />
-        <button disabled={inProgress} hidden={!isUrl} onClick={getSuggestions}>
-          Suggest badges
-        </button>
-      </form>
-      {renderSuggestions()}
-    </section>
-  )
-}
diff --git a/frontend/lib/generate-image-markup.spec.ts b/frontend/lib/generate-image-markup.spec.ts
index 786eb211f7c8ef9fa7f8a0e8cc6ef9b22675fbb8..64740e44b60d7c167ed7bf64cde9b1b9125f08bc 100644
--- a/frontend/lib/generate-image-markup.spec.ts
+++ b/frontend/lib/generate-image-markup.spec.ts
@@ -18,48 +18,30 @@ test(bareLink, () => {
 })
 
 test(html, () => {
-  given(
-    'https://img.shields.io/badge',
-    'https://example.com/example',
-    'Example'
-  ).expect(
-    '<a href="https://example.com/example"><img alt="Example" src="https://img.shields.io/badge"></a>'
+  given('https://img.shields.io/badge', 'Example').expect(
+    '<img alt="Example" src="https://img.shields.io/badge">'
   )
-  given('https://img.shields.io/badge', undefined, undefined).expect(
+  given('https://img.shields.io/badge', undefined).expect(
     '<img src="https://img.shields.io/badge">'
   )
 })
 
 test(markdown, () => {
-  given('https://img.shields.io/badge', undefined, 'Example').expect(
+  given('https://img.shields.io/badge', 'Example').expect(
     '![Example](https://img.shields.io/badge)'
   )
-  given(
-    'https://img.shields.io/badge',
-    'https://example.com/example',
-    'Example'
-  ).expect(
-    '[![Example](https://img.shields.io/badge)](https://example.com/example)'
-  )
-  given('https://img.shields.io/badge', undefined, undefined).expect(
+  given('https://img.shields.io/badge', undefined).expect(
     '![](https://img.shields.io/badge)'
   )
 })
 
 test(reStructuredText, () => {
-  given('https://img.shields.io/badge', undefined, undefined).expect(
+  given('https://img.shields.io/badge', undefined).expect(
     '.. image:: https://img.shields.io/badge'
   )
-  given('https://img.shields.io/badge', undefined, 'Example').expect(
+  given('https://img.shields.io/badge', 'Example').expect(
     '.. image:: https://img.shields.io/badge\n   :alt: Example'
   )
-  given(
-    'https://img.shields.io/badge',
-    'https://example.com/example',
-    'Example'
-  ).expect(
-    '.. image:: https://img.shields.io/badge\n   :alt: Example\n   :target: https://example.com/example'
-  )
 })
 
 test(renderAsciiDocAttributes, () => {
@@ -70,33 +52,21 @@ test(renderAsciiDocAttributes, () => {
 })
 
 test(asciiDoc, () => {
-  given('https://img.shields.io/badge', undefined, undefined).expect(
+  given('https://img.shields.io/badge', undefined).expect(
     'image:https://img.shields.io/badge[]'
   )
-  given('https://img.shields.io/badge', undefined, 'Example').expect(
+  given('https://img.shields.io/badge', 'Example').expect(
     'image:https://img.shields.io/badge[Example]'
   )
-  given(
-    'https://img.shields.io/badge',
-    undefined,
-    'Example, with comma'
-  ).expect('image:https://img.shields.io/badge["Example, with comma"]')
-  given(
-    'https://img.shields.io/badge',
-    'https://example.com/example',
-    'Example'
-  ).expect(
-    'image:https://img.shields.io/badge["Example",link="https://example.com/example"]'
+  given('https://img.shields.io/badge', 'Example, with comma').expect(
+    'image:https://img.shields.io/badge["Example, with comma"]'
   )
 })
 
 test(generateMarkup, () => {
   given({
     badgeUrl: 'https://img.shields.io/badge',
-    link: 'https://example.com/example',
     title: 'Example',
     markupFormat: 'markdown',
-  }).expect(
-    '[![Example](https://img.shields.io/badge)](https://example.com/example)'
-  )
+  }).expect('![Example](https://img.shields.io/badge)')
 })
diff --git a/frontend/lib/generate-image-markup.ts b/frontend/lib/generate-image-markup.ts
index f9e4f291eebf171708bbb115432a67c2ad4ed9e8..b83964fe3ec82eaefa44b0ab9bce3a4ea5a564ed 100644
--- a/frontend/lib/generate-image-markup.ts
+++ b/frontend/lib/generate-image-markup.ts
@@ -2,42 +2,21 @@ export function bareLink(badgeUrl: string, link?: string, title = ''): string {
   return badgeUrl
 }
 
-export function html(badgeUrl: string, link?: string, title?: string): string {
+export function html(badgeUrl: string, title?: string): string {
   // To be more robust, this should escape the title.
   const alt = title ? ` alt="${title}"` : ''
-  const img = `<img${alt} src="${badgeUrl}">`
-  if (link) {
-    return `<a href="${link}">${img}</a>`
-  } else {
-    return img
-  }
+  return `<img${alt} src="${badgeUrl}">`
 }
 
-export function markdown(
-  badgeUrl: string,
-  link?: string,
-  title?: string
-): string {
-  const withoutLink = `![${title || ''}](${badgeUrl})`
-  if (link) {
-    return `[${withoutLink}](${link})`
-  } else {
-    return withoutLink
-  }
+export function markdown(badgeUrl: string, title?: string): string {
+  return `![${title || ''}](${badgeUrl})`
 }
 
-export function reStructuredText(
-  badgeUrl: string,
-  link?: string,
-  title?: string
-): string {
+export function reStructuredText(badgeUrl: string, title?: string): string {
   let result = `.. image:: ${badgeUrl}`
   if (title) {
     result += `\n   :alt: ${title}`
   }
-  if (link) {
-    result += `\n   :target: ${link}`
-  }
   return result
 }
 
@@ -91,13 +70,9 @@ export function renderAsciiDocAttributes(
   }
 }
 
-export function asciiDoc(
-  badgeUrl: string,
-  link?: string,
-  title?: string
-): string {
+export function asciiDoc(badgeUrl: string, title?: string): string {
   const positional = title ? [title] : []
-  const named = link ? { link } : ({} as { [k: string]: string })
+  const named = {} as { [k: string]: string }
   const attrs = renderAsciiDocAttributes(positional, named)
   return `image:${badgeUrl}${attrs}`
 }
@@ -106,12 +81,10 @@ export type MarkupFormat = 'markdown' | 'rst' | 'asciidoc' | 'link' | 'html'
 
 export function generateMarkup({
   badgeUrl,
-  link,
   title,
   markupFormat,
 }: {
   badgeUrl: string
-  link?: string
   title?: string
   markupFormat: MarkupFormat
 }): string {
@@ -122,5 +95,5 @@ export function generateMarkup({
     link: bareLink,
     html,
   }[markupFormat]
-  return generatorFn(badgeUrl, link, title)
+  return generatorFn(badgeUrl, title)
 }
diff --git a/frontend/lib/service-definitions/index.ts b/frontend/lib/service-definitions/index.ts
index 31fe5ed8b4250a0870165c763e24244c4c336979..bea8dc4abde7165fe5bd75254edf0c61105865d5 100644
--- a/frontend/lib/service-definitions/index.ts
+++ b/frontend/lib/service-definitions/index.ts
@@ -64,13 +64,4 @@ export function getDefinitionsForCategory(
   return byCategory[category] || []
 }
 
-export interface Suggestion {
-  title: string
-  link: string
-  example: ExampleSignature
-  preview: {
-    style?: string
-  }
-}
-
-export type RenderableExample = Example | Suggestion
+export type RenderableExample = Example
diff --git a/frontend/pages/endpoint.tsx b/frontend/pages/endpoint.tsx
index aef1c029a72494d89ad8f63363900b7d178cf733..fc93aa756b62445e4c206336a7154cf45a61b211 100644
--- a/frontend/pages/endpoint.tsx
+++ b/frontend/pages/endpoint.tsx
@@ -244,7 +244,6 @@ export default function EndpointPage(): JSX.Element {
         exampleQueryParams={{
           url: 'https://shields.redsparr0w.com/2473/monday',
         }}
-        isPrefilled={false}
         pattern="/endpoint"
         title="Custom badge"
       />
diff --git a/services/suggest.integration.js b/services/suggest.integration.js
deleted file mode 100644
index 68efaafcaae4f7bcbc7a3ab999742a69d2a305db..0000000000000000000000000000000000000000
--- a/services/suggest.integration.js
+++ /dev/null
@@ -1,270 +0,0 @@
-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.util.toObject().private.gh_token
-    if (!token) {
-      throw Error('The integration tests require a gh_token to be set')
-    }
-    apiProvider = new GithubApiProvider({
-      baseUrl: githubApiBaseUrl,
-      globalToken: token,
-      withPooling: false,
-    })
-  })
-
-  let port, baseUrl
-  before(async function () {
-    port = await portfinder.getPortPromise()
-    baseUrl = `http://127.0.0.1:${port}`
-  })
-
-  let camp
-  before(async function () {
-    camp = Camp.start({ port, hostname: '::' })
-    await new Promise(resolve => camp.on('listening', () => resolve()))
-  })
-  after(async function () {
-    if (camp) {
-      await new Promise(resolve => camp.close(resolve))
-      camp = undefined
-    }
-  })
-
-  const origin = 'https://example.test'
-  before(function () {
-    setRoutes([origin], apiProvider, camp)
-  })
-  describe('GitHub', function () {
-    context('with an existing project', function () {
-      it('returns the expected suggestions', async function () {
-        const { statusCode, body } = await got(
-          `${baseUrl}/$suggest/v1?url=${encodeURIComponent(
-            'https://github.com/atom/atom'
-          )}`,
-          {
-            responseType: 'json',
-          }
-        )
-        expect(statusCode).to.equal(200)
-        expect(body).to.deep.equal({
-          suggestions: [
-            {
-              title: 'GitHub issues',
-              link: 'https://github.com/atom/atom/issues',
-              example: {
-                pattern: '/github/issues/:user/:repo',
-                namedParams: { user: 'atom', repo: 'atom' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'GitHub forks',
-              link: 'https://github.com/atom/atom/network',
-              example: {
-                pattern: '/github/forks/:user/:repo',
-                namedParams: { user: 'atom', repo: 'atom' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'GitHub stars',
-              link: 'https://github.com/atom/atom/stargazers',
-              example: {
-                pattern: '/github/stars/:user/:repo',
-                namedParams: { user: 'atom', repo: 'atom' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'GitHub license',
-              link: 'https://github.com/atom/atom/blob/master/LICENSE.md',
-              example: {
-                pattern: '/github/license/:user/:repo',
-                namedParams: { user: 'atom', repo: 'atom' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'Twitter',
-              link: 'https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2Fatom%2Fatom',
-              example: {
-                pattern: '/twitter/url',
-                namedParams: {},
-                queryParams: {
-                  url: 'https://github.com/atom/atom',
-                },
-              },
-              preview: {
-                style: 'social',
-              },
-            },
-          ],
-        })
-      })
-    })
-
-    context('with a non-existent project', function () {
-      it('returns the expected suggestions', async function () {
-        this.timeout(5000)
-
-        const { statusCode, body } = await got(
-          `${baseUrl}/$suggest/v1?url=${encodeURIComponent(
-            'https://github.com/badges/not-a-real-project'
-          )}`,
-          {
-            responseType: 'json',
-          }
-        )
-        expect(statusCode).to.equal(200)
-        expect(body).to.deep.equal({
-          suggestions: [
-            {
-              title: 'GitHub issues',
-              link: 'https://github.com/badges/not-a-real-project/issues',
-              example: {
-                pattern: '/github/issues/:user/:repo',
-                namedParams: { user: 'badges', repo: 'not-a-real-project' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'GitHub forks',
-              link: 'https://github.com/badges/not-a-real-project/network',
-              example: {
-                pattern: '/github/forks/:user/:repo',
-                namedParams: { user: 'badges', repo: 'not-a-real-project' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'GitHub stars',
-              link: 'https://github.com/badges/not-a-real-project/stargazers',
-              example: {
-                pattern: '/github/stars/:user/:repo',
-                namedParams: { user: 'badges', repo: 'not-a-real-project' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'GitHub license',
-              link: 'https://github.com/badges/not-a-real-project',
-              example: {
-                pattern: '/github/license/:user/:repo',
-                namedParams: { user: 'badges', repo: 'not-a-real-project' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'Twitter',
-              link: 'https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2Fbadges%2Fnot-a-real-project',
-              example: {
-                pattern: '/twitter/url',
-                namedParams: {},
-                queryParams: {
-                  url: 'https://github.com/badges/not-a-real-project',
-                },
-              },
-              preview: {
-                style: 'social',
-              },
-            },
-          ],
-        })
-      })
-    })
-  })
-
-  describe('GitLab', function () {
-    context('with an existing project', function () {
-      it('returns the expected suggestions', async function () {
-        const { statusCode, body } = await got(
-          `${baseUrl}/$suggest/v1?url=${encodeURIComponent(
-            'https://gitlab.com/gitlab-org/gitlab'
-          )}`,
-          {
-            responseType: 'json',
-          }
-        )
-        expect(statusCode).to.equal(200)
-        expect(body).to.deep.equal({
-          suggestions: [
-            {
-              title: 'GitLab pipeline',
-              link: 'https://gitlab.com/gitlab-org/gitlab/builds',
-              example: {
-                pattern: '/gitlab/pipeline/:user/:repo',
-                namedParams: { user: 'gitlab-org', repo: 'gitlab' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'Twitter',
-              link: 'https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgitlab.com%2Fgitlab-org%2Fgitlab',
-              example: {
-                pattern: '/twitter/url',
-                namedParams: {},
-                queryParams: {
-                  url: 'https://gitlab.com/gitlab-org/gitlab',
-                },
-              },
-              preview: {
-                style: 'social',
-              },
-            },
-          ],
-        })
-      })
-    })
-
-    context('with an nonexisting project', function () {
-      it('returns the expected suggestions', async function () {
-        const { statusCode, body } = await got(
-          `${baseUrl}/$suggest/v1?url=${encodeURIComponent(
-            'https://gitlab.com/gitlab-org/not-gitlab'
-          )}`,
-          {
-            responseType: 'json',
-          }
-        )
-        expect(statusCode).to.equal(200)
-        expect(body).to.deep.equal({
-          suggestions: [
-            {
-              title: 'GitLab pipeline',
-              link: 'https://gitlab.com/gitlab-org/not-gitlab/builds',
-              example: {
-                pattern: '/gitlab/pipeline/:user/:repo',
-                namedParams: { user: 'gitlab-org', repo: 'not-gitlab' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'Twitter',
-              link: 'https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgitlab.com%2Fgitlab-org%2Fnot-gitlab',
-              example: {
-                pattern: '/twitter/url',
-                namedParams: {},
-                queryParams: {
-                  url: 'https://gitlab.com/gitlab-org/not-gitlab',
-                },
-              },
-              preview: {
-                style: 'social',
-              },
-            },
-          ],
-        })
-      })
-    })
-  })
-})
diff --git a/services/suggest.js b/services/suggest.js
deleted file mode 100644
index 6e2936265b729474d57e53d285b92e2667bc84d8..0000000000000000000000000000000000000000
--- a/services/suggest.js
+++ /dev/null
@@ -1,201 +0,0 @@
-// Suggestion API
-//
-// eg. /$suggest/v1?url=https://github.com/badges/shields
-//
-// This endpoint is called from frontend/components/suggestion-and-search.js.
-
-import { URL } from 'url'
-import { fetch } from '../core/base-service/got.js'
-
-function twitterPage(url) {
-  if (url.protocol === null) {
-    return null
-  }
-
-  const schema = url.protocol.slice(0, -1)
-  const host = url.host
-  const path = url.pathname
-  return {
-    title: 'Twitter',
-    link: `https://twitter.com/intent/tweet?text=Wow:&url=${encodeURIComponent(
-      url.href
-    )}`,
-    example: {
-      pattern: '/twitter/url',
-      namedParams: {},
-      queryParams: { url: `${schema}://${host}${path}` },
-    },
-    preview: {
-      style: 'social',
-    },
-  }
-}
-
-function githubIssues(user, repo) {
-  const repoSlug = `${user}/${repo}`
-  return {
-    title: 'GitHub issues',
-    link: `https://github.com/${repoSlug}/issues`,
-    example: {
-      pattern: '/github/issues/:user/:repo',
-      namedParams: { user, repo },
-      queryParams: {},
-    },
-  }
-}
-
-function githubForks(user, repo) {
-  const repoSlug = `${user}/${repo}`
-  return {
-    title: 'GitHub forks',
-    link: `https://github.com/${repoSlug}/network`,
-    example: {
-      pattern: '/github/forks/:user/:repo',
-      namedParams: { user, repo },
-      queryParams: {},
-    },
-  }
-}
-
-function githubStars(user, repo) {
-  const repoSlug = `${user}/${repo}`
-  return {
-    title: 'GitHub stars',
-    link: `https://github.com/${repoSlug}/stargazers`,
-    example: {
-      pattern: '/github/stars/:user/:repo',
-      namedParams: { user, repo },
-      queryParams: {},
-    },
-  }
-}
-
-async function githubLicense(githubApiProvider, user, repo) {
-  const repoSlug = `${user}/${repo}`
-
-  let link = `https://github.com/${repoSlug}`
-
-  const { buffer } = await githubApiProvider.fetch(
-    fetch,
-    `/repos/${repoSlug}/license`
-  )
-  try {
-    const data = JSON.parse(buffer)
-    if ('html_url' in data) {
-      link = data.html_url
-    }
-  } catch (e) {}
-
-  return {
-    title: 'GitHub license',
-    link,
-    example: {
-      pattern: '/github/license/:user/:repo',
-      namedParams: { user, repo },
-      queryParams: {},
-    },
-  }
-}
-
-function gitlabPipeline(user, repo) {
-  const repoSlug = `${user}/${repo}`
-  return {
-    title: 'GitLab pipeline',
-    link: `https://gitlab.com/${repoSlug}/builds`,
-    example: {
-      pattern: '/gitlab/pipeline/:user/:repo',
-      namedParams: { user, repo },
-      queryParams: {},
-    },
-  }
-}
-
-async function findSuggestions(githubApiProvider, url) {
-  let promises = []
-  if (url.hostname === 'github.com' || url.hostname === 'gitlab.com') {
-    const userRepo = url.pathname.slice(1).split('/')
-    const user = userRepo[0]
-    const repo = userRepo[1]
-    if (url.hostname === 'github.com') {
-      promises = promises.concat([
-        githubIssues(user, repo),
-        githubForks(user, repo),
-        githubStars(user, repo),
-        githubLicense(githubApiProvider, user, repo),
-      ])
-    } else {
-      promises = promises.concat([gitlabPipeline(user, repo)])
-    }
-  }
-  promises.push(twitterPage(url))
-
-  const suggestions = await Promise.all(promises)
-
-  return suggestions.filter(b => b != null)
-}
-
-// data: {url}, JSON-serializable object.
-// end: function(json), with json of the form:
-//  - suggestions: list of objects of the form:
-//    - title: string
-//    - link: target as a string URL
-//    - example: object
-//      - pattern: string
-//      - namedParams: object
-//      - queryParams: object (optional)
-//        - link: target as a string URL
-//    - preview: object (optional)
-//      - style: string
-function setRoutes(allowedOrigin, githubApiProvider, server) {
-  server.ajax.on('suggest/v1', (data, end, ask) => {
-    // The typical dev and production setups are cross-origin. However, in
-    // Heroku deploys and some self-hosted deploys these requests may come from
-    // the same host. Chrome does not send an Origin header on same-origin
-    // requests, but Firefox does.
-    //
-    // It would be better to solve this problem using some well-tested
-    // middleware.
-    const origin = ask.req.headers.origin
-    if (origin) {
-      let host
-      try {
-        host = new URL(origin).hostname
-      } catch (e) {
-        ask.res.setHeader('Access-Control-Allow-Origin', 'null')
-        end({ err: 'Disallowed' })
-        return
-      }
-
-      if (host !== ask.req.headers.host) {
-        if (allowedOrigin.includes(origin)) {
-          ask.res.setHeader('Access-Control-Allow-Origin', origin)
-        } else {
-          ask.res.setHeader('Access-Control-Allow-Origin', 'null')
-          end({ err: 'Disallowed' })
-          return
-        }
-      }
-    }
-
-    let url
-    try {
-      url = new URL(data.url)
-    } catch (e) {
-      end({ err: `${e}` })
-      return
-    }
-
-    findSuggestions(githubApiProvider, url)
-      // This interacts with callback code and can't use async/await.
-      // eslint-disable-next-line promise/prefer-await-to-then
-      .then(suggestions => {
-        end({ suggestions })
-      })
-      // eslint-disable-next-line promise/prefer-await-to-then
-      .catch(err => {
-        end({ suggestions: [], err })
-      })
-  })
-}
-
-export { findSuggestions, githubLicense, setRoutes }
diff --git a/services/suggest.spec.js b/services/suggest.spec.js
deleted file mode 100644
index 3e2a9c8f495c11cd56be0222c1385bd9df2cbccb..0000000000000000000000000000000000000000
--- a/services/suggest.spec.js
+++ /dev/null
@@ -1,177 +0,0 @@
-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'
-  const apiProvider = new GithubApiProvider({
-    baseUrl: githubApiBaseUrl,
-    globalToken: 'fake-token',
-    withPooling: false,
-  })
-
-  describe('GitHub license', function () {
-    context('When html_url included in response', function () {
-      it('Should link to it', async function () {
-        const scope = nock(githubApiBaseUrl)
-          .get('/repos/atom/atom/license')
-          .reply(200, {
-            html_url: 'https://github.com/atom/atom/blob/master/LICENSE.md',
-            license: {
-              key: 'mit',
-              name: 'MIT License',
-              spdx_id: 'MIT',
-              url: 'https://api.github.com/licenses/mit',
-              node_id: 'MDc6TGljZW5zZTEz',
-            },
-          })
-
-        expect(await githubLicense(apiProvider, 'atom', 'atom')).to.deep.equal({
-          title: 'GitHub license',
-          link: 'https://github.com/atom/atom/blob/master/LICENSE.md',
-          example: {
-            pattern: '/github/license/:user/:repo',
-            namedParams: { user: 'atom', repo: 'atom' },
-            queryParams: {},
-          },
-        })
-
-        scope.done()
-      })
-    })
-
-    context('When html_url not included in response', function () {
-      it('Should link to the repo', async function () {
-        const scope = nock(githubApiBaseUrl)
-          .get('/repos/atom/atom/license')
-          .reply(200, {
-            license: { key: 'mit' },
-          })
-
-        expect(await githubLicense(apiProvider, 'atom', 'atom')).to.deep.equal({
-          title: 'GitHub license',
-          link: 'https://github.com/atom/atom',
-          example: {
-            pattern: '/github/license/:user/:repo',
-            namedParams: { user: 'atom', repo: 'atom' },
-            queryParams: {},
-          },
-        })
-
-        scope.done()
-      })
-    })
-  })
-
-  describe('Scoutcamp integration', function () {
-    let port, baseUrl
-    before(async function () {
-      port = await portfinder.getPortPromise()
-      baseUrl = `http://127.0.0.1:${port}`
-    })
-
-    let camp
-    before(async function () {
-      camp = Camp.start({ port, hostname: '::' })
-      await new Promise(resolve => camp.on('listening', () => resolve()))
-    })
-    after(async function () {
-      if (camp) {
-        await new Promise(resolve => camp.close(resolve))
-        camp = undefined
-      }
-    })
-
-    const origin = 'https://example.test'
-    before(function () {
-      setRoutes([origin], apiProvider, camp)
-    })
-
-    context('without an origin header', function () {
-      it('returns the expected suggestions', async function () {
-        const scope = nock(githubApiBaseUrl)
-          .get('/repos/atom/atom/license')
-          .reply(200, {
-            html_url: 'https://github.com/atom/atom/blob/master/LICENSE.md',
-            license: {
-              key: 'mit',
-              name: 'MIT License',
-              spdx_id: 'MIT',
-              url: 'https://api.github.com/licenses/mit',
-              node_id: 'MDc6TGljZW5zZTEz',
-            },
-          })
-
-        const { statusCode, body } = await got(
-          `${baseUrl}/$suggest/v1?url=${encodeURIComponent(
-            'https://github.com/atom/atom'
-          )}`,
-          {
-            responseType: 'json',
-          }
-        )
-        expect(statusCode).to.equal(200)
-        expect(body).to.deep.equal({
-          suggestions: [
-            {
-              title: 'GitHub issues',
-              link: 'https://github.com/atom/atom/issues',
-              example: {
-                pattern: '/github/issues/:user/:repo',
-                namedParams: { user: 'atom', repo: 'atom' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'GitHub forks',
-              link: 'https://github.com/atom/atom/network',
-              example: {
-                pattern: '/github/forks/:user/:repo',
-                namedParams: { user: 'atom', repo: 'atom' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'GitHub stars',
-              link: 'https://github.com/atom/atom/stargazers',
-              example: {
-                pattern: '/github/stars/:user/:repo',
-                namedParams: { user: 'atom', repo: 'atom' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'GitHub license',
-              link: 'https://github.com/atom/atom/blob/master/LICENSE.md',
-              example: {
-                pattern: '/github/license/:user/:repo',
-                namedParams: { user: 'atom', repo: 'atom' },
-                queryParams: {},
-              },
-            },
-            {
-              title: 'Twitter',
-              link: 'https://twitter.com/intent/tweet?text=Wow:&url=https%3A%2F%2Fgithub.com%2Fatom%2Fatom',
-              example: {
-                pattern: '/twitter/url',
-                namedParams: {},
-                queryParams: {
-                  url: 'https://github.com/atom/atom',
-                },
-              },
-              preview: {
-                style: 'social',
-              },
-            },
-          ],
-        })
-
-        scope.done()
-      })
-    })
-  })
-})