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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 21 additions & 8 deletions apps/landing/src/app/docs/page.tsx
Original file line number Diff line number Diff line change
@@ -1,24 +1,27 @@
import type { Metadata } from "next";
import { Metadata } from "next";
import Link from "next/link";
import {
Terminal,
Server,
BookOpen,
Code2,
ExternalLink,
Server,
Smartphone,
Bot,
Terminal,
Layout,
Blocks,
Sparkles,
ExternalLink,
Bot,
} from "lucide-react";
import { buttonVariants, cn } from "@opencom/ui";
import { Section, SectionHeader, FeatureCard, Screenshot } from "@/components/sections";
import { Section, SectionHeader, FeatureCard } from "@/components/sections";
import {
OPENCOM_GITHUB_DOCS_URL,
OPENCOM_GITHUB_REPO_URL,
OPENCOM_HOSTED_ONBOARDING_URL,
} from "@/lib/links";

import { WidgetHomeGraphic } from "@/components/landing/graphics/widget-home-graphic";
import { ToursGraphic } from "@/components/landing/graphics/tours-graphic";
import { createLandingPageMetadata } from "@/lib/metadata";

export const metadata: Metadata = createLandingPageMetadata({
Expand Down Expand Up @@ -221,8 +224,18 @@ export default function DocsPage() {
</a>
</div>
<div className="grid gap-6 md:grid-cols-2">
<Screenshot src="/screenshots/widget-tab-home.png" alt="Widget home tab" />
<Screenshot src="/screenshots/widget-tour-post-step.png" alt="Widget product tour" />
<div className="rounded-[2.5rem] bg-[#f9fafb] dark:bg-card border border-slate-200/50 dark:border-white/5 shadow-[0_40px_80px_-20px_rgba(0,0,0,0.1)] dark:shadow-[0_40px_80px_-20px_rgba(0,0,0,0.5)] p-2 relative overflow-hidden h-full min-h-[400px]">
<div className="absolute inset-0 rounded-[2.5rem] shadow-[inset_0_1px_0_rgba(255,255,255,0.8)] dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] pointer-events-none z-10" />
<div className="rounded-[2rem] overflow-hidden border border-border/50 bg-muted/20 dark:bg-black relative w-full h-full">
<WidgetHomeGraphic />
</div>
</div>
<div className="rounded-[2.5rem] bg-[#f9fafb] dark:bg-card border border-slate-200/50 dark:border-white/5 shadow-[0_40px_80px_-20px_rgba(0,0,0,0.1)] dark:shadow-[0_40px_80px_-20px_rgba(0,0,0,0.5)] p-2 relative overflow-hidden h-full min-h-[400px]">
<div className="absolute inset-0 rounded-[2.5rem] shadow-[inset_0_1px_0_rgba(255,255,255,0.8)] dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] pointer-events-none z-10" />
<div className="rounded-[2rem] overflow-hidden border border-border/50 bg-muted/20 dark:bg-black relative w-full h-full">
<ToursGraphic />
</div>
</div>
</div>
</div>
</Section>
Expand Down
29 changes: 14 additions & 15 deletions apps/landing/src/app/features/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
Check,
Sparkles,
} from "lucide-react";
import { Section, SectionHeader, FeatureCard, Screenshot, CTA } from "@/components/sections";
import { Section, SectionHeader, FeatureCard, CTA } from "@/components/sections";
import { OPENCOM_GITHUB_DOCS_URL, OPENCOM_HOSTED_ONBOARDING_URL } from "@/lib/links";

import { InboxGraphic } from "@/components/landing/graphics/inbox-graphic";
Expand All @@ -27,6 +27,9 @@ import { TicketsGraphic } from "@/components/landing/graphics/tickets-graphic";
import { SurveysGraphic } from "@/components/landing/graphics/surveys-graphic";
import { CampaignsGraphic } from "@/components/landing/graphics/campaigns-graphic";
import { ReportsGraphic } from "@/components/landing/graphics/reports-graphic";
import { KnowledgeBaseGraphic } from "@/components/landing/graphics/knowledge-graphic";
import { ChecklistsGraphic } from "@/components/landing/graphics/checklists-graphic";
import { TooltipsGraphic } from "@/components/landing/graphics/tooltips-graphic";

export const metadata: Metadata = {
title: "Features | Opencom",
Expand Down Expand Up @@ -71,7 +74,7 @@ const featureCategories = [
title: "Knowledge Hub",
description: "Self-service help center with searchable articles, snippets, and folders.",
icon: BookOpen,
screenshot: "/screenshots/web-knowledge.png",
Graphic: KnowledgeBaseGraphic,
features: [
"Article management with folders",
"Saved reply snippets",
Expand Down Expand Up @@ -146,7 +149,7 @@ const featureCategories = [
title: "Checklists",
description: "Guide users through onboarding with task lists.",
icon: ListChecks,
screenshot: "/screenshots/web-checklists.png",
Graphic: ChecklistsGraphic,
features: [
"Multi-step onboarding checklists",
"Task completion tracking",
Expand All @@ -161,7 +164,7 @@ const featureCategories = [
title: "Tooltips",
description: "Contextual hints attached to page elements.",
icon: MousePointerClick,
screenshot: "/screenshots/web-tooltips.png",
Graphic: TooltipsGraphic,
features: [
"On-hover tooltips",
"Click-triggered beacons",
Expand Down Expand Up @@ -263,18 +266,14 @@ export default function FeaturesPage() {
</ul>
</div>
<div className={index % 2 === 1 ? "lg:order-1" : ""}>
{category.Graphic ? (
<div className="rounded-[2.5rem] bg-[#f9fafb] dark:bg-card border border-slate-200/50 dark:border-white/5 shadow-[0_40px_80px_-20px_rgba(0,0,0,0.1)] dark:shadow-[0_40px_80px_-20px_rgba(0,0,0,0.5)] p-2 relative overflow-hidden">
{/* Subtle inner glow */}
<div className="absolute inset-0 rounded-[2.5rem] shadow-[inset_0_1px_0_rgba(255,255,255,0.8)] dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] pointer-events-none z-10" />

<div className="rounded-[2rem] overflow-hidden border border-border/50 bg-muted/20 dark:bg-black relative aspect-[16/10]">
<category.Graphic />
</div>
<div className="rounded-[2.5rem] bg-[#f9fafb] dark:bg-card border border-slate-200/50 dark:border-white/5 shadow-[0_40px_80px_-20px_rgba(0,0,0,0.1)] dark:shadow-[0_40px_80px_-20px_rgba(0,0,0,0.5)] p-2 relative overflow-hidden">
{/* Subtle inner glow */}
<div className="absolute inset-0 rounded-[2.5rem] shadow-[inset_0_1px_0_rgba(255,255,255,0.8)] dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] pointer-events-none z-10" />

<div className="rounded-[2rem] overflow-hidden border border-border/50 bg-muted/20 dark:bg-black relative aspect-[16/10]">
<category.Graphic />
</div>
) : (
<Screenshot src={category.screenshot} alt={`${category.title} screenshot`} />
)}
</div>
</div>
</div>
</Section>
Expand Down
19 changes: 16 additions & 3 deletions apps/landing/src/app/support/page.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import type { Metadata } from "next";
import { Clock3, LifeBuoy, MessageCircle, MousePointerClick } from "lucide-react";
import { Screenshot, Section, SectionHeader } from "@/components/sections";
import { Section, SectionHeader } from "@/components/sections";
import { WidgetCtaPanel } from "@/components/support/widget-cta-panel";
import { createLandingPageMetadata } from "@/lib/metadata";

import { WidgetHomeGraphic } from "@/components/landing/graphics/widget-home-graphic";
import { WidgetChatGraphic } from "@/components/landing/graphics/widget-chat-graphic";

export const metadata: Metadata = createLandingPageMetadata({
title: "Support | Opencom",
description:
Expand Down Expand Up @@ -64,8 +67,18 @@ export default function SupportPage() {
</div>

<div className="space-y-6">
<Screenshot src="/screenshots/widget-tab-home.png" alt="Opencom widget Home tab" />
<Screenshot src="/screenshots/widget-outbound-chat.png" alt="Opencom widget chat view" />
<div className="rounded-[2.5rem] bg-[#f9fafb] dark:bg-card border border-slate-200/50 dark:border-white/5 shadow-[0_40px_80px_-20px_rgba(0,0,0,0.1)] dark:shadow-[0_40px_80px_-20px_rgba(0,0,0,0.5)] p-2 relative overflow-hidden h-full min-h-[400px]">
<div className="absolute inset-0 rounded-[2.5rem] shadow-[inset_0_1px_0_rgba(255,255,255,0.8)] dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] pointer-events-none z-10" />
<div className="rounded-[2rem] overflow-hidden border border-border/50 bg-muted/20 dark:bg-black relative w-full h-full flex items-center justify-center p-8">
<WidgetHomeGraphic />
</div>
</div>
<div className="rounded-[2.5rem] bg-[#f9fafb] dark:bg-card border border-slate-200/50 dark:border-white/5 shadow-[0_40px_80px_-20px_rgba(0,0,0,0.1)] dark:shadow-[0_40px_80px_-20px_rgba(0,0,0,0.5)] p-2 relative overflow-hidden h-full min-h-[400px]">
<div className="absolute inset-0 rounded-[2.5rem] shadow-[inset_0_1px_0_rgba(255,255,255,0.8)] dark:shadow-[inset_0_1px_0_rgba(255,255,255,0.05)] pointer-events-none z-10" />
<div className="rounded-[2rem] overflow-hidden border border-border/50 bg-muted/20 dark:bg-black relative w-full h-full flex items-center justify-center p-8">
<WidgetChatGraphic />
</div>
</div>
</div>
</div>
</Section>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
"use client";

import { motion } from "framer-motion";
import { CheckSquareOffset, DotsSixVertical, Plus } from "@phosphor-icons/react";

export function ChecklistsGraphic() {
return (
<div className="relative w-full h-full bg-[#f9fafb] dark:bg-[#0a0a0a] overflow-hidden flex items-center justify-center font-sans p-8">
{/* Background Dots */}
<div className="absolute inset-0 opacity-20 pointer-events-none p-6">
<div className="w-full h-full border-2 border-dashed border-border/40 rounded-3xl" />
</div>

<motion.div
initial={{ y: 20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
className="relative z-10 w-full max-w-sm bg-card rounded-2xl shadow-xl border border-border/50 overflow-hidden"
>
<div className="p-4 border-b border-border/50 bg-muted/20 flex items-center justify-between">
<div>
<h3 className="text-sm font-bold">Onboarding Checklist</h3>
<p className="text-[10px] text-muted-foreground">Target: New Signups</p>
</div>
<div className="px-2 py-1 rounded bg-green-500/10 text-green-600 dark:text-green-400 text-[10px] font-bold uppercase tracking-wider">
Active
</div>
</div>

<div className="p-4 space-y-3">
{[
{ title: "Complete Profile", desc: "Add your name and avatar", done: true, active: false },
{ title: "Invite Team Members", desc: "Invite at least 2 colleagues", done: false, active: true },
{ title: "Connect Integration", desc: "Link Slack or Linear", done: false, active: false },
].map((task, i) => (
<motion.div
key={i}
initial={{ x: -10, opacity: 0 }}
animate={{ x: 0, opacity: 1 }}
transition={{ delay: i * 0.15 }}
className={`group flex items-start gap-3 p-3 rounded-xl border transition-colors ${
task.active
? 'border-primary/40 bg-primary/5 shadow-sm'
: 'border-border/50 bg-background hover:border-border'
}`}
>
<DotsSixVertical className="w-4 h-4 text-muted-foreground/30 mt-0.5 opacity-0 group-hover:opacity-100 transition-opacity cursor-grab" />

<div className={`mt-0.5 shrink-0 transition-colors ${task.done ? 'text-primary' : 'text-muted-foreground/40'}`}>
<CheckSquareOffset weight={task.done ? "fill" : "regular"} className="w-5 h-5" />
</div>

<div className="flex-1 min-w-0">
<div className={`text-sm font-medium ${task.done ? 'line-through text-muted-foreground' : 'text-foreground'}`}>
{task.title}
</div>
<div className="text-xs text-muted-foreground truncate">{task.desc}</div>

{task.active && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: "auto", opacity: 1 }}
className="mt-3 flex items-center gap-2"
>
<button className="px-3 py-1.5 text-[10px] font-semibold bg-primary text-primary-foreground rounded-md shadow-sm">
Edit Action
</button>
<span className="text-[10px] text-muted-foreground">Trigger: Tour Completed</span>
</motion.div>
)}
</div>
</motion.div>
))}

<motion.button
whileHover={{ scale: 1.02 }}
whileTap={{ scale: 0.98 }}
className="w-full py-2.5 rounded-xl border border-dashed border-border flex items-center justify-center gap-2 text-xs font-medium text-muted-foreground hover:text-foreground hover:bg-muted/20 transition-colors"
>
<Plus weight="bold" /> Add Step
</motion.button>
</div>
</motion.div>
</div>
);
}
105 changes: 105 additions & 0 deletions apps/landing/src/components/landing/graphics/knowledge-graphic.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
"use client";

import { motion } from "framer-motion";
import { BookOpenText, Folder, Article, MagnifyingGlass } from "@phosphor-icons/react";

export function KnowledgeBaseGraphic() {
return (
<div className="relative w-full h-full bg-background dark:bg-[#0a0a0a] overflow-hidden flex font-sans">
{/* Sidebar */}
<div className="w-[30%] h-full border-r border-border/50 bg-muted/10 p-4 flex flex-col gap-4">
<div className="flex items-center gap-2 px-3 py-2 bg-background border border-border/50 rounded-lg text-muted-foreground">
<MagnifyingGlass className="w-4 h-4" />
<span className="text-xs">Search articles...</span>
</div>

<div className="space-y-1">
<div className="flex items-center gap-2 px-2 py-1.5 rounded-lg bg-primary/10 text-primary text-sm font-medium">
<Folder weight="fill" className="w-4 h-4" />
Getting Started
</div>
<div className="pl-6 space-y-1">
<div className="flex items-center gap-2 px-2 py-1 rounded-md text-foreground text-xs font-medium bg-muted/50">
<Article weight="fill" className="w-3 h-3 text-muted-foreground" />
Installation Guide
</div>
<div className="flex items-center gap-2 px-2 py-1 rounded-md text-muted-foreground hover:text-foreground text-xs transition-colors">
<Article className="w-3 h-3" />
Quickstart Tutorial
</div>
</div>
</div>

<div className="space-y-1">
<div className="flex items-center gap-2 px-2 py-1.5 rounded-lg text-foreground text-sm font-medium hover:bg-muted/50 transition-colors">
<Folder weight="fill" className="w-4 h-4 text-blue-500" />
API Reference
</div>
</div>
</div>

{/* Editor Area */}
<div className="flex-1 h-full p-8 relative flex flex-col">
{/* Floating Toolbar */}
<motion.div
initial={{ y: -20, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
transition={{ delay: 0.2 }}
className="absolute top-6 left-1/2 -translate-x-1/2 bg-card border border-border/50 rounded-lg shadow-sm px-3 py-1.5 flex items-center gap-2"
>
<div className="w-4 h-4 rounded bg-muted flex items-center justify-center text-[10px] font-bold">B</div>
<div className="w-4 h-4 rounded hover:bg-muted flex items-center justify-center text-[10px] italic">I</div>
<div className="w-4 h-4 rounded hover:bg-muted flex items-center justify-center text-[10px] underline">U</div>
<div className="w-px h-4 bg-border/50 mx-1" />
<div className="w-4 h-4 rounded hover:bg-muted flex items-center justify-center text-[10px]">H1</div>
<div className="w-4 h-4 rounded hover:bg-muted flex items-center justify-center text-[10px]">H2</div>
</motion.div>

<div className="mt-12 space-y-6 max-w-lg">
<motion.h1
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
className="text-3xl font-bold tracking-tight text-foreground focus:outline-none"
>
Installation Guide
</motion.h1>

<motion.div
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
transition={{ delay: 0.1 }}
className="space-y-4"
>
<p className="text-sm text-muted-foreground leading-relaxed">
Welcome to the Opencom installation guide. This document will walk you through setting up the core platform and integrating the frontend widgets.
</p>

<div className="bg-muted/30 border border-border/50 rounded-xl p-4 font-mono text-xs text-foreground/80 relative group">
<div className="absolute top-2 right-2 w-4 h-4 rounded bg-muted-foreground/20" />
<span className="text-primary">npm</span> install @opencom/widget<br/>
<span className="text-primary">npx</span> opencom init
</div>

<div className="flex items-center gap-2">
<div className="h-2 w-full bg-muted rounded" />
</div>
<div className="flex items-center gap-2">
<div className="h-2 w-5/6 bg-muted rounded" />
</div>
</motion.div>
</div>

{/* Abstract Publish Button */}
<motion.div
initial={{ scale: 0.9, opacity: 0 }}
animate={{ scale: 1, opacity: 1 }}
transition={{ delay: 0.4, type: "spring" }}
className="absolute bottom-6 right-6 px-4 py-2 bg-primary text-primary-foreground text-xs font-bold rounded-lg shadow-lg flex items-center gap-2"
>
<BookOpenText weight="fill" className="w-4 h-4" />
Publish Article
</motion.div>
</div>
</div>
);
}
Loading
Loading