Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { chipClass } from "@scibly/ui/design-language";
import { cn } from "@scibly/ui/utils";
import { ArrowDown, Github } from "lucide-react";

import { PILLARS, tint } from "@/app/[lang]/components/marketing-tokens";

import { type HeroDictionary } from "./i18n/hero.types";

export function HeroOpenSourceChip({ t }: { t: HeroDictionary["openSource"] }) {
return (
<a
href="#open-source"
className={cn(
chipClass,
// Custom properties, not an inline `boxShadow`: that would outrank the press state's `shadow-none`.
"group inline-flex items-center gap-2 border-(--os-edge) bg-(--os-face) text-(--os-ink) no-underline shadow-[0_3px_0_0_var(--os-lip)] hover:bg-(--os-face-hover)",
)}
style={{
"--os-face": tint(PILLARS.learner.softColor, 26),
"--os-face-hover": tint(PILLARS.learner.softColor, 44),
"--os-edge": tint(PILLARS.learner.softColor, 82),
"--os-lip": tint(PILLARS.learner.lipColor, 58),
"--os-ink": PILLARS.learner.accentColor,
}}
>
<Github size={14} strokeWidth={2} aria-hidden />
{t.label}
<span className="h-3.5 w-px bg-current opacity-25" aria-hidden />
<span className="font-mono text-[11.5px] tracking-[0.01em]">
{t.license}
</span>
<ArrowDown
size={13}
className="opacity-55 transition-transform group-hover:translate-y-0.5"
aria-hidden
/>
</a>
);
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type ReactNode } from "react";

import { HeroGlassFrame } from "./hero-glass-frame";
import { HeroOpenSourceChip } from "./hero-open-source-chip";
import { type HeroDictionary } from "./i18n/hero.types";

interface HeroProps {
Expand Down Expand Up @@ -34,6 +35,10 @@ export function Hero({ t, children }: HeroProps) {
<div
className={`relative z-[2] flex min-h-0 flex-1 flex-col items-center justify-center px-5 pt-24 pb-9 text-center md:absolute md:px-[clamp(40px,6vw,96px)] md:py-[clamp(24px,4vh,60px)] ${CONTENT_INSET}`}
>
<div className="mb-[clamp(16px,2.6vh,26px)]">
<HeroOpenSourceChip t={t.openSource} />
</div>

{/* Measured in characters so the line length holds at every size. German
compounds need the wider measure to keep the headline off a fourth
line; phones stay tighter so it never runs edge to edge. */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
"titleHighlight": "moderne",
"titleSuffix": " Teams",
"subtitle": "Wir verwandeln vorhandenes Unternehmenswissen in interaktive Kurse.",
"openSource": {
"label": "Scibly ist Open Source",
"license": "AGPLv3"
},
"complianceBadges": [
{
"kind": "euServer",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@
"titleHighlight": "modern",
"titleSuffix": " teams",
"subtitle": "We turn your existing company knowledge into interactive courses.",
"openSource": {
"label": "Scibly is open source",
"license": "AGPLv3"
},
"complianceBadges": [
{
"kind": "euServer",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ export type HeroDictionary = {
titleHighlight: string;
titleSuffix: string;
subtitle: string;
openSource: {
label: string;
license: string;
};
complianceBadges: Array<{
kind: string;
label: string;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"openSource": {
"eyebrow": "Open Source",
"title": "Offener Code. Deine Wahl. Deine Kontrolle.",
"subtitle": "Der Code von Scibly ist Open Source auf GitHub. Klone das Repository, starte den Stack und sieh selbst, wie Scibly funktioniert.",
"actions": {
"repo": "Code auf GitHub ansehen",
"selfHost": "Selbst hosten"
},
"licenseLabel": "AGPLv3",
"terminal": {
"transcriptLabel": "Terminal-Ausgabe",
"stepsLabel": "Terminal-Schritte"
},
"steps": [
{
"kind": "clone",
"label": "Repository klonen",
"caption": "Der komplette Code. Kein abgespecktes Template.",
"note": "AGPLv3. Forke es und liefere deinen eigenen Build aus."
},
{
"kind": "boot",
"label": "Stack starten",
"caption": "Ein Befehl. Datenbank und Apps laufen.",
"note": "Ein Befehl, und der komplette Stack l盲uft auf deiner eigenen Infrastruktur."
},
{
"kind": "issue",
"label": "Bringe deine Ideen ein",
"caption": "Bugs melden, Ideen teilen und neue Features vorschlagen.",
"note": "Landet im selben Tracker, aus dem wir planen."
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"openSource": {
"eyebrow": "Open source",
"title": "Open code. Your choice. Your control.",
"subtitle": "Scibly's code is open source on GitHub. Clone the repository, start the stack, and see for yourself how Scibly works.",
"actions": {
"repo": "View the code on GitHub",
"selfHost": "Host it yourself"
},
"licenseLabel": "AGPLv3",
"terminal": {
"transcriptLabel": "Terminal transcript",
"stepsLabel": "Terminal steps"
},
"steps": [
{
"kind": "clone",
"label": "Clone the repository",
"caption": "The complete code. Not a stripped-down template.",
"note": "AGPLv3. Fork it and ship your own build."
},
{
"kind": "boot",
"label": "Start the stack",
"caption": "One command. Database and apps running.",
"note": "One command, and the whole stack runs on your own infrastructure."
},
{
"kind": "issue",
"label": "Contribute your ideas",
"caption": "Report bugs, share ideas, suggest new features.",
"note": "Lands in the same tracker we plan from."
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
type OpenSourceStep = {
kind: string;
label: string;
caption: string;
note: string;
};

export type OpenSourceDictionary = {
eyebrow: string;
title: string;
subtitle: string;
actions: {
repo: string;
selfHost: string;
};
licenseLabel: string;
terminal: {
transcriptLabel: string;
stepsLabel: string;
};
steps: OpenSourceStep[];
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { Braces, Container, GitFork, Terminal } from "lucide-react";

import {
type AtmosphereTile,
MarketingAtmosphere,
} from "@/app/[lang]/components/marketing-grid-field";
import { PILLARS } from "@/app/[lang]/components/marketing-tokens";

const tiles: AtmosphereTile[] = [
{
id: "terminal",
className: "top-[16%] left-[3.5%] hidden xl:flex",
icon: <Terminal size={24} strokeWidth={1.8} />,
tone: PILLARS.import,
},
{
id: "fork",
className: "top-[24%] right-[4%] hidden xl:flex",
icon: <GitFork size={24} strokeWidth={1.8} />,
tone: PILLARS.byoai,
},
{
id: "container",
className: "bottom-[18%] left-[5%] hidden 2xl:flex",
icon: <Container size={23} strokeWidth={1.8} />,
tone: PILLARS.channels,
},
{
id: "braces",
className: "right-[3.5%] bottom-[15%] hidden 2xl:flex",
icon: <Braces size={23} strokeWidth={1.8} />,
tone: PILLARS.learner,
},
];

const indents = [
"top-[54%] left-[4%] hidden xl:block",
"top-[62%] right-[5%] hidden xl:block",
];

export function OpenSourceAtmosphere() {
return <MarketingAtmosphere tiles={tiles} indents={indents} />;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
import { routes } from "@scibly/routes";
import { CircleDot, Container, type LucideIcon, Terminal } from "lucide-react";

import { type Pillar, PILLARS } from "@/app/[lang]/components/marketing-tokens";

/* The transcript stays untranslated: `docker compose up` prints English in every locale. */
export const MONO_FONT = 'ui-monospace, "SFMono-Regular", Menlo, monospace';

const SELF_HOST_STEP_IDS = ["clone", "boot", "issue"] as const;

type SelfHostStepId = (typeof SELF_HOST_STEP_IDS)[number];

export const toSelfHostStepId = (id: string): SelfHostStepId | undefined =>
SELF_HOST_STEP_IDS.find((known) => known === id);

type TerminalLineTone = "log" | "ok" | "port";

export type TerminalLine = {
tone: TerminalLineTone;
text: string;
value?: string;
};

type SelfHostStep = {
pillar: Pillar;
icon: LucideIcon;
command: string;
lines: readonly TerminalLine[];
};

export const SELF_HOST_STEPS = {
clone: {
pillar: PILLARS.import,
icon: Terminal,
command: "git clone https://github.com/scibly-dev/scibly",
lines: [
{ tone: "log", text: "Cloning into 'scibly'..." },
{ tone: "log", text: "remote: Counting objects: 100%, done." },
{ tone: "ok", text: "apps/ packages/ ee/ docs/" },
],
},
boot: {
pillar: PILLARS.channels,
icon: Container,
command: "docker compose up -d --build",
lines: [
{ tone: "ok", text: "Container scibly-postgres-1 Started" },
{ tone: "port", text: "web", value: "http://localhost:3000" },
{ tone: "port", text: "app", value: "http://localhost:3001" },
{ tone: "port", text: "collab", value: "ws://localhost:4000" },
],
},
issue: {
pillar: PILLARS.analytics,
icon: CircleDot,
command: "gh issue create --repo scibly-dev/scibly",
lines: [
{ tone: "log", text: "Creating issue in scibly-dev/scibly" },
{ tone: "log", text: "? Title SCORM export for course packages" },
{ tone: "ok", text: "? What's next? Submit" },
],
},
} satisfies Record<SelfHostStepId, SelfHostStep>;

export function transcriptOf(step: SelfHostStep): string {
return step.lines
.map((line) => [line.text, line.value].filter(Boolean).join(" "))
.join(" 路 ");
}

export const SELF_HOSTING_GUIDE_HREF =
routes.external.github.file("docs/docker.md");
Loading
Loading