Available Hooks & Context
Gymlium provides React hooks that give your template components access to platform data, authentication state, and utility functions. These hooks are the primary way your template interacts with the platform — you never need to fetch data directly.
useApp()
The main hook for accessing application-level data and utilities. Available in every component.
import { useApp } from '@/hooks/useApp'
export default function HomeContent() {
const {
locale,
isRtl,
t,
localePath,
clientName,
locales,
plan,
planLimits,
stats,
registrationOpen,
} = useApp()
return (
<main>
<h1>{t('welcomeTo')} {clientName}</h1>
</main>
)
}Return values
| Property | Type | Description |
|---|---|---|
locale | string | Current active locale code (e.g. "en", "ar", "fr") |
isRtl | boolean | true when the current locale is a right-to-left language (Arabic, Persian) |
t | (key: string) => string | Translation function — returns the translated string for the given key |
localePath | (path: string) => string | Prefixes a path with the current locale (e.g. localePath('/about') → "/en/about") |
clientName | string | The trainer’s business name as configured in their dashboard |
locales | string[] | Array of locale codes enabled for this trainer’s site |
plan | string | The trainer’s subscription plan (e.g. "starter", "professional", "elite") |
planLimits | PlanLimits | Feature limits based on the trainer’s plan (see below) |
stats | SiteStats | Site-level statistics (see below) |
registrationOpen | boolean | Whether client registration is currently enabled |
PlanLimits object
interface PlanLimits {
maxPages: number // Maximum number of enabled pages
maxBlogPosts: number // Maximum blog posts (-1 = unlimited)
maxClients: number // Maximum registered clients
hasScheduling: boolean // Whether scheduling feature is available
hasEvents: boolean // Whether events feature is available
hasBlog: boolean // Whether blog feature is available
}Use planLimits to conditionally show or hide sections. For example, don’t render a “Blog” nav link if planLimits.hasBlog is false:
const { planLimits, localePath, t } = useApp()
return (
<nav>
<a href={localePath('/')}>{t('home')}</a>
<a href={localePath('/about')}>{t('about')}</a>
{planLimits.hasBlog && (
<a href={localePath('/blog')}>{t('blog')}</a>
)}
{planLimits.hasScheduling && (
<a href={localePath('/schedule')}>{t('schedule')}</a>
)}
</nav>
)SiteStats object
interface SiteStats {
postCount: number // Number of published blog posts
serviceCount: number // Number of active services
testimonialCount: number // Number of approved testimonials
eventCount: number // Number of upcoming events
transformationCount: number // Number of transformation entries
}Use stats to decide whether to render empty-state messages or hide sections entirely:
const { stats, t } = useApp()
{stats.testimonialCount > 0 ? (
<TestimonialCarousel />
) : (
<p>{t('noTestimonialsYet')}</p>
)}useAuth()
Provides the current authentication state. Use this to show login/logout controls, protect pages, and display user-specific content.
import { useAuth } from '@/hooks/useAuth'
export function Header() {
const { user, loading, isAdmin, signOut } = useAuth()
if (loading) return null
return (
<div>
{user ? (
<>
<span>{user.displayName}</span>
{isAdmin && <a href="/dashboard">Dashboard</a>}
<button onClick={signOut}>Sign out</button>
</>
) : (
<a href="/login">Sign in</a>
)}
</div>
)
}Return values
| Property | Type | Description |
|---|---|---|
user | User | null | Current user object, or null if not authenticated |
loading | boolean | true while auth state is being resolved |
isAdmin | boolean | true if the current user is the trainer (site owner) |
signOut | () => Promise<void> | Signs the user out and redirects to the home page |
User object
interface User {
id: string
email: string
displayName: string
photoURL: string | null
role: 'admin' | 'client'
}Always check loading before making assumptions about user. During initial page load, user is null and loading is true — this doesn’t mean the visitor is unauthenticated.
useRouter()
The standard Next.js router hook from next/navigation. Use it for programmatic navigation.
import { useRouter } from 'next/navigation'
import { useApp } from '@/hooks/useApp'
export default function LoginContent() {
const router = useRouter()
const { localePath } = useApp()
function handleLoginSuccess() {
router.push(localePath('/account'))
}
return <div>{/* login form */}</div>
}Always wrap paths with localePath() when using router.push() or router.replace() to ensure locale-aware navigation.
Hook usage rules
- Hooks can only be called inside React components or other hooks — standard React rules apply
useApp()anduseAuth()are available everywhere — the platform wraps your template in the necessary context providers- Don’t destructure more than you need — for performance, only pull the values your component actually uses
t()always returns a string — if the key doesn’t exist, it returns the key itself as a fallbacklocalePath()handles the root path —localePath('/')correctly returns"/en"(not"/en/")