<?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: Maksim Baranov</title>
    <description>The latest articles on DEV Community by Maksim Baranov (@rsale).</description>
    <link>https://dev.to/rsale</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3686168%2Fc52397e4-eddd-49cf-9e2d-8b8d45f743ba.png</url>
      <title>DEV Community: Maksim Baranov</title>
      <link>https://dev.to/rsale</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/rsale"/>
    <language>en</language>
    <item>
      <title>From Idea to MVP: Building a Classified Platform in Serbia</title>
      <dc:creator>Maksim Baranov</dc:creator>
      <pubDate>Tue, 30 Dec 2025 14:37:55 +0000</pubDate>
      <link>https://dev.to/rsale/from-idea-to-mvp-building-a-classified-platform-in-serbia-5gg6</link>
      <guid>https://dev.to/rsale/from-idea-to-mvp-building-a-classified-platform-in-serbia-5gg6</guid>
      <description>&lt;p&gt;Hey dev.to! My name is Maksim, and I want to share the story of building &lt;a href="https://rsale.net/ru" rel="noopener noreferrer"&gt;Rsale.net&lt;/a&gt; — a classified platform for Serbia. This is a story about technical decisions, architectural trade-offs, and the specifics of the Balkan market.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5weqpgnhamwwx4acb0e.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq5weqpgnhamwwx4acb0e.jpg" alt=" " width="800" height="455"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Project Status: Backend and frontend are currently under active development. The site currently displays test data to demonstrate functionality.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Why Serbia?&lt;/strong&gt;&lt;br&gt;
Serbia is an interesting market for classifieds:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;7 million population with a growing e-commerce segment&lt;/li&gt;
&lt;li&gt;Dominated by outdated platforms with 2010s-era UX&lt;/li&gt;
&lt;li&gt;High smartphone penetration rate&lt;/li&gt;
&lt;li&gt;Active Russian-speaking community (relocants)&lt;/li&gt;
&lt;li&gt;We saw an opportunity to create a modern platform that combines products and services with a focus on multilingualism and geolocation.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tech Stack: Why These Choices&lt;br&gt;
Architecture: Microservices&lt;/p&gt;

&lt;p&gt;We chose a microservices architecture with clear separation of responsibilities:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;┌─────────────────────────────────────────────────────────┐
│                      Frontend                           │
│                   Next.js 15 + React 19                 │
└─────────────────────┬───────────────────────────────────┘
                      │ REST API
                      ▼
┌─────────────────────────────────────────────────────────┐
│                    API Gateway                          │
│                    ASP.NET Core                         │
└───┬─────────────┬─────────────┬─────────────┬───────────┘
    │             │             │             │
    ▼             ▼             ▼             ▼
┌────────┐  ┌──────────┐  ┌──────────┐  ┌────────────┐
│Products│  │ Services │  │   Auth   │  │Translation │
│Service │  │ Service  │  │ Service  │  │  Service   │
│        │  │          │  │  (OIDC)  │  │   (AI)     │
└────────┘  └──────────┘  └──────────┘  └────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why microservices for an MVP? The common advice is "start with a monolith". But we had reasons:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Independent scaling — the translation service is under heavier load than others&lt;/li&gt;
&lt;li&gt;Different teams — frontend and backend are developed in parallel&lt;/li&gt;
&lt;li&gt;AI component isolation — Translation Service can be easily replaced or updated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Why ASP.NET Core?&lt;/strong&gt;&lt;br&gt;
Performance — one of the fastest web frameworks (TechEmpower benchmarks)&lt;br&gt;
Type safety — C# catches errors at compile time&lt;br&gt;
Ecosystem — Entity Framework, Identity, SignalR out of the box&lt;br&gt;
Hosting — works great in Docker/Kubernetes&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Frontend: Next.js 15 + React 19&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// package.json
{
  "dependencies": {
    "next": "15.4.6",
    "react": "19.1.0",
    "next-intl": "^4.6.1",        // i18n
    "zustand": "^5.0.8",           // State management
    "framer-motion": "^12.23.24",  // Animations
    "@microsoft/signalr": "^9.0.6" // Real-time chat
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why Next.js 15?&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;App Router — native Server Components support&lt;/li&gt;
&lt;li&gt;ISR (Incremental Static Regeneration) — critical for classified SEO&lt;/li&gt;
&lt;li&gt;next-intl — best integration for multilingualism&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Frontend + Backend Integration&lt;/strong&gt;&lt;br&gt;
Frontend communicates with ASP.NET Core via REST API with retry logic:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// lib/server-api-service.ts

  async function fetchWithRetry&amp;lt;T&amp;gt;(endpoint: string): Promise&amp;lt;T&amp;gt; {
  const url = `${API_CONFIG.EXTERNAL_API_URL}${endpoint}`;

  for (let attempt = 1; attempt &amp;lt;= 3; attempt++) {
    try {
      const controller = new AbortController();
      const timeoutId = setTimeout(() =&amp;gt; controller.abort(), 10000);

      const response = await fetch(url, {
        signal: controller.signal,
        headers: { 
          'Content-Type': 'application/json',
          'User-Agent': 'RSALE-Frontend/1.0' 
        }
      });

      clearTimeout(timeoutId);
      return await response.json();

    } catch (error) {
      if (attempt === 3) throw error;
      await new Promise(r =&amp;gt; setTimeout(r, 1000));
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;ISR Architecture: The Key to SEO&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For classifieds, SEO is everything. Every listing must be indexed by Google. We use different revalidation intervals:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// lib/config.ts
export const ISR_CONFIG = {
  REVALIDATE_MAIN: 300,      // Homepage: 5 min
  REVALIDATE_PRODUCTS: 600,  // Lists: 10 min  
  REVALIDATE_DETAILS: 1200,  // Product pages: 20 min
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Server Components vs Client Components&lt;/strong&gt;&lt;br&gt;
We developed the "Server-First + Client Wrapper" pattern:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app/[locale]/page.tsx — Server Component
export default async function HomePage({ params }) {
  const { locale } = await params;
  setRequestLocale(locale);
  return (
    &amp;lt;&amp;gt;
      {/* SEO-critical content renders on server */}
      &amp;lt;script type="application/ld+json" 
        dangerouslySetInnerHTML={{ 
          __html: JSON.stringify(structuredData.website()) 
        }} 
      /&amp;gt;

      &amp;lt;Suspense fallback={&amp;lt;CategoriesSkeleton /&amp;gt;}&amp;gt;
        &amp;lt;MainPageContent /&amp;gt;  {/* Server Component */}
      &amp;lt;/Suspense&amp;gt;
    &amp;lt;/&amp;gt;
  );
} 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rule: Everything the search bot sees — server component. Interactivity (modals, forms, auth) — client components.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Three Languages: Serbian, English, Russian&lt;/strong&gt;&lt;br&gt;
Multilingualism was mandatory from day one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// app/[locale]/products/page.tsx
export default async function ProductsPage({ params }) {
  const { locale } = await params;
  setRequestLocale(locale);

  const t = await getTranslations('navigation');

  return (
    &amp;lt;h1&amp;gt;{t('products')}&amp;lt;/h1&amp;gt;  
    // ru: "Товары", sr: "Производи", en: "Products"
  );
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Important lesson: Serbian has two alphabets — Cyrillic and Latin. We chose Cyrillic as more traditional for the older generation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI Translation of Listings on the Server&lt;/strong&gt;&lt;br&gt;
One of our key features — automatic listing translation using AI. When a user adds a product or service in one language, the Translation Service automatically translates the content into the other two languages:&lt;/p&gt;

&lt;p&gt;User writes in Russian:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Продаю iPhone 14 Pro, отличное состояние, полный комплект"&lt;br&gt;
↓ AI Translation Service ↓&lt;br&gt;
Serbian: "Продајем iPhone 14 Pro, одлично стање, комплетан сет"&lt;br&gt;
English: "Selling iPhone 14 Pro, excellent condition, full set"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;Backend implementation (ASP.NET Core):&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
// TranslationService.cs
public class AITranslationService : ITranslationService
{
    private readonly IAIClient _aiClient;

    public async Task&amp;lt;TranslatedContent&amp;gt; TranslateAsync(
        string title, 
        string description, 
        string sourceLang)
    {
        var targetLanguages = new[] { "ru", "sr", "en" }
            .Where(l =&amp;gt; l != sourceLang);

        var translations = new Dictionary&amp;lt;string, LocalizedContent&amp;gt;();

        foreach (var targetLang in targetLanguages)
        {
            var translated = await _aiClient.TranslateAsync(
                new TranslationRequest
                {
                    Title = title,
                    Description = description,
                    From = sourceLang,
                    To = targetLang
                });

            translations[targetLang] = translated;
        }

        return new TranslatedContent
        {
            Original = new LocalizedContent { Title = title, Description = description },
            SourceLanguage = sourceLang,
            Translations = translations
        };
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Why this matters:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Lower barrier to entry — sellers don't think about translation&lt;/li&gt;
&lt;li&gt;SEO in all languages — listings are indexed in three language versions&lt;/li&gt;
&lt;li&gt;3x audience — a Russian-speaking seller reaches Serbian and English-speaking buyers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Current Development Metrics&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Metric Value
Build Time (frontend)   ~3 sec
Bundle Size 99.7 kB
Lighthouse Performance  90+
SEO Score   9/10
Static Pages    72

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;What's Next?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We're actively working on:&lt;/li&gt;
&lt;li&gt;Completing the backend — transitioning from test data to production&lt;/li&gt;
&lt;li&gt;PWA — offline mode for mobile&lt;/li&gt;
&lt;li&gt;Real-time chat — SignalR is already connected on both ends&lt;/li&gt;
&lt;li&gt;On-Demand Revalidation — webhook from ASP.NET Core to Next.js when listings change&lt;/li&gt;
&lt;li&gt;Improving AI translation — contextual translation based on product category&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Building a classified platform in 2024-2025 isn't rocket science, but it requires thoughtful technical decisions:&lt;/li&gt;
&lt;li&gt;ASP.NET Core for a reliable and fast backend&lt;/li&gt;
&lt;li&gt;Microservices for independent scaling (especially AI translation)&lt;/li&gt;
&lt;li&gt;Next.js 15 with ISR for SEO and performance&lt;/li&gt;
&lt;li&gt;AI translation to remove language barriers&lt;/li&gt;
&lt;li&gt;The project is still in development, but the architecture is already set up right — and that's what matters. If you have questions about our stack or architecture — drop them in the comments!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://rsale.net/" rel="noopener noreferrer"&gt;rsale.net&lt;/a&gt; - check out the demo &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrown2qf3zzpl3wshdly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkrown2qf3zzpl3wshdly.png" alt=" " width="163" height="41"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>startup</category>
      <category>nextjs</category>
      <category>dotnet</category>
    </item>
  </channel>
</rss>
