Serving a webpage that displays the HTTP request information sent by the client
Can I use other modules to make this job easier?

You can use some web framework like fastify or express.
This would ease the code a lot

For a job this simple, is it worth to work with HTML and CSS as separate files?

Assumig your project will grown, it is a good approach to move some &quot;static text&quot; in a separated file.

How are HTML and CSS normally handled inside JS files (edits, appends, etc)?

You have made a server side rendering (SSR) by your hand.
Since it would be hard to manage manually all those piece of strings and would be also dandgerous to
some script injection, you could use some fremework as vue
or other templating systems like handlebarsjs or others - here a list

How well am I handling the construction of HTML and CSS?

There could be some security issue for links like that if you start to process those values:
http://localhost:3000/?user=%3Cimg%20src=%27aaa%27%20onerror=alert(1)%3E
the framework protect you from these cases usually.
This code:
  const htmlTitle = '&lt;title&gt;Your Request Is&lt;/title&gt;'
  const htmlEncode = '&lt;meta charset=&quot;UTF-8&quot;&gt;'
  const htmlHead = `&lt;head&gt;${htmlTitle}${htmlCSS}${htmlEncode}&lt;/head&gt;`
  const htmlTop = `&lt;html lang=&quot;en&quot;&gt;${htmlHead}&lt;body&gt;`

produce every time the same output string, so you could do it once instead of every request:
this will stress less the nodejs garbage collector for high throughput site.

Can this be done more concisely?

You could write less code using some Object and Array functions:
function stringTemplates (request) {
  return `&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
&lt;title&gt;Your Request Is&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;table&gt;&lt;tbody&gt;
${Object.entries(request.headers).map(processLine).join('')}
${['httpVersion', 'httpVersionMinor', 'httpVersionMajor', 'method', 'url'].map(prop =&gt; processLine([prop, request[prop]])).join('')}
&lt;/tbody&gt;&lt;/table&gt;
&lt;/body&gt;
&lt;/html&gt;
`
}

function processLine ([header, value]) {
  return `&lt;tr&gt;&lt;td&gt;${header}&lt;/td&gt;&lt;td&gt;${value}&lt;/td&gt;&lt;/tr&gt;`
}


What would you do differently to improve this in any way?

This shows only GET, but in order to learn the HTTP standard it would useful to show in:

query parameters
form parameter (with different encoding)