Serve a web client

Prompt:

Add a simple web page to this backend so people can use it in a browser.

Also works:

  • "Serve the front end from the same app."
  • "Put a page at the app's root address."

What your tool does

  • Reads the platform's deploy skill, whose web-client item says where the files go.
  • Writes the page, its script, and its stylesheet as client/index.html, client/app.js, and client/styles.css in the folder the turnzero-cloud command zips, the one that contains package.json.
  • Serves every other file the page uses, such as an image or a font, from a route of your application's own.
  • Leaves the client/ folder out of an application that has no web client, such as a mobile app's backend.
  • Deploys the application as Deploy an application describes, then requests / on the environment's hostname to check the page.

What you need

  • A backend that deploys, or one your tool is about to deploy (Deploy an application).
  • A web client whose built output is one page, one script, and one stylesheet, plus any further files your backend serves itself.

Before your AI starts

This section is for your AI tool: what it checks and gathers before it begins. You don't need to do these steps yourself.

  • Your tool connected and signed in (Connect your tool).
  • The folder the turnzero-cloud command zips: the one that contains package.json and its lockfile. The client/ folder goes in that folder.

Steps

1. Put the three files under client/

Your tool writes the built files into the client/ folder before the deploy, so the zip contains them.

A web client's built files are the zip's client/index.html, client/app.js, and client/styles.css. The platform serves those three itself: a GET of /, /index.html, /app.js, or /styles.css returns them ahead of your routes, and reaches your application only where the version lacks the file. Any other method, path, or file under client/, such as an image, reaches your application.

A web client is optional. An application without one, such as the backend of a mobile app, ships no client/ folder, and every request reaches its own routes. Build a mobile app's backend walks through that shape.

2. Serve every other file from your routes

A further file under client/, such as client/logo.png, is deployed with the rest of the zip, and a request for it reaches your application. So your backend serves it from a route of its own. This route reads the file from the deployed folder, with src/main.mjs as the server's entry. No test checks this sample.

import { createServer } from 'node:http';
import { readFile } from 'node:fs/promises';

createServer(async (req, res) => {
  if (req.method === 'GET' && req.url === '/logo.png') {
    res.writeHead(200, { 'content-type': 'image/png' });
    res.end(await readFile(new URL('../client/logo.png', import.meta.url)));
    return;
  }
  // Your other routes, the health path among them.
  res.writeHead(404).end();
}).listen(process.env.PORT);

3. Deploy and check the page

Your tool deploys the application as Deploy an application describes. Once the deploy ends deployed, it requests /, /app.js, and /styles.css on the environment's hostname, and one path your backend serves.

Expected result

A request for / or /index.html on the application's hostname returns the page, and /app.js and /styles.css return the script and the stylesheet. Every other request reaches your application's routes, and your backend answers it.

Refusals

No refusal is specific to a web client. The deploy's own refusals are in Deploy an application.

A request for the page meets one answer of the router's own:

Refusal Status Cause Remedy
not_deployed 404 The environment has no deployed version yet, so there is no page to serve. Deploy to the environment, then request the page again.