NoWayOS
EN
GitHub
MenuClose

Build

Porting from React

Bring an existing React interface to NoWayOS: measure it with the Screen Compiler's coverage report, see what converts as written, what to change and what moves into your application, and read every error it can give.

You do not start again. Most of a React screen converts as it is written: its layout, its text, its buttons and fields, its conditions and lists, its own small components. The rest is either a short rewrite or work that moves into your application, which on a computer with one job is where it belongs.

Measure it first

Before changing a line, ask the Screen Compiler how far your code already goes. Clone your application beside the two repositories from Screens from React, so the dev container can see it, and run the coverage report on its source:

cd nowayos-work # holds nowayos and screen-compiler
git clone https://example.com/your-app.git my-app
cd screen-compiler
make run ARGS="audit ../my-app/src"

The report reads every .tsx file under that folder and counts each construct it finds: elements, props, style properties, hooks, lists, conditions, operators and imports. Each one gets a verdict:

  • in the subset: it converts, where it is used as the subset allows;
  • on the road: it does not convert yet, and the report names the step that will convert it;
  • out by design: it never will, and the report says why;
  • unknown: the Screen Compiler does not recognise it. Unknown is never counted as converting.

Then come the steps of the road with how often each is needed, and every file with its result. A file "converts" only if check passes it, so the figure at the top is the true one. The report names constructs and never quotes your code, so it is safe to share. Like the compiler itself, run it only on code you trust.

What maps onto what

In React DOM In the subset
<div> laid out with flexbox <Column> or <Row>, with gap, padding and a declared style
<h1>, <p>, <span>, <label> <Text> in a role: title, heading, body, label, caption or display
<button onClick={…}> <Button onClick={props.onSave}>: a callback prop becomes an action
<input>, a checkbox, radio buttons, <select> <TextInput>, <Checkbox>, <RadioGroup>, <Select>, each with an id the application reads and sets
{ready && <X/>}, ? :, !ready, step === "review" groups and switches the application sets
items.map(…) rows: a list the file holds, or a prop's list sliced to a most, props.items.slice(0, 5)
Hello, {name}! literal words compiled in around a slot the application fills
Your own components and fragments, in the screen's file or one beside it expanded at build time, as if the screen were written flat
style={{ padding: "16px" }}, color: "var(--text-muted)" the declared style properties, lengths in layout units, colours the theme's

The tables on Screens from React list exactly what each component takes. They come from the Screen Compiler's own tables, so they cannot drift from what it accepts.

What moves into your application

There is no JavaScript on the device. A screen is a fixed tree that your application drives through numbered actions, fields, slots, groups and switches. So some things stay out by design, each for a reason:

  • State and hooks (useState, useEffect, context). The application holds the state and sets what a screen shows.
  • A field's value, checked and onChange. The application reads and sets a field through its id.
  • Spread props. What they hold is known only when the code runs.
  • Computed styles, colour values and global stylesheets. A style is static, colours are the theme's so the large-text theme can recolour every screen and contrast is checked, and there is no cascade.
  • Animation.
  • A list with no most. Slice it, .slice(0, 5), so the screen knows how many rows it may show.
  • Comparisons other than a prop === a string, and if or switch in a screen's function. Work the answer out in the application and pass it as a prop.
  • Components from packages, and files outside the screen's folder. A screen reads only its own folder and below: put your components beside it, ./parts/header.
  • A handler that does more than call a prop. onClick={() => props.onSave()} converts; anything more is the application's work.

What the road brings next

The coverage report names these planned steps when your code needs them:

  • more of CSS layout: flex growth, alignSelf, minimum and maximum heights, padding on each side, and margins;
  • common HTML elements, each by one fixed rule;
  • CSS modules, one class per element;
  • layering: elements laid over one another;
  • images and masked entry.

Until a step lands, its constructs are refused rather than guessed. Every step keeps the same rule: exact, or not at all.

Reading an error

An error gives the file, line and column, a code, what is wrong, and a line of help:

web-search.tsx:16:28: error[unknown-name]: `query` is not a prop of the component
 help: text from the application must be a prop: take it as one, function Screen({ query }) { … }

With any error, nothing is written. The codes:

Code What it means What to do
syntax The file is not valid TSX, or breaks a rule every module keeps. Fix the code at the position given.
unsupported A construct outside the subset. Follow the help: rewrite it in the subset, or move the work into the application.
unknown-element An element that is not one of the kit's, or not imported. Import it from "nowayos:kit", or use the kit's element.
unknown-prop A prop or style property the element does not take. Use one the tables list for it.
invalid-value A prop the element takes, given a value it does not. Give a value of the kind the tables list.
missing-prop A prop the element needs is not given. Give it: the tables show these in bold.
invalid-children An element holds what it cannot, such as two children in <Screen> or text in a <Column>. Wrap them, or move the text into a <Text>.
unknown-name A name that is not a prop, a design token or an import. Take it as a prop, or declare it.
duplicate-name Two things would get the same name in the generated code, such as isReady and is_ready. Rename one.
reserved-name A name that Rust or the generated code keeps for itself, such as type. Rename it.
limit Past a limit on size, depth or count. Shorten it, or split it into parts.
no-screen The file has no screen component: a function returning <Screen>. Export one.
internal A fault in the Screen Compiler itself. Report it, with the input that caused it.

When a construct you need is on the road and not yet built, say so, with the report: it shows which steps matter most.