Package Exports
- @startnext/chrome
- @startnext/chrome/render
Readme
@startnext/chrome
Startnext Header/Footer Web Components
Wiederverwendbare Header- und Footer-Components für alle Startnext Microservices.
Installation
npm install @startnext/chrome
# or
pnpm add @startnext/chromeQuick Start
Modern JavaScript (React, Vue, etc.)
import '@startnext/chrome';<startnext-header></startnext-header>
<startnext-footer></startnext-footer>Via CDN (PHP, Vanilla HTML)
<script type="module" src="https://unpkg.com/@startnext/chrome@latest/dist/index.js"></script>
<startnext-header></startnext-header>
<startnext-footer></startnext-footer>API
<startnext-header>
Attributes:
| Attribute | Type | Default | Description |
|---|---|---|---|
lang |
string |
'de' |
Sprache ('de', 'en') |
light |
boolean |
false |
Heller Header (weiße Schrift/Icons über dunklem Hero, wechselt automatisch zu dunkel beim Scrollen). Standard ohne Attribut: dunkler Header |
large-animation |
boolean |
false |
Große Lottie-Logo-Animation mit Claim und horizontaler Navigation |
authenticated |
boolean |
false |
Zeigt User-Avatar statt "Anmelden" Button |
user-name |
string |
- | Name des eingeloggten Users |
user-avatar |
string |
- | Avatar-URL des Users |
color-mode |
'light' | 'dark' |
auto | Farbmodus. Ohne Attribut: Header scannt <html> nach Klasse dark/light. Ohne Klasse: Default dark (dunkle Seite, heller Header). Toggle-Button wechselt <html>-Klasse und Header-Darstellung |
hide-color-mode |
boolean |
false |
Versteckt den Color-Mode Toggle-Button |
hide-lang |
boolean |
false |
Versteckt den Language-Switcher |
hide-login |
boolean |
false |
Versteckt den Login/Avatar-Button |
show-back-link |
boolean |
false |
Zeigt einen "Zurueck zu Startnext"-Link (Text kommt von der API) |
back-url |
string |
- | Ueberschreibt die Back-Link-URL |
back-label |
string |
- | Ueberschreibt den Back-Link-Text |
api-url |
string |
- | API-Endpoint-URL fuer Live-Daten aus Notion |
Events:
| Event | Detail | Description |
|---|---|---|
burger-menu-toggle |
{ open: boolean } |
Burger-Menü geöffnet/geschlossen |
user-menu-toggle |
{ open: boolean } |
User-Menü geöffnet/geschlossen |
navigation-click |
{ item: NavigationItem } |
Navigation-Link geklickt |
cta-click |
{ url: string } |
"Projekt starten" Button geklickt |
logout |
{} |
Abmelden geklickt |
language-change |
{ language: string } |
Sprache gewechselt |
scroll-state-change |
{ scrolled: boolean, slideUp: boolean } |
Scroll-Zustand geändert |
color-mode-change |
{ mode: 'light' | 'dark' } |
Farbmodus gewechselt (per Toggle-Button) |
Usage Examples:
<!-- Default: dunkler Header (dunkle Schrift für helle Seiten) -->
<startnext-header></startnext-header>
<!-- Heller Header (weiße Schrift über dunklem Hero) -->
<startnext-header light></startnext-header>
<!-- Heller Header + große Animation (z.B. Startseite) -->
<startnext-header light large-animation></startnext-header>
<!-- Heller Header + groß + eingeloggt -->
<startnext-header
light
large-animation
authenticated
user-name="Elias Groesel"
user-avatar="https://..."
></startnext-header><!-- Color Mode: Header scannt <html> automatisch -->
<!-- html.dark → heller Header, html.light → dunkler Header -->
<!-- Toggle-Button (Sun/Moon) im Header wechselt den Modus -->
<html class="dark">
<startnext-header light large-animation></startnext-header>
</html><!-- Embedded / Microservice-Modus: Login ausblenden, Back-Link anzeigen -->
<startnext-header
hide-login
show-back-link
back-url="https://www.startnext.com"
back-label="Zurueck zu Startnext"
api-url="https://scs-api.vercel.app"
></startnext-header>const header = document.querySelector('startnext-header');
header.addEventListener('navigation-click', (e) => {
console.log(e.detail.item);
// e.preventDefault() to handle navigation yourself
});
header.addEventListener('language-change', (e) => {
// Footer synchronisiert Sprache automatisch (lang-sync ist default true).
// Manuelle Synchronisation nur noetig wenn lang-sync="false" gesetzt ist:
// document.querySelector('startnext-footer').setAttribute('lang', e.detail.language);
});
header.addEventListener('logout', () => {
// Handle logout
});
header.addEventListener('color-mode-change', (e) => {
console.log(`Color mode: ${e.detail.mode}`); // 'light' | 'dark'
// <html>-Klasse wird automatisch vom Header gesetzt
});<startnext-footer>
Attributes:
| Attribute | Type | Default | Description |
|---|---|---|---|
lang |
string |
'de' |
Sprache ('de', 'en') |
api-url |
string |
- | API-Endpoint-URL fuer Live-Daten |
lang-sync |
boolean |
true |
Synchronisiert Sprache automatisch wenn der Header ein language-change Event emittiert. Mit lang-sync="false" deaktivieren |
Events:
| Event | Detail | Description |
|---|---|---|
navigation-click |
{ item: { url, label } } |
Footer-Link geklickt |
Theming
Override CSS Custom Properties:
startnext-header {
--primary-color: #0066FF;
--btn-primary-bg: #0066FF;
--header-bg-scrolled: #FAFAFA;
}
startnext-footer {
--footer-bg: #111111;
--footer-link-hover: #0066FF;
}Fonts
Standardmäßig nutzen die Components System-Fonts als Fallback. Für eigene Schriftarten @font-face im eigenen CSS deklarieren und --font-family setzen:
@font-face {
font-family: "PFDin";
font-weight: 400;
font-style: normal;
font-display: swap;
src: url("/fonts/PFDin-subset.woff2") format("woff2");
}
startnext-header, startnext-footer {
--font-family: "PFDin", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
}Server-Side Rendering (SSR)
Das Paket exportiert einen server-sicheren Subpath @startnext/chrome/render mit reinen String-Funktionen (keine Browser-Abhaengigkeiten). Damit kann der API-Server fertig gerendertes HTML per Declarative Shadow DOM erzeugen.
Render Entry Point
import {
renderHeader, renderBurgerItems, renderUserItems,
renderFooter,
headerCSS, footerCSS,
renderHeaderCrawlerNav, renderFooterCrawlerNav,
toHeaderRenderData, toFooterRenderData,
getUiString, getIcon,
} from '@startnext/chrome/render';Exports
| Export | Beschreibung |
|---|---|
renderHeader(props) |
Header Shadow DOM HTML |
renderBurgerItems(data, expandedSections) |
Burger-Menue Items HTML |
renderUserItems(data, expandedSections) |
User-Menue Items HTML |
renderFooter(data) |
Footer Shadow DOM HTML |
headerCSS, footerCSS, resetCSS |
CSS als Strings |
getIcon(name, size?) |
SVG-Icon als String |
getUiString(key, lang) |
UI-String (ARIA Labels etc.) |
toHeaderRenderData(apiData) |
API-Daten → HeaderData (fuegt stub theme hinzu) |
toFooterRenderData(apiData) |
API-Daten → FooterData (fuegt stub theme hinzu) |
renderHeaderCrawlerNav(data) |
Crawler-<nav> fuer Header (Light DOM, SEO) |
renderFooterCrawlerNav(data) |
Crawler-<nav> fuer Footer (Light DOM, SEO) |
Hydration
Wenn der Server HTML mit Declarative Shadow DOM (<template shadowrootmode="open">) liefert, erkennt die Web Component den bestehenden shadowRoot und hydriert statt neu zu rendern:
- Browser parst DSD →
shadowRootexistiert vor dem Custom-Element-Constructor BaseComponenterkennt bestehendenshadowRoot, setztisHydrating = truerender()ueberspringtinnerHTML, ruft nurattachEvents()aufconnectedCallback()erkennt bestehenden[data-crawler-nav], ueberspringtrenderLightDomNav()loadApiData()holt frische Daten → loest danach ein vollstaendiges Re-Render aus
<!-- Server liefert fertiges HTML -->
<startnext-header lang="de" light large-animation>
<template shadowrootmode="open">
<style>/* headerCSS */</style>
<div><!-- Shadow DOM HTML --></div>
</template>
<nav data-crawler-nav aria-hidden="true" style="display:none">
<!-- SEO-Links -->
</nav>
</startnext-header>
<!-- JS hydriert automatisch -->
<script type="module" src="@startnext/chrome"></script>Browser Support
- Chrome/Edge 90+ (Declarative Shadow DOM: Chrome 90+, Firefox 123+, Safari 16.4+)
- Firefox 88+ (123+ fuer SSR/Hydration)
- Safari 14+ (16.4+ fuer SSR/Hydration)
Development
# Install deps (from monorepo root)
pnpm install
# Dev mode (watch)
pnpm --filter @startnext/chrome dev
# Build
pnpm --filter @startnext/chrome build
# Lint
pnpm --filter @startnext/chrome lintDemo-Seite oeffnen: demo/index.html
Architecture
Jede Component ist modular in drei Dateien aufgeteilt:
src/
├── components/
│ ├── base/
│ │ ├── BaseComponent.ts # Abstrakte Basis (Shadow DOM, DSD-Hydration, Events, Theming)
│ │ ├── icons.ts # SVG-Icon-Registry
│ │ └── styles.ts # Shared Reset-CSS
│ ├── header/
│ │ ├── StartnextHeader.ts # Logik (Scroll, Drawers, Lottie, Events, Hydration)
│ │ ├── header.css.ts # CSS als Template-Literal-Export
│ │ └── header.template.ts # Render-Funktionen (HTML-Strings)
│ └── footer/
│ ├── StartnextFooter.ts # Logik (Render, Events, Hydration)
│ ├── footer.css.ts # CSS als Template-Literal-Export
│ └── footer.template.ts # Render-Funktion (HTML-String)
├── data/
│ ├── mockData.ts # Mock-Daten
│ └── uiStrings.ts # UI-Strings (ARIA Labels, de/en)
├── types/
│ └── index.ts # Alle TypeScript-Interfaces
├── index.ts # Browser-Entry (Custom Elements registrieren)
└── render.ts # Server-Entry (reine String-Funktionen, kein Browser)Konventionen:
- CSS in
*.css.tsals exportierter Template-Literal-String (kein extra Build-Plugin noetig) - Templates in
*.template.tsals reine Funktionen die HTML-Strings zurueckgeben (server-safe) - Logik in der Hauptdatei: Event-Handling, State, Lifecycle, Hydration
- BEM-Naming fuer CSS-Klassen (
headbar__left,drawer__item--highlighted) - Shadow DOM (open mode), kein Virtual DOM, Declarative Shadow DOM fuer SSR
Zwei Entry Points:
src/index.ts→dist/index.js(ESM) +dist/index.umd.js(UMD) — Browser, registriert Custom Elementssrc/render.ts→dist/render.js(ESM) — Server, reine String-Funktionen ohne Browser-Abhaengigkeiten
Monorepo Structure
packages/
scs-web-component/ ← dieses Paket
scs-api/ ← Express API Service (nutzt @startnext/chrome/render fuer SSR)