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 ஒருங்கிணைப்பு, அணுகல்தன்மை மற்றும் வெளியிடுதல் ஆகியவற்றை உள்ளடக்கியது.
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 தொடக்கம்
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">Install Tamil UI Package
Install the core package which contains the reusable components, tokens, typography helpers, and agent guidelines.
npm install @tamildesignsystem/reactFont 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}`}>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-tamilApply 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>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.
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 requiredThemeProvider (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 classApplied 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 overrideTo 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-themesconst { resolvedTheme, setTheme } = useTheme(). Always resolvedTheme (never theme) to avoid SSR mismatch. Toggle: setTheme(resolvedTheme === 'dark' ? 'light' : 'dark').
SSR hydration
suppressHydrationWarningRequired on both <html> and <body> elements to prevent next-themes hydration warnings. Already in layout.tsx — do not remove.
A11y provider
AccessibilityProvider in layout.tsxApplies 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 lintZero ESLint errors and warnings.
Type check
npx tsc --noEmitZero TypeScript type errors.
Production build
npm run buildAll routes compile. Check for Tamil text in build output.
Visual QA
Browser at 375px and 1440pxNo clipped Tamil diacritics, no container overflow, no broken layouts.
Dark mode QA
Toggle dark mode in browserVerify 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 contentVerify line-heights, wrapping, badge sizing, and form labels.
Accessibility audit
Keyboard navigation + screen readerAll interactive elements reachable. aria-labels correct.
Performance
Lighthouse or similarFont loading optimized. No layout shifts from Tamil font swap.
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