Command Palette

Search for a command to run...

Kural AI

Tamil site building guide

தமிழ் இணையதள கட்டுமான வழிகாட்டி

End-to-end guide to building a production-quality Tamil-first website using Tamil DS. Covers setup, typography safety, component usage, Kural AI integration, accessibility, and deployment.

Tamil DS பயன்படுத்தி உற்பத்தி-தர தமிழ் முதன்மை இணையதளத்தை உருவாக்குவதற்கான முழுமையான வழிகாட்டி. அமைப்பு, எழுத்துரு பாதுகாப்பு, கூறு பயன்பாடு, குறள் AI ஒருங்கிணைப்பு, அணுகல்தன்மை மற்றும் வெளியிடுதல் ஆகியவற்றை உள்ளடக்கியது.

Next.jsReactTailwind CSSTamil DSKural AI

Build a Tamil-first site that works perfectly from day one.

முதல் நாளிலிருந்தே சரியாக செயல்படும் தமிழ் முதன்மை இணையதளத்தை உருவாக்குங்கள்.

This guide walks through every step from HTML root configuration to deployment. Follow it sequentially for a new project, or jump to specific sections when retrofitting Tamil support into an existing site.

1. Initial Setup

அடிப்படை அமைப்பு — HTML root, எழுத்துரு ஏற்றுதல், மற்றும் Tamil DS தொடக்கம்

1

HTML root configuration

Set lang="ta" on the <html> element. This activates Tamil DS's line-height scoping for text content nodes under :lang(ta). IMPORTANT: lang=ta on a container makes its :lang(ta) selector match ALL descendants — including buttons, inputs, checkboxes and switches. The CSS is scoped to only text content nodes (p, li, span, td, blockquote) so interactive controls are not affected.

<html lang="ta" dir="ltr">
2

Install Tamil UI Package

Install the core package which contains the reusable components, tokens, typography helpers, and agent guidelines.

npm install @tamildesignsystem/react
3

Font loading (Next.js 16 / React 19)

Load Noto Sans Tamil as the primary Tamil font alongside Inter for Latin text. Tamil DS provides the font-tamil utility class that maps to the Tamil font stack. Using next/font/google with the variable option for Tailwind v4 CSS custom properties.

import { Inter, Noto_Sans_Tamil } from "next/font/google";

const inter = Inter({ subsets: ["latin"], variable: "--font-sans" });
const notoTamil = Noto_Sans_Tamil({ subsets: ["tamil"], variable: "--font-tamil" });

// Apply to body — this sets the CSS custom properties, not the class itself:
<body className={`${inter.variable} ${notoTamil.variable}`}>
4

Import Tamil UI globals (Tailwind v4)

Import the Tamil UI globals.css stylesheet from the package. This is Tailwind v4 CSS-first config.

@import "tailwindcss";
@source "../../node_modules/@tamildesignsystem/react/dist";
@import "@tamildesignsystem/react/styles.css";

// This stylesheet includes:
// - @theme {} blocks: token colors (--background, --foreground, --primary, etc.)
// - Tamil line-height interceptors for :lang(ta) and .font-tamil
5

Apply font-tamil class — SCOPING RULES

CRITICAL RULE: Apply font-tamil only on text content elements (p, span, Label, h1-h6), NEVER on a wrapper div, Card, CardContent, or section that also contains form controls (Input, Checkbox, Switch, Button, Select). Putting lang=ta or .font-tamil on a container bleeds line-height: 1.8 into all interactive controls, distorting their height and visual alignment.

// CORRECT — font-tamil on individual text nodes:
<Label htmlFor="name" className="font-tamil">பெயர்</Label>
<p className="font-tamil">விதிமுறைகளை ஏற்கிறேன்</p>
<span lang="ta" className="font-tamil">அறிவிப்புகள்</span>

// CORRECT — for fully Tamil sites (no form controls as direct descendants of body):
<body className="font-tamil">

// WRONG — bleeds line-height into Checkbox, Input and Button inside:
<CardContent lang="ta" className="font-tamil">  {/* ❌ */}
  <Input />
  <Checkbox />
  <Button />
</CardContent>

// CORRECT version of the above:
<CardContent>  {/* ✅ no lang/font-tamil on wrapper */}
  <Input />
  <div className="flex items-center gap-2.5">
    <Checkbox id="terms" />
    <Label htmlFor="terms" className="font-tamil">விதிமுறைகளை ஏற்கிறேன்</Label>
  </div>
  <Button>Submit</Button>
</CardContent>
6

Configure Next.js 16 metadata

Set the default language and locale in your Next.js layout for proper SEO and browser rendering. Next.js 16 uses App Router with layout.tsx.

// src/app/layout.tsx
export const metadata: Metadata = {
  title: "Your Tamil Site",
  description: "தமிழில் கட்டப்பட்ட இணையதளம்",
  openGraph: { locale: "ta_IN" },
};

// root layout — note lang on the html element, NOT on body or wrapper:
export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="ta" dir="ltr">
      <body className={`${inter.variable} ${notoTamil.variable}`}>
        {children}
      </body>
    </html>
  );
}

2. Tamil Typography Safety

தமிழ் எழுத்துரு பாதுகாப்பு — உயிரெழுத்து மோதல்களைத் தடுக்கும் விதிகள்

Line-height scoping — CRITICAL

எழுத்து உயரப் பாதுகாப்பு — முக்கியமானது

  • Tamil DS applies line-height: 1.8 ONLY to text content nodes (p, li, span, td, blockquote, figcaption) — not to every element matching .font-tamil or :lang(ta).
  • This scoping is intentional: interactive controls (button, input, label, checkbox, switch) must NOT inherit line-height: 1.8 from a parent container.
  • leading-none is scaled to 1.35, leading-tight to 1.45, leading-snug to 1.55 for Tamil text.
  • Never use arbitrary tight line-heights like leading-[1.1] or leading-[1.08] on Tamil text.
  • For body copy, use leading-7 (1.75rem) or leading-relaxed as the default.

Diacritic-safe containers

உயிரெழுத்து-பாதுகாப்பான கொள்கலன்கள்

  • Never combine fixed heights (h-5, h-6, h-8) with overflow-hidden on elements containing Tamil text.
  • Tamil vowel markers (ி, ீ, ு, ூ, ்) extend above and below standard letter heights.
  • Use min-h-* with h-fit instead of fixed h-* values for badges, chips, and inline elements.
  • Apply comfortable vertical padding (py-1.5 or py-2) rather than relying on tight height constraints.

Character width

எழுத்து அகலம்

  • Tamil characters are wider than Latin equivalents. A 10-character English word may need 15+ Tamil characters.
  • Allow Tamil labels to wrap in chips and buttons rather than truncating.
  • Set max-width for body copy at 50-65 Tamil characters per line (roughly 600-700px at text-sm).
  • Test all UI labels with real Tamil strings, not placeholder Latin text.

Critical: Never do this

leading-none on Tamil text → diacritics will overlap

h-5 overflow-hidden on badges → vowel marks will be clipped

leading-[1.08] on headings → combining characters will collide

truncate on Tamil labels without tooltip → content becomes unreadable

3. Component Patterns for Tamil

தமிழ் உரைக்கான கூறு வடிவங்கள் — ஒவ்வொரு கூறுக்கும் தமிழ் பாதுகாப்பு வழிமுறைகள்

Navigation

Use bilingual nav labels only when explicitly bilingual. Default to Tamil-only for Tamil sites. Include skip-to-main link and keyboard navigation.

font-tamil on nav labels, aria-labels in Tamil

Hero section

Compact hero with confident h1, short supporting Tamil copy, one primary CTA, one secondary action, and a real UI surface (search, form, dashboard).

Use leading-snug or leading-[1.35] minimum for large Tamil headings

Service cards

Cards for repeated items (services, schemes, departments). Use rounded-md, border, bg-card, subtle shadow, and 20-28px padding.

font-tamil on all card text, icon alignment with Tamil title baselines

Forms and inputs

Pair inputs with Tamil labels. Placeholder text in Tamil. Validation messages in Tamil. Use w-full min-w-0 for responsive inputs.

Use the font-tamil class on Input, Textarea, Select components

Tables

Use Tamil column headers with font-tamil. Allow generous row height for Tamil text. Use leading-6 or leading-7 for table cell content.

Never truncate Tamil text in table cells without tooltip

Badges and chips

Use min-h-5 h-fit instead of h-5 for badges containing Tamil text. Remove overflow-hidden. Add py-0.5 minimum.

Test with vowel markers like ி, ீ that extend vertically

Dialogs and sheets

Tamil title and description with font-tamil. Generous padding. Action buttons with Tamil labels.

Ensure dialog body scrolls and does not clip Tamil content

4. Kural AI Integration

குறள் AI ஒருங்கிணைப்பு — திறன் குறிகள், உள்ளமை தூண்டல் மற்றும் கட்டளை பகுப்பாய்வு

Tamil DS provides two chat interface patterns: KuralAIChatSection for embedded page sections and FloatingKuralChat for floating assistants. Both follow the same design specification for Skills Tags, Inline Prompt layout, and slash command responses.

Skills Tags setup

Clickable slash-command lozenges that populate the chat input with the corresponding command.

const skillTags = [
  { label: "/சுருக்கம் / summarize", command: "/சுருக்கம்" },
  { label: "/தகுதி / eligibility", command: "/தகுதி" },
  { label: "/ஆவணங்கள் / documents", command: "/ஆவணங்கள்" },
  { label: "/விண்ணப்பம் / apply", command: "/விண்ணப்பம்" },
  { label: "/தொடர்பு / contact", command: "/தொடர்பு" },
];

// Render as clickable lozenges:
<div className="flex flex-wrap gap-2">
  {skillTags.map((tag) => (
    <button
      key={tag.command}
      type="button"
      onClick={() => {
        setValue(tag.command + " ");
        inputRef.current?.focus();
      }}
      className="inline-flex items-center rounded-md border border-border
        bg-muted/50 px-2.5 py-0.5 text-xs font-semibold text-foreground
        font-tamil shadow-sm transition hover:bg-accent"
    >
      <span className="text-muted-foreground mr-1">/</span>
      {tag.label.substring(1)}
    </button>
  ))}
</div>

Inline Prompt composer

The standard Tamil DS inline prompt layout with action icons flanking the input.

<div className="flex items-center gap-2 rounded-md border px-3 py-2
  shadow-xs focus-within:ring-1 focus-within:ring-ring">
  <Plus className="h-4 w-4 text-muted-foreground" />
  <Settings2 className="h-4 w-4 text-muted-foreground" />
  <input
    ref={inputRef}
    value={value}
    onChange={(e) => setValue(e.target.value)}
    className="flex h-8 w-full min-w-0 bg-transparent px-2 text-sm
      font-tamil outline-none placeholder:text-muted-foreground"
    placeholder="கேட்க, அல்லது செயல்களுக்கு / ஐ தட்டச்சு செய்க"
  />
  <Mic className="h-4 w-4 text-muted-foreground" />
  <Button size="icon-xs">
    <ArrowUp className="h-3 w-3" />
  </Button>
</div>
<p className="mt-2 text-center text-[11px] text-muted-foreground font-tamil">
  <Info className="inline h-3 w-3" /> AI பயன்படுத்தப்படுகிறது. முடிவுகளை சரிபார்க்கவும்.
</p>

Slash command parser

Parse slash commands first, then fall back to keyword matching for natural language queries.

function getAIReply(prompt: string): ChatMessage {
  const query = prompt.toLowerCase().trim();

  if (query.startsWith("/சுருக்கம்") || query.startsWith("/summarize")) {
    return {
      role: "assistant",
      title: "சுருக்கம் / Summary",
      text: "Structured bilingual response text here...",
      bullets: ["Bullet point 1", "Bullet point 2", "Bullet point 3"],
    };
  }

  if (query.startsWith("/தகுதி") || query.startsWith("/eligibility")) {
    return { role: "assistant", title: "தகுதி / Eligibility", text: "...", bullets: [...] };
  }

  // ... more slash commands

  // Fallback to keyword matching
  return { role: "assistant", title: "Default", text: "...", bullets: [...] };
}

5. Accessibility for Tamil Sites

தமிழ் இணையதளங்களுக்கான அணுகல்தன்மை — திரை வாசிப்பான்கள், விசைப்பலகை மற்றும் பார்வை பாதுகாப்பு

Set lang="ta" on the root <html> element for screen reader pronunciation.

Include a skip-to-main link at the top of the page: <a href="#main" className="sr-only focus:not-sr-only">.

All icon-only buttons require aria-label in Tamil (e.g. aria-label="செய்தி அனுப்பு").

Provide text size and contrast controls for public-service pages (AccessibilityToolbar pattern).

Focus-visible rings on all interactive elements. Use focus-visible:ring-2 focus-visible:ring-ring.

Color should never be the sole indicator of status. Pair with icon or text label.

Floating chat widgets must be keyboard-reachable and closable with Escape key.

Test at 375px mobile width: no clipped Tamil text, no overflowing containers, no hidden primary actions.

Short browser height: floating panels use viewport-safe height (e.g. [height:min(660px,calc(100dvh-7.25rem))]).

Semantic heading hierarchy: one h1 per page, logical h2/h3 flow without skips.

Zero new implementation

6. Theming & Dark Mode

Light mode, dark mode, high contrast and on-demand palette overrides are already built into the project. No new ThemeProvider, CSS files or theming libraries are needed. Use token utilities and let the cascade do the work.

Theme foundation

Zero new implementation required

ThemeProvider (next-themes 0.4.6) is already configured in layout.tsx. defaultTheme='light', enableSystem=true. Do NOT add a second ThemeProvider or change these props.

Dark mode mechanism

CSS .dark class on <html>

next-themes adds/removes .dark automatically. Tailwind v4 @custom-variant dark (&:is(.dark *)) in globals.css maps .dark to all dark: utilities.

Light tokens

:root {} in globals.css

--background: oklch(0.99 0 0), --foreground: oklch(0.145 0 0), --primary: oklch(0.56 0.18 285) [violet brand], --card: white, --muted: oklch(0.965 0.001 260), --border: oklch(0.922 0.004 260).

Dark tokens

.dark {} in globals.css

--background: oklch(0.10 0 0), --foreground: oklch(0.93 0 0), --primary: oklch(0.70 0.16 285) [lighter violet], --card: oklch(0.135 0.005 260), shadows use higher opacity (0.24–0.56).

High contrast

.a11y-high-contrast class

Applied by AccessibilityProvider. Overrides background→white/black, foreground→black/white, border→black/white. Works on top of both light and dark. No extra code needed.

On-demand theming

Inline CSS property override

To change palette for a section: <div style={{'--primary': 'oklch(0.60 0.20 160)', '--brand': 'oklch(0.60 0.20 160)'} as React.CSSProperties}>. All child primitives inherit it automatically.

Correct utility usage

Token-based utilities only

✅ bg-background, bg-card, bg-primary, text-foreground, text-muted-foreground, border-border. ❌ Never: bg-white, bg-gray-900, text-black, border-gray-200, hardcoded oklch() in JSX.

Theme toggle pattern

useTheme() from next-themes

const { resolvedTheme, setTheme } = useTheme(). Always resolvedTheme (never theme) to avoid SSR mismatch. Toggle: setTheme(resolvedTheme === 'dark' ? 'light' : 'dark').

SSR hydration

suppressHydrationWarning

Required on both <html> and <body> elements to prevent next-themes hydration warnings. Already in layout.tsx — do not remove.

A11y provider

AccessibilityProvider in layout.tsx

Applies a11y-text-{sm|md|lg|xl|2xl}, a11y-spacing-*, a11y-high-contrast, a11y-dyslexia classes to <html>. State persisted to localStorage. Access via useAccessibility() hook.

7. Deployment Checklist

வெளியிடுதல் சோதனைப் பட்டியல் — உற்பத்திக்கு முன் சரிபார்க்க வேண்டிய அனைத்தும்

Pre-build

npm run lint

Zero ESLint errors and warnings.

Type check

npx tsc --noEmit

Zero TypeScript type errors.

Production build

npm run build

All routes compile. Check for Tamil text in build output.

Visual QA

Browser at 375px and 1440px

No clipped Tamil diacritics, no container overflow, no broken layouts.

Dark mode QA

Toggle dark mode in browser

Verify all surfaces switch correctly. No hardcoded white/black. Check cards, inputs, borders, badges and status colors in dark mode.

Tamil text test

Review all pages with real Tamil content

Verify line-heights, wrapping, badge sizing, and form labels.

Accessibility audit

Keyboard navigation + screen reader

All interactive elements reachable. aria-labels correct.

Performance

Lighthouse or similar

Font loading optimized. No layout shifts from Tamil font swap.

Tamil-first, always

UI defaults to Tamil. English appears only for proper nouns, code, and explicit bilingual requests.

Bilingual when needed

Use Skills Tags with bilingual labels (/சுருக்கம் / summarize). AI responses include both Tamil titles and English equivalents.

Production-ready

Every step verified with lint, type-check, and build. No clipped text, no broken layouts, no missing accessibility.

Continue with the AI Vibe Coding Manual

This guide covers Tamil site specifics. For the full AI coding operating manual including workflow, component decisions, prompts, and verification, see the parent page.

Back to AI Vibe Coding Manual