This example uses OpenLayers v10.9.0. The latest is v.
Edit

#### Reprojection with coordinate system search

reprojection 8 projection 14 proj4js 6 epsg 1 maptiler 26 graticule 3

#####

Search projection:
Render reprojection edges
Show tile coordinates
Show graticule

Demonstrates client-side raster reprojection of OSM to arbitrary projection

This example shows client-side raster reprojection capabilities from OSM (EPSG:3857) to arbitrary projection by searching in MapTiler Cloud Coordinates API. Note: Make sure to get your own API key at https://www.maptiler.com/cloud/ when using this example.

##### main.js

    import Map from 'ol/Map.js';
    import View from 'ol/View.js';
    import {applyTransform} from 'ol/extent.js';
    import Graticule from 'ol/layer/Graticule.js';
    import TileLayer from 'ol/layer/Tile.js';
    import {get as getProjection, getTransform} from 'ol/proj.js';
    import {register} from 'ol/proj/proj4.js';
    import OSM from 'ol/source/OSM.js';
    import TileDebug from 'ol/source/TileDebug.js';
    import Stroke from 'ol/style/Stroke.js';
    import proj4 from 'proj4';

    const key = 'Get your own API key at https://www.maptiler.com/cloud/';

    const osmSource = new OSM();

    const debugLayer = new TileLayer({
      source: new TileDebug({
        tileGrid: osmSource.getTileGrid(),
        projection: osmSource.getProjection(),
      }),
      visible: false,
    });

    const graticule = new Graticule({
      // the style to use for the lines, optional.
      strokeStyle: new Stroke({
        color: 'rgba(255,120,0,0.9)',
        width: 2,
        lineDash: [0.5, 4],
      }),
      showLabels: true,
      visible: false,
      wrapX: false,
    });

    const map = new Map({
      layers: [
        new TileLayer({
          source: osmSource,
        }),
        debugLayer,
        graticule,
      ],
      target: 'map',
      view: new View({
        projection: 'EPSG:3857',
        center: [0, 0],
        zoom: 1,
      }),
    });

    const queryInput = document.getElementById('epsg-query');
    const searchButton = document.getElementById('epsg-search');
    const resultSpan = document.getElementById('epsg-result');
    const renderEdgesCheckbox = document.getElementById('render-edges');
    const showTilesCheckbox = document.getElementById('show-tiles');
    const showGraticuleCheckbox = document.getElementById('show-graticule');

    function setProjection(code, name, proj4def, bbox) {
      if (code === null || name === null || proj4def === null || bbox === null) {
        resultSpan.innerHTML = 'Nothing usable found, using EPSG:3857...';
        map.setView(
          new View({
            projection: 'EPSG:3857',
            center: [0, 0],
            zoom: 1,
          }),
        );
        return;
      }

      resultSpan.innerHTML = '(' + code + ') ' + name;

      proj4.defs(code, proj4def);
      register(proj4);
      const newProj = getProjection(code);
      const fromLonLat = getTransform('EPSG:4326', newProj);

      newProj.setWorldExtent(bbox);

      // approximate calculation of projection extent,
      // checking if the world extent crosses the dateline
      if (bbox[0] > bbox[2]) {
        bbox[2] += 360;
      }
      const extent = applyTransform(bbox, fromLonLat, undefined, 8);
      newProj.setExtent(extent);
      const newView = new View({
        projection: newProj,
      });
      map.setView(newView);
      newView.fit(extent);
    }

    function search(query) {
      resultSpan.innerHTML = 'Searching ...';
      fetch(
        `https://api.maptiler.com/coordinates/search/${query}.json?exports=true&key=${key}`,
      )
        .then(function (response) {
          return response.json();
        })
        .then(function (json) {
          const results = json['results'];
          if (results && results.length > 0) {
            for (let i = 0, ii = results.length; i < ii; i++) {
              const result = results[i];
              if (result) {
                const id = result['id'];
                const code = id['authority'] + ':' + id['code'];
                const name = result['name'];
                const proj4def = result['exports']['wkt'];
                const bbox = result['bbox'];
                if (
                  code &&
                  code.length > 0 &&
                  proj4def &&
                  proj4def.length > 0 &&
                  bbox &&
                  bbox.length == 4
                ) {
                  setProjection(code, name, proj4def, bbox);
                  return;
                }
              }
            }
          }
          setProjection(null, null, null, null);
        });
    }

    /**
     * Handle click event.
     * @param {Event} event The event.
     */
    searchButton.onclick = function (event) {
      search(queryInput.value);
      event.preventDefault();
    };

    /**
     * Handle checkbox change events.
     */
    function onReprojectionChange() {
      osmSource.setRenderReprojectionEdges(renderEdgesCheckbox.checked);
    }
    function onGraticuleChange() {
      graticule.setVisible(showGraticuleCheckbox.checked);
    }
    function onTilesChange() {
      debugLayer.setVisible(showTilesCheckbox.checked);
    }
    showGraticuleCheckbox.addEventListener('change', onGraticuleChange);
    renderEdgesCheckbox.addEventListener('change', onReprojectionChange);
    showTilesCheckbox.addEventListener('change', onTilesChange);

    onReprojectionChange();
    onGraticuleChange();
    onTilesChange();

##### index.html

    <!DOCTYPE html>
    <html lang="en">
      <head>
        <meta charset="UTF-8">
        <title>Reprojection with coordinate system search</title>
        <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/css/bootstrap.min.css">
        <link rel="stylesheet" href="node_modules/ol/ol.css">
        <style>
          .map {
            width: 100%;
            height: 400px;
          }
        </style>
      </head>
      <body>
        <div id="map" class="map"></div>
        <form class="row">
          <span class="col-auto">
            <span class="input-group">
              <label class="input-group-text" for="epsg-query">Search projection:&nbsp</label>
              <input type="text" id="epsg-query" placeholder="4326, 27700, 3031, US National Atlas, Swiss, France, ..." class="form-control" size="50" />
              <button class="btn btn-outline-secondary" id="epsg-search">Search</button>
            </span>
          </span>
          <span class="mt-2" id="epsg-result">&nbsp;</span>
        </form>
        <form>
          <div class="form-check mt-2">
            <input class="form-check-input" type="checkbox" id="render-edges" />
            <label class="form-check-label" for="render-edges">Render reprojection edges</label><br>
          </div>
          <div class="form-check">
            <input class="form-check-input" type="checkbox" id="show-tiles" />
            <label class="form-check-label" for="show-tiles">Show tile coordinates</label><br>
          </div>
          <div class="form-check">
            <input class="form-check-input" type="checkbox" id="show-graticule" />
            <label class="form-check-label" for="show-graticule">Show graticule</label>
          </div>
        </form>

        <script type="module" src="main.js"></script>
      </body>
    </html>

##### package.json

    {
      "name": "reprojection-by-code",
      "dependencies": {
        "ol": "10.9.0",
        "proj4": "2.20.8"
      },
      "devDependencies": {
        "vite": "^3.2.3"
      },
      "scripts": {
        "start": "vite",
        "build": "vite build"
      }
    }