Frontend development using Nuxt.js for 1C-Bitrix

Our company is engaged in the development, support and maintenance of Bitrix and Bitrix24 solutions of any complexity. From simple one-page sites to complex online stores, CRM systems with 1C and telephony integration. The experience of developers is confirmed by certificates from the vendor.
Our competencies:
Development stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1175
  • image_bitrix-bitrix-24-1c_fixper_448_0.png
    Website development for FIXPER company
    811
  • image_bitrix-bitrix-24-1c_development_of_an_online_appointment_booking_widget_for_a_medical_center_594_0.webp
    Development based on Bitrix, Bitrix24, 1C for the company Development of an Online Appointment Booking Widget for a Medical Center
    564
  • image_bitrix-bitrix-24-1c_mirsanbel_458_0.webp
    Development based on 1C Enterprise for MIRSANBEL
    747
  • image_crm_dolbimby_434_0.webp
    Website development on CRM Bitrix24 for DOLBIMBY
    655
  • image_crm_technotorgcomplex_453_0.webp
    Development based on Bitrix24 for the company TECHNOTORGKOMPLEKS
    976

Nuxt.js Frontend for 1C-Bitrix

Nuxt.js is a Vue framework with built-in SSR, the Vue-stack equivalent of Next.js. When a team or project has historically used Vue, Nuxt.js is the natural choice for a headless architecture on top of 1C-Bitrix. The principles are identical to Next.js: Bitrix serves data via REST API, Nuxt handles rendering. The implementation details differ.

Headless Bitrix + Nuxt: Key Differences from Next.js

Nuxt.js uses the Vue Composition API and its own data-fetching system (useAsyncData, useFetch). Routing is filesystem-based, similar to Next.js. SSR, SSG, and ISR (called "hybrid rendering" in Nuxt) are all available.

// pages/catalog/[slug].vue
<script setup lang="ts">
const route = useRoute();

const { data: category } = await useFetch(
  `/api/catalog/category/${route.params.slug}`,
  {
    key:      `category-${route.params.slug}`,
    server:   true, // render on the server
    lazy:     false,
  }
);

const { data: products } = await useFetch('/api/catalog/products', {
  query:  { section: route.params.slug, limit: 24 },
  key:    `products-${route.params.slug}`,
  server: true,
});

// SEO
useHead({
  title:       category.value?.name,
  meta: [
    { name: 'description', content: category.value?.description },
    { property: 'og:title',       content: category.value?.name },
    { property: 'og:description', content: category.value?.description },
  ],
});
</script>

useFetch in Nuxt 3 automatically deduplicates requests — the same call on the server during SSR is not repeated on the client during hydration.

Nuxt Server Routes as a Bitrix Proxy

Nuxt 3 has a built-in H3 server with server routes (server/api/). This allows creating a proxy layer directly inside Nuxt without a separate backend service:

// server/api/catalog/products.get.ts
export default defineEventHandler(async (event) => {
  const query = getQuery(event);

  const response = await $fetch(
    `${process.env.BITRIX_URL}/local/ajax/api.php`,
    {
      method: 'POST',
      body: {
        action: 'catalog.products.list',
        ...query,
      },
      headers: {
        'X-Bitrix-Token': process.env.BITRIX_API_TOKEN,
      },
    }
  );

  // Normalize Bitrix data
  return {
    items: response.data.map(normalizeProduct),
    total: response.total,
  };
});

Nuxt server routes run on the Node.js server — Bitrix tokens never reach the browser, and CORS is not an issue.

State Management: Pinia

// stores/cart.ts
export const useCartStore = defineStore('cart', () => {
  const items   = ref<CartItem[]>([]);
  const isLoading = ref(false);

  async function addToCart(productId: number, quantity: number) {
    isLoading.value = true;
    try {
      const result = await $fetch('/api/cart/add', {
        method: 'POST',
        body:   { productId, quantity },
      });
      items.value = result.items;
    } finally {
      isLoading.value = false;
    }
  }

  const total = computed(() =>
    items.value.reduce((sum, item) => sum + item.price * item.quantity, 0)
  );

  return { items, isLoading, total, addToCart };
});

Pinia is the official Vue 3 state manager. Simpler than Redux, integrates with Vue DevTools, supports SSR with hydration state.

Case Study: Nuxt.js for a Construction Portal

A construction services portal: contractor catalog (12,000 companies), ratings, reviews, tender module. Bitrix was used for content and user management. Vue was the frontend team's chosen stack.

Primary challenge: SEO for contractor pages (each is a unique company with unique content). SSG was not feasible due to frequent data updates; SSR with caching was the optimal approach.

Implementation:

  1. Nuxt 3 with hybrid rendering: contractor pages — SSR + Redis cache (5 minutes); static pages (About, Terms) — SSG.

  2. Nuxt server routes: proxy to Bitrix REST API with useStorage('redis') cache from unstorage (bundled with Nuxt).

  3. Contractor search — Vue component with instant search via Typesense. When a company is updated in Bitrix, it triggers a webhook → a Node.js service updates the Typesense index.

  4. Tender module — SPA inside Nuxt: application submission, review status, chat with the client. JWT authentication stored in an httpOnly cookie.

Metric Before (Bitrix template) After (Nuxt.js)
TTFB (company page) 1.2–1.8 s 180–250 ms (cache)
Core Web Vitals (LCP) 5.2 s 1.8 s
Search engine indexing Full (HTML) Full (SSR)
New section development time 40% faster (components)

ISR Equivalent in Nuxt (SWR Cache)

Nuxt implements stale-while-revalidate via routeRules:

// nuxt.config.ts
export default defineNuxtConfig({
  routeRules: {
    '/catalog/**':  { swr: 300 },  // 5-minute cache, background revalidation
    '/company/**':  { swr: 180 },  // 3-minute cache
    '/about':       { prerender: true }, // static generation
    '/cart/**':     { ssr: false }, // CSR only, no SSR
  }
});

This is the Next.js ISR equivalent — pages are served from cache and updated in the background after expiry.

Deployment

Nuxt 3 supports multiple deployment targets: Node.js server, static export, edge functions (Cloudflare Workers, Vercel Edge). For a setup co-located with Bitrix on the same server — Node.js + PM2 + nginx.

# nginx: Nuxt on port 3000, Bitrix on port 80
server {
    server_name shop.example.ru;

    location /bitrix/  { proxy_pass http://127.0.0.1:8080; }
    location /upload/  { proxy_pass http://127.0.0.1:8080; }
    location /local/ajax/ { proxy_pass http://127.0.0.1:8080; }
    location /         { proxy_pass http://127.0.0.1:3000; }
}

Scope of Work

  • Bitrix API design for Nuxt consumption
  • Nuxt server route development (proxy + caching)
  • Vue/Nuxt component development: catalog, product page, search, cart
  • Hybrid rendering configuration: routeRules per page type
  • Pinia stores: cart, authentication, wishlist
  • Node.js + nginx deployment, PM2 cluster configuration

Timeline: comparable to Next.js — MVP 2–3 months, full project 4–6 months.