portals can get complex, especially entering them. the easiest is most likely drei/portal. a first rough scaffold of the website you linked could be done in a few minutes.
if you want this in vanilla it can only be done with a shader. it’s not enough to render a scene into a webglrendertarget using the same camera and project it onto a plane, that would skew it when you turn the camera. the plane has to act as a mask into the virtual scene instead.
as for entering, drei/portal uses a propperty “blend”. if it’s > 0 it renders the main scene and the portal as a mix until it reaches 1 and then it only renders the portal fullscreen, without needing to project it.
Portal rendering is a big topic and the things we’re calling “portals” aren’t always the same as portals in the sense of portal rendering in engines like unreal etc. or the game “portal” which do additional mathematical trickery to determine portal → portal visibility… so that portals that aren’t on-screen don’t need to be rendered… nor portals not visible through other portals recursively etc.
You can use stencil buffer &| depth buffer &| alpha &| clipping planes, to composite different views/scenes without shaders… and/or you can use rendertargets and shaders. You can also use renderer.viewport to restrict drawing to a subset of the framebuffer.
You could draw your main scene… then clear the depth buffer to the near plane depth… render the portal shape using depthFunc: always, with polygonOffset to the far depth…, then render the second scene from the second camera. You could also set [clipping planes]
(three.js docs) to clip to a portal shape.