Handling Navigation Links When Converting Stitch HTML to React Router

When converting Stitch HTML to React Router, replace internal <a> tags with React Router <Link> components, preserve external links as standard anchors, and generate corresponding <Route> definitions to enable client-side navigation without page reloads.

Stitch HTML represents a plain-HTML snapshot of a running web application. When transforming these static snapshots into a single-page React application using the stitch::react-components skill from the google-labs-code/stitch-skills repository, you must convert static anchor tags into dynamic React Router navigation components. This conversion preserves the original user flow while enabling the performance benefits of client-side routing.

Understanding the Stitch to React Router Conversion Pipeline

The conversion process begins with the stitch::extract-static-html skill defined in plugins/stitch-design/skills/extract-static-html/SKILL.md, which produces self-contained HTML files for each page with inlined CSS and images. The stitch::react-components skill (located in plugins/stitch-build/skills/react-components/SKILL.md) then transforms these static pages into React components, including the critical step of handling navigation links within the scripts/ directory implementation.

The workflow follows a systematic approach to ensure all internal navigation becomes functional client-side routing:

  1. Extract static HTML – Produce self-contained snapshots from the original application.
  2. Parse the HTML – Locate all <a> elements using parsers like cheerio or native DOM APIs.
  3. Identify navigation types – Distinguish internal links (pointing to other extracted pages) from external URLs.
  4. Replace internal anchors – Transform internal <a> tags into React Router <Link> components.
  5. Generate route definitions – Create corresponding <Route> entries for each page component.

Before transformation, the conversion logic categorizes each anchor tag to determine routing behavior. Internal links point to paths within the extracted site structure (e.g., /profile, /settings), while external links start with http:// or https://. Only internal links require conversion to React Router components; external links should remain as standard <a> tags with target="_blank" to ensure proper browser behavior for outside domains.

For every internal navigation link identified in the HTML snapshot, the conversion replaces the standard anchor tag with React Router's <Link> component. The transformation logic resides in the plugins/stitch-build/skills/react-components/scripts/ directory, where the HTML-to-JSX transformation maps the href attribute to the to prop:

// Original HTML from Stitch snapshot
<a href="/profile">Profile</a>

// After conversion to React Router
import { Link } from "react-router-dom";

<Link to="/profile">Profile</Link>

Any additional attributes (such as aria-label, className, or rel) are copied to the <Link> component to preserve accessibility and styling. This transformation ensures that clicking the link updates the URL and renders the new component without triggering a full page reload.

Generating Route Definitions for Converted Pages

After converting the navigation links, you must define the routing structure in your application's entry point. The stitch::react-components skill generates these definitions in App.tsx, creating a <Routes> wrapper containing individual <Route> elements for each extracted page:

import { BrowserRouter, Routes, Route } from "react-router-dom";
import ProfilePage from "./pages/ProfilePage";
import SettingsPage from "./pages/SettingsPage";

export default function App() {
  return (
    <BrowserRouter>
      <Routes>
        <Route path="/profile" element={<ProfilePage />} />
        <Route path="/settings" element={<SettingsPage />} />
        {/* Additional routes for other extracted pages */}
      </Routes>
    </BrowserRouter>
  );
}

Place more specific routes before catch-all routes (e.g., /*) to prevent shadowing, as React Router matches routes from top to bottom.

Preserving Query Parameters and Hash Fragments

When handling navigation links during conversion, the system must maintain URL parameters that appear in the original HTML. If an anchor tag contains query strings (?) or hash fragments (#), the conversion logic preserves these in the to prop of the <Link> component:

<Link to="/search?q=react#results">Search</Link>

This preservation ensures that filtered views, search results, and anchor-based navigation continue to function correctly after the Stitch HTML to React Router conversion.

Resolve Relative URLs Convert relative paths (e.g., ./about or ../contact) to absolute routes against the base path of the extracted site before assigning them to to values. This prevents broken links in the generated React application.

Handle External URLs Securely Keep external URLs as plain <a> elements with target="_blank" and rel="noopener noreferrer" attributes. This prevents accidental client-side navigation to undefined routes and ensures proper security practices when linking to outside domains.

Client-Side vs. Server-Side Rendering The components generated by stitch::react-components are designed for client-side rendering (CSR). If your deployment requires server-side rendering (SSR) using frameworks like Next.js, you must implement corresponding route definitions in the SSR framework's routing system separately.

Maintain Accessibility Preserve aria-* attributes and link text content during conversion to ensure the resulting React application remains accessible to screen readers. The <Link> component should retain all semantic meaning from the original <a> tag.

Summary

  • Extract snapshots using stitch::extract-static-html to generate static HTML files with inlined assets.
  • Transform internal links by replacing <a href="..."> with <Link to="..."> components, while keeping external links as standard anchors.
  • Generate route definitions in App.tsx for every converted page component to establish the client-side routing structure.
  • Preserve URL parameters including query strings and hash fragments in the to prop to maintain deep-linking functionality.
  • Verify navigation by testing that clicks update the URL without full page reloads and that all routes render the correct components.

Frequently Asked Questions

What distinguishes Stitch HTML from a React Router application?

Stitch HTML is a static snapshot produced by the stitch::extract-static-html skill, using standard anchor tags (<a>) that trigger full page reloads. A React Router application uses client-side navigation with <Link> components, enabling single-page application performance without server round-trips for every view change.

The skill checks the href attribute for http:// or https:// prefixes to identify external URLs, which remain as standard <a> tags. Internal links—those pointing to paths within the extracted site structure—are converted to React Router <Link> components to enable client-side navigation within the application.

Where are route definitions generated during the Stitch to React conversion?

Route definitions are generated in the main application entry point (typically App.tsx), where the skill creates a <Routes> component containing <Route> elements for each extracted HTML page. The transformation logic resides in plugins/stitch-build/skills/react-components/scripts/.

Yes, the conversion logic explicitly preserves query strings and hash fragments when mapping href attributes to to props. For example, <a href="/search?q=test#top"> becomes <Link to="/search?q=test#top">, ensuring that search parameters and anchor links function correctly in the React Router application.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →