Model.Unit.tsx Implementation Guide

Model.Unit.tsx files are foundational server components that provide reusable presentation elements for domain models in Akan.js applications. They create consistent visual representations that can be used across pages, zones, templates, and utilities.

Purpose and Role

Model Unit components serve several critical purposes in the Akan.js architecture:

  • Create standardized visual representations of domain entities
  • Serve as atomic UI building blocks for complex interfaces
  • Encapsulate rendering logic for cnst.LightModel data objects
  • Optimize for Next.js server components architecture

Component Variations

Abstract

Minimal representation with essential information only

<Product.Unit.Abstract product={product} />
Card

Medium-detail representation in a card format

<Product.Unit.Card product={product} />
Full

Complete representation with all relevant details

<Product.Unit.Full product={product} />
Row

Table row representation for list views

<Product.Unit.Row product={product} />

Example: Product Unit Components

// Product.Unit.tsx
export const Abstract = ({ product, className }) => (
  <div className={"flex items-center gap-3"}>
    {product.thumbnail && (
      <Image file={product.thumbnail} className="h-12 w-12 rounded" />
    )}
    <div>
      <h3 className="font-medium">{product.name}</h3>
      <p className="text-sm">{product.price.toLocaleString()} KRW</p>
    </div>
  </div>
);
export const Card = ({ product, className }) => (
  <div className={"card bg-base-100 shadow-sm"}>
    {product.image && (
      <Image file={product.image} className="h-48 w-full object-cover" />
    )}
    <div className="card-body">
      <h2 className="card-title">{product.name}</h2>
      <p className="line-clamp-2">{product.shortDescription}</p>
      <div className="card-actions justify-end">
        <button className="btn btn-primary btn-sm">View</button>
      </div>
    </div>
  </div>
);

Implementation Guidelines

server-components

Keep as server components without client-side hooks

// No useState, useEffect, etc.
lightmodel

Only access properties defined in LightModel types

product.name // Not product.description
conditional

Use optional chaining for nested properties

product.avatar?.url
className

Always include className prop for styling

className={'base-classes'}

Image Handling Best Practice

import { Image } from "@akanjs/ui";
export const Card = ({ product }) => (
  <div className="card">
    {product.image ? (
      <Image 
        file={product.image} 
        alt={product.name}
        className="h-40 w-full object-cover"
        sizes="(max-width: 768px) 100vw, 50vw"
      />
    ) : (
      <div className="bg-base-200 flex h-40 items-center justify-center">
        <span className="text-base-content/50">No image</span>
      </div>
    )}
  </div>
);

Usage Examples

In Pages

// Product page
import { Product } from "@shared/client";
export default async function ProductsPage() {
  const products = await getProducts();
  
  return (
    <div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
      {products.map(product => (
        <Product.Unit.Card 
          key={product.id} 
          product={product} 
          href={`/products/${product.id}`}
        />
      ))}
    </div>
  );
}

In Templates

// Product selection template
"use client";
import { useState } from "react";
import { Product } from "@shared/client";
export const ProductSelector = ({ products }) => {
  const [selectedId, setSelectedId] = useState(null);
  return (
    <div className="space-y-2">
      {products.map(product => (
        <div 
          key={product.id}
          className={`cursor-pointer transition-all ${selectedId === product.id ? "ring-2 ring-primary" : ""}`}
          onClick={() => setSelectedId(product.id)}
        >
          <Product.Unit.Abstract product={product} />
        </div>
      ))}
    </div>
  );
};

Performance Optimization

For optimal performance with Unit components:

// Memoization in client components
"use client";
import { memo } from "react";
import { Product } from "@shared/client";
const MemoizedCard = memo(Product.Unit.Card);
export const ProductGrid = ({ products }) => (
  <div className="grid grid-cols-3 gap-4">
    {products.map(product => (
      <MemoizedCard key={product.id} product={product} />
    ))}
  </div>
);
// Virtualization for long lists
"use client";
import { useVirtualizer } from "@tanstack/react-virtual";
import { useRef } from "react";
import { User } from "@shared/client";
export const VirtualUserList = ({ users }) => {
  const parentRef = useRef();
  const rowVirtualizer = useVirtualizer({
    count: users.length,
    getScrollElement: () => parentRef.current,
    estimateSize: () => 64,
  });
  return (
    <div ref={parentRef} className="h-[600px] overflow-auto">
      <div style={{ height: `${rowVirtualizer.getTotalSize()}px`}}>
        {rowVirtualizer.getVirtualItems().map(virtualItem => (
          <div 
            key={virtualItem.key}
            style={{
              position: "absolute",
              top: 0,
              left: 0,
              width: "100%",
              height: `${virtualItem.size}px`,
              transform: `translateY(${virtualItem.start}px)`,
            }}
          >
            <User.Unit.Row user={users[virtualItem.index]} />
          </div>
        ))}
      </div>
    </div>
  );
};

Troubleshooting

server-hooks

Server component using client hooks

Remove useState/useEffect from Unit files
missing-props

Accessing undefined properties

product.description → product.shortDescription
image-errors

Missing alt text for images

<Image alt="Product image" ... />

Conclusion

Model.Unit.tsx files are essential building blocks in Akan.js that enable consistent, reusable presentation components for domain models. By following these implementation guidelines, you'll create performant, maintainable UI components that work seamlessly across your application.

Released under the MIT License
Official Akan.js Consulting onAkansoft
Copyright © 2025 Akan.js. All rights reserved.
System managed bybassman