Référence des types
Les types TypeScript que les auteurs de thèmes + de plugins utilisent le plus souvent, avec les définitions canoniques et ce qui est réellement dans chaque champ.
Les types TypeScript que les auteurs de thèmes + de plugins utilisent le plus souvent, avec les définitions canoniques et ce qui est réellement dans chaque champ.
Pour la liste exhaustive, voir la source : src/core/types.ts (types côté admin) et src/themes/types.ts (types côté thème).
Types de contenu
Post
Le même type couvre les posts (type: "post") et les pages (type: "page").
interface Post {
id: string;
type: "post" | "page";
title: string;
slug: string;
contentMarkdown: string;
excerpt?: string;
heroMediaId?: string; // id du doc Media ; résoudre via `media.get(heroMediaId)`
authorId: string; // uid User
primaryTermId?: string; // catégorie principale (id de Term)
termIds: string[]; // tous les termes (catégories + tags)
status: "draft" | "online";
publishedAt?: Timestamp;
createdAt: Timestamp;
updatedAt: Timestamp;
lastPublishedPath?: string; // chemin actuel sur Flexweg
lastPublishedHash?: string; // hash sha256 du HTML actuel
previousPublishedPaths?: string[]; // chemins dont la suppression a échoué
lastPublishedPathsByLocale?: Record<string, string>; // multilang
seo?: SeoMeta;
translations?: Record<string, unknown>; // données opaques de plugin (multilang)
}
Timestamp est firebase.firestore.Timestamp en mode Firebase, un objet équivalent (toMillis(), toDate()) en mode SQLite.
Term
Catégorie ou tag.
interface Term {
id: string;
type: "category" | "tag";
name: string;
slug: string;
description?: string;
parentId?: string; // catégories peuvent avoir un parent
seo?: SeoMeta;
translations?: Record<string, unknown>;
}
SeoMeta
interface SeoMeta {
title?: string;
description?: string;
ogImage?: string;
}
Sur un post : fallback vers title / excerpt / heroMedia. Sur un terme : fallback vers name / description.
Media
interface Media {
id: string;
fileName: string;
alt?: string;
caption?: string;
formats?: Record<string, MediaFormat>; // pipeline multi-variantes
defaultFormat?: string; // ex. "medium"
url?: string; // legacy single-URL (ancienne version)
size?: number;
contentType?: string;
uploadedBy?: string;
createdAt: Timestamp;
}
interface MediaFormat {
url: string;
width: number;
height: number;
bytes?: number;
format: string; // "webp", "svg", etc.
}
SiteSettings
interface SiteSettings {
title: string;
description: string;
language: string; // BCP-47
baseUrl: string; // URL absolue du site
activeThemeId: string;
homeMode: "latest" | "static-page";
homePageId?: string;
paginationMode: "global" | "paginated";
enabledPlugins: string[];
menus: { header: MenuItem[]; footer: MenuItem[] };
themeConfigs?: Record<string, unknown>;
pluginConfigs?: Record<string, unknown>;
}
User
interface User {
uid: string; // Firebase Auth uid OU SQLite users.id
email: string;
firstName?: string;
lastName?: string;
bio?: string;
avatarMediaId?: string;
role: "admin" | "editor";
preferences?: { adminLocale?: string };
createdAt: Timestamp;
}
Types côté publication
PublishContext
Le contexte passé à chaque étape du pipeline de publication.
interface PublishContext {
settings: SiteSettings;
posts: Post[]; // tous les posts
pages: Post[]; // toutes les pages
terms: Term[]; // catégories + tags
media: Map<string, Media>;
}
SiteContext
Le contexte passé au template du thème pour le rendu.
interface SiteContext {
settings: SiteSettings;
resolvedMenus: { header: ResolvedMenuItem[]; footer: ResolvedMenuItem[] };
themeCssPath: string; // ex. "theme-assets/default.css"
themeConfig?: unknown; // la config résolue du thème
homePath?: string; // pour le lien du logo (utile en multilang)
}
BaseLayoutProps
Les props du BaseLayout du thème.
interface BaseLayoutProps {
site: SiteContext;
pageTitle: string;
pageDescription?: string;
ogImage?: string;
currentPath: string; // chemin de la page courante
currentLocale?: string; // langue courante (pour multilang)
children: React.ReactNode;
}
Types de manifest
PluginManifest
interface PluginManifest<TConfig = unknown> {
id: string;
name: string;
version: string;
description?: string;
author?: string;
readme?: string;
register: (api: typeof pluginApi) => void;
settings?: {
navLabelKey: string;
defaultConfig: TConfig;
component: React.ComponentType<PluginSettingsPageProps<TConfig>>;
};
i18n?: Record<string, Record<string, unknown>>;
}
ThemeManifest
interface ThemeManifest<TConfig = unknown> {
id: string;
name: string;
version: string;
description?: string;
scssEntry?: string;
cssText: string;
compileCss?: (config: TConfig) => string;
templates: {
base: React.ComponentType<BaseLayoutProps>;
home: React.ComponentType<unknown>;
single: React.ComponentType<unknown>;
category: React.ComponentType<unknown>;
author: React.ComponentType<unknown>;
notFound: React.ComponentType<unknown>;
};
formats?: ImageFormat[]; // pipeline d'images
blocks?: BlockManifest[];
settings?: {
navLabelKey: string;
defaultConfig: TConfig;
component: React.ComponentType<unknown>;
};
i18n?: Record<string, Record<string, unknown>>;
}
BlockManifest
interface BlockManifest {
id: string; // "<namespace>/<name>"
titleKey: string;
namespace?: string;
icon: React.ComponentType;
category: "text" | "media" | "layout" | "embed" | "advanced";
insert: (chain: Chain, ctx: { pickMedia: () => Promise<Media | null> }) => void;
extensions?: Tiptap.Extension[];
isActive?: (editor: Tiptap.Editor) => boolean;
inspector?: React.ComponentType<{ attrs, updateAttrs, editor }>;
}
Types de hook
NewsLocaleEntry (sitemap.news.locales)
interface NewsLocaleEntry {
language: string;
path: string;
entities: SitemapEntity[];
}
RssLocaleEntry (rss.site.locales)
interface RssLocaleEntry {
language: string;
path: string;
channelTitle: string;
channelLink: string;
channelDescription: string;
items: RssItem[];
}
RssItem
interface RssItem {
title: string;
link: string;
guid: string;
description: string;
pubDateMs: number;
category?: string;
enclosure?: { url: string; length: number; type: string };
}
AdditionalRender (publish.additional)
interface AdditionalRender {
path: string;
html: string;
}
AdditionalListingRender (publish.extraListings)
Idem AdditionalRender.
MenuJson
Le format de /menu.json uploadé à la racine du site.
interface MenuJson {
header: ResolvedMenuItem[];
footer: ResolvedMenuItem[];
branding?: {
siteTitle: string;
logoUrl?: string;
};
}
interface ResolvedMenuItem {
id: string;
label: string;
href: string;
children?: ResolvedMenuItem[];
translations?: Record<string, { label: string }>;
}
Types côté thème
MediaView
Le shape Media consommable par les composants de thème — résolu par le publisher avant le rendu.
interface MediaView {
alt: string;
caption?: string;
default: string; // URL de la variante par défaut
formats: Record<string, MediaFormatView>;
}
interface MediaFormatView {
url: string;
width: number;
height: number;
}
AuthorView
interface AuthorView {
uid: string;
displayName: string; // "Prénom Nom"
bio?: string;
avatarUrl?: string;
}
ResolvedMenuItem
Voir MenuJson ci-dessus.
SingleTemplateProps
interface SingleTemplateProps {
site: SiteContext;
post: CardPost; // forme enrichie de Post avec URL, hero, category
bodyHtml: string; // HTML rendu du markdown du post
author?: AuthorView;
relatedPosts?: CardPost[]; // si le thème en surface
}
CategoryTemplateProps
interface CategoryTemplateProps {
site: SiteContext;
term: Term;
posts: CardPost[]; // posts dans cette catégorie
archivesLink?: string;
popularTags?: Term[];
}