- {' '}
- {/* Increased Z-index for text clarity */}
- {/*/!* 2. Enhanced Badge (More Polished) *!/*/}
- {/*
*/}
- {/* /!* Added icon *!/*/}
- {/* Powered by Vercel Ai SDK*/}
- {/* */}
- {/* 3. Improved Typography & Visual Impact */}
-
- ThinkInk
-
- {/* 4. Refined Tagline */}
-
- The ultimate **AI-powered content creation platform**. Generate high-quality articles,
- blog posts, and more in **seconds**.
-
- {/* 5. Enhanced CTA Buttons */}
-
-
-
+ {/* 1. Subtle Background Texture (Grain/Vignette) */}
+
+ {/* Soft grain / vignette for tactile depth */}
+
+
+
+
+
+
+
+ {/* Hero Content Grid */}
+
+
+ {/* Left side: Text Content and CTAs */}
+
+
- Start Generating
-
-
-
-
+
+
+ A sleek, minimal content generator tuned for clarity and quality. One pipeline
+ endless possibilities. Grounded by research, refined by AI.
+
+
+
- Learn More
-
-
-
+ {/* FIX: Replaced next/link with standard tag */}
+
+ Try it free
+
+
+ {/* FIX: Replaced next/link with standard tag */}
+
+ Explore features
+
+
+
+
+
+
1
+
+
Trusted by creators
+
Used daily by modern teams
+
+
+
+
+
99%
+
+
Uptime & performance
+
Reliably available
+
+
+
+
+
+ {/* Right side visual — Platform Screensho */}
+
+
+
+ {/* Image 1: Primary Screenshot (Foreground) */}
+
+
+ width={1300}
+ height={650}
+ className="w-full h-auto object-cover"
+ />
+
+
+ {/* Image 2: Secondary Screenshot (Background/Layered) */}
+
+
+
+
+ {/* Abstract Background Element (Moved further back) */}
+
+
+
+
-
+
);
-};
+}
+
+
+export default memo(Hero);
\ No newline at end of file
diff --git a/components/Landing/HeroSecondary.tsx b/components/Landing/HeroSecondary.tsx
deleted file mode 100644
index fbe334f..0000000
--- a/components/Landing/HeroSecondary.tsx
+++ /dev/null
@@ -1,86 +0,0 @@
-'use client';
-import React from 'react';
-import Image from 'next/image';
-import { motion } from 'framer-motion';
-
-const Hero = () => {
- return (
-
-
- {/* Left Column: Text Content */}
-
-
- Unleash Your AI Writer. Create Fact-Based Content, Instantly.
-
-
- Generate high-quality blogs, social media posts, and more with our advanced AI. Grounded
- in truth, crafted for impact.
-
-
- Start Generating for Free
-
-
-
- {/* Right Column: Image and Animation */}
-
-
-
-
-
- {/* Background Decoration */}
-
-
-
-
- );
-};
-
-export default Hero;
diff --git a/components/Landing/MonoCTA.tsx b/components/Landing/MonoCTA.tsx
deleted file mode 100644
index f1847dc..0000000
--- a/components/Landing/MonoCTA.tsx
+++ /dev/null
@@ -1,26 +0,0 @@
-'use client'
-
-import React from 'react';
-import { Button } from '@/components/ui/button';
-import Link from 'next/link';
-import { motion } from 'framer-motion';
-
-export default function MonoCTA() {
- return (
-
-
-
-
-
Start creating memorable content today.
-
Try ThinkInk for free — no credit card required. Scale your writing workflows with minimal overhead.
-
-
-
- Get started
- See features
-
-
-
-
- );
-}
diff --git a/components/Landing/MonoFeatures.tsx b/components/Landing/MonoFeatures.tsx
deleted file mode 100644
index 8ce1338..0000000
--- a/components/Landing/MonoFeatures.tsx
+++ /dev/null
@@ -1,175 +0,0 @@
-'use client'
-
-import React from 'react';
-import { motion, AnimatePresence } from 'framer-motion';
-import {Button} from '@/components/ui/button';
-import { cn } from '@/lib/utils';
-
-export default function MonoFeatures() {
- const [selectedFeature, setSelectedFeature] = React.useState(null);
-
- const features = [
- {
- id: 'f1',
- title: 'Two-Stage Refinement Pipeline',
- desc: 'Precision starts upstream. Refine prompt parameters before execution to ensure superior content grounding.',
- fullDescription: 'Our proprietary dual-stage system separates conceptual alignment from final drafting. Stage 1 focuses on filtering and optimizing the prompt payload based on historical performance and compliance metrics. This rigorous upstream vetting results in cleaner, more targeted content output from Stage 2.',
- icon: (
-
-
-
-
-
- ),
- },
- {
- id: 'f2',
- title: 'Automated Compliance Checks',
- desc: 'Instant, automated checks for tone consistency, citation integrity, length compliance, and SEO alignment.',
- fullDescription: 'Every generated document passes through an automated quality gate. This includes real-time validation against predefined metrics for SEO density, brand tone, and legal compliance (e.g., source attribution). Publish with absolute confidence, knowing your content is checked and verified.',
- icon: (
-
-
-
-
- ),
- },
- {
- id: 'f3',
- title: 'Webhooks & API Integration',
- desc: 'Deliver content automatically and securely to your CMS or preferred publishing platform via robust webhooks.',
- fullDescription: 'Integrate ThinkInk into your existing content stack via our secure, API-first architecture. Configure custom webhooks to trigger content delivery, approval flows, or archival processes instantly upon generation completion, achieving full operational automation.',
- icon: (
-
-
-
-
- ),
- }
- ];
-
- const handleCardClick = (feature) => {
- setSelectedFeature(selectedFeature?.id === feature.id ? null : feature);
- };
-
- const featureRevealVariants = {
- hidden: { opacity: 0, height: 0, scaleY: 0.95 },
- visible: {
- opacity: 1,
- height: "auto",
- scaleY: 1,
- transition: { duration: 0.5, ease: [0.25, 1, 0.5, 1] }
- },
- exit: {
- opacity: 0,
- height: 0,
- paddingTop: 0,
- paddingBottom: 0,
- transition: { duration: 0.3, ease: "easeOut" }
- }
- };
-
- return (
-
-
-
-
- Power Engineered for Content Mastery.
-
-
- Everything you need to produce polished content quickly — reliability without the noise.
-
-
-
- {/* Feature Cards Grid */}
-
- {features.map((f, idx) => (
-
handleCardClick(f)}
- role="button"
- aria-expanded={selectedFeature?.id === f.id}
- className={`relative bg-white border group rounded-2xl p-8 cursor-pointer transition-all duration-300 transform
- ${selectedFeature?.id === f.id ? 'border-black ring-4 ring-black/10 shadow-2xl shadow-black/10' : ' hover:border-black/50 shadow-lg hover:shadow-xl hover:shadow-neutral-200'}
- `}
- >
-
- {/* Icon Wrapper (Sleek Border) */}
-
- {f.icon}
-
-
-
{f.title}
-
-
- {f.desc}
-
-
-
-
- {selectedFeature?.id === f.id ? 'Description revealed ↓' : 'Click to learn more →'}
-
-
- ))}
-
-
- {/* === Full Description Reveal Section === */}
-
- {selectedFeature && (
-
-
- {/* Reveal Icon and Title */}
-
-
- {selectedFeature.icon}
-
-
- {selectedFeature.title}
-
-
-
- {/* Full Description Text */}
-
- {selectedFeature.fullDescription}
-
-
- {/* Closing Button */}
-
- setSelectedFeature(null)}
- className="bg-neutral-100 text-neutral-800 px-4 py-2 text-sm font-semibold rounded-lg hover:bg-neutral-200 transition"
- >
- Close Description
-
-
-
-
- )}
-
-
-
- );
-}
\ No newline at end of file
diff --git a/components/Landing/MonoFooter.tsx b/components/Landing/MonoFooter.tsx
deleted file mode 100644
index f2b08a5..0000000
--- a/components/Landing/MonoFooter.tsx
+++ /dev/null
@@ -1,29 +0,0 @@
-'use client'
-
-import React from 'react';
-
-export default function MonoFooter() {
- return (
-
-
-
-
-
TI
-
-
ThinkInk
-
AI content refined for quality
-
-
-
-
-
-
© {new Date().getFullYear()} ThinkInk — All rights reserved
-
-
-
- );
-}
diff --git a/components/Landing/MonoHero.tsx b/components/Landing/MonoHero.tsx
deleted file mode 100644
index e1330de..0000000
--- a/components/Landing/MonoHero.tsx
+++ /dev/null
@@ -1,150 +0,0 @@
-'use client'
-
-import React from 'react';
-import { motion } from 'framer-motion';
-import { Button } from '@/components/ui/button';
-import SCREENSHOT_URL from '@/assets/hero_image.png';
-import Image from 'next/image';
-
-
-export default function MonoHero() {
- return (
-
- );
-}
\ No newline at end of file
diff --git a/components/Landing/MonoTestimonials.tsx b/components/Landing/MonoTestimonials.tsx
deleted file mode 100644
index ba5eaad..0000000
--- a/components/Landing/MonoTestimonials.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-'use client'
-
-import React from 'react';
-import { motion } from 'framer-motion';
-
-const quotes = [
- {
- id: 'q1',
- quote: 'ThinkInk transformed our content workflow — outputs are cleaner and more consistent than ever.',
- author: 'Jamal T., Editorial Lead',
- },
- {
- id: 'q2',
- quote: 'The two-step prompt refinement saved us hours per week and improved our SEO metrics.',
- author: 'Sara L., Growth Marketer',
- },
- {
- id: 'q3',
- quote: 'Reliable, fast, and the minimal UI keeps our writers focused. A modern tool for modern teams.',
- author: 'Alex P., Product Manager',
- }
-];
-
-export default function MonoTestimonials() {
- return (
-
-
-
Trusted & loved
-
Hear what early teams say
-
-
- {quotes.map((q, idx) => (
-
- “{q.quote}”
- {q.author}
-
- ))}
-
-
-
- );
-}
diff --git a/components/Landing/Navbar.tsx b/components/Landing/Navbar.tsx
index aca5e3a..8381ad9 100644
--- a/components/Landing/Navbar.tsx
+++ b/components/Landing/Navbar.tsx
@@ -1,120 +1,104 @@
'use client';
-import { motion } from 'framer-motion';
-// Assuming '@/components/ui/button' is available and using Link as a standard anchor replacement
+import { AnimatePresence, motion } from 'framer-motion';
import { Button } from '@/components/ui/button';
-// Replaced import from 'next/link' with a standard variable declaration for Link
-const Link = (props) => ;
+import Link from 'next/link';
import { Menu, X, BookOpen } from 'lucide-react';
-import { useState } from 'react';
+import { memo, useState } from 'react';
-export const Navbar = () => {
- const [isOpen, setIsOpen] = useState(false);
+const Navbar = () => {
+ const [isMenuOpen, setIsMenuOpen] = useState(false);
- const navLinks = [
- { href: '#features', label: 'Features' },
- { href: '#services', label: 'Services' },
- { href: '#about', label: 'About' },
- ];
+ const toggleMenu = () => {
+ setIsMenuOpen(!isMenuOpen);
+ };
- // Variants for the mobile menu animation
- const menuVariants: any = {
- open: { opacity: 1, y: 0, transition: { type: 'spring', stiffness: 300, damping: 30 } },
- closed: { opacity: 0, y: -20, transition: { duration: 0.3 } },
- };
+ const navItems = [
+ { href: "#features", label: "Features" },
+ { href: "#automation", label: "Automation" },
+ ];
- return (
- // --- Enhanced Floating Capsule Container ---
-
-
- {/* Logo/Brand */}
+ return (
-
-
- ThinkInk
-
-
-
- {/* Desktop Navigation Links */}
-
- {navLinks.map((link) => (
-
- {link.label}
- {/* Active/Hover Underline Effect */}
-
-
- ))}
-
-
- {/* Desktop CTA Button */}
-
-
-
- Get Started
-
-
-
+
+ {/* Logo / Brand Name */}
+
+ TI
+ Think-Ink
+
+
+ {/* Desktop Navigation */}
+
+ {navItems.map(item => (
+
+ {item.label}
+
+ ))}
+
+
+ Get started
+
+
+
+
+ {/* Mobile Menu Button */}
+
+
+ {isMenuOpen ? : }
+
+
+
- {/* Mobile Menu Button */}
-
- setIsOpen(!isOpen)}
- className="rounded-full p-2 text-black transition-colors hover:bg-neutral-100"
- >
- {isOpen ? : }
-
-
-
+ {/* Mobile Menu Content (Animated Overlay) */}
+
+ {isMenuOpen && (
+
+ )}
+
+
+ );
};
+
+export default memo(Navbar);
diff --git a/components/Layout/Dashboard/API-Integrations/WebhookManager.tsx b/components/Layout/Dashboard/API-Integrations/WebhookManager.tsx
index 6fdc6d0..09b0c43 100644
--- a/components/Layout/Dashboard/API-Integrations/WebhookManager.tsx
+++ b/components/Layout/Dashboard/API-Integrations/WebhookManager.tsx
@@ -40,7 +40,7 @@ const mockDecrypt = (data) => data.startsWith('ENC:') ? atob(data.slice(4)) : da
const defaultWebhook = {
url: '',
trigger_event: 'content.complete',
- secret_key: crypto.randomUUID(), // Auto-generate a strong initial secret
+ secret_key: "", // Auto-generate a strong initial secret
is_active: true,
};
@@ -508,12 +508,12 @@ export const WebhookManager = () => {
{/* Details */}
Destination URL
-
+
{hook.url}
-
+
Trigger: {hook.trigger_event}
Secured by Secret Key
diff --git a/components/Layout/Dashboard/Generate/Editor/CustomImageDialog.tsx b/components/Layout/Dashboard/Generate/Editor/CustomImageDialog.tsx
index abc2f14..f1d3748 100644
--- a/components/Layout/Dashboard/Generate/Editor/CustomImageDialog.tsx
+++ b/components/Layout/Dashboard/Generate/Editor/CustomImageDialog.tsx
@@ -2,6 +2,10 @@ import React, { useState } from 'react';
import { Button } from '@/components/ui/button'; // Assuming you use a UI library
import { Input } from '@/components/ui/input';
import { SaveImageParameters } from '@mdxeditor/editor'; // The type for submitting data
+import { Dialog, DialogContent, DialogTrigger } from '@/components/ui/dialog';
+import { cn } from '@/lib/utils';
+import { Images } from '../RightSidebarPanel';
+import { ImagePlus } from 'lucide-react';
// Define the shape of the props the MDX editor will pass to your component
interface CustomImageDialogProps {
@@ -13,7 +17,7 @@ interface CustomImageDialogProps {
// state: EditingImageDialogState | NewImageDialogState;
}
-const CustomImageDialog: React.FC
= ({ onImageUpload, onClose }) => {
+const CustomImageDialog = () => {
const [url, setUrl] = useState('');
const [altText, setAltText] = useState('');
const [file, setFile] = useState(null);
@@ -25,12 +29,7 @@ const CustomImageDialog: React.FC = ({ onImageUpload, on
// CASE 1: Image URL provided
if (url.trim()) {
- onImageUpload({
- src: url.trim(),
- altText: altText.trim(),
- // width and height are optional, but good practice if known
- });
- onClose();
+
return;
}
@@ -42,13 +41,7 @@ const CustomImageDialog: React.FC = ({ onImageUpload, on
// You would call your private API route here (e.g., /api/upload-image)
const uploadedUrl = await uploadImageToServer(file);
- // --- STEP B: Submit the final URL to the MDX Editor ---
- onImageUpload({
- src: uploadedUrl,
- altText: altText.trim() || file.name,
- // You could fetch dimensions from the server response here if needed
- });
- onClose();
+
} catch (error) {
console.error('Image upload failed:', error);
alert('Failed to upload image. Check console for details.');
@@ -80,59 +73,18 @@ const CustomImageDialog: React.FC = ({ onImageUpload, on
};
return (
-
-
Insert Image
-
- {/* File Upload Section */}
-
-
Upload File
-
{
- setFile(e.target.files?.[0] || null);
- // Clear URL when file is selected
- setUrl('');
- }}
- />
-
or enter a URL below
-
-
- {/* URL Input Section */}
-
- Image URL
- {
- setUrl(e.target.value);
- // Clear file when URL is manually entered
- setFile(null);
- }}
- />
-
-
- {/* Alt Text Input */}
-
- Alt Text
- setAltText(e.target.value)}
- />
-
-
- {/* Actions */}
-
-
- Cancel
-
-
- {loading ? 'Uploading...' : 'Insert Image'}
+ <>
+
+
+
+
-
-
+
+
+
+
+
+ >
);
};
diff --git a/components/Layout/Dashboard/Generate/Editor/Editor.tsx b/components/Layout/Dashboard/Generate/Editor/Editor.tsx
index b06b19f..99b9260 100644
--- a/components/Layout/Dashboard/Generate/Editor/Editor.tsx
+++ b/components/Layout/Dashboard/Generate/Editor/Editor.tsx
@@ -61,7 +61,7 @@ export default function Editor() {
-
+
{/* You can add more buttons here */}
@@ -92,7 +92,7 @@ export default function Editor() {
tablePlugin(),
]}
contentEditableClassName={cn(
- 'container-full !h-full p-2 overflow-y-auto prose markdown markdown-content-area',
+ 'container-full !h-full p-2 pt-10! overflow-y-auto prose markdown markdown-content-area',
)}
className={cn('container-full overflow-hidden rounded-md bg-white')}
/>
diff --git a/components/Layout/Dashboard/Generate/Editor/EditorLoader.tsx b/components/Layout/Dashboard/Generate/Editor/EditorLoader.tsx
index f8f5a61..b70fc2f 100644
--- a/components/Layout/Dashboard/Generate/Editor/EditorLoader.tsx
+++ b/components/Layout/Dashboard/Generate/Editor/EditorLoader.tsx
@@ -18,10 +18,6 @@ export default function EditorLoader({ className }: CodeEditorLoaderProps) {
className, // Allows setting height/width from the dynamic import
)}
>
-
- Loading : Initializing Markdown Interface...
-
-
{/* Simulated Code/Content Lines */}
{Array.from({ length: LINE_COUNT }).map((_, index) => {
// Line width varies to mimic code structure
diff --git a/components/Layout/Dashboard/Generate/RightSidebarPanel.tsx b/components/Layout/Dashboard/Generate/RightSidebarPanel.tsx
index 0b355c5..8292470 100644
--- a/components/Layout/Dashboard/Generate/RightSidebarPanel.tsx
+++ b/components/Layout/Dashboard/Generate/RightSidebarPanel.tsx
@@ -15,7 +15,7 @@ import { ChatHistoryRenderer } from '@/components/Layout/Dashboard/Generate/Chat
import { ScrollArea } from '@/components/ui/scroll-area';
import { toast } from 'sonner';
import { Button } from '@mdxeditor/editor';
-import { Upload, X } from 'lucide-react';
+import { TrashIcon, Upload, X } from 'lucide-react';
import { motion } from 'framer-motion';
import MobileSheetWrapper from '@/components/Layout/Dashboard/Generate/MobileSheetWrapper';
import { SystemPromptSelector } from '@/components/Layout/Dashboard/Generate/AISystemConfig';
@@ -136,7 +136,7 @@ export const Source = () => {
);
};
-const Images = () => {
+export const Images = ({ width = 400}) => {
const { generatedContent, setGeneratedContent, localImages, setLocalImages } = useContent();
// MAINTAINED LOGIC: Extract images from Markdown
@@ -202,7 +202,7 @@ const Images = () => {
return (
@@ -239,11 +239,11 @@ const Images = () => {
{/* Action Buttons Overlay */}
-
+
{/* Insert Button (Primary Action) */}
handleInsertImage(url)}
- className="mb-1 w-full bg-indigo-600 text-xs font-semibold text-white hover:bg-indigo-700"
+ className="mb-1 w-full bg-indigo-600 cursor-pointer text-xs rounded-md p-2.5 transition-300 font-semibold text-white hover:bg-indigo-700"
>
Insert into Editor
@@ -252,9 +252,9 @@ const Images = () => {
{isLocalImage(url) && (
handleRemoveLocalImage(url)}
- className="w-full border border-black/20 bg-white text-xs font-semibold text-black hover:bg-black hover:text-white"
+ className="container-fit bg-white border border-black/20 rounded-md p-2.5 transition-300 text-xs font-semibold text-black"
>
- Remove
+
)}
diff --git a/components/Layout/Dashboard/Generate/content/Renderer.tsx b/components/Layout/Dashboard/Generate/content/Renderer.tsx
index 03f2f01..38f745d 100644
--- a/components/Layout/Dashboard/Generate/content/Renderer.tsx
+++ b/components/Layout/Dashboard/Generate/content/Renderer.tsx
@@ -12,11 +12,12 @@ import { Source } from '../RightSidebarPanel';
import EditorLoader from '@/components/Layout/Dashboard/Generate/Editor/EditorLoader';
import { FileText, PenLine, Link as LinkIcon, Code } from 'lucide-react';
import { PromptSelector } from '@/components/Layout/Dashboard/Generate/PromptSelector';
+import { ContentLoadingSkeleton } from '@/components/ui/ContentLoadingSkeleton';
const Editor = dynamic(() => import('../Editor/Editor'), {
// Make sure we turn SSR off
ssr: false,
- loading: () =>
,
+ loading: () =>
,
});
export default function Renderer() {
diff --git a/components/ui/ContentLoadingSkeleton.tsx b/components/ui/ContentLoadingSkeleton.tsx
index abad60d..8f78204 100644
--- a/components/ui/ContentLoadingSkeleton.tsx
+++ b/components/ui/ContentLoadingSkeleton.tsx
@@ -4,11 +4,12 @@ import { cn } from '@/lib/utils';
import { Skeleton } from '@/components/ui/skeleton';
import { Loader } from 'lucide-react';
-export const ContentLoadingSkeleton = () => {
+export const ContentLoadingSkeleton = ({isGenerating = true}) => {
return (
{/* 1. Header and Loader */}
-
@@ -16,6 +17,16 @@ export const ContentLoadingSkeleton = () => {
Generating Content. Please wait...
+ ) : (
+
+
+
+ Loading editor...
+
+
+ )}
{/* 2. Main Title/Heading Skeleton */}
@@ -47,6 +58,11 @@ export const ContentLoadingSkeleton = () => {
+ {!isGenerating && (
+
+
+
+ )}
);