Typography Style Guide

.hero-title-large

Font: IBM Plex Sans Thai

Weight: 700 (Bold)

Size: 56px

Line Height: 66px

Used for: Main hero headlines on all pages

Best Places to Work Thailand

.hero-content

Font: IBM Plex Sans Thai

Weight: 400 (Regular)

Size: 22px

Line Height: 1.6

Used for: Hero subtitles and lead paragraphs

Turn employee voices into your strongest employer brand — and be recognized as one of Thailand's Best Places to Work™.

.section-title

Font: IBM Plex Sans Thai

Weight: 700 (Bold)

Size: 38px

Line Height: 1.3

Used for: Section headings (H2), e.g., above carousels

Trusted by Leading Companies

.content-text

Font: IBM Plex Sans Thai

Weight: 400 (Regular)

Size: 19px

Line Height: 35px

Used for: Body text, paragraphs, general content

Our comprehensive engagement survey helps you understand what your employees truly think and feel about their workplace. With actionable insights, you can build a stronger culture and improve retention.

HTML Heading Elements (H1-H5)

English

<h1>Font: IBM Plex Sans Thai | Weight: 700

Best Places to Work Thailand

<h2>Font: IBM Plex Sans Thai | Weight: 700

Trusted by Leading Companies

<h3>Font: IBM Plex Sans Thai | Weight: 700

Comprehensive Engagement Solutions

<h4>Font: IBM Plex Sans Thai | Weight: 700

Employee Survey and Analytics

<h5>Font: IBM Plex Sans Thai | Weight: 700
Workplace Culture Assessment

Thai (ไทย)

<h1>Font: IBM Plex Sans Thai | Weight: 700

สถานที่ทำงานที่ดีที่สุด

<h2>Font: IBM Plex Sans Thai | Weight: 700

บริษัทชั้นนำที่ไว้วางใจเรา

<h3>Font: IBM Plex Sans Thai | Weight: 700

โซลูชันการสำรวจความผูกพันที่ครอบคลุม

<h4>Font: IBM Plex Sans Thai | Weight: 700

แบบสำรวจและวิเคราะห์พนักงาน

<h5>Font: IBM Plex Sans Thai | Weight: 700
การประเมินวัฒนธรรมในที่ทำงาน

Thai Language Examples

สถานที่ทำงานที่ดีที่สุด

เปลี่ยนเสียงของพนักงานให้เป็นแบรนด์นายจ้างที่แข็งแกร่งที่สุด — และได้รับการยอมรับว่าเป็นหนึ่งในสถานที่ทำงานที่ดีที่สุดของประเทศไทย™

บริษัทชั้นนำที่ไว้วางใจเรา

แบบสำรวจความผูกพันที่ครอบคลุมของเราช่วยให้คุณเข้าใจว่าพนักงานของคุณคิดและรู้สึกอย่างไรเกี่ยวกับสถานที่ทำงานของพวกเขา ด้วยข้อมูลเชิงลึกที่นำไปปฏิบัติได้ คุณสามารถสร้างวัฒนธรรมที่แข็งแกร่งขึ้นและปรับปรุงการรักษาพนักงาน

Brand Colors

Brand Blue

#002B49

bg-brand-blue

text-brand-blue

Brand Blue Dark

#001a33

bg-brand-blue-dark

Hero backgrounds

Brand Blue Link

#0066CC

text-[#0066CC]

"Read More" links

Brand Red

#E6332A

bg-brand-red

text-brand-red

Brand Gray

#F5F5F5

bg-brand-gray

Section backgrounds

Semantic Colors

Success

#22C55E

bg-green-500

Error

#EF4444

bg-red-500

Section Examples

<Section background="white" padding="lg">

Section Title Example

This is an example of a section with white background. Use this for standard content sections.

<Section background="gray" padding="lg">

Section Title Example

This is an example of a section with gray background. Use this to create visual separation between sections.

1

Feature One

Feature description

2

Feature Two

Feature description

3

Feature Three

Feature description

<Section background="blue" padding="lg">

Section Title Example

This is an example of a section with blue background. Use this for prominent call-to-action sections.

Quick Reference

Class NameSizeWeightLine HeightUsage
.hero-title-large56px70066pxHero H1 headlines
.section-title38px7001.3Section H2 headings
.hero-content22px4001.6Hero subtitles
.content-text19px40035pxBody paragraphs

Intercom Integration

Implementation

Intercom is integrated globally via the root layout. The chat widget should appear in the bottom-right corner of all pages.

Component Location

src/components/Intercom.tsx

src/app/[locale]/layout.tsx

Code Example

'use client';

import { useEffect } from 'react';
import Intercom from '@intercom/messenger-js-sdk';

const INTERCOM_APP_ID = 'vsewq5ic';

export function IntercomMessenger() {
  useEffect(() => {
    Intercom({
      app_id: INTERCOM_APP_ID,
    });
  }, []);

  return null;
}

Usage in Layout

import { IntercomMessenger } from '@/components/Intercom';

export default async function LocaleLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <IntercomMessenger />
      </body>
    </html>
  );
}

Status

✅ Intercom is active on all pages including this typography page.

Look for the chat widget in the bottom-right corner of your browser window.

Configuration

App ID: vsewq5ic

Package: @intercom/messenger-js-sdk

Note: The App ID is hardcoded in the component. For production, consider using an environment variable.

Snitcher Integration

Implementation

Snitcher is integrated globally via the root layout. It provides session recording and visitor analytics to help identify potential leads and understand visitor behavior.

Component Location

src/components/Snitcher.tsx

src/app/[locale]/layout.tsx

Code Example

'use client';

import Script from 'next/script';

export function Snitcher() {
  const snitcherId = process.env.NEXT_PUBLIC_SNITCHER_ID;

  if (!snitcherId) {
    return null;
  }

  return (
    <Script
      id="snitcher"
      strategy="afterInteractive"
      dangerouslySetInnerHTML={{
        __html: `
          (function(s,n,i,t,c,h,e,r){
            s.SnitcherObject=t;
            s[t]=s[t]||function(){(s[t].q=s[t].q||[]).push(arguments)};
            s[t].l=1*new Date();
            h=n.getElementsByTagName('head')[0];
            e=n.createElement('script');
            e.async=1;
            e.src=i;
            e.charset='utf-8';
            h.appendChild(e);
          })(window,document,'https://cdn.snitcher.com/snt.js','_snt',[SNITCHER_ID]);
        `,
      }}
    />
  );
}

Usage in Layout

import { Snitcher } from '@/components/Snitcher';

export default async function LocaleLayout({ children }) {
  return (
    <html>
      <body>
        {children}
        <Snitcher />
      </body>
    </html>
  );
}

Status

⚠️ Snitcher is not configured. Add NEXT_PUBLIC_SNITCHER_ID to environment variables.

Snitcher runs silently in the background and tracks visitor sessions. Check your Snitcher dashboard to view analytics.

Configuration

Environment Variable: NEXT_PUBLIC_SNITCHER_ID

CDN: https://cdn.snitcher.com/snt.js

Note: Snitcher requires a valid ID from your Snitcher account. Add it to your .env.local file and Vercel environment variables.

Features

  • Session recording and playback
  • Visitor identification and lead tracking
  • Heatmaps and user behavior analytics
  • Conversion tracking and funnel analysis

Biome (Linter & Formatter)

Overview

Biome is used as the linter and formatter for this project. It provides fast, zero-config linting and formatting for JavaScript, TypeScript, and JSON files.

Configuration

biome.json

Version: @biomejs/biome@2.3.7

Available Commands

npm run lintCheck for linting errors
npm run lint:fixFix linting errors automatically
npm run formatFormat all files
npm run format:checkCheck formatting without making changes
npm run checkRun all checks (lint + format)

Key Settings

  • Indent: 2 spaces
  • Line Width: 100 characters
  • Quote Style: Single quotes for JS, double for JSX
  • Semicolons: Always required

Zod (Schema Validation)

Overview

Zod is used for TypeScript-first schema validation. It's integrated with React Hook Form for form validation and API route validation.

Configuration

src/lib/validations.ts

Version: zod@^4.1.13

Integration: @hookform/resolvers

Example Schema

import { z } from 'zod';

export const contactFormSchema = z.object({
  company: z.string().optional(),
  phone: z
    .string()
    .min(1, 'Phone number is required')
    .regex(/^[\d\s\-\+\(\)]+$/, 'Please enter a valid phone number'),
  email: z
    .string()
    .min(1, 'Email is required')
    .email('Please enter a valid email address'),
  message: z
    .string()
    .min(1, 'Message is required')
    .min(10, 'Message must be at least 10 characters')
    .max(2000, 'Message must be less than 2000 characters'),
});

export type ContactFormData = z.infer<typeof contactFormSchema>;

Usage with React Hook Form

import { useForm } from 'react-hook-form';
import { zodResolver } from '@hookform/resolvers/zod';
import { contactFormSchema, type ContactFormData } from '@/lib/validations';

const {
  register,
  handleSubmit,
  formState: { errors },
} = useForm<ContactFormData>({
  resolver: zodResolver(contactFormSchema),
});

Usage in API Routes

import { contactFormSchema } from '@/lib/validations';

export async function POST(request: NextRequest) {
  const body = await request.json();
  
  // Validate with Zod schema
  const validationResult = contactFormSchema.safeParse(body);
  
  if (!validationResult.success) {
    return NextResponse.json(
      { error: 'Validation failed', details: validationResult.error.issues },
      { status: 400 }
    );
  }
  
  const { company, phone, email, message } = validationResult.data;
  // ... rest of the handler
}

Where It's Used

  • ContactSection - Contact form validation
  • ResumeSearchSection - Resume search form validation
  • /api/contact - API route validation

Article Style Guide

Article H2 Heading

Format: ## Heading

Font: IBM Plex Sans Thai

Weight: 700 (Bold)

Size: 24px (md: 30px)

Line Height: 1.2

Spacing: mt-10 mb-6

Used for: Main section headings in case study articles

How it started?

Article H3 Heading

Format: ### Heading

Font: IBM Plex Sans Thai

Weight: 700 (Bold)

Size: 20px (md: 24px)

Line Height: 1.2

Spacing: mt-8 mb-4

Used for: Subsection headings within article sections

Challenges as New Opportunities

Article Paragraphs

Font: System default

Weight: 400 (Regular)

Size: 16px (md: 18px)

Line Height: 1.6 (relaxed)

Spacing: mb-6 (mb-3 if followed by bullets)

Bold Text: Use **text** for important terms

Used for: Body text, paragraphs in case study articles

Meet Seven Peaks – not just your ordinary software development company, but a thriving hub of innovation and diversity. With a dynamic team of over 200 professionals hailing from 25 countries, Seven Peaks stands out as a beacon of digital transformation excellence in Thailand and beyond.

Article Bullet Points

Format: Start with

Font: System default

Weight: 400 (Regular)

Size: 16px (md: 18px)

Line Height: 1.6 (relaxed)

Spacing: mb-3 (first), mb-4 (subsequent)

Indent: ml-4

Used for: Lists and key points in case study articles

Embracing a diverse workforce brings forth the need for a deeper understanding of various cultures and age groups within the organization.

The company faced the struggle of attracting qualified IT candidates in a competitive market.

Article Quotes

Format: "Quote" + — Attribution

Background: bg-brand-gray

Border: border-l-4 border-brand-blue

Padding: p-6 (md: p-8)

Spacing: my-8

Quote Size: text-lg (md: text-xl)

Quote Style: italic, font-medium

Used for: Executive quotes and testimonials in case studies

“It's not enough to be only an employer, it's important to be able to provide a workplace where our team feel belonging and respect while still providing a career path for developing further growth.”

Jostein Aksnes, CEO

Article Images

Aspect Ratio: 16:9 (aspect-video)

Object Fit: cover

Corners: No rounded corners

Spacing: mb-8 mt-4

Width: 100% (responsive)

Min Height: 200px

Used for: Case study images, always cropped to 16:9 ratio

16:9 Aspect Ratio Image

Article YouTube Videos

Format: Full YouTube URL

Aspect Ratio: 16:9 (aspect-video)

Spacing: mb-8 mt-6

Width: 100% (responsive)

Auto-detect: Supports youtu.be, youtube.com/watch, youtube.com/embed

Used for: Video embeds in case study articles

YouTube Video Embed