JSFiddle - React, Tailwind, and code Playground

CSS

body {
	  margin: 0;
}

JavaScript

import * as THREE from 'https://cdn.skypack.dev/three'
import {
	NormalPass,
  RenderPass,
	EffectComposer,
  OverrideMaterialManager
} from 'https://cdn.skypack.dev/postprocessing'

let camera, scene, renderer;
let geometry, material, mesh1, mesh2;
let composer;

init();

function init() {

    camera = new THREE.PerspectiveCamera( 70, window.innerWidth / window.innerHeight, 0.01, 10 );
    camera.position.z = 1;

    scene = new THREE.Scene();

    material = new THREE.MeshBasicMaterial();

    // mesh with no normals and uses flat shading
    mesh1 = new THREE.Mesh(
    	new THREE.BoxGeometry( 0.2, 0.2, 0.2 ),
      new THREE.MeshNormalMaterial()
    );
    mesh1.position.x = - 0.15;
    mesh1.geometry.deleteAttribute( 'normal' );
    mesh1.material.flatShading = true;
    
    // mesh with a backside material
    mesh2 = new THREE.Mesh(
    	new THREE.BoxGeometry( 0.2, 0.2, 0.2 ),
      new THREE.MeshNormalMaterial()
    );
    mesh2.position.x = 0.15;
    mesh2.material.side = THREE.BackSide;
    
    scene.add( mesh1, mesh2 );

    renderer = new THREE.WebGLRenderer( { antialias: true } );
    renderer.setSize( window.innerWidth, window.innerHeight );
    renderer.setAnimationLoop( animation );
    document.body.appendChild( renderer.domElement );
    
    OverrideMaterialManager.workaroundEnabled = true;
    
    composer = new EffectComposer( renderer );
    composer.addPass( new RenderPass( scene, camera ) );
    composer.addPass( new NormalPass( scene, camera ) );

}

function animation( time ) {

    mesh1.rotation.x = time / 2000;
    mesh1.rotation.y = time / 1000;
    
    mesh2.rotation.x = time / 2000;
    mesh2.rotation.y = time / 1000;
    
    composer.render();

}