Kateb Tech Docs
Packages

@katebtech/pages

Reusable page layouts, marketing page sections, service pages, and shared page-level components.

@katebtech/pages

Reusable page-section components for Kateb Tech website projects.

This package provides About, Contact, Services, and shared page UI components that can be imported independently by website projects. It should contain reusable page-building UI only; route files, website-specific data, SEO config, server actions, database queries, and publishing workflow details belong outside this package.

Purpose

@katebtech/pages keeps common page sections consistent across Kateb Tech websites while allowing each consuming website to provide its own content and routing.

Use this package for:

  • reusable page-section React components
  • shared page layout helpers
  • public props and content types for page sections

Do not use this package for:

  • Next.js route files such as app/about-us/page.tsx
  • SEO metadata for a specific website
  • organisation profile data
  • public route config
  • service, FAQ, opening-hours, or team-member content for one client
  • server actions, database queries, or email sending logic

Current package version: 2.0.6

Package Overview

Public subpaths:

@katebtech/pages/_ui
@katebtech/pages/about
@katebtech/pages/contact
@katebtech/pages/services

Peer dependencies:

  • next
  • react
  • react-dom

Runtime dependencies:

  • @katebtech/core
  • @katebtech/media
  • react-icons
  • swiper
  • zod

File Structure

src
├── _ui
│   ├── PageIntro.tsx
│   ├── Section.tsx
│   ├── index.ts
│   └── types.ts
├── about
│   ├── AboutTextSections.tsx
│   ├── AboutValues.tsx
│   ├── TeamGrid.tsx
│   ├── index.ts
│   └── types.ts
├── contact
│   ├── _ui
│   │   ├── ContactFAQ.tsx
│   │   ├── ContactMap.tsx
│   │   ├── OpeningHours.tsx
│   │   ├── index.ts
│   │   └── types.ts
│   └── index.ts
├── services
│   ├── _ui
│   │   ├── ServiceDetails.tsx
│   │   ├── ServiceLeafCard.tsx
│   │   ├── ServiceLeafCardSkeleton.tsx
│   │   └── index.ts
│   ├── index.ts
│   └── types.ts
└── index.ts

Import Style

Consumers should prefer specific package subpaths:

import { PageIntro, Section } from "@katebtech/pages/_ui";
import { AboutValues } from "@katebtech/pages/about";
import { ContactFAQ } from "@katebtech/pages/contact";
import { ServiceDetails } from "@katebtech/pages/services";

Import public types from the same subpath as the component:

import type { AboutValuesSection } from "@katebtech/pages/about";
import type { OpeningHours } from "@katebtech/pages/contact";
import type { ServicesPage } from "@katebtech/pages/services";

Inside this package, use relative imports instead of importing from @katebtech/pages.

Package Rules

  • Keep public components, helpers, and public types exported from the relevant index.ts.
  • Keep implementation details and internal-only types private.
  • Use PascalCase for React components, camelCase for functions and variables, and descriptive file and folder names.
  • Avoid any unless there is a strong reason.
  • Prefer explicit public types, readonly arrays for immutable data, discriminated unions for state shapes, and as const where literal types are useful.
  • Keep lower-level shared UI in _ui; feature sections belong under their feature folder.
  • Avoid circular dependencies between _ui, about, contact, and services.
  • Keep package exports in package.json aligned with public module paths.

Module Documentation

Shared Page UI

Import from @katebtech/pages/_ui.

import { PageIntro, Section } from "@katebtech/pages/_ui";

PageIntro

Renders a page heading and optional intro paragraphs.

<PageIntro
  heading="About Us"
  subHeading={[
    "We help organisations build practical websites and digital systems.",
  ]}
/>

Props:

PropTypeDefaultDescription
headingstringOptionalMain page heading.
subHeadingreadonly string[]OptionalSupporting intro paragraphs.
isRtlbooleanfalseEnables right-to-left text.

Section

Reusable section wrapper for page content.

<Section id="values">
  <AboutValues section={valuesSection} />
</Section>

Props:

PropTypeDefaultDescription
childrenReact.ReactNodeRequiredSection content.
classNamestringOptionalAdditional classes.
idstringOptionalSection id.
labelledBystringOptionalValue for aria-labelledby.

About

Import from @katebtech/pages/about.

import {
  AboutTextSections,
  AboutValues,
  TeamGrid,
} from "@katebtech/pages/about";
import type {
  AboutTextSection,
  AboutValuesSection,
  TeamMember,
  TeamSection,
} from "@katebtech/pages/about";

AboutTextSections

Renders a vertical list of about-page text sections.

<AboutTextSections
  sections={[
    {
      id: "our-story",
      title: "Our Story",
      items: [
        "We help small businesses build reliable websites and practical digital systems.",
      ],
    },
  ]}
/>

AboutValues

Renders a values section with a heading and list.

<AboutValues
  section={{
    id: "values",
    title: "Our Values",
    items: ["Clear communication", "Reliable delivery", "Practical support"],
  }}
/>

TeamGrid

Renders a team section with optional profile images.

<TeamGrid
  team={{
    id: "team",
    title: "Our Team",
    intro: "Our team brings practical experience and clear communication.",
    professionalTitles: ["Web Development", "SEO", "Business Systems"],
    members: [
      {
        name: "Team Member",
        role: "Support",
        bio: "Supports client projects and delivery.",
      },
    ],
  }}
/>

Contact

Import from @katebtech/pages/contact.

import {
  ContactFAQ,
  ContactMap,
  OpeningHoursComponent,
} from "@katebtech/pages/contact";
import type {
  ContactFAQProps,
  ContactMapProps,
  FAQItem,
  OpeningHours,
  OpeningHoursComponentProps,
} from "@katebtech/pages/contact";

ContactFAQ

Renders a contact-page FAQ using native details and summary elements.

<ContactFAQ
  items={[
    {
      q: "How quickly do you reply?",
      a: "We usually respond within one business day.",
    },
  ]}
/>

ContactMap

Renders a Google Maps iframe for a business address.

<ContactMap address="Dandenong VIC 3175, Australia" zoom={14} />

OpeningHoursComponent

Renders weekly opening hours.

<OpeningHoursComponent
  hours={{
    mon: { closed: false, open: "09:00", close: "17:00" },
    tue: { closed: false, open: "09:00", close: "17:00" },
    wed: { closed: false, open: "09:00", close: "17:00" },
    thu: { closed: false, open: "09:00", close: "17:00" },
    fri: { closed: false, open: "09:00", close: "17:00" },
    sat: { closed: true },
    sun: { closed: true },
  }}
/>

Services

Import from @katebtech/pages/services.

import {
  ServiceDetails,
  ServiceLeafCard,
  ServiceLeafCardSkeleton,
} from "@katebtech/pages/services";
import type {
  ServiceLeaf,
  ServicePricing,
  ServiceProductMeta,
  ServicesPage,
  ServiceSubCategory,
} from "@katebtech/pages/services";

ServiceDetails

Renders service leaf cards from a ServiceSubCategory collection.

<ServiceDetails subcategories={service.subcategories} aspect="16/9" />

ServiceLeafCard

Renders one service leaf card with heading, description, optional item list, and image gallery.

<ServiceLeafCard leaf={leaf} index={0} leafId="contract-review" />

ServiceLeafCardSkeleton

Loading skeleton for service leaf cards.

<ServiceLeafCardSkeleton />

Example service data:

import type { ServicesPage } from "@katebtech/pages/services";

export const SERVICES_PAGE = {
  buyingProperty: {
    slug: "buying-property-conveyancing-dandenong",
    label: "Buying Property Conveyancing",
    labelFarsi: "انتقال سند برای خرید ملک",
    keywords: ["conveyancing", "property"],
    description: ["Licensed conveyancing support for buyers in Victoria."],
    image: [],
    ogImage: "/images/services/buying-property.jpg",
    subcategories: {},
  },
} satisfies Record<string, ServicesPage>;

On this page