<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Exarbi</title>
    <description>The latest articles on DEV Community by Exarbi (@exarbi).</description>
    <link>https://dev.to/exarbi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4034426%2F5fc268f3-e159-4a13-b9ae-56e3330b292e.png</url>
      <title>DEV Community: Exarbi</title>
      <link>https://dev.to/exarbi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/exarbi"/>
    <language>en</language>
    <item>
      <title>How We Built a Multilingual Crypto Arbitrage Monitoring Platform with Next.js</title>
      <dc:creator>Exarbi</dc:creator>
      <pubDate>Fri, 17 Jul 2026 20:50:42 +0000</pubDate>
      <link>https://dev.to/exarbi/how-we-built-a-multilingual-crypto-arbitrage-monitoring-platform-with-nextjs-42h4</link>
      <guid>https://dev.to/exarbi/how-we-built-a-multilingual-crypto-arbitrage-monitoring-platform-with-nextjs-42h4</guid>
      <description>&lt;p&gt;Building a crypto product is not only about collecting price data.&lt;/p&gt;

&lt;p&gt;Once we started working on Exarbi, we quickly realized that a visible price difference between two exchanges does not automatically mean there is a usable arbitrage opportunity.&lt;/p&gt;

&lt;p&gt;Transfer networks, deposit and withdrawal availability, data freshness, fees, liquidity, and authentication architecture all affect the final product.&lt;/p&gt;

&lt;p&gt;This post explains some of the technical decisions behind Exarbi, a multilingual crypto arbitrage monitoring platform built with Next.js.&lt;/p&gt;

&lt;h2&gt;
  
  
  What Exarbi does
&lt;/h2&gt;

&lt;p&gt;Exarbi helps users compare price differences across centralized crypto exchanges and review operational signals that may affect an opportunity.&lt;/p&gt;

&lt;p&gt;The platform brings together:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cross-exchange price differences&lt;/li&gt;
&lt;li&gt;Deposit and withdrawal availability&lt;/li&gt;
&lt;li&gt;Network compatibility&lt;/li&gt;
&lt;li&gt;Transfer-readiness signals&lt;/li&gt;
&lt;li&gt;Data freshness&lt;/li&gt;
&lt;li&gt;Risk indicators&lt;/li&gt;
&lt;li&gt;Exchange filtering&lt;/li&gt;
&lt;li&gt;Telegram alerts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Exarbi is a monitoring and decision-support platform.&lt;/p&gt;

&lt;p&gt;It does not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Request exchange API keys&lt;/li&gt;
&lt;li&gt;Execute trades on behalf of users&lt;/li&gt;
&lt;li&gt;Hold user funds&lt;/li&gt;
&lt;li&gt;Act as an automated trading bot&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Users remain responsible for reviewing the data and making their own trading decisions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why we chose Next.js App Router
&lt;/h2&gt;

&lt;p&gt;Exarbi uses Next.js with the App Router and TypeScript.&lt;/p&gt;

&lt;p&gt;The application contains two distinct areas:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Public marketing and educational pages&lt;/li&gt;
&lt;li&gt;Authenticated application routes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The public side includes landing pages, pricing, exchange coverage, legal pages, and a multilingual blog.&lt;/p&gt;

&lt;p&gt;The authenticated side includes dashboards, alerts, market scanning, exchange data, and account features.&lt;/p&gt;

&lt;p&gt;Keeping these areas separate became important for both performance and SEO.&lt;/p&gt;

&lt;p&gt;Public pages should produce complete server-rendered HTML, while private application routes should never appear as indexable pages to search-engine crawlers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Separating public and protected routes
&lt;/h2&gt;

&lt;p&gt;One issue we found during technical SEO testing was that an unauthenticated request to &lt;code&gt;/dashboard&lt;/code&gt; could return an HTTP 200 response before a client-side redirect moved the visitor to the login page.&lt;/p&gt;

&lt;p&gt;For users, the behavior looked correct.&lt;/p&gt;

&lt;p&gt;For crawlers, however, the protected route could look like a real page.&lt;/p&gt;

&lt;p&gt;We moved the authoritative authentication check to the server layout layer. Protected routes now verify the session before rendering.&lt;/p&gt;

&lt;p&gt;The resulting behavior is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authenticated users receive the protected page&lt;/li&gt;
&lt;li&gt;Unauthenticated users receive a real HTTP redirect&lt;/li&gt;
&lt;li&gt;Client-side session monitoring remains only as a fallback&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This avoids exposing private application shells to crawlers and reduces unnecessary dashboard JavaScript for unauthenticated visitors.&lt;/p&gt;

&lt;h2&gt;
  
  
  Supporting eight languages
&lt;/h2&gt;

&lt;p&gt;Exarbi currently supports:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Turkish&lt;/li&gt;
&lt;li&gt;English&lt;/li&gt;
&lt;li&gt;German&lt;/li&gt;
&lt;li&gt;French&lt;/li&gt;
&lt;li&gt;Russian&lt;/li&gt;
&lt;li&gt;Arabic&lt;/li&gt;
&lt;li&gt;Japanese&lt;/li&gt;
&lt;li&gt;Chinese&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Multilingual SEO requires more than translating visible text.&lt;/p&gt;

&lt;p&gt;For every indexable public page, we need to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Locale-aware canonical URLs&lt;/li&gt;
&lt;li&gt;Reciprocal hreflang links&lt;/li&gt;
&lt;li&gt;&lt;code&gt;x-default&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Localized titles and descriptions&lt;/li&gt;
&lt;li&gt;Translated route slugs&lt;/li&gt;
&lt;li&gt;Sitemap consistency&lt;/li&gt;
&lt;li&gt;Arabic right-to-left layout&lt;/li&gt;
&lt;li&gt;Japanese and Chinese text segmentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Private and authentication pages follow a different policy.&lt;/p&gt;

&lt;p&gt;Login, registration, password reset, verification, account, and dashboard pages are marked as &lt;code&gt;noindex&lt;/code&gt;. They do not publish canonical or hreflang clusters because they are not intended to appear in search results.&lt;/p&gt;

&lt;h2&gt;
  
  
  Avoiding misleading arbitrage signals
&lt;/h2&gt;

&lt;p&gt;A raw spread is not enough to describe a practical arbitrage opportunity.&lt;/p&gt;

&lt;p&gt;For example, two exchanges may show different prices while:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Withdrawals are suspended&lt;/li&gt;
&lt;li&gt;The token uses different contract addresses&lt;/li&gt;
&lt;li&gt;The required network is unavailable&lt;/li&gt;
&lt;li&gt;Liquidity is too low&lt;/li&gt;
&lt;li&gt;Fees remove the apparent profit&lt;/li&gt;
&lt;li&gt;The price data is stale&lt;/li&gt;
&lt;li&gt;The spread disappears before a transfer completes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why the product UI focuses on context in addition to price differences.&lt;/p&gt;

&lt;p&gt;The objective is not to label every spread as profitable. It is to make the conditions behind the spread easier to inspect.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reducing unnecessary client-side JavaScript
&lt;/h2&gt;

&lt;p&gt;Another challenge was the amount of shared JavaScript loaded by public routes.&lt;/p&gt;

&lt;p&gt;Our public layout originally handled several responsibilities inside one large client component:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication state&lt;/li&gt;
&lt;li&gt;Mobile navigation&lt;/li&gt;
&lt;li&gt;Language selection&lt;/li&gt;
&lt;li&gt;Logout dialogs&lt;/li&gt;
&lt;li&gt;Header state&lt;/li&gt;
&lt;li&gt;Footer rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This meant mostly static public pages inherited a larger hydration boundary than necessary.&lt;/p&gt;

&lt;p&gt;We are moving toward a server-shell and client-island architecture.&lt;/p&gt;

&lt;p&gt;The server renders:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Navigation structure&lt;/li&gt;
&lt;li&gt;Logo and branding&lt;/li&gt;
&lt;li&gt;Footer content&lt;/li&gt;
&lt;li&gt;Legal links&lt;/li&gt;
&lt;li&gt;Product links&lt;/li&gt;
&lt;li&gt;Static calls to action&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Small client components handle only the interactive parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Authentication controls&lt;/li&gt;
&lt;li&gt;Language menu&lt;/li&gt;
&lt;li&gt;Mobile drawer&lt;/li&gt;
&lt;li&gt;Logout dialog&lt;/li&gt;
&lt;li&gt;Live homepage data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to force the number of JavaScript files down. Next.js naturally generates multiple cacheable chunks.&lt;/p&gt;

&lt;p&gt;The useful metrics are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Total transferred JavaScript&lt;/li&gt;
&lt;li&gt;Hydration scope&lt;/li&gt;
&lt;li&gt;Parse and execution time&lt;/li&gt;
&lt;li&gt;Unused JavaScript&lt;/li&gt;
&lt;li&gt;Total Blocking Time&lt;/li&gt;
&lt;li&gt;Interaction latency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;One large bundle is not automatically better than several small, cacheable chunks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consent-aware third-party scripts
&lt;/h2&gt;

&lt;p&gt;Exarbi uses services such as analytics, customer support, payments, and transactional email.&lt;/p&gt;

&lt;p&gt;Third-party scripts need to be treated carefully because they can affect both performance and privacy.&lt;/p&gt;

&lt;p&gt;Our general approach is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Do not load analytics before the required consent&lt;/li&gt;
&lt;li&gt;Load support tooling lazily&lt;/li&gt;
&lt;li&gt;Avoid loading Stripe JavaScript on pages that do not need checkout&lt;/li&gt;
&lt;li&gt;Keep server-side email services out of the browser bundle&lt;/li&gt;
&lt;li&gt;Prevent duplicate script initialization during client navigation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This work is incremental because aggressive script restrictions can easily break login, payment, analytics, or support flows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical SEO as an engineering problem
&lt;/h2&gt;

&lt;p&gt;Many SEO issues in modern web applications are architecture issues rather than copywriting issues.&lt;/p&gt;

&lt;p&gt;Some examples we encountered include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Client-side redirects returning HTTP 200&lt;/li&gt;
&lt;li&gt;Private routes receiving public internal links&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;noindex&lt;/code&gt; pages inheriting hreflang metadata&lt;/li&gt;
&lt;li&gt;Query-based category pages creating crawl noise&lt;/li&gt;
&lt;li&gt;Shared client layouts increasing public JavaScript&lt;/li&gt;
&lt;li&gt;Sitemap URLs not matching live canonical behavior&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tools such as Screaming Frog and Seobility helped identify symptoms, but every warning still required inspection.&lt;/p&gt;

&lt;p&gt;For example, multiple JavaScript chunks are normal in Next.js. Repeated footer text is also normal. A short contact page is not automatically thin content.&lt;/p&gt;

&lt;p&gt;The important step is finding the component or routing behavior behind the warning before changing the site.&lt;/p&gt;

&lt;h2&gt;
  
  
  What we learned
&lt;/h2&gt;

&lt;p&gt;The most important lesson has been that market data, application architecture, performance, and SEO cannot be treated as isolated systems.&lt;/p&gt;

&lt;p&gt;A decision in one layer often affects several others.&lt;/p&gt;

&lt;p&gt;Moving authentication checks to the server improved:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Security boundaries&lt;/li&gt;
&lt;li&gt;Crawl behavior&lt;/li&gt;
&lt;li&gt;Redirect semantics&lt;/li&gt;
&lt;li&gt;Public bundle isolation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Splitting public components into server and client boundaries improves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Initial JavaScript transfer&lt;/li&gt;
&lt;li&gt;Hydration cost&lt;/li&gt;
&lt;li&gt;Cache behavior&lt;/li&gt;
&lt;li&gt;Maintainability&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adding transfer and risk context improves:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Product clarity&lt;/li&gt;
&lt;li&gt;User decision-making&lt;/li&gt;
&lt;li&gt;The accuracy of product positioning&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We are continuing to improve Exarbi gradually, measuring each architectural change before moving to the next one.&lt;/p&gt;

&lt;p&gt;You can see the public product here:&lt;/p&gt;

&lt;p&gt;You can explore the public product at &lt;a href="https://exarbi.com/en" rel="noopener noreferrer"&gt;Exarbi&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>nextjs</category>
      <category>typescript</category>
      <category>webdev</category>
      <category>web3</category>
    </item>
  </channel>
</rss>
