Skip to content
Draft
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
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.mp4 filter=lfs diff=lfs merge=lfs -text
59 changes: 59 additions & 0 deletions bun.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions packages/mukti-web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
"@react-three/postprocessing": "^3.0.4",
"@tabler/icons-react": "^3.34.1",
"@tanstack/react-query": "^5.90.11",
"@videojs/react": "^10.0.0-beta.11",
"@xyflow/react": "^12.10.0",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
Expand Down
3 changes: 3 additions & 0 deletions packages/mukti-web/public/demo/demo-01.mp4
Git LFS file not shown
3 changes: 3 additions & 0 deletions packages/mukti-web/public/demo/demo-02.mp4
Git LFS file not shown
4 changes: 4 additions & 0 deletions packages/mukti-web/src/app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
'use client';

import LandingCTA from '@/components/landing/landing-cta';
import LandingDemo from '@/components/landing/landing-demo';
import LandingFaq from '@/components/landing/landing-faq';
import LandingFooter from '@/components/landing/landing-footer';
import LandingHero from '@/components/landing/landing-hero';
import LandingNav from '@/components/landing/landing-nav';
Expand All @@ -14,10 +16,12 @@ export default function Home() {
<main className="japandi-page bg-grain min-h-screen w-full overflow-x-hidden selection:bg-japandi-sage selection:text-white">
<LandingNav />
<LandingHero />
<LandingDemo />
<LandingPhilosophy />
<LandingPillars />
<LandingProcess />
<LandingResearch />
<LandingFaq />
<LandingCTA />
<LandingFooter />
</main>
Expand Down
28 changes: 23 additions & 5 deletions packages/mukti-web/src/components/landing/landing-cta.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
'use client';

import { ArrowRight, CheckCircle2, Loader2 } from 'lucide-react';
import { ArrowRight, CheckCircle2, Loader2, Star } from 'lucide-react';
import { AnimatePresence, motion } from 'motion/react';
import Link from 'next/link';
import { useState } from 'react';

import { apiClient, ApiClientError } from '@/lib/api/client';
Expand Down Expand Up @@ -60,12 +61,11 @@ export default function LandingCTA() {
<span className="text-japandi-sage text-japandi-label tracking-[0.2em] block mb-6">
Early Access
</span>
<h2 className="text-japandi-stone text-4xl md:text-5xl lg:text-6xl font-light tracking-wide leading-tight mb-6">
<h2 className="text-japandi-stone text-4xl md:text-5xl lg:text-6xl font-light tracking-wide leading-tight mb-4">
Be the first to use Mukti
</h2>
<p className="text-japandi-stone/80 text-lg md:text-xl font-light leading-relaxed max-w-2xl mx-auto mb-12">
Join the waitlist for early access. No spoon-feeding included. Just pure cognitive
liberation.
<p className="text-japandi-terracotta/80 text-sm md:text-base font-medium tracking-wide mb-4">
First 100 users get founding member status
</p>
</motion.div>

Expand Down Expand Up @@ -187,6 +187,24 @@ export default function LandingCTA() {
We respect your attention. No spam, ever.
</motion.p>
)}

{/* Secondary CTA — GitHub */}
<motion.div
className="mt-10 flex items-center justify-center"
initial={{ opacity: 0 }}
transition={{ delay: 0.6, duration: 1.2, ease: [0.25, 0.1, 0.25, 1] }}
viewport={{ once: true }}
whileInView={{ opacity: 1 }}
>
<Link
className="group flex items-center gap-2 rounded-sm border border-japandi-stone/10 bg-japandi-cream px-5 py-2.5 text-sm tracking-widest text-japandi-stone/60 transition-colors duration-300 hover:border-japandi-stone/30 hover:text-japandi-stone"
href="https://github.com/shettydev/mukti"
target="_blank"
>
<Star className="h-4 w-4 transition-colors duration-300 group-hover:text-yellow-400" />
<span>Star on GitHub</span>
</Link>
</motion.div>
</div>
</section>
);
Expand Down
120 changes: 120 additions & 0 deletions packages/mukti-web/src/components/landing/landing-demo.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
'use client';

import { Play } from 'lucide-react';
import { motion } from 'motion/react';

import VideoJsPlayer from './video-js-player';

const demos = [
{
description:
'Choose from six classical Socratic techniques — each a different lens for examining your ideas. The AI never answers, only asks.',
id: 'chat',
label: 'Socratic Dialogue',
placeholder: '/demos/socratic-chat.mp4',
title: 'Six methods, one purpose: deeper thinking',
video: '/demo/demo-01.mp4',
},
{
description:
'Place your problem at the center. Add constraints as Soil, surface hidden Assumptions as Roots, and let Insights emerge naturally. Each node opens its own Socratic dialogue.',
id: 'canvas',
label: 'Thinking Canvas',
placeholder: '/demos/thinking-canvas.mp4',
title: 'Map the problem before you solve it',
video: '/demo/demo-02.mp4',
},
{
description:
"Start with a question and let your thinking unfold. Branch into possibilities, surface questions you hadn't thought to ask, and track which paths you've truly explored.",
id: 'map',
label: 'Thinking Map',
placeholder: '/demos/thinking-map.mp4',
title: 'Let your reasoning branch freely',
},
];

export default function LandingDemo() {
return (
<section
className="relative w-full px-5 xs:px-6 py-20 sm:py-24 md:px-12 lg:py-32 bg-japandi-light-stone/20"
id="demo"
>
<div className="mx-auto max-w-6xl">
<motion.div
className="mb-16 text-center"
initial={{ opacity: 0, y: 20 }}
transition={{ duration: 1.2, ease: [0.25, 0.1, 0.25, 1] }}
viewport={{ once: true }}
whileInView={{ opacity: 1, y: 0 }}
>
<span className="text-japandi-label block mb-4 tracking-[0.2em] text-japandi-sage">
See It In Action
</span>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-light tracking-wide leading-tight text-japandi-stone">
How Mukti works
</h2>
</motion.div>

<div className="grid grid-cols-1 gap-12 lg:gap-16">
{demos.map((demo, index) => (
<motion.div
className={
demo.video
? 'flex flex-col gap-6'
: 'grid grid-cols-1 md:grid-cols-2 gap-8 md:gap-12 items-center'
}
initial={{ opacity: 0, y: 30 }}
key={demo.id}
transition={{
delay: index * 0.15,
duration: 1.2,
ease: [0.25, 0.1, 0.25, 1],
}}
viewport={{ once: true }}
whileInView={{ opacity: 1, y: 0 }}
>
{/* Alternate layout: even rows swap text/video */}
<div className={!demo.video && index % 2 === 1 ? 'md:order-2' : ''}>
<div
className={`relative w-full overflow-hidden rounded-sm border border-japandi-sand/40 bg-japandi-cream ${demo.video ? '' : 'aspect-[16/10]'}`}
>
{demo.video ? (
<VideoJsPlayer src={demo.video} />
) : (
<div className="absolute inset-0 flex flex-col items-center justify-center gap-4 bg-japandi-light-stone/30">
<div className="flex h-14 w-14 items-center justify-center rounded-full border border-japandi-stone/15 bg-japandi-cream/80">
<Play className="ml-0.5 h-5 w-5 text-japandi-terracotta" />
</div>
<div className="text-center">
<p className="text-japandi-label text-xs tracking-[0.2em] text-japandi-sage">
{demo.label}
</p>
<p className="mt-1 text-xs text-japandi-stone/40">
Video placeholder — record with Screen Studio
</p>
</div>
</div>
)}
<div className="bg-grain pointer-events-none absolute inset-0 opacity-30" />
</div>
</div>

<div className={!demo.video && index % 2 === 1 ? 'md:order-1' : ''}>
<span className="text-japandi-label block mb-3 text-xs tracking-[0.2em] text-japandi-terracotta">
Pillar {String(index + 1).padStart(2, '0')}
</span>
<h3 className="mb-4 text-2xl md:text-3xl font-light tracking-wide text-japandi-stone leading-tight">
{demo.title}
</h3>
<p className="text-base md:text-lg font-light leading-relaxed text-japandi-stone/70">
{demo.description}
</p>
</div>
</motion.div>
))}
</div>
</div>
</section>
);
}
81 changes: 81 additions & 0 deletions packages/mukti-web/src/components/landing/landing-faq.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
'use client';

import { motion } from 'motion/react';

import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from '@/components/ui/accordion';

const faqs = [
{
answer:
"No — it's the opposite. Most AI tools give you answers instantly. Mukti uses the Socratic method to ask you questions that guide you toward your own answers. The AI is there to challenge your thinking, not replace it.",
question: 'Is Mukti just another AI chatbot?',
},
{
answer:
"Mukti uses an adaptive scaffolding system with 5 levels. At the lowest level, it's pure Socratic questioning. If you're genuinely stuck and the system detects a knowledge gap, it gradually provides more support — but it never just hands you the answer. The goal is always to help you arrive at the insight yourself.",
question: 'Will I ever get a direct answer?',
},
{
answer:
'Mukti offers a free tier with core features. You can also bring your own API key (BYOK) for AI providers like OpenRouter to unlock unlimited usage. Premium features will be available through a subscription.',
question: 'Is it free to use?',
},
{
answer:
"Mukti connects to multiple AI providers through OpenRouter. You can use the default model or bring your own API key to choose your preferred model. The AI doesn't answer your questions — it generates the Socratic questions that challenge your thinking.",
question: 'What AI model does Mukti use?',
},
{
answer:
"Your thinking sessions, canvases, and conversations are private to your account. API keys are encrypted at rest. We don't train on your data or share it with third parties. Your cognitive journey is yours alone.",
question: 'Is my data private?',
},
];

export default function LandingFaq() {
return (
<section className="relative w-full px-5 xs:px-6 py-20 sm:py-24 md:px-12 lg:py-32 bg-japandi-cream">
<div className="mx-auto max-w-3xl">
<motion.div
className="mb-12 text-center"
initial={{ opacity: 0, y: 20 }}
transition={{ duration: 1.2, ease: [0.25, 0.1, 0.25, 1] }}
viewport={{ once: true }}
whileInView={{ opacity: 1, y: 0 }}
>
<span className="text-japandi-label block mb-4 tracking-[0.2em] text-japandi-sage">
Questions
</span>
<h2 className="text-4xl md:text-5xl lg:text-6xl font-light tracking-wide leading-tight text-japandi-stone">
Frequently asked
</h2>
</motion.div>

<motion.div
initial={{ opacity: 0, y: 20 }}
transition={{ delay: 0.2, duration: 1.2, ease: [0.25, 0.1, 0.25, 1] }}
viewport={{ once: true }}
whileInView={{ opacity: 1, y: 0 }}
>
<Accordion className="w-full" collapsible type="single">
{faqs.map((faq, index) => (
<AccordionItem className="border-japandi-sand/30" key={index} value={`faq-${index}`}>
<AccordionTrigger className="text-left text-base md:text-lg font-light tracking-wide text-japandi-stone hover:text-japandi-terracotta hover:no-underline py-5 [&[data-state=open]]:text-japandi-terracotta">
{faq.question}
</AccordionTrigger>
<AccordionContent className="text-base font-light leading-relaxed text-japandi-stone/70 pb-6">
{faq.answer}
</AccordionContent>
</AccordionItem>
))}
</Accordion>
</motion.div>
</div>
</section>
);
}
42 changes: 32 additions & 10 deletions packages/mukti-web/src/components/landing/landing-footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,34 +5,56 @@ import Link from 'next/link';
export default function LandingFooter() {
return (
<footer className="w-full px-5 xs:px-6 py-10 sm:py-12 md:px-12 bg-japandi-cream border-t border-japandi-sand/20">
<div className="max-w-7xl mx-auto flex flex-col md:flex-row items-center justify-between gap-8">
<div className="text-japandi-stone/60 text-sm tracking-widest lowercase">
<div className="max-w-7xl mx-auto flex flex-col items-center gap-8 md:grid md:grid-cols-3 md:items-center">
<div className="text-japandi-stone/60 text-sm tracking-widest lowercase md:justify-self-start">
© {new Date().getFullYear()} mukti
</div>

<div className="flex items-center gap-8">
<div className="flex flex-wrap items-center justify-center gap-6 md:gap-8">
<Link
className="text-japandi-stone/60 hover:text-japandi-terracotta text-sm tracking-widest uppercase transition-colors duration-300"
href="#philosophy"
>
Philosophy
</Link>
<Link
className="text-japandi-stone/60 hover:text-japandi-terracotta text-sm tracking-widest uppercase transition-colors duration-300"
href="#demo"
>
Demo
</Link>
<Link
className="text-japandi-stone/60 hover:text-japandi-terracotta text-sm tracking-widest uppercase transition-colors duration-300"
href="#join"
>
Waitlist
</Link>
</div>

<div className="text-japandi-stone/40 text-sm tracking-widest">
Crafted by{' '}
<Link
className="font-normal text-japandi-stone/60 hover:text-japandi-terracotta transition-colors"
href="https://github.com/shettydev"
className="text-japandi-stone/60 hover:text-japandi-terracotta text-sm tracking-widest uppercase transition-colors duration-300"
href="https://github.com/shettydev/mukti"
target="_blank"
>
प्रतीक शेट्टी
GitHub
</Link>
</div>

<div className="flex flex-wrap items-center justify-center gap-4 text-japandi-stone/40 text-xs tracking-widest md:justify-self-end">
<span>
Crafted by{' '}
<Link
className="font-normal text-japandi-stone/60 hover:text-japandi-terracotta transition-colors"
href="https://github.com/shettydev"
target="_blank"
>
प्रतीक शेट्टी
</Link>
</span>
<span className="hidden md:inline text-japandi-sand/60">|</span>
<Link className="hover:text-japandi-terracotta transition-colors" href="/privacy">
Privacy
</Link>
<Link className="hover:text-japandi-terracotta transition-colors" href="/terms">
Terms
</Link>
</div>
</div>
Expand Down
10 changes: 5 additions & 5 deletions packages/mukti-web/src/components/landing/landing-hero.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,11 @@ export default function LandingHero() {
transition={{ delay: 0.8, duration: 1.2, ease: [0.25, 0.1, 0.25, 1] }}
>
<Link
className="group flex items-center gap-2 text-japandi-terracotta text-base xs:text-lg tracking-widest hover:text-japandi-stone transition-colors duration-500"
href="#philosophy"
className="group flex items-center gap-2 text-japandi-stone/60 text-sm tracking-widest hover:text-japandi-terracotta transition-colors duration-500"
href="#demo"
>
<span>Learn the method</span>
<ArrowRight className="w-4 h-4 transition-transform duration-500 group-hover:translate-x-1" />
<span>See it in action</span>
<ArrowRight className="w-3 h-3 transition-transform duration-500 group-hover:translate-x-1" />
</Link>
</motion.div>
</div>
Expand All @@ -81,7 +81,7 @@ export default function LandingHero() {
transition={{ delay: 1.2, duration: 1, ease: [0.25, 0.1, 0.25, 1] }}
>
<motion.div style={{ opacity }}>
<Link aria-label="Scroll to content" href="#philosophy">
<Link aria-label="Scroll to content" href="#demo">
<motion.div
animate={{ y: [0, 8, 0] }}
transition={{ duration: 1.5, ease: 'easeInOut', repeat: Infinity }}
Expand Down
Loading
Loading