Skip to content

Fix Vite preview host blocking, add .gitignore, sync stale lockfile - #1

Merged
GothwadTech merged 12 commits into
mainfrom
arena/b14c474b-gothwadtech
Oct 13, 2026
Merged

GothwadTech merged 12 commits into
mainfrom
arena/b14c474b-gothwadtech

Conversation

@GothwadTech

@GothwadTech GothwadTech commented Oct 13, 2026 •

Copy link
Copy Markdown
Owner

Full cleanup pass on the Gothwad Tech site: dead code removal, housekeeping, honest framing of the browser benchmarks, lint tooling, path routing and code splitting.

Eight commits, roughly in order. Net effect: −958 lines, −388 KB of committed cruft, initial JS −29%.

1. Dev server was unreachable through any proxy

vite.config.ts returned HTTP 403 for every non-localhost Host header, so the app could not be viewed in a preview/sandbox environment at all. Added server.allowedHosts. Also fixed a mojibake comment (Do not modifyâ—file watching, a double-encoded em-dash).

2. No .gitignore

The repo had none. Installing deps and running a build drops node_modules/ and dist/ into the tree — one git add . and they'd have been committed. Added a standard Node/Vite ignore file, including .env*.

3. Stale package-lock.json

It still declared react-router-dom and @google/genai ^1.29.0 while package.json had already dropped the router and moved to ^2.4.0. Installs weren't reproducible. Regenerated.

4. Removed 32 dead files (~2,250 LOC)

Root components/ (24 files) and screens/ (8 files) were a leftover react-router version of the site. Nothing outside those folders imports them — they only import each other.

They were the sole cause of all 13 typecheck errors (they import react-router-dom, now removed). src/ was always clean. Removing them takes tsc --noEmit from 13 errors → 0, and drops CSS from 94.2 → 79.3 kB since Tailwind no longer scans them. Recoverable from history at 14e3273.

5. Housekeeping

  • Dropped web.zip (388 KB stale build artifact) from git.
  • package.json renamed from the leftover template name react-example → gothwadtech.
  • De-duplicated public/: the icon set was committed 5 times over. md5 confirmed byte-identical copies in assets/favicons/, assets/pwa/, and 4 root icon-*.png files. Kept the canonical /assets/icons/* set plus root favicon.ico and apple-touch-icon.png (auto-requested by browsers). Fixed the two manifest.json entries that would have 404'd.

6. Browser benchmarks are now honestly labelled

BrowserSimulatorModal presented hardcoded arithmetic as a measured head-to-head comparison:

gothwadRam = 45 + tabCount * 9.5
chromeRam  = 160 + tabCount * 42   → "Consumes 3.4x more memory"
simulatedAdsBlocked  = 38
simulatedDataSavedMb = 14.2
"Speed: 38.4 MB/s"

Presenting modelled figures as measured performance is a misleading-advertising risk (ASCI in India). No numbers were changed — only the framing: a persistent disclaimer on every tab, ~N MB (modelled), "Modelled at ~Nx the figure above — illustrative, not a measured comparison", "(sample page)", "Simulated speed", and the URL bar changed from gothwad://speed-benchmark-core to gothwad://demo/illustrative-preview.

7. ESLint + unused imports

Added an ESLint 10 flat config with typescript-eslint, react-hooks and react-refresh.

Only the classic rules-of-hooks + exhaustive-deps pair is enabled. eslint-plugin-react-hooks v7's configs.recommended now bundles the entire React Compiler ruleset (immutability, purity, gating, use-memo, set-state-in-effect…), which assumes the app is verified by the React Compiler and would flood a hand-written codebase — so rules are opted into individually. Noted in the config.

Removed 131 unused imports across 18 files (mostly lucide-react icons). The bundle is byte-identical since Vite tree-shakes them anyway — pure hygiene. Warnings: 140 → 25, 0 errors.

Scripts: lint is now eslint, typecheck is tsc, verify runs all three plus build.

8. Real path routing + code splitting + per-route SEO

  • Routing: #products → /products. Crawlers largely ignore fragments, so the old URLs were effectively one page to Google. Legacy links still work — a hash naming a route is replaceState'd to the canonical path on mount. Plain in-page anchors (#docs, #services, #mission, #order) are untouched and still scroll; the home page has section ids that overlap route names, so pageFromHash only matches real routes. Back/forward works via popstate.
  • SEO: per-route document.title, meta description, og:*/twitter:* and canonical — path routing is only worth doing if crawled metadata changes with the route. sitemap.xml now lists the 6 real routes instead of 8 hash URLs.
  • Perf: lazy-loaded all six pages and three modals behind Suspense. Initial chunk 386 → 275 kB raw, 104.6 → 85.8 kB gzip (−19%); each page is now a 5–23 kB chunk fetched on demand. Modals mount only when opened, safe because all three guard with a plain if (!isOpen) return null and have no exit animation.
  • CI: added .github/workflows/ci.yml running typecheck + lint + build with npm caching.

Verification

npm run verify   →   typecheck ✓   lint ✓ (0 errors)   build ✓

Dev server: /, /products, /solutions, /portfolio, /about, /contact all 200 with SPA fallback; /manifest.json, /favicon.ico, /robots.txt, /sitemap.xml and icons still served as static (ahead of the Vercel rewrite), so deep links work in production while assets keep their correct content types.

Worth knowing

  • lint changed meaning — it used to run tsc --noEmit, it now runs ESLint. Use npm run typecheck for types.
  • 25 remaining lint warnings are non-blocking and left deliberately: 16 unused props/vars, 7 any, 2 react-refresh warnings on the Theme/Language contexts (they export a provider component and a hook from one file — a normal pattern). Adding --max-warnings now would just turn CI red; happy to clean these up separately.
  • No secret leak — process.env.GOTHWAD_API_KEY in DeveloperDocsSection is inside a displayed code sample, not real config.
  • Deployment — Cloudflare only. vercel.json is deleted; nothing is hosted on Vercel. The site deploys through Cloudflare Pages, which does not rewrite unknown paths by default, so moving to real paths would have made /products 404 on refresh. Added public/_redirects with /* /index.html 200 (Vite copies it verbatim into dist/). Static assets are matched before the catch-all, so favicon, manifest, sitemap and icons keep their real content.
    • When you move to Cloudflare Workers, _redirects will not carry the SPA fallback — Workers ignores it for that. You'll need this in wrangler.jsonc instead:
      "assets": {
        "directory": "./dist",
        "not_found_handling": "single-page-application"
      }
      plus a "binding": "ASSETS" and an env.ASSETS.fetch(request) fallback in the Worker if you add Worker code alongside the static assets. Noted in public/_redirects so it isn't lost.
  • I could not verify the live deployment end-to-end from this sandbox: outbound network is restricted to GitHub/npm/PyPI, so I couldn't fetch gothwadtech.com/products. Worth one manual click on a deep link after merge.

Arena Agent and others added 8 commits October 13, 2026 00:41
- vite.config.ts: set server.allowedHosts so the dev server accepts
  requests coming through sandbox preview proxies (it previously
  returned HTTP 403 for any non-localhost Host header), and fix a
  double-encoded em-dash (mojibake) in a comment.
- Add .gitignore: the repo had none, so node_modules/ and dist/ were
  at risk of being committed on the next 'git add .'.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
The lockfile was stale: it still declared react-router-dom and
@google/genai ^1.29.0, while package.json had already dropped the
router and moved to @google/genai ^2.4.0. Regenerated so installs
are reproducible.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
The root components/ (24 files) and screens/ (8 files, ~2,250 LOC) are
a leftover react-router version of the site. Nothing outside those two
folders imports them -- they only import each other.

They were the sole cause of all 13 typecheck errors: they import
'react-router-dom', which was removed from package.json when the site
was rewritten to hash routing under src/. So 'npm run lint' failed even
though src/ itself was always clean.

Removing them takes tsc --noEmit from 13 errors to 0. As a bonus the
Tailwind build shrinks (94.24 -> 79.28 kB CSS, 13.60 -> 11.47 kB gzip)
since those files are no longer scanned for classes.

Also narrow allowedHosts to 'true as const' -- Vite types it as
'true | string[]', and a plain object literal widens it to boolean.

Recoverable from git history at 14e3273 if ever needed.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
- Remove web.zip (388 KB stale build artifact) that was committed to
  the repo and bloated every clone.
- package.json: rename from the leftover template name 'react-example'
  to 'gothwadtech'; lockfile name field synced to match.
- De-duplicate public/: the icon set was committed 5 times over. md5
  confirmed these were byte-identical copies:
    public/assets/favicons/  (2)  -> root favicon.ico, apple-touch-icon.png
    public/assets/pwa/       (5)  -> public/assets/icons/*
    public/icon-{192,512}.png, icon-{192,512}-maskable.png (4)
    public/assets/icons/{apple-touch-icon.png,favicon.ico} (2)
    public/assets/brand/gothwad-logo.png -> identical to brand/logo.png
  Kept the canonical set under /assets/icons/ plus root favicon.ico and
  apple-touch-icon.png (both auto-requested by browsers).
- manifest.json: drop the two /icon-*.png entries that now 404; the
  equivalent /assets/icons/* entries were already present.

Verified every asset referenced by index.html, manifest.json and src/
still resolves. Lint clean, build unchanged.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
BrowserSimulatorModal presented hardcoded numbers as if they were
measured results of a head-to-head comparison against real browsers:

  gothwadRam = 45 + tabCount * 9.5
  chromeRam  = 160 + tabCount * 42    -> "Consumes 3.4x more memory"
  simulatedAdsBlocked   = 38
  simulatedDataSavedMb  = 14.2
  "Speed: 38.4 MB/s"

Presenting modelled figures as measured performance is a misleading
advertising risk (ASCI in India). The interactive behaviour is kept
intact; only the framing changes:

- Add a persistent amber disclaimer at the top of the modal, visible on
  every tab, stating figures are simulated and depend on real hardware,
  OS, extensions and workload.
- RAM values now read "~N MB (modelled)".
- "Consumes Nx more memory" -> "Modelled at ~Nx the figure above -
  illustrative, not a measured comparison".
- Ad/data counters marked "(sample page)" and "not measured".
- Download speed prefixed "Simulated"; progress labelled as a demo.
- URL bar gothwad://speed-benchmark-core -> gothwad://demo/illustrative-preview;
  "Hardware Emulation" -> "Simulated preview".

No numbers were changed - only how they are presented.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Tooling:
- Add eslint 10 flat config (eslint.config.js) with typescript-eslint,
  react-hooks and react-refresh.
- Only the classic react-hooks pair is enabled. v7's configs.recommended
  now bundles the whole React Compiler ruleset (immutability, purity,
  gating, use-memo, set-state-in-effect...), which assumes the app is
  verified by the React Compiler and would flood a hand-written
  codebase. Rules are opted into individually instead; noted in config.
- Scripts: `lint` is now eslint, `typecheck` is tsc, and `verify` runs
  typecheck + lint + build. (Previously `lint` ran tsc.)

Cleanup:
- Remove 131 unused imports across 18 files, mostly lucide-react icons
  imported but never rendered. Production bundle is byte-identical
  (386.02 kB) since Vite tree-shakes them either way - this is purely
  hygiene.

Result: 140 warnings -> 25 (0 errors), tsc clean, build unchanged.
The remaining 25 are genuine but non-blocking: 16 unused vars/props,
7 `any`, 2 react-refresh warnings on the Theme/Language contexts
(exporting a provider component and a hook from one file, a normal
pattern).

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Routing:
- Replace hash routing (#products) with real paths (/products). Crawlers
  largely ignore fragments, so the old URLs were effectively one page to
  Google. Unknown paths fall back to home, matching previous behaviour.
- Legacy links are preserved: on mount, a hash that names a route
  (#products, #browser, #leadership) is replaceState'd to the canonical
  path. Plain in-page anchors such as #docs, #services, #mission and
  #order are left untouched and keep scrolling normally -- the home page
  has section ids that overlap some route names, so pageFromHash only
  matches real routes.
- Back/forward works via popstate.

SEO:
- Add per-route document.title, meta description, og:* and twitter:* tags
  plus a canonical link. Path routing is only worth doing if the crawled
  metadata changes with the route.
- sitemap.xml: replace the 8 hash URLs with the 6 real routes and refresh
  lastmod.

Performance:
- Lazy-load all six pages and the three modals behind Suspense. Modals
  are now mounted only when opened, which is safe because all three
  guard with a plain `if (!isOpen) return null` and have no exit
  animation.
- Initial chunk: 386 kB -> 275 kB raw, 104.6 -> 85.8 kB gzip. Each page
  is now a 5-23 kB chunk fetched on demand.

vercel.json already rewrites all paths to /index.html, so deep links
work in production; static files are still served ahead of the rewrite
(verified favicon, manifest, sitemap and icons all return 200).

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Runs typecheck, lint and build on every push to main and on pull
requests, with npm caching and in-progress runs cancelled on new pushes.

Mirrors the local `npm run verify` script (typecheck && lint && build),
which currently passes: tsc clean, eslint 0 errors / 25 warnings, build
OK.

Note the lint step passes with warnings by design -- the 25 remaining
are non-blocking (unused props, 7 `any`, and 2 react-refresh warnings on
the Theme/Language contexts, which export a provider component and a
hook from one file). Tightening them is a separate cleanup; wiring
--max-warnings now would just turn CI red.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented Oct 13, 2026 •

Copy link
Copy Markdown

Deploying gothwadtech with  Cloudflare Pages  Cloudflare Pages

Latest commit: d7b3693
Status: ✅  Deploy successful!
Preview URL: https://d125fc7a.gothwadtech.pages.dev
Branch Preview URL: https://arena-b14c474b-gothwadtech.gothwadtech.pages.dev

View logs

Arena Agent and others added 4 commits October 13, 2026 01:08
The repo deploys via Cloudflare Pages (visible in the PR checks), but
only had a vercel.json rewrite -- which Cloudflare ignores.

Cloudflare Pages serves static assets and 404s unknown paths by
default. Since the previous commit moved routing from #products to
/products, every deep link would have 404'd on hard refresh or direct
navigation; only / would have worked.

Add public/_redirects:

    /*    /index.html   200

Vite copies public/* verbatim into dist, so the rule lands in the build
output where Cloudflare reads it. Static assets are matched and served
before the catch-all, so /favicon.ico, /manifest.json, /sitemap.xml and
/assets/* keep their real content rather than falling through to
index.html. vercel.json is retained for Vercel deploys.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
Remove vercel.json -- nothing is hosted on Vercel, and its SPA rewrite
was inert here. It also gave a false sense of coverage: the actual host
is Cloudflare Pages, which needs public/_redirects (added in the
previous commit) and ignores vercel.json entirely.

Update the _redirects comment to drop the Vercel reference and record
what the future move to Cloudflare Workers will require, since Workers
does not use this file for the SPA fallback:

    "assets": {
      "directory": "./dist",
      "not_found_handling": "single-page-application"
    }

plus an ASSETS binding and an env.ASSETS.fetch() fallback if Worker code
is added alongside the static assets.

Left alone: the mention of Vercel in src/data/companyData.ts, which is
customer-facing copy about edge platforms the company builds for, not a
statement about where this site is hosted. Say the word if you want it
changed too.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
The site's purpose changed: instead of a corporate agency site, the root
domain is now the front door to the Gothwad ecosystem (Google-style), with
the company content moving to about.gothwadtech.com in a follow-up.

Decisions (from Pawan, 2026-10-13):
- gothwadtech.com = portal at the root
- corporate/agency content -> about.gothwadtech.com
- search = OpenRouter AI: AI-written answer on top, real cited sources below
- homepage main body = product shortcuts, with the search bar above them
- keep our own brand (#0494f4 + lucide), NOT the Google palette used by
  accounts/mail

What's here
- src/data/gothwadApps.ts: ecosystem catalog (13 apps) ported from
  accounts/web/js/gothwad-apps.js. Keep the two in sync.
- src/data/portalConfig.ts: every domain in one place (Rule #1 from the
  Accounts repo). Nothing is hardcoded elsewhere; all values are overridable
  via VITE_* env vars.
- src/components/portal/: SearchBox (hero + bar), AppShortcuts (the product
  tiles that form the main body of the homepage), PortalBar (9-dot app
  launcher + theme toggle + account chip).
- src/pages/PortalHome.tsx: wordmark + search + shortcuts + footer.
- src/pages/SearchPage.tsx: AI answer card, cited sources with favicons,
  loading skeleton, and a clear "not enabled yet" state when the Worker has
  no key.
- worker/: Cloudflare Worker for /api/search. Holds the OpenRouter key so it
  never reaches the browser, caches answers in KV, and rate limits per IP.
- AGENTS.md + TASK.md, following the accounts/mail convention so future
  agents get context up front.

Routing
- /            portal home
- /search?q=   results
- /legacy      the old corporate homepage, kept so nothing is lost until
               about.gothwadtech.com is live (delete it then)
- the corporate Navbar/Footer/WhatsApp button are now suppressed on portal
  routes, which ship their own bar and footer

Notes
- The Worker is not wired up yet: it needs a KV namespace id in
  worker/wrangler.toml and OPENROUTER_API_KEY as a Worker secret. Until then
  the search page shows an explicit "not enabled" message.
- Web search is billed by OpenRouter (~$4/1,000 results) even on :free
  models, which is why the KV cache and daily limit are not optional.
- Fixes a regression from the earlier icon de-duplication: Logo.tsx pointed
  at /icon-512.png, which had been deleted.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
I misread the requirement and built an AI search system (OpenRouter +
Cloudflare Worker + /search page). That is not what was wanted: the brief was
"search bar ki jagah product shortcuts", i.e. replace the search bar with
product shortcuts. Reverting all of it.

Removed:
- src/components/portal/SearchBox.tsx
- src/pages/SearchPage.tsx
- src/services/searchApi.ts, src/types/search.ts
- worker/ (OpenRouter client, KV cache, rate limiter, wrangler.toml)
- the /search route, searchQuery state and handleSearch in App.tsx
- SEARCH_API from portalConfig.ts, VITE_SEARCH_API from vite-env.d.ts
- worker:* npm scripts, and the worker/ entry in the tsconfig exclude

The homepage is now just the wordmark and the product shortcut grid, with the
app launcher and account chip in the top bar.

/unknown paths still fall back to home, so any /search URL that got shared
lands on the portal rather than 404ing.

Recoverable from history at 2246bc4 if it is ever wanted again.

AGENTS.md now states plainly that this project has no search system, so a
future agent does not rebuild it unprompted.

Co-authored-by: arena-agent <297053741+arena-agent@users.noreply.github.com>
@GothwadTech
GothwadTech merged commit 5e12d5d into main Oct 13, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant