React Development in Morocco
I build React applications in TypeScript so the interface can grow without collapsing into ad-hoc components.
That includes dashboards, customer portals, and design systems that match how the product actually works — not a generic admin theme.
TypeScript is not decoration on top of JavaScript — it is how a component knows what shape of data it is receiving before that assumption breaks in production. A dashboard tracking fleet status or treasury operations has enough moving state that catching a mismatched field at compile time saves a debugging session later.
Component systems get organized by domain — billing, fleet, inventory — not by generic file type, so a new screen in an existing domain reuses what is already there instead of starting from a blank component. State that needs to be live, like a fleet map, is driven by the same WebSocket events the backend already emits rather than a separate polling loop.
I ship Vite + React for authenticated product UIs when server rendering adds operational complexity without a real benefit, and Next.js when the product needs SSR or is public-facing content. The choice is based on what the interface actually has to do, not a default.
Business problems
- A dashboard that is a pile of components with no domain language, so a new developer has to read every file to guess what a piece of UI is actually for.
- JavaScript that cannot be refactored when the product grows, because nothing enforces what shape of data a function or a component actually expects until it fails at runtime.
- State management that grew organically into a tangle of prop drilling and ad-hoc context, so a simple UI change risks breaking a screen three levels away.
- Prop drilling five components deep because there is no clear state boundary, so a small UI tweak means touching files that have nothing to do with the actual change.
- A component library that duplicates the same button, input and table in four slightly different versions because nobody owns consistency.
- Bundle size that grows unnoticed until a page takes visibly longer to load, because nobody was watching what got pulled in with each new dependency.
- Forms with no real validation feedback, so a user only finds out what went wrong after submitting into a black hole.
Development process
- TypeScript first. Organize by domain (billing, fleet, inventory), not by file type, so related logic and components sit together instead of scattered across generic folders.
- Consume a real API contract — usually Laravel REST from the same engagement — with generated or hand-written types that keep the frontend honest about what the backend actually returns.
- Keep live state (WebSocket-driven dashboards, real-time maps) separate from request-response state, so a component does not have to guess which kind of update it is reacting to.
- Establish a small shared component library early — inputs, tables, modals — so new screens compose from it instead of reinventing basic UI every time.
- Write the data-fetching layer once per domain (a hook, a query client) instead of scattering fetch calls through components, so a backend change touches one place, not twenty.
- Watch bundle size as part of the build, not as an occasional audit, so a heavy new dependency is a conscious decision, not an accident.
- Build forms with inline validation and clear error states from the start, since that is where most of a user's frustration with a product actually happens.
What you get
- Product UIs that stay coherent as modules are added, because the component and domain structure was designed to grow rather than patched to survive.
- Type errors caught before a deploy instead of discovered by a user clicking the wrong button at the wrong time.
- Fewer visual inconsistencies, because a button behaves the same way in the billing screen as in the fleet screen.
- Onboarding a new frontend developer takes a walkthrough of the domain structure, not an archaeology dig through unrelated components.
- A product that stays fast to load as it grows, because bundle size was a constraint from the start, not a fire drill later.
- Forms that tell a user what is wrong before they submit, instead of after, which is where most support tickets about a broken form actually come from.
- A component library that a designer can hand off to without a lengthy translation step, because the components already map to the same names used in design files.
Selected projects
FAQ
Do you use Next.js?
When the product needs SSR or a content-heavy public site. For authenticated product UIs I often ship Vite + React, which is faster to operate.