DEV Community

Cover image for Building simple ECommerce site with Juris
artydev
artydev

Posted on

Building simple ECommerce site with Juris

If you want to build a simple, lightweight eCommerce website without relying on React, Angular, Vue.js, or other overhyped frameworks, follow along.

We’ll keep things minimal and efficient by using just two libraries: Juris and BSS.

Let’s start by looking at the project’s folder structure::

Let's extent it:

It’s worth noting that, for now, we don’t need to include Node.js in our workflow.

We’ll begin by examining the index.html file :

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Galaxy Tech Shop</title>
  <script type="importmap">
    {
      "imports": {
        "juris": "https://esm.sh/juris@0.9",
        "bss": "https://esm.sh/bss@1.6"
      }
    }
  </script>
</head>
<body>
  <div id="app"></div>
  <script type="module" src="./src/main.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

Let’s ask an AI to explain what’s happening here.

Development Perspective

This HTML file reflects a modern, minimalist, and framework-free approach to web development. Let’s break down what makes it interesting from a development standpoint.

🚀 Modern JavaScript Without a Build Step

By using type="module" along with an import map, we can rely on native ES modules directly in the browser.

This means:

  • No bundler
  • No transpiler
  • No immediate need for Node.js

This setup keeps the development workflow lightweight and fast.

📦 CDN-Based Dependency Management

The dependencies (juris and bss) are loaded directly from a CDN via esm.sh.

Benefits:

  • Instant setup
  • No local installation
  • Ideal for prototypes and small projects

You can run the project using a simple static server.

🧩 Clear Separation of Concerns

The HTML stays minimal and declarative:

  • A single mounting point: #app
  • All logic lives in main.js

This keeps the structure clean and easy to maintain.

🔮 Future-Friendly Architecture

Even without a framework, this setup follows modern SPA principles.

If the project grows, adding a build step or a Node.js workflow later will be straightforward.

🌍 Standards-First Approach

Everything here is based on web standards:

  • ES modules
  • Import maps
  • Semantic HTML

This reduces vendor lock-in and improves long-term maintainability.

⚖️ Trade-offs to Consider

  • CDN imports may need optimization for production (caching, version pinning).
  • Import maps are supported by modern browsers, but not legacy ones.

✅ Summary

This approach prioritizes simplicity, performance, and control.

It’s a solid foundation for lightweight applications, educational projects, or anyone looking to avoid heavy frameworks while still writing modern web code.


Let us examine now the entry point app.js :

import { Juris } from 'juris';
import { initGlobalStyles } from './styles/global.js';
import { products } from './data/products.js';
import { loadCartFromStorage } from './utils/storage.js';

// Styles
initGlobalStyles();

// 1. IMPORT the missing UI components
import { NavLink } from './components/ui/NavLink.js';
import { CartBadge } from './components/ui/CartBadge.js';
import { Hero } from './components/ui/Hero.js';
import { Breadcrumb } from './components/ui/Breadcrumb.js';

// 2. IMPORT the rest of your components
import { ProductCard } from './components/product/ProductCard.js';
import { CartItem } from './components/product/CartItem.js';
import { ProductsPage } from './components/pages/ProductsPage.js';
import { CartPage } from './components/pages/CartPage.js';
import { ProductDetailPage } from './components/pages/ProductDetailPage.js';
import { RouteRenderer } from './components/routing/RouteRenderer.js';
import { App } from './app.js';

const juris = new Juris({
    states: {
        products,
        cart: loadCartFromStorage(),
        router: {
            currentRoute: location.hash.slice(1) || '/'
        }
    },
    components: {
        NavLink, 
        Hero, 
        CartItem, 
        Breadcrumb, 
        ProductCard, 
        CartBadge,
        ProductsPage, 
        CartPage, 
        ProductDetailPage, 
        RouteRenderer
    }
});

document.getElementById('app').append(juris.objectToHtml(App));

window.addEventListener('hashchange', () =>
    juris.setState('router.currentRoute', location.hash.slice(1) || '/')
);
Enter fullscreen mode Exit fullscreen mode

Top comments (0)