feat: HLS streaming, transcripts, agent course generation & landing-page course previews (#663)
New features: - HLS video encoding/streaming (hls routes, hls-encoder) and a media transcripts pipeline (transcripts route + media-transcript queries) - AI assistant chat vs. run model: agent-course-generation worker/queue, run-monitor pane, chat-changes card, content ask-ai bar - Per-theme course-page previews across org landing-page themes (bold, classic, corporate, editorial, etc.) with a shared course token/component set - View-as-student mode and login-link / link-invite invite flows Refactor: - Extract packages/core consolidating config (env, storage, dashboard-url), services and utils previously duplicated under apps/api/src/config - Remove legacy agent service modules (chat-tools, chat-context, context-window, document, fetch-url, lesson-content) - Relax Cross-Origin-Resource-Policy to allow cross-origin media embedding - Add format script to tenant-router so turbo run format covers it
This commit is contained in:
@@ -23,10 +23,10 @@
|
||||
];
|
||||
|
||||
const agents = [
|
||||
{ name: 'Cursor', logo: '/cursor-logo.png' },
|
||||
{ name: 'Claude Code', logo: '/claude-logo.svg' },
|
||||
{ name: 'Codex', logo: '/codex-logo.png' },
|
||||
{ name: 'OpenCode', logo: '/opencode-logo.svg' }
|
||||
{ name: 'Cursor', logo: 'https://assets.cdn.clsrio.com/www/home/cursor-logo.png' },
|
||||
{ name: 'Claude Code', logo: 'https://assets.cdn.clsrio.com/www/home/claude-logo.svg' },
|
||||
{ name: 'Codex', logo: 'https://assets.cdn.clsrio.com/www/home/codex-logo.png' },
|
||||
{ name: 'OpenCode', logo: 'https://assets.cdn.clsrio.com/www/home/opencode-logo.svg' }
|
||||
];
|
||||
</script>
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
<div class="mx-auto mt-10 w-full max-w-[1100px]">
|
||||
<div class="overflow-hidden rounded-2xl bg-white shadow-sm ring-1 ring-gray-200">
|
||||
<img
|
||||
src="/ai-course-builder.jpeg"
|
||||
src="https://assets.cdn.clsrio.com/www/home/ai-course-builder.jpeg"
|
||||
alt="Course builder — plan, approve, implement. Templates, in-editor chat, and MCP."
|
||||
class="block h-auto w-full"
|
||||
loading="lazy"
|
||||
|
||||
@@ -152,7 +152,7 @@
|
||||
<div class="mx-auto mt-10 w-full max-w-[960px] overflow-hidden rounded-lg">
|
||||
<div style="padding:{videoAspect} 0 0 0;position:relative;">
|
||||
<iframe
|
||||
src="https://player.vimeo.com/video/{vimeoVideoId}?badge=0&autopause=0&player_id=0&app_id=58479&autoplay=1&muted=1&loop=1"
|
||||
src="https://player.vimeo.com/video/{vimeoVideoId}?badge=0&autopause=0&player_id=0&app_id=58479&loop=1"
|
||||
frameborder="0"
|
||||
allow="autoplay; fullscreen; picture-in-picture; clipboard-write; encrypted-media; web-share"
|
||||
referrerpolicy="strict-origin-when-cross-origin"
|
||||
|
||||
@@ -145,6 +145,12 @@
|
||||
>Docs vs Company Academy</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="/public-courses"
|
||||
class="ui:text-muted-foreground ui:hover:text-foreground text-sm transition-colors">Public Courses</a
|
||||
>
|
||||
</li>
|
||||
<li>
|
||||
<a href="/teach" class="ui:text-muted-foreground ui:hover:text-foreground text-sm transition-colors"
|
||||
>Teach with us</a
|
||||
@@ -177,7 +183,7 @@
|
||||
<ul class="space-y-3">
|
||||
<li>
|
||||
<a
|
||||
href="https://feedback.classroomio.com"
|
||||
href="https://feedback.classroomio.com/roadmap"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="ui:text-muted-foreground ui:hover:text-foreground text-sm transition-colors">Roadmap</a
|
||||
|
||||
@@ -109,7 +109,7 @@
|
||||
<div class="relative z-30 mx-auto mt-14 w-full max-w-[1100px]">
|
||||
<div class="overflow-hidden rounded-2xl bg-white shadow-sm ring-1 ring-gray-200">
|
||||
<img
|
||||
src="/hero-academy.jpeg"
|
||||
src="https://assets.cdn.clsrio.com/www/home/hero-academy.jpeg"
|
||||
alt="Branded customer academy on a custom domain — catalog, programs, AI tutor"
|
||||
width="2560"
|
||||
height="1440"
|
||||
|
||||
@@ -27,7 +27,6 @@ export { default as ImagePlaceholder } from './image-placeholder.svelte';
|
||||
export { default as LanguageReel } from './language-reel.svelte';
|
||||
export { default as LearnerSection } from './learner-section.svelte';
|
||||
export { default as Modal } from './modal.svelte';
|
||||
export { default as MoreFeatures } from './more-features.svelte';
|
||||
export { default as McpServerSection } from './mcp-server-section.svelte';
|
||||
export { default as MultiAcademySection } from './multi-academy-section.svelte';
|
||||
export { default as Navigation } from './navigation.svelte';
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { onMount } from 'svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { folder, globe, team, transcription } from '$lib/emojis';
|
||||
import { tools } from '$lib/utils/constants/tools';
|
||||
|
||||
let selected = $state(0);
|
||||
let interval: NodeJS.Timer = $state();
|
||||
|
||||
const moreFeatures = [
|
||||
{
|
||||
icon: globe,
|
||||
title: 'Customizable Landing Page',
|
||||
description: 'A minimalistic landing page template out of the box to share your courses with the world',
|
||||
image: '/landing-page-builder.webp'
|
||||
},
|
||||
{
|
||||
icon: team,
|
||||
title: 'Team management',
|
||||
description: 'Extend invitations and manage your teaching institution seamlessly through ClassroomIO.',
|
||||
image: '/team-management.png'
|
||||
},
|
||||
// {
|
||||
// icon: transcription,
|
||||
// title: 'Auto Video Transcription',
|
||||
// description:
|
||||
// 'AI automatically transcribes videos, making content searchable for seamless student access.',
|
||||
// image: '/video-transcription.png'
|
||||
// },
|
||||
{
|
||||
icon: folder,
|
||||
title: 'Downloadable Lesson PDF',
|
||||
description: 'Students can download lessons automatically for offline access.',
|
||||
image: '/download-pdf.png'
|
||||
}
|
||||
];
|
||||
|
||||
const freeTools = tools.filter((item) => item.showFeature);
|
||||
|
||||
onMount(() => {
|
||||
if (window.innerWidth > 768) {
|
||||
interval = setInterval(() => {
|
||||
selected = moreFeatures[selected + 1] ? selected + 1 : 0;
|
||||
}, 3000);
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<!-- More Features -->
|
||||
<section id="morefeatures" class="bg-gray-50 px-3 py-[10%] lg:px-0">
|
||||
<div class="mx-0 lg:mx-[12%]">
|
||||
<div class="mx-4 mb-14 w-full lg:mx-0 lg:w-4/5">
|
||||
<h2 class="mt-2 text-3xl tracking-tight">There is More...</h2>
|
||||
<p class="mt-4 w-[94%] text-lg text-gray-500 lg:w-4/5">
|
||||
ClassroomIO is packed with useful features while we try to make it easy to use.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-col-reverse gap-3 md:gap-10 lg:flex-row" id="image-container">
|
||||
<div class="mt-5 flex w-[95%] overflow-auto p-3 lg:mt-0 lg:block lg:w-[45%] lg:overflow-hidden">
|
||||
{#each moreFeatures as moreFeature, i}
|
||||
<button
|
||||
class="rounded-md p-4 {i === selected &&
|
||||
'selected'} mb-3 min-w-[75vw] cursor-pointer text-start lg:min-w-[unset]"
|
||||
onclick={() => {
|
||||
selected = i;
|
||||
clearInterval(interval);
|
||||
}}
|
||||
>
|
||||
<div class="flex items-center gap-1">
|
||||
<img loading="lazy" width="32" height="32" src={moreFeature.icon} alt="" class="w-8" />
|
||||
<p class="text-lg">
|
||||
{moreFeature.title}
|
||||
</p>
|
||||
</div>
|
||||
<p class="text-sm">{moreFeature.description}</p>
|
||||
</button>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<!-- Video -->
|
||||
<div class="h-full w-full p-3 lg:w-2/3 lg:p-0">
|
||||
{#key selected}
|
||||
<img
|
||||
width="100%"
|
||||
height="100%"
|
||||
loading="lazy"
|
||||
id="image"
|
||||
in:fly={{ x: 100, duration: 800 }}
|
||||
class="flex w-full flex-col items-center"
|
||||
src={moreFeatures[selected].image}
|
||||
alt={moreFeatures[selected].title}
|
||||
/>
|
||||
{/key}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<style>
|
||||
#morefeatures .selected {
|
||||
background-image: linear-gradient(45deg, rgb(253, 239, 132), rgb(247, 198, 169), rgb(21, 186, 196));
|
||||
}
|
||||
</style>
|
||||
@@ -105,10 +105,10 @@
|
||||
href: '/mcp-recipes'
|
||||
},
|
||||
{
|
||||
key: 'github',
|
||||
title: 'GitHub',
|
||||
subtitle: 'Star, read the source, fork.',
|
||||
href: '/github'
|
||||
key: 'storybook',
|
||||
title: 'Storybook',
|
||||
subtitle: 'Browse and reuse UI components.',
|
||||
href: 'https://ui.classroomio.dev'
|
||||
}
|
||||
];
|
||||
|
||||
@@ -305,7 +305,12 @@
|
||||
|
||||
<div class="hidden! flex-row items-center justify-between gap-3 lg:flex!">
|
||||
<a href="/discord" target="_blank" class="flex items-center transition-opacity duration-200 hover:opacity-80">
|
||||
<img loading="lazy" alt="discord logo" src="/discord-blue.png" class="h-5 w-6 cursor-pointer" />
|
||||
<img
|
||||
loading="lazy"
|
||||
alt="discord logo"
|
||||
src="https://assets.cdn.clsrio.com/www/home/discord-blue.png"
|
||||
class="h-5 w-6 cursor-pointer"
|
||||
/>
|
||||
</a>
|
||||
<div class="flex items-center">
|
||||
<a
|
||||
@@ -316,7 +321,7 @@
|
||||
<img
|
||||
loading="lazy"
|
||||
alt="github logo"
|
||||
src="/github-mark.png"
|
||||
src="https://assets.cdn.clsrio.com/www/home/github-mark.png"
|
||||
class="h-5 w-5 cursor-pointer transition-transform duration-200 group-hover:scale-110"
|
||||
/>
|
||||
<span
|
||||
@@ -402,7 +407,12 @@
|
||||
target="_blank"
|
||||
class="flex w-full items-center rounded-md px-4 py-4 text-left text-sm transition-all duration-200 hover:bg-gray-100 md:text-lg"
|
||||
>
|
||||
<img loading="lazy" alt="discord logo" src="/discord-blue.png" class="mr-2 h-5 w-6 cursor-pointer" />
|
||||
<img
|
||||
loading="lazy"
|
||||
alt="discord logo"
|
||||
src="https://assets.cdn.clsrio.com/www/home/discord-blue.png"
|
||||
class="mr-2 h-5 w-6 cursor-pointer"
|
||||
/>
|
||||
<span>Discord</span>
|
||||
</a>
|
||||
<a
|
||||
@@ -413,7 +423,7 @@
|
||||
<img
|
||||
loading="lazy"
|
||||
alt="github logo"
|
||||
src="/github-mark.png"
|
||||
src="https://assets.cdn.clsrio.com/www/home/github-mark.png"
|
||||
class="h-5 w-5 cursor-pointer transition-transform duration-200 group-hover:scale-110"
|
||||
/>
|
||||
<span class="ml-3 transition-colors duration-200 group-hover:text-black">Github</span>
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
import { dev } from '$app/environment';
|
||||
|
||||
const USERJOT_APP_ID = 'cm4a6vcmp00jpmdb5n66rmkzz';
|
||||
|
||||
let isInitialized = false;
|
||||
|
||||
function isWidgetAllowed(): boolean {
|
||||
return !dev;
|
||||
}
|
||||
|
||||
function ensureSdkLoaded(): void {
|
||||
if (window.uj) return;
|
||||
|
||||
window.$ujq = window.$ujq || [];
|
||||
window.uj =
|
||||
window.uj ||
|
||||
(new Proxy({} as Window['uj'], {
|
||||
get:
|
||||
(_, prop) =>
|
||||
(...args: unknown[]) =>
|
||||
window.$ujq.push([prop, ...args])
|
||||
}) as Window['uj']);
|
||||
|
||||
const script = document.createElement('script');
|
||||
script.type = 'module';
|
||||
script.async = true;
|
||||
script.src = 'https://cdn.userjot.com/sdk/v2/uj.js';
|
||||
document.head.appendChild(script);
|
||||
}
|
||||
|
||||
export function initUserJot(): void {
|
||||
if (isInitialized) return;
|
||||
if (!isWidgetAllowed()) return;
|
||||
|
||||
ensureSdkLoaded();
|
||||
|
||||
window.uj.init(USERJOT_APP_ID, {
|
||||
trigger: 'custom',
|
||||
position: 'right',
|
||||
theme: 'auto'
|
||||
});
|
||||
|
||||
isInitialized = true;
|
||||
}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
declare global {
|
||||
interface Window {
|
||||
$ujq: unknown[];
|
||||
uj: {
|
||||
init: (
|
||||
appId: string,
|
||||
options?: {
|
||||
widget?: boolean;
|
||||
position?: 'left' | 'right';
|
||||
theme?: 'auto' | 'light' | 'dark';
|
||||
}
|
||||
) => void;
|
||||
identify: (user: { id: string; email?: string; firstName?: string; lastName?: string; avatar?: string }) => void;
|
||||
[method: string]: (...args: unknown[]) => void;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
@@ -187,7 +187,7 @@
|
||||
<div class="mx-auto mt-14 w-full max-w-[1100px]">
|
||||
<div class="overflow-hidden rounded-2xl bg-white shadow-sm ring-1 ring-gray-200">
|
||||
<img
|
||||
src="/org-compliance.jpeg"
|
||||
src="https://assets.cdn.clsrio.com/www/compliance-training/org-compliance.jpeg"
|
||||
alt="Compliance dashboard — required learners grouped by compliant, expiring soon, and non-compliant"
|
||||
class="block h-auto w-full"
|
||||
loading="eager"
|
||||
@@ -215,7 +215,7 @@
|
||||
eyebrow="Inside a compliance program"
|
||||
title="A look inside a compliance program."
|
||||
description="From importing your team to issuing a certificate — the whole flow at a glance."
|
||||
imageSrc="/compliance-dashboard.jpeg"
|
||||
imageSrc="https://assets.cdn.clsrio.com/www/compliance-training/compliance-dashboard.jpeg"
|
||||
imageAlt="Compliance dashboard — required learners, status, and certificates"
|
||||
/>
|
||||
|
||||
@@ -234,7 +234,7 @@
|
||||
eyebrow="Renewals on autopilot"
|
||||
title="Training that re-runs itself."
|
||||
description="Set a retake interval once. ClassroomIO automatically moves learners back into “expiring soon”, sends reminders, holds them in a grace period, and flags non-compliance — all without admin intervention."
|
||||
imageSrc="/course-compliance.jpeg"
|
||||
imageSrc="https://assets.cdn.clsrio.com/www/compliance-training/course-compliance.jpeg"
|
||||
imageAlt="Compliance settings panel — retake interval, grace period, reminders, waiver rules"
|
||||
>
|
||||
{#snippet bullets()}
|
||||
@@ -317,7 +317,7 @@
|
||||
accent="In your dashboard"
|
||||
title="A personal course-authoring assistant."
|
||||
description="Drop in a policy doc or paste a URL. The assistant plans the compliance course, drafts each lesson, writes the quiz questions, and stops for your approval before publishing — so building required training drops from a week to an afternoon."
|
||||
imageSrc="/ai-course-builder.jpeg"
|
||||
imageSrc="https://assets.cdn.clsrio.com/www/compliance-training/ai-course-builder.jpeg"
|
||||
imageAlt="Course builder — plan, approve, implement. Templates, in-editor chat, and MCP."
|
||||
/>
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@
|
||||
<div class="mx-auto mt-14 w-full max-w-[1100px]">
|
||||
<div class="overflow-hidden rounded-2xl bg-white shadow-sm ring-1 ring-gray-200">
|
||||
<img
|
||||
src="/beautiful-academy-site.jpeg"
|
||||
src="https://assets.cdn.clsrio.com/www/customer-education/beautiful-academy-site.jpeg"
|
||||
alt="Branded customer academy on a custom domain — hero, catalog, themed branding"
|
||||
class="block h-auto w-full"
|
||||
loading="eager"
|
||||
@@ -269,7 +269,7 @@
|
||||
eyebrow="Make it yours"
|
||||
title="Customize how your customer academy looks like."
|
||||
description="Theme the catalog, swap fonts and colors to match your brand, and build landing pages that feel like the rest of your product — without losing the LMS underneath."
|
||||
imageSrc="/customizable-academy.jpeg"
|
||||
imageSrc="https://assets.cdn.clsrio.com/www/customer-education/customizable-academy.jpeg"
|
||||
imageAlt="Customizable customer academy — catalog, course page, certificate"
|
||||
/>
|
||||
|
||||
@@ -318,7 +318,7 @@
|
||||
]}
|
||||
statusBar="connected · org: yourcompany · widget: getting-started"
|
||||
previewUrl="help.yourcompany.com / getting-started"
|
||||
previewImageSrc="/embeddable-widget.jpeg"
|
||||
previewImageSrc="https://assets.cdn.clsrio.com/www/customer-education/embeddable-widget.jpeg"
|
||||
previewAlt="Lesson widget embedded inside a help-center page"
|
||||
capabilities={[
|
||||
{ label: 'One script tag', sub: 'Drop-in install, no SDK required' },
|
||||
|
||||
@@ -192,7 +192,7 @@
|
||||
<div class="mx-auto mt-14 w-full max-w-[1100px]">
|
||||
<div class="overflow-hidden rounded-2xl bg-white shadow-sm ring-1 ring-gray-200">
|
||||
<img
|
||||
src="/docs-vs-customer-site.jpeg"
|
||||
src="https://assets.cdn.clsrio.com/www/docs-vs-company-academy/docs-vs-customer-site.jpeg"
|
||||
alt="Docs answering questions, customer academy building capability — side by side"
|
||||
class="block h-auto w-full"
|
||||
loading="eager"
|
||||
|
||||
@@ -221,7 +221,7 @@
|
||||
<div class="mx-auto mt-14 w-full max-w-[1100px]">
|
||||
<div class="overflow-hidden rounded-2xl bg-white shadow-sm ring-1 ring-gray-200">
|
||||
<img
|
||||
src="/latest-courses.jpeg"
|
||||
src="https://assets.cdn.clsrio.com/www/partner-training/latest-courses.jpeg"
|
||||
alt="Partner academy — latest courses, program structure, and learner state"
|
||||
class="block h-auto w-full"
|
||||
loading="eager"
|
||||
@@ -254,7 +254,7 @@
|
||||
eyebrow="Public course pages"
|
||||
title="Open a few courses to the public, gate the rest."
|
||||
description="Pick the courses you want anyone to see. Partners (and the curious ones who aren’t partners yet) can jump in without signing up, watch a few lessons, and if they’re hooked they create an account to unlock the rest of your catalog."
|
||||
imageSrc="/public-courses.jpeg"
|
||||
imageSrc="https://assets.cdn.clsrio.com/www/partner-training/public-courses.jpeg"
|
||||
imageAlt="Public partner course pages — open courses up front, sign-up gates the rest"
|
||||
/>
|
||||
|
||||
@@ -281,7 +281,7 @@
|
||||
]}
|
||||
statusBar="connected · org: yourcompany · widget: partner-onboarding"
|
||||
previewUrl="partners.yourcompany.com / academy"
|
||||
previewImageSrc="/embeddable-widget.jpeg"
|
||||
previewImageSrc="https://assets.cdn.clsrio.com/www/partner-training/embeddable-widget.jpeg"
|
||||
previewAlt="Course widget embedded inside a partner portal"
|
||||
capabilities={[
|
||||
{ label: 'One script tag', sub: 'Drop-in install, no SDK required' },
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
<script>
|
||||
<script lang="ts">
|
||||
import { dev } from '$app/environment';
|
||||
import { page } from '$app/state';
|
||||
import { Footer, Navigation, NotFound } from '$lib/components';
|
||||
import { initUserJot } from '$lib/utils/userjot';
|
||||
import extend from 'just-extend';
|
||||
import { onMount } from 'svelte';
|
||||
import { MetaTags } from 'svelte-meta-tags';
|
||||
@@ -13,7 +14,10 @@
|
||||
onMount(() => {
|
||||
if (dev) {
|
||||
localStorage.setItem('umami.disabled', '1');
|
||||
return;
|
||||
}
|
||||
|
||||
initUserJot();
|
||||
});
|
||||
|
||||
let metaTags = $derived(extend(true, {}, data.baseMetaTags, page.data.pageMetaTags));
|
||||
|
||||
@@ -15,6 +15,11 @@ export async function load({ url }) {
|
||||
const starsCache = new Map<string, { stars: number; lastUpdated: number }>();
|
||||
const CACHE_TIME = 1000 * 60 * 60 * 48; // 48 hours
|
||||
const CACHE_KEY = 'github-stars';
|
||||
const DEFAULT_META_TITLE = 'ClassroomIO | The Most Customizable Platform for Customer, Partner, and Employee Education';
|
||||
const DEFAULT_META_DESCRIPTION =
|
||||
'One platform for customer academies, partner certification, and employee training. Build courses with AI, publish under your domain, and track completions.';
|
||||
const DEFAULT_OG_IMAGE_URL = 'https://brand.cdn.clsrio.com/og/classroomio-opengraph.png';
|
||||
const DEFAULT_OG_IMAGE_ALT = 'ClassroomIO platform for customer, partner, and employee education';
|
||||
|
||||
async function getStars() {
|
||||
const now = Date.now();
|
||||
@@ -43,27 +48,27 @@ async function getStars() {
|
||||
}
|
||||
|
||||
function getBaseMetaTags(url: URL) {
|
||||
const canonicalUrl = new URL(url.pathname, url.origin).href;
|
||||
|
||||
const metatags = Object.freeze({
|
||||
title: 'ClassroomIO | The Open Source Learning Management System for Companies',
|
||||
description:
|
||||
'A flexible, user-friendly platform for creating, managing, and delivering courses for companies and training organisations',
|
||||
canonical: new URL(url.pathname, url.origin).href,
|
||||
title: DEFAULT_META_TITLE,
|
||||
description: DEFAULT_META_DESCRIPTION,
|
||||
canonical: canonicalUrl,
|
||||
openGraph: {
|
||||
type: 'website',
|
||||
url: new URL(url.pathname, url.origin).href,
|
||||
locale: 'en_IE',
|
||||
title: 'ClassroomIO | The Open Source Learning Management System for Companies',
|
||||
description:
|
||||
'A flexible, user-friendly platform for creating, managing, and delivering courses for companies and training organisations',
|
||||
url: canonicalUrl,
|
||||
locale: 'en_US',
|
||||
title: DEFAULT_META_TITLE,
|
||||
description: DEFAULT_META_DESCRIPTION,
|
||||
siteName: 'ClassroomIO',
|
||||
images: [
|
||||
{
|
||||
url: 'https://brand.cdn.clsrio.com/og/classroomio-og.png',
|
||||
alt: 'ClassroomIO OG Image',
|
||||
url: DEFAULT_OG_IMAGE_URL,
|
||||
alt: DEFAULT_OG_IMAGE_ALT,
|
||||
width: 1920,
|
||||
height: 1080,
|
||||
secureUrl: 'https://brand.cdn.clsrio.com/og/classroomio-og.png',
|
||||
type: 'image/jpeg'
|
||||
secureUrl: DEFAULT_OG_IMAGE_URL,
|
||||
type: 'image/png'
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -71,11 +76,10 @@ function getBaseMetaTags(url: URL) {
|
||||
handle: '@classroomio',
|
||||
site: '@classroomio',
|
||||
cardType: 'summary_large_image' as const,
|
||||
title: 'ClassroomIO | The Open Source Learning Management System for Companies',
|
||||
description:
|
||||
'A flexible, user-friendly platform for creating, managing, and delivering courses for companies and training organisations',
|
||||
image: 'https://brand.cdn.clsrio.com/og/classroomio-og.png',
|
||||
imageAlt: 'ClassroomIO OG Image'
|
||||
title: DEFAULT_META_TITLE,
|
||||
description: DEFAULT_META_DESCRIPTION,
|
||||
image: DEFAULT_OG_IMAGE_URL,
|
||||
imageAlt: DEFAULT_OG_IMAGE_ALT
|
||||
}
|
||||
}) satisfies MetaTagsProps;
|
||||
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
<script lang="ts">
|
||||
import { Faq, FeatureGrid, PageHeader, PageSignupCTA, TrustBand, WorkflowSteps } from '$lib/components';
|
||||
import { Badge } from '@cio/ui/base/badge';
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
import { BlurFade } from '@cio/ui/custom/animation/blurfade';
|
||||
import Check from '@lucide/svelte/icons/check';
|
||||
import Globe from '@lucide/svelte/icons/globe';
|
||||
import GraduationCap from '@lucide/svelte/icons/graduation-cap';
|
||||
import MoonStar from '@lucide/svelte/icons/moon-star';
|
||||
import Palette from '@lucide/svelte/icons/palette';
|
||||
import Sparkles from '@lucide/svelte/icons/sparkles';
|
||||
import Users from '@lucide/svelte/icons/users';
|
||||
import Zap from '@lucide/svelte/icons/zap';
|
||||
|
||||
const creatorUseCases = [
|
||||
'A free intro course that leads into a paid program',
|
||||
'A public sample course people can review before they buy',
|
||||
'A short onboarding or community course that does not need login friction',
|
||||
'Partner or reseller training you can share with a link',
|
||||
'A simple home for short lessons and self-graded modules'
|
||||
];
|
||||
|
||||
const learnerUseCases = [
|
||||
'Browse the full catalog without creating an account',
|
||||
'Read in light mode or dark mode',
|
||||
'Get immediate quiz feedback',
|
||||
'Start on mobile and continue on desktop',
|
||||
'Use a course page that matches the creator brand they came for'
|
||||
];
|
||||
|
||||
const keyFeatures = [
|
||||
{
|
||||
Icon: Palette,
|
||||
title: 'Branding controls',
|
||||
description:
|
||||
'Choose a landing theme, add your logo, set your site name, and connect a custom domain without custom development.'
|
||||
},
|
||||
{
|
||||
Icon: MoonStar,
|
||||
title: 'Light and dark mode',
|
||||
description:
|
||||
'The lesson viewer includes a built-in mode switcher, and the learner preference stays in place between visits.'
|
||||
},
|
||||
{
|
||||
Icon: Sparkles,
|
||||
title: 'Clean lesson pages',
|
||||
description:
|
||||
'Public course pages use the same design system as the rest of ClassroomIO, so they feel like part of your product instead of a separate microsite.'
|
||||
},
|
||||
{
|
||||
Icon: Zap,
|
||||
title: 'Auto-graded quizzes',
|
||||
description:
|
||||
'Support for 15 auto-gradable question types, including multiple choice, ordering, hotspot, short answer, and fill-in-the-blank, with instant feedback in the lesson.'
|
||||
}
|
||||
];
|
||||
|
||||
const conversionMechanics = [
|
||||
{
|
||||
title: 'Inline callout cards',
|
||||
description:
|
||||
'Add a callout card inside any lesson with a title, description, button label, and link to your paid course, checkout, or community.'
|
||||
},
|
||||
{
|
||||
title: 'Locked lesson previews',
|
||||
description:
|
||||
'Leave part of the course open, then replace locked lesson content with a callout that points to the next step.'
|
||||
},
|
||||
{
|
||||
title: 'Payment, discount, and invite gating',
|
||||
description: 'Route learners into paid enrollment with payment links, discount codes, or invite-based access.'
|
||||
},
|
||||
{
|
||||
title: 'Auto-enroll after sign-up',
|
||||
description: 'Learners who sign in can return to the lesson they were already viewing instead of starting over.'
|
||||
}
|
||||
];
|
||||
|
||||
const brandingItems = ['Custom domain', 'Your logo', 'Your site name', 'Dark mode built-in', 'SEO-friendly pages'];
|
||||
|
||||
const workflow = [
|
||||
{
|
||||
title: 'Build the course',
|
||||
description:
|
||||
'Use the same course editor you already use for paid courses. Public courses support all 15 auto-gradable question types.',
|
||||
label: 'Step 01'
|
||||
},
|
||||
{
|
||||
title: 'Switch type to PUBLIC',
|
||||
description:
|
||||
'Change the course type to `PUBLIC`. If a question type is not supported, ClassroomIO flags it before publish.',
|
||||
label: 'Step 02'
|
||||
},
|
||||
{
|
||||
title: 'Set the page up',
|
||||
description: 'Choose a theme, add your logo and site name, and connect a custom domain if you want one.',
|
||||
label: 'Step 03'
|
||||
},
|
||||
{
|
||||
title: 'Publish',
|
||||
description:
|
||||
'Publish the course on your public site, then add callouts or locked lessons where you want to turn readers into enrollments.',
|
||||
label: 'Step 04'
|
||||
}
|
||||
];
|
||||
|
||||
const publicCoursesFaqs = [
|
||||
{
|
||||
question: 'Does hosting a public course cost extra?',
|
||||
answer:
|
||||
'No. Public courses are part of your existing ClassroomIO workspace. Every paid plan can publish them, and learners do not count against your seat limits until they enroll in a paid course.'
|
||||
},
|
||||
{
|
||||
question: 'Can I require payment, or capture leads on a public course?',
|
||||
answer:
|
||||
'Yes. You can attach a payment link, a discount code, or an invite token to the enrollment flow. You can also place callout cards inside lessons that link to a paid course, a community, or any URL you choose.'
|
||||
},
|
||||
{
|
||||
question: 'Do I need a custom domain?',
|
||||
answer:
|
||||
'No. Every public course is available on your ClassroomIO public site by default. A custom domain is optional if you want the course to live at your own URL.'
|
||||
},
|
||||
{
|
||||
question: 'Can search engines index a public course?',
|
||||
answer:
|
||||
'Yes. Public course landing pages and lesson previews are server-rendered and include the metadata search engines need, so courses are discoverable.'
|
||||
},
|
||||
{
|
||||
question: 'How are quizzes graded?',
|
||||
answer:
|
||||
'Instantly in the browser. Public courses support 15 auto-gradable question types, including multiple choice, ordering, matching, hotspot, fill-in-the-blank, numeric, short answer, and file upload.'
|
||||
},
|
||||
{
|
||||
question: 'Can I gate some lessons and leave the rest public?',
|
||||
answer:
|
||||
'Yes. Lock the lessons you want to gate and the viewer will show a callout card in place of the content. You can use that card to send people to the paid version of the course.'
|
||||
},
|
||||
{
|
||||
question: 'Can I match the course page to my brand?',
|
||||
answer:
|
||||
'Yes. You can choose a landing theme, upload your logo, set a site name, and optionally connect a custom domain. Dark mode is built in for learners.'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Public Courses | ClassroomIO</title>
|
||||
<meta
|
||||
name="description"
|
||||
content="Publish public courses on your own branded page, with built-in quizzes, lesson callouts, and optional custom domains."
|
||||
/>
|
||||
<meta property="og:title" content="Public Courses | ClassroomIO" />
|
||||
<meta
|
||||
property="og:description"
|
||||
content="A branded public course page for sharing free lessons, quizzes, and previews before someone enrolls."
|
||||
/>
|
||||
</svelte:head>
|
||||
|
||||
<section class="bg-white">
|
||||
<PageHeader className="px-6 lg:px-12">
|
||||
<div class="mx-auto flex max-w-[820px] flex-col items-center text-center">
|
||||
<Badge variant="outline" class="mb-6 gap-2! bg-white px-3.5! py-1.5!">
|
||||
<Globe size={14} class="text-blue-700" />
|
||||
Public Courses
|
||||
</Badge>
|
||||
|
||||
<h1 class="text-[clamp(2.4rem,4vw,3.6rem)] leading-[1.08] font-medium tracking-tight text-gray-950">
|
||||
Publish free courses that lead to paid enrollments.
|
||||
</h1>
|
||||
|
||||
<p class="mt-6 text-sm leading-relaxed lg:text-base">
|
||||
Public courses let you share lessons without asking people to create an account first. You can publish free
|
||||
course content, add quizzes, customize the page, and guide interested learners into a paid course or community.
|
||||
</p>
|
||||
|
||||
<div class="mt-8 flex flex-wrap items-center justify-center gap-3">
|
||||
<Button data-cal-config="'layout':'month_view'" data-cal-link="classroomio/demo">Book a Demo</Button>
|
||||
<Button href="/signup" variant="outline">Start free</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mx-auto mt-14 w-full max-w-[1100px]">
|
||||
<img
|
||||
src="https://assets.cdn.clsrio.com/www/public-courses/public-courses-hero.jpeg"
|
||||
alt="Public course page on desktop"
|
||||
width="1920"
|
||||
height="1481"
|
||||
loading="eager"
|
||||
class="w-full rounded-2xl border border-gray-200 shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
</PageHeader>
|
||||
|
||||
<!-- Use cases: two-column split -->
|
||||
<section class="bg-gray-50 px-6 py-16 lg:px-12 lg:py-24">
|
||||
<div class="mx-auto max-w-[1120px]">
|
||||
<div class="mb-10 max-w-[720px]">
|
||||
<div class="mb-3 text-xs font-medium tracking-widest text-blue-700 uppercase">Why teams use it</div>
|
||||
<h2 class="text-[clamp(2rem,3vw,2.7rem)] leading-[1.15] font-medium tracking-tight text-gray-950">
|
||||
Public courses are useful before someone is ready to enroll.
|
||||
</h2>
|
||||
<p class="mt-5 text-base leading-relaxed text-gray-500">
|
||||
Teams use them to share sample lessons, open training, and course previews. Learners get a low-friction way to
|
||||
read or try the material before deciding what to do next.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 lg:divide-x lg:divide-gray-200">
|
||||
<div class="rounded-2xl border border-gray-200 bg-white p-8 lg:rounded-r-none lg:border-r-0">
|
||||
<div class="text-[11px] font-medium tracking-widest text-blue-700 uppercase">For creators</div>
|
||||
<h3 class="mt-4 text-[clamp(1.4rem,2.2vw,1.9rem)] leading-[1.15] font-medium tracking-tight text-gray-950">
|
||||
A practical way to publish useful course content in public.
|
||||
</h3>
|
||||
|
||||
<div class="my-7 border-t border-gray-200"></div>
|
||||
|
||||
<ul class="space-y-4">
|
||||
{#each creatorUseCases as useCase}
|
||||
<li class="flex items-start gap-3 text-sm text-gray-700">
|
||||
<span
|
||||
class="mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-blue-50 text-blue-700"
|
||||
>
|
||||
<Check size={12} strokeWidth={2.5} />
|
||||
</span>
|
||||
{useCase}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
<div class="mt-8">
|
||||
<span
|
||||
class="inline-flex items-center gap-2 rounded-full bg-blue-50 px-3 py-1.5 text-xs font-medium text-blue-700"
|
||||
>
|
||||
<GraduationCap size={13} strokeWidth={2} />
|
||||
Shareable by default
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-6 rounded-2xl border border-gray-200 bg-white p-8 lg:mt-0 lg:rounded-l-none lg:border-l-0">
|
||||
<div class="text-[11px] font-medium tracking-widest text-emerald-700 uppercase">For learners</div>
|
||||
<h3 class="mt-4 text-[clamp(1.4rem,2.2vw,1.9rem)] leading-[1.15] font-medium tracking-tight text-gray-950">
|
||||
A simple course page that is easy to browse and easy to read.
|
||||
</h3>
|
||||
|
||||
<div class="my-7 border-t border-gray-200"></div>
|
||||
|
||||
<ul class="space-y-4">
|
||||
{#each learnerUseCases as useCase}
|
||||
<li class="flex items-start gap-3 text-sm text-gray-700">
|
||||
<span
|
||||
class="mt-0.5 flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-emerald-50 text-emerald-700"
|
||||
>
|
||||
<Check size={12} strokeWidth={2.5} />
|
||||
</span>
|
||||
{useCase}
|
||||
</li>
|
||||
{/each}
|
||||
</ul>
|
||||
|
||||
<div class="mt-8">
|
||||
<span
|
||||
class="inline-flex items-center gap-2 rounded-full bg-emerald-50 px-3 py-1.5 text-xs font-medium text-emerald-700"
|
||||
>
|
||||
<Users size={13} strokeWidth={2} />
|
||||
No login wall
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Key features -->
|
||||
<FeatureGrid
|
||||
eyebrow="What you get"
|
||||
title="The essentials are already built in."
|
||||
description="You do not need a separate website project to publish public course pages that look finished and work well."
|
||||
features={keyFeatures}
|
||||
columns={4}
|
||||
/>
|
||||
|
||||
<!-- Drive-to-paid story -->
|
||||
<section class="bg-white px-6 py-12 lg:px-12 lg:py-16">
|
||||
<div class="mx-auto grid max-w-[1100px] grid-cols-1 items-center gap-12 lg:grid-cols-2 lg:gap-20">
|
||||
<div>
|
||||
<div class="mb-2 text-xs font-medium tracking-widest text-blue-700 uppercase">Moving people forward</div>
|
||||
<h2 class="text-[clamp(1.75rem,2.6vw,2.2rem)] leading-[1.15] font-medium tracking-tight">
|
||||
If someone wants more, you can give them a clear next step.
|
||||
</h2>
|
||||
<p class="mt-5 text-base leading-relaxed text-gray-500">
|
||||
Public courses are useful on their own, but they can also lead into a paid course, a cohort, or a community.
|
||||
Add callouts inside lessons, lock selected content, and guide people into enrollment when it makes sense.
|
||||
</p>
|
||||
<ul class="mt-6 space-y-3 text-sm text-gray-700">
|
||||
{#each conversionMechanics as item, i}
|
||||
<BlurFade delay={0.06 * i} once>
|
||||
<li class="flex gap-3">
|
||||
<span class="mt-1.5 inline-flex h-1.5 w-1.5 shrink-0 rounded-full bg-blue-700"></span>
|
||||
<span>
|
||||
<span class="font-medium text-gray-950">{item.title}.</span>
|
||||
<span class="ml-1 text-gray-500">{item.description}</span>
|
||||
</span>
|
||||
</li>
|
||||
</BlurFade>
|
||||
{/each}
|
||||
</ul>
|
||||
</div>
|
||||
<img
|
||||
src="https://assets.cdn.clsrio.com/www/public-courses/public-course-empty-state.jpeg"
|
||||
alt="Public course empty state in the dashboard"
|
||||
width="1920"
|
||||
height="1410"
|
||||
loading="lazy"
|
||||
class="w-full rounded-2xl border border-gray-200 shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- Custom domain + branding trust band -->
|
||||
<TrustBand caption="Branding options" items={brandingItems} />
|
||||
|
||||
<!-- How it works -->
|
||||
<WorkflowSteps
|
||||
eyebrow="How it works"
|
||||
title="Set it up in the same workflow you already use."
|
||||
description="You do not need a second publishing tool. Public courses use the same course editor and publishing flow as the rest of ClassroomIO."
|
||||
steps={workflow}
|
||||
/>
|
||||
|
||||
<!-- FAQ -->
|
||||
<section class="bg-white px-6 lg:px-12">
|
||||
<Faq
|
||||
heading="Public courses, answered"
|
||||
subheading="A few common questions before teams publish their first public course."
|
||||
items={publicCoursesFaqs}
|
||||
hideCta
|
||||
/>
|
||||
</section>
|
||||
|
||||
<!-- Final CTA -->
|
||||
<PageSignupCTA
|
||||
header="Publish a public course without spinning up a separate site."
|
||||
subText="Use the same ClassroomIO workspace to share free lessons, add quizzes, and point interested learners toward the next step."
|
||||
btnLabel="Book a Demo"
|
||||
/>
|
||||
</section>
|
||||
@@ -0,0 +1,7 @@
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
|
||||
export const prerender = false;
|
||||
|
||||
export const load = () => {
|
||||
redirect(307, 'https://feedback.classroomio.com/roadmap');
|
||||
};
|
||||
@@ -1,107 +0,0 @@
|
||||
<script>
|
||||
import { PageHeader, Timeline, PageSignupCTA } from '$lib/components';
|
||||
|
||||
const newFeatures = [
|
||||
{
|
||||
title: 'LMS Customization',
|
||||
desc: 'Right in your settings you can customize what you students see in their dashboard in few clicks.'
|
||||
},
|
||||
{
|
||||
title: 'Course Newsfeed',
|
||||
desc: 'You can now send a broadcast message to all the students participating in your course right from our dashboard.'
|
||||
},
|
||||
{
|
||||
title: 'Tags',
|
||||
desc: 'You can now group courses into organization-specific categories and filter course catalogs using tags.'
|
||||
},
|
||||
{
|
||||
title: 'Multi language support',
|
||||
desc: 'Our dashboard now supports 7 new languages. In addition, we allow you create course content in those any of those languages.'
|
||||
},
|
||||
{
|
||||
title: 'Security RLS',
|
||||
desc: "All the tables we've created now have role level security enabled by default"
|
||||
},
|
||||
{
|
||||
title: 'Increased video limit',
|
||||
desc: 'You can now upload a single video of about 500mb without interruption.'
|
||||
},
|
||||
{
|
||||
title: 'More certificate templates',
|
||||
desc: 'We have shipped 4 more certificate templates in which you can choose from right within your course dashboard'
|
||||
}
|
||||
];
|
||||
|
||||
const upcomingFeatures = [
|
||||
{
|
||||
title: 'Pathways',
|
||||
desc: 'This feature gives you the ability to group courses into folder which we are calling - Pathways. Students can complete a series of courses before getting a certificate'
|
||||
},
|
||||
{
|
||||
title: 'Course Batches',
|
||||
desc: 'A course can be taken in batches, meaning that you can create different cohorts of students within one course. The benefit of this is that you can teach a course multiple times to different groups of students. This is useful mainly for bootcamps and teaching organizations.'
|
||||
},
|
||||
{
|
||||
title: 'API',
|
||||
desc: 'We are working on our public API which allows you to perform CRUD operations against your classroomio organization.'
|
||||
},
|
||||
{
|
||||
title: 'Embedable Course',
|
||||
desc: 'You can embed selected course form ClassroomIO on any website of your choice'
|
||||
},
|
||||
{
|
||||
title: 'Landing page builder',
|
||||
desc: 'With more templates and pages, we will allow educators create simple web pages using our platform to showcase their programs and offerings.'
|
||||
},
|
||||
{
|
||||
title: 'Analytics',
|
||||
desc: 'Educators can easily track students course completion rating, understand what topics are not clearly understood and much more.'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<svelte:head>
|
||||
<title>Roadmap | ClassroomIO</title>
|
||||
</svelte:head>
|
||||
|
||||
<PageHeader className="flex flex-col items-center justify-center text-center">
|
||||
<h1 class="text-start text-4xl text-slate-900 md:text-center md:text-6xl">Product Roadmap</h1>
|
||||
<p class="mt-10 w-[80%] text-start text-slate-700 md:w-[40%] md:text-center">
|
||||
This is a live document, and will be updated regularly. To submit an idea, or to view a list of feature requests and
|
||||
ideas that we're considering, check out our <a
|
||||
href="https://feedback.classroomio.com"
|
||||
target="_blank"
|
||||
rel="noopener"
|
||||
class="underline">feedback portal</a
|
||||
>
|
||||
</p>
|
||||
</PageHeader>
|
||||
<section class="relative flex w-full flex-col items-center border-b-2 px-4 py-20">
|
||||
<img src="/roadmap-one.svg" alt="" class="absolute right-0 bottom-0 w-60 lg:w-96" />
|
||||
<img src="/roadmap-two.svg" alt="" class="absolute top-0 left-0 hidden lg:block" />
|
||||
<div class="flex flex-col items-start space-y-10 px-4">
|
||||
<div>
|
||||
<h1 class="text-3xl">Latest Features</h1>
|
||||
</div>
|
||||
|
||||
<Timeline items={newFeatures} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="flex w-full flex-col items-center border-b-2 px-4 py-20">
|
||||
<div class="flex flex-col items-start space-y-10 px-4">
|
||||
<div>
|
||||
<h1 class="text-3xl">Upcoming Features</h1>
|
||||
</div>
|
||||
|
||||
<Timeline items={upcomingFeatures} />
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<PageSignupCTA
|
||||
header="Share Your First Course With Your Audience In Minutes"
|
||||
subText="In about 4 Clicks you can already start creating courses."
|
||||
btnLabel="Get started for free"
|
||||
link="/signup"
|
||||
demo={false}
|
||||
/>
|
||||
@@ -5,17 +5,17 @@
|
||||
|
||||
const whyStart = [
|
||||
{
|
||||
src: '/teach/teach-from-anywhere.svg',
|
||||
src: 'https://assets.cdn.clsrio.com/www/teach/teach-from-anywhere.svg',
|
||||
header: 'Fully Online; Teach from anywhere',
|
||||
subText: ' Facilitate a subject from the comfort of your space, engaging students from highly diverse background'
|
||||
},
|
||||
{
|
||||
src: '/teach/get-paid.svg',
|
||||
src: 'https://assets.cdn.clsrio.com/www/teach/get-paid.svg',
|
||||
header: 'Get paid extra commission',
|
||||
subText: 'Get paid for the course you design and earn extra comission based on course perfomance'
|
||||
},
|
||||
{
|
||||
src: '/teach/inspire-learners.svg',
|
||||
src: 'https://assets.cdn.clsrio.com/www/teach/inspire-learners.svg',
|
||||
header: 'Inspire learners',
|
||||
subText: 'Your opportunity to inspire thousands of learners to achieve dreams and academic pursue exellence'
|
||||
}
|
||||
@@ -93,14 +93,14 @@
|
||||
</div>
|
||||
|
||||
<div class=" ">
|
||||
<img src="/teach/teacher-hero.png" alt="" class="w-full" />
|
||||
<img src="https://assets.cdn.clsrio.com/www/teach/teacher-hero.png" alt="" class="w-full" />
|
||||
</div>
|
||||
</PageHeader>
|
||||
|
||||
<div class="mx-auto mt-10">
|
||||
<div class="border-b border-slate-100 px-[10%] pb-10">
|
||||
<h1 class="flex items-center justify-center gap-3 pb-28 text-center text-3xl">
|
||||
Why you should teach with us? <img src="/teach/star.svg" alt="" />
|
||||
Why you should teach with us? <img src="https://assets.cdn.clsrio.com/www/teach/star.svg" alt="" />
|
||||
</h1>
|
||||
|
||||
<div class="mt-10 flex flex-wrap justify-center lg:justify-between">
|
||||
@@ -122,7 +122,7 @@
|
||||
|
||||
<div class="mt-10 px-[10%] py-10">
|
||||
<h1 class="mb-28 flex items-center justify-center gap-3 text-center text-3xl">
|
||||
How to get started <img src="/teach/thumbs-up.svg" alt="" />
|
||||
How to get started <img src="https://assets.cdn.clsrio.com/www/teach/thumbs-up.svg" alt="" />
|
||||
</h1>
|
||||
|
||||
<div class="mx-auto mt-5 flex flex-wrap justify-between gap-y-10">
|
||||
@@ -154,7 +154,7 @@
|
||||
my students are happy. Love the product
|
||||
</h1>
|
||||
<div class="mt-3 flex flex-row items-center justify-center gap-4">
|
||||
<img src="/teach/user-profile.png" alt="" class="w-8" />
|
||||
<img src="https://assets.cdn.clsrio.com/www/teach/user-profile.png" alt="" class="w-8" />
|
||||
<p class="text-sm">
|
||||
<span class="mr-2 font-semibold"> Bilik Diana </span> English tutor
|
||||
</p>
|
||||
|
||||
Reference in New Issue
Block a user