Aabha · Frontend foundations

React with TypeScript · Harbor Together

01 · Set up a repeatable React workspace

The problem we are solving

In Basic JavaScript, you built Harbor Together by selecting elements and changing their text, attributes and children. That approach gave you useful knowledge of the browser. Now imagine that the same event appears in a search result, a saved list and a detail screen. Each screen must agree about what “saved” means. Coordinating every DOM change by hand becomes harder as the interface grows.

React lets us describe the interface for the current data. When relevant data change, React renders again and commits the necessary DOM changes. It does not replace HTML, CSS or JavaScript. A button still needs a useful name; a form still needs labels; an array still uses ordinary JavaScript methods. This course changes how we organize the UI, while retaining those foundations.

By the end of this lesson you will start a local development server, explain its entry point, change a typed component, and distinguish a type-check failure from a browser failure. Read the entry diagnostic before installing anything. The course is intended for a learner who already understands functions, objects and modules.

Four tools, four jobs

Node runs development tools outside the browser. npm installs packages and runs named scripts. Vite transforms source files and serves the local app during development. TypeScript checks whether values are being used consistently with their declared or inferred types. React is the UI library loaded by the resulting application. None of these roles is a registration server.

The browser does not receive your type annotations as a runtime data validator. Vite can transform TypeScript without performing the full type-check. Therefore “the page appeared” and “the types passed” are separate observations. Keep a second terminal available for the check command.

Source files go through a type-check and a separate Vite transformation; only browser JavaScript reaches the DOM.

Start from the supplied, pinned project

Use the included project rather than a new scaffold with today’s changing defaults. Install a supported Node release from the official Node website if Node is missing; the version register records the exact tested runtime and package pins. An existing editor is enough. You do not need a paid service or an editor extension.

  1. Extract the entire ZIP into a folder you own. Open that folder in your editor.
  2. Open a terminal in that folder. Run node --version and npm --version. If the commands are not found after installation, reopen the terminal and check the official installation guidance rather than pasting an unknown fix.
  3. Run npm ci. It installs the dependency tree recorded in package-lock.json. The first install needs network access. Let it finish before starting the app.
  4. Run npm run dev. Open the local URL it prints, then follow the link to checkpoint 01. The examples are at /checkpoints/01/ through /checkpoints/10/.
  5. In a second terminal, run npm run typecheck. Stop the dev server with Ctrl+C when finished.

If a command fails, copy its exact error into your evidence log. A permission problem is different from an unsupported Node version or a network failure. Do not use administrator privileges or disable security as a general repair. Keep the dependency cache in a directory your account can write. Use the package’s version register and README when troubleshooting.

package.json names direct dependencies and scripts. package-lock.json records a resolved dependency tree, including transitive packages. node_modules is installed output; it is not where you edit course code. npm ci expects the manifest and lockfile to agree and replaces installed dependencies. Keep your own work outside node_modules. Updating dependencies is deliberate maintenance, not a first response to every bug.

Trace the first render

Open checkpoint 01’s index.html and its module entry. An HTML container gives React somewhere to put the app. The entry module finds that container, creates a React root, and renders the top-level component. There is one entry per checkpoint. Editing that entry changes that checkpoint, but later checkpoints deliberately import shared modules. Editing a shared helper can affect several pages; use a copy of the whole project for experiments and consult code-guide.md to see those dependencies.

A simplified component looks like this:

const courseName: string = 'Harbor Together';

export default function App() {
  return (
    <main>
      <h1>{courseName}</h1>
      <p>A fictional community-events practice app.</p>
    </main>
  );
}

string describes text. The braces around courseName evaluate a JavaScript expression and put its value into the heading. The parentheses after return keep the multiline expression together. The file extension .tsx means TypeScript containing JSX. A .ts file can contain ordinary typed logic but not JSX markup. A component name begins with an uppercase letter so JSX can distinguish it from a built-in HTML element.

The annotation on courseName is optional here: TypeScript can infer a string from the initializer. We show it once to expose the syntax. Adding annotations to every obvious local value makes code harder to read without increasing useful checks. Use explicit types at meaningful boundaries, such as component props and external-data parsers.

Make a controlled mistake

Change the text and save. Observe the update in the local browser. Then, in your own copied experiment, try assigning a number to a variable explicitly declared as string. Run the type-check and read the filename, line and expected type. Restore the valid text and run the check again. This experiment succeeds when you can explain the error, not when you hide it with any.

Next, temporarily misspell a module import path. Compare the development-server message with the type error. Both stop progress, but their causes differ. Do not change unrelated CSS or reinstall every package when the evidence points to a filename.

The included Strict Mode wrapper adds development checks. Later lessons explain why it can call render logic and effect setup more than you expect. Do not remove it merely to quiet an unfamiliar observation. For now, keep rendering free of writes, random IDs and external requests.

Evidence before moving on

Record the URL, the command that starts the app, the command that checks types, and the source file that owns the heading. Explain why the static course reader can open directly as HTML but the runnable TypeScript examples need Vite. Complete the three exercises, then compare your reasoning with the separate solutions.

Primary reading: Vite setup, React TypeScript, TypeScript strict checks, Node releases. Source checks and package versions are dated in the course register.