feat: enhance API and middleware functionality: add public API routes, implement program and course member checks, and improve rate limiting for invite acceptance. Update OpenAPI spec generation to focus on public API endpoints and add new middleware for automation key scopes. Include new documentation for lesson AI features and public API tests.
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
<script>
|
||||
import { BlurFade } from '@cio/ui/custom/animation/blurfade';
|
||||
import { BorderBeam } from '@cio/ui/custom/animation/border-beam';
|
||||
|
||||
const aiFeatures = [
|
||||
{
|
||||
icon: '⚡',
|
||||
title: 'Create a full course in seconds',
|
||||
description:
|
||||
'Tell your agent what to build. It creates the course, writes the lessons, and adds quizzes. What used to take days now takes seconds.'
|
||||
},
|
||||
{
|
||||
icon: '🔄',
|
||||
title: 'Update content instantly',
|
||||
description:
|
||||
'Policies changed? Tell your agent to update the course. It rewrites the affected lessons and adjusts the quiz questions to match.'
|
||||
},
|
||||
{
|
||||
icon: '📄',
|
||||
title: 'Turn any doc into training',
|
||||
description:
|
||||
'Point your agent at a Notion page, Google Doc, or PDF. It reads the source and builds a structured course with assessments.'
|
||||
}
|
||||
];
|
||||
|
||||
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' }
|
||||
];
|
||||
</script>
|
||||
|
||||
<section
|
||||
id="ai"
|
||||
class="relative overflow-hidden bg-linear-to-br from-gray-950 to-[#0f1629] px-6 py-16 text-white lg:px-12 lg:py-24"
|
||||
>
|
||||
<div
|
||||
class="pointer-events-none absolute -top-[200px] -right-[200px] h-[600px] w-[600px] bg-[radial-gradient(circle,rgba(2,51,189,0.15)_0%,transparent_70%)]"
|
||||
></div>
|
||||
|
||||
<div class="mx-auto max-w-[1100px]">
|
||||
<div class="grid grid-cols-1 items-center gap-12 lg:grid-cols-2 lg:gap-20">
|
||||
<div>
|
||||
<BlurFade once>
|
||||
<div class="mb-3.5 text-xs font-medium tracking-widest text-blue-400 uppercase">AI-Powered Content</div>
|
||||
<h2 class="mb-4 text-[clamp(2rem,3vw,2.8rem)] leading-[1.15] font-medium tracking-tight text-white">
|
||||
Let your agent do<br />the course building.
|
||||
</h2>
|
||||
<p class="mb-14 max-w-[520px] text-base leading-relaxed text-gray-500 lg:text-lg">
|
||||
Connect your favorite coding agent to ClassroomIO via MCP. Create, update, and publish entire courses from
|
||||
your terminal in seconds.
|
||||
</p>
|
||||
</BlurFade>
|
||||
|
||||
<div class="flex flex-col gap-6">
|
||||
{#each aiFeatures as feature, i}
|
||||
<BlurFade delay={0.15 * i} once>
|
||||
<div class="flex items-start gap-4 rounded-xl border border-white/[0.08] bg-white/[0.04] p-6">
|
||||
<div class="flex h-11 w-11 shrink-0 items-center justify-center rounded-lg bg-blue-700/20 text-2xl">
|
||||
{feature.icon}
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="mb-1.5 text-sm font-medium text-white">{feature.title}</h4>
|
||||
<p class="text-sm leading-relaxed text-gray-500">{feature.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</BlurFade>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<BlurFade delay={0.2} once>
|
||||
<div>
|
||||
<!-- Code Block -->
|
||||
<div class="relative overflow-hidden rounded-2xl border border-gray-800 bg-[#0d0d0d]">
|
||||
<BorderBeam size={200} duration={10} colorFrom="#0233BD" colorTo="#6b8fff" />
|
||||
<div class="flex items-center gap-2 border-b border-gray-800 bg-gray-900 px-5 py-3.5">
|
||||
<div class="h-2.5 w-2.5 rounded-full bg-red-400"></div>
|
||||
<div class="h-2.5 w-2.5 rounded-full bg-yellow-400"></div>
|
||||
<div class="h-2.5 w-2.5 rounded-full bg-green-500"></div>
|
||||
<span class="ml-2 text-xs text-gray-600">mcp.json</span>
|
||||
</div>
|
||||
<div class="p-6 font-mono text-xs leading-loose whitespace-pre text-gray-400 lg:text-sm">
|
||||
{'{'}<br />{' '}<span class="text-blue-400">"mcpServers"</span>: {'{'}<br />{' '}<span
|
||||
class="text-blue-400">"classroomio"</span
|
||||
>: {'{'}<br />{' '}<span class="text-blue-400">"command"</span>:
|
||||
<span class="text-green-400">"npx"</span>,<br />{' '}<span class="text-blue-400">"args"</span>:
|
||||
[<span class="text-green-400">"-y"</span>, <span class="text-green-400">"@classroomio/mcp"</span>],<br
|
||||
/>{' '}<span class="text-blue-400">"env"</span>: {'{'}<br />{' '}<span
|
||||
class="text-blue-400">"CLASSROOMIO_API_URL"</span
|
||||
>: <span class="text-green-400">"https://api.classroomio.com"</span>,<br />{' '}<span
|
||||
class="text-blue-400">"CLASSROOMIO_API_KEY"</span
|
||||
>: <span class="text-green-400">"<your-mcp-key>"</span><br />{' }'}<br />{' }'}<br
|
||||
/>{' }'}<br />{'}'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Supported Agents -->
|
||||
<div class="mt-6">
|
||||
<div class="mb-3 text-xs tracking-wider text-gray-600 uppercase">Works with</div>
|
||||
<div class="flex flex-wrap gap-3">
|
||||
{#each agents as agent}
|
||||
<div
|
||||
class="flex items-center gap-2 rounded-full border border-white/[0.08] bg-white/[0.06] px-3.5 py-2"
|
||||
>
|
||||
<img src={agent.logo} alt="{agent.name} logo" class="h-5 w-5 rounded-full" />
|
||||
<span class="text-xs text-gray-300">{agent.name}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BlurFade>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,57 @@
|
||||
<script>
|
||||
const integrations = [
|
||||
{
|
||||
icon: '🔌',
|
||||
title: 'REST API',
|
||||
description:
|
||||
'Full API access to every object in your LMS. Create users, enroll learners, pull completions. All programmatically, at scale.'
|
||||
},
|
||||
{
|
||||
icon: '⚡',
|
||||
title: 'Zapier Integration',
|
||||
comingSoon: true,
|
||||
description:
|
||||
'Connect to 6,000+ apps without writing a line of code. Auto-enroll from your CRM, send Slack alerts on completion, update your spreadsheet.'
|
||||
},
|
||||
{
|
||||
icon: '🪝',
|
||||
title: 'Webhooks',
|
||||
comingSoon: true,
|
||||
description:
|
||||
'Real-time event notifications for every action. Course enrolled, lesson completed, certificate issued. Push to any endpoint instantly.'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<section class="bg-gray-50 px-6 py-16 lg:px-12 lg:py-24">
|
||||
<div class="mx-auto max-w-[1100px]">
|
||||
<div class="mb-3.5 text-xs font-medium tracking-widest text-blue-700 uppercase">Automate the boring parts</div>
|
||||
<h2 class="mb-4 text-[clamp(2rem,3vw,2.8rem)] leading-[1.15] font-medium tracking-tight">
|
||||
Set it up once.<br />Let it run.
|
||||
</h2>
|
||||
<p class="mb-14 max-w-[520px] text-base leading-relaxed text-gray-500 lg:text-lg">
|
||||
Connect ClassroomIO to everything you already use. New hire joins Slack? They're enrolled. Course completed? Your
|
||||
HRIS knows.
|
||||
</p>
|
||||
|
||||
<div class="grid grid-cols-1 gap-5 md:grid-cols-3">
|
||||
{#each integrations as item}
|
||||
<div
|
||||
class="rounded-2xl border border-gray-200 bg-white p-8 transition-all duration-200 hover:border-gray-950 hover:shadow-lg hover:shadow-black/5"
|
||||
>
|
||||
<div class="mb-4 text-3xl">{item.icon}</div>
|
||||
<h3 class="mb-2 text-base font-medium">
|
||||
{item.title}
|
||||
{#if item.comingSoon}
|
||||
<span
|
||||
class="ml-1 rounded-full bg-blue-700 px-1.5 py-0.5 align-middle text-[0.6rem] tracking-wide text-white uppercase"
|
||||
>Soon</span
|
||||
>
|
||||
{/if}
|
||||
</h3>
|
||||
<p class="text-sm leading-relaxed text-gray-500">{item.description}</p>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,57 @@
|
||||
<script>
|
||||
import { BlurFade } from '@cio/ui/custom/animation/blurfade';
|
||||
import { Meteors } from '@cio/ui/custom/animation/meteors';
|
||||
|
||||
const steps = [
|
||||
{
|
||||
number: '01',
|
||||
title: 'Invite your team',
|
||||
description:
|
||||
'Add users individually, bulk import via CSV, or connect your HRIS. Assign courses automatically based on role or department.'
|
||||
},
|
||||
{
|
||||
number: '02',
|
||||
title: 'Publish your courses',
|
||||
description:
|
||||
'Build courses with video, text, quizzes, and assignments. Set pass thresholds, enforce order, and control who sees what.'
|
||||
},
|
||||
{
|
||||
number: '03',
|
||||
title: 'Set certification rules',
|
||||
description:
|
||||
'Define expiry dates, renewal requirements, and passing scores. Issue branded certificates automatically on completion.'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<section id="features" class="bg-gray-950 px-6 py-16 text-white lg:px-12 lg:py-24">
|
||||
<div class="mx-auto max-w-[1100px]">
|
||||
<BlurFade once>
|
||||
<div class="mb-3.5 text-xs font-medium tracking-widest text-blue-400 uppercase">Certifications & Compliance</div>
|
||||
<h2 class="mb-4 text-[clamp(2rem,3vw,2.8rem)] leading-[1.15] font-medium tracking-tight text-white">
|
||||
Go from zero to certified<br />in one afternoon.
|
||||
</h2>
|
||||
<p class="mb-14 max-w-[520px] text-base leading-relaxed text-gray-500 lg:text-lg">
|
||||
Everything you need to run a serious certification program. No duct tape, no spreadsheets, no chasing people
|
||||
down.
|
||||
</p>
|
||||
</BlurFade>
|
||||
|
||||
<div class="grid grid-cols-1 gap-0.5 overflow-hidden rounded-2xl border border-gray-800 bg-gray-800 md:grid-cols-3">
|
||||
{#each steps as step, i}
|
||||
<BlurFade delay={0.1 * i} once>
|
||||
<div
|
||||
class="relative overflow-hidden bg-gray-900 p-8 transition-colors duration-200 hover:bg-gray-900/80 lg:p-9"
|
||||
>
|
||||
<Meteors number={6} />
|
||||
<div class="mb-3.5 text-[2.8rem] leading-none font-medium text-blue-700 italic">
|
||||
{step.number}
|
||||
</div>
|
||||
<h3 class="mb-2.5 text-base font-medium text-white">{step.title}</h3>
|
||||
<p class="text-sm leading-relaxed text-gray-500">{step.description}</p>
|
||||
</div>
|
||||
</BlurFade>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,72 @@
|
||||
<script>
|
||||
import { BlurFade } from '@cio/ui/custom/animation/blurfade';
|
||||
|
||||
const deployOptions = [
|
||||
{
|
||||
icon: '🚂',
|
||||
title: 'Railway',
|
||||
description: 'One-click deploy with our Railway template. Live in under 3 minutes.',
|
||||
href: 'https://railway.app'
|
||||
},
|
||||
{
|
||||
icon: '🐳',
|
||||
title: 'Docker Compose',
|
||||
description: 'Standard Docker setup for any Linux server or VPS. Full control.',
|
||||
href: '/github'
|
||||
},
|
||||
{
|
||||
icon: '❄️',
|
||||
title: 'Coolify',
|
||||
description: 'Self-hosted Heroku alternative. Deploy ClassroomIO alongside your stack.',
|
||||
href: 'https://coolify.io'
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<section id="deploy" class="bg-white px-6 py-16 lg:px-12 lg:py-24">
|
||||
<div class="mx-auto max-w-[1100px]">
|
||||
<div class="grid grid-cols-1 items-center gap-12 lg:grid-cols-2 lg:gap-20">
|
||||
<BlurFade once>
|
||||
<div>
|
||||
<div class="mb-3.5 text-xs font-medium tracking-widest text-blue-700 uppercase">Deploy to your servers</div>
|
||||
<h2 class="mb-4 text-[clamp(2rem,3vw,2.8rem)] leading-[1.15] font-medium tracking-tight">
|
||||
Your data.<br />Your servers.<br />Your call.
|
||||
</h2>
|
||||
<p class="mb-8 max-w-[520px] text-base leading-relaxed text-gray-500 lg:text-lg">
|
||||
No SaaS lock-in. No per-seat pricing surprises. Deploy ClassroomIO wherever you run your infrastructure.
|
||||
Minutes, not days.
|
||||
</p>
|
||||
|
||||
<div class="mt-3 rounded-xl border border-gray-200 bg-gray-50 p-5">
|
||||
<div class="mb-2.5 text-xs font-medium tracking-wider text-gray-500 uppercase">One-line deploy</div>
|
||||
<code class="font-mono text-sm text-gray-950">docker compose up -d</code>
|
||||
</div>
|
||||
</div>
|
||||
</BlurFade>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
{#each deployOptions as option, i}
|
||||
<BlurFade delay={0.1 * i} once>
|
||||
<a
|
||||
href={option.href}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="flex items-center gap-5 rounded-xl border-[1.5px] border-gray-200 p-6 text-gray-950 no-underline transition-all duration-200 hover:border-blue-700 hover:bg-blue-50"
|
||||
>
|
||||
<div
|
||||
class="flex h-11 w-11 shrink-0 items-center justify-center rounded-lg border border-gray-200 bg-gray-50 text-xl"
|
||||
>
|
||||
{option.icon}
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="mb-0.5 text-sm font-medium">{option.title}</h4>
|
||||
<p class="text-sm text-gray-500">{option.description}</p>
|
||||
</div>
|
||||
<span class="ml-auto text-lg text-gray-400">→</span>
|
||||
</a>
|
||||
</BlurFade>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,263 @@
|
||||
<script>
|
||||
import { BlurFade } from '@cio/ui/custom/animation/blurfade';
|
||||
import { BorderBeam } from '@cio/ui/custom/animation/border-beam';
|
||||
import { DotPattern } from '@cio/ui/custom/animation/dot-pattern';
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: '🏢',
|
||||
title: 'Multi-tenancy',
|
||||
description: 'Isolated environments for each department, team, or client organization.'
|
||||
},
|
||||
{
|
||||
icon: '📋',
|
||||
title: 'Audit Logs',
|
||||
description: 'Full visibility into every action, login, and change across your platform.'
|
||||
},
|
||||
{
|
||||
icon: '🔌',
|
||||
title: 'API Access',
|
||||
description: 'Programmatic control over users, courses, enrollments, and completions.'
|
||||
},
|
||||
{
|
||||
icon: '🔐',
|
||||
title: 'RBAC',
|
||||
description: 'Fine-grained roles and permissions for admins, teachers, and learners.'
|
||||
},
|
||||
{
|
||||
icon: '🔑',
|
||||
title: 'SSO / OIDC',
|
||||
description: 'Single sign-on with your identity provider. SAML and OIDC supported.'
|
||||
},
|
||||
{
|
||||
icon: '🛡️',
|
||||
title: 'SLA & Support',
|
||||
description: 'Guaranteed uptime, priority assistance, and a dedicated point of contact.'
|
||||
},
|
||||
{
|
||||
icon: '🎨',
|
||||
title: 'White Labeling',
|
||||
description: 'Fully customize the look and feel so learners only see your brand.'
|
||||
}
|
||||
];
|
||||
|
||||
const uiComponents = [
|
||||
{ label: 'Button', category: 'Atom' },
|
||||
{ label: 'Card', category: 'Molecule' },
|
||||
{ label: 'Dialog', category: 'Molecule' },
|
||||
{ label: 'Input', category: 'Atom' },
|
||||
{ label: 'Badge', category: 'Atom' },
|
||||
{ label: 'Table', category: 'Molecule' },
|
||||
{ label: 'Tabs', category: 'Atom' },
|
||||
{ label: 'Select', category: 'Atom' },
|
||||
{ label: 'Sidebar', category: 'Molecule' },
|
||||
{ label: 'Field', category: 'Molecule' },
|
||||
{ label: 'Editor', category: 'Molecule' },
|
||||
{ label: 'Accordion', category: 'Atom' }
|
||||
];
|
||||
</script>
|
||||
|
||||
<section class="relative overflow-hidden bg-gray-950 px-6 py-16 text-white lg:px-12 lg:py-24">
|
||||
<DotPattern
|
||||
fillColor="rgb(255 255 255 / 0.05)"
|
||||
class="absolute inset-0 h-full w-full [mask-image:radial-gradient(600px_circle_at_center,white,transparent)]"
|
||||
/>
|
||||
|
||||
<div class="relative z-10 mx-auto max-w-[1100px]">
|
||||
<BlurFade once>
|
||||
<div class="mb-3.5 text-xs font-medium tracking-widest text-blue-400 uppercase">Enterprise</div>
|
||||
<h2 class="mb-4 text-[clamp(2rem,3vw,2.8rem)] leading-[1.15] font-medium tracking-tight text-white">
|
||||
Enterprise-grade, out of the box.
|
||||
</h2>
|
||||
<p class="mb-6 max-w-[560px] text-base leading-relaxed text-gray-500 lg:text-lg">
|
||||
Everything in the open-source core, plus the control, security, and support that compliance teams need at scale.
|
||||
</p>
|
||||
|
||||
<button
|
||||
data-cal-link="classroomio/enterprise"
|
||||
data-cal-config="'layout':'month_view'"
|
||||
class="mb-14 inline-flex cursor-pointer items-center gap-2 rounded-lg bg-blue-700 px-6 py-3 text-sm font-medium text-white transition-all duration-200 hover:bg-blue-800"
|
||||
>
|
||||
Talk to us →
|
||||
</button>
|
||||
</BlurFade>
|
||||
|
||||
<div class="grid grid-cols-1 gap-4 sm:grid-cols-2 lg:grid-cols-4">
|
||||
{#each features as feature, i}
|
||||
<BlurFade delay={0.08 * i} once>
|
||||
<div
|
||||
class="rounded-xl border border-white/[0.08] bg-white/[0.04] p-5 transition-all duration-200 hover:bg-white/[0.06]"
|
||||
>
|
||||
<div class="mb-3 text-2xl">{feature.icon}</div>
|
||||
<h3 class="mb-1.5 text-sm font-medium text-white">{feature.title}</h3>
|
||||
<p class="text-xs leading-relaxed text-gray-500">{feature.description}</p>
|
||||
</div>
|
||||
</BlurFade>
|
||||
{/each}
|
||||
</div>
|
||||
|
||||
<!-- Composable UI -->
|
||||
<div class="mt-20">
|
||||
<BlurFade delay={0.1} once>
|
||||
<div class="grid grid-cols-1 items-center gap-12 lg:grid-cols-2 lg:gap-20">
|
||||
<div>
|
||||
<div class="mb-3.5 text-xs font-medium tracking-widest text-blue-400 uppercase">Design System</div>
|
||||
<h3 class="mb-4 text-[clamp(1.5rem,2.5vw,2.2rem)] leading-[1.2] font-medium tracking-tight text-white">
|
||||
Composable UI.<br />Build it your way.
|
||||
</h3>
|
||||
<p class="mb-6 max-w-[480px] text-base leading-relaxed text-gray-500 lg:text-lg">
|
||||
A library of 50+ accessible, themeable components built on Svelte 5 and Tailwind. Atoms, molecules, and
|
||||
full templates you can compose into any learning experience.
|
||||
</p>
|
||||
|
||||
<div class="mb-8 flex flex-wrap gap-2">
|
||||
<span
|
||||
class="rounded-full border border-white/[0.1] bg-white/[0.05] px-3 py-1 text-xs font-medium text-gray-300"
|
||||
>
|
||||
shadcn-svelte
|
||||
</span>
|
||||
<span
|
||||
class="rounded-full border border-white/[0.1] bg-white/[0.05] px-3 py-1 text-xs font-medium text-gray-300"
|
||||
>
|
||||
Tailwind v4
|
||||
</span>
|
||||
<span
|
||||
class="rounded-full border border-white/[0.1] bg-white/[0.05] px-3 py-1 text-xs font-medium text-gray-300"
|
||||
>
|
||||
Accessible
|
||||
</span>
|
||||
<span
|
||||
class="rounded-full border border-white/[0.1] bg-white/[0.05] px-3 py-1 text-xs font-medium text-gray-300"
|
||||
>
|
||||
Themeable
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<a
|
||||
href="https://ui.classroomio.dev"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="inline-flex items-center gap-2 rounded-lg border border-white/[0.15] bg-white/[0.06] px-5 py-2.5 text-sm font-medium text-white no-underline transition-all duration-200 hover:border-blue-500/40 hover:bg-white/[0.1]"
|
||||
>
|
||||
Explore the design system
|
||||
<span class="text-blue-400">→</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="relative">
|
||||
<div class="relative overflow-hidden rounded-2xl border border-white/[0.08] bg-white/[0.03] p-6">
|
||||
<BorderBeam colorFrom="#3b82f6" colorTo="#0233BD" size={200} duration={8} />
|
||||
|
||||
<div class="mb-5 flex items-center gap-2">
|
||||
<div class="h-3 w-3 rounded-full bg-white/[0.15]"></div>
|
||||
<div class="h-3 w-3 rounded-full bg-white/[0.1]"></div>
|
||||
<div class="h-3 w-3 rounded-full bg-white/[0.1]"></div>
|
||||
<span class="ml-2 text-xs text-gray-600">@cio/ui</span>
|
||||
</div>
|
||||
|
||||
<!-- Mini component showcase -->
|
||||
<div class="space-y-4">
|
||||
<!-- Row 1: Buttons -->
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<div class="rounded-md bg-blue-700 px-3 py-1.5 text-xs font-medium text-white">Primary</div>
|
||||
<div class="rounded-md border border-white/[0.15] px-3 py-1.5 text-xs font-medium text-gray-300">
|
||||
Outline
|
||||
</div>
|
||||
<div class="rounded-md bg-white/[0.08] px-3 py-1.5 text-xs font-medium text-gray-400">Ghost</div>
|
||||
<div class="rounded-full bg-blue-500/15 px-2.5 py-0.5 text-[10px] font-medium text-blue-400">
|
||||
Badge
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Row 2: Input + Select mock -->
|
||||
<div class="flex gap-2">
|
||||
<div
|
||||
class="flex-1 rounded-md border border-white/[0.1] bg-white/[0.04] px-3 py-2 text-xs text-gray-500"
|
||||
>
|
||||
Search courses...
|
||||
</div>
|
||||
<div
|
||||
class="flex items-center gap-1 rounded-md border border-white/[0.1] bg-white/[0.04] px-3 py-2 text-xs text-gray-500"
|
||||
>
|
||||
Select
|
||||
<svg
|
||||
class="h-3 w-3 text-gray-600"
|
||||
viewBox="0 0 12 12"
|
||||
fill="none"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
>
|
||||
<path d="M3 4.5L6 7.5L9 4.5" />
|
||||
</svg>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Row 3: Card preview -->
|
||||
<div class="rounded-lg border border-white/[0.08] bg-white/[0.03] p-3">
|
||||
<div class="mb-2 flex items-center gap-2">
|
||||
<div class="h-6 w-6 rounded-full bg-blue-700/30"></div>
|
||||
<div>
|
||||
<div class="text-xs font-medium text-gray-300">Card Component</div>
|
||||
<div class="text-[10px] text-gray-600">Composable header, body, footer</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-1.5">
|
||||
<div class="h-1 flex-1 rounded-full bg-blue-700/30"></div>
|
||||
<div class="h-1 w-8 rounded-full bg-white/[0.06]"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Row 4: Toggle + Switch + Checkbox -->
|
||||
<div class="flex items-center gap-4">
|
||||
<div class="flex items-center gap-1.5">
|
||||
<div class="h-4 w-7 rounded-full bg-blue-700 p-0.5">
|
||||
<div class="h-3 w-3 translate-x-3 rounded-full bg-white"></div>
|
||||
</div>
|
||||
<span class="text-[10px] text-gray-500">Switch</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<div class="flex h-4 w-4 items-center justify-center rounded border border-blue-700 bg-blue-700">
|
||||
<svg class="h-2.5 w-2.5 text-white" viewBox="0 0 12 12" fill="none">
|
||||
<path d="M2.5 6L5 8.5L9.5 3.5" stroke="currentColor" stroke-width="1.5" />
|
||||
</svg>
|
||||
</div>
|
||||
<span class="text-[10px] text-gray-500">Checkbox</span>
|
||||
</div>
|
||||
<div class="flex items-center gap-1.5">
|
||||
<div class="flex h-4 w-4 items-center justify-center rounded-full border border-blue-700">
|
||||
<div class="h-2 w-2 rounded-full bg-blue-700"></div>
|
||||
</div>
|
||||
<span class="text-[10px] text-gray-500">Radio</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Component tags floating below -->
|
||||
<div class="mt-4 flex flex-wrap items-center gap-1.5">
|
||||
{#each uiComponents as comp, i}
|
||||
<BlurFade delay={0.04 * i} once>
|
||||
<span
|
||||
class="rounded-md border px-2 py-0.5 text-[10px] font-medium transition-colors duration-200 {comp.category ===
|
||||
'Atom'
|
||||
? 'border-blue-500/20 bg-blue-500/10 text-blue-400'
|
||||
: 'border-purple-500/20 bg-purple-500/10 text-purple-400'}"
|
||||
>
|
||||
{comp.label}
|
||||
</span>
|
||||
</BlurFade>
|
||||
{/each}
|
||||
<BlurFade delay={0.04 * uiComponents.length} once>
|
||||
<span
|
||||
class="rounded-md border border-white/[0.08] bg-white/[0.04] px-2 py-0.5 text-[10px] font-medium text-gray-500"
|
||||
>
|
||||
+48 more
|
||||
</span>
|
||||
</BlurFade>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BlurFade>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,71 @@
|
||||
<script>
|
||||
import { BlurFade } from '@cio/ui/custom/animation/blurfade';
|
||||
|
||||
const features = [
|
||||
{
|
||||
icon: '🎨',
|
||||
title: 'Full Theming',
|
||||
description:
|
||||
"Match your brand exactly. Custom colors, fonts, logos, and layouts. Your learners will never know it's ClassroomIO under the hood.",
|
||||
tags: ['Custom colors', 'Logo upload', 'Font control']
|
||||
},
|
||||
{
|
||||
icon: '🌐',
|
||||
title: 'Custom Domain',
|
||||
description:
|
||||
'Serve your LMS from learn.yourcompany.com. Full SSL, zero ClassroomIO branding. Just your platform, your way.',
|
||||
tags: ['SSL included', 'White label', 'DNS setup guide']
|
||||
},
|
||||
{
|
||||
icon: '⚙️',
|
||||
title: 'Deep LMS Customization',
|
||||
description:
|
||||
'Modern codebase means any developer can go in and change anything. No Moodle plugin archaeology. No undocumented hacks.',
|
||||
tags: ['Modern stack', 'Clean codebase', 'Extensible']
|
||||
},
|
||||
{
|
||||
icon: '📊',
|
||||
title: 'Manager Dashboards',
|
||||
description:
|
||||
'See exactly where your team stands. Completion rates, overdue courses, certificate expiry dates, all in one view and exportable to CSV.',
|
||||
tags: ['Team views', 'CSV export', 'Audit logs']
|
||||
}
|
||||
];
|
||||
</script>
|
||||
|
||||
<section class="bg-gray-50 px-6 py-16 lg:px-12 lg:py-24">
|
||||
<div class="mx-auto max-w-[1100px]">
|
||||
<BlurFade once>
|
||||
<div class="mb-3.5 text-xs font-medium tracking-widest text-blue-700 uppercase">Make it yours</div>
|
||||
<h2 class="mb-4 text-[clamp(2rem,3vw,2.8rem)] leading-[1.15] font-medium tracking-tight">
|
||||
Your brand.<br />Your domain. Your rules.
|
||||
</h2>
|
||||
<p class="mb-14 max-w-[520px] text-base leading-relaxed text-gray-500 lg:text-lg">
|
||||
ClassroomIO bends to fit your organization, not the other way around.
|
||||
</p>
|
||||
</BlurFade>
|
||||
|
||||
<div class="grid grid-cols-1 gap-6 md:grid-cols-2">
|
||||
{#each features as feature, i}
|
||||
<BlurFade delay={0.1 * i} once>
|
||||
<div class="rounded-2xl border border-gray-200 bg-white p-8 lg:p-9">
|
||||
<div class="mb-5 flex h-12 w-12 items-center justify-center rounded-xl bg-blue-50 text-2xl">
|
||||
{feature.icon}
|
||||
</div>
|
||||
<h3 class="mb-2.5 text-xl font-medium tracking-tight">{feature.title}</h3>
|
||||
<p class="mb-5 text-sm leading-relaxed text-gray-500">{feature.description}</p>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{#each feature.tags as tag}
|
||||
<span
|
||||
class="rounded-full border border-gray-200 bg-gray-50 px-2.5 py-1 text-xs font-medium text-gray-500"
|
||||
>
|
||||
{tag}
|
||||
</span>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</BlurFade>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -0,0 +1,24 @@
|
||||
<section class="bg-gray-50 px-6 py-16 text-center lg:px-12 lg:py-24">
|
||||
<h2 class="mb-4 text-[clamp(2rem,3.5vw,3rem)] font-bold tracking-tight">
|
||||
Ready to replace Moodle<br />with something you'll <em class="text-blue-700 italic">actually enjoy?</em>
|
||||
</h2>
|
||||
<p class="mx-auto mb-9 max-w-[480px] text-base text-gray-500 lg:text-lg">
|
||||
Get up and running in an afternoon. No vendor calls, no implementation fees, no surprises.
|
||||
</p>
|
||||
<div class="mb-9 flex flex-wrap justify-center gap-3.5">
|
||||
<a
|
||||
href="/signup"
|
||||
class="inline-flex items-center gap-2 rounded-lg bg-gray-950 px-7 py-3.5 text-sm font-semibold text-white no-underline transition-all duration-200 hover:-translate-y-0.5 hover:bg-blue-700 lg:text-base"
|
||||
>
|
||||
Get Started Free →
|
||||
</a>
|
||||
<button
|
||||
data-cal-link="classroomio/demo"
|
||||
data-cal-config="'layout':'month_view'"
|
||||
class="cursor-pointer rounded-lg border-[1.5px] border-gray-200 bg-transparent px-7 py-3.5 text-sm font-medium text-gray-950 transition-all duration-200 hover:border-gray-950 lg:text-base"
|
||||
>
|
||||
Book a Demo
|
||||
</button>
|
||||
</div>
|
||||
<div class="text-sm text-gray-500">Open source · Self-hosted · No credit card required</div>
|
||||
</section>
|
||||
@@ -11,7 +11,7 @@
|
||||
<p class="mr-2 mb-5 text-sm leading-7 tracking-wide text-gray-600 lg:text-base lg:leading-7">
|
||||
The Open Source Learning Management System for Companies
|
||||
<br />
|
||||
ClassroomIO is the easiest way to grow your teaching business.
|
||||
Nail your compliance training and your certification program.
|
||||
</p>
|
||||
<!-- <a
|
||||
href="https://www.producthunt.com/posts/classroomio?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-classroomio"
|
||||
@@ -50,19 +50,16 @@
|
||||
<p class="mb-3 text-base leading-6 font-semibold text-gray-900 lg:mb-10 lg:text-base">Product</p>
|
||||
<ul class="space-y-2 lg:space-y-4">
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/#coursemanagement"> Course Management </a>
|
||||
<a href="/#features"> Certifications </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/#customization"> Customizations </a>
|
||||
<a href="/#ai"> AI Content </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/#collaboration"> Forum </a>
|
||||
<a href="/#deploy"> Deploy </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/#ai"> AI Lesson Planner </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="/#student-dashboard"> Student Dashboard </a>
|
||||
<a href="/#testimonial"> Testimonials </a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -113,17 +110,13 @@
|
||||
<a href="mailto:[email protected]" target="_blank"> Support </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="https://app.enzuzo.com/policies/privacy/958fc978-5477-11ee-a03b-7b111830c594" target="_blank">
|
||||
Privacy policy
|
||||
</a>
|
||||
<a href="/privacy"> Privacy policy </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a target="_blank" href="https://classroomio.com/docs/quickstart/signup"> Getting Started </a>
|
||||
</li>
|
||||
<li class="text-sm leading-6 tracking-wide text-gray-600 hover:text-gray-900 lg:text-base">
|
||||
<a href="https://app.enzuzo.com/policies/tos/958fc978-5477-11ee-a03b-7b111830c594" target="_blank">
|
||||
Terms of use
|
||||
</a>
|
||||
<a href="/tos"> Terms of use </a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
@@ -1,220 +1,137 @@
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { sineInOut } from 'svelte/easing';
|
||||
import { PUBLIC_ENABLE_USERS_COMPANIES } from '$env/static/public';
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
|
||||
const names = [
|
||||
{ label: 'Audience', color: '#3ADFEC' },
|
||||
{ label: 'Employees', color: '#BF0696' },
|
||||
{ label: 'Customers', color: '#0233BD' },
|
||||
{ label: 'Students', color: '#9747FF' }
|
||||
];
|
||||
let animate = $state(false);
|
||||
let titleIndex = $state(0);
|
||||
let timeout: NodeJS.Timeout;
|
||||
|
||||
onMount(() => {
|
||||
setTimeout(() => {
|
||||
animate = true;
|
||||
}, 70);
|
||||
|
||||
timeout = setInterval(() => {
|
||||
const nextIndex = titleIndex + 1;
|
||||
titleIndex = names[nextIndex] ? nextIndex : 0;
|
||||
}, 3000);
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
clearTimeout(timeout);
|
||||
});
|
||||
<script>
|
||||
import { BlurFade } from '@cio/ui/custom/animation/blurfade';
|
||||
import { BorderBeam } from '@cio/ui/custom/animation/border-beam';
|
||||
import { Badge } from '@cio/ui/base/badge';
|
||||
</script>
|
||||
|
||||
<div class="hero-bg relative h-full w-full border-b-2 bg-[#F5F8FE] pt-18 text-center">
|
||||
<div class="w-full pt-24">
|
||||
<div class="mb-10 ml-[5%] flex w-full items-center justify-start lg:ml-0 lg:justify-center">
|
||||
<a
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow"
|
||||
href="/github"
|
||||
style="color: rgb(75, 85, 99);"
|
||||
class="rounded-full border-2 border-[#C2D2FF] bg-[#DCE5FF] px-4 py-1 text-sm font-medium text-[#4B5563] hover:underline"
|
||||
>We are <span class="ui:text-primary">100%</span> open source</a
|
||||
>
|
||||
</div>
|
||||
<section class="px-6 pt-32 pb-16 lg:px-12 lg:pt-40 lg:pb-24">
|
||||
<div class="mx-auto grid max-w-[1100px] grid-cols-1 items-center gap-12 lg:grid-cols-2 lg:gap-20">
|
||||
<div>
|
||||
<BlurFade delay={0} once>
|
||||
<a href="/blog/learn-from-the-best" class="mb-7 inline-block">
|
||||
<Badge variant="secondary" class="gap-2! px-3.5! py-1.5! text-xs! underline!">
|
||||
<span class="relative flex h-2 w-2">
|
||||
<span class="absolute inline-flex h-full w-full animate-ping rounded-full bg-green-400 opacity-75"></span>
|
||||
<span class="relative inline-flex h-2 w-2 rounded-full bg-green-500"></span>
|
||||
</span>
|
||||
Introducing ClassroomIO Version 2 →
|
||||
</Badge>
|
||||
</a>
|
||||
</BlurFade>
|
||||
|
||||
<div class="absolute top-[10%] left-[5%] hidden w-[90%] justify-between lg:flex">
|
||||
{#if animate}
|
||||
<div
|
||||
class="relative rotate-12 transition-all hover:scale-110"
|
||||
transition:fly={{ y: 100, delay: 0, easing: sineInOut }}
|
||||
>
|
||||
<BlurFade delay={0.1} once>
|
||||
<h1 class="mb-6 text-[clamp(2.4rem,4vw,3.4rem)] leading-[1.12] font-medium tracking-tight text-gray-950">
|
||||
Nail your compliance training and your
|
||||
<em class="text-blue-700 not-italic">certification program.</em>
|
||||
</h1>
|
||||
</BlurFade>
|
||||
|
||||
<BlurFade delay={0.2} once>
|
||||
<p class="mb-9 max-w-[480px] text-base leading-relaxed text-gray-500 lg:text-lg">
|
||||
ClassroomIO is the open source LMS built for compliance-driven teams. Run your certification programs, track
|
||||
completions, and prove training happened. No Moodle headaches.
|
||||
</p>
|
||||
</BlurFade>
|
||||
|
||||
<BlurFade delay={0.3} once>
|
||||
<div class="flex flex-wrap items-center gap-3.5">
|
||||
<a
|
||||
href="/#collaboration"
|
||||
class="rounded-[4px] border-[1.5px] border-[#3ADFEC] bg-white px-6 py-2 text-lg font-bold text-[#3ADFEC]"
|
||||
>Collaboration</a
|
||||
href="/signup"
|
||||
class="inline-flex items-center gap-2 rounded-lg bg-gray-950 px-7 py-3.5 text-sm font-medium text-white no-underline transition-all duration-200 hover:-translate-y-0.5 hover:bg-blue-700 lg:text-base"
|
||||
>
|
||||
<svg
|
||||
class="absolute -right-1 -bottom-2.5"
|
||||
width="11"
|
||||
height="11"
|
||||
viewBox="0 0 11 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
Get Started Free →
|
||||
</a>
|
||||
<button
|
||||
data-cal-link="classroomio/demo"
|
||||
data-cal-config="'layout':'month_view'"
|
||||
class="cursor-pointer rounded-lg border-[1.5px] border-gray-200 bg-transparent px-7 py-3.5 text-sm font-medium text-gray-950 transition-all duration-200 hover:border-gray-950 lg:text-base"
|
||||
>
|
||||
<rect width="10.9223" height="10.9223" fill="#3ADFEC" />
|
||||
</svg>
|
||||
Book a Demo
|
||||
</button>
|
||||
</div>
|
||||
</BlurFade>
|
||||
|
||||
<div
|
||||
class="relative -rotate-12 transition-all hover:scale-110"
|
||||
transition:fly={{ x: 100, delay: 50, easing: sineInOut }}
|
||||
>
|
||||
<a
|
||||
href="/github"
|
||||
target="_blank"
|
||||
class="rounded-[4px] border-[1.5px] border-[#BF0696] bg-white px-6 py-2 text-lg font-bold text-[#BF0696]"
|
||||
>Open Source</a
|
||||
>
|
||||
<svg
|
||||
class="absolute -right-1 -bottom-2.5"
|
||||
width="11"
|
||||
height="11"
|
||||
viewBox="0 0 11 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="10.9223" height="10.9223" fill="#BF0696" />
|
||||
</svg>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
<div class="w-full">
|
||||
<div class="ml-6 text-left text-2xl font-semibold text-slate-900 lg:text-center lg:text-6xl">
|
||||
<span>Educate Your</span>
|
||||
<div class="mb-2 flex flex-wrap items-center justify-center lg:gap-3">
|
||||
<span
|
||||
class="relative mt-1 mb-0 inline-block h-[40px] w-full overflow-hidden md:mt-0 md:h-[50px] lg:-mb-4 lg:h-[75px] lg:w-[48%] lg:text-center"
|
||||
>
|
||||
{#key titleIndex}
|
||||
<span
|
||||
class="absolute right-[unset] left-0 w-full lg:right-0 lg:left-[unset]"
|
||||
style="color: {names[titleIndex].color}"
|
||||
transition:fly={{ y: 100, delay: 0, easing: sineInOut }}
|
||||
>
|
||||
<span class="m-auto w-full text-center">
|
||||
{names[titleIndex].label}
|
||||
</span>
|
||||
</span>
|
||||
{/key}
|
||||
<BlurFade delay={0.4} once>
|
||||
<div class="mt-7 flex flex-wrap items-center gap-5 text-xs text-gray-500">
|
||||
<span class="flex items-center gap-1.5">
|
||||
<span class="font-medium text-blue-700">✓</span> Open source
|
||||
</span>
|
||||
<span class="flex items-center gap-1.5">
|
||||
<span class="font-medium text-blue-700">✓</span> Self-hosted
|
||||
</span>
|
||||
<span class="flex items-center gap-1.5">
|
||||
<span class="font-medium text-blue-700">✓</span> No per-seat fees
|
||||
</span>
|
||||
</div>
|
||||
<span>from one Platform</span>
|
||||
</div>
|
||||
|
||||
<p class="ui:text-muted-foreground mx-auto mt-10 px-4 md:text-lg lg:mt-6 lg:w-[42%] lg:p-0">
|
||||
ClassroomIO is an open source learning management system for companies. We give you a suite of tools to help you
|
||||
achieve your training, onboarding and certification goals.
|
||||
</p>
|
||||
</BlurFade>
|
||||
</div>
|
||||
|
||||
<div class="absolute top-[30%] left-[5%] hidden w-[90%] justify-between lg:flex">
|
||||
{#if animate}
|
||||
<div
|
||||
class="relative -rotate-12 transition-all hover:scale-110"
|
||||
transition:fly={{ x: -100, delay: 100, easing: sineInOut }}
|
||||
>
|
||||
<a
|
||||
href="/#customization"
|
||||
class="rounded-[4px] border-[1.5px] border-[#0233BD] bg-white px-6 py-2 text-lg font-bold text-[#0233BD]"
|
||||
>
|
||||
Customizable LMS
|
||||
</a>
|
||||
|
||||
<svg
|
||||
class="absolute -right-1 -bottom-2.5"
|
||||
width="11"
|
||||
height="11"
|
||||
viewBox="0 0 11 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="10.9223" height="10.9223" fill="#0233BD" />
|
||||
</svg>
|
||||
<!-- Hero Visual -->
|
||||
<BlurFade delay={0.2} once>
|
||||
<div class="relative overflow-hidden rounded-2xl border border-gray-200 bg-gray-50 shadow-2xl/5">
|
||||
<BorderBeam size={250} duration={12} colorFrom="#0233BD" colorTo="#6b8fff" delay={1} />
|
||||
<div class="flex items-center gap-2 border-b border-gray-200 bg-white px-4 py-3.5">
|
||||
<div class="h-2.5 w-2.5 rounded-full bg-red-400"></div>
|
||||
<div class="h-2.5 w-2.5 rounded-full bg-yellow-400"></div>
|
||||
<div class="h-2.5 w-2.5 rounded-full bg-green-500"></div>
|
||||
</div>
|
||||
<div
|
||||
class="relative rotate-12 transition-all hover:scale-110"
|
||||
transition:fly={{ y: 100, delay: 150, easing: sineInOut }}
|
||||
>
|
||||
<a
|
||||
href="/#ai"
|
||||
class="rounded-[4px] border-[1.5px] border-[#9747FF] bg-white px-6 py-2 text-lg font-bold text-[#9747FF]"
|
||||
>AI Support</a
|
||||
>
|
||||
<div class="p-6">
|
||||
<div class="mb-3.5 text-xs font-medium tracking-wider text-gray-500 uppercase">Team Progress - This Week</div>
|
||||
|
||||
<svg
|
||||
class="absolute -right-1 -bottom-2.5"
|
||||
width="11"
|
||||
height="11"
|
||||
viewBox="0 0 11 11"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<rect width="10.9223" height="10.9223" fill="#9747FF" />
|
||||
</svg>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
<div class="mb-3 flex items-center gap-3.5 rounded-xl border border-gray-200 bg-white p-4">
|
||||
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-blue-50 text-lg">📋</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="mb-1 text-sm font-medium">Annual Compliance Training</div>
|
||||
<div class="h-1 overflow-hidden rounded-full bg-gray-200">
|
||||
<div class="h-full rounded-full bg-blue-700" style="width: 85%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="shrink-0 rounded-full bg-blue-50 px-2 py-0.5 text-[0.7rem] font-medium whitespace-nowrap text-blue-700"
|
||||
>
|
||||
85%
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="my-10 flex flex-col items-center justify-center gap-4 md:flex-row">
|
||||
<Button variant="outline" href="/demo" target="_blank" rel="noopener noreferrer nofollow">Book a demo</Button>
|
||||
<Button href="/signup" target="_blank" rel="noopener noreferrer nofollow">Sign Up for Free</Button>
|
||||
<!-- <a
|
||||
class="font-medium lg:font-semibold text-sm md:text-base w-11/12 md:w-fit border px-6 py-3 lg:px-10 lg:py-5 rounded-md"
|
||||
href="/github"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer nofollow"
|
||||
>
|
||||
View on Github
|
||||
</a> -->
|
||||
</div>
|
||||
<div class="mb-3 flex items-center gap-3.5 rounded-xl border border-gray-200 bg-white p-4">
|
||||
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-green-50 text-lg">🛡️</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="mb-1 text-sm font-medium">Security & Compliance</div>
|
||||
<div class="h-1 overflow-hidden rounded-full bg-gray-200">
|
||||
<div class="h-full rounded-full bg-green-500" style="width: 100%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="shrink-0 rounded-full bg-green-50 px-2 py-0.5 text-[0.7rem] font-medium whitespace-nowrap text-green-600"
|
||||
>
|
||||
✓ Done
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- <div class="relative my-5 md:my-10">
|
||||
<img
|
||||
width="710"
|
||||
height="710"
|
||||
src="./cio-hero.webp"
|
||||
alt="hero section with dark vs light mode"
|
||||
class=""
|
||||
/>
|
||||
|
||||
</div> -->
|
||||
<div style="position: relative; padding-bottom: calc(50% + 42px);" class="mx-auto w-[85%] lg:w-[70%]">
|
||||
<iframe
|
||||
title="ClassroomIO Live Demo"
|
||||
src="https://app.supademo.com/embed/cluw8chyy06nhq2s9m697a680"
|
||||
allow="clipboard-write"
|
||||
frameborder="0"
|
||||
webkitallowfullscreen="true"
|
||||
mozallowfullscreen="true"
|
||||
allowfullscreen
|
||||
style="position: absolute; top: 0; left: 0; width: 100%; height: 100%;"
|
||||
></iframe>
|
||||
</div>
|
||||
<div class="mb-3 flex items-center gap-3.5 rounded-xl border border-gray-200 bg-white p-4">
|
||||
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-orange-50 text-lg">🎯</div>
|
||||
<div class="min-w-0 flex-1">
|
||||
<div class="mb-1 text-sm font-medium">Product Certification</div>
|
||||
<div class="h-1 overflow-hidden rounded-full bg-gray-200">
|
||||
<div class="h-full rounded-full bg-blue-700" style="width: 42%"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="shrink-0 rounded-full bg-blue-50 px-2 py-0.5 text-[0.7rem] font-medium whitespace-nowrap text-blue-700"
|
||||
>
|
||||
42%
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{#if PUBLIC_ENABLE_USERS_COMPANIES}
|
||||
<div class="mb-[10%] px-[15%]">
|
||||
<h2 class="text-base font-semibold text-gray-900 lg:text-xl">Used at</h2>
|
||||
<div class="flex w-full flex-row flex-wrap items-center justify-between gap-5 py-[5%]">
|
||||
<img loading="lazy" src="/hero-1.svg" alt="" class="w-[30%] lg:w-[13%]" />
|
||||
<img loading="lazy" src="/hero-2.svg" alt="" class="w-[30%] lg:w-[13%]" />
|
||||
<img loading="lazy" src="/hero-3.svg" alt="" class="w-[30%] lg:w-[13%]" />
|
||||
<img loading="lazy" src="/hero-4.svg" alt="" class="w-[30%] lg:w-[13%]" />
|
||||
<img loading="lazy" src="/hero-5.svg" alt="" class="w-[30%] lg:w-[13%]" />
|
||||
<div class="mt-4 flex items-center gap-3 rounded-lg bg-blue-50 p-4">
|
||||
<span class="text-xl">🏆</span>
|
||||
<div>
|
||||
<div class="text-sm font-medium">3 certificates issued today</div>
|
||||
<div class="text-xs text-gray-500">Sarah, Marcus & Priya completed their certs</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
</BlurFade>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,17 +1,26 @@
|
||||
// UI Components - Named exports for easy importing
|
||||
export { default as AiSection } from './ai-section.svelte';
|
||||
export { default as AutomateSection } from './automate-section.svelte';
|
||||
export { default as BlogListItem } from './blog-list-item.svelte';
|
||||
export { default as CertSection } from './cert-section.svelte';
|
||||
export { default as CoreFeatureSection } from './core-feature-section.svelte';
|
||||
export { default as CoreFeatures } from './core-features.svelte';
|
||||
export { default as CustomImg } from './custom-img.svelte';
|
||||
export { default as DeploySection } from './deploy-section.svelte';
|
||||
export { default as EnterpriseSection } from './enterprise-section.svelte';
|
||||
export { default as Faq } from './faq.svelte';
|
||||
export { default as FeaturesSection } from './features-section.svelte';
|
||||
export { default as Footer } from './footer.svelte';
|
||||
export { default as FooterCta } from './footer-cta.svelte';
|
||||
export { default as Hero } from './hero.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 Navigation } from './navigation.svelte';
|
||||
export { default as NotFound } from './not-found.svelte';
|
||||
export { default as PageHeader } from './page-header.svelte';
|
||||
export { default as PageSignupCTA } from './page-signup-cta.svelte';
|
||||
export { default as QuestionTypes } from './question-types.svelte';
|
||||
export { default as SenjaEmbed } from './senja-embed.svelte';
|
||||
export { default as StudentDashboard } from './student-dashboard.svelte';
|
||||
export { default as Success } from './success.svelte';
|
||||
|
||||
@@ -0,0 +1,127 @@
|
||||
<script>
|
||||
import { BlurFade } from '@cio/ui/custom/animation/blurfade';
|
||||
import { BorderBeam } from '@cio/ui/custom/animation/border-beam';
|
||||
|
||||
const learnerModes = [
|
||||
{
|
||||
icon: '📖',
|
||||
title: 'Read it',
|
||||
description: 'Standard lesson view for learners who prefer reading at their own pace.'
|
||||
},
|
||||
{
|
||||
icon: '🎧',
|
||||
title: 'Listen to it',
|
||||
description:
|
||||
'One click and AI reads the lesson aloud. Perfect for commuters, multitaskers, and auditory learners.',
|
||||
comingSoon: true
|
||||
},
|
||||
{
|
||||
icon: '⚡',
|
||||
title: 'Get the summary',
|
||||
description:
|
||||
'AI condenses any lesson into 5 key bullet points. Great for reviewing before an assessment or when time is short.'
|
||||
}
|
||||
];
|
||||
|
||||
const summaryItems = [
|
||||
'Data privacy governs how personal information is collected, stored, and shared',
|
||||
'Consent must be obtained before collecting any personal data',
|
||||
'GDPR and CCPA set the global standard for data handling obligations',
|
||||
'Breaches must be reported within 72 hours under most regulations',
|
||||
'Employees are the most common cause of accidental data exposure'
|
||||
];
|
||||
</script>
|
||||
|
||||
<section class="bg-white px-6 py-16 lg:px-12 lg:py-24">
|
||||
<div class="mx-auto max-w-[1100px]">
|
||||
<div class="grid grid-cols-1 items-center gap-12 lg:grid-cols-2 lg:gap-20">
|
||||
<div>
|
||||
<BlurFade once>
|
||||
<div class="mb-3.5 text-xs font-medium tracking-widest text-blue-700 uppercase">
|
||||
Built for learners, not just admins
|
||||
</div>
|
||||
<h2 class="mb-4 text-[clamp(2rem,3vw,2.8rem)] leading-[1.15] font-medium tracking-tight">
|
||||
Every student learns differently.<br />We support <em class="text-blue-700 italic">all of them.</em>
|
||||
</h2>
|
||||
<p class="mb-10 max-w-[520px] text-base leading-relaxed text-gray-500 lg:text-lg">
|
||||
Most LMS platforms are built for the person running them. We built ClassroomIO for the person going through
|
||||
them. Because a certification program only works if people actually retain what they learned.
|
||||
</p>
|
||||
</BlurFade>
|
||||
|
||||
<div class="flex flex-col gap-4">
|
||||
{#each learnerModes as mode, i}
|
||||
<BlurFade delay={0.1 * i} once>
|
||||
<div class="flex items-start gap-3.5">
|
||||
<div class="flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-blue-50 text-lg">
|
||||
{mode.icon}
|
||||
</div>
|
||||
<div>
|
||||
<h4 class="mb-1 text-sm font-medium">
|
||||
{mode.title}
|
||||
{#if mode.comingSoon}
|
||||
<span
|
||||
class="ml-1 rounded-full bg-blue-700 px-1.5 py-0.5 align-middle text-[0.6rem] tracking-wide text-white uppercase"
|
||||
>Soon</span
|
||||
>
|
||||
{/if}
|
||||
</h4>
|
||||
<p class="text-sm leading-relaxed text-gray-500">{mode.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
</BlurFade>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Lesson Mock UI -->
|
||||
<BlurFade delay={0.2} once>
|
||||
<div class="relative overflow-hidden rounded-2xl border border-gray-200 bg-gray-50 shadow-2xl/5">
|
||||
<BorderBeam size={200} duration={14} colorFrom="#0233BD" colorTo="#93c5fd" />
|
||||
<div class="flex items-center justify-between border-b border-gray-200 bg-white px-5 py-4">
|
||||
<div class="text-sm font-medium">Data Privacy & Compliance</div>
|
||||
<div class="rounded-full border border-gray-200 bg-gray-50 px-2.5 py-0.5 text-xs text-gray-500">
|
||||
Lesson 3 of 8
|
||||
</div>
|
||||
</div>
|
||||
<div class="p-6">
|
||||
<div class="mb-5 text-sm leading-relaxed text-gray-500">
|
||||
Data privacy refers to the proper handling, processing, and storage of personal information. Organizations
|
||||
must ensure that customer data is collected with consent, stored securely, and never shared without
|
||||
authorization...
|
||||
</div>
|
||||
|
||||
<div class="mb-5 flex flex-wrap gap-2.5">
|
||||
<button
|
||||
class="flex items-center gap-1.5 rounded-lg border-none bg-gray-950 px-4 py-2 text-xs font-medium text-white"
|
||||
>
|
||||
🎧 Listen
|
||||
<span
|
||||
class="ml-1 rounded-full bg-blue-700 px-1.5 py-0.5 text-[0.6rem] tracking-wide text-white uppercase"
|
||||
>Soon</span
|
||||
>
|
||||
</button>
|
||||
<button
|
||||
class="flex items-center gap-1.5 rounded-lg border-[1.5px] border-gray-200 bg-white px-4 py-2 text-xs font-medium text-gray-950"
|
||||
>
|
||||
⚡ Summarize
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="rounded-xl border border-gray-200 bg-white p-4">
|
||||
<div class="mb-3 text-xs font-medium tracking-wider text-blue-700 uppercase">AI Summary</div>
|
||||
<div class="flex flex-col gap-2.5">
|
||||
{#each summaryItems as item}
|
||||
<div class="flex gap-2.5 text-xs leading-relaxed">
|
||||
<span class="shrink-0 font-medium text-blue-700">•</span>
|
||||
<span>{item}</span>
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</BlurFade>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
@@ -1,4 +1,6 @@
|
||||
<script>
|
||||
import { DotPattern } from '@cio/ui/custom/animation/dot-pattern';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Props
|
||||
* @property {string} [className]
|
||||
@@ -9,6 +11,9 @@
|
||||
let { className = '', children } = $props();
|
||||
</script>
|
||||
|
||||
<header class="hero-bg w-full border-b border-slate-100 pt-32 pb-16 lg:min-h-[20rem] {className}">
|
||||
{@render children?.()}
|
||||
<header class="relative w-full overflow-hidden border-b border-slate-100 pt-32 pb-16 lg:min-h-[20rem]">
|
||||
<DotPattern fillColor="rgb(2 51 189 / 0.25)" class="absolute inset-0 h-full w-full" />
|
||||
<div class="relative z-10 {className}">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<section class="bg-gray-50 py-16 lg:py-24">
|
||||
<div class="mx-auto mb-10 max-w-[1100px] px-6 text-center lg:mb-14 lg:px-12">
|
||||
<div class="mb-3.5 text-xs font-medium tracking-widest text-blue-700 uppercase">Assessments & Exams</div>
|
||||
<h2 class="mb-4 text-[clamp(2rem,3vw,2.8rem)] leading-[1.15] font-medium tracking-tight">
|
||||
Exams that go beyond multiple choice.
|
||||
</h2>
|
||||
<p class="mx-auto max-w-[560px] text-base leading-relaxed text-gray-500 lg:text-lg">
|
||||
Most LMS platforms give you multiple choice and call it a day. ClassroomIO supports the full range so your exams
|
||||
actually test what matters.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-center lg:px-12">
|
||||
<div data-cio-widget="question-type-picker" class="w-full max-w-[900px]"></div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<svelte:head>
|
||||
<script
|
||||
type="module"
|
||||
src="https://assets.cdn.clsrio.com/embeds/question-type-picker/question-type-picker.js"
|
||||
></script>
|
||||
</svelte:head>
|
||||
@@ -1,19 +1,19 @@
|
||||
<script>
|
||||
import { SenjaEmbed } from '$lib/components';
|
||||
import { Button } from '@cio/ui/base/button';
|
||||
</script>
|
||||
|
||||
<section id="testimonial" class="flex flex-col items-center space-y-2 px-3 py-[5%] lg:px-0">
|
||||
<h1 class="mx-auto my-0 flex flex-col items-center gap-4 text-3xl leading-normal font-normal md:text-4xl lg:text-5xl">
|
||||
Hear from Happy ClassroomIO Users
|
||||
</h1>
|
||||
<section id="testimonial" class="bg-white px-6 py-16 lg:px-12 lg:py-24">
|
||||
<div class="mx-auto max-w-[1100px] text-center">
|
||||
<div class="mb-3.5 text-xs font-bold tracking-widest text-blue-700 uppercase">Testimonials</div>
|
||||
<h2 class="mb-4 text-[clamp(2rem,3vw,2.8rem)] leading-[1.15] font-bold tracking-tight">
|
||||
Hear from happy ClassroomIO users
|
||||
</h2>
|
||||
<p class="mx-auto mb-10 max-w-[520px] text-base leading-relaxed text-gray-500 lg:text-lg">
|
||||
See what excites them about building and managing training programs with ClassroomIO.
|
||||
</p>
|
||||
|
||||
<p class="ui:text-muted-foreground mx-auto px-4 text-center text-base leading-6 tracking-wide lg:w-2/4 lg:p-0">
|
||||
See what excites them about building and managing bootcamps with ClassroomIO.
|
||||
</p>
|
||||
<Button href="/signup" target="_blank" rel="noopener noreferrer nofollow">Sign Up for Free</Button>
|
||||
|
||||
<div class="relative my-5 w-[85%] md:my-10 lg:w-[70%]">
|
||||
<SenjaEmbed id="3e847d7a-13d3-483e-8a71-5b35273dcc6c" />
|
||||
<div class="relative mx-auto w-full">
|
||||
<SenjaEmbed id="3e847d7a-13d3-483e-8a71-5b35273dcc6c" />
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
<script>
|
||||
import { DotPattern } from '@cio/ui/custom/animation/dot-pattern';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Props
|
||||
* @property {string} [className]
|
||||
@@ -9,6 +11,9 @@
|
||||
let { className = '', children } = $props();
|
||||
</script>
|
||||
|
||||
<header class="tools-hero-bg py-24 text-center {className} border-b border-slate-100 bg-white">
|
||||
{@render children?.()}
|
||||
<header class="relative py-24 text-center {className} overflow-hidden border-b border-slate-100 bg-white">
|
||||
<DotPattern fillColor="rgb(2 51 189 / 0.25)" class="absolute inset-0 h-full w-full" />
|
||||
<div class="relative z-10">
|
||||
{@render children?.()}
|
||||
</div>
|
||||
</header>
|
||||
|
||||
Reference in New Issue
Block a user