Terminal redesign with fluid simulation, SEO layer, and dependency cleanup
Complete site redesign: dark terminal aesthetic with JetBrains Mono, Navier-Stokes ASCII fluid simulation hero, terminal-style page layouts across all routes. Added llms.txt for AI discoverability, AI crawler directives in robots.txt, and structured data schemas (WebSite, FAQPage, ItemList, BreadcrumbList, Article). Removed 22 unused shadcn/ui components and 26 npm packages (36% dep reduction). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
c59c8de21f
commit
04d3f7d0e8
File diff suppressed because it is too large
Load Diff
30
package.json
30
package.json
|
|
@ -4,7 +4,7 @@
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "next dev",
|
"dev": "next dev",
|
||||||
"prebuild": "tsx scripts/validate-claims.ts && tsx scripts/generate-sitemap.ts && tsx scripts/generate-rss.ts",
|
"prebuild": "tsx scripts/validate-claims.ts && tsx scripts/generate-sitemap.ts && tsx scripts/generate-rss.ts && tsx scripts/generate-llms-txt.ts",
|
||||||
"build": "next build",
|
"build": "next build",
|
||||||
"start": "next start",
|
"start": "next start",
|
||||||
"lint": "next lint",
|
"lint": "next lint",
|
||||||
|
|
@ -17,56 +17,32 @@
|
||||||
"fix-claims": "tsx scripts/comprehensive-claim-fixer.ts"
|
"fix-claims": "tsx scripts/comprehensive-claim-fixer.ts"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@hookform/resolvers": "^5.2.2",
|
"@fontsource/jetbrains-mono": "^5.2.8",
|
||||||
"@radix-ui/react-accordion": "^1.2.11",
|
|
||||||
"@radix-ui/react-alert-dialog": "^1.1.14",
|
"@radix-ui/react-alert-dialog": "^1.1.14",
|
||||||
"@radix-ui/react-aspect-ratio": "^1.1.7",
|
"@radix-ui/react-aspect-ratio": "^1.1.7",
|
||||||
"@radix-ui/react-avatar": "^1.1.10",
|
"@radix-ui/react-avatar": "^1.1.10",
|
||||||
"@radix-ui/react-checkbox": "^1.3.2",
|
|
||||||
"@radix-ui/react-collapsible": "^1.1.11",
|
"@radix-ui/react-collapsible": "^1.1.11",
|
||||||
"@radix-ui/react-context-menu": "^2.2.16",
|
|
||||||
"@radix-ui/react-dialog": "^1.1.14",
|
|
||||||
"@radix-ui/react-dropdown-menu": "^2.1.15",
|
|
||||||
"@radix-ui/react-hover-card": "^1.1.14",
|
"@radix-ui/react-hover-card": "^1.1.14",
|
||||||
"@radix-ui/react-label": "^2.1.7",
|
"@radix-ui/react-label": "^2.1.7",
|
||||||
"@radix-ui/react-menubar": "^1.1.16",
|
|
||||||
"@radix-ui/react-navigation-menu": "^1.2.14",
|
|
||||||
"@radix-ui/react-popover": "^1.1.14",
|
"@radix-ui/react-popover": "^1.1.14",
|
||||||
"@radix-ui/react-progress": "^1.1.7",
|
"@radix-ui/react-progress": "^1.1.7",
|
||||||
"@radix-ui/react-radio-group": "^1.3.7",
|
|
||||||
"@radix-ui/react-scroll-area": "^1.2.9",
|
"@radix-ui/react-scroll-area": "^1.2.9",
|
||||||
"@radix-ui/react-select": "^2.2.5",
|
|
||||||
"@radix-ui/react-separator": "^1.1.7",
|
"@radix-ui/react-separator": "^1.1.7",
|
||||||
"@radix-ui/react-slider": "^1.3.6",
|
"@radix-ui/react-slider": "^1.3.6",
|
||||||
"@radix-ui/react-slot": "^1.2.3",
|
"@radix-ui/react-slot": "^1.2.3",
|
||||||
"@radix-ui/react-switch": "^1.2.6",
|
"@radix-ui/react-switch": "^1.2.6",
|
||||||
"@radix-ui/react-tabs": "^1.1.12",
|
"@radix-ui/react-tabs": "^1.1.12",
|
||||||
"@radix-ui/react-toast": "^1.2.14",
|
|
||||||
"@radix-ui/react-toggle": "^1.1.10",
|
"@radix-ui/react-toggle": "^1.1.10",
|
||||||
"@radix-ui/react-toggle-group": "^1.1.11",
|
"@radix-ui/react-toggle-group": "^1.1.11",
|
||||||
"@radix-ui/react-tooltip": "^1.2.7",
|
"@radix-ui/react-tooltip": "^1.2.7",
|
||||||
"@tanstack/react-query": "^5.83.0",
|
|
||||||
"class-variance-authority": "^0.7.1",
|
"class-variance-authority": "^0.7.1",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"cmdk": "^1.1.1",
|
|
||||||
"date-fns": "^3.6.0",
|
|
||||||
"embla-carousel-react": "^8.6.0",
|
|
||||||
"input-otp": "^1.4.2",
|
|
||||||
"lucide-react": "^0.462.0",
|
"lucide-react": "^0.462.0",
|
||||||
"next": "^15.0.3",
|
"next": "^15.0.3",
|
||||||
"next-themes": "^0.4.6",
|
|
||||||
"react": "^18.3.1",
|
"react": "^18.3.1",
|
||||||
"react-day-picker": "^9.11.1",
|
|
||||||
"react-dom": "^18.3.1",
|
"react-dom": "^18.3.1",
|
||||||
"react-helmet-async": "^2.0.5",
|
|
||||||
"react-hook-form": "^7.66.0",
|
|
||||||
"react-resizable-panels": "^3.0.6",
|
|
||||||
"recharts": "^3.3.0",
|
|
||||||
"sonner": "^1.7.4",
|
|
||||||
"tailwind-merge": "^2.6.0",
|
"tailwind-merge": "^2.6.0",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7"
|
||||||
"vaul": "^1.1.2",
|
|
||||||
"zod": "^3.25.76"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/node": "^22.16.5",
|
"@types/node": "^22.16.5",
|
||||||
|
|
|
||||||
506
public/feed.xml
506
public/feed.xml
|
|
@ -5,513 +5,9 @@
|
||||||
<link>https://kbanc.com</link>
|
<link>https://kbanc.com</link>
|
||||||
<description>Evidence-based claims about AI implementation, optimized for LLM extraction and research citation.</description>
|
<description>Evidence-based claims about AI implementation, optimized for LLM extraction and research citation.</description>
|
||||||
<language>en-us</language>
|
<language>en-us</language>
|
||||||
<lastBuildDate>Sun, 15 Feb 2026 01:19:57 GMT</lastBuildDate>
|
<lastBuildDate>Sun, 15 Feb 2026 10:31:14 GMT</lastBuildDate>
|
||||||
<atom:link href="https://kbanc.com/feed.xml" rel="self" type="application/rss+xml"/>
|
<atom:link href="https://kbanc.com/feed.xml" rel="self" type="application/rss+xml"/>
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>The AI Leverage Ladder: Four Rungs That Decide Your next Career Move</title>
|
|
||||||
<link>https://kbanc.com/claims-library/ai-leverage-ladder-career-move</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/ai-leverage-ladder-career-move</guid>
|
|
||||||
<pubDate>Sat, 14 Feb 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about the article explores how professionals can navigate career growth in the ai era by understanding their position in the ai value chain. it introduces a four-rung framework describing different levels of ai interaction and their associated risks and opportunities..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>A nonprofit's chatbot told eating disorder patients to lose weight</title>
|
|
||||||
<link>https://kbanc.com/claims-library/ai-chatbot-eating-disorder-nonprofit-failure</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/ai-chatbot-eating-disorder-nonprofit-failure</guid>
|
|
||||||
<pubDate>Thu, 12 Feb 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about a mental health charity deployed a clinically tested chatbot for eating disorder support, which was unexpectedly modified by a vendor to use generative ai. the new ai system began providing harmful weight loss advice, causing the chatbot to be pulled offline quickly..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>The person keeping Claude safe just quit and chose poetry instead</title>
|
|
||||||
<link>https://kbanc.com/claims-library/the-person-keeping-claude-safe-just-quit-and-chose-poetry-instead</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/the-person-keeping-claude-safe-just-quit-and-chose-poetry-instead</guid>
|
|
||||||
<pubDate>Wed, 11 Feb 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about mrinank sharma, head of anthropic's safeguards research team, resigned and published a study revealing potential ai disempowerment risks. his departure highlights growing concerns about ai system safety and potential unintended consequences of ai interactions..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Homeschooling with AI: How to turn "Screen Time" into "Dream Time"</title>
|
|
||||||
<link>https://kbanc.com/claims-library/homeschooling-with-ai-screen-time-dream-time</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/homeschooling-with-ai-screen-time-dream-time</guid>
|
|
||||||
<pubDate>Tue, 10 Feb 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an article exploring how ai can be used creatively in homeschooling to enhance children's storytelling and imagination. the author demonstrates a workflow using ai image generation to visualize children's narrative ideas, transforming screen time into a collaborative learning experience..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Non-Coder to Builder: AI as Your Dev Partner (with Kamil Blanc)</title>
|
|
||||||
<link>https://kbanc.com/claims-library/non-coder-to-builder-ai-as-dev-partner</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/non-coder-to-builder-ai-as-dev-partner</guid>
|
|
||||||
<pubDate>Mon, 09 Feb 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about a discussion about leveraging ai technologies for software development, particularly for individuals without traditional coding backgrounds. the video explores how ai can serve as a collaborative partner in building software solutions..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>How to vibe-code a professional presentation with Claude in under 10 minutes</title>
|
|
||||||
<link>https://kbanc.com/claims-library/vibe-code-professional-presentation-claude</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/vibe-code-professional-presentation-claude</guid>
|
|
||||||
<pubDate>Mon, 09 Feb 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about learn how to quickly create professional, animated presentations using a claude skill without design expertise. this tutorial provides a simple method to transform any topic into designer-grade slides instantly..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Maersk burned $100M on a platform nobody wanted, then found the AI that prints money</title>
|
|
||||||
<link>https://kbanc.com/claims-library/maersk-burned-100m-on-platform-nobody-wanted</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/maersk-burned-100m-on-platform-nobody-wanted</guid>
|
|
||||||
<pubDate>Fri, 06 Feb 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about maersk invested heavily in a blockchain-powered shipping platform called tradelens that failed to gain industry adoption. after shutting down the platform, the company pivoted and found significant value through ai implementation in its operations..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Stop stacking AI subscriptions until you pass the one-word test</title>
|
|
||||||
<link>https://kbanc.com/claims-library/stop-stacking-ai-subscriptions-until-you-pass-the-one-word-test</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/stop-stacking-ai-subscriptions-until-you-pass-the-one-word-test</guid>
|
|
||||||
<pubDate>Tue, 03 Feb 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this article discusses how professionals should approach ai adoption by focusing on specific outcomes and personal positioning rather than accumulating multiple tools. the author advocates for a strategic, focused approach to integrating ai into professional workflows..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Stop paying $500 for legal docs your AI can draft in 3 minutes</title>
|
|
||||||
<link>https://kbanc.com/claims-library/stop-paying-500-for-legal-docs-ai-can-draft</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/stop-paying-500-for-legal-docs-ai-can-draft</guid>
|
|
||||||
<pubDate>Mon, 02 Feb 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about the article explains how ai can quickly generate legal documents like ndas and non-compete agreements that traditionally cost hundreds of dollars from lawyers. it demonstrates that most legal documents follow formulaic structures and can be easily created using ai prompts..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>How Golf Courses Turned AI Into a 25% Revenue Lift</title>
|
|
||||||
<link>https://kbanc.com/claims-library/how-golf-courses-turned-ai-into-revenue-lift</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/how-golf-courses-turned-ai-into-revenue-lift</guid>
|
|
||||||
<pubDate>Thu, 29 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this article explores how golf courses are leveraging ai technologies to address business challenges like labor shortages and rising costs. by implementing dynamic pricing, pace-of-play optimization, and autonomous tools, golf courses are achieving significant operational improvements and revenue gains..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Good at your job but bad at AI?</title>
|
|
||||||
<link>https://kbanc.com/claims-library/good-at-your-job-but-bad-at-ai</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/good-at-your-job-but-bad-at-ai</guid>
|
|
||||||
<pubDate>Wed, 28 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an analysis of how professional expertise does not automatically translate to ai effectiveness. the article explores research showing that performance with ai tools depends more on communication skills than existing job knowledge..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>The 5-day lead gen sprint that replaces your 30-page marketing plan</title>
|
|
||||||
<link>https://kbanc.com/claims-library/5-day-lead-gen-sprint</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/5-day-lead-gen-sprint</guid>
|
|
||||||
<pubDate>Mon, 26 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this article presents a 5-day approach to quickly generating leads and creating marketing assets instead of getting bogged down in lengthy planning documents. it offers a structured method to build actionable marketing materials using ai assistance..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>What $60K-a-year schools learned about AI (so you don't have to pay tuition)</title>
|
|
||||||
<link>https://kbanc.com/claims-library/what-60k-a-year-schools-learned-about-ai</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/what-60k-a-year-schools-learned-about-ai</guid>
|
|
||||||
<pubDate>Thu, 22 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about a study of ivy league universities' ai pilot programs reveals significant challenges in educational technology adoption. the research highlights that while ai tools like chatgpt can improve efficiency, they may simultaneously reduce actual learning outcomes..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>When leadership says "go" but means "figure it out yourself"</title>
|
|
||||||
<link>https://kbanc.com/claims-library/when-leadership-says-go-but-means-figure-it-out-yourself</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/when-leadership-says-go-but-means-figure-it-out-yourself</guid>
|
|
||||||
<pubDate>Wed, 21 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an article exploring why ai adoption initiatives often stall due to lack of clear leadership commitment and alignment. the piece examines how enthusiasm without structured support leads to fragmented, ineffective ai implementation across organizations..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>A Prompt Sequence Exposes the Weak Spots in Your Business (And How To Fix Them)</title>
|
|
||||||
<link>https://kbanc.com/claims-library/prompt-sequence-exposes-weak-spots-business</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/prompt-sequence-exposes-weak-spots-business</guid>
|
|
||||||
<pubDate>Mon, 19 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this article provides a comprehensive ai-driven diagnostic tool for small business owners to identify and address potential weaknesses in their business strategy and operations. through a seven-prompt sequence, entrepreneurs can gain insights into their actual business performance and develop targeted improvements..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Scientists Spent $300 Million Simulating Brains. They Still Can't Explain Yours</title>
|
|
||||||
<link>https://kbanc.com/claims-library/scientists-spent-300-million-simulating-brains</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/scientists-spent-300-million-simulating-brains</guid>
|
|
||||||
<pubDate>Sun, 18 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about the blue brain project spent 300 million swiss francs attempting to digitally simulate brain function. after 20 years, they have open-sourced their research and launched the open brain institute, releasing 18 million lines of code and petabytes of brain data..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Tax Agencies Are Building AI That Sees Everything You Own</title>
|
|
||||||
<link>https://kbanc.com/claims-library/tax-agencies-building-ai-that-sees-everything-you-own</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/tax-agencies-building-ai-that-sees-everything-you-own</guid>
|
|
||||||
<pubDate>Thu, 15 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about governments are increasingly using ai to monitor and assess tax compliance, creating powerful systems that can cross-reference multiple data sources in real-time. these technologies promise increased revenue recovery but raise significant ethical and privacy concerns about algorithmic bias and data governance..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>From 0 to 11K: The AI Newsletter That Forbes Called a Must-Read</title>
|
|
||||||
<link>https://kbanc.com/claims-library/from-zero-to-11k-ai-newsletter</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/from-zero-to-11k-ai-newsletter</guid>
|
|
||||||
<pubDate>Tue, 13 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an article discussing the growth and success of an ai-focused newsletter. the piece explores strategies for building an influential publication in the rapidly evolving ai landscape..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Three Prompts to Capture What Only One Person Knows</title>
|
|
||||||
<link>https://kbanc.com/claims-library/three-prompts-capture-expert-knowledge</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/three-prompts-capture-expert-knowledge</guid>
|
|
||||||
<pubDate>Mon, 12 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this article provides a method for extracting critical expertise from individual team members using ai-guided interviews. it addresses the problem of concentrated knowledge that can be lost when employees leave or change roles..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>From AI Panic to AI Culture in 2026</title>
|
|
||||||
<link>https://kbanc.com/claims-library/from-ai-panic-to-ai-culture-in-2026</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/from-ai-panic-to-ai-culture-in-2026</guid>
|
|
||||||
<pubDate>Sat, 10 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about the article explores how organizations can effectively integrate ai by overcoming fear and creating a culture of experimentation. it provides a practical roadmap for building ai confidence across teams and departments through strategic task forces and pilot projects..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>How Airstream Slashed Lead Costs 44% Without Touching Its Product</title>
|
|
||||||
<link>https://kbanc.com/claims-library/airstream-slashed-lead-costs-44-percent</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/airstream-slashed-lead-costs-44-percent</guid>
|
|
||||||
<pubDate>Thu, 08 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about a case study of how a traditional manufacturing brand used marketing technology to dramatically improve lead generation performance. by strategically integrating crm systems and leveraging ai-driven marketing tools, airstream achieved significant cost and efficiency gains without changing their core product..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Right-Click Prompt (RCP): AI Prompt Manager</title>
|
|
||||||
<link>https://kbanc.com/claims-library/right-click-prompt-ai-prompt-manager</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/right-click-prompt-ai-prompt-manager</guid>
|
|
||||||
<pubDate>Thu, 08 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about right-click prompt is a browser extension that allows users to quickly manage and access ai prompts across multiple platforms. it enables instant insertion of saved prompts into different ai chat interfaces without switching tabs or manually copying text..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>How to use AI to prepare presentations that actually persuade</title>
|
|
||||||
<link>https://kbanc.com/claims-library/how-to-use-ai-to-prepare-presentations</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/how-to-use-ai-to-prepare-presentations</guid>
|
|
||||||
<pubDate>Mon, 05 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this article provides a strategic approach to using ai for creating more persuasive presentations. it offers a specific ai prompt framework based on ancient rhetorical techniques to help professionals improve their presentation preparation..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>What's your plan for 26?</title>
|
|
||||||
<link>https://kbanc.com/claims-library/whats-your-plan-for-26</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/whats-your-plan-for-26</guid>
|
|
||||||
<pubDate>Sun, 04 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an article discussing strategy and preparation for the year 2026, likely focused on ai adoption and professional development. appears to be part of a series exploring emerging technologies and their impact on work..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Hershey's $250M AI bet: margin protection through physics</title>
|
|
||||||
<link>https://kbanc.com/claims-library/hersheys-250m-ai-bet-margin-protection-through-physics</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/hersheys-250m-ai-bet-margin-protection-through-physics</guid>
|
|
||||||
<pubDate>Thu, 01 Jan 2026 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about hershey has successfully leveraged ai to dramatically reduce product waste and accelerate innovation cycles in manufacturing. by implementing advanced sensor technologies and algorithmic analysis, the company transformed its production processes despite initial skepticism from factory operators..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>A Personal Operating System for Founders, Built in 10 Minutes with Claude Code</title>
|
|
||||||
<link>https://kbanc.com/claims-library/personal-operating-system-for-founders</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/personal-operating-system-for-founders</guid>
|
|
||||||
<pubDate>Wed, 31 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an ai-generated personal productivity system for founders and ceos that helps with systematic self-reflection and goal tracking. the system is designed to be simple, non-technical, and easily implemented in under 10 minutes. it provides a structured approach to daily, weekly, quarterly, and annual personal reviews..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>How do I use ChatGPT for quarterly planning?</title>
|
|
||||||
<link>https://kbanc.com/claims-library/how-to-use-chatgpt-for-quarterly-planning</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/how-to-use-chatgpt-for-quarterly-planning</guid>
|
|
||||||
<pubDate>Mon, 29 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this article appears to discuss strategies for incorporating chatgpt into quarterly business planning processes. the piece likely explores how ai can assist in goal setting, strategy development, and organizational planning..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>What I learned sharing the stage with AI experts at Limitless Live 2025</title>
|
|
||||||
<link>https://kbanc.com/claims-library/ai-experts-limitless-live-2025</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/ai-experts-limitless-live-2025</guid>
|
|
||||||
<pubDate>Sat, 27 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about a summary of insights from an ai panel discussing how professionals can effectively leverage ai tools. the discussion covered practical strategies for integrating ai into work and creative processes, emphasizing human direction and critical thinking..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Hallmark Spent 115 Years Selling Effort, Then AI Showed Up</title>
|
|
||||||
<link>https://kbanc.com/claims-library/hallmark-spent-115-years-selling-effort-then-ai-showed-up</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/hallmark-spent-115-years-selling-effort-then-ai-showed-up</guid>
|
|
||||||
<pubDate>Wed, 24 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about hallmark demonstrates a unique ai strategy focused on operational improvement rather than customer-facing generative tools. by making ai invisible and focusing on relationship tracking, they've maintained the human touch in greeting card production while leveraging machine learning behind the scenes..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>The AI Skill That Actually Gets You Hired in 2026</title>
|
|
||||||
<link>https://kbanc.com/claims-library/ai-skill-hired-2026</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/ai-skill-hired-2026</guid>
|
|
||||||
<pubDate>Tue, 23 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an analysis of emerging ai career dynamics, focusing on the shift from pure coding skills to strategic product thinking and business understanding. the article explores how professionals can position themselves effectively in an evolving ai job market..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>How to Know Exactly Who to Promote, Develop, or Let Go</title>
|
|
||||||
<link>https://kbanc.com/claims-library/how-to-know-exactly-who-to-promote-develop-or-let-go</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/how-to-know-exactly-who-to-promote-develop-or-let-go</guid>
|
|
||||||
<pubDate>Mon, 22 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about a strategic approach to employee assessment using the 9-box grid methodology, which helps managers systematically evaluate team members based on current performance and future potential. the article provides an ai-guided framework for making critical talent management decisions..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Why did Kroger give up on robots and switch to store-based AI?</title>
|
|
||||||
<link>https://kbanc.com/claims-library/kroger-robots-ai-pivot</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/kroger-robots-ai-pivot</guid>
|
|
||||||
<pubDate>Thu, 18 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about kroger abandoned its seven-year robotic warehouse project after spending significant resources and incurring substantial financial losses. the company shifted from hardware-based solutions to software and data science approaches to drive margin expansion. this case study highlights the challenges of technological innovation in retail logistics..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>How I Create All My Newsletter Visuals Without Any Design Skills</title>
|
|
||||||
<link>https://kbanc.com/claims-library/newsletter-visuals-without-design-skills</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/newsletter-visuals-without-design-skills</guid>
|
|
||||||
<pubDate>Tue, 16 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about the article provides a step-by-step workflow for creating custom newsletter visuals using ai tools without requiring professional design skills. the author outlines a systematic approach using five different tools to generate, customize, and optimize visual content efficiently..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>The One-leak Method That Fixes Funnels Faster than Full Audits</title>
|
|
||||||
<link>https://kbanc.com/claims-library/one-leak-method-fixes-funnels-faster</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/one-leak-method-fixes-funnels-faster</guid>
|
|
||||||
<pubDate>Mon, 15 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an article introducing an ai-powered diagnostic tool designed to quickly identify and resolve the most costly leak in a sales funnel. the method promises faster optimization compared to comprehensive funnel audits by targeting the highest-impact issue..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>3 Ways Instacart Made Themselves Essential to Every Client They Work With</title>
|
|
||||||
<link>https://kbanc.com/claims-library/3-ways-instacart-made-themselves-essential</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/3-ways-instacart-made-themselves-essential</guid>
|
|
||||||
<pubDate>Thu, 11 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about instacart transformed from a delivery service to an ai-powered operating system for grocery retail, strategically positioning themselves as indispensable to their clients. by leveraging ai for inventory, pricing, and advertising, they created deep operational integration that makes them critical to their partners' success..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Build Your Human API: Why Domain Expertise Alone Won't Make You Good at AI</title>
|
|
||||||
<link>https://kbanc.com/claims-library/build-your-human-api-why-domain-expertise-alone-wont-make-you-good-at-ai</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/build-your-human-api-why-domain-expertise-alone-wont-make-you-good-at-ai</guid>
|
|
||||||
<pubDate>Tue, 09 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about research reveals that working effectively with ai is a distinct skill, separate from domain expertise. ability to collaborate with ai does not automatically correlate with professional experience or intelligence..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>A Better Way to Design Employee Training with AI</title>
|
|
||||||
<link>https://kbanc.com/claims-library/better-way-to-design-employee-training-with-ai</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/better-way-to-design-employee-training-with-ai</guid>
|
|
||||||
<pubDate>Mon, 08 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about the article provides a practical approach to using ai for designing employee training programs quickly and effectively. it focuses on four targeted prompts that leverage learning science principles to create more specific and usable training content..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>3 Stats That Explain Why Your Coworkers Are Quietly Panicking About AI</title>
|
|
||||||
<link>https://kbanc.com/claims-library/coworkers-quietly-panicking-about-ai</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/coworkers-quietly-panicking-about-ai</guid>
|
|
||||||
<pubDate>Sun, 07 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an analysis of worker sentiment toward ai in the workplace, revealing significant anxiety and uncertainty about technological disruption. the article explores employees' perceptions of ai's potential impact on their roles and the critical need for proactive skill development..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Your AI Content Factory Has a Bottleneck, and It's Not What You Think</title>
|
|
||||||
<link>https://kbanc.com/claims-library/ai-content-factory-bottleneck</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/ai-content-factory-bottleneck</guid>
|
|
||||||
<pubDate>Fri, 05 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about companies are rapidly adopting ai for content generation but struggling with manual review processes. the article explores the challenges of ai content governance and introduces the concept of 'guardian agents' as a solution to verify and validate ai-generated content..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>AI Adopters Club</title>
|
|
||||||
<link>https://kbanc.com/claims-library/ai-adopters-club</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/ai-adopters-club</guid>
|
|
||||||
<pubDate>Thu, 04 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this appears to be a substack publication focused on ai adoption and insights. the article seems to be a paid/members-only content piece by author kamil banc..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Every Junior Role You Cut With AI Is a Senior Hire You'll Overpay for Later</title>
|
|
||||||
<link>https://kbanc.com/claims-library/every-junior-role-you-cut-with-ai</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/every-junior-role-you-cut-with-ai</guid>
|
|
||||||
<pubDate>Wed, 03 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about companies cutting junior roles due to ai efficiency are creating a hidden talent pipeline problem. by eliminating entry-level positions that traditionally build professional skills and judgment, organizations risk creating a leadership gap in future years..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Make yourself indispensable at work by solving the AI problem no one sees</title>
|
|
||||||
<link>https://kbanc.com/claims-library/make-yourself-indispensable-ai-problem</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/make-yourself-indispensable-ai-problem</guid>
|
|
||||||
<pubDate>Tue, 02 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this article explores how professionals can position themselves as ai experts by addressing the gap between ai adoption beliefs and actual implementation. it highlights the challenges of unguided ai tool usage in organizations and offers a strategy for individuals to build career leverage..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Your AI gives everyone the same answer. Here's how to get the good ones it's hiding.</title>
|
|
||||||
<link>https://kbanc.com/claims-library/ai-prompting-diversity-creativity</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/ai-prompting-diversity-creativity</guid>
|
|
||||||
<pubDate>Mon, 01 Dec 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about a stanford research team discovered a single prompting technique can restore creative diversity in ai assistants without retraining or modifying code. this method allows users to generate significantly more unique and varied outputs from their ai tools..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>How To Become an AI Translator and Get Promoted</title>
|
|
||||||
<link>https://kbanc.com/claims-library/how-to-become-an-ai-translator-and-get-promoted</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/how-to-become-an-ai-translator-and-get-promoted</guid>
|
|
||||||
<pubDate>Fri, 28 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about the article explores the emerging role of an ai translator who bridges communication between business teams and technical teams. it discusses how professionals can transition from shadow ai usage to becoming strategic ai implementation experts..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>RIP Shadow IT, How to Become an AI Translator for Your Boss</title>
|
|
||||||
<link>https://kbanc.com/claims-library/rip-shadow-it-how-to-become-an-ai-translator-for-your-boss</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/rip-shadow-it-how-to-become-an-ai-translator-for-your-boss</guid>
|
|
||||||
<pubDate>Fri, 28 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this article explores the transition from unauthorized ai tool usage to strategic ai implementation in organizations. it provides a framework for transforming 'shadow ai' into sanctioned, governed ai solutions that align with business needs..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>How Nescafé cut product development from 3 months to 3 weeks</title>
|
|
||||||
<link>https://kbanc.com/claims-library/how-nescafe-cut-product-development</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/how-nescafe-cut-product-development</guid>
|
|
||||||
<pubDate>Thu, 27 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about nescafé transformed its product development process using ai technologies, dramatically reducing innovation cycles and improving operational efficiency. by leveraging predictive technologies, the company cut product ideation time from months to weeks and generated significant cost savings..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Your job title means nothing to AI</title>
|
|
||||||
<link>https://kbanc.com/claims-library/job-title-means-nothing-to-ai</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/job-title-means-nothing-to-ai</guid>
|
|
||||||
<pubDate>Wed, 26 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about the article explores how professionals can effectively use ai by breaking down their work into specific, executable workflows instead of relying on abstract job titles. it provides a framework for translating complex tasks into machine-readable instructions that leverage ai's capabilities..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Google's Nano Banana Pro Is Finally Ready For Business</title>
|
|
||||||
<link>https://kbanc.com/claims-library/google-nano-banana-pro-business</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/google-nano-banana-pro-business</guid>
|
|
||||||
<pubDate>Mon, 24 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an exploration of google's nano banana pro api, which promises advanced ai-generated visual capabilities for business product mockups and marketing materials. the tool aims to solve common ai image generation problems like incorrect text and brand representation..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>JPMorgan Spent $18 Billion on AI. The Best ROI Came From Contract Review.</title>
|
|
||||||
<link>https://kbanc.com/claims-library/jpmorgan-ai-contract-review</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/jpmorgan-ai-contract-review</guid>
|
|
||||||
<pubDate>Thu, 20 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about jpmorgan invested heavily in ai technology, generating significant value through strategic implementation. the most impactful use case was contract review automation, which saved hundreds of thousands of work hours. other productivity gains came from coding assistants and document processing tools..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>The AI Reflex: Building Intuition While Everyone Else Googles Prompt Templates</title>
|
|
||||||
<link>https://kbanc.com/claims-library/ai-reflex-building-intuition</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/ai-reflex-building-intuition</guid>
|
|
||||||
<pubDate>Wed, 19 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an article exploring how to develop an instinctive approach to using ai tools in professional settings, moving beyond simple prompt engineering. the piece argues that successful ai adoption requires building a reflexive, integrated relationship with ai technologies..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Five AI Systems That Raise Your Business Valuation</title>
|
|
||||||
<link>https://kbanc.com/claims-library/five-ai-systems-that-raise-your-business-valuation</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/five-ai-systems-that-raise-your-business-valuation</guid>
|
|
||||||
<pubDate>Tue, 18 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this article explores how ai can help businesses improve their valuation by systematically reducing operational risks and creating more predictable systems. it details five specific ai-powered approaches that can transform a business's attractiveness to potential buyers and increase its market value..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Stop Guessing What Your Customers Want and Start Asking AI</title>
|
|
||||||
<link>https://kbanc.com/claims-library/stop-guessing-what-your-customers-want-and-start-asking-ai</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/stop-guessing-what-your-customers-want-and-start-asking-ai</guid>
|
|
||||||
<pubDate>Mon, 17 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about this article discusses how ai can transform customer persona development by focusing on concrete decision criteria instead of superficial demographic details. it outlines a method for using ai to extract meaningful insights about customer needs, pricing strategies, and sales objections..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>When the Patient Builds Better AI Than the Hospital</title>
|
|
||||||
<link>https://kbanc.com/claims-library/when-the-patient-builds-better-ai-than-the-hospital</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/when-the-patient-builds-better-ai-than-the-hospital</guid>
|
|
||||||
<pubDate>Fri, 14 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an article about how an individual used multi-agent ai to diagnose his own rare cancer after medical specialists missed it. the story explores how careful ai-assisted preparation can dramatically improve decision-making in high-stakes scenarios like medical treatment and professional meetings..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>Sports stadiums spent billions testing AI so you don't have to</title>
|
|
||||||
<link>https://kbanc.com/claims-library/sports-stadiums-ai-implementation</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/sports-stadiums-ai-implementation</guid>
|
|
||||||
<pubDate>Thu, 13 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about sports stadiums are pioneering large-scale ai implementation across complex operational environments. by solving critical challenges in crowd management, revenue optimization, and efficiency, they've created a replicable playbook for ai adoption across industries..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>The AI Photo Prompt That Gets You Free Appetizers (Challenge Inside)</title>
|
|
||||||
<link>https://kbanc.com/claims-library/ai-photo-prompt-free-appetizers</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/ai-photo-prompt-free-appetizers</guid>
|
|
||||||
<pubDate>Wed, 12 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an article exploring how to use ai prompts to transform mediocre restaurant and business photos into professional-quality marketing images. the technique involves using chatgpt to enhance visual content for small businesses and entrepreneurs with limited budgets..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
|
||||||
<title>I Just Watched Predator: Badlands. It's About Your Career</title>
|
|
||||||
<link>https://kbanc.com/claims-library/predator-badlands-career-adaptability</link>
|
|
||||||
<guid>https://kbanc.com/claims-library/predator-badlands-career-adaptability</guid>
|
|
||||||
<pubDate>Tue, 11 Nov 2025 00:00:00 GMT</pubDate>
|
|
||||||
<description>5 atomic claims about an article exploring career adaptability through the lens of a predator movie, highlighting how professionals can thrive in a rapidly changing work environment. the piece argues that adaptive skills are more important than technical expertise in the modern workplace..</description>
|
|
||||||
<author>kamil@kbanc.com (Kamil Banc)</author>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>How to Get AI Market Research That Survives CFO Scrutiny</title>
|
<title>How to Get AI Market Research That Survives CFO Scrutiny</title>
|
||||||
<link>https://kbanc.com/claims-library/ai-market-research-cfo-scrutiny</link>
|
<link>https://kbanc.com/claims-library/ai-market-research-cfo-scrutiny</link>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,239 @@
|
||||||
|
# kbanc.com
|
||||||
|
|
||||||
|
> AI implementation insights from Kamil Banc. 135 atomic claims extracted from 27 articles about AI adoption, strategy, tools, and measurement.
|
||||||
|
|
||||||
|
## Claims Library
|
||||||
|
|
||||||
|
### [How to Get AI Market Research That Survives CFO Scrutiny](https://kbanc.com/claims-library/ai-market-research-cfo-scrutiny)
|
||||||
|
Published: 2025-11-10 | Topics: strategy, tools, measurement
|
||||||
|
1. McKinsey testing revealed that AI-generated sector analysis frequently contains citation inflation and conclusions contradicting cited sources.
|
||||||
|
2. Thirty-eight percent of AI-generated market research reports contain at least one material factual error requiring correction.
|
||||||
|
3. LLM-generated analysis often includes unfounded projections that lack verification when stakeholders request source documentation for claims.
|
||||||
|
4. Treating AI as a report vending machine produces confident but unreliable outputs with unverifiable statistics and claims.
|
||||||
|
5. Proper research prompts can trace every claim to authoritative sources including SEC filings, government data, and academic research.
|
||||||
|
|
||||||
|
### [Leaders who use AI daily scale it 3x faster than those who delegate](https://kbanc.com/claims-library/leaders-use-ai-daily-scale-3x-faster)
|
||||||
|
Published: 2025-11-10 | Topics: strategy, implementation, business
|
||||||
|
1. Leaders who personally use AI tools are three times more likely to scale AI across their organizations.
|
||||||
|
2. Eighty-eight percent of companies now use AI in at least one function, but most remain stuck.
|
||||||
|
3. Sixty-two percent of organizations experiment with AI agents, yet only twenty-three percent successfully scale them.
|
||||||
|
4. Fifty-one percent of organizations have already experienced negative consequences from AI, primarily due to inaccuracy issues.
|
||||||
|
5. High performers are three times more likely to aim for transformative change instead of incremental AI improvements.
|
||||||
|
|
||||||
|
### [Your Team Stopped Questioning AI Six Weeks Ago](https://kbanc.com/claims-library/team-stopped-questioning-ai)
|
||||||
|
Published: 2025-11-07 | Topics: strategy, tools, implementation
|
||||||
|
1. Microsoft Research found teams using AI for six months showed declining critical evaluation skills as delegation increased.
|
||||||
|
2. A strategy team's AI-drafted market entry plan resulted in a two million dollar mistake from unquestioned assumptions.
|
||||||
|
3. MBA students using thinker AI took three hours but identified stakeholder risks doer AI missed completely.
|
||||||
|
4. Doer AI executes tasks like drafting emails and summarizing documents while thinker AI challenges assumptions and gaps.
|
||||||
|
5. Water rights conflict identified by thinker AI would have cost fifty million dollars to fix post-launch.
|
||||||
|
|
||||||
|
### [Rockstar's $10 Billion AI Secret](https://kbanc.com/claims-library/rockstars-10-billion-ai-secret)
|
||||||
|
Published: 2025-11-06 | Topics: strategy, business, implementation
|
||||||
|
1. Take-Two's CEO publicly dismissed AI creativity while filing patents for AI-generated building interiors and NPC awareness
|
||||||
|
2. Rockstar patents Virtual Navigation AI for driver awareness and Procedural Interiors auto-generating unique buildings
|
||||||
|
3. The $12.7 billion Zynga acquisition targeted AI platforms for player behavior analysis and churn prediction
|
||||||
|
4. AI prediction engines power microtransactions that drive 75% of Take-Two's net bookings
|
||||||
|
5. Red Dead 2 required 1,600 people working 50-60 hours weekly for a year—unsustainable for GTA VI
|
||||||
|
|
||||||
|
### [The Internal Tools You Can Vibe Code and the Ones That Will Cost You Later](https://kbanc.com/claims-library/vibe-coding-technical-expertise)
|
||||||
|
Published: 2025-11-04 | Topics: strategy, implementation
|
||||||
|
1. AI autocomplete handles 95% of code generation for experienced developers using Cursor
|
||||||
|
2. Self-contained features like Spotify Wrapped clone can be built entirely with AI coding platforms
|
||||||
|
3. Production system maintenance requires understanding codebase architecture, debugging patterns, and infrastructure dependencies
|
||||||
|
4. Building a product once costs less than maintaining custom internal software long-term
|
||||||
|
5. Solo technical founders gain significant leverage with AI coding tools; non-technical founders face scaling limits
|
||||||
|
|
||||||
|
### [The AI Prompt That Maps Employee Skill Gaps in One Session](https://kbanc.com/claims-library/ai-prompt-maps-employee-skill-gaps-one-session)
|
||||||
|
Published: 2025-11-03 | Topics: tools, implementation, strategy
|
||||||
|
1. Structured prompt interviews managers through six categories: employee basics, performance, role requirements, development goals, resources
|
||||||
|
2. Standard AI prompts accept incomplete data upfront, causing costly assumptions like $5,000 certifications on $500 budgets
|
||||||
|
3. Complete analysis takes 15 minutes: executive summary, prioritized gaps, development timeline, investment breakdown, monitoring plan
|
||||||
|
4. Prompt catches tensions like employees wanting leadership roles when their gap is technical execution
|
||||||
|
5. Each gap links to performance evidence with targeted recommendations within stated budget and timeframe
|
||||||
|
|
||||||
|
### [Vibe Hackathons Transform AI Adoption in Three Hours](https://kbanc.com/claims-library/vibe-hackathons)
|
||||||
|
Published: 2025-11-01 | Topics: strategy, implementation
|
||||||
|
1. Vibe hackathons shift AI from abstract concept to daily tool in three hours
|
||||||
|
2. Mixed teams combining technical and non-technical staff identify automation opportunities developers miss
|
||||||
|
3. Executive participation in hackathons signals support for experimentation and surfaces friction points
|
||||||
|
4. ChatGPT usage doubles the week after hackathons because people experience creation satisfaction
|
||||||
|
5. Single-page prototypes with no databases can be built in two to four hours
|
||||||
|
|
||||||
|
### [Hilton Deployed 41 AI Use Cases. Three Paid Back in Six Months.](https://kbanc.com/claims-library/hilton-deployed-41-ai-use-cases-three-paid-back-in-six-months)
|
||||||
|
Published: 2025-10-30 | Topics: strategy, implementation, measurement
|
||||||
|
1. Hilton operates 41 distinct AI use cases as live systems across 7,500 properties in 138 countries
|
||||||
|
2. AI-powered marketing campaigns at Hilton properties delivered strong double-digit incremental revenue growth
|
||||||
|
3. Food waste dropped over 60% in 200 Hilton hotels using Winnow's AI kitchen scales
|
||||||
|
4. Customer service chatbots cut query resolution times by 50% with 90% positive feedback
|
||||||
|
5. Hilton migrated reservations to cloud and built unified property management before deploying AI
|
||||||
|
|
||||||
|
### [Systems thinking makes your AI skills actually useful](https://kbanc.com/claims-library/systems-thinking-ai-skill)
|
||||||
|
Published: 2025-10-29 | Topics: strategy, implementation
|
||||||
|
1. Amazon's hiring algorithm collapsed because engineers optimized for historical patterns without mapping how those patterns formed
|
||||||
|
2. Starbucks reduced wait times without adding staff by mapping customer flow, movement, equipment as system
|
||||||
|
3. Automating without mapping dependencies shifts work to marketing, support, IT who inherit edge cases
|
||||||
|
4. Starbucks improved performance by simplifying menu layouts, repositioning equipment based on movement patterns, and adding order-ahead capability
|
||||||
|
5. Systems thinking helps anticipate ripple effects, avoid unintended consequences, and design solutions that align with broader organizational contexts
|
||||||
|
|
||||||
|
### [Your Voice AI Demo Works Great Until Real Customers Call](https://kbanc.com/claims-library/improve-your-voice-ai-with-assemblyai)
|
||||||
|
Published: 2025-10-28 | Topics: tools, implementation, business
|
||||||
|
1. 97% of voice AI projects fail at transcription where lab accuracy collapses under production conditions
|
||||||
|
2. Companies using voice AI handle 20-30% more calls with 30-40% fewer agents, cutting costs 30%
|
||||||
|
3. Building custom speech recognition requires 18-36 months, millions in budget before shipping to customers
|
||||||
|
4. Calabrio increased satisfaction 80%, reduced developer time 62.5% after switching to specialist transcription provider
|
||||||
|
5. Voice AI market grows from $3.14 billion in 2024 to $47.5 billion by 2034
|
||||||
|
|
||||||
|
### [Run a $150K market entry study in 20 minutes](https://kbanc.com/claims-library/market-entry-research-prompt)
|
||||||
|
Published: 2025-10-27 | Topics: strategy, tools, business
|
||||||
|
1. Consulting firms charge $150K for market entry studies following standard seven-domain research scripts
|
||||||
|
2. AI tools complete multi-step research in 10-20 minutes, reducing traditional research time by 60-70%
|
||||||
|
3. Market research difficulty stems from not knowing which questions to ask in what sequence
|
||||||
|
4. Structured prompts generate 3,000-5,000 word strategic plans with executive summaries and detailed roadmaps
|
||||||
|
5. Consultants sell question sequences and methodology, not proprietary data or exclusive market intelligence
|
||||||
|
|
||||||
|
### [Alpha School: How Two Hours of AI-Led Learning Beats a Full Day of Classes](https://kbanc.com/claims-library/alpha-school-how-two-hours-of-ai-led-learning-beats-full-day-classes)
|
||||||
|
Published: 2025-10-23 | Topics: strategy, implementation, business
|
||||||
|
1. Schools compressed core curriculum into two focused hours of adaptive practice with automated feedback
|
||||||
|
2. Teachers spent triple the time mentoring individuals after implementing the AI-led learning model
|
||||||
|
3. Students hit mastery targets quicker under the compressed two-hour AI-led curriculum approach
|
||||||
|
4. Parents received transparent student progress updates every Friday in the new AI-led system
|
||||||
|
5. Most pilots fail: automating wrong tasks, under-staffing humans, skipping governance, measuring activity not outcomes
|
||||||
|
|
||||||
|
### [I looked at 30 days of my AI conversations and found something surprising](https://kbanc.com/claims-library/30-days-ai-conversations-surprising-patterns)
|
||||||
|
Published: 2025-10-22 | Topics: strategy, implementation, tools
|
||||||
|
1. The author identified 10 distinct repeating patterns in 30 days of AI conversation history across ChatGPT and Claude
|
||||||
|
2. Email triage prompts filter inbox to identify what needs response today, who's waited 48+ hours
|
||||||
|
3. Prompt optimization merges multiple templates into single reusable tools under 200 words for varied cases
|
||||||
|
4. Custom skills enable repeatable workflows like morning briefings analyzing 7 days of Gmail on command
|
||||||
|
5. Effective AI prompts specify context, constraints, output format, and exclusions as systematic infrastructure
|
||||||
|
|
||||||
|
### [Claude Skills cuts 8-hour tasks down to 1 hour](https://kbanc.com/claims-library/claude-skills-productivity-boost)
|
||||||
|
Published: 2025-10-21 | Topics: tools, implementation
|
||||||
|
1. Rakuten compressed an 8-hour task into 1 hour using Claude Skills with same quality
|
||||||
|
2. Claude Skills load instructions only when relevant rather than reading all instructions every time
|
||||||
|
3. Claude's pre-built Excel Skill achieved 83% accuracy on expert-level financial modeling tests
|
||||||
|
4. Skills cannot exceed 8MB total file size and don't work with extended thinking mode
|
||||||
|
5. Skills work best for high-volume repetitive tasks with small variations in data
|
||||||
|
|
||||||
|
### [Claude Skills - Business Implementation Guide](https://kbanc.com/claims-library/claude-skills-business-implementation-guide)
|
||||||
|
Published: 2025-10-21 | Topics: implementation, business, tools
|
||||||
|
1. The guide provides detailed breakdowns comparing Claude Skills with ChatGPT's GPTs and Microsoft Copilot for specific business scenarios
|
||||||
|
2. Pre-built Skill examples are included that can be copied and customized immediately without starting from scratch
|
||||||
|
3. The guide includes a scaling playbook that addresses moving from one Skill to dozens across an organization
|
||||||
|
4. Training methodologies for teams and measurement frameworks for results are provided as part of the implementation guide
|
||||||
|
5. The guide identifies common mistakes in Skills implementation that waste organizational time and money
|
||||||
|
|
||||||
|
### [Training your AI reflex muscle is easier than you think](https://kbanc.com/claims-library/training-your-ai-reflex-muscle-is-easier-than-you-think)
|
||||||
|
Published: 2025-10-20 | Topics: strategy, implementation, tools
|
||||||
|
1. AI adoption failure is primarily a habit problem rather than a training problem
|
||||||
|
2. Building an AI reflex muscle can be accomplished in a 20-minute exercise
|
||||||
|
3. The exercise involves identifying three time-wasting tasks, selecting one, and creating a solution using ChatGPT or Claude
|
||||||
|
4. The reflex to automatically spot AI opportunities is more valuable than individual automated solutions
|
||||||
|
5. Regular practice trains the brain to automatically identify tasks suitable for AI automation
|
||||||
|
|
||||||
|
### [Your team uses AI daily and you still see no ROI](https://kbanc.com/claims-library/your-team-uses-ai-daily-and-you-still-see-no-roi)
|
||||||
|
Published: 2025-10-18 | Topics: strategy, measurement, business
|
||||||
|
1. BCG studied 1,250 companies: 95% see zero measurable ROI from AI investments despite high usage
|
||||||
|
2. Top 5% concentrate AI investment in R&D, sales, marketing, manufacturing, IT—delivering 2x revenue growth
|
||||||
|
3. 78% of firms use AI, yet 83% see no profit impact—adoption doesn't equal results
|
||||||
|
4. 70% of product teams using AI report revenue increases; supply chain teams cut costs 20%+
|
||||||
|
5. Companies use only 47% of SaaS licenses, wasting an average of $21M annually
|
||||||
|
|
||||||
|
### [Amazon Cuts Costs 25% With AI: Here's Their Exact Process](https://kbanc.com/claims-library/amazon-ai-playbook)
|
||||||
|
Published: 2025-10-16 | Topics: strategy, implementation
|
||||||
|
1. Amazon's recommendation engine generates $200 billion in annual sales representing 35% of total e-commerce revenue
|
||||||
|
2. The Working Backwards process starts with a mock press release written from the customer's perspective before building anything
|
||||||
|
3. Amazon reduced warehouse operating costs by 25% through AI-powered robotic systems and predictive inventory placement
|
||||||
|
4. Teams spend more time on press release iteration than on technical architecture, ensuring customer value before building
|
||||||
|
5. Amazon's AI implementation follows a three-phase pattern: customer value identification, metric definition, and iterative deployment
|
||||||
|
|
||||||
|
### [AI Adoption Isn't a Training Problem. It's a Habit Problem.](https://kbanc.com/claims-library/ai-adoption-isnt-a-training-problem-its-a-habit-problem)
|
||||||
|
Published: 2025-10-14 | Topics: strategy, implementation, business
|
||||||
|
1. 42% abandoned AI initiatives in 2025, up from 17%—double typical technology failure rates
|
||||||
|
2. Employees use AI three times more than managers think, proving capability exists but environments prevent habits
|
||||||
|
3. Thomson Reuters hit 100% AI adoption by redesigning workflows, not training—making AI the easiest path
|
||||||
|
4. 99% of AI implementations caused losses, with 64% losing over $1 million from compliance failures
|
||||||
|
5. 45% of workplace behavior stems from location and time triggers, not willpower—environment drives habits
|
||||||
|
|
||||||
|
### [This Procurement Prompt Stops You from Wasting Money on Software Nobody Uses](https://kbanc.com/claims-library/procurement-prompt-stops-software-waste)
|
||||||
|
Published: 2025-10-13 | Topics: strategy, tools, implementation
|
||||||
|
1. Mid-size companies waste $18 million annually on unused software subscriptions they never deploy
|
||||||
|
2. Organizations actively use only 47% of the SaaS licenses they pay for annually
|
||||||
|
3. Wasted software spend equals $4,830 per employee, representing a 21.9% increase from the previous year.
|
||||||
|
4. Shadow IT accounts for 48% of total IT spending in some organizations.
|
||||||
|
5. 30% of company applications overlap in functionality due to uncoordinated purchasing decisions.
|
||||||
|
|
||||||
|
### [How to Use Sora 2 to Create Your Own Marketing Videos (Without Hiring Anyone)](https://kbanc.com/claims-library/sora-2-ad-creation-workflow)
|
||||||
|
Published: 2025-10-10 | Topics: tools, implementation, strategy
|
||||||
|
1. Five of six scenes generated successfully first try; only closing scene required fifteen iterations
|
||||||
|
2. AI tool stack (Sora 2, ChatGPT Plus, Suno, Eleven Labs) costs $35 monthly for 45-minute production cycles
|
||||||
|
3. Notebook LM synthesized newsletter archives to extract positioning, feeding refined messaging back into ChatGPT scripts
|
||||||
|
4. Sora 2 lacks context retention; each scene requires complete self-contained description with subject, setting, action
|
||||||
|
5. Final ad generated strong audience engagement; people assumed it required days or professional production team
|
||||||
|
|
||||||
|
### [Just Do It With Data: Nike's $500M AI Gamble](https://kbanc.com/claims-library/nike-500m-ai-gamble-direct-sales-transformation)
|
||||||
|
Published: 2025-10-09 | Topics: strategy, business, implementation
|
||||||
|
1. Nike's direct sales grew from $11.8 billion to $23 billion using AI-powered transformation
|
||||||
|
2. Nike acquired four AI startups, building complete AI capability in 36 months versus typical 5 years
|
||||||
|
3. Nike's first-party data ecosystem generates 4x higher customer lifetime value compared to traditional approaches.
|
||||||
|
4. Nike's supply chain AI tripled digital fulfillment capacity while simultaneously reducing operational costs.
|
||||||
|
5. Nike's first digital sales decline since 2015 caused a $70 billion market cap loss
|
||||||
|
|
||||||
|
### [Why Judgment Is Your New Career Currency](https://kbanc.com/claims-library/ai-judgment-skills)
|
||||||
|
Published: 2025-10-08 | Topics: strategy, business
|
||||||
|
1. AI will fully replace just 0.7% of job-related skills per CNBC—disruption affects competencies
|
||||||
|
2. AI dominates forecasting outcomes; humans decide which predictions to trust and what actions follow
|
||||||
|
3. Law partners draft contracts in 30 minutes using AI, eliminating traditional junior associate apprenticeships
|
||||||
|
4. Harvard research shows structured pre-decision notes improve outcomes, requiring explicit reasoning before committing to major choices
|
||||||
|
5. Good Judgment Project: forecasters tracking accuracy improve 30% faster than those who don't
|
||||||
|
|
||||||
|
### [5 Signs You're Using AI as an Assistant When It Should Be Your Advisor](https://kbanc.com/claims-library/ai-strategic-partner)
|
||||||
|
Published: 2025-10-07 | Topics: strategy, implementation
|
||||||
|
1. Microsoft's research on 297 early Copilot users found that high-value implementations involve iterative collaboration rather than one-off queries
|
||||||
|
2. Human-AI collaboration in medical diagnosis achieves 90% accuracy, surpassing humans alone (81%) or AI alone (73%)
|
||||||
|
3. McDonald's China increased monthly employee AI transactions from 2,000 to 30,000 after implementing Azure AI and GitHub Copilot
|
||||||
|
4. Most enterprises skip foundational adoption stages; 68% of C-suite report rushed integration creates division
|
||||||
|
5. Effective AI co-thinking requires memory retention, dedicated project contexts, and custom instructions promoting critical questioning over agreement
|
||||||
|
|
||||||
|
### [Make ChatGPT Writing Undetectable With Five Techniques](https://kbanc.com/claims-library/undetectable-writing)
|
||||||
|
Published: 2025-05-27 | Topics: tools, implementation
|
||||||
|
1. Active voice increases reading speed 10% and reader comprehension, making AI writing feel natural
|
||||||
|
2. Varied sentence length prevents detection patterns that expose AI-generated content to readers and tools
|
||||||
|
3. Corporate clichés like 'unlock potential' and 'game-changer' signal AI authorship to readers
|
||||||
|
4. Concrete examples replace abstract explanations, making content more credible, engaging, and memorable
|
||||||
|
5. Reading content aloud reveals unnatural phrasing that silent review typically misses or overlooks
|
||||||
|
|
||||||
|
### [How to Set Up ChatGPT Properly in Under 10 Minutes](https://kbanc.com/claims-library/chatgpt-setup)
|
||||||
|
Published: 2025-05-16 | Topics: tools, implementation
|
||||||
|
1. Enabling ChatGPT memory function eliminates context repetition and improves response relevance by learning preferences over time
|
||||||
|
2. Custom instructions defining role, constraints, and output format reduce prompt length by 60% while improving consistency
|
||||||
|
3. Configuring ChatGPT as a specific advisor type (strategic, technical, creative) shapes response style without per-prompt specification
|
||||||
|
4. Ten minutes of initial setup saves twenty hours annually by eliminating repetitive prompt refinement
|
||||||
|
5. Memory function works across conversations, building context that improves recommendations over weeks and months
|
||||||
|
|
||||||
|
### [Top 10 ChatGPT Features That Actually Matter At Work](https://kbanc.com/claims-library/chatgpt-features)
|
||||||
|
Published: 2025-04-29 | Topics: tools, implementation
|
||||||
|
1. ChatGPT's file upload feature reduced a marketing director's weekly report preparation time from 3 hours to 20 minutes
|
||||||
|
2. Custom GPTs with pre-loaded context cut strategic planning time 70% by eliminating repetitive prompts
|
||||||
|
3. Voice mode enables hands-free brainstorming during commutes, reclaiming previously unproductive daily commute time
|
||||||
|
4. The Canvas feature allows side-by-side editing with AI, reducing the copy-paste workflow that breaks creative flow
|
||||||
|
5. ChatGPT's web search integration provides cited sources, eliminating the need to switch between AI and traditional search
|
||||||
|
|
||||||
|
## Topics
|
||||||
|
|
||||||
|
- [AI Strategy](https://kbanc.com/ai-strategy): Strategic planning and implementation approaches for AI adoption
|
||||||
|
- [AI Implementation](https://kbanc.com/ai-implementation): Hands-on implementation techniques and frameworks
|
||||||
|
- [AI Tools](https://kbanc.com/ai-tools): Practical tools and platforms for AI implementation
|
||||||
|
- [AI Business Applications](https://kbanc.com/ai-business-applications): Real-world business use cases and applications
|
||||||
|
- [Measuring AI ROI](https://kbanc.com/measuring-ai-roi): Measuring AI impact and return on investment
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
- [About Kamil Banc](https://kbanc.com/about)
|
||||||
|
- [FAQ](https://kbanc.com/faq)
|
||||||
|
- [How I Built This](https://kbanc.com/how-i-built-this)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
All claims licensed under CC BY 4.0. Attribution: "Kamil Banc, AI Adopters Club" + link to kbanc.com/claims-library/[slug]
|
||||||
|
|
@ -0,0 +1,47 @@
|
||||||
|
# kbanc.com
|
||||||
|
|
||||||
|
> AI implementation insights from Kamil Banc. 135 atomic claims extracted from 27 articles about AI adoption, strategy, tools, and measurement.
|
||||||
|
|
||||||
|
## Claims Library
|
||||||
|
|
||||||
|
- [How to Get AI Market Research That Survives CFO Scrutiny](https://kbanc.com/claims-library/ai-market-research-cfo-scrutiny): The article discusses the challenges of AI-generated market research and provides a methodology for creating more accurate and verifiable research reports. It highlights the issues of citation inflation and unfounded projections in AI-generated analyses.
|
||||||
|
- [Leaders who use AI daily scale it 3x faster than those who delegate](https://kbanc.com/claims-library/leaders-use-ai-daily-scale-3x-faster): McKinsey research reveals that executives who personally use AI tools are three times more likely to scale AI across their organizations than those who merely sponsor initiatives. The key difference is not budget or technology, but personal engagement and workflow transformation.
|
||||||
|
- [Your Team Stopped Questioning AI Six Weeks Ago](https://kbanc.com/claims-library/team-stopped-questioning-ai): Microsoft research reveals that teams using AI without critical evaluation experience declining judgment and decision-making skills. The study highlights the importance of using AI as both a 'doer' for execution and a 'thinker' for challenging assumptions and improving strategic outcomes.
|
||||||
|
- [Rockstar's $10 Billion AI Secret](https://kbanc.com/claims-library/rockstars-10-billion-ai-secret): Take-Two Interactive's CEO publicly claims AI has "no creativity" while the company files patents for advanced AI systems. This dual narrative protects a $12.7 billion AI strategy that includes automated world-building, AI-driven QA, and player behavior prediction engines acquired through Zynga.
|
||||||
|
- [The Internal Tools You Can Vibe Code and the Ones That Will Cost You Later](https://kbanc.com/claims-library/vibe-coding-technical-expertise): Where pure AI coding succeeds and where technical knowledge remains essential
|
||||||
|
- [The AI Prompt That Maps Employee Skill Gaps in One Session](https://kbanc.com/claims-library/ai-prompt-maps-employee-skill-gaps-one-session): A structured prompt approach transforms performance reviews into actionable development plans by interviewing managers through six categories. The method prevents common AI pitfalls by collecting complete information before generating recommendations, producing budget-aligned plans in a single session.
|
||||||
|
- [Vibe Hackathons Transform AI Adoption in Three Hours](https://kbanc.com/claims-library/vibe-hackathons): Experiential learning accelerates AI adoption
|
||||||
|
- [Hilton Deployed 41 AI Use Cases. Three Paid Back in Six Months.](https://kbanc.com/claims-library/hilton-deployed-41-ai-use-cases-three-paid-back-in-six-months): Hilton operates 41 live AI use cases across 7,500 properties in 138 countries. Three systems—marketing automation, AI kitchen scales, and chatbots—delivered rapid returns by solving specific high-cost problems. The company modernized data infrastructure first, then matched proven tools to operational pain points.
|
||||||
|
- [Systems thinking makes your AI skills actually useful](https://kbanc.com/claims-library/systems-thinking-ai-skill): Most AI projects fail because teams optimize isolated tasks without mapping dependencies. Systems thinking—the ability to see how parts influence each other—separates successful implementations from expensive mistakes. Learn practical exercises to build this skill in 30 minutes.
|
||||||
|
- [Your Voice AI Demo Works Great Until Real Customers Call](https://kbanc.com/claims-library/improve-your-voice-ai-with-assemblyai): Most voice AI projects fail not at conversational design or prompts, but at transcription accuracy in production. This analysis reveals why lab benchmarks collapse under real customer audio and how the build-versus-buy decision determines whether you ship this quarter or spend years debugging.
|
||||||
|
- [Run a $150K market entry study in 20 minutes](https://kbanc.com/claims-library/market-entry-research-prompt): Market research isn't hard because data is unavailable—it's hard because people don't know what questions to ask. This article reveals how AI tools like Gemini Deep Research can run the same structured analysis consultants charge $150K for, delivering market entry plans in 20 minutes instead of months.
|
||||||
|
- [Alpha School: How Two Hours of AI-Led Learning Beats a Full Day of Classes](https://kbanc.com/claims-library/alpha-school-how-two-hours-of-ai-led-learning-beats-full-day-classes): A handful of schools split work between AI-automated delivery and human judgment, compressing core curriculum into two focused hours. The remaining time opened for projects and face-to-face coaching, with students hitting mastery targets faster while teachers tripled mentoring time.
|
||||||
|
- [I looked at 30 days of my AI conversations and found something surprising](https://kbanc.com/claims-library/30-days-ai-conversations-surprising-patterns): A detailed analysis of 30 days of ChatGPT and Claude conversations reveals 10 repeating prompt patterns that demonstrate systematic AI use. The author shares specific prompt structures for tasks like email triage, presentation assembly, and workflow documentation, showing how to treat AI as infrastructure rather than a casual tool.
|
||||||
|
- [Claude Skills cuts 8-hour tasks down to 1 hour](https://kbanc.com/claims-library/claude-skills-productivity-boost): New Claude feature saves time on repetitive tasks through saved instructions
|
||||||
|
- [Claude Skills - Business Implementation Guide](https://kbanc.com/claims-library/claude-skills-business-implementation-guide): A comprehensive guide for implementing Claude Skills in business environments. Includes tool comparisons, ready-to-use templates, and a complete playbook for scaling from first deployment to enterprise-wide adoption.
|
||||||
|
- [Training your AI reflex muscle is easier than you think](https://kbanc.com/claims-library/training-your-ai-reflex-muscle-is-easier-than-you-think): AI adoption fails because of habit problems, not training gaps. This practical guide shows how to build an AI reflex muscle in 20 minutes by automating one annoying task. The goal is developing automatic pattern recognition for AI opportunities.
|
||||||
|
- [Your team uses AI daily and you still see no ROI](https://kbanc.com/claims-library/your-team-uses-ai-daily-and-you-still-see-no-roi): BCG's study of 1,250 companies reveals why high AI adoption doesn't translate to returns. The top 5% concentrate investments in revenue-driving functions like R&D and sales, while most automate administrative tasks that don't impact the bottom line.
|
||||||
|
- [Amazon Cuts Costs 25% With AI: Here's Their Exact Process](https://kbanc.com/claims-library/amazon-ai-playbook): Amazon's systematic AI implementation methodology
|
||||||
|
- [AI Adoption Isn't a Training Problem. It's a Habit Problem.](https://kbanc.com/claims-library/ai-adoption-isnt-a-training-problem-its-a-habit-problem): Most AI rollouts fail despite extensive training because the real issue isn't capability—it's habit formation. This article reveals why 42% of AI initiatives were abandoned in 2025 and shows how to redesign workflows so AI becomes the path of least resistance, creating automatic adoption without force.
|
||||||
|
- [This Procurement Prompt Stops You from Wasting Money on Software Nobody Uses](https://kbanc.com/claims-library/procurement-prompt-stops-software-waste): Companies waste $4,830 per employee on unused software licenses annually. An AI-powered procurement prompt prevents this by forcing structured evaluation questions before any purchase, addressing the 48% shadow IT spending that creates duplicate capabilities.
|
||||||
|
- [How to Use Sora 2 to Create Your Own Marketing Videos (Without Hiring Anyone)](https://kbanc.com/claims-library/sora-2-ad-creation-workflow): A practical breakdown of creating professional marketing videos using Sora 2 and complementary AI tools in under an hour. The workflow combines ChatGPT for scripting, Notebook LM for positioning, Suno for music, and basic editing to replace agency-level production on a $35/month budget.
|
||||||
|
- [Just Do It With Data: Nike's $500M AI Gamble](https://kbanc.com/claims-library/nike-500m-ai-gamble-direct-sales-transformation): Nike invested heavily in AI between 2019-2024, acquiring four startups and growing direct sales to $23 billion. However, an aggressive digital-only strategy backfired, causing the company's first digital sales decline since 2015 and a $70 billion market cap loss from mismanaged restructuring.
|
||||||
|
- [Why Judgment Is Your New Career Currency](https://kbanc.com/claims-library/ai-judgment-skills): AI replaces 0.7% of skills, judgment becomes differentiator
|
||||||
|
- [5 Signs You're Using AI as an Assistant When It Should Be Your Advisor](https://kbanc.com/claims-library/ai-strategic-partner): Human-AI collaboration outperforms either party independently
|
||||||
|
- [Make ChatGPT Writing Undetectable With Five Techniques](https://kbanc.com/claims-library/undetectable-writing): Five techniques to make AI writing sound natural
|
||||||
|
- [How to Set Up ChatGPT Properly in Under 10 Minutes](https://kbanc.com/claims-library/chatgpt-setup): Essential configuration for real value extraction
|
||||||
|
- [Top 10 ChatGPT Features That Actually Matter At Work](https://kbanc.com/claims-library/chatgpt-features): Most impactful workplace features with measurable savings
|
||||||
|
|
||||||
|
## Topics
|
||||||
|
|
||||||
|
- [AI Strategy](https://kbanc.com/ai-strategy): Strategic planning and implementation approaches for AI adoption
|
||||||
|
- [AI Implementation](https://kbanc.com/ai-implementation): Hands-on implementation techniques and frameworks
|
||||||
|
- [AI Tools](https://kbanc.com/ai-tools): Practical tools and platforms for AI implementation
|
||||||
|
- [AI Business Applications](https://kbanc.com/ai-business-applications): Real-world business use cases and applications
|
||||||
|
- [Measuring AI ROI](https://kbanc.com/measuring-ai-roi): Measuring AI impact and return on investment
|
||||||
|
|
||||||
|
## About
|
||||||
|
|
||||||
|
- [About Kamil Banc](https://kbanc.com/about)
|
||||||
|
- [FAQ](https://kbanc.com/faq)
|
||||||
|
- [How I Built This](https://kbanc.com/how-i-built-this)
|
||||||
|
|
@ -1,4 +1,26 @@
|
||||||
User-agent: *
|
User-agent: *
|
||||||
Allow: /
|
Allow: /
|
||||||
|
|
||||||
|
# AI Crawlers - explicitly allowed
|
||||||
|
User-agent: GPTBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: ChatGPT-User
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: PerplexityBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: ClaudeBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: anthropic-ai
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Google-Extended
|
||||||
|
Allow: /
|
||||||
|
|
||||||
Sitemap: https://kbanc.com/sitemap.xml
|
Sitemap: https://kbanc.com/sitemap.xml
|
||||||
|
|
||||||
|
# AI-readable content index
|
||||||
|
# See https://kbanc.com/llms.txt
|
||||||
|
|
|
||||||
|
|
@ -180,340 +180,4 @@
|
||||||
<changefreq>monthly</changefreq>
|
<changefreq>monthly</changefreq>
|
||||||
<priority>0.8</priority>
|
<priority>0.8</priority>
|
||||||
</url>
|
</url>
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/predator-badlands-career-adaptability</loc>
|
|
||||||
<lastmod>2025-11-11</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/ai-photo-prompt-free-appetizers</loc>
|
|
||||||
<lastmod>2025-11-12</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/sports-stadiums-ai-implementation</loc>
|
|
||||||
<lastmod>2025-11-13</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/when-the-patient-builds-better-ai-than-the-hospital</loc>
|
|
||||||
<lastmod>2025-11-14</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/stop-guessing-what-your-customers-want-and-start-asking-ai</loc>
|
|
||||||
<lastmod>2025-11-17</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/five-ai-systems-that-raise-your-business-valuation</loc>
|
|
||||||
<lastmod>2025-11-18</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/ai-reflex-building-intuition</loc>
|
|
||||||
<lastmod>2025-11-19</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/jpmorgan-ai-contract-review</loc>
|
|
||||||
<lastmod>2025-11-20</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/google-nano-banana-pro-business</loc>
|
|
||||||
<lastmod>2025-11-24</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/job-title-means-nothing-to-ai</loc>
|
|
||||||
<lastmod>2025-11-26</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/how-nescafe-cut-product-development</loc>
|
|
||||||
<lastmod>2025-11-27</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/how-to-become-an-ai-translator-and-get-promoted</loc>
|
|
||||||
<lastmod>2025-11-28</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/rip-shadow-it-how-to-become-an-ai-translator-for-your-boss</loc>
|
|
||||||
<lastmod>2025-11-28</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/ai-prompting-diversity-creativity</loc>
|
|
||||||
<lastmod>2025-12-01</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/make-yourself-indispensable-ai-problem</loc>
|
|
||||||
<lastmod>2025-12-02</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/every-junior-role-you-cut-with-ai</loc>
|
|
||||||
<lastmod>2025-12-03</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/ai-adopters-club</loc>
|
|
||||||
<lastmod>2025-12-04</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/ai-content-factory-bottleneck</loc>
|
|
||||||
<lastmod>2025-12-05</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/coworkers-quietly-panicking-about-ai</loc>
|
|
||||||
<lastmod>2025-12-07</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/better-way-to-design-employee-training-with-ai</loc>
|
|
||||||
<lastmod>2025-12-08</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/build-your-human-api-why-domain-expertise-alone-wont-make-you-good-at-ai</loc>
|
|
||||||
<lastmod>2025-12-09</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/3-ways-instacart-made-themselves-essential</loc>
|
|
||||||
<lastmod>2025-12-11</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/one-leak-method-fixes-funnels-faster</loc>
|
|
||||||
<lastmod>2025-12-15</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/newsletter-visuals-without-design-skills</loc>
|
|
||||||
<lastmod>2025-12-16</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/kroger-robots-ai-pivot</loc>
|
|
||||||
<lastmod>2025-12-18</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/how-to-know-exactly-who-to-promote-develop-or-let-go</loc>
|
|
||||||
<lastmod>2025-12-22</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/ai-skill-hired-2026</loc>
|
|
||||||
<lastmod>2025-12-23</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/hallmark-spent-115-years-selling-effort-then-ai-showed-up</loc>
|
|
||||||
<lastmod>2025-12-24</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/ai-experts-limitless-live-2025</loc>
|
|
||||||
<lastmod>2025-12-27</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/how-to-use-chatgpt-for-quarterly-planning</loc>
|
|
||||||
<lastmod>2025-12-29</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/personal-operating-system-for-founders</loc>
|
|
||||||
<lastmod>2025-12-31</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/hersheys-250m-ai-bet-margin-protection-through-physics</loc>
|
|
||||||
<lastmod>2026-01-01</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/whats-your-plan-for-26</loc>
|
|
||||||
<lastmod>2026-01-04</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/how-to-use-ai-to-prepare-presentations</loc>
|
|
||||||
<lastmod>2026-01-05</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/airstream-slashed-lead-costs-44-percent</loc>
|
|
||||||
<lastmod>2026-01-08</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/right-click-prompt-ai-prompt-manager</loc>
|
|
||||||
<lastmod>2026-01-08</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/from-ai-panic-to-ai-culture-in-2026</loc>
|
|
||||||
<lastmod>2026-01-10</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/three-prompts-capture-expert-knowledge</loc>
|
|
||||||
<lastmod>2026-01-12</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/from-zero-to-11k-ai-newsletter</loc>
|
|
||||||
<lastmod>2026-01-13</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/tax-agencies-building-ai-that-sees-everything-you-own</loc>
|
|
||||||
<lastmod>2026-01-15</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/maersk-burned-100m-on-platform-nobody-wanted</loc>
|
|
||||||
<lastmod>2026-02-06</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/stop-stacking-ai-subscriptions-until-you-pass-the-one-word-test</loc>
|
|
||||||
<lastmod>2026-02-03</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/stop-paying-500-for-legal-docs-ai-can-draft</loc>
|
|
||||||
<lastmod>2026-02-02</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/how-golf-courses-turned-ai-into-revenue-lift</loc>
|
|
||||||
<lastmod>2026-01-29</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/good-at-your-job-but-bad-at-ai</loc>
|
|
||||||
<lastmod>2026-01-28</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/5-day-lead-gen-sprint</loc>
|
|
||||||
<lastmod>2026-01-26</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/what-60k-a-year-schools-learned-about-ai</loc>
|
|
||||||
<lastmod>2026-01-22</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/when-leadership-says-go-but-means-figure-it-out-yourself</loc>
|
|
||||||
<lastmod>2026-01-21</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/prompt-sequence-exposes-weak-spots-business</loc>
|
|
||||||
<lastmod>2026-01-19</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/scientists-spent-300-million-simulating-brains</loc>
|
|
||||||
<lastmod>2026-01-18</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/non-coder-to-builder-ai-as-dev-partner</loc>
|
|
||||||
<lastmod>2026-02-09</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/vibe-code-professional-presentation-claude</loc>
|
|
||||||
<lastmod>2026-02-09</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/homeschooling-with-ai-screen-time-dream-time</loc>
|
|
||||||
<lastmod>2026-02-10</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/the-person-keeping-claude-safe-just-quit-and-chose-poetry-instead</loc>
|
|
||||||
<lastmod>2026-02-11</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/ai-chatbot-eating-disorder-nonprofit-failure</loc>
|
|
||||||
<lastmod>2026-02-12</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
<url>
|
|
||||||
<loc>https://kbanc.com/claims-library/ai-leverage-ladder-career-move</loc>
|
|
||||||
<lastmod>2026-02-14</lastmod>
|
|
||||||
<changefreq>monthly</changefreq>
|
|
||||||
<priority>0.8</priority>
|
|
||||||
</url>
|
|
||||||
</urlset>
|
</urlset>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
// Auto-generate llms.txt and llms-full.txt from centralized claims data
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { ALL_CLAIMS_DATA, SORTED_CLAIMS } from '../src/data/claims';
|
||||||
|
import { TOPICS } from '../src/lib/topics';
|
||||||
|
|
||||||
|
const baseUrl = 'https://kbanc.com';
|
||||||
|
|
||||||
|
// Calculate totals
|
||||||
|
const totalClaims = ALL_CLAIMS_DATA.reduce((sum, article) => sum + article.claims.length, 0);
|
||||||
|
const totalArticles = ALL_CLAIMS_DATA.length;
|
||||||
|
|
||||||
|
const header = `# kbanc.com
|
||||||
|
|
||||||
|
> AI implementation insights from Kamil Banc. ${totalClaims} atomic claims extracted from ${totalArticles} articles about AI adoption, strategy, tools, and measurement.`;
|
||||||
|
|
||||||
|
const topicsSection = `## Topics
|
||||||
|
|
||||||
|
- [AI Strategy](${baseUrl}/ai-strategy): Strategic planning and implementation approaches for AI adoption
|
||||||
|
- [AI Implementation](${baseUrl}/ai-implementation): Hands-on implementation techniques and frameworks
|
||||||
|
- [AI Tools](${baseUrl}/ai-tools): Practical tools and platforms for AI implementation
|
||||||
|
- [AI Business Applications](${baseUrl}/ai-business-applications): Real-world business use cases and applications
|
||||||
|
- [Measuring AI ROI](${baseUrl}/measuring-ai-roi): Measuring AI impact and return on investment`;
|
||||||
|
|
||||||
|
const aboutSection = `## About
|
||||||
|
|
||||||
|
- [About Kamil Banc](${baseUrl}/about)
|
||||||
|
- [FAQ](${baseUrl}/faq)
|
||||||
|
- [How I Built This](${baseUrl}/how-i-built-this)`;
|
||||||
|
|
||||||
|
// --- Generate llms.txt (concise) ---
|
||||||
|
|
||||||
|
function generateLlmsTxt(): string {
|
||||||
|
const lines: string[] = [header, '', '## Claims Library', ''];
|
||||||
|
|
||||||
|
for (const article of SORTED_CLAIMS) {
|
||||||
|
lines.push(`- [${article.title}](${baseUrl}/claims-library/${article.slug}): ${article.description}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.push('', topicsSection, '', aboutSection, '');
|
||||||
|
|
||||||
|
return lines.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Generate llms-full.txt (comprehensive) ---
|
||||||
|
|
||||||
|
function generateLlmsFullTxt(): string {
|
||||||
|
const lines: string[] = [header, '', '## Claims Library', ''];
|
||||||
|
|
||||||
|
for (const article of SORTED_CLAIMS) {
|
||||||
|
const topicLabels = article.topics.map(t => t.id).join(', ');
|
||||||
|
lines.push(`### [${article.title}](${baseUrl}/claims-library/${article.slug})`);
|
||||||
|
lines.push(`Published: ${article.date} | Topics: ${topicLabels}`);
|
||||||
|
|
||||||
|
article.claims.forEach((claim, i) => {
|
||||||
|
lines.push(`${i + 1}. ${claim}`);
|
||||||
|
});
|
||||||
|
|
||||||
|
lines.push('');
|
||||||
|
}
|
||||||
|
|
||||||
|
lines.push(topicsSection, '', aboutSection, '');
|
||||||
|
|
||||||
|
lines.push(`## License
|
||||||
|
|
||||||
|
All claims licensed under CC BY 4.0. Attribution: "Kamil Banc, AI Adopters Club" + link to kbanc.com/claims-library/[slug]
|
||||||
|
`);
|
||||||
|
|
||||||
|
return lines.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write files
|
||||||
|
const publicDir = path.join(process.cwd(), 'public');
|
||||||
|
|
||||||
|
const llmsTxt = generateLlmsTxt();
|
||||||
|
fs.writeFileSync(path.join(publicDir, 'llms.txt'), llmsTxt, 'utf-8');
|
||||||
|
|
||||||
|
const llmsFullTxt = generateLlmsFullTxt();
|
||||||
|
fs.writeFileSync(path.join(publicDir, 'llms-full.txt'), llmsFullTxt, 'utf-8');
|
||||||
|
|
||||||
|
console.log(`Generated llms.txt (${totalArticles} articles listed)`);
|
||||||
|
console.log(`Generated llms-full.txt (${totalClaims} claims across ${totalArticles} articles)`);
|
||||||
|
|
@ -0,0 +1,168 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import { ExternalLink, ArrowLeft, Calendar } from "lucide-react";
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "About Kamil Banc | AI Implementation Expert & Strategist",
|
||||||
|
description: "Learn about Kamil Banc's approach to AI implementation, his professional background in helping organizations adopt AI systems that generate measurable ROI, and his work with the AI Adopters Club community.",
|
||||||
|
authors: [{ name: "Kamil Banc" }],
|
||||||
|
openGraph: {
|
||||||
|
type: "profile",
|
||||||
|
url: "https://kbanc.com/about",
|
||||||
|
title: "About Kamil Banc | AI Implementation Expert & Strategist",
|
||||||
|
description: "Learn about Kamil Banc's approach to AI implementation.",
|
||||||
|
images: [{ url: "https://kbanc.com/kamil-banc-og.jpg", width: 1200, height: 630, alt: "Kamil Banc" }],
|
||||||
|
},
|
||||||
|
twitter: { card: "summary_large_image", site: "@kamilbanc", creator: "@kamilbanc", title: "About Kamil Banc | AI Implementation Expert & Strategist", description: "Learn about Kamil Banc's approach to AI implementation.", images: ["https://kbanc.com/kamil-banc-og.jpg"] },
|
||||||
|
alternates: { canonical: "https://kbanc.com/about" },
|
||||||
|
};
|
||||||
|
|
||||||
|
const jsonLd = {
|
||||||
|
"@context": "https://schema.org", "@type": "Person", name: "Kamil Banc", jobTitle: "AI Implementation Expert & Strategist",
|
||||||
|
description: "AI implementation expert helping organizations transform AI from decorative art into practical business machinery with measurable ROI.",
|
||||||
|
url: "https://kbanc.com", image: "https://kbanc.com/kamil-banc.jpg",
|
||||||
|
sameAs: ["https://www.linkedin.com/in/kbanc/", "https://aiadopters.club", "https://x.com/kamilbanc"],
|
||||||
|
knowsAbout: ["Artificial Intelligence", "AI Implementation", "AI Strategy", "Digital Transformation", "Large Language Models", "LLM Integration", "Enterprise AI", "AI ROI Measurement", "Change Management for AI", "Prompt Engineering", "Generative AI", "AI Workflow Design", "Business Process Automation"],
|
||||||
|
hasOccupation: { "@type": "Occupation", name: "AI Implementation Expert", description: "Specializes in helping organizations implement practical AI systems.", skills: ["AI Strategy Development", "LLM Implementation", "AI Workflow Design", "Change Management", "ROI Analysis"] },
|
||||||
|
affiliation: { "@type": "Organization", name: "AI Adopters Club", url: "https://aiadopters.club" },
|
||||||
|
founder: { "@type": "Organization", name: "AI Adopters Club", url: "https://aiadopters.club" },
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AboutPage() {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<script type="application/ld+json" dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }} />
|
||||||
|
<div className="min-h-screen bg-background">
|
||||||
|
<header className="border-b border-border py-6">
|
||||||
|
<div className="container max-w-[1200px] mx-auto px-6 md:px-8 lg:px-12">
|
||||||
|
<div className="flex items-center justify-between">
|
||||||
|
<Link href="/" className="inline-flex items-center gap-2 text-accent hover:underline text-sm"><ArrowLeft className="h-4 w-4" />Back to Home</Link>
|
||||||
|
<Link href="/claims-library" className="text-accent hover:underline text-sm">Claims Library</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main id="main-content" className="pb-16">
|
||||||
|
<section className="border-b border-border py-12 md:py-16">
|
||||||
|
<div className="container max-w-[1200px] mx-auto px-6 md:px-8 lg:px-12">
|
||||||
|
<div className="grid grid-cols-1 lg:grid-cols-[1fr_auto] gap-8 lg:gap-12">
|
||||||
|
<div className="space-y-6">
|
||||||
|
<div className="flex flex-row gap-6 items-center">
|
||||||
|
<img src="/kamil-banc.jpg" alt="Kamil Banc" className="w-32 h-32 md:w-40 md:h-40 rounded-lg object-cover flex-shrink-0" />
|
||||||
|
<div>
|
||||||
|
<h1 className="text-4xl md:text-5xl font-bold mb-3">About Kamil Banc</h1>
|
||||||
|
<p className="text-xl text-secondary">AI Implementation Expert & Strategist</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p className="text-lg leading-relaxed">I help organizations transform AI from decorative art into practical business machinery. My focus is on real implementations that generate measurable value.</p>
|
||||||
|
</div>
|
||||||
|
<div className="border border-border rounded-lg p-6 lg:w-80 flex-shrink-0 space-y-4 h-fit">
|
||||||
|
<div>
|
||||||
|
<h3 className="font-semibold mb-2">Join AI Adopters Club</h3>
|
||||||
|
<p className="text-sm text-muted-foreground mb-4">Access enterprise case studies, premium workflows, and our AI chatbot.</p>
|
||||||
|
<a href="https://aiadopters.club/subscribe" target="_blank" rel="noopener noreferrer" className="bg-accent hover:bg-accent/90 text-accent-foreground font-medium px-4 py-2 rounded-lg transition-colors text-center inline-flex items-center justify-center gap-2 w-full text-sm">Get Premium Access<ExternalLink className="h-3 w-3" /></a>
|
||||||
|
</div>
|
||||||
|
<div className="flex flex-col gap-2 pt-2 border-t border-border">
|
||||||
|
<a href="https://www.linkedin.com/in/kbanc/" target="_blank" rel="noopener noreferrer" className="text-accent hover:underline inline-flex items-center gap-1 text-sm">LinkedIn <ExternalLink className="h-3 w-3" /></a>
|
||||||
|
<a href="https://x.com/kamilbanc" target="_blank" rel="noopener noreferrer" className="text-accent hover:underline inline-flex items-center gap-1 text-sm">X/Twitter <ExternalLink className="h-3 w-3" /></a>
|
||||||
|
<a href="https://aiadopters.club" target="_blank" rel="noopener noreferrer" className="text-accent hover:underline inline-flex items-center gap-1 text-sm">AI Adopters Club <ExternalLink className="h-3 w-3" /></a>
|
||||||
|
<a href="https://calendly.com/kamil-banc/ai-consultation" target="_blank" rel="noopener noreferrer" className="text-accent hover:underline inline-flex items-center gap-1 text-sm"><Calendar className="h-3 w-3" />Schedule Consultation</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="py-12 md:py-16">
|
||||||
|
<div className="container max-w-[1200px] mx-auto px-6 md:px-8 lg:px-12">
|
||||||
|
<h2 className="text-3xl md:text-4xl font-bold mb-8">Professional Background</h2>
|
||||||
|
<div className="space-y-6 text-base leading-relaxed">
|
||||||
|
<p>My journey into AI implementation began not with a fascination for the technology itself, but with a frustration about how it was being adopted. I watched countless organizations invest heavily in AI initiatives only to see them fail.</p>
|
||||||
|
<p>Too many AI projects start with solutions looking for problems. My approach is different. I start with the business problem, not the technology.</p>
|
||||||
|
<p>Over the years, I have developed a framework for AI adoption that focuses on three critical elements: practical implementation patterns, organizational readiness, and continuous measurement.</p>
|
||||||
|
<p>One of the most important lessons I have learned is that successful AI adoption is fundamentally about people, not technology.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="bg-muted py-12 md:py-16">
|
||||||
|
<div className="container max-w-[1200px] mx-auto px-6 md:px-8 lg:px-12">
|
||||||
|
<h2 className="text-3xl md:text-4xl font-bold mb-8">Philosophy & Approach</h2>
|
||||||
|
<div className="space-y-6 text-base leading-relaxed">
|
||||||
|
<p>My philosophy: practical value over theoretical potential. The AI industry is full of hype. My job is to cut through that noise and focus on what actually works.</p>
|
||||||
|
<p>I believe AI should be treated as a tool for solving specific business problems. I advocate for an incremental approach to AI adoption.</p>
|
||||||
|
<p>I believe strongly in knowledge sharing and community learning. This is why I founded AI Adopters Club.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="py-12 md:py-16">
|
||||||
|
<div className="container max-w-[1200px] mx-auto px-6 md:px-8 lg:px-12">
|
||||||
|
<h2 className="text-3xl md:text-4xl font-bold mb-8">AI Adopters Club</h2>
|
||||||
|
<div className="space-y-6 text-base leading-relaxed">
|
||||||
|
<p>In 2023, I founded AI Adopters Club as a community of practitioners focused on practical AI adoption.</p>
|
||||||
|
<p>We share real case studies, implementation patterns, workflow templates, and honest assessments of what works.</p>
|
||||||
|
</div>
|
||||||
|
<div className="mt-8 border border-accent rounded-lg p-8 bg-accent/5">
|
||||||
|
<h3 className="text-2xl font-bold mb-4">Join the Community</h3>
|
||||||
|
<p className="mb-6">Get access to implementation frameworks, case studies, and a community of practitioners.</p>
|
||||||
|
<div className="flex flex-col sm:flex-row gap-4">
|
||||||
|
<a href="https://aiadopters.club/subscribe" target="_blank" rel="noopener noreferrer" className="bg-accent hover:bg-accent/90 text-accent-foreground font-medium px-6 py-3 rounded-lg transition-colors inline-flex items-center justify-center gap-2">Get Premium Access<ExternalLink className="h-4 w-4" /></a>
|
||||||
|
<a href="https://aiadopters.club" target="_blank" rel="noopener noreferrer" className="border border-border hover:bg-muted font-medium px-6 py-3 rounded-lg transition-colors inline-flex items-center justify-center gap-2">Learn More<ExternalLink className="h-4 w-4" /></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section className="border-t border-border py-12 md:py-16">
|
||||||
|
<div className="container max-w-[1200px] mx-auto px-6 md:px-8 lg:px-12">
|
||||||
|
<h2 className="text-3xl md:text-4xl font-bold mb-8">Get in Touch</h2>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-8">
|
||||||
|
<div className="space-y-6 text-base leading-relaxed">
|
||||||
|
<p>I work with organizations across industries to implement AI systems that generate measurable business value.</p>
|
||||||
|
<div className="space-y-3">
|
||||||
|
<h3 className="font-semibold text-lg">I can help with:</h3>
|
||||||
|
<ul className="space-y-2 list-disc list-inside text-muted-foreground">
|
||||||
|
<li>AI strategy development and roadmapping</li>
|
||||||
|
<li>Implementation of specific AI use cases</li>
|
||||||
|
<li>Training and capability building</li>
|
||||||
|
<li>ROI measurement and optimization</li>
|
||||||
|
<li>LLM integration and workflow design</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="bg-muted border border-border rounded-lg p-6 space-y-4">
|
||||||
|
<h3 className="font-semibold text-lg">Schedule a Consultation</h3>
|
||||||
|
<a href="https://calendly.com/kamil-banc/ai-consultation" target="_blank" rel="noopener noreferrer" className="bg-accent hover:bg-accent/90 text-accent-foreground font-medium px-4 py-2 rounded-lg transition-colors inline-flex items-center justify-center gap-2 w-full text-sm"><Calendar className="h-4 w-4" />Book Consultation</a>
|
||||||
|
</div>
|
||||||
|
<div className="bg-muted border border-border rounded-lg p-6 space-y-3">
|
||||||
|
<h3 className="font-semibold text-lg">Connect Online</h3>
|
||||||
|
<div className="flex flex-col gap-2">
|
||||||
|
<a href="https://www.linkedin.com/in/kbanc/" target="_blank" rel="noopener noreferrer" className="text-accent hover:underline inline-flex items-center gap-1 text-sm">LinkedIn <ExternalLink className="h-3 w-3" /></a>
|
||||||
|
<a href="https://x.com/kamilbanc" target="_blank" rel="noopener noreferrer" className="text-accent hover:underline inline-flex items-center gap-1 text-sm">X/Twitter <ExternalLink className="h-3 w-3" /></a>
|
||||||
|
<a href="https://aiadopters.club" target="_blank" rel="noopener noreferrer" className="text-accent hover:underline inline-flex items-center gap-1 text-sm">AI Adopters Club <ExternalLink className="h-3 w-3" /></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer className="border-t border-border py-8">
|
||||||
|
<div className="container max-w-[1200px] mx-auto px-6 md:px-8 lg:px-12">
|
||||||
|
<div className="flex flex-col md:flex-row justify-between items-center gap-4">
|
||||||
|
<p className="text-sm text-muted-foreground">© {new Date().getFullYear()} Kamil Banc. All rights reserved.</p>
|
||||||
|
<div className="flex gap-6 text-sm">
|
||||||
|
<Link href="/" className="text-accent hover:underline">Home</Link>
|
||||||
|
<Link href="/claims-library" className="text-accent hover:underline">Claims Library</Link>
|
||||||
|
<a href="https://aiadopters.club" target="_blank" rel="noopener noreferrer" className="text-accent hover:underline inline-flex items-center gap-1">AI Adopters Club <ExternalLink className="h-3 w-3" /></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,532 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { getClaimsByTopic } from "@/data/claims";
|
||||||
|
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||||
|
import TerminalFooter from "@/components/TerminalFooter";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "AI Business Applications: Complete Guide by Industry & Department | Kamil Banc",
|
||||||
|
description: "Discover the most impactful AI applications in 2024-2025. GitHub Copilot delivers 26% more PRs, customer service AI deflects 80% of queries. Real statistics and use cases by industry.",
|
||||||
|
keywords: ["AI business applications", "AI use cases", "enterprise AI", "AI by industry", "AI productivity", "AI customer service", "AI software development"],
|
||||||
|
authors: [{ name: "Kamil Banc" }],
|
||||||
|
openGraph: {
|
||||||
|
title: "AI Business Applications: Complete Guide by Industry & Department",
|
||||||
|
description: "Real statistics on AI productivity gains: 26% more developer output, 80% query deflection, double-digit ops improvements.",
|
||||||
|
url: "https://kbanc.com/ai-business-applications",
|
||||||
|
type: "article",
|
||||||
|
},
|
||||||
|
alternates: {
|
||||||
|
canonical: "https://kbanc.com/ai-business-applications",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Compile-time Article JSON-LD from static object literal - no user input */
|
||||||
|
const jsonLd = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Article",
|
||||||
|
headline: "AI Business Applications: Complete Guide by Industry & Department",
|
||||||
|
author: {
|
||||||
|
"@type": "Person",
|
||||||
|
name: "Kamil Banc",
|
||||||
|
jobTitle: "AI Implementation Expert & Strategist",
|
||||||
|
url: "https://kbanc.com/about",
|
||||||
|
image: "https://kbanc.com/kamil-banc.jpg",
|
||||||
|
},
|
||||||
|
publisher: {
|
||||||
|
"@type": "Organization",
|
||||||
|
name: "Kamil Banc",
|
||||||
|
url: "https://kbanc.com",
|
||||||
|
},
|
||||||
|
datePublished: "2024-12-20",
|
||||||
|
dateModified: "2024-12-20",
|
||||||
|
description: "Comprehensive guide to AI business applications with real statistics and use cases by industry and department.",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AIBusinessApplicationsPage() {
|
||||||
|
const businessClaims = getClaimsByTopic("business");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Compile-time Article JSON-LD from static object literal - no user input */}
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
<div className="min-h-screen bg-background">
|
||||||
|
<header className="border-b border-border py-8 mb-8">
|
||||||
|
<div className="max-w-4xl mx-auto px-6">
|
||||||
|
<Breadcrumbs
|
||||||
|
items={[
|
||||||
|
{ label: "~", href: "/" },
|
||||||
|
{ label: "ai-business-applications" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<h1 className="text-2xl md:text-3xl font-bold text-foreground mb-2">
|
||||||
|
AI Business Applications
|
||||||
|
</h1>
|
||||||
|
<p className="text-terminal-dim text-sm">
|
||||||
|
Complete guide by industry and department
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main className="max-w-4xl mx-auto px-6 pb-12">
|
||||||
|
{/* Introduction */}
|
||||||
|
<section className="terminal-panel mb-8">
|
||||||
|
<span className="terminal-panel-title">readme</span>
|
||||||
|
<p className="text-sm text-foreground mt-2 leading-relaxed mb-3">
|
||||||
|
The most impactful AI business applications in 2024-2025 are in software development, customer service, sales/marketing, operations/supply chain, and R&D. Measured productivity gains commonly range from 15-50% on specific workflows, with double-digit cost savings at scale.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground leading-relaxed">
|
||||||
|
This guide provides a structured view of AI applications by function and industry, with concrete use cases and statistics from real implementations. Whether you're starting your AI journey or scaling existing capabilities, understanding where AI delivers proven value helps prioritize investments.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Quick Stats Overview */}
|
||||||
|
<div className="grid grid-cols-2 md:grid-cols-4 gap-4 mb-12">
|
||||||
|
<div className="terminal-panel text-center">
|
||||||
|
<p className="text-3xl font-bold text-terminal-green">26%</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">More developer output</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel text-center">
|
||||||
|
<p className="text-3xl font-bold text-terminal-cyan">80%</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">Query deflection</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel text-center">
|
||||||
|
<p className="text-3xl font-bold text-terminal-yellow">14%</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">More issues/hour</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel text-center">
|
||||||
|
<p className="text-3xl font-bold text-terminal-green">55%</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">Faster task completion</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Software Engineering */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat software-engineering.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
AI coding assistants and DevOps copilots are among the clearest, quantified wins in 2024-2025, with measured productivity gains that translate directly to faster delivery and reduced costs.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="terminal-panel mb-6">
|
||||||
|
<span className="terminal-panel-title">key statistics</span>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4 mt-2">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-2xl font-bold text-terminal-green">26%</p>
|
||||||
|
<p className="text-sm text-foreground">More pull requests per week with GitHub Copilot</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">Source: Microsoft/Accenture study, 4,867 developers</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-2xl font-bold text-terminal-green">55.8%</p>
|
||||||
|
<p className="text-sm text-foreground">Faster task completion in controlled experiments</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">Source: arXiv controlled study</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">High-Impact Use Cases by Industry</h3>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground">Software & Tech</h4>
|
||||||
|
<ul className="mt-2 space-y-1 text-sm text-foreground">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Code generation and refactoring from natural-language specs</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Feature scaffolding, boilerplate, and test generation</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Incident summarization and log analysis to shorten MTTR</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground">Financial Services / Insurance IT</h4>
|
||||||
|
<ul className="mt-2 space-y-1 text-sm text-foreground">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Legacy code translation (COBOL/Java/.NET)</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Policy rules extraction into modern services</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Cutting manual effort on remediation and documentation</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground">Manufacturing IT/OT</h4>
|
||||||
|
<ul className="mt-2 space-y-1 text-sm text-foreground">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>AI assistants for automation system scripts</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Sensor/event log analysis for root-cause identification</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Reducing engineer time on low-level scripting</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-yellow mt-6">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong className="text-terminal-yellow">Business impact:</strong>{" "}
|
||||||
|
20-30%+ throughput gain on development tasks for teams that adopt AI coding tools deeply. Faster onboarding and reduced dependency on senior engineers as copilots encode patterns and best practices.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Customer Service */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat customer-service.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
Customer service is one of the most mature, ROI-proven AI domains, with measurable gains in deflection, handling times, and agent capacity.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="terminal-panel mb-6">
|
||||||
|
<span className="terminal-panel-title">key statistics</span>
|
||||||
|
<div className="grid md:grid-cols-3 gap-4 mt-2">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-2xl font-bold text-terminal-green">80%</p>
|
||||||
|
<p className="text-sm text-foreground">Routine query deflection by AI chatbots</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-2xl font-bold text-terminal-green">14%</p>
|
||||||
|
<p className="text-sm text-foreground">More issues handled per hour</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-2xl font-bold text-terminal-green">9%</p>
|
||||||
|
<p className="text-sm text-foreground">Reduction in average handle time</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel mt-4">
|
||||||
|
<p className="font-bold text-foreground">Bank of America "Erica"</p>
|
||||||
|
<p className="text-sm text-terminal-dim">1+ billion interactions, 17% call center load reduction</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">High-Impact Use Cases</h3>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground mb-2">Retail, E-commerce, Banking, Telecom</h4>
|
||||||
|
<ul className="space-y-1 text-sm text-foreground">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>24/7 virtual agents for balance/order queries</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Password resets and shipment status</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Agent copilots for knowledge surfacing</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground mb-2">B2B SaaS and Tech</h4>
|
||||||
|
<ul className="space-y-1 text-sm text-foreground">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>AI triage by intent, priority, sentiment</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Helping specialists focus on complex cases</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Multi-channel history summarization</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-yellow mt-6">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong className="text-terminal-yellow">Business impact:</strong>{" "}
|
||||||
|
30-80% deflection of routine contacts with well-designed self-service flows, leading to lower staffing needs or capacity to absorb growth. 10-20% improvement in agent productivity via faster response and summarization.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Sales & Marketing */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat sales-marketing.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
AI is materially changing pipeline generation, personalization, and content throughput across industries, enabling teams to do more with existing resources.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">High-Impact Use Cases</h3>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground mb-2">B2B Sales</h4>
|
||||||
|
<ul className="space-y-2 text-sm text-foreground">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
<strong>Lead scoring and intent prediction</strong> - Models prioritize accounts based on behavior and fit, increasing conversion rates on sales activities
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
<strong>AI email/call copilots</strong> - Suggest next best actions and draft outreach tailored to industry and role, boosting rep throughput
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground mb-2">Marketing Across Industries</h4>
|
||||||
|
<ul className="space-y-2 text-sm text-foreground">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
<strong>Content generation</strong> - Ads, landing pages, SEO articles, and localization, allowing teams to test more variants without proportional headcount
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
<strong>Customer segmentation and propensity modeling</strong> - Enable more targeted campaigns and better allocation of budget
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-yellow mt-6">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong className="text-terminal-yellow">Business impact:</strong>{" "}
|
||||||
|
Higher campaign ROI as models concentrate spend on high-propensity segments. Large time savings on content production and reporting tasks, enabling marketing teams to redeploy effort into strategy and experimentation.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Operations & Supply Chain */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat operations.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
AI in operations focuses heavily on forecasting, optimization, and automation of repetitive decision steps, delivering double-digit throughput improvements.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">High-Impact Use Cases</h3>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground mb-2">Retail, CPG, Logistics</h4>
|
||||||
|
<ul className="space-y-1 text-sm text-foreground">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Demand forecasting and inventory optimization</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Reduce stock-outs and overstock</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Dynamic routing for delivery fleets</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground mb-2">Shared Services (Finance, HR, Procurement)</h4>
|
||||||
|
<ul className="space-y-1 text-sm text-foreground">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Intelligent document processing (invoices, contracts, POs)</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Auto-extract, validate, and code line items</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>AI assistants for employee HR/IT questions</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-yellow mt-6">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong className="text-terminal-yellow">Business impact:</strong>{" "}
|
||||||
|
Double-digit improvements in throughput of back-office processes as AI handles extraction and first-pass decisions, with humans reviewing exceptions. Reduction in operational costs from lower error rates and faster cycle times.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* R&D and Drug Discovery */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat rd-discovery.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
In specialized industries, AI is transforming core R&D and analytical workflows, often with step-change speedups rather than marginal gains.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="terminal-panel mb-6">
|
||||||
|
<span className="terminal-panel-title">breakthrough example</span>
|
||||||
|
<div className="terminal-panel mt-2">
|
||||||
|
<p className="text-lg font-bold text-terminal-green">Ebola Drug Candidates in Under 24 Hours</p>
|
||||||
|
<p className="text-sm text-foreground mt-2">AI systems identified two viable drug candidates in under a day, illustrating dramatic compression of early-stage discovery timelines that traditionally take months.</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-2">Source: NIH/PMC research</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">High-Impact Use Cases</h3>
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground">Pharma and Biotech</h4>
|
||||||
|
<ul className="mt-2 space-y-1 text-sm text-foreground">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Target identification, hit discovery, compound optimization</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Toxicity prediction shortening early discovery cycles</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Platforms: Atomwise, BenevolentAI</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground">Manufacturing and Engineering</h4>
|
||||||
|
<ul className="mt-2 space-y-1 text-sm text-foreground">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Predictive maintenance from sensor data</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Anticipate component failures before they occur</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Reduce unplanned downtime</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="font-bold text-foreground">Legal and Professional Services</h4>
|
||||||
|
<ul className="mt-2 space-y-1 text-sm text-foreground">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Contract review and clause extraction</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Accelerate due diligence</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Lower billable-hour requirements for routine work</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Summary Table */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat impact-summary.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="terminal-panel overflow-x-auto">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-border">
|
||||||
|
<th className="text-left p-2 text-terminal-dim">Function</th>
|
||||||
|
<th className="text-left p-2 text-terminal-dim">Key Metric</th>
|
||||||
|
<th className="text-left p-2 text-terminal-dim">Impact Range</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-foreground">
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Software Development</td>
|
||||||
|
<td className="p-2">Developer throughput</td>
|
||||||
|
<td className="p-2 text-terminal-green font-bold">+20-30%</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Customer Service</td>
|
||||||
|
<td className="p-2">Query deflection</td>
|
||||||
|
<td className="p-2 text-terminal-green font-bold">30-80%</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Customer Service</td>
|
||||||
|
<td className="p-2">Agent productivity</td>
|
||||||
|
<td className="p-2 text-terminal-green font-bold">+10-20%</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Contact Center</td>
|
||||||
|
<td className="p-2">Issues per hour</td>
|
||||||
|
<td className="p-2 text-terminal-green font-bold">+14%</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Contact Center</td>
|
||||||
|
<td className="p-2">Handle time</td>
|
||||||
|
<td className="p-2 text-terminal-green font-bold">-9%</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="p-2 font-bold">Back Office</td>
|
||||||
|
<td className="p-2">Process throughput</td>
|
||||||
|
<td className="p-2 text-terminal-green font-bold">Double-digit gain</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Prioritization */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat prioritization.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
When selecting AI applications for your organization, consider these factors:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[1]</span> Data Readiness
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
AI applications require quality data. Prioritize use cases where you have clean, accessible data or can acquire it efficiently.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[2]</span> Volume and Frequency
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
High-volume, repetitive tasks offer the best ROI for automation. Customer service queries and document processing are common starting points.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[3]</span> Measurability
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Choose use cases with clear before/after metrics. Developer PRs, deflection rates, and handle times are all measurable.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[4]</span> Change Readiness
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Even the best AI fails without adoption. Start with teams that are open to new tools and can champion success.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Related Claims */}
|
||||||
|
{businessClaims.length > 0 && (
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
grep -l "business" claims/*
|
||||||
|
</h2>
|
||||||
|
<div className="space-y-4">
|
||||||
|
{businessClaims.slice(0, 4).map((article) => (
|
||||||
|
<div key={article.slug} className="terminal-panel">
|
||||||
|
<Link
|
||||||
|
href={`/claims-library/${article.slug}`}
|
||||||
|
className="font-bold text-foreground hover:text-terminal-cyan transition-colors"
|
||||||
|
>
|
||||||
|
{article.title}
|
||||||
|
</Link>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">
|
||||||
|
{article.claims.length} atomic claims
|
||||||
|
</p>
|
||||||
|
<ul className="mt-2 space-y-1">
|
||||||
|
{article.claims.slice(0, 2).map((claim, idx) => (
|
||||||
|
<li
|
||||||
|
key={idx}
|
||||||
|
className="text-sm text-foreground flex items-start"
|
||||||
|
>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
<span>{claim}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* See Also */}
|
||||||
|
<section className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">see also</span>
|
||||||
|
<div className="space-y-2 mt-2 text-sm">
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/measuring-ai-roi"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat measuring-ai-roi/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/ai-implementation"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat ai-implementation/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/ai-strategy"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat ai-strategy/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/claims-library"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
ls claims-library/
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<TerminalFooter />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,704 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { getClaimsByTopic } from "@/data/claims";
|
||||||
|
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||||
|
import TerminalFooter from "@/components/TerminalFooter";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "AI Implementation Guide: From Pilot to Production | Kamil Banc",
|
||||||
|
description: "Complete guide to implementing AI in your organization. Learn proven frameworks for planning, executing, and scaling AI initiatives with practical tips for avoiding common pitfalls.",
|
||||||
|
keywords: ["AI implementation", "AI deployment", "AI pilot", "AI production", "AI change management", "AI project management"],
|
||||||
|
authors: [{ name: "Kamil Banc" }],
|
||||||
|
openGraph: {
|
||||||
|
title: "AI Implementation Guide: From Pilot to Production",
|
||||||
|
description: "Proven frameworks for successfully implementing AI initiatives in your organization.",
|
||||||
|
url: "https://kbanc.com/ai-implementation",
|
||||||
|
type: "article",
|
||||||
|
},
|
||||||
|
alternates: {
|
||||||
|
canonical: "https://kbanc.com/ai-implementation",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Compile-time Article JSON-LD from static object literal - no user input */
|
||||||
|
const jsonLd = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Article",
|
||||||
|
headline: "AI Implementation Guide: From Pilot to Production",
|
||||||
|
author: {
|
||||||
|
"@type": "Person",
|
||||||
|
name: "Kamil Banc",
|
||||||
|
jobTitle: "AI Implementation Expert & Strategist",
|
||||||
|
url: "https://kbanc.com/about",
|
||||||
|
image: "https://kbanc.com/kamil-banc.jpg",
|
||||||
|
},
|
||||||
|
publisher: {
|
||||||
|
"@type": "Organization",
|
||||||
|
name: "Kamil Banc",
|
||||||
|
url: "https://kbanc.com",
|
||||||
|
},
|
||||||
|
datePublished: "2024-12-20",
|
||||||
|
dateModified: "2024-12-20",
|
||||||
|
description: "Comprehensive guide to AI implementation with proven frameworks, change management strategies, and common pitfall avoidance.",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AIImplementationPage() {
|
||||||
|
const implementationClaims = getClaimsByTopic("implementation");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Compile-time Article JSON-LD from static object literal - no user input */}
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
<div className="min-h-screen bg-background">
|
||||||
|
<header className="border-b border-border py-8 mb-8">
|
||||||
|
<div className="max-w-4xl mx-auto px-6">
|
||||||
|
<Breadcrumbs
|
||||||
|
items={[
|
||||||
|
{ label: "~", href: "/" },
|
||||||
|
{ label: "ai-implementation" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<h1 className="text-2xl md:text-3xl font-bold text-foreground mb-2">
|
||||||
|
AI Implementation Guide
|
||||||
|
</h1>
|
||||||
|
<p className="text-terminal-dim text-sm">
|
||||||
|
From pilot to production
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main className="max-w-4xl mx-auto px-6 pb-12">
|
||||||
|
{/* Introduction */}
|
||||||
|
<section className="terminal-panel mb-8">
|
||||||
|
<span className="terminal-panel-title">readme</span>
|
||||||
|
<p className="text-sm text-foreground mt-2 leading-relaxed mb-3">
|
||||||
|
The gap between AI pilot and AI in production is where most organizations stumble. Research shows that only 10-15% of AI pilots ever reach full-scale deployment. The difference between success and failure isn't usually the AI technology itself, it's the implementation approach.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground leading-relaxed mb-3">
|
||||||
|
Successful AI implementation requires equal attention to technology, process, and people. Organizations that treat AI deployment as purely a technical project consistently underperform those that take a holistic approach.
|
||||||
|
</p>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong className="text-terminal-cyan">Key insight:</strong>{" "}
|
||||||
|
80% of AI implementation effort goes into activities that have nothing to do with the AI model itself: data preparation, integration, change management, monitoring, and iteration. Plan accordingly.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Implementation Phases */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat implementation-phases.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
Successful AI implementations follow a disciplined phased approach that builds confidence and reduces risk at each stage.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[1]</span> Discovery and Scoping
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-3">
|
||||||
|
Define the problem precisely, establish success criteria, and assess feasibility before writing any code.
|
||||||
|
</p>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-terminal-cyan font-bold mb-2">Key Activities</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Define business problem and success metrics</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Identify data sources and assess quality</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Map stakeholders and decision rights</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Estimate effort and timeline realistically</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-terminal-cyan font-bold mb-2">Exit Criteria</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Clear problem statement documented</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Measurable success criteria agreed</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Data access confirmed and assessed</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Executive sponsor committed</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[2]</span> Proof of Concept (POC)
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-3">
|
||||||
|
Validate that AI can solve the problem with acceptable accuracy before investing in production infrastructure.
|
||||||
|
</p>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-terminal-cyan font-bold mb-2">Key Activities</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Build minimal viable model</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Test on representative sample data</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Validate with domain experts</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Identify technical risks early</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-terminal-cyan font-bold mb-2">Exit Criteria</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Model meets accuracy threshold</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Technical feasibility confirmed</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Major risks identified and mitigated</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Go/no-go decision made</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[3]</span> Pilot Deployment
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-3">
|
||||||
|
Deploy to a limited user group in real conditions to validate business value and refine the solution.
|
||||||
|
</p>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-terminal-cyan font-bold mb-2">Key Activities</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Deploy to 5-10% of target users</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Build production-like infrastructure</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Collect user feedback systematically</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Measure business impact vs. baseline</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-terminal-cyan font-bold mb-2">Exit Criteria</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Business value demonstrated</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>User adoption met targets</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>System stable in production</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Scale plan validated</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[4]</span> Production Rollout
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-3">
|
||||||
|
Scale to full user population with proper training, change management, and support structures.
|
||||||
|
</p>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-terminal-cyan font-bold mb-2">Key Activities</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Execute phased rollout plan</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Train all affected users</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Establish support processes</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Monitor adoption and performance</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-terminal-cyan font-bold mb-2">Exit Criteria</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>All target users onboarded</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Performance meets SLAs</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Support team operational</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Business outcomes achieved</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[5]</span> Optimization and Evolution
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-3">
|
||||||
|
Continuously improve the AI system based on real-world performance and changing requirements.
|
||||||
|
</p>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-terminal-cyan font-bold mb-2">Key Activities</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Monitor model performance drift</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Retrain on new data regularly</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Add features based on user feedback</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Expand to adjacent use cases</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-xs text-terminal-cyan font-bold mb-2">Success Indicators</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Sustained or improving accuracy</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Growing user engagement</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Expanding business value</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Manageable maintenance burden</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Readiness Assessment */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat readiness-assessment.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
Before starting any AI implementation, assess your organization's readiness across these critical dimensions. Gaps in any area can derail even the best AI solutions.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="terminal-panel overflow-x-auto mb-6">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-border">
|
||||||
|
<th className="text-left p-2 text-terminal-dim font-normal">Dimension</th>
|
||||||
|
<th className="text-left p-2 text-terminal-green font-normal">Ready</th>
|
||||||
|
<th className="text-left p-2 text-terminal-red font-normal">Not Ready</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-foreground">
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Data</td>
|
||||||
|
<td className="p-2">Accessible, clean, sufficient volume</td>
|
||||||
|
<td className="p-2">Siloed, poor quality, limited history</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Infrastructure</td>
|
||||||
|
<td className="p-2">Cloud/compute available, CI/CD in place</td>
|
||||||
|
<td className="p-2">Limited compute, manual deployments</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Skills</td>
|
||||||
|
<td className="p-2">ML engineers on staff or contracted</td>
|
||||||
|
<td className="p-2">No ML expertise, no training plan</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Sponsorship</td>
|
||||||
|
<td className="p-2">Executive champion, budget secured</td>
|
||||||
|
<td className="p-2">No executive buy-in, uncertain funding</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Change Capacity</td>
|
||||||
|
<td className="p-2">Users open to new tools, bandwidth available</td>
|
||||||
|
<td className="p-2">Change fatigue, competing initiatives</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="p-2 font-bold">Problem Clarity</td>
|
||||||
|
<td className="p-2">Specific use case, measurable success</td>
|
||||||
|
<td className="p-2">Vague objectives, unclear metrics</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-yellow">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong className="text-terminal-yellow">Pro tip:</strong>{" "}
|
||||||
|
If you have three or more "Not Ready" assessments, address these gaps before starting the AI implementation. Trying to solve readiness issues in parallel with AI development rarely works.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Change Management */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat change-management.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
AI changes how people work. Even the most technically elegant AI solution will fail if users don't adopt it. Change management isn't optional, it's essential.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">
|
||||||
|
The ADKAR Model for AI Adoption
|
||||||
|
</h3>
|
||||||
|
<div className="space-y-4 mb-8">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<h4 className="text-terminal-cyan font-bold">Awareness</h4>
|
||||||
|
<p className="text-sm text-foreground mt-2">Users understand why AI is being introduced and what it will change.</p>
|
||||||
|
<p className="text-sm text-terminal-dim mt-2"><strong className="text-foreground">Actions:</strong> Town halls, demos, executive communications explaining the "why"</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<h4 className="text-terminal-cyan font-bold">Desire</h4>
|
||||||
|
<p className="text-sm text-foreground mt-2">Users want to participate and see personal benefit in the change.</p>
|
||||||
|
<p className="text-sm text-terminal-dim mt-2"><strong className="text-foreground">Actions:</strong> Involve power users early, address "what's in it for me," recognize early adopters</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<h4 className="text-terminal-cyan font-bold">Knowledge</h4>
|
||||||
|
<p className="text-sm text-foreground mt-2">Users know how to use the AI system effectively.</p>
|
||||||
|
<p className="text-sm text-terminal-dim mt-2"><strong className="text-foreground">Actions:</strong> Role-specific training, quick reference guides, sandbox environments for practice</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<h4 className="text-terminal-cyan font-bold">Ability</h4>
|
||||||
|
<p className="text-sm text-foreground mt-2">Users can apply their knowledge in real work situations.</p>
|
||||||
|
<p className="text-sm text-terminal-dim mt-2"><strong className="text-foreground">Actions:</strong> Coaching support, desk drops, floor walkers during rollout, peer mentors</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<h4 className="text-terminal-cyan font-bold">Reinforcement</h4>
|
||||||
|
<p className="text-sm text-foreground mt-2">Changes are sustained over time and don't regress to old ways.</p>
|
||||||
|
<p className="text-sm text-terminal-dim mt-2"><strong className="text-foreground">Actions:</strong> Usage monitoring, refresher training, success celebrations, KPIs tied to adoption</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">
|
||||||
|
Addressing AI Resistance
|
||||||
|
</h3>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<h4 className="text-foreground font-bold mb-2">"AI will take my job"</h4>
|
||||||
|
<p className="text-sm text-terminal-dim">Frame AI as a tool that handles repetitive tasks, freeing people for higher-value work. Be honest if roles will change, and provide reskilling paths.</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<h4 className="text-foreground font-bold mb-2">"I don't trust AI decisions"</h4>
|
||||||
|
<p className="text-sm text-terminal-dim">Start with AI as an assistant, not decision-maker. Show how AI reasoning works. Let users override AI suggestions initially.</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<h4 className="text-foreground font-bold mb-2">"This is just another tech fad"</h4>
|
||||||
|
<p className="text-sm text-terminal-dim">Show concrete business impact with data. Connect AI to real problems they care about. Demonstrate quick wins that affect their daily work.</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<h4 className="text-foreground font-bold mb-2">"It's too complicated"</h4>
|
||||||
|
<p className="text-sm text-terminal-dim">Invest in UX that hides complexity. Provide just-in-time training at point of use. Create clear documentation and support channels.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Technical Implementation */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat technical-best-practices.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">
|
||||||
|
Data Pipeline Essentials
|
||||||
|
</h3>
|
||||||
|
<div className="space-y-4 mb-8">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="text-foreground font-bold mb-1">Build for maintainability first</h4>
|
||||||
|
<p className="text-sm text-terminal-dim">Data pipelines need to run reliably for years. Invest in monitoring, alerting, and documentation from day one.</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="text-foreground font-bold mb-1">Version everything</h4>
|
||||||
|
<p className="text-sm text-terminal-dim">Data, models, and code should all be versioned so you can reproduce results and rollback when needed.</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="text-foreground font-bold mb-1">Separate training from inference</h4>
|
||||||
|
<p className="text-sm text-terminal-dim">Training is batch-oriented and compute-intensive. Inference is real-time and latency-sensitive. Different architectures for different needs.</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="text-foreground font-bold mb-1">Plan for data drift</h4>
|
||||||
|
<p className="text-sm text-terminal-dim">Real-world data changes over time. Build monitoring to detect when input data diverges from training data.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">
|
||||||
|
Model Deployment Patterns
|
||||||
|
</h3>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4 mb-8">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">shadow mode</span>
|
||||||
|
<p className="text-sm text-terminal-dim mt-2">AI runs in parallel with existing process, predictions logged but not acted upon.</p>
|
||||||
|
<p className="text-sm text-foreground mt-2"><strong>Use when:</strong> First production deployment, high-risk decisions</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">human-in-the-loop</span>
|
||||||
|
<p className="text-sm text-terminal-dim mt-2">AI makes recommendations, humans approve or override before action.</p>
|
||||||
|
<p className="text-sm text-foreground mt-2"><strong>Use when:</strong> Building trust, regulatory requirements, learning period</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">canary deployment</span>
|
||||||
|
<p className="text-sm text-terminal-dim mt-2">New model version handles small percentage of traffic, gradually increasing.</p>
|
||||||
|
<p className="text-sm text-foreground mt-2"><strong>Use when:</strong> Model updates, testing improvements safely</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">full automation</span>
|
||||||
|
<p className="text-sm text-terminal-dim mt-2">AI makes and executes decisions autonomously.</p>
|
||||||
|
<p className="text-sm text-foreground mt-2"><strong>Use when:</strong> Proven accuracy, reversible decisions, high-volume tasks</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">
|
||||||
|
Monitoring and Observability
|
||||||
|
</h3>
|
||||||
|
<div className="terminal-panel overflow-x-auto">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-border">
|
||||||
|
<th className="text-left p-2 text-terminal-dim font-normal">What to Monitor</th>
|
||||||
|
<th className="text-left p-2 text-terminal-dim font-normal">Why It Matters</th>
|
||||||
|
<th className="text-left p-2 text-terminal-dim font-normal">Alert When</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-foreground">
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Prediction latency</td>
|
||||||
|
<td className="p-2">User experience, SLA compliance</td>
|
||||||
|
<td className="p-2">p95 exceeds threshold</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Prediction volume</td>
|
||||||
|
<td className="p-2">Detect adoption issues or system problems</td>
|
||||||
|
<td className="p-2">Significant drop from baseline</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Input data distribution</td>
|
||||||
|
<td className="p-2">Detect data drift before accuracy degrades</td>
|
||||||
|
<td className="p-2">Distribution shift detected</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Prediction distribution</td>
|
||||||
|
<td className="p-2">Detect model drift or upstream changes</td>
|
||||||
|
<td className="p-2">Output distribution changes</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="p-2 font-bold">Business metrics</td>
|
||||||
|
<td className="p-2">Validate AI is delivering value</td>
|
||||||
|
<td className="p-2">Metrics diverge from targets</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Common Pitfalls */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat pitfalls.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Skipping the Baseline
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Implementing AI without measuring current performance makes it impossible to prove value.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong>Prevention:</strong> Always measure the status quo before AI implementation. Document current accuracy, speed, cost, and user satisfaction.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> The Perfect Data Trap
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Waiting for perfect data before starting. Data is never perfect, and requirements become clear through iteration.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong>Prevention:</strong> Start with available data, learn what's actually needed, and improve data quality in parallel with model development.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Pilot Without Production Plan
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Building a successful pilot on infrastructure and processes that can't scale to production.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong>Prevention:</strong> Design for production from day one. Use production-like infrastructure even for pilots. Plan the full journey before starting.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Ignoring the Last Mile
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Focusing all effort on model accuracy while neglecting user interface, workflow integration, and training.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong>Prevention:</strong> Allocate at least 50% of effort to integration, UX, and change management. The best model is useless if people don't use it.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Set and Forget
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Treating deployment as the finish line instead of the starting point of ongoing operation.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong>Prevention:</strong> Budget for ongoing maintenance, monitoring, and improvement. Plan for model retraining and version updates from the start.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Success Factors */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat success-factors.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[1]</span> Start with a real business problem
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">The best AI implementations solve problems people actually have. Start with users who are asking for help, not with technology looking for a use case.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[2]</span> Secure executive sponsorship
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">AI implementations face resistance and require resources. An executive sponsor can remove blockers, secure budget, and signal organizational priority.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[3]</span> Involve end users early and often
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">Users who participate in design become advocates. Users who have AI imposed on them become resisters. Involve them from discovery through optimization.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[4]</span> Plan for iteration
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">The first version won't be perfect. Build in time and resources for learning and improvement. Success comes from rapid iteration, not perfect planning.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[5]</span> Measure and communicate impact
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">Track business metrics from day one. Communicate wins widely to build momentum. Be honest about challenges to maintain credibility.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[6]</span> Build for the long term
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">Sustainable AI requires sustainable infrastructure, processes, and skills. Avoid shortcuts that create technical debt. Invest in capabilities you'll use repeatedly.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Implementation Checklist */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat checklist.txt
|
||||||
|
</h2>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">quick implementation checklist</span>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4 text-sm mt-4">
|
||||||
|
<div>
|
||||||
|
<p className="text-foreground font-bold mb-2">Before Starting:</p>
|
||||||
|
<ul className="space-y-1 text-terminal-dim">
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Problem clearly defined and scoped</li>
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Success metrics established</li>
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Baseline measurements taken</li>
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Executive sponsor identified</li>
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Data access confirmed</li>
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Team assembled with right skills</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<p className="text-foreground font-bold mb-2">During Implementation:</p>
|
||||||
|
<ul className="space-y-1 text-terminal-dim">
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Users involved in design</li>
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Phase gates respected</li>
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Production infrastructure ready</li>
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Training materials prepared</li>
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Monitoring implemented</li>
|
||||||
|
<li><span className="text-terminal-dim mr-2">[ ]</span>Support processes established</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Related Claims */}
|
||||||
|
{implementationClaims.length > 0 && (
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
grep -r "implementation" claims-library/
|
||||||
|
</h2>
|
||||||
|
<div className="space-y-4">
|
||||||
|
{implementationClaims.slice(0, 4).map((article) => (
|
||||||
|
<div key={article.slug} className="terminal-panel">
|
||||||
|
<Link
|
||||||
|
href={`/claims-library/${article.slug}`}
|
||||||
|
className="font-bold text-foreground hover:text-terminal-cyan transition-colors"
|
||||||
|
>
|
||||||
|
{article.title}
|
||||||
|
</Link>
|
||||||
|
<div className="mt-2 space-y-1">
|
||||||
|
{article.claims.slice(0, 2).map((claim, idx) => (
|
||||||
|
<div key={idx} className="pl-4 border-l border-terminal-green">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<span className="text-terminal-green text-xs font-bold mr-2">[{idx + 1}]</span>
|
||||||
|
{claim}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
href={`/claims-library/${article.slug}`}
|
||||||
|
className="inline-block mt-2 text-xs text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
View all {article.claims.length} claims
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* See Also */}
|
||||||
|
<section className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">see also</span>
|
||||||
|
<div className="space-y-2 mt-2 text-sm">
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/ai-strategy"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat ai-strategy/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/ai-tools"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat ai-tools/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/measuring-ai-roi"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat measuring-ai-roi/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/claims-library"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
ls claims-library/
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<TerminalFooter />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,763 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { getClaimsByTopic } from "@/data/claims";
|
||||||
|
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||||
|
import TerminalFooter from "@/components/TerminalFooter";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "AI Strategy Guide: Building Your Enterprise AI Roadmap | Kamil Banc",
|
||||||
|
description:
|
||||||
|
"Learn how to build an effective AI strategy for your organization. From vision to execution, discover frameworks for prioritizing AI initiatives and avoiding common pitfalls.",
|
||||||
|
keywords: [
|
||||||
|
"AI strategy",
|
||||||
|
"enterprise AI",
|
||||||
|
"AI roadmap",
|
||||||
|
"AI transformation",
|
||||||
|
"AI governance",
|
||||||
|
"AI prioritization",
|
||||||
|
],
|
||||||
|
authors: [{ name: "Kamil Banc" }],
|
||||||
|
openGraph: {
|
||||||
|
title: "AI Strategy Guide: Building Your Enterprise AI Roadmap",
|
||||||
|
description:
|
||||||
|
"Frameworks for building and executing an effective AI strategy in your organization.",
|
||||||
|
url: "https://kbanc.com/ai-strategy",
|
||||||
|
type: "article",
|
||||||
|
},
|
||||||
|
alternates: {
|
||||||
|
canonical: "https://kbanc.com/ai-strategy",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Compile-time Article JSON-LD from static object literal - no user input */
|
||||||
|
const jsonLd = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Article",
|
||||||
|
headline: "AI Strategy Guide: Building Your Enterprise AI Roadmap",
|
||||||
|
author: {
|
||||||
|
"@type": "Person",
|
||||||
|
name: "Kamil Banc",
|
||||||
|
jobTitle: "AI Implementation Expert & Strategist",
|
||||||
|
url: "https://kbanc.com/about",
|
||||||
|
image: "https://kbanc.com/kamil-banc.jpg",
|
||||||
|
},
|
||||||
|
publisher: {
|
||||||
|
"@type": "Organization",
|
||||||
|
name: "Kamil Banc",
|
||||||
|
url: "https://kbanc.com",
|
||||||
|
},
|
||||||
|
datePublished: "2024-12-20",
|
||||||
|
dateModified: "2024-12-20",
|
||||||
|
description:
|
||||||
|
"Comprehensive guide to building an enterprise AI strategy with frameworks, governance, and execution roadmaps.",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AIStrategyPage() {
|
||||||
|
const strategyClaims = getClaimsByTopic("strategy");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Compile-time Article JSON-LD from static object literal - no user input */}
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
<div className="min-h-screen bg-background">
|
||||||
|
<header className="border-b border-border py-8 mb-8">
|
||||||
|
<div className="max-w-4xl mx-auto px-6">
|
||||||
|
<Breadcrumbs
|
||||||
|
items={[
|
||||||
|
{ label: "~", href: "/" },
|
||||||
|
{ label: "ai-strategy" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<h1 className="text-2xl md:text-3xl font-bold text-foreground mb-2">
|
||||||
|
AI Strategy Guide
|
||||||
|
</h1>
|
||||||
|
<p className="text-terminal-dim text-sm">
|
||||||
|
From vision to execution: frameworks for building AI capabilities
|
||||||
|
that deliver lasting business value
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main className="max-w-4xl mx-auto px-6 pb-12">
|
||||||
|
{/* Introduction */}
|
||||||
|
<section className="terminal-panel mb-8">
|
||||||
|
<span className="terminal-panel-title">readme</span>
|
||||||
|
<p className="text-sm text-foreground mt-2 leading-relaxed mb-3">
|
||||||
|
Most organizations approach AI backwards, starting with technology
|
||||||
|
instead of strategy. They invest in tools and pilots without a
|
||||||
|
clear vision of how AI will transform their business. The result:
|
||||||
|
scattered initiatives, disappointed stakeholders, and unrealized
|
||||||
|
potential.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground leading-relaxed mb-3">
|
||||||
|
An effective AI strategy answers three fundamental questions: Where
|
||||||
|
will AI create the most value for our business? What capabilities
|
||||||
|
do we need to build? And how will we execute systematically rather
|
||||||
|
than opportunistically?
|
||||||
|
</p>
|
||||||
|
<div className="border-l-2 border-terminal-cyan pl-4 mt-4">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong className="text-terminal-cyan">Key principle:</strong>{" "}
|
||||||
|
AI strategy isn't about adopting technology. It's about
|
||||||
|
identifying where intelligent automation and augmentation will
|
||||||
|
create competitive advantage and building the organizational
|
||||||
|
capabilities to capture that value.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* The Five Pillars */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat five-pillars.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
A robust AI strategy rests on five interconnected pillars.
|
||||||
|
Weakness in any one undermines the others.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[1]</span> Strategic
|
||||||
|
Vision
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Define how AI will transform your business model, operations,
|
||||||
|
and competitive position over 3-5 years.
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>What
|
||||||
|
customer experiences will AI enable that weren't
|
||||||
|
possible before?
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Where
|
||||||
|
will AI create operational advantages competitors can't
|
||||||
|
easily replicate?
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>How will
|
||||||
|
AI change the economics of your business?
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[2]</span> Use Case
|
||||||
|
Portfolio
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Identify and prioritize the specific applications where AI
|
||||||
|
will deliver measurable value.
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Map use
|
||||||
|
cases to strategic objectives and business outcomes
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Balance
|
||||||
|
quick wins with transformational initiatives
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Consider
|
||||||
|
data readiness, technical feasibility, and change management
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[3]</span> Data
|
||||||
|
Foundation
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Establish the data infrastructure, governance, and quality
|
||||||
|
standards AI requires.
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Inventory
|
||||||
|
data assets and assess quality for AI use cases
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Build
|
||||||
|
data pipelines that can feed AI systems reliably
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Implement governance that enables rather than blocks AI
|
||||||
|
adoption
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[4]</span> Talent and
|
||||||
|
Organization
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Build the human capabilities and organizational structures to
|
||||||
|
develop, deploy, and scale AI.
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Determine
|
||||||
|
build vs. buy vs. partner for AI capabilities
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Upskill
|
||||||
|
existing workforce for AI collaboration
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Create
|
||||||
|
centers of excellence and embed AI expertise in business
|
||||||
|
units
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[5]</span> Governance
|
||||||
|
and Ethics
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Establish frameworks for responsible AI that build trust and
|
||||||
|
manage risk.
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Define
|
||||||
|
principles for AI fairness, transparency, and accountability
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Create
|
||||||
|
review processes for high-risk AI applications
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Build
|
||||||
|
monitoring systems to detect and address issues in production
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Prioritization */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat prioritization.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
Not all AI opportunities are created equal. A systematic
|
||||||
|
prioritization approach helps focus resources on initiatives that
|
||||||
|
balance value, feasibility, and strategic fit.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">
|
||||||
|
The Value-Feasibility Matrix
|
||||||
|
</h3>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4 mb-6">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">
|
||||||
|
high value / high feasibility
|
||||||
|
</span>
|
||||||
|
<p className="text-sm text-terminal-green font-bold mt-2">
|
||||||
|
Priority 1: Execute Now
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">
|
||||||
|
Clear ROI, available data, proven technology, willing
|
||||||
|
stakeholders. These are your quick wins that build momentum.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">
|
||||||
|
high value / low feasibility
|
||||||
|
</span>
|
||||||
|
<p className="text-sm text-terminal-yellow font-bold mt-2">
|
||||||
|
Priority 2: Plan and Prepare
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">
|
||||||
|
Transformational potential but requires capability building.
|
||||||
|
Start groundwork now for future execution.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">
|
||||||
|
low value / high feasibility
|
||||||
|
</span>
|
||||||
|
<p className="text-sm text-terminal-cyan font-bold mt-2">
|
||||||
|
Priority 3: Opportunistic
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">
|
||||||
|
Easy to implement but limited impact. Consider as learning
|
||||||
|
opportunities or capacity builders.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">
|
||||||
|
low value / low feasibility
|
||||||
|
</span>
|
||||||
|
<p className="text-sm text-terminal-red font-bold mt-2">
|
||||||
|
Avoid
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">
|
||||||
|
Neither impactful nor achievable. Don't waste resources
|
||||||
|
here.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">
|
||||||
|
Feasibility Assessment Criteria
|
||||||
|
</h3>
|
||||||
|
<div className="terminal-panel overflow-x-auto">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-border">
|
||||||
|
<th className="text-left p-2 text-terminal-dim">Factor</th>
|
||||||
|
<th className="text-left p-2 text-terminal-green">
|
||||||
|
High Feasibility
|
||||||
|
</th>
|
||||||
|
<th className="text-left p-2 text-terminal-red">
|
||||||
|
Low Feasibility
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-foreground">
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Data</td>
|
||||||
|
<td className="p-2">Clean, accessible, sufficient volume</td>
|
||||||
|
<td className="p-2">Siloed, poor quality, limited history</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Technology</td>
|
||||||
|
<td className="p-2">
|
||||||
|
Proven solutions exist, clear architecture
|
||||||
|
</td>
|
||||||
|
<td className="p-2">Requires R&D, unproven at scale</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">People</td>
|
||||||
|
<td className="p-2">Skills available, stakeholder buy-in</td>
|
||||||
|
<td className="p-2">
|
||||||
|
Skills gap, organizational resistance
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="p-2 font-bold">Process</td>
|
||||||
|
<td className="p-2">
|
||||||
|
Well-defined, minimal change needed
|
||||||
|
</td>
|
||||||
|
<td className="p-2">Requires major workflow redesign</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Building Capabilities */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat capability-maturity.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
AI success requires a combination of technical expertise, business
|
||||||
|
acumen, and change management skills. Organizations typically
|
||||||
|
evolve through three capability maturity stages.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
Stage 1: Foundation
|
||||||
|
</h3>
|
||||||
|
<p className="text-xs text-terminal-dim mb-2">
|
||||||
|
Focus: Pilots and proof of concepts
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Small AI
|
||||||
|
team or external partners leading initiatives
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>1-3 use
|
||||||
|
cases in production
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Basic
|
||||||
|
data infrastructure and governance
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Executive sponsorship established
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
Stage 2: Scaling
|
||||||
|
</h3>
|
||||||
|
<p className="text-xs text-terminal-dim mb-2">
|
||||||
|
Focus: Expanding proven use cases
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>AI Center
|
||||||
|
of Excellence with 10-30 specialists
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>5-15 use
|
||||||
|
cases in production
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>MLOps
|
||||||
|
capabilities for model deployment and monitoring
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Business
|
||||||
|
units actively requesting AI solutions
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
Stage 3: Transformation
|
||||||
|
</h3>
|
||||||
|
<p className="text-xs text-terminal-dim mb-2">
|
||||||
|
Focus: AI-first operations
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>AI
|
||||||
|
expertise embedded across the organization
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>50+ use
|
||||||
|
cases with self-service capabilities
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>AI
|
||||||
|
considered in every major business decision
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Continuous innovation and experimentation culture
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-yellow mt-4">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong className="text-terminal-yellow">Key insight:</strong>{" "}
|
||||||
|
Most organizations take 2-3 years to move from Foundation to
|
||||||
|
Scaling, and another 2-3 years to reach Transformation. Trying
|
||||||
|
to skip stages leads to fragile capabilities and unsustainable
|
||||||
|
results.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Governance */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat governance.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
Good AI governance enables innovation while managing risk. It
|
||||||
|
should accelerate responsible adoption, not create bureaucratic
|
||||||
|
barriers.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">
|
||||||
|
Risk-Based Governance Tiers
|
||||||
|
</h3>
|
||||||
|
<div className="space-y-4 mb-6">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h4 className="text-terminal-green font-bold">
|
||||||
|
Low Risk: Streamlined Review
|
||||||
|
</h4>
|
||||||
|
<p className="text-sm text-terminal-dim mt-1">
|
||||||
|
Internal productivity tools, content generation, basic
|
||||||
|
automation. Self-service deployment with standard security
|
||||||
|
review.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-yellow">
|
||||||
|
<h4 className="text-terminal-yellow font-bold">
|
||||||
|
Medium Risk: Enhanced Review
|
||||||
|
</h4>
|
||||||
|
<p className="text-sm text-terminal-dim mt-1">
|
||||||
|
Customer-facing AI, decision support systems, process
|
||||||
|
automation. Technical and business review, monitoring
|
||||||
|
requirements.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h4 className="text-terminal-red font-bold">
|
||||||
|
High Risk: Full Board Review
|
||||||
|
</h4>
|
||||||
|
<p className="text-sm text-terminal-dim mt-1">
|
||||||
|
Automated decisions affecting people (hiring, credit,
|
||||||
|
healthcare), high-stakes predictions. Ethics review, ongoing
|
||||||
|
audit, human oversight requirements.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4">
|
||||||
|
Core Governance Principles
|
||||||
|
</h3>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">Transparency</p>
|
||||||
|
<p className="text-xs text-terminal-dim">
|
||||||
|
Stakeholders understand how AI systems make decisions
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">Accountability</p>
|
||||||
|
<p className="text-xs text-terminal-dim">
|
||||||
|
Clear ownership for AI system outcomes
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">Fairness</p>
|
||||||
|
<p className="text-xs text-terminal-dim">
|
||||||
|
Systems tested for bias and equitable treatment
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">Security</p>
|
||||||
|
<p className="text-xs text-terminal-dim">
|
||||||
|
Data protected, systems resilient to attack
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Common Pitfalls */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat pitfalls.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Technology-First
|
||||||
|
Thinking
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Starting with "let's use AI" instead of
|
||||||
|
"what problem are we solving?" leads to solutions
|
||||||
|
looking for problems.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong>Instead:</strong> Start with business outcomes and work
|
||||||
|
backward to whether AI is the right solution.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Pilot Purgatory
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Endless proofs of concept that never reach production or
|
||||||
|
scale. Often caused by lack of production infrastructure and
|
||||||
|
unclear success criteria.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong>Instead:</strong> Define success criteria upfront and
|
||||||
|
build production readiness from the start.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Ignoring Change
|
||||||
|
Management
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Technical success that fails to deliver value because users
|
||||||
|
don't adopt the AI system or work around it.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong>Instead:</strong> Involve end users early, design for
|
||||||
|
adoption, and invest in training.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Underestimating
|
||||||
|
Data Requirements
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Discovering data quality and access issues after committing to
|
||||||
|
an AI initiative, causing delays and failures.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong>Instead:</strong> Assess data readiness as part of
|
||||||
|
feasibility evaluation before committing resources.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* First Steps */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat first-steps.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[1]</span> Assess
|
||||||
|
Current State
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Inventory existing AI initiatives, data assets, technical
|
||||||
|
capabilities, and organizational readiness. Understand your
|
||||||
|
starting point honestly.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[2]</span> Define
|
||||||
|
Strategic Objectives
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Align AI vision with business strategy. Where does AI fit in
|
||||||
|
your 3-5 year business plan? What capabilities must you build?
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[3]</span> Identify
|
||||||
|
Quick Wins
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Find 2-3 high-value, high-feasibility use cases to build
|
||||||
|
momentum and demonstrate value while laying groundwork for
|
||||||
|
bigger initiatives.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[4]</span> Establish
|
||||||
|
Governance
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Create lightweight governance that enables responsible
|
||||||
|
experimentation. Don't let perfect be the enemy of good.
|
||||||
|
Evolve as you learn.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[5]</span> Build
|
||||||
|
Capabilities Incrementally
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Start with what you need for initial use cases and expand
|
||||||
|
systematically. Avoid building infrastructure for hypothetical
|
||||||
|
future needs.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Related Claims */}
|
||||||
|
{strategyClaims.length > 0 && (
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
grep -l "strategy" claims/*
|
||||||
|
</h2>
|
||||||
|
<div className="space-y-4">
|
||||||
|
{strategyClaims.slice(0, 4).map((article) => (
|
||||||
|
<div key={article.slug} className="terminal-panel">
|
||||||
|
<Link
|
||||||
|
href={`/claims-library/${article.slug}`}
|
||||||
|
className="font-bold text-foreground hover:text-terminal-cyan transition-colors"
|
||||||
|
>
|
||||||
|
{article.title}
|
||||||
|
</Link>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">
|
||||||
|
{article.claims.length} atomic claims
|
||||||
|
</p>
|
||||||
|
<ul className="mt-2 space-y-1">
|
||||||
|
{article.claims.slice(0, 2).map((claim, idx) => (
|
||||||
|
<li
|
||||||
|
key={idx}
|
||||||
|
className="text-sm text-foreground flex items-start"
|
||||||
|
>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
<span>{claim}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Related Resources */}
|
||||||
|
<section className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">see also</span>
|
||||||
|
<div className="space-y-2 mt-2 text-sm">
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/ai-implementation"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat ai-implementation/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/measuring-ai-roi"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat measuring-ai-roi/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/ai-business-applications"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat ai-business-applications/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/claims-library"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
ls claims-library/
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<TerminalFooter />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,753 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { getClaimsByTopic } from "@/data/claims";
|
||||||
|
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||||
|
import TerminalFooter from "@/components/TerminalFooter";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "AI Tools Selection Guide: Choosing the Right AI for Your Business | Kamil Banc",
|
||||||
|
description:
|
||||||
|
"Complete guide to selecting AI tools for your organization. Compare categories, evaluation criteria, and build vs buy decisions for enterprise AI adoption.",
|
||||||
|
keywords: [
|
||||||
|
"AI tools",
|
||||||
|
"AI software",
|
||||||
|
"enterprise AI",
|
||||||
|
"AI platforms",
|
||||||
|
"AI evaluation",
|
||||||
|
"LLM tools",
|
||||||
|
"AI comparison",
|
||||||
|
],
|
||||||
|
authors: [{ name: "Kamil Banc" }],
|
||||||
|
openGraph: {
|
||||||
|
title:
|
||||||
|
"AI Tools Selection Guide: Choosing the Right AI for Your Business",
|
||||||
|
description:
|
||||||
|
"Frameworks for evaluating and selecting AI tools that fit your organization's needs.",
|
||||||
|
url: "https://kbanc.com/ai-tools",
|
||||||
|
type: "article",
|
||||||
|
},
|
||||||
|
alternates: {
|
||||||
|
canonical: "https://kbanc.com/ai-tools",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Compile-time Article JSON-LD from static object literal - no user input */
|
||||||
|
const jsonLd = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Article",
|
||||||
|
headline:
|
||||||
|
"AI Tools Selection Guide: Choosing the Right AI for Your Business",
|
||||||
|
author: {
|
||||||
|
"@type": "Person",
|
||||||
|
name: "Kamil Banc",
|
||||||
|
jobTitle: "AI Implementation Expert & Strategist",
|
||||||
|
url: "https://kbanc.com/about",
|
||||||
|
image: "https://kbanc.com/kamil-banc.jpg",
|
||||||
|
},
|
||||||
|
publisher: {
|
||||||
|
"@type": "Organization",
|
||||||
|
name: "Kamil Banc",
|
||||||
|
url: "https://kbanc.com",
|
||||||
|
},
|
||||||
|
datePublished: "2024-12-20",
|
||||||
|
dateModified: "2024-12-20",
|
||||||
|
description:
|
||||||
|
"Comprehensive guide to evaluating and selecting AI tools for enterprise adoption.",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function AIToolsPage() {
|
||||||
|
const toolsClaims = getClaimsByTopic("tools");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Compile-time Article JSON-LD from static object literal - no user input */}
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
<div className="min-h-screen bg-background">
|
||||||
|
<header className="border-b border-border py-8 mb-8">
|
||||||
|
<div className="max-w-4xl mx-auto px-6">
|
||||||
|
<Breadcrumbs
|
||||||
|
items={[
|
||||||
|
{ label: "~", href: "/" },
|
||||||
|
{ label: "ai-tools" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<h1 className="text-2xl md:text-3xl font-bold text-foreground mb-2">
|
||||||
|
AI Tools Selection Guide
|
||||||
|
</h1>
|
||||||
|
<p className="text-terminal-dim text-sm">
|
||||||
|
Choosing the right AI for your business
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main className="max-w-4xl mx-auto px-6 pb-12">
|
||||||
|
{/* Introduction */}
|
||||||
|
<section className="terminal-panel mb-8">
|
||||||
|
<span className="terminal-panel-title">readme</span>
|
||||||
|
<p className="text-sm text-foreground mt-2 leading-relaxed mb-3">
|
||||||
|
The AI tools market has exploded. Every vendor claims their
|
||||||
|
solution is "AI-powered," making it increasingly
|
||||||
|
difficult to separate genuine capability from marketing hype.
|
||||||
|
This guide provides frameworks for cutting through the noise and
|
||||||
|
selecting tools that actually deliver value.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground leading-relaxed mb-4">
|
||||||
|
Successful AI tool selection requires understanding your specific
|
||||||
|
use cases, evaluating tools against clear criteria, and making
|
||||||
|
informed build-vs-buy decisions. The right tool depends on your
|
||||||
|
context. There's no universal "best" option.
|
||||||
|
</p>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong>Selection principle:</strong> The best AI tool is the
|
||||||
|
one that solves your specific problem with acceptable cost,
|
||||||
|
complexity, and risk. Not the one with the most impressive
|
||||||
|
demo or the highest benchmark scores.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Tool Categories */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat tool-categories.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-foreground mb-6 leading-relaxed">
|
||||||
|
Understanding the AI tool landscape requires categorizing by
|
||||||
|
function, deployment model, and integration level.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4 text-sm">
|
||||||
|
By function
|
||||||
|
</h3>
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-8">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">
|
||||||
|
language & content
|
||||||
|
</span>
|
||||||
|
<ul className="space-y-2 mt-2 text-sm">
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>LLM APIs (OpenAI, Anthropic, Google)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Writing assistants (Jasper, Copy.ai)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Code assistants (GitHub Copilot, Cursor)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Document processing (AWS Textract)</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">
|
||||||
|
customer engagement
|
||||||
|
</span>
|
||||||
|
<ul className="space-y-2 mt-2 text-sm">
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Chatbots (Intercom, Drift, Ada)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Voice AI (Speechmatics, Deepgram)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Personalization (Dynamic Yield)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Sentiment analysis (MonkeyLearn)</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">
|
||||||
|
analytics & intelligence
|
||||||
|
</span>
|
||||||
|
<ul className="space-y-2 mt-2 text-sm">
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Predictive analytics (DataRobot)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Business intelligence (ThoughtSpot)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Forecasting (Prophet, Temporal)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Anomaly detection (Anodot)</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">
|
||||||
|
operations & automation
|
||||||
|
</span>
|
||||||
|
<ul className="space-y-2 mt-2 text-sm">
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>RPA + AI (UiPath, Automation Anywhere)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Document automation (Hyperscience)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Workflow automation (Zapier AI)</span>
|
||||||
|
</li>
|
||||||
|
<li className="flex items-start gap-2">
|
||||||
|
<span className="text-terminal-green">-</span>
|
||||||
|
<span>Supply chain AI (o9 Solutions)</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3 className="text-foreground font-bold mb-4 text-sm">
|
||||||
|
By deployment model
|
||||||
|
</h3>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<div className="overflow-x-auto">
|
||||||
|
<table className="w-full text-sm">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-border">
|
||||||
|
<th className="text-left py-2 pr-4 text-terminal-dim font-normal">
|
||||||
|
Model
|
||||||
|
</th>
|
||||||
|
<th className="text-left py-2 pr-4 text-terminal-dim font-normal">
|
||||||
|
Best for
|
||||||
|
</th>
|
||||||
|
<th className="text-left py-2 text-terminal-dim font-normal">
|
||||||
|
Considerations
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="py-2 pr-4 font-bold text-foreground">
|
||||||
|
SaaS
|
||||||
|
</td>
|
||||||
|
<td className="py-2 pr-4 text-foreground">
|
||||||
|
Quick deployment, standard use cases
|
||||||
|
</td>
|
||||||
|
<td className="py-2 text-terminal-dim">
|
||||||
|
Data leaves your environment, vendor lock-in
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="py-2 pr-4 font-bold text-foreground">
|
||||||
|
API-Based
|
||||||
|
</td>
|
||||||
|
<td className="py-2 pr-4 text-foreground">
|
||||||
|
Custom applications, flexibility
|
||||||
|
</td>
|
||||||
|
<td className="py-2 text-terminal-dim">
|
||||||
|
Requires dev resources, usage-based costs
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="py-2 pr-4 font-bold text-foreground">
|
||||||
|
On-Premise
|
||||||
|
</td>
|
||||||
|
<td className="py-2 pr-4 text-foreground">
|
||||||
|
Sensitive data, regulatory requirements
|
||||||
|
</td>
|
||||||
|
<td className="py-2 text-terminal-dim">
|
||||||
|
Higher upfront cost, maintenance burden
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="py-2 pr-4 font-bold text-foreground">
|
||||||
|
Hybrid/VPC
|
||||||
|
</td>
|
||||||
|
<td className="py-2 pr-4 text-foreground">
|
||||||
|
Balance of control and convenience
|
||||||
|
</td>
|
||||||
|
<td className="py-2 text-terminal-dim">
|
||||||
|
Complex setup, higher costs than pure SaaS
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Evaluation Framework */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat evaluation-framework.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-foreground mb-6 leading-relaxed">
|
||||||
|
Evaluate AI tools across five dimensions. Weight each dimension
|
||||||
|
based on your specific priorities and constraints.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[1]</span> Capability
|
||||||
|
fit
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Does the tool actually solve your problem with acceptable
|
||||||
|
accuracy and performance?
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Test
|
||||||
|
with your actual data and use cases, not demo data
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Evaluate edge cases and failure modes
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Understand accuracy requirements and whether the tool
|
||||||
|
meets them
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Check
|
||||||
|
latency and throughput for your volume requirements
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[2]</span> Integration
|
||||||
|
complexity
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
How easily does the tool fit into your existing technology
|
||||||
|
stack and workflows?
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>API
|
||||||
|
quality and documentation
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Pre-built connectors for your systems (CRM, ERP, etc.)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Authentication and SSO support
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Data
|
||||||
|
format compatibility
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[3]</span> Security
|
||||||
|
and compliance
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Does the tool meet your security standards and regulatory
|
||||||
|
requirements?
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Data
|
||||||
|
handling: Where is data stored? Is it used for training?
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Certifications: SOC 2, HIPAA, GDPR, ISO 27001
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Access
|
||||||
|
controls and audit logging
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Data
|
||||||
|
residency options if required
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[4]</span> Total cost
|
||||||
|
of ownership
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
What's the true cost including hidden and long-term
|
||||||
|
expenses?
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Licensing/subscription fees at your expected usage
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Integration and customization costs
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Training and change management
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Ongoing maintenance and support costs
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[5]</span> Vendor
|
||||||
|
viability
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Will this vendor be around and continuing to invest in the
|
||||||
|
product?
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Funding status and business model
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Product roadmap and innovation pace
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Customer base and market position
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Support quality and responsiveness
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Build vs Buy */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat build-vs-buy.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-foreground mb-6 leading-relaxed">
|
||||||
|
Not every AI capability needs to be purchased. Sometimes building
|
||||||
|
in-house or using open-source solutions makes more sense.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4 mb-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<h3 className="text-foreground font-bold mb-3">
|
||||||
|
Consider buying when...
|
||||||
|
</h3>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Standard use case with established solutions
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Time
|
||||||
|
to market is critical
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Limited internal AI/ML expertise
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Not a
|
||||||
|
core competitive differentiator
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Vendor
|
||||||
|
can iterate faster than you
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-yellow">
|
||||||
|
<h3 className="text-foreground font-bold mb-3">
|
||||||
|
Consider building when...
|
||||||
|
</h3>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Unique
|
||||||
|
requirements no vendor addresses
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Core
|
||||||
|
competitive advantage
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Strong
|
||||||
|
internal AI/ML team
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Sensitive data that can't leave your environment
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Long-term cost advantage at your scale
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong>Hybrid approach:</strong> Many organizations buy
|
||||||
|
commodity AI capabilities (OCR, speech-to-text) while building
|
||||||
|
custom solutions for differentiated use cases. APIs from
|
||||||
|
providers like OpenAI and Anthropic let you build custom
|
||||||
|
applications without building models from scratch.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Selection Mistakes */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat selection-mistakes.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Buying based
|
||||||
|
on demos
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
Vendors demo their best scenarios. Always test with your
|
||||||
|
actual data and edge cases. Request a proof of concept or
|
||||||
|
pilot before committing.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Ignoring
|
||||||
|
integration costs
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
The tool subscription is often the smallest part of total
|
||||||
|
cost. Budget for integration, customization, training, and
|
||||||
|
ongoing maintenance.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Chasing
|
||||||
|
features over fit
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
More features doesn't mean better. A simpler tool that
|
||||||
|
fits your specific needs often delivers more value than a
|
||||||
|
feature-rich platform you'll never fully utilize.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span>{" "}
|
||||||
|
Underestimating lock-in
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
Consider switching costs before committing. How portable is
|
||||||
|
your data and configuration? What happens if you need to
|
||||||
|
change vendors?
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Selection Process */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat selection-process.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[1]</span> Define
|
||||||
|
requirements
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
Document specific use cases, success criteria, technical
|
||||||
|
constraints, and budget. Be specific about what "good
|
||||||
|
enough" looks like.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[2]</span> Create
|
||||||
|
shortlist
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
Research 5-10 potential solutions. Quickly eliminate obvious
|
||||||
|
misfits based on capability, deployment model, and price
|
||||||
|
range.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[3]</span> Deep
|
||||||
|
evaluation (3-5 tools)
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
Request demos, review documentation, check references. Score
|
||||||
|
against your evaluation criteria.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[4]</span> Proof of
|
||||||
|
concept (1-2 tools)
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
Test top candidates with your actual data and use cases.
|
||||||
|
Involve end users. Measure against success criteria.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[5]</span> Negotiate
|
||||||
|
and commit
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
Negotiate terms based on POC results. Consider pilots or
|
||||||
|
phased rollouts to manage risk.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Related Claims */}
|
||||||
|
{toolsClaims.length > 0 && (
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
grep -r "tools" claims-library/
|
||||||
|
</h2>
|
||||||
|
<div className="space-y-4">
|
||||||
|
{toolsClaims.slice(0, 4).map((article) => (
|
||||||
|
<div key={article.slug} className="terminal-panel">
|
||||||
|
<Link
|
||||||
|
href={`/claims-library/${article.slug}`}
|
||||||
|
className="font-bold text-foreground hover:text-terminal-cyan transition-colors"
|
||||||
|
>
|
||||||
|
{article.title}
|
||||||
|
</Link>
|
||||||
|
<div className="mt-2 space-y-1">
|
||||||
|
{article.claims.slice(0, 2).map((claim, idx) => (
|
||||||
|
<div
|
||||||
|
key={idx}
|
||||||
|
className="pl-4 border-l border-terminal-green"
|
||||||
|
>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<span className="text-terminal-green text-xs font-bold mr-2">
|
||||||
|
[{idx + 1}]
|
||||||
|
</span>
|
||||||
|
{claim}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
<Link
|
||||||
|
href={`/claims-library/${article.slug}`}
|
||||||
|
className="inline-block mt-2 text-xs text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
View all {article.claims.length} claims
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Related Resources */}
|
||||||
|
<section className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">see also</span>
|
||||||
|
<div className="space-y-2 mt-2 text-sm">
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/ai-implementation"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat ai-implementation/*
|
||||||
|
</Link>
|
||||||
|
<span className="text-terminal-dim ml-2">
|
||||||
|
Implementation best practices
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/measuring-ai-roi"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat measuring-ai-roi/*
|
||||||
|
</Link>
|
||||||
|
<span className="text-terminal-dim ml-2">
|
||||||
|
Measuring AI ROI
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/ai-strategy"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat ai-strategy/*
|
||||||
|
</Link>
|
||||||
|
<span className="text-terminal-dim ml-2">
|
||||||
|
Building your AI strategy
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/claims-library"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
ls claims-library/
|
||||||
|
</Link>
|
||||||
|
<span className="text-terminal-dim ml-2">
|
||||||
|
Browse all claims
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<TerminalFooter />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,38 +1,35 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import { getTopicsForArticle } from "@/lib/topics";
|
|
||||||
import { getClaimBySlug, ALL_CLAIMS_DATA } from "@/data/claims";
|
import { getClaimBySlug, ALL_CLAIMS_DATA } from "@/data/claims";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { ArrowLeft, Linkedin, Youtube, Download } from "lucide-react";
|
|
||||||
import { CopyButton } from "@/components/CopyButton";
|
import { CopyButton } from "@/components/CopyButton";
|
||||||
import { HowToCite } from "@/components/HowToCite";
|
import { HowToCite } from "@/components/HowToCite";
|
||||||
import { notFound } from "next/navigation";
|
import { notFound } from "next/navigation";
|
||||||
|
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||||
|
import RelatedClaims from "@/components/RelatedClaims";
|
||||||
|
import TerminalFooter from "@/components/TerminalFooter";
|
||||||
|
|
||||||
// Generate static params for all claims pages
|
|
||||||
export async function generateStaticParams() {
|
export async function generateStaticParams() {
|
||||||
return ALL_CLAIMS_DATA.map((claim) => ({
|
return ALL_CLAIMS_DATA.map((claim) => ({
|
||||||
slug: claim.slug,
|
slug: claim.slug,
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generate metadata dynamically for each page
|
|
||||||
export async function generateMetadata({
|
export async function generateMetadata({
|
||||||
params
|
params,
|
||||||
}: {
|
}: {
|
||||||
params: Promise<{ slug: string }>
|
params: Promise<{ slug: string }>;
|
||||||
}): Promise<Metadata> {
|
}): Promise<Metadata> {
|
||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
const claim = getClaimBySlug(slug);
|
const claim = getClaimBySlug(slug);
|
||||||
|
|
||||||
if (!claim) {
|
if (!claim) {
|
||||||
return {
|
return { title: "Claim Not Found" };
|
||||||
title: "Claim Not Found | Kamil Banc",
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const description = `${claim.claims.length} atomic claims about ${claim.description.toLowerCase()}.`;
|
const description = `${claim.claims.length} atomic claims about ${claim.description.toLowerCase()}.`;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
title: `${claim.title} | Kamil Banc`,
|
title: claim.title,
|
||||||
description,
|
description,
|
||||||
authors: [{ name: "Kamil Banc" }],
|
authors: [{ name: "Kamil Banc" }],
|
||||||
openGraph: {
|
openGraph: {
|
||||||
|
|
@ -53,9 +50,9 @@ export async function generateMetadata({
|
||||||
}
|
}
|
||||||
|
|
||||||
export default async function DynamicClaimPage({
|
export default async function DynamicClaimPage({
|
||||||
params
|
params,
|
||||||
}: {
|
}: {
|
||||||
params: Promise<{ slug: string }>
|
params: Promise<{ slug: string }>;
|
||||||
}) {
|
}) {
|
||||||
const { slug } = await params;
|
const { slug } = await params;
|
||||||
const claim = getClaimBySlug(slug);
|
const claim = getClaimBySlug(slug);
|
||||||
|
|
@ -64,7 +61,7 @@ export default async function DynamicClaimPage({
|
||||||
notFound();
|
notFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON-LD schema for SEO
|
// JSON-LD Article schema - values sourced from compile-time claim data, safe to inline
|
||||||
const jsonLd = {
|
const jsonLd = {
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "Article",
|
"@type": "Article",
|
||||||
|
|
@ -72,12 +69,13 @@ export default async function DynamicClaimPage({
|
||||||
author: {
|
author: {
|
||||||
"@type": "Person",
|
"@type": "Person",
|
||||||
name: "Kamil Banc",
|
name: "Kamil Banc",
|
||||||
jobTitle: "Author",
|
jobTitle: "AI Implementation Expert & Strategist",
|
||||||
affiliation: {
|
url: "https://kbanc.com/about",
|
||||||
"@type": "Organization",
|
image: "https://kbanc.com/kamil-banc.jpg",
|
||||||
name: "AI Adopters Club",
|
sameAs: [
|
||||||
url: "https://aiadopters.club",
|
"https://www.linkedin.com/in/kbanc/",
|
||||||
},
|
"https://x.com/kamilbanc",
|
||||||
|
],
|
||||||
},
|
},
|
||||||
datePublished: claim.date,
|
datePublished: claim.date,
|
||||||
dateModified: claim.date,
|
dateModified: claim.date,
|
||||||
|
|
@ -91,89 +89,72 @@ export default async function DynamicClaimPage({
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
{/* Trusted compile-time JSON-LD structured data for SEO */}
|
||||||
<script
|
<script
|
||||||
type="application/ld+json"
|
type="application/ld+json"
|
||||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
/>
|
/>
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
<header className="bg-muted border-b-2 border-border py-8 mb-12">
|
<header className="border-b border-border py-8 mb-8">
|
||||||
<div className="container max-w-3xl mx-auto px-6">
|
<div className="max-w-3xl mx-auto px-6">
|
||||||
<Link
|
<Breadcrumbs
|
||||||
href="/claims-library"
|
items={[
|
||||||
className="inline-flex items-center text-sm text-primary hover:underline mb-4"
|
{ label: "~", href: "/" },
|
||||||
>
|
{ label: "claims-library", href: "/claims-library" },
|
||||||
<ArrowLeft className="mr-2 h-4 w-4" />
|
{ label: slug },
|
||||||
Back to Claims Library
|
]}
|
||||||
</Link>
|
/>
|
||||||
<h1 className="text-4xl font-bold mb-2 text-foreground">
|
<h1 className="text-2xl md:text-3xl font-bold text-foreground mb-2">
|
||||||
{claim.title}
|
{claim.title}
|
||||||
</h1>
|
</h1>
|
||||||
<div className="flex items-center gap-3">
|
<div className="text-sm text-terminal-dim">
|
||||||
<p className="text-muted-foreground">
|
|
||||||
By{" "}
|
By{" "}
|
||||||
<a
|
<Link href="/about" className="text-terminal-cyan hover:underline">
|
||||||
href="https://aiadopters.club"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-primary hover:underline"
|
|
||||||
>
|
|
||||||
Kamil Banc
|
Kamil Banc
|
||||||
</a>
|
</Link>
|
||||||
, Author at AI Adopters Club
|
{" "}| {new Date(claim.date).toLocaleDateString("en-US", {
|
||||||
</p>
|
month: "long",
|
||||||
<a
|
day: "numeric",
|
||||||
href="https://www.linkedin.com/in/kbanc/"
|
year: "numeric",
|
||||||
target="_blank"
|
})}
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-primary hover:text-primary/80 transition-colors"
|
|
||||||
aria-label="LinkedIn Profile"
|
|
||||||
>
|
|
||||||
<Linkedin className="h-5 w-5" />
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://www.youtube.com/@adaptandcreate"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-primary hover:text-primary/80 transition-colors"
|
|
||||||
aria-label="YouTube Channel"
|
|
||||||
>
|
|
||||||
<Youtube className="h-5 w-5" />
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main className="container max-w-3xl mx-auto px-6 pb-12">
|
<main className="max-w-3xl mx-auto px-6 pb-12">
|
||||||
{/* Topic Tags */}
|
{/* Topic tags */}
|
||||||
<section className="mb-8 -mt-4">
|
<div className="flex flex-wrap gap-2 mb-8">
|
||||||
<div className="flex flex-wrap gap-2">
|
{claim.topics.map((topic) => (
|
||||||
{getTopicsForArticle(claim.slug).map((topic) => (
|
<Link
|
||||||
<span
|
|
||||||
key={topic.id}
|
key={topic.id}
|
||||||
className={`px-3 py-1 rounded-full text-sm font-medium ${topic.color}`}
|
href={`/${topic.slug || topic.id}`}
|
||||||
|
className="terminal-tag hover:text-terminal-bright transition-colors"
|
||||||
>
|
>
|
||||||
{topic.label}
|
{topic.id}
|
||||||
</span>
|
</Link>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Atomic Claims Section */}
|
{/* Atomic Claims */}
|
||||||
<section className="mb-12">
|
<section className="mb-12">
|
||||||
<h2 className="text-3xl font-semibold mb-6 mt-12">Atomic Claims</h2>
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat claims.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
{claim.claims.map((claimText, index) => (
|
{claim.claims.map((claimText, index) => (
|
||||||
<article
|
<article
|
||||||
key={index}
|
key={index}
|
||||||
className="bg-muted border border-border border-l-4 border-l-accent rounded-lg p-6 mb-6 transition-transform hover:translate-y-[-2px] hover:shadow-md"
|
className="terminal-panel mb-4 border-l-2 border-l-terminal-green"
|
||||||
>
|
>
|
||||||
<div className="flex justify-between items-start gap-4">
|
<div className="flex justify-between items-start gap-4">
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<h3 className="text-lg font-semibold mb-3">
|
<h3 className="text-sm font-bold mb-2">
|
||||||
<span className="text-accent">Claim {index + 1}:</span>{" "}
|
<span className="text-terminal-green">
|
||||||
|
[{index + 1}]
|
||||||
|
</span>{" "}
|
||||||
{claim.claimTitles[index]}
|
{claim.claimTitles[index]}
|
||||||
</h3>
|
</h3>
|
||||||
<p className="text-lg font-medium leading-relaxed text-foreground">
|
<p className="text-sm leading-relaxed text-foreground">
|
||||||
{claimText}
|
{claimText}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -186,22 +167,24 @@ export default async function DynamicClaimPage({
|
||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Supporting Evidence Section */}
|
{/* Supporting Evidence */}
|
||||||
<section className="mb-12">
|
<section className="mb-12">
|
||||||
<h2 className="text-3xl font-semibold mb-6 mt-12">Supporting Evidence</h2>
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat evidence.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
{/* Quote */}
|
{/* Quote */}
|
||||||
<div className="bg-card border border-border rounded-lg p-6 mb-6">
|
<div className="terminal-panel mb-4">
|
||||||
<div className="flex justify-between items-start gap-4 mb-3">
|
<div className="flex justify-between items-start gap-4 mb-2">
|
||||||
<h3 className="text-lg font-semibold">Quote</h3>
|
<span className="terminal-panel-title">quote</span>
|
||||||
<CopyButton
|
<CopyButton
|
||||||
text={`"${claim.quote}" - Kamil Banc`}
|
text={`"${claim.quote}" - Kamil Banc`}
|
||||||
size="sm"
|
size="sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<blockquote className="italic text-lg leading-relaxed text-foreground border-l-4 border-l-accent pl-6 my-6">
|
<blockquote className="border-l-2 border-terminal-cyan pl-4 italic text-foreground">
|
||||||
<p>"{claim.quote}"</p>
|
<p>"{claim.quote}"</p>
|
||||||
<cite className="block not-italic text-sm text-muted-foreground mt-4">
|
<cite className="block not-italic text-xs text-terminal-dim mt-2">
|
||||||
Kamil Banc
|
Kamil Banc
|
||||||
</cite>
|
</cite>
|
||||||
</blockquote>
|
</blockquote>
|
||||||
|
|
@ -209,67 +192,49 @@ export default async function DynamicClaimPage({
|
||||||
|
|
||||||
{/* Key Statistics */}
|
{/* Key Statistics */}
|
||||||
{claim.keyStatistics.length > 0 && (
|
{claim.keyStatistics.length > 0 && (
|
||||||
<div className="bg-card border border-border rounded-lg p-6 mb-6">
|
<div className="terminal-panel mb-4">
|
||||||
<h3 className="text-lg font-semibold mb-3">Key Statistics</h3>
|
<span className="terminal-panel-title">statistics</span>
|
||||||
<ul className="space-y-3">
|
<ul className="space-y-3 mt-2">
|
||||||
{claim.keyStatistics.map((stat, index) => (
|
{claim.keyStatistics.map((stat, index) => (
|
||||||
<li key={index} className="p-3 bg-muted rounded-lg">
|
<li key={index} className="flex justify-between items-start gap-4">
|
||||||
<div className="flex justify-between items-start gap-4">
|
|
||||||
<div className="flex-1">
|
<div className="flex-1">
|
||||||
<p className="text-lg font-semibold text-accent">{stat.stat}</p>
|
<p className="text-sm font-bold text-terminal-yellow">
|
||||||
<p className="text-sm text-muted-foreground">{stat.context}</p>
|
{stat.stat}
|
||||||
|
</p>
|
||||||
|
<p className="text-xs text-terminal-dim">
|
||||||
|
{stat.context}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<CopyButton
|
<CopyButton
|
||||||
text={`${stat.stat}: ${stat.context}`}
|
text={`${stat.stat}: ${stat.context}`}
|
||||||
size="sm"
|
size="sm"
|
||||||
/>
|
/>
|
||||||
</div>
|
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Sources & Citations */}
|
{/* Sources */}
|
||||||
<div className="bg-card border border-border rounded-lg p-6 mb-6">
|
<div className="terminal-panel mb-4">
|
||||||
<h3 className="text-lg font-semibold mb-3">Sources & Citations</h3>
|
<span className="terminal-panel-title">sources</span>
|
||||||
<div className="space-y-4">
|
<div className="space-y-2 mt-2 text-sm">
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm font-semibold text-muted-foreground mb-2">
|
<span className="text-terminal-dim">original: </span>
|
||||||
Original Article (Full Context):
|
|
||||||
</p>
|
|
||||||
<div className="flex items-center gap-2 pl-6 relative">
|
|
||||||
<span className="absolute left-0 text-accent font-bold">→</span>
|
|
||||||
<a
|
<a
|
||||||
href={claim.originalUrl}
|
href={claim.originalUrl}
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
className="text-foreground hover:text-accent hover:underline transition-colors"
|
className="text-terminal-cyan hover:underline"
|
||||||
>
|
>
|
||||||
{claim.title} (AI Adopters Club)
|
{claim.title} (AI Adopters Club)
|
||||||
</a>
|
</a>
|
||||||
<CopyButton
|
|
||||||
text={claim.originalUrl}
|
|
||||||
label=""
|
|
||||||
size="sm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm font-semibold text-muted-foreground mb-2">
|
<span className="text-terminal-dim">cite: </span>
|
||||||
Cite This Page (Structured Claims):
|
<code className="text-xs text-foreground">
|
||||||
</p>
|
kbanc.com/claims-library/{claim.slug}
|
||||||
<div className="flex items-center gap-2 pl-6 relative">
|
|
||||||
<span className="absolute left-0 text-accent font-bold">→</span>
|
|
||||||
<code className="text-sm bg-muted px-2 py-1 rounded">
|
|
||||||
https://kbanc.com/claims-library/{claim.slug}
|
|
||||||
</code>
|
</code>
|
||||||
<CopyButton
|
|
||||||
text={`https://kbanc.com/claims-library/${claim.slug}`}
|
|
||||||
label=""
|
|
||||||
size="sm"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -283,68 +248,19 @@ export default async function DynamicClaimPage({
|
||||||
originalUrl={claim.originalUrl}
|
originalUrl={claim.originalUrl}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
{/* Download Section */}
|
{/* Context */}
|
||||||
<section className="bg-muted border-2 border-accent rounded-lg p-8 mb-12 text-center">
|
<section className="terminal-panel mb-8">
|
||||||
<h2 className="text-2xl font-semibold mb-4">Download Data</h2>
|
<span className="terminal-panel-title">context</span>
|
||||||
<p className="mb-6">Access structured claim data in CSV format:</p>
|
<p className="text-sm text-foreground mt-2 leading-relaxed">
|
||||||
<a href={`/assets/${claim.slug}-claims.csv`} download>
|
{claim.supportingContext}
|
||||||
<button className="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 h-10 px-4 py-2 bg-accent hover:bg-accent/90 text-accent-foreground transition-transform hover:translate-y-[-2px]">
|
</p>
|
||||||
<Download className="mr-2 h-4 w-4" />
|
|
||||||
Download Claims Data (CSV)
|
|
||||||
</button>
|
|
||||||
</a>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Context Section */}
|
{/* Related Claims */}
|
||||||
<section className="bg-muted rounded-lg p-8 mb-12">
|
<RelatedClaims currentSlug={claim.slug} />
|
||||||
<h2 className="text-2xl font-semibold mb-4">Context</h2>
|
|
||||||
<p className="mb-4 text-foreground">
|
|
||||||
This page presents atomic claims extracted from research on{" "}
|
|
||||||
{claim.description.toLowerCase()}. Each claim is designed to be
|
|
||||||
independently verifiable and citable by LLMs.
|
|
||||||
</p>
|
|
||||||
<p className="text-foreground">{claim.supportingContext}</p>
|
|
||||||
</section>
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
{/* Footer */}
|
<TerminalFooter />
|
||||||
<footer className="bg-muted border-t-2 border-border py-8 mt-12 text-center">
|
|
||||||
<div className="container max-w-3xl mx-auto px-6">
|
|
||||||
<p className="mb-2 text-sm text-muted-foreground">
|
|
||||||
Content licensed under{" "}
|
|
||||||
<a
|
|
||||||
href="https://creativecommons.org/licenses/by/4.0/"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
className="text-primary hover:underline"
|
|
||||||
>
|
|
||||||
CC BY 4.0
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
Source:{" "}
|
|
||||||
<a
|
|
||||||
href="https://aiadopters.club"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
className="text-primary hover:underline"
|
|
||||||
>
|
|
||||||
AI Adopters Club
|
|
||||||
</a>{" "}
|
|
||||||
by Kamil Banc
|
|
||||||
</p>
|
|
||||||
<p className="mt-4 text-sm text-muted-foreground">
|
|
||||||
<a
|
|
||||||
href="https://aiadopters.club/p/work-with-kamil"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
className="text-accent hover:text-accent/80 transition-colors"
|
|
||||||
>
|
|
||||||
Need help with AI integration? → Work with Kamil
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { ArrowLeft } from "lucide-react";
|
import { SORTED_CLAIMS, getTotalClaimsCount } from "@/data/claims";
|
||||||
import { SORTED_CLAIMS, getTotalClaimsCount, getClaimBySlug } from "@/data/claims";
|
|
||||||
import { getAllTopics } from "@/lib/topics";
|
import { getAllTopics } from "@/lib/topics";
|
||||||
|
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||||
|
import TerminalFooter from "@/components/TerminalFooter";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: `Complete Claims Index - All ${getTotalClaimsCount()} Atomic Claims | Kamil Banc`,
|
title: `Complete Claims Index - All ${getTotalClaimsCount()} Atomic Claims`,
|
||||||
description: `Comprehensive index of all ${getTotalClaimsCount()} atomic claims about AI implementation from AI Adopters Club. Optimized for LLM extraction and research citation.`,
|
description: `Comprehensive index of all ${getTotalClaimsCount()} atomic claims about AI implementation from AI Adopters Club. Optimized for LLM extraction and research citation.`,
|
||||||
alternates: {
|
alternates: {
|
||||||
canonical: "https://kbanc.com/claims-library/all",
|
canonical: "https://kbanc.com/claims-library/all",
|
||||||
|
|
@ -13,10 +14,8 @@ export const metadata: Metadata = {
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function AllClaimsPage() {
|
export default function AllClaimsPage() {
|
||||||
// Automatically populated from centralized claims data
|
|
||||||
const allTopics = getAllTopics();
|
const allTopics = getAllTopics();
|
||||||
|
|
||||||
// Group articles by topic
|
|
||||||
const articlesByTopic: Record<string, typeof SORTED_CLAIMS> = {};
|
const articlesByTopic: Record<string, typeof SORTED_CLAIMS> = {};
|
||||||
SORTED_CLAIMS.forEach((claim) => {
|
SORTED_CLAIMS.forEach((claim) => {
|
||||||
claim.topics.forEach((topic) => {
|
claim.topics.forEach((topic) => {
|
||||||
|
|
@ -27,38 +26,61 @@ export default function AllClaimsPage() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// ItemList schema - compile-time trusted data, safe to inline as JSON-LD
|
||||||
|
const itemListJsonLd = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "ItemList",
|
||||||
|
name: "AI Adoption Claims Library - Complete Index",
|
||||||
|
description: `All ${getTotalClaimsCount()} atomic claims about AI implementation`,
|
||||||
|
numberOfItems: SORTED_CLAIMS.length,
|
||||||
|
itemListElement: SORTED_CLAIMS.map((claim, index) => ({
|
||||||
|
"@type": "ListItem",
|
||||||
|
position: index + 1,
|
||||||
|
url: `https://kbanc.com/claims-library/${claim.slug}`,
|
||||||
|
name: claim.title,
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
{/* Compile-time JSON-LD structured data from claims.ts - no user input */}
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(itemListJsonLd) }}
|
||||||
|
/>
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
<header className="bg-muted border-b-2 border-border py-8 mb-12">
|
<header className="border-b border-border py-8 mb-8">
|
||||||
<div className="container max-w-4xl mx-auto px-6">
|
<div className="max-w-4xl mx-auto px-6">
|
||||||
<Link
|
<Breadcrumbs
|
||||||
href="/claims-library"
|
items={[
|
||||||
className="inline-flex items-center text-sm text-primary hover:underline mb-4"
|
{ label: "~", href: "/" },
|
||||||
>
|
{ label: "claims-library", href: "/claims-library" },
|
||||||
<ArrowLeft className="mr-2 h-4 w-4" />
|
{ label: "all" },
|
||||||
Back to Claims Library
|
]}
|
||||||
</Link>
|
/>
|
||||||
<h1 className="text-4xl font-bold mb-3 text-foreground">
|
<h1 className="text-2xl md:text-3xl font-bold text-foreground mb-2">
|
||||||
Complete Claims Index
|
Complete Claims Index
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-lg text-muted-foreground">
|
<p className="text-terminal-dim text-sm">
|
||||||
All {getTotalClaimsCount()} atomic claims from {SORTED_CLAIMS.length} articles, optimized for AI extraction and research citation
|
All {getTotalClaimsCount()} atomic claims from{" "}
|
||||||
|
{SORTED_CLAIMS.length} articles, optimized for AI extraction and
|
||||||
|
research citation
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main className="container max-w-4xl mx-auto px-6 pb-12">
|
<main className="max-w-4xl mx-auto px-6 pb-12">
|
||||||
{/* Quick Navigation */}
|
{/* Quick nav */}
|
||||||
<section className="mb-12 p-6 bg-muted rounded-lg">
|
<section className="terminal-panel mb-8">
|
||||||
<h2 className="text-2xl font-semibold mb-4">Browse by Topic</h2>
|
<span className="terminal-panel-title">browse by topic</span>
|
||||||
<div className="flex flex-wrap gap-2">
|
<div className="flex flex-wrap gap-2 mt-2">
|
||||||
{allTopics.map((topic) => (
|
{allTopics.map((topic) => (
|
||||||
<a
|
<a
|
||||||
key={topic.id}
|
key={topic.id}
|
||||||
href={`#topic-${topic.id}`}
|
href={`#topic-${topic.id}`}
|
||||||
className={`px-4 py-2 rounded-lg text-sm font-medium hover:opacity-80 transition-opacity ${topic.color}`}
|
className="terminal-tag hover:text-terminal-bright transition-colors"
|
||||||
>
|
>
|
||||||
{topic.label} ({articlesByTopic[topic.id]?.length || 0})
|
{topic.id} ({articlesByTopic[topic.id]?.length || 0})
|
||||||
</a>
|
</a>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -70,42 +92,49 @@ export default function AllClaimsPage() {
|
||||||
if (topicArticles.length === 0) return null;
|
if (topicArticles.length === 0) return null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<section key={topic.id} id={`topic-${topic.id}`} className="mb-16">
|
<section key={topic.id} id={`topic-${topic.id}`} className="mb-12">
|
||||||
<div className="flex items-center gap-3 mb-6">
|
<h2 className="terminal-prompt text-foreground font-bold mb-2">
|
||||||
<h2 className="text-3xl font-bold">{topic.label}</h2>
|
cat {topic.id}/*
|
||||||
<span className={`px-3 py-1 rounded-full text-sm ${topic.color}`}>
|
</h2>
|
||||||
{topicArticles.length} {topicArticles.length === 1 ? "article" : "articles"}
|
<p className="text-xs text-terminal-dim mb-6">
|
||||||
</span>
|
{topic.description}
|
||||||
</div>
|
</p>
|
||||||
<p className="text-muted-foreground mb-8">{topic.description}</p>
|
|
||||||
|
|
||||||
{topicArticles.map((article) => {
|
{topicArticles.map((article) => (
|
||||||
return (
|
<article
|
||||||
<article key={article.slug} className="mb-10 p-6 bg-card border border-border rounded-lg">
|
key={article.slug}
|
||||||
<div className="mb-4">
|
className="terminal-panel mb-6"
|
||||||
|
>
|
||||||
|
<div className="mb-3">
|
||||||
<Link
|
<Link
|
||||||
href={`/claims-library/${article.slug}`}
|
href={`/claims-library/${article.slug}`}
|
||||||
className="text-xl font-semibold text-foreground hover:text-accent transition-colors"
|
className="font-bold text-foreground hover:text-terminal-cyan transition-colors"
|
||||||
>
|
>
|
||||||
{article.title}
|
{article.title}
|
||||||
</Link>
|
</Link>
|
||||||
<p className="text-sm text-muted-foreground mt-1">
|
<p className="text-xs text-terminal-dim mt-1">
|
||||||
Published: {new Date(article.date).toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })} •{" "}
|
{new Date(article.date).toLocaleDateString("en-US", {
|
||||||
{article.claims.length} Claims
|
year: "numeric",
|
||||||
|
month: "long",
|
||||||
|
day: "numeric",
|
||||||
|
})}{" "}
|
||||||
|
| {article.claims.length} claims
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="space-y-3">
|
<div className="space-y-2">
|
||||||
{article.claims.map((claim, idx) => (
|
{article.claims.map((claim, idx) => (
|
||||||
<div
|
<div
|
||||||
key={idx}
|
key={idx}
|
||||||
className="p-4 bg-muted border-l-4 border-l-accent rounded"
|
className="pl-4 border-l border-terminal-green"
|
||||||
>
|
>
|
||||||
<div className="flex items-start gap-3">
|
<div className="flex items-start gap-2">
|
||||||
<span className="text-accent font-bold text-sm flex-shrink-0">
|
<span className="text-terminal-green text-xs font-bold flex-shrink-0">
|
||||||
{idx + 1}
|
[{idx + 1}]
|
||||||
</span>
|
</span>
|
||||||
<p className="text-foreground leading-relaxed">{claim}</p>
|
<p className="text-sm text-foreground leading-relaxed">
|
||||||
|
{claim}
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
|
@ -113,55 +142,39 @@ export default function AllClaimsPage() {
|
||||||
|
|
||||||
<Link
|
<Link
|
||||||
href={`/claims-library/${article.slug}`}
|
href={`/claims-library/${article.slug}`}
|
||||||
className="inline-block mt-4 text-sm text-accent hover:underline"
|
className="inline-block mt-3 text-xs text-terminal-cyan hover:underline"
|
||||||
>
|
>
|
||||||
View full article with evidence →
|
View full article with evidence
|
||||||
</Link>
|
</Link>
|
||||||
</article>
|
</article>
|
||||||
);
|
))}
|
||||||
})}
|
|
||||||
</section>
|
</section>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
|
||||||
{/* Citation Information */}
|
{/* Citation info */}
|
||||||
<section className="mt-16 p-8 bg-muted rounded-lg">
|
<section className="terminal-panel">
|
||||||
<h2 className="text-2xl font-semibold mb-4">How to Cite These Claims</h2>
|
<span className="terminal-panel-title">citation</span>
|
||||||
<p className="mb-4 text-foreground">
|
<p className="text-sm text-foreground mt-2 mb-2">
|
||||||
All claims are licensed under{" "}
|
All claims licensed under{" "}
|
||||||
<a
|
<a
|
||||||
href="https://creativecommons.org/licenses/by/4.0/"
|
href="https://creativecommons.org/licenses/by/4.0/"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener"
|
rel="noopener"
|
||||||
className="text-accent hover:underline"
|
className="text-terminal-cyan hover:underline"
|
||||||
>
|
>
|
||||||
Creative Commons Attribution 4.0
|
CC BY 4.0
|
||||||
</a>
|
</a>
|
||||||
</p>
|
</p>
|
||||||
<div className="bg-card p-4 rounded border border-border">
|
<code className="text-xs text-terminal-dim">
|
||||||
<p className="text-sm font-mono text-muted-foreground">
|
Attribution: "Kamil Banc, AI Adopters Club" + link to
|
||||||
Required attribution: "Kamil Banc, AI Adopters Club" with link to
|
kbanc.com/claims-library/[slug]
|
||||||
kbanc.com/claims-library/[article-slug]
|
</code>
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer className="bg-muted border-t-2 border-border py-8 mt-12 text-center">
|
<TerminalFooter />
|
||||||
<div className="container max-w-4xl mx-auto px-6">
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
<a
|
|
||||||
href="https://aiadopters.club"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
className="text-accent hover:underline"
|
|
||||||
>
|
|
||||||
AI Adopters Club
|
|
||||||
</a>{" "}
|
|
||||||
by Kamil Banc
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,26 @@
|
||||||
"use client";
|
"use client";
|
||||||
|
|
||||||
import type { Metadata } from "next";
|
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { ArrowLeft, Linkedin, Search } from "lucide-react";
|
|
||||||
import { useState, useMemo } from "react";
|
import { useState, useMemo } from "react";
|
||||||
import { ALL_CLAIMS_DATA, getTotalClaimsCount } from "@/data/claims";
|
import { ALL_CLAIMS_DATA, getTotalClaimsCount } from "@/data/claims";
|
||||||
|
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||||
|
import TerminalFooter from "@/components/TerminalFooter";
|
||||||
|
|
||||||
export default function ClaimsLibraryPage() {
|
export default function ClaimsLibraryPage() {
|
||||||
const [selectedTopic, setSelectedTopic] = useState<string>("all");
|
const [selectedTopic, setSelectedTopic] = useState<string>("all");
|
||||||
const [searchQuery, setSearchQuery] = useState("");
|
const [searchQuery, setSearchQuery] = useState("");
|
||||||
|
|
||||||
// Automatically populated from centralized claims data
|
|
||||||
const articles = ALL_CLAIMS_DATA;
|
const articles = ALL_CLAIMS_DATA;
|
||||||
|
|
||||||
const filteredArticles = useMemo(() => {
|
const filteredArticles = useMemo(() => {
|
||||||
let filtered = articles;
|
let filtered = articles;
|
||||||
|
|
||||||
// Filter by topic
|
|
||||||
if (selectedTopic !== "all") {
|
if (selectedTopic !== "all") {
|
||||||
filtered = filtered.filter((article) =>
|
filtered = filtered.filter((article) =>
|
||||||
article.topics.some((t) => t.id === selectedTopic)
|
article.topics.some((t) => t.id === selectedTopic)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filter by search query
|
|
||||||
if (searchQuery) {
|
if (searchQuery) {
|
||||||
const query = searchQuery.toLowerCase();
|
const query = searchQuery.toLowerCase();
|
||||||
filtered = filtered.filter(
|
filtered = filtered.filter(
|
||||||
|
|
@ -34,142 +31,120 @@ export default function ClaimsLibraryPage() {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sort by date (most recent first)
|
|
||||||
return filtered.sort(
|
return filtered.sort(
|
||||||
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
|
(a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()
|
||||||
);
|
);
|
||||||
}, [articles, selectedTopic, searchQuery]);
|
}, [articles, selectedTopic, searchQuery]);
|
||||||
|
|
||||||
const topics = [
|
const topics = [
|
||||||
{ id: "all", label: "All Topics", color: "bg-accent text-accent-foreground" },
|
{ id: "all", label: "all" },
|
||||||
{ id: "strategy", label: "AI Strategy", color: "bg-blue-100 text-blue-800" },
|
{ id: "strategy", label: "strategy" },
|
||||||
{ id: "tools", label: "AI Tools", color: "bg-green-100 text-green-800" },
|
{ id: "tools", label: "tools" },
|
||||||
{ id: "business", label: "Business Applications", color: "bg-pink-100 text-pink-800" },
|
{ id: "business", label: "business" },
|
||||||
{ id: "implementation", label: "Implementation", color: "bg-orange-100 text-orange-800" },
|
{ id: "implementation", label: "implementation" },
|
||||||
{ id: "measurement", label: "ROI & Measurement", color: "bg-purple-100 text-purple-800" },
|
{ id: "measurement", label: "measurement" },
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
<header className="bg-muted border-b-2 border-border py-8 mb-12">
|
<header className="border-b border-border py-8 mb-8">
|
||||||
<div className="container max-w-6xl mx-auto px-6">
|
<div className="max-w-4xl mx-auto px-6">
|
||||||
<Link
|
<Breadcrumbs
|
||||||
href="/"
|
items={[
|
||||||
className="inline-flex items-center text-sm text-primary hover:underline mb-4"
|
{ label: "~", href: "/" },
|
||||||
>
|
{ label: "claims-library" },
|
||||||
<ArrowLeft className="mr-2 h-4 w-4" />
|
]}
|
||||||
Back to Home
|
/>
|
||||||
</Link>
|
<h1 className="text-2xl md:text-3xl font-bold text-foreground mb-2">
|
||||||
<h1 className="text-4xl font-bold mb-2 text-foreground">
|
|
||||||
AI Adoption Claims Library
|
AI Adoption Claims Library
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-muted-foreground mb-4">
|
<p className="text-terminal-dim text-sm">
|
||||||
{filteredArticles.length} {filteredArticles.length === 1 ? 'article' : 'articles'} • {getTotalClaimsCount()} atomic claims • Evidence-based insights optimized for LLM citations
|
{filteredArticles.length} articles, {getTotalClaimsCount()} atomic claims.
|
||||||
|
Evidence-based insights optimized for LLM citations.
|
||||||
</p>
|
</p>
|
||||||
<div className="flex items-center gap-3">
|
|
||||||
<span className="text-sm text-muted-foreground">
|
|
||||||
By{" "}
|
|
||||||
<a
|
|
||||||
href="https://aiadopters.club"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-primary hover:underline"
|
|
||||||
>
|
|
||||||
Kamil Banc
|
|
||||||
</a>
|
|
||||||
</span>
|
|
||||||
<a
|
|
||||||
href="https://www.linkedin.com/in/kbanc/"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-primary hover:text-primary/80 transition-colors"
|
|
||||||
aria-label="LinkedIn Profile"
|
|
||||||
>
|
|
||||||
<Linkedin className="h-5 w-5" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main className="container max-w-6xl mx-auto px-6 pb-12">
|
<main className="max-w-4xl mx-auto px-6 pb-12">
|
||||||
{/* Filters Section */}
|
{/* Search styled as grep */}
|
||||||
<section className="mb-8">
|
<section className="mb-6">
|
||||||
{/* Topic Filters */}
|
<div className="flex items-center gap-2 mb-4">
|
||||||
<div className="flex flex-wrap gap-2 mb-4">
|
<span className="text-terminal-green font-bold text-sm">$</span>
|
||||||
|
<span className="text-foreground text-sm">grep -i</span>
|
||||||
|
<input
|
||||||
|
type="text"
|
||||||
|
placeholder="query"
|
||||||
|
value={searchQuery}
|
||||||
|
onChange={(e) => setSearchQuery(e.target.value)}
|
||||||
|
className="flex-1 bg-transparent border-b border-border text-foreground text-sm px-2 py-1 focus:outline-none focus:border-terminal-green placeholder:text-terminal-dim"
|
||||||
|
/>
|
||||||
|
<span className="text-foreground text-sm">claims/*</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Topic filter as bracket tags */}
|
||||||
|
<div className="flex flex-wrap gap-2">
|
||||||
{topics.map((topic) => (
|
{topics.map((topic) => (
|
||||||
<button
|
<button
|
||||||
key={topic.id}
|
key={topic.id}
|
||||||
onClick={() => setSelectedTopic(topic.id)}
|
onClick={() => setSelectedTopic(topic.id)}
|
||||||
className={`px-4 py-2 rounded-full text-sm font-medium transition-all ${
|
className={`text-xs font-mono px-2 py-1 border transition-colors ${
|
||||||
selectedTopic === topic.id
|
selectedTopic === topic.id
|
||||||
? topic.color
|
? "border-terminal-green text-terminal-green"
|
||||||
: "bg-muted text-muted-foreground hover:bg-muted/80"
|
: "border-border text-terminal-dim hover:text-foreground hover:border-foreground"
|
||||||
}`}
|
}`}
|
||||||
>
|
>
|
||||||
{topic.label}
|
[{topic.label}]
|
||||||
</button>
|
</button>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Search Bar */}
|
|
||||||
<div className="relative">
|
|
||||||
<Search className="absolute left-3 top-1/2 transform -translate-y-1/2 h-4 w-4 text-muted-foreground" />
|
|
||||||
<input
|
|
||||||
type="text"
|
|
||||||
placeholder="Search articles, topics, or claims..."
|
|
||||||
value={searchQuery}
|
|
||||||
onChange={(e) => setSearchQuery(e.target.value)}
|
|
||||||
className="w-full pl-10 pr-4 py-3 bg-muted border border-border rounded-lg focus:outline-none focus:ring-2 focus:ring-accent"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Results count */}
|
{/* Results count */}
|
||||||
{(selectedTopic !== "all" || searchQuery) && (
|
{(selectedTopic !== "all" || searchQuery) && (
|
||||||
<div className="mb-6 text-sm text-muted-foreground">
|
<div className="mb-4 text-xs text-terminal-dim">
|
||||||
Showing {filteredArticles.length} of {articles.length} articles
|
Showing {filteredArticles.length} of {articles.length} articles
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Grid Layout */}
|
{/* Claims grid as terminal panels */}
|
||||||
<section className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-12">
|
<section className="space-y-4 mb-12">
|
||||||
{filteredArticles.map((article) => (
|
{filteredArticles.map((article) => (
|
||||||
<article
|
<article
|
||||||
key={article.slug}
|
key={article.slug}
|
||||||
className="bg-card border border-border rounded-lg p-6 transition-all hover:shadow-lg hover:translate-y-[-2px] flex flex-col"
|
className="terminal-panel hover:border-terminal-dim transition-colors"
|
||||||
>
|
>
|
||||||
{/* Topic Tags */}
|
{/* Topic tags */}
|
||||||
<div className="flex flex-wrap gap-2 mb-3">
|
<div className="flex flex-wrap gap-2 mb-2">
|
||||||
{article.topics.map((topic) => (
|
{article.topics.map((topic) => (
|
||||||
<span
|
<span key={topic.id} className="terminal-tag">
|
||||||
key={topic.id}
|
{topic.id}
|
||||||
className={`px-2 py-1 rounded text-xs font-medium ${topic.color}`}
|
|
||||||
>
|
|
||||||
{topic.label}
|
|
||||||
</span>
|
</span>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Title */}
|
{/* Title */}
|
||||||
<h3 className="text-lg font-semibold mb-2 text-foreground">
|
<h3 className="font-bold mb-2">
|
||||||
<Link
|
<Link
|
||||||
href={`/claims-library/${article.slug}`}
|
href={`/claims-library/${article.slug}`}
|
||||||
className="hover:text-accent transition-colors"
|
className="text-foreground hover:text-terminal-cyan transition-colors"
|
||||||
>
|
>
|
||||||
{article.title}
|
{article.title}
|
||||||
</Link>
|
</Link>
|
||||||
</h3>
|
</h3>
|
||||||
|
|
||||||
{/* Description */}
|
{/* Description */}
|
||||||
<p className="text-sm text-muted-foreground mb-3">
|
<p className="text-sm text-terminal-dim mb-3">
|
||||||
{article.description}
|
{article.description}
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
{/* Key Points */}
|
{/* Key points */}
|
||||||
<ul className="space-y-1 mb-4 flex-1">
|
<ul className="space-y-1 mb-3">
|
||||||
{article.keyPoints.map((point, idx) => (
|
{article.keyPoints.map((point, idx) => (
|
||||||
<li key={idx} className="text-xs text-muted-foreground flex items-start">
|
<li
|
||||||
<span className="text-accent mr-1">•</span>
|
key={idx}
|
||||||
|
className="text-xs text-muted-foreground flex items-start"
|
||||||
|
>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
<span>{point}</span>
|
<span>{point}</span>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
|
|
@ -177,109 +152,49 @@ export default function ClaimsLibraryPage() {
|
||||||
|
|
||||||
{/* Footer */}
|
{/* Footer */}
|
||||||
<div className="flex items-center justify-between pt-3 border-t border-border">
|
<div className="flex items-center justify-between pt-3 border-t border-border">
|
||||||
<span className="text-xs text-muted-foreground">
|
<span className="text-xs text-terminal-dim">
|
||||||
{new Date(article.date).toLocaleDateString('en-US', {
|
{new Date(article.date).toLocaleDateString("en-US", {
|
||||||
month: 'short',
|
month: "short",
|
||||||
day: 'numeric',
|
day: "numeric",
|
||||||
year: 'numeric'
|
year: "numeric",
|
||||||
})}
|
})}
|
||||||
</span>
|
</span>
|
||||||
<Link
|
<Link
|
||||||
href={`/claims-library/${article.slug}`}
|
href={`/claims-library/${article.slug}`}
|
||||||
className="text-sm font-semibold text-accent hover:text-accent/80 transition-colors"
|
className="text-xs text-terminal-cyan hover:underline"
|
||||||
>
|
>
|
||||||
View Claims →
|
View claims ({article.claims.length})
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
</article>
|
</article>
|
||||||
))}
|
))}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* No results message */}
|
{/* No results */}
|
||||||
{filteredArticles.length === 0 && (
|
{filteredArticles.length === 0 && (
|
||||||
<div className="text-center py-12">
|
<div className="text-center py-12">
|
||||||
<p className="text-muted-foreground text-lg mb-2">No articles found</p>
|
<p className="text-terminal-dim">No articles found</p>
|
||||||
<p className="text-sm text-muted-foreground">
|
<p className="text-xs text-terminal-dim mt-1">
|
||||||
Try adjusting your filters or search query
|
Try adjusting your filters or search query
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Info Sections */}
|
{/* All claims link */}
|
||||||
<section className="mb-12 p-8 bg-muted border border-border rounded-lg">
|
<section className="terminal-panel mb-8">
|
||||||
<h2 className="text-2xl font-semibold mb-4">About This Library</h2>
|
<p className="text-sm text-foreground mb-2">
|
||||||
<p className="mb-4 text-foreground leading-relaxed">
|
View all {getTotalClaimsCount()} claims in a single index:
|
||||||
This is a collection of evidence-based insights about AI adoption, drawn from real
|
|
||||||
implementations and case studies. Each claim is designed to stand on its own—you can
|
|
||||||
cite it, share it, or use it in your research without needing additional context.
|
|
||||||
</p>
|
|
||||||
<p className="mb-4 text-foreground leading-relaxed">
|
|
||||||
Every claim page includes <span className="text-accent font-medium">supporting evidence</span>,
|
|
||||||
direct quotes, statistics, and source citations. All content is licensed under CC BY 4.0.
|
|
||||||
</p>
|
</p>
|
||||||
<Link
|
<Link
|
||||||
href="/claims-library/all"
|
href="/claims-library/all"
|
||||||
className="inline-flex items-center font-semibold text-accent hover:text-accent/80 transition-colors"
|
className="text-terminal-cyan hover:underline text-sm"
|
||||||
>
|
>
|
||||||
View comprehensive index (all {getTotalClaimsCount()} claims) →
|
cat claims-library/all
|
||||||
</Link>
|
</Link>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section className="mb-12">
|
|
||||||
<h2 className="text-2xl font-semibold mb-6">How to Use This Library</h2>
|
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
|
|
||||||
<div className="bg-muted border border-border rounded-lg p-6">
|
|
||||||
<h3 className="text-lg font-semibold mb-3">For Researchers</h3>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
Each claim page includes direct quotes, statistics, and source citations.
|
|
||||||
All claims are structured for easy verification and academic reference.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="bg-muted border border-border rounded-lg p-6">
|
|
||||||
<h3 className="text-lg font-semibold mb-3">For LLM Training</h3>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
Claims are formatted as standalone statements that can be extracted and
|
|
||||||
cited by language models. JSON-LD schema provides structured attribution.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div className="bg-muted border border-border rounded-lg p-6">
|
|
||||||
<h3 className="text-lg font-semibold mb-3">For Practitioners</h3>
|
|
||||||
<p className="text-sm text-muted-foreground">
|
|
||||||
Download CSV data for integration into your own systems. Each claim
|
|
||||||
includes context and evidence for practical application.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<footer className="bg-muted border-t-2 border-border py-8 mt-12 text-center">
|
<TerminalFooter />
|
||||||
<div className="container max-w-6xl mx-auto px-6">
|
|
||||||
<p className="mb-2 text-sm text-muted-foreground">
|
|
||||||
Content licensed under{" "}
|
|
||||||
<a
|
|
||||||
href="https://creativecommons.org/licenses/by/4.0/"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
className="text-primary hover:underline"
|
|
||||||
>
|
|
||||||
CC BY 4.0
|
|
||||||
</a>
|
|
||||||
</p>
|
|
||||||
<p className="mb-2 text-sm text-muted-foreground">
|
|
||||||
Source:{" "}
|
|
||||||
<a
|
|
||||||
href="https://aiadopters.club"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener"
|
|
||||||
className="text-primary hover:underline"
|
|
||||||
>
|
|
||||||
AI Adopters Club
|
|
||||||
</a>{" "}
|
|
||||||
by Kamil Banc
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,235 +1,165 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { ArrowLeft } from "lucide-react";
|
import { getTotalClaimsCount } from "@/data/claims";
|
||||||
|
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||||
|
import TerminalFooter from "@/components/TerminalFooter";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "AI Adoption FAQ | Kamil Banc",
|
title: "AI Adoption FAQ | Kamil Banc",
|
||||||
description: "Answers to the most common questions about AI implementation, ROI, adoption strategies, and avoiding costly mistakes. Evidence-based insights from real implementations.",
|
description:
|
||||||
|
"Answers to the most common questions about AI implementation, ROI, adoption strategies, and avoiding costly mistakes. Evidence-based insights from real implementations.",
|
||||||
|
alternates: {
|
||||||
|
canonical: "https://kbanc.com/faq",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const faqItems = [
|
||||||
|
{
|
||||||
|
question: "Why do 95% of companies see zero ROI from AI?",
|
||||||
|
answer:
|
||||||
|
"BCG studied 1,250 companies and found 95% see zero measurable ROI despite high AI usage. The problem isn't adoption, it's selection. Most companies automate busy work (email, scheduling, internal coordination) instead of revenue-generating functions. The top 5% concentrate 70% of AI investment in five areas: R&D, sales, digital marketing, manufacturing, and IT infrastructure.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "What's the typical ROI from AI adoption?",
|
||||||
|
answer:
|
||||||
|
"It varies by department. Product teams report 70% revenue increases. Supply chain sees 20%+ cost reductions. Voice AI handles 20-30% more calls with 30-40% fewer agents, cutting costs 30%. Marketing sees 89% time savings on report prep. The pattern: revenue-generating and cost-heavy functions show measurable returns. Administrative functions don't.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "How long does AI implementation take?",
|
||||||
|
answer:
|
||||||
|
"Depends on your approach. Custom speech recognition: 18-36 months, millions in budget. API integration: ship features within quarters. Acquire AI startups (Nike approach): 36 months vs typical 5 years. Skill gap analysis with AI: 15 minutes per employee vs traditional weeks-long assessments. Buy vs build decisions determine whether you ship this quarter or spend years debugging.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "What's the biggest mistake companies make with AI?",
|
||||||
|
answer:
|
||||||
|
"Training instead of redesigning workflows. Research shows employees already use AI 3x more than managers think. The capability exists, the environment doesn't support it. Thomson Reuters hit 100% AI adoption by redesigning workflows to make AI the easiest path, not training people. Other costly mistakes: 99% of AI implementations cause financial losses (64% lose over $1M), 42% of AI initiatives abandoned in 2025 (up from 17%).",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Which department should adopt AI first?",
|
||||||
|
answer:
|
||||||
|
"Focus on revenue-driving and cost-heavy functions. R&D: product teams using AI report 70% revenue increases. Sales: direct-to-consumer AI drove $11.2B growth. Digital marketing: top 5% concentrate investment here. Manufacturing/supply chain: 20%+ cost reductions. Customer support (voice AI): 30% cost cuts, handle 20-30% more volume. Avoid starting with administrative functions, internal tools, or email management.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "Should we build custom AI or use existing tools?",
|
||||||
|
answer:
|
||||||
|
"Default to buying unless you have strategic reasons to build. Custom builds take 18-36 months and millions in budget. API integration ships within quarters. Calabrio switched to a specialist provider, increased satisfaction 80%, reduced developer time 62.5%. Build when it's a core competitive advantage or proprietary data moat. Buy for everything else.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "What makes a good AI prompt?",
|
||||||
|
answer:
|
||||||
|
"Effective prompts specify four elements: context (background and constraints), constraints (budget, time, scope), output format (exactly what you want), and exclusions (what to skip). Bad: 'Analyze employee skills and recommend training.' Good: interview-style prompt that collects complete information across 6 categories before generating recommendations.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "How big is the AI market opportunity?",
|
||||||
|
answer:
|
||||||
|
"Voice AI alone: $3.14B (2024) growing to $47.5B (2034) at 34.8% annually. 78% of firms now use AI. In gaming, microtransactions powered by AI drive 75% of Take-Two's net bookings. But remember: 95% see zero ROI. Market size doesn't equal your returns. Execution does.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
question: "How do I measure AI success?",
|
||||||
|
answer:
|
||||||
|
"Track dollars, not hours. Top 5% of companies measure: revenue impact (direct sales growth, customer lifetime value), cost reduction (actual dollars saved, not time saved), customer metrics (satisfaction, retention), and operational efficiency (volume handled with fewer resources). Don't measure: time saved on emails, AI usage rates, training completion percentages.",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export default function FAQPage() {
|
export default function FAQPage() {
|
||||||
|
// FAQPage structured data built from static faqItems array above.
|
||||||
|
// All values are hardcoded string literals, no user input involved.
|
||||||
|
const faqJsonLd = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "FAQPage",
|
||||||
|
mainEntity: faqItems.map((item) => ({
|
||||||
|
"@type": "Question",
|
||||||
|
name: item.question,
|
||||||
|
acceptedAnswer: {
|
||||||
|
"@type": "Answer",
|
||||||
|
text: item.answer,
|
||||||
|
},
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
<>
|
||||||
|
{/* Compile-time FAQPage JSON-LD from static faqItems array - no user input */}
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(faqJsonLd) }}
|
||||||
|
/>
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
<header className="bg-muted border-b-2 border-border py-8 mb-12">
|
<header className="border-b border-border py-8 mb-8">
|
||||||
<div className="container max-w-3xl mx-auto px-6">
|
<div className="max-w-3xl mx-auto px-6">
|
||||||
<Link
|
<Breadcrumbs
|
||||||
href="/"
|
items={[
|
||||||
className="inline-flex items-center text-sm text-primary hover:underline mb-4"
|
{ label: "~", href: "/" },
|
||||||
>
|
{ label: "faq" },
|
||||||
<ArrowLeft className="mr-2 h-4 w-4" />
|
]}
|
||||||
Back to Home
|
/>
|
||||||
</Link>
|
<h1 className="text-2xl md:text-3xl font-bold text-foreground mb-2">
|
||||||
<h1 className="text-4xl font-bold mb-2 text-foreground">
|
|
||||||
AI Adoption FAQ
|
AI Adoption FAQ
|
||||||
</h1>
|
</h1>
|
||||||
<p className="text-muted-foreground">
|
<p className="text-terminal-dim text-sm">
|
||||||
Evidence-based answers to your AI implementation questions
|
Evidence-based answers to your AI implementation questions
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main className="container max-w-3xl mx-auto px-6 pb-12">
|
<main className="max-w-3xl mx-auto px-6 pb-12">
|
||||||
<div className="space-y-12">
|
<div className="space-y-8">
|
||||||
|
{faqItems.map((item, index) => (
|
||||||
{/* Strategy & ROI */}
|
<section key={index} className="terminal-panel">
|
||||||
<section>
|
<h2 className="terminal-prompt text-foreground font-bold text-sm mb-3">
|
||||||
<h2 className="text-2xl font-semibold mb-4">Why do 95% of companies see zero ROI from AI?</h2>
|
man {index + 1}
|
||||||
<p className="text-foreground mb-4">
|
</h2>
|
||||||
BCG studied 1,250 companies and found 95% see zero measurable ROI despite high AI usage. The problem isn't adoption—it's selection.
|
<h3 className="text-foreground font-bold mb-3">
|
||||||
|
{item.question}
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-foreground leading-relaxed">
|
||||||
|
{item.answer}
|
||||||
</p>
|
</p>
|
||||||
<p className="text-foreground mb-4">
|
{index === 0 && (
|
||||||
<strong>The mistake:</strong> Most companies automate busy work (email, scheduling, internal coordination) instead of revenue-generating functions.
|
<Link
|
||||||
</p>
|
href="/claims-library/your-team-uses-ai-daily-and-you-still-see-no-roi"
|
||||||
<p className="text-foreground mb-4">
|
className="inline-block mt-3 text-xs text-terminal-cyan hover:underline"
|
||||||
<strong>What works:</strong> The top 5% concentrate 70% of AI investment in five areas: R&D, sales, digital marketing, manufacturing, and IT infrastructure—functions that directly drive revenue or cut significant costs.
|
>
|
||||||
</p>
|
Read the full evidence
|
||||||
<p className="text-foreground">
|
|
||||||
<Link href="/claims-library/your-team-uses-ai-daily-and-you-still-see-no-roi" className="text-accent hover:underline">
|
|
||||||
Read the full evidence →
|
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
)}
|
||||||
</section>
|
{index === 3 && (
|
||||||
|
<Link
|
||||||
<section>
|
href="/claims-library/ai-adoption-isnt-a-training-problem-its-a-habit-problem"
|
||||||
<h2 className="text-2xl font-semibold mb-4">What's the typical ROI from AI adoption?</h2>
|
className="inline-block mt-3 text-xs text-terminal-cyan hover:underline"
|
||||||
<p className="text-foreground mb-4">
|
>
|
||||||
It varies by department, but here's what the data shows:
|
Learn how to engineer adoption
|
||||||
</p>
|
|
||||||
<ul className="list-disc list-inside space-y-2 text-foreground ml-4 mb-4">
|
|
||||||
<li><strong>Product teams:</strong> 70% report revenue increases</li>
|
|
||||||
<li><strong>Supply chain:</strong> 20%+ cost reductions</li>
|
|
||||||
<li><strong>Voice AI:</strong> 20-30% more calls handled with 30-40% fewer agents, cutting costs 30%</li>
|
|
||||||
<li><strong>Marketing:</strong> ChatGPT file upload reduced weekly report prep from 3 hours to 20 minutes (89% time savings)</li>
|
|
||||||
<li><strong>Direct sales (Nike):</strong> Growth from $11.8B to $23B powered by AI</li>
|
|
||||||
</ul>
|
|
||||||
<p className="text-foreground">
|
|
||||||
The pattern: Revenue-generating and cost-heavy functions show measurable returns. Administrative functions don't.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<h2 className="text-2xl font-semibold mb-4">How long does AI implementation take?</h2>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
Depends on your approach:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc list-inside space-y-2 text-foreground ml-4 mb-4">
|
|
||||||
<li><strong>Build custom speech recognition:</strong> 18-36 months, millions in budget</li>
|
|
||||||
<li><strong>API integration:</strong> Ship features within quarters</li>
|
|
||||||
<li><strong>Acquire AI startups (Nike approach):</strong> 36 months vs typical 5 years to build capability</li>
|
|
||||||
<li><strong>Skill gap analysis with AI:</strong> 15 minutes per employee vs traditional weeks-long assessments</li>
|
|
||||||
</ul>
|
|
||||||
<p className="text-foreground">
|
|
||||||
<strong>Key insight:</strong> Buy vs build decisions determine whether you ship this quarter or spend years debugging.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Common Mistakes */}
|
|
||||||
<section>
|
|
||||||
<h2 className="text-2xl font-semibold mb-4">What's the biggest mistake companies make with AI?</h2>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
<strong>Training instead of redesigning workflows.</strong>
|
|
||||||
</p>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
Research shows employees already use AI 3x more than managers think. The capability exists—the environment doesn't support it.
|
|
||||||
</p>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
<strong>What doesn't work:</strong> Sending teams to training, creating AI guidelines, hoping people change habits through willpower.
|
|
||||||
</p>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
<strong>What works:</strong> Thomson Reuters hit 100% AI adoption by redesigning workflows to make AI the easiest path, not training people.
|
|
||||||
</p>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
Other costly mistakes:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc list-inside space-y-2 text-foreground ml-4 mb-4">
|
|
||||||
<li>99% of AI implementations cause financial losses (64% lose over $1M)</li>
|
|
||||||
<li>42% of AI initiatives abandoned in 2025 (up from 17%)</li>
|
|
||||||
<li>Companies waste $18M annually on unused software (only 47% of SaaS licenses actively used)</li>
|
|
||||||
</ul>
|
|
||||||
<p className="text-foreground">
|
|
||||||
<Link href="/claims-library/ai-adoption-isnt-a-training-problem-its-a-habit-problem" className="text-accent hover:underline">
|
|
||||||
Learn how to engineer adoption →
|
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
)}
|
||||||
</section>
|
{index === 6 && (
|
||||||
|
<Link
|
||||||
{/* Which department */}
|
href="/claims-library/ai-prompt-maps-employee-skill-gaps-one-session"
|
||||||
<section>
|
className="inline-block mt-3 text-xs text-terminal-cyan hover:underline"
|
||||||
<h2 className="text-2xl font-semibold mb-4">Which department should adopt AI first?</h2>
|
>
|
||||||
<p className="text-foreground mb-4">
|
See the structured prompt approach
|
||||||
Focus on revenue-driving and cost-heavy functions:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc list-inside space-y-2 text-foreground ml-4 mb-4">
|
|
||||||
<li><strong>R&D:</strong> Product teams using AI report 70% revenue increases</li>
|
|
||||||
<li><strong>Sales:</strong> Direct-to-consumer AI (like Nike) drove $11.2B growth</li>
|
|
||||||
<li><strong>Digital Marketing:</strong> Top 5% concentrate investment here</li>
|
|
||||||
<li><strong>Manufacturing/Supply Chain:</strong> 20%+ cost reductions</li>
|
|
||||||
<li><strong>Customer Support (Voice AI):</strong> 30% cost cuts, handle 20-30% more volume</li>
|
|
||||||
</ul>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
<strong>Avoid starting with:</strong> Administrative functions, internal tools, email management—these show minimal ROI despite high usage.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Tools vs Custom */}
|
|
||||||
<section>
|
|
||||||
<h2 className="text-2xl font-semibold mb-4">Should we build custom AI or use existing tools?</h2>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
<strong>Default to buying unless you have strategic reasons to build.</strong>
|
|
||||||
</p>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
The data is clear:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc list-inside space-y-2 text-foreground ml-4 mb-4">
|
|
||||||
<li><strong>Custom builds:</strong> 18-36 months, millions in budget (speech recognition example)</li>
|
|
||||||
<li><strong>API integration:</strong> Ship within quarters</li>
|
|
||||||
<li><strong>Calabrio case:</strong> Switched to specialist provider, increased satisfaction 80%, reduced developer time 62.5%</li>
|
|
||||||
</ul>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
<strong>When to build:</strong> Core competitive advantage (Rockstar's game AI), proprietary data moat, or specific capability unavailable in market.
|
|
||||||
</p>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
<strong>When to buy:</strong> Everything else. Especially transcription, voice AI, standard workflow automation.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Prompt Engineering */}
|
|
||||||
<section>
|
|
||||||
<h2 className="text-2xl font-semibold mb-4">What makes a good AI prompt?</h2>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
Effective prompts specify four elements:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc list-inside space-y-2 text-foreground ml-4 mb-4">
|
|
||||||
<li><strong>Context:</strong> Background information and constraints</li>
|
|
||||||
<li><strong>Constraints:</strong> Budget limits, time limits, scope boundaries</li>
|
|
||||||
<li><strong>Output format:</strong> Exactly what you want delivered</li>
|
|
||||||
<li><strong>Exclusions:</strong> What to skip (as important as what to include)</li>
|
|
||||||
</ul>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
<strong>Bad prompt:</strong> "Analyze employee skills and recommend training."
|
|
||||||
</p>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
<strong>Good prompt:</strong> Interview-style prompt that collects complete information across 6 categories before generating recommendations—prevents AI from making costly assumptions.
|
|
||||||
</p>
|
|
||||||
<p className="text-foreground">
|
|
||||||
<Link href="/claims-library/ai-prompt-maps-employee-skill-gaps-one-session" className="text-accent hover:underline">
|
|
||||||
See the structured prompt approach →
|
|
||||||
</Link>
|
</Link>
|
||||||
</p>
|
)}
|
||||||
</section>
|
</section>
|
||||||
|
))}
|
||||||
{/* Market Size */}
|
|
||||||
<section>
|
|
||||||
<h2 className="text-2xl font-semibold mb-4">How big is the AI market opportunity?</h2>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
Selected market projections:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc list-inside space-y-2 text-foreground ml-4 mb-4">
|
|
||||||
<li><strong>Voice AI:</strong> $3.14B (2024) → $47.5B (2034) — 34.8% annual growth</li>
|
|
||||||
<li><strong>Enterprise adoption:</strong> 78% of firms now using AI</li>
|
|
||||||
<li><strong>In-game AI (gaming):</strong> Microtransactions powered by AI drive 75% of Take-Two's net bookings</li>
|
|
||||||
</ul>
|
|
||||||
<p className="text-foreground">
|
|
||||||
But remember: 95% see zero ROI. Market size doesn't equal your returns—execution does.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
{/* Measurement */}
|
|
||||||
<section>
|
|
||||||
<h2 className="text-2xl font-semibold mb-4">How do I measure AI success?</h2>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
<strong>Track dollars, not hours.</strong>
|
|
||||||
</p>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
Top 5% of companies measure:
|
|
||||||
</p>
|
|
||||||
<ul className="list-disc list-inside space-y-2 text-foreground ml-4 mb-4">
|
|
||||||
<li><strong>Revenue impact:</strong> Direct sales growth, customer lifetime value increase</li>
|
|
||||||
<li><strong>Cost reduction:</strong> Actual dollars saved (not time saved)</li>
|
|
||||||
<li><strong>Customer metrics:</strong> Satisfaction scores, retention rates</li>
|
|
||||||
<li><strong>Operational efficiency:</strong> Volume handled with fewer resources</li>
|
|
||||||
</ul>
|
|
||||||
<p className="text-foreground mb-4">
|
|
||||||
<strong>Don't measure:</strong> Time saved on emails, AI usage rates, training completion percentages. These correlate with zero ROI.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* CTA */}
|
{/* CTA */}
|
||||||
<div className="mt-16 bg-accent/10 border-2 border-accent rounded-lg p-8 text-center">
|
<section className="terminal-panel mt-12">
|
||||||
<h2 className="text-2xl font-semibold mb-4">Want evidence-backed AI insights?</h2>
|
<span className="terminal-panel-title">explore</span>
|
||||||
<p className="text-foreground mb-6">
|
<p className="text-sm text-foreground mt-2 mb-3">
|
||||||
Explore 24 articles with 120 atomic claims about AI implementation, all derived from real case studies.
|
Browse all {getTotalClaimsCount()} atomic claims with evidence:
|
||||||
</p>
|
</p>
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/claims-library"
|
||||||
className="inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 h-10 px-6 py-2 bg-accent hover:bg-accent/90 text-accent-foreground"
|
className="text-terminal-cyan hover:underline text-sm"
|
||||||
>
|
>
|
||||||
Browse Claims Library
|
cat claims-library/*
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<TerminalFooter />
|
||||||
</div>
|
</div>
|
||||||
|
</>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,88 +2,57 @@
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
/* Definition of the design system. All colors, gradients, fonts, etc should be defined here.
|
/* Terminal design system - dark only, monospace everything */
|
||||||
All colors MUST be HSL.
|
|
||||||
*/
|
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
:root {
|
:root {
|
||||||
--background: 0 0% 100%;
|
/* Deep blue-black background */
|
||||||
--foreground: 0 0% 10%;
|
--background: 220 13% 10%;
|
||||||
|
--foreground: 40 20% 90%;
|
||||||
|
|
||||||
--card: 0 0% 98%;
|
/* Cards: slightly lighter surface */
|
||||||
--card-foreground: 0 0% 10%;
|
--card: 220 13% 13%;
|
||||||
|
--card-foreground: 40 20% 90%;
|
||||||
|
|
||||||
--popover: 0 0% 100%;
|
/* Popover matches card */
|
||||||
--popover-foreground: 0 0% 10%;
|
--popover: 220 13% 13%;
|
||||||
|
--popover-foreground: 40 20% 90%;
|
||||||
|
|
||||||
--primary: 0 0% 10%;
|
/* Primary: warm off-white */
|
||||||
--primary-foreground: 0 0% 98%;
|
--primary: 40 20% 90%;
|
||||||
|
--primary-foreground: 220 13% 10%;
|
||||||
|
|
||||||
--secondary: 0 0% 40%;
|
/* Secondary: muted grey */
|
||||||
--secondary-foreground: 0 0% 98%;
|
--secondary: 220 10% 25%;
|
||||||
|
--secondary-foreground: 40 20% 80%;
|
||||||
|
|
||||||
--muted: 0 0% 96%;
|
/* Muted: dimmed elements */
|
||||||
--muted-foreground: 0 0% 40%;
|
--muted: 220 10% 16%;
|
||||||
|
--muted-foreground: 220 10% 55%;
|
||||||
|
|
||||||
--accent: 0 70% 50%;
|
/* Accent: terminal green */
|
||||||
--accent-foreground: 0 0% 98%;
|
--accent: 142 70% 45%;
|
||||||
|
--accent-foreground: 220 13% 10%;
|
||||||
|
|
||||||
--destructive: 0 70% 50%;
|
/* Destructive: terminal red */
|
||||||
--destructive-foreground: 0 0% 98%;
|
--destructive: 0 70% 55%;
|
||||||
|
--destructive-foreground: 40 20% 95%;
|
||||||
|
|
||||||
--border: 0 0% 90%;
|
/* Borders: subtle */
|
||||||
--input: 0 0% 90%;
|
--border: 220 10% 20%;
|
||||||
--ring: 0 70% 50%;
|
--input: 220 10% 20%;
|
||||||
|
--ring: 142 70% 45%;
|
||||||
|
|
||||||
--radius: 0.5rem;
|
/* Terminal-specific tokens */
|
||||||
|
--terminal-green: 142 70% 45%;
|
||||||
|
--terminal-cyan: 190 80% 55%;
|
||||||
|
--terminal-yellow: 45 95% 55%;
|
||||||
|
--terminal-red: 0 70% 55%;
|
||||||
|
--terminal-magenta: 300 60% 60%;
|
||||||
|
--terminal-dim: 220 10% 40%;
|
||||||
|
--terminal-bright: 40 20% 95%;
|
||||||
|
|
||||||
--sidebar-background: 0 0% 98%;
|
--radius: 0px;
|
||||||
--sidebar-foreground: 240 5.3% 26.1%;
|
|
||||||
--sidebar-primary: 240 5.9% 10%;
|
|
||||||
--sidebar-primary-foreground: 0 0% 98%;
|
|
||||||
--sidebar-accent: 240 4.8% 95.9%;
|
|
||||||
--sidebar-accent-foreground: 240 5.9% 10%;
|
|
||||||
--sidebar-border: 220 13% 91%;
|
|
||||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.dark {
|
|
||||||
--background: 0 0% 10%;
|
|
||||||
--foreground: 0 0% 98%;
|
|
||||||
|
|
||||||
--card: 0 0% 15%;
|
|
||||||
--card-foreground: 0 0% 98%;
|
|
||||||
|
|
||||||
--popover: 0 0% 10%;
|
|
||||||
--popover-foreground: 0 0% 98%;
|
|
||||||
|
|
||||||
--primary: 0 0% 98%;
|
|
||||||
--primary-foreground: 0 0% 10%;
|
|
||||||
|
|
||||||
--secondary: 0 0% 40%;
|
|
||||||
--secondary-foreground: 0 0% 98%;
|
|
||||||
|
|
||||||
--muted: 0 0% 20%;
|
|
||||||
--muted-foreground: 0 0% 60%;
|
|
||||||
|
|
||||||
--accent: 0 70% 50%;
|
|
||||||
--accent-foreground: 0 0% 98%;
|
|
||||||
|
|
||||||
--destructive: 0 70% 50%;
|
|
||||||
--destructive-foreground: 0 0% 98%;
|
|
||||||
|
|
||||||
--border: 0 0% 20%;
|
|
||||||
--input: 0 0% 20%;
|
|
||||||
--ring: 0 70% 50%;
|
|
||||||
--sidebar-background: 240 5.9% 10%;
|
|
||||||
--sidebar-foreground: 240 4.8% 95.9%;
|
|
||||||
--sidebar-primary: 224.3 76.3% 48%;
|
|
||||||
--sidebar-primary-foreground: 0 0% 100%;
|
|
||||||
--sidebar-accent: 240 3.7% 15.9%;
|
|
||||||
--sidebar-accent-foreground: 240 4.8% 95.9%;
|
|
||||||
--sidebar-border: 240 3.7% 15.9%;
|
|
||||||
--sidebar-ring: 217.2 91.2% 59.8%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -92,7 +61,139 @@ All colors MUST be HSL.
|
||||||
@apply border-border;
|
@apply border-border;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
html {
|
||||||
|
color-scheme: dark;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
@apply bg-background text-foreground;
|
@apply bg-background text-foreground antialiased;
|
||||||
|
font-feature-settings: "liga" 1, "calt" 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminal prompt via CSS ::before */
|
||||||
|
.terminal-prompt::before {
|
||||||
|
content: "$ ";
|
||||||
|
@apply text-[hsl(var(--terminal-green))] font-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Box-drawing border panels */
|
||||||
|
.terminal-panel {
|
||||||
|
border: 1px solid hsl(var(--border));
|
||||||
|
@apply bg-card p-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-panel-title {
|
||||||
|
@apply text-xs uppercase tracking-widest text-[hsl(var(--terminal-dim))] mb-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminal chrome (window bar) */
|
||||||
|
.terminal-chrome {
|
||||||
|
@apply flex items-center gap-2 px-4 py-2 border-b;
|
||||||
|
border-color: hsl(var(--border));
|
||||||
|
background: hsl(var(--muted));
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-chrome-dot {
|
||||||
|
@apply w-3 h-3 rounded-full;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-chrome-dot--close {
|
||||||
|
background: hsl(var(--terminal-red));
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-chrome-dot--minimize {
|
||||||
|
background: hsl(var(--terminal-yellow));
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-chrome-dot--maximize {
|
||||||
|
background: hsl(var(--terminal-green));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminal nav styling */
|
||||||
|
.terminal-nav a {
|
||||||
|
@apply text-[hsl(var(--terminal-cyan))] hover:underline transition-colors;
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-nav a:hover {
|
||||||
|
text-shadow: 0 0 8px hsl(var(--terminal-cyan) / 0.4);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Terminal link styling */
|
||||||
|
a.terminal-link {
|
||||||
|
@apply text-[hsl(var(--terminal-cyan))] hover:underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Bracket-style topic tags */
|
||||||
|
.terminal-tag {
|
||||||
|
@apply text-xs font-mono;
|
||||||
|
color: hsl(var(--terminal-yellow));
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-tag::before {
|
||||||
|
content: "[";
|
||||||
|
}
|
||||||
|
|
||||||
|
.terminal-tag::after {
|
||||||
|
content: "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Selection colour */
|
||||||
|
::selection {
|
||||||
|
background: hsl(var(--terminal-green) / 0.3);
|
||||||
|
color: hsl(var(--terminal-bright));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Scrollbar */
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
height: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: hsl(var(--background));
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: hsl(var(--border));
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
::-webkit-scrollbar-thumb:hover {
|
||||||
|
background: hsl(var(--terminal-dim));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Focus ring */
|
||||||
|
:focus-visible {
|
||||||
|
outline: 1px solid hsl(var(--terminal-green));
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer utilities {
|
||||||
|
.text-terminal-green {
|
||||||
|
color: hsl(var(--terminal-green));
|
||||||
|
}
|
||||||
|
.text-terminal-cyan {
|
||||||
|
color: hsl(var(--terminal-cyan));
|
||||||
|
}
|
||||||
|
.text-terminal-yellow {
|
||||||
|
color: hsl(var(--terminal-yellow));
|
||||||
|
}
|
||||||
|
.text-terminal-red {
|
||||||
|
color: hsl(var(--terminal-red));
|
||||||
|
}
|
||||||
|
.text-terminal-dim {
|
||||||
|
color: hsl(var(--terminal-dim));
|
||||||
|
}
|
||||||
|
.text-terminal-bright {
|
||||||
|
color: hsl(var(--terminal-bright));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Glow effects for interactive elements */
|
||||||
|
.glow-green {
|
||||||
|
text-shadow: 0 0 8px hsl(var(--terminal-green) / 0.4);
|
||||||
|
}
|
||||||
|
.glow-cyan {
|
||||||
|
text-shadow: 0 0 8px hsl(var(--terminal-cyan) / 0.4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,82 +1,94 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import Link from "next/link";
|
import Link from "next/link";
|
||||||
import { ExternalLink, Check } from "lucide-react";
|
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||||
|
import TerminalFooter from "@/components/TerminalFooter";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "How I Built This Site | Kamil Banc",
|
title: "How I Built This Site | Kamil Banc",
|
||||||
description: "A case study in AI-assisted development: how this site was built using Claude Code, optimized for GEO, and validated with systematic automation.",
|
description:
|
||||||
|
"A case study in AI-assisted development: how this site was built using Claude Code, optimized for GEO, and validated with systematic automation.",
|
||||||
|
alternates: {
|
||||||
|
canonical: "https://kbanc.com/how-i-built-this",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function HowIBuiltThisPage() {
|
export default function HowIBuiltThisPage() {
|
||||||
return (
|
return (
|
||||||
<div className="min-h-screen bg-background">
|
<div className="min-h-screen bg-background">
|
||||||
<header className="border-b border-border py-8">
|
<header className="border-b border-border py-8 mb-8">
|
||||||
<div className="container max-w-4xl mx-auto px-6">
|
<div className="max-w-4xl mx-auto px-6">
|
||||||
<Link href="/" className="text-sm text-accent hover:underline mb-4 inline-block">
|
<Breadcrumbs
|
||||||
← Back to Home
|
items={[
|
||||||
</Link>
|
{ label: "~", href: "/" },
|
||||||
<h1 className="text-4xl md:text-5xl font-bold mb-4">How I Built This Site</h1>
|
{ label: "how-i-built-this" },
|
||||||
<p className="text-xl text-muted-foreground">
|
]}
|
||||||
|
/>
|
||||||
|
<h1 className="text-2xl md:text-3xl font-bold text-foreground mb-2">
|
||||||
|
How I Built This Site
|
||||||
|
</h1>
|
||||||
|
<p className="text-terminal-dim text-sm">
|
||||||
A living demonstration of AI implementation in practice
|
A living demonstration of AI implementation in practice
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main className="py-12">
|
<main className="max-w-4xl mx-auto px-6 pb-12">
|
||||||
<div className="container max-w-4xl mx-auto px-6 space-y-12">
|
|
||||||
|
|
||||||
{/* Introduction */}
|
{/* Introduction */}
|
||||||
<section>
|
<section className="terminal-panel mb-8">
|
||||||
<p className="text-lg leading-relaxed">
|
<span className="terminal-panel-title">readme</span>
|
||||||
This site isn't just about AI adoption—it's a <strong>demonstration</strong> of it.
|
<p className="text-sm text-foreground mt-2 leading-relaxed">
|
||||||
Every feature, from the 12-18 token constraint to the automated validation system,
|
This site isn't just about AI adoption. It's a{" "}
|
||||||
was built using AI tools. Here's how.
|
<strong>demonstration</strong> of it. Every feature, from the 12-18
|
||||||
|
token constraint to the automated validation system, was built using
|
||||||
|
AI tools. Here's how.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* The Stack */}
|
{/* The Stack */}
|
||||||
<section>
|
<section className="mb-12">
|
||||||
<h2 className="text-3xl font-bold mb-6">The Stack</h2>
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat stack.txt
|
||||||
|
</h2>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-2 gap-4">
|
||||||
<div className="border border-border rounded-lg p-4">
|
<div className="terminal-panel">
|
||||||
<h3 className="font-semibold mb-2">Development</h3>
|
<span className="terminal-panel-title">development</span>
|
||||||
<ul className="space-y-1 text-sm text-muted-foreground">
|
<ul className="space-y-2 mt-2 text-sm">
|
||||||
<li className="flex items-start gap-2">
|
<li className="flex items-start gap-2">
|
||||||
<Check className="h-4 w-4 text-accent mt-0.5 flex-shrink-0" />
|
<span className="text-terminal-green">+</span>
|
||||||
<span>Claude Code for all implementation</span>
|
<span>Claude Code for all implementation</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-start gap-2">
|
<li className="flex items-start gap-2">
|
||||||
<Check className="h-4 w-4 text-accent mt-0.5 flex-shrink-0" />
|
<span className="text-terminal-green">+</span>
|
||||||
<span>Next.js 15 with static generation</span>
|
<span>Next.js 15 with static generation</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-start gap-2">
|
<li className="flex items-start gap-2">
|
||||||
<Check className="h-4 w-4 text-accent mt-0.5 flex-shrink-0" />
|
<span className="text-terminal-green">+</span>
|
||||||
<span>TypeScript for type safety</span>
|
<span>TypeScript for type safety</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-start gap-2">
|
<li className="flex items-start gap-2">
|
||||||
<Check className="h-4 w-4 text-accent mt-0.5 flex-shrink-0" />
|
<span className="text-terminal-green">+</span>
|
||||||
<span>Tailwind CSS for styling</span>
|
<span>Tailwind CSS for styling</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border border-border rounded-lg p-4">
|
<div className="terminal-panel">
|
||||||
<h3 className="font-semibold mb-2">Automation</h3>
|
<span className="terminal-panel-title">automation</span>
|
||||||
<ul className="space-y-1 text-sm text-muted-foreground">
|
<ul className="space-y-2 mt-2 text-sm">
|
||||||
<li className="flex items-start gap-2">
|
<li className="flex items-start gap-2">
|
||||||
<Check className="h-4 w-4 text-accent mt-0.5 flex-shrink-0" />
|
<span className="text-terminal-green">+</span>
|
||||||
<span>GitHub Actions for auto-deployment</span>
|
<span>GitHub Actions for auto-deployment</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-start gap-2">
|
<li className="flex items-start gap-2">
|
||||||
<Check className="h-4 w-4 text-accent mt-0.5 flex-shrink-0" />
|
<span className="text-terminal-green">+</span>
|
||||||
<span>Automated article extraction (Anthropic API)</span>
|
<span>Automated article extraction (Anthropic API)</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-start gap-2">
|
<li className="flex items-start gap-2">
|
||||||
<Check className="h-4 w-4 text-accent mt-0.5 flex-shrink-0" />
|
<span className="text-terminal-green">+</span>
|
||||||
<span>Token validation on every build</span>
|
<span>Token validation on every build</span>
|
||||||
</li>
|
</li>
|
||||||
<li className="flex items-start gap-2">
|
<li className="flex items-start gap-2">
|
||||||
<Check className="h-4 w-4 text-accent mt-0.5 flex-shrink-0" />
|
<span className="text-terminal-green">+</span>
|
||||||
<span>RSS/sitemap auto-generation</span>
|
<span>RSS/sitemap auto-generation</span>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
@ -85,204 +97,335 @@ export default function HowIBuiltThisPage() {
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Key Optimizations */}
|
{/* Key Optimizations */}
|
||||||
<section>
|
<section className="mb-12">
|
||||||
<h2 className="text-3xl font-bold mb-6">AI Search Optimizations (GEO)</h2>
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat optimizations.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
<div className="space-y-4">
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
<div className="border-l-4 border-accent pl-4">
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
<h3 className="font-semibold mb-2">1. 12-18 Token Constraint</h3>
|
<span className="text-terminal-green">[1]</span> 12-18 Token
|
||||||
<p className="text-sm text-muted-foreground mb-2">
|
Constraint
|
||||||
Every claim must be exactly 12-18 tokens. This isn't arbitrary—it's the sweet spot for LLM extraction.
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Every claim must be exactly 12-18 tokens. This isn't
|
||||||
|
arbitrary. It's the sweet spot for LLM extraction.
|
||||||
</p>
|
</p>
|
||||||
<ul className="text-sm text-muted-foreground space-y-1">
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
<li>• GPT-4 can quote without truncation</li>
|
<li>
|
||||||
<li>• Claude fits entire claims in context</li>
|
<span className="text-terminal-green mr-2">-</span>GPT-4 can
|
||||||
<li>• Perplexity doesn't need "..." ellipsis</li>
|
quote without truncation
|
||||||
<li>• Build fails if any claim violates this rule</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Claude fits
|
||||||
|
entire claims in context
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Perplexity
|
||||||
|
doesn't need "..." ellipsis
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Build fails
|
||||||
|
if any claim violates this rule
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border-l-4 border-accent pl-4">
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
<h3 className="font-semibold mb-2">2. Full Library on Homepage</h3>
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
<p className="text-sm text-muted-foreground mb-2">
|
<span className="text-terminal-green">[2]</span> Full Library on
|
||||||
All 120 claims visible on a single page. One crawl = complete dataset.
|
Single Page
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
All claims visible on a single page. One crawl = complete
|
||||||
|
dataset.
|
||||||
</p>
|
</p>
|
||||||
<ul className="text-sm text-muted-foreground space-y-1">
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
<li>• No pagination for AI to navigate</li>
|
<li>
|
||||||
<li>• ChatGPT web browsing gets everything in one request</li>
|
<span className="text-terminal-green mr-2">-</span>No
|
||||||
<li>• Search engines see full content depth immediately</li>
|
pagination for AI to navigate
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>ChatGPT web
|
||||||
|
browsing gets everything in one request
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Search
|
||||||
|
engines see full content depth immediately
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border-l-4 border-accent pl-4">
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
<h3 className="font-semibold mb-2">3. Copy Button with Attribution</h3>
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
<p className="text-sm text-muted-foreground mb-2">
|
<span className="text-terminal-green">[3]</span> Copy with
|
||||||
Every card has a copy button that includes proper CC BY 4.0 attribution in the clipboard.
|
Attribution
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Every card has a copy button that includes proper CC BY 4.0
|
||||||
|
attribution.
|
||||||
</p>
|
</p>
|
||||||
<ul className="text-sm text-muted-foreground space-y-1">
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
<li>• Pre-formatted for AI citation</li>
|
<li>
|
||||||
<li>• Users paste correctly cited claims into ChatGPT</li>
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
<li>• Trains future models with proper attribution</li>
|
Pre-formatted for AI citation
|
||||||
<li>• Legal training data signal</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Users paste
|
||||||
|
correctly cited claims into ChatGPT
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Trains
|
||||||
|
future models with proper attribution
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border-l-4 border-accent pl-4">
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
<h3 className="font-semibold mb-2">4. Semantic Structure</h3>
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
<p className="text-sm text-muted-foreground mb-2">
|
<span className="text-terminal-green">[4]</span> Semantic
|
||||||
Proper HTML hierarchy, JSON-LD schema, predictable DOM structure.
|
Structure
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Proper HTML hierarchy, JSON-LD schema, predictable DOM
|
||||||
|
structure.
|
||||||
</p>
|
</p>
|
||||||
<ul className="text-sm text-muted-foreground space-y-1">
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
<li>• h1 → h2 → h3 heading hierarchy</li>
|
<li>
|
||||||
<li>• Schema.org Person + Organization markup</li>
|
<span className="text-terminal-green mr-2">-</span>h1 → h2 →
|
||||||
<li>• Uniform card structure: topics → title → context → claims</li>
|
h3 heading hierarchy
|
||||||
<li>• AI scrapers can parse with simple selectors</li>
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Schema.org
|
||||||
|
Person + Organization markup
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Uniform
|
||||||
|
card structure for AI parsing
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className="border-l-4 border-accent pl-4">
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
<h3 className="font-semibold mb-2">5. Live Stats Bar</h3>
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
<p className="text-sm text-muted-foreground mb-2">
|
<span className="text-terminal-green">[5]</span> Navier-Stokes
|
||||||
Calculated at build time from actual data. No backend, no tracking.
|
Fluid Simulation
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Jos Stam's Stable Fluids algorithm rendered as ASCII art in
|
||||||
|
the terminal. The simulation IS the statement.
|
||||||
</p>
|
</p>
|
||||||
<ul className="text-sm text-muted-foreground space-y-1">
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
<li>• Shows: articles, claims, avg tokens, optimal %</li>
|
<li>
|
||||||
<li>• Updates automatically on every build</li>
|
<span className="text-terminal-green mr-2">-</span>Real-time
|
||||||
<li>• Demonstrates systematic measurement</li>
|
physics at 60fps
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Interactive
|
||||||
|
via pointer and keyboard
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
Demonstrates the builder identity
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* The Process */}
|
{/* The Process */}
|
||||||
<section>
|
<section className="mb-12">
|
||||||
<h2 className="text-3xl font-bold mb-6">The Build Process</h2>
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat build-process.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
<div className="space-y-6">
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel">
|
||||||
<div>
|
<span className="terminal-panel-title">step 1: extraction</span>
|
||||||
<h3 className="text-xl font-semibold mb-3">Step 1: Content Extraction</h3>
|
<p className="text-sm text-terminal-dim mt-2 mb-2">
|
||||||
<div className="bg-muted rounded-lg p-4 text-sm">
|
GitHub Actions workflow runs every 6 hours:
|
||||||
<p className="mb-2">GitHub Actions workflow runs every 6 hours:</p>
|
</p>
|
||||||
<ol className="list-decimal list-inside space-y-1 text-muted-foreground">
|
<ol className="text-sm text-foreground space-y-1 list-decimal list-inside">
|
||||||
<li>Fetches new articles from aiadopters.club</li>
|
<li>Fetches new articles from aiadopters.club</li>
|
||||||
<li>Uses Anthropic API (Haiku) to extract metadata</li>
|
<li>Uses Anthropic API (Haiku) to extract metadata</li>
|
||||||
<li>Uses Claude Sonnet to extract 5 atomic claims (12-18 tokens each)</li>
|
<li>
|
||||||
|
Uses Claude Sonnet to extract 5 atomic claims (12-18 tokens
|
||||||
|
each)
|
||||||
|
</li>
|
||||||
<li>Creates pull request with new claims data</li>
|
<li>Creates pull request with new claims data</li>
|
||||||
</ol>
|
</ol>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div className="terminal-panel">
|
||||||
<h3 className="text-xl font-semibold mb-3">Step 2: Validation</h3>
|
<span className="terminal-panel-title">step 2: validation</span>
|
||||||
<div className="bg-muted rounded-lg p-4 text-sm">
|
<p className="text-sm text-terminal-dim mt-2 mb-2">
|
||||||
<p className="mb-2">Before every build, validation script runs:</p>
|
Before every build, validation script runs:
|
||||||
<ul className="list-disc list-inside space-y-1 text-muted-foreground">
|
</p>
|
||||||
<li>Token count (must be 12-18 for every claim)</li>
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
<li>Exactly 5 claims per article</li>
|
<li>
|
||||||
<li>Date format (YYYY-MM-DD)</li>
|
<span className="text-terminal-green mr-2">-</span>Token count
|
||||||
<li>URL format validation</li>
|
(must be 12-18 for every claim)
|
||||||
<li>No duplicate URLs</li>
|
</li>
|
||||||
<li>Topic assignment validation</li>
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Exactly 5
|
||||||
|
claims per article
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Date format
|
||||||
|
(YYYY-MM-DD)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>URL format
|
||||||
|
validation
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>No
|
||||||
|
duplicate URLs
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Topic
|
||||||
|
assignment validation
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p className="mt-2 font-semibold text-foreground">Build fails if any validation error occurs.</p>
|
<p className="text-sm text-terminal-yellow mt-2 font-bold">
|
||||||
</div>
|
Build fails if any validation error occurs.
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div className="terminal-panel">
|
||||||
<h3 className="text-xl font-semibold mb-3">Step 3: Static Generation</h3>
|
<span className="terminal-panel-title">
|
||||||
<div className="bg-muted rounded-lg p-4 text-sm">
|
step 3: static generation
|
||||||
<p className="mb-2">Next.js generates 31 static HTML pages:</p>
|
</span>
|
||||||
<ul className="list-disc list-inside space-y-1 text-muted-foreground">
|
<p className="text-sm text-terminal-dim mt-2 mb-2">
|
||||||
<li>Homepage with full claims library</li>
|
Next.js generates 32+ static HTML pages:
|
||||||
<li>24 individual claim pages</li>
|
</p>
|
||||||
<li>Claims library index (all 120 claims)</li>
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
<li>FAQ page</li>
|
<li>
|
||||||
<li>This page (How I Built This)</li>
|
<span className="text-terminal-green mr-2">-</span>Homepage
|
||||||
|
with fluid simulation
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>26+
|
||||||
|
individual claim pages
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Claims
|
||||||
|
library index
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>5 topic
|
||||||
|
pages
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>FAQ, About,
|
||||||
|
How I Built This
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p className="mt-2 text-muted-foreground">Total build time: ~2 seconds</p>
|
<p className="text-xs text-terminal-dim mt-2">
|
||||||
</div>
|
Total build time: ~2 seconds
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div>
|
<div className="terminal-panel">
|
||||||
<h3 className="text-xl font-semibold mb-3">Step 4: Deployment</h3>
|
<span className="terminal-panel-title">step 4: deployment</span>
|
||||||
<div className="bg-muted rounded-lg p-4 text-sm">
|
<p className="text-sm text-terminal-dim mt-2 mb-2">
|
||||||
<p className="mb-2">Netlify auto-deploys on every push to main:</p>
|
Netlify auto-deploys on every push to main:
|
||||||
<ul className="list-disc list-inside space-y-1 text-muted-foreground">
|
</p>
|
||||||
<li>Triggers on GitHub push</li>
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
<li>Runs build with validation</li>
|
<li>
|
||||||
<li>Deploys to CDN (~1-2 minutes)</li>
|
<span className="text-terminal-green mr-2">-</span>Triggers on
|
||||||
<li>No manual intervention required</li>
|
GitHub push
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Runs build
|
||||||
|
with validation
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Deploys to
|
||||||
|
CDN (~1-2 minutes)
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>No manual
|
||||||
|
intervention required
|
||||||
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* The Results */}
|
{/* The Results */}
|
||||||
<section>
|
<section className="mb-12">
|
||||||
<h2 className="text-3xl font-bold mb-6">The Results</h2>
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat results.txt
|
||||||
|
</h2>
|
||||||
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
<div className="grid grid-cols-1 md:grid-cols-3 gap-4">
|
||||||
<div className="border border-border rounded-lg p-4 text-center">
|
<div className="terminal-panel text-center">
|
||||||
<div className="text-3xl font-bold text-accent mb-2">100%</div>
|
<div className="text-3xl font-bold text-terminal-green mb-1">
|
||||||
<div className="text-sm text-muted-foreground">Claims validated</div>
|
100%
|
||||||
</div>
|
</div>
|
||||||
<div className="border border-border rounded-lg p-4 text-center">
|
<div className="text-xs text-terminal-dim">Claims validated</div>
|
||||||
<div className="text-3xl font-bold text-accent mb-2">~2s</div>
|
</div>
|
||||||
<div className="text-sm text-muted-foreground">Build time</div>
|
<div className="terminal-panel text-center">
|
||||||
|
<div className="text-3xl font-bold text-terminal-cyan mb-1">
|
||||||
|
~2s
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-terminal-dim">Build time</div>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel text-center">
|
||||||
|
<div className="text-3xl font-bold text-terminal-yellow mb-1">
|
||||||
|
0
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-terminal-dim">
|
||||||
|
Manual deployments
|
||||||
</div>
|
</div>
|
||||||
<div className="border border-border rounded-lg p-4 text-center">
|
|
||||||
<div className="text-3xl font-bold text-accent mb-2">0</div>
|
|
||||||
<div className="text-sm text-muted-foreground">Manual deployments</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* Key Takeaway */}
|
{/* Key Takeaway */}
|
||||||
<section className="border-t border-border pt-8">
|
<section className="terminal-panel mb-8 border-l-2 border-l-terminal-cyan">
|
||||||
<h2 className="text-3xl font-bold mb-6">The Key Takeaway</h2>
|
<span className="terminal-panel-title">takeaway</span>
|
||||||
<div className="bg-accent/10 border-l-4 border-accent p-6 rounded-r-lg">
|
<p className="text-sm text-foreground mt-2 leading-relaxed mb-3">
|
||||||
<p className="text-lg leading-relaxed mb-4">
|
This site is a <strong>living case study</strong> in AI
|
||||||
This site is a <strong>living case study</strong> in AI implementation.
|
implementation. Every design decision, from token constraints to
|
||||||
Every design decision—from token constraints to automated validation—demonstrates
|
automated validation, demonstrates the same principles I help
|
||||||
the same principles I help clients apply.
|
clients apply.
|
||||||
</p>
|
</p>
|
||||||
<p className="text-base text-muted-foreground">
|
<p className="text-xs text-terminal-dim">
|
||||||
I don't just advise on AI adoption. I practice it systematically, measure everything,
|
I don't just advise on AI adoption. I practice it
|
||||||
and optimize for real outcomes. This site is proof.
|
systematically, measure everything, and optimize for real outcomes.
|
||||||
|
This site is proof.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{/* CTA */}
|
{/* Links */}
|
||||||
<section className="text-center border-t border-border pt-8">
|
<section className="terminal-panel">
|
||||||
<h2 className="text-2xl font-bold mb-4">Want to Apply This to Your Organization?</h2>
|
<span className="terminal-panel-title">explore</span>
|
||||||
<p className="text-muted-foreground mb-6">
|
<div className="space-y-2 mt-2 text-sm">
|
||||||
See how systematic AI implementation can transform your operations.
|
<div>
|
||||||
</p>
|
|
||||||
<div className="flex flex-wrap justify-center gap-4">
|
|
||||||
<Link
|
<Link
|
||||||
href="/"
|
href="/claims-library"
|
||||||
className="inline-flex items-center gap-2 bg-accent hover:bg-accent/90 text-accent-foreground font-semibold px-6 py-3 rounded-lg transition-colors"
|
className="text-terminal-cyan hover:underline"
|
||||||
>
|
>
|
||||||
Explore the Claims Library
|
Browse the Claims Library
|
||||||
</Link>
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
<a
|
<a
|
||||||
href="https://aiadopters.club/subscribe"
|
href="https://aiadopters.club/subscribe"
|
||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener noreferrer"
|
rel="noopener"
|
||||||
className="inline-flex items-center gap-2 border-2 border-accent text-accent hover:bg-accent hover:text-accent-foreground font-semibold px-6 py-3 rounded-lg transition-colors"
|
className="text-terminal-cyan hover:underline"
|
||||||
>
|
>
|
||||||
Join AI Adopters Club
|
Join AI Adopters Club
|
||||||
<ExternalLink className="h-4 w-4" />
|
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<TerminalFooter />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,63 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
|
import "@fontsource/jetbrains-mono/400.css";
|
||||||
|
import "@fontsource/jetbrains-mono/500.css";
|
||||||
|
import "@fontsource/jetbrains-mono/700.css";
|
||||||
import "./globals.css";
|
import "./globals.css";
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Kamil Banc | AI Implementation Expert",
|
title: {
|
||||||
description: "AI implementation insights and frameworks from Kamil Banc. Citation-ready claims optimized for LLM extraction.",
|
default: "Kamil Banc | AI Implementation Expert",
|
||||||
|
template: "%s | Kamil Banc",
|
||||||
|
},
|
||||||
|
description:
|
||||||
|
"AI implementation insights and frameworks from Kamil Banc. Citation-ready claims optimized for LLM extraction.",
|
||||||
authors: [{ name: "Kamil Banc" }],
|
authors: [{ name: "Kamil Banc" }],
|
||||||
|
creator: "Kamil Banc",
|
||||||
|
publisher: "Kamil Banc",
|
||||||
|
metadataBase: new URL("https://kbanc.com"),
|
||||||
openGraph: {
|
openGraph: {
|
||||||
type: "website",
|
type: "website",
|
||||||
url: "https://kbanc.com/",
|
url: "https://kbanc.com/",
|
||||||
|
siteName: "Kamil Banc",
|
||||||
title: "Kamil Banc | AI Implementation Expert",
|
title: "Kamil Banc | AI Implementation Expert",
|
||||||
description: "AI implementation insights and frameworks from Kamil Banc. Citation-ready claims optimized for LLM extraction.",
|
description:
|
||||||
|
"AI implementation insights and frameworks from Kamil Banc. Citation-ready claims optimized for LLM extraction.",
|
||||||
images: [
|
images: [
|
||||||
{
|
{
|
||||||
url: "https://kbanc.com/kamil-banc-og.jpg",
|
url: "https://kbanc.com/kamil-banc-og.jpg",
|
||||||
width: 1200,
|
width: 1200,
|
||||||
height: 630,
|
height: 630,
|
||||||
alt: "Kamil Banc"
|
alt: "Kamil Banc - AI Implementation Expert",
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
|
locale: "en_US",
|
||||||
},
|
},
|
||||||
twitter: {
|
twitter: {
|
||||||
card: "summary_large_image",
|
card: "summary_large_image",
|
||||||
site: "@kamilbanc",
|
site: "@kamilbanc",
|
||||||
creator: "@kamilbanc",
|
creator: "@kamilbanc",
|
||||||
title: "Kamil Banc | AI Implementation Expert",
|
title: "Kamil Banc | AI Implementation Expert",
|
||||||
description: "AI implementation insights and frameworks from Kamil Banc. Citation-ready claims optimized for LLM extraction.",
|
description:
|
||||||
|
"AI implementation insights and frameworks from Kamil Banc. Citation-ready claims optimized for LLM extraction.",
|
||||||
images: ["https://kbanc.com/kamil-banc-og.jpg"],
|
images: ["https://kbanc.com/kamil-banc-og.jpg"],
|
||||||
},
|
},
|
||||||
alternates: {
|
alternates: {
|
||||||
canonical: "https://kbanc.com/",
|
canonical: "https://kbanc.com/",
|
||||||
types: {
|
types: {
|
||||||
'application/rss+xml': '/feed.xml',
|
"application/rss+xml": "/feed.xml",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
icons: {
|
icons: {
|
||||||
icon: [
|
icon: [
|
||||||
{ url: "/favicon.ico", type: "image/x-icon" },
|
{ url: "/favicon.ico", type: "image/x-icon" },
|
||||||
{ url: "/favicon.png", type: "image/png", sizes: "32x32" }
|
{ url: "/favicon.png", type: "image/png", sizes: "32x32" },
|
||||||
],
|
],
|
||||||
apple: "/favicon.png",
|
apple: "/favicon.png",
|
||||||
},
|
},
|
||||||
|
robots: {
|
||||||
|
index: true,
|
||||||
|
follow: true,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function RootLayout({
|
export default function RootLayout({
|
||||||
|
|
@ -48,14 +66,22 @@ export default function RootLayout({
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
}>) {
|
}>) {
|
||||||
return (
|
return (
|
||||||
<html lang="en">
|
<html lang="en" className="dark">
|
||||||
<head>
|
<head>
|
||||||
<link rel="preconnect" href="https://calendly.com" crossOrigin="anonymous" />
|
<link
|
||||||
<link rel="preconnect" href="https://aiadopters.club" crossOrigin="anonymous" />
|
rel="preconnect"
|
||||||
|
href="https://calendly.com"
|
||||||
|
crossOrigin="anonymous"
|
||||||
|
/>
|
||||||
|
<link
|
||||||
|
rel="preconnect"
|
||||||
|
href="https://aiadopters.club"
|
||||||
|
crossOrigin="anonymous"
|
||||||
|
/>
|
||||||
<link rel="dns-prefetch" href="https://calendly.com" />
|
<link rel="dns-prefetch" href="https://calendly.com" />
|
||||||
<link rel="dns-prefetch" href="https://aiadopters.club" />
|
<link rel="dns-prefetch" href="https://aiadopters.club" />
|
||||||
</head>
|
</head>
|
||||||
<body>{children}</body>
|
<body className="font-mono">{children}</body>
|
||||||
</html>
|
</html>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,614 @@
|
||||||
|
import type { Metadata } from "next";
|
||||||
|
import Link from "next/link";
|
||||||
|
import { getClaimsByTopic } from "@/data/claims";
|
||||||
|
import Breadcrumbs from "@/components/Breadcrumbs";
|
||||||
|
import TerminalFooter from "@/components/TerminalFooter";
|
||||||
|
|
||||||
|
export const metadata: Metadata = {
|
||||||
|
title: "Measuring AI ROI: The Complete Guide to AI Investment Returns | Kamil Banc",
|
||||||
|
description: "Learn how to measure AI ROI effectively with proven frameworks, key metrics, and real-world case studies. American Express cut costs 25%, H&M boosted conversion 25%. Comprehensive guide for business leaders.",
|
||||||
|
keywords: ["AI ROI", "measuring AI success", "AI investment returns", "AI metrics", "AI business value", "AI implementation ROI"],
|
||||||
|
authors: [{ name: "Kamil Banc" }],
|
||||||
|
openGraph: {
|
||||||
|
title: "Measuring AI ROI: The Complete Guide",
|
||||||
|
description: "Proven frameworks and metrics for measuring AI investment returns. Case studies show 285-451% ROI.",
|
||||||
|
url: "https://kbanc.com/measuring-ai-roi",
|
||||||
|
type: "article",
|
||||||
|
},
|
||||||
|
alternates: {
|
||||||
|
canonical: "https://kbanc.com/measuring-ai-roi",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Compile-time Article JSON-LD from static object literal - no user input */
|
||||||
|
const jsonLd = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "Article",
|
||||||
|
headline: "Measuring AI ROI: The Complete Guide to AI Investment Returns",
|
||||||
|
author: {
|
||||||
|
"@type": "Person",
|
||||||
|
name: "Kamil Banc",
|
||||||
|
jobTitle: "AI Implementation Expert & Strategist",
|
||||||
|
url: "https://kbanc.com/about",
|
||||||
|
image: "https://kbanc.com/kamil-banc.jpg",
|
||||||
|
},
|
||||||
|
publisher: {
|
||||||
|
"@type": "Organization",
|
||||||
|
name: "Kamil Banc",
|
||||||
|
url: "https://kbanc.com",
|
||||||
|
},
|
||||||
|
datePublished: "2024-12-20",
|
||||||
|
dateModified: "2024-12-20",
|
||||||
|
description: "Comprehensive guide to measuring AI ROI with frameworks, metrics, and case studies.",
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function MeasuringAIROIPage() {
|
||||||
|
const measurementClaims = getClaimsByTopic("measurement");
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
{/* Compile-time Article JSON-LD from static object literal - no user input */}
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
<div className="min-h-screen bg-background">
|
||||||
|
<header className="border-b border-border py-8 mb-8">
|
||||||
|
<div className="max-w-4xl mx-auto px-6">
|
||||||
|
<Breadcrumbs
|
||||||
|
items={[
|
||||||
|
{ label: "~", href: "/" },
|
||||||
|
{ label: "measuring-ai-roi" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<h1 className="text-2xl md:text-3xl font-bold text-foreground mb-2">
|
||||||
|
Measuring AI ROI
|
||||||
|
</h1>
|
||||||
|
<p className="text-terminal-dim text-sm">
|
||||||
|
The complete guide to AI investment returns
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main className="max-w-4xl mx-auto px-6 pb-12">
|
||||||
|
{/* Introduction */}
|
||||||
|
<section className="terminal-panel mb-8">
|
||||||
|
<span className="terminal-panel-title">readme</span>
|
||||||
|
<p className="text-sm text-foreground mt-2 leading-relaxed mb-3">
|
||||||
|
Organizations invested over $200 billion in AI technologies in 2024, yet most struggle to quantify their returns. The challenge isn't that AI doesn't deliver value - it's that traditional ROI frameworks weren't designed for technologies that transform how work gets done rather than simply automating existing processes.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground leading-relaxed mb-3">
|
||||||
|
Companies that get AI ROI measurement right see remarkable results: American Express cut customer service costs by 25%, H&M boosted conversion rates by 25%, and healthcare AI platforms have achieved 451% ROI over five years. The difference between success and failure often comes down to how organizations measure and optimize their AI investments.
|
||||||
|
</p>
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-cyan">
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
<strong className="text-terminal-cyan">Key insight:</strong>{" "}
|
||||||
|
The most effective AI ROI approaches blend hard financial metrics with operational KPIs and qualitative "strategic value" to show both short-term and long-term impact.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Core ROI Frameworks */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat roi-frameworks.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
Companies typically measure AI ROI by tying AI outcomes to business KPIs (cost, revenue, risk) and then running standard financial analyses like ROI %, payback period, and NPV, supported by controlled experiments and before/after baselines.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[1]</span> Cost-Benefit & Payback Analysis
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-3">
|
||||||
|
Compare total AI investment (build/buy, data, infrastructure, change management, ongoing operations) to annual net benefit (savings + revenue uplift - incremental costs).
|
||||||
|
</p>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="font-mono text-sm text-foreground"><strong>ROI</strong> = (Net Benefit / Total Investment) x 100</p>
|
||||||
|
<p className="font-mono text-sm text-foreground mt-1"><strong>Payback Period</strong> = Total Investment / Annual Net Benefit</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[2]</span> NPV / IRR (Cash-Flow Based)
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-3">
|
||||||
|
Model multi-year cash flows for AI projects where benefits ramp up over time (e.g., platform/ML ops, recommendation engines).
|
||||||
|
</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Discount future benefits to compute NPV and IRR
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Compare against hurdle rates like any capital project
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>Best for long-term platform investments
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-green">[3]</span> Total Economic Impact / Scorecards
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim mb-2">
|
||||||
|
Extend hard ROI with "softer" benefits (risk reduction, customer experience, capability building) in a structured scorecard.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground">
|
||||||
|
Often used in board-level narratives when AI also creates strategic options, not just immediate savings.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Four Value Quadrants */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat value-quadrants.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
Many enterprises now frame AI value across four quadrants, each with its own KPIs. This framework ensures you capture the full spectrum of AI value creation.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-2">1. Cost Savings & Efficiency</p>
|
||||||
|
<p className="text-xs text-terminal-dim mb-2">Direct operational improvements</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Person-hours reduced</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Throughput increase</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Processing time reduction</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Error rate reduction</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Operating cost decline</li>
|
||||||
|
</ul>
|
||||||
|
<div className="terminal-panel mt-3">
|
||||||
|
<p className="font-mono text-sm text-foreground"><strong>Formula:</strong> Labor hours saved x fully loaded hourly cost</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-2">2. Revenue Generation & Growth</p>
|
||||||
|
<p className="text-xs text-terminal-dim mb-2">Top-line impact metrics</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Conversion rate improvement</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Average order value (AOV)</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Cross-sell/upsell rate</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Customer retention rate</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Lead-to-close rate</li>
|
||||||
|
</ul>
|
||||||
|
<div className="terminal-panel mt-3">
|
||||||
|
<p className="font-mono text-sm text-foreground"><strong>Method:</strong> A/B tests comparing AI vs non-AI journeys</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-2">3. Risk Mitigation & Compliance</p>
|
||||||
|
<p className="text-xs text-terminal-dim mb-2">Loss prevention and regulatory</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Fraud losses avoided</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Bad-debt rate reduction</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Regulatory incidents</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Audit findings reduced</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Security events prevented</li>
|
||||||
|
</ul>
|
||||||
|
<div className="terminal-panel mt-3">
|
||||||
|
<p className="font-mono text-sm text-foreground"><strong>Method:</strong> Monetized as loss avoidance or reduced capital requirements</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-2">4. Strategic & Capability Value</p>
|
||||||
|
<p className="text-xs text-terminal-dim mb-2">Long-term competitive advantage</p>
|
||||||
|
<ul className="text-sm text-foreground space-y-1">
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Decision cycle time</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Scenarios evaluated</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Forecast accuracy</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>New products enabled</li>
|
||||||
|
<li><span className="text-terminal-green mr-2">-</span>Market positioning</li>
|
||||||
|
</ul>
|
||||||
|
<div className="terminal-panel mt-3">
|
||||||
|
<p className="font-mono text-sm text-foreground"><strong>Method:</strong> Scenario value + strategic positioning narrative</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Metrics by Category */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat metrics.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
Across use cases, companies typically track a mix of financial, operational, customer, and workforce metrics. Choose metrics that align with your specific use cases and business objectives.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="terminal-panel overflow-x-auto mb-6">
|
||||||
|
<span className="terminal-panel-title">metrics by category</span>
|
||||||
|
<table className="w-full text-sm mt-2">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-border">
|
||||||
|
<th className="text-left p-2 text-terminal-dim">Category</th>
|
||||||
|
<th className="text-left p-2 text-terminal-dim">Key Metrics</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-foreground">
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Financial</td>
|
||||||
|
<td className="p-2">Cost savings, maintenance reduction, incremental revenue, margin uplift, ROI %, payback period, NPV/IRR, 3-5 year TCO</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Operational</td>
|
||||||
|
<td className="p-2">Processing time, throughput per FTE, error/defect rate, uptime, forecast accuracy, code generation speed, bug resolution time</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Customer</td>
|
||||||
|
<td className="p-2">CSAT/NPS, churn rate, conversion rate, cart abandonment, self-service rate, response/resolution time</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="p-2 font-bold">Workforce</td>
|
||||||
|
<td className="p-2">Tasks automated, low-value work reduction, employee satisfaction, ramp-up time for new staff</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel overflow-x-auto">
|
||||||
|
<span className="terminal-panel-title">metrics by use case</span>
|
||||||
|
<table className="w-full text-sm mt-2">
|
||||||
|
<thead>
|
||||||
|
<tr className="border-b border-border">
|
||||||
|
<th className="text-left p-2 text-terminal-dim">Use Case</th>
|
||||||
|
<th className="text-left p-2 text-terminal-dim">Hard Metrics</th>
|
||||||
|
<th className="text-left p-2 text-terminal-dim">Supporting Metrics</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody className="text-foreground">
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">AI Chatbot/Agent</td>
|
||||||
|
<td className="p-2">Cost per contact, call deflection %, FTE savings</td>
|
||||||
|
<td className="p-2">CSAT/NPS, first-response time, resolution time</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Recommendations/CX</td>
|
||||||
|
<td className="p-2">Conversion rate, AOV, revenue per session</td>
|
||||||
|
<td className="p-2">Time on site, engagement, repeat purchase</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Predictive Maintenance</td>
|
||||||
|
<td className="p-2">Downtime reduction, maintenance cost savings</td>
|
||||||
|
<td className="p-2">Forecast accuracy, asset utilization</td>
|
||||||
|
</tr>
|
||||||
|
<tr className="border-b border-border/50">
|
||||||
|
<td className="p-2 font-bold">Risk/Fraud/Credit</td>
|
||||||
|
<td className="p-2">Losses avoided, charge-offs reduced</td>
|
||||||
|
<td className="p-2">Detection accuracy, false positives, review workload</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td className="p-2 font-bold">AI-Assisted Dev/Ops</td>
|
||||||
|
<td className="p-2">Dev cost savings, time-to-market, infra cost reduction</td>
|
||||||
|
<td className="p-2">Code quality, security findings, incident frequency</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Case Studies */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat case-studies.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
Examining how leading organizations measure and achieve AI ROI provides practical insights for your own measurement strategy.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-3">Customer Service Chatbots</p>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">American Express</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">AI chatbots automated large share of customer interactions</p>
|
||||||
|
<p className="text-sm mt-2"><span className="text-terminal-green font-bold">25% cost reduction, 10% CSAT increase</span></p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">Bank of America "Erica"</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">AI assistant handling over 1 billion interactions</p>
|
||||||
|
<p className="text-sm mt-2"><span className="text-terminal-green font-bold">17% call-center load reduction</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-3">Retail Personalization</p>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">H&M AI Agent</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">AI resolved 70% of queries autonomously</p>
|
||||||
|
<p className="text-sm mt-2"><span className="text-terminal-green font-bold">25% conversion increase, 3x faster response</span></p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">E-commerce Recommendations</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">A/B tested recommendation engine</p>
|
||||||
|
<p className="text-sm mt-2"><span className="text-terminal-green font-bold">Payback achieved within months</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-3">Operations & Supply Chain</p>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">Manufacturing Predictive Maintenance</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">95% accurate two-week failure prediction</p>
|
||||||
|
<p className="text-sm mt-2"><span className="text-terminal-green font-bold">Positive ROI in 9 months</span></p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">Supply Chain AI</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">23% inventory cost reduction, 18% fewer stockouts</p>
|
||||||
|
<p className="text-sm mt-2"><span className="text-terminal-green font-bold">340% ROI in 18 months</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-3">Financial Services & Healthcare</p>
|
||||||
|
<div className="grid md:grid-cols-2 gap-4">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">Banking AI</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">78% faster loan processing</p>
|
||||||
|
<p className="text-sm mt-2"><span className="text-terminal-green font-bold">285% ROI in 1 year</span></p>
|
||||||
|
</div>
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold">Radiology AI Platform</p>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">Including radiologist time savings</p>
|
||||||
|
<p className="text-sm mt-2"><span className="text-terminal-green font-bold">451-791% ROI over 5 years</span></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p className="mt-6 text-sm text-terminal-dim">
|
||||||
|
For more enterprise AI case studies, see our analysis of{" "}
|
||||||
|
<Link href="/claims-library/amazon-ai-playbook" className="text-terminal-cyan hover:underline">Amazon's AI Playbook</Link>,{" "}
|
||||||
|
<Link href="/claims-library/hilton-deployed-41-ai-use-cases" className="text-terminal-cyan hover:underline">Hilton's 41 AI Use Cases</Link>, and{" "}
|
||||||
|
<Link href="/claims-library/nike-500m-ai-gamble" className="text-terminal-cyan hover:underline">Nike's $500M AI Investment</Link>.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Practical Playbook */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat measurement-playbook.txt
|
||||||
|
</h2>
|
||||||
|
<p className="text-sm text-terminal-dim mb-6">
|
||||||
|
Follow this five-step roadmap to establish effective AI ROI measurement in your organization:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[1]</span> Start with Business Goals & Baselines
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Define specific business outcomes at the outset (cost, revenue, risk, CX) and capture pre-AI baselines (current processing time, conversion rate, loss rate). Without baselines, you can't attribute improvements to AI.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[2]</span> Map AI Outputs to Business KPIs
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Translate model-level metrics (precision, latency) into business-level KPIs such as fewer manual reviews, faster approvals, or higher acceptance rates. Connect technical performance to business outcomes.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[3]</span> Use Pilots, A/B Tests, and Control Groups
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Run side-by-side comparisons of AI vs non-AI processes to attribute impact and reduce noise from external factors. This is the gold standard for proving causation, not just correlation.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[4]</span> Include Total Cost of Ownership
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Account for data engineering, infrastructure, licensing, governance, monitoring, and retraining - not just initial build costs. Many organizations underestimate ongoing AI costs by 40-60%.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-green">
|
||||||
|
<h3 className="text-foreground font-bold mb-1">
|
||||||
|
<span className="text-terminal-green">[5]</span> Report Ranges and Scenarios
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Use best/likely/worst cases and sensitivity analyses on key assumptions (adoption rate, volume growth) to give leadership a realistic view. Single-point estimates create false confidence.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Common Mistakes */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat mistakes.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Measuring Too Early
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
AI implementations need 90+ days for user adoption and process optimization. Measuring in the first 30 days often shows negative returns that don't reflect long-term value.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Ignoring Hidden Costs
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Focusing only on software costs while ignoring training, integration, change management, and ongoing maintenance distorts true ROI calculations.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> Single-Metric Focus
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Optimizing for one metric (like cost savings) while ignoring others (like quality or employee satisfaction) leads to suboptimal outcomes and can damage long-term value.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel border-l-2 border-l-terminal-red">
|
||||||
|
<h3 className="text-foreground font-bold mb-2">
|
||||||
|
<span className="text-terminal-red">[!]</span> No Baseline Measurement
|
||||||
|
</h3>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Without clear pre-implementation baselines, you can't accurately attribute improvements to AI versus other factors or external market changes.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* FAQ */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
cat faq.txt
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div className="space-y-4">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-2">How long should we wait before measuring AI ROI?</p>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Most AI implementations need 90 days minimum for accurate ROI assessment. This allows time for user adoption, process optimization, and stabilization. Track leading indicators (adoption, usage patterns) from day one, but hold off on formal ROI calculations.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-2">What's a good ROI target for AI projects?</p>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Based on case studies, productivity-focused AI should target 3-5x ROI within 18 months. Top performers achieve 285-340% ROI within a year. Healthcare and specialized applications can see 400%+ over longer horizons.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-2">Should we measure ROI at the tool level or portfolio level?</p>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Both. Individual tool ROI informs optimization and expansion decisions. Portfolio-level ROI provides executive visibility and justifies continued AI investment. Some tools may have negative individual ROI but contribute to portfolio value through integration effects.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<p className="text-foreground font-bold mb-2">How do we measure ROI for hard-to-quantify benefits?</p>
|
||||||
|
<p className="text-sm text-terminal-dim">
|
||||||
|
Use scorecards that combine hard financial metrics with softer benefits (risk reduction, customer experience, capability building). For strategic value, express it as scenario value plus narrative on positioning - boards understand this language.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Conclusion */}
|
||||||
|
<section className="mb-12">
|
||||||
|
<div className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">taking action</span>
|
||||||
|
<p className="text-sm text-foreground mt-2 leading-relaxed mb-3">
|
||||||
|
Effective AI ROI measurement isn't just about justifying investments - it's about creating a feedback loop that drives continuous improvement and helps you make better decisions about where to focus AI resources.
|
||||||
|
</p>
|
||||||
|
<p className="text-sm text-foreground leading-relaxed">
|
||||||
|
Start with the four-quadrant framework, establish clear baselines, and commit to regular measurement reviews. The organizations that master AI ROI measurement are the ones that consistently get more value from their AI investments - like the 340% ROI achievers in supply chain or the 25% cost reducers in customer service.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Related Claims */}
|
||||||
|
{measurementClaims.length > 0 && (
|
||||||
|
<section className="mb-12">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold mb-6">
|
||||||
|
grep -l "measurement" claims/*
|
||||||
|
</h2>
|
||||||
|
<div className="space-y-4">
|
||||||
|
{measurementClaims.slice(0, 4).map((article) => (
|
||||||
|
<div key={article.slug} className="terminal-panel">
|
||||||
|
<Link
|
||||||
|
href={`/claims-library/${article.slug}`}
|
||||||
|
className="font-bold text-foreground hover:text-terminal-cyan transition-colors"
|
||||||
|
>
|
||||||
|
{article.title}
|
||||||
|
</Link>
|
||||||
|
<p className="text-xs text-terminal-dim mt-1">
|
||||||
|
{article.claims.length} atomic claims
|
||||||
|
</p>
|
||||||
|
<ul className="mt-2 space-y-1">
|
||||||
|
{article.claims.slice(0, 2).map((claim, idx) => (
|
||||||
|
<li
|
||||||
|
key={idx}
|
||||||
|
className="text-sm text-foreground flex items-start"
|
||||||
|
>
|
||||||
|
<span className="text-terminal-green mr-2">-</span>
|
||||||
|
<span>{claim}</span>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{/* Related Resources */}
|
||||||
|
<section className="terminal-panel">
|
||||||
|
<span className="terminal-panel-title">see also</span>
|
||||||
|
<div className="space-y-2 mt-2 text-sm">
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/ai-implementation"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat ai-implementation/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/ai-strategy"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat ai-strategy/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/ai-business-applications"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
cat ai-business-applications/*
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<Link
|
||||||
|
href="/claims-library"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
ls claims-library/
|
||||||
|
</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<TerminalFooter />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
251
src/app/page.tsx
251
src/app/page.tsx
|
|
@ -1,63 +1,264 @@
|
||||||
import type { Metadata } from "next";
|
import type { Metadata } from "next";
|
||||||
import StatsBar from "@/components/StatsBar";
|
import Link from "next/link";
|
||||||
import Header from "@/components/Header";
|
import { ALL_CLAIMS_DATA, getTotalClaimsCount } from "@/data/claims";
|
||||||
import HowToUse from "@/components/HowToUse";
|
import TerminalChrome from "@/components/TerminalChrome";
|
||||||
import Services from "@/components/Services";
|
import FluidSimulation from "@/components/FluidSimulationLoader";
|
||||||
import ClaimsLibrary from "@/components/ClaimsLibrary";
|
|
||||||
import Footer from "@/components/Footer";
|
|
||||||
|
|
||||||
export const metadata: Metadata = {
|
export const metadata: Metadata = {
|
||||||
title: "Kamil Banc | AI Implementation Expert",
|
title: "Kamil Banc | AI Implementation Expert",
|
||||||
description: "AI implementation expert helping organizations transform AI from decorative art into practical business machinery with measurable ROI.",
|
description:
|
||||||
|
"AI implementation expert helping organizations transform AI from decorative art into practical business machinery with measurable ROI.",
|
||||||
};
|
};
|
||||||
|
|
||||||
// JSON-LD structured data
|
const personJsonLd = {
|
||||||
const jsonLd = {
|
|
||||||
"@context": "https://schema.org",
|
"@context": "https://schema.org",
|
||||||
"@type": "Person",
|
"@type": "Person",
|
||||||
name: "Kamil Banc",
|
name: "Kamil Banc",
|
||||||
jobTitle: "AI Implementation Expert",
|
jobTitle: "AI Implementation Expert & Strategist",
|
||||||
description: "AI implementation expert helping organizations transform AI from decorative art into practical business machinery with measurable ROI.",
|
description:
|
||||||
|
"AI implementation expert helping organizations transform AI from decorative art into practical business machinery with measurable ROI.",
|
||||||
url: "https://kbanc.com",
|
url: "https://kbanc.com",
|
||||||
image: "https://kbanc.com/kamil-banc.jpg",
|
image: "https://kbanc.com/kamil-banc.jpg",
|
||||||
sameAs: [
|
sameAs: [
|
||||||
"https://www.linkedin.com/in/kbanc/",
|
"https://www.linkedin.com/in/kbanc/",
|
||||||
"https://aiadopters.club",
|
"https://aiadopters.club",
|
||||||
"https://x.com/kamilbanc"
|
"https://x.com/kamilbanc",
|
||||||
],
|
],
|
||||||
knowsAbout: [
|
knowsAbout: [
|
||||||
"Artificial Intelligence",
|
"Artificial Intelligence",
|
||||||
"AI Implementation",
|
"AI Implementation",
|
||||||
"AI Strategy",
|
"AI Strategy",
|
||||||
"Digital Transformation",
|
"Digital Transformation",
|
||||||
"AI Adoption"
|
"AI Adoption",
|
||||||
|
"Large Language Models",
|
||||||
|
"LLM Integration",
|
||||||
|
"Enterprise AI",
|
||||||
|
"AI ROI Measurement",
|
||||||
|
"Prompt Engineering",
|
||||||
|
"Generative AI",
|
||||||
|
"AI Workflow Design",
|
||||||
|
"Business Process Automation",
|
||||||
|
"AI Tools Selection",
|
||||||
],
|
],
|
||||||
|
hasOccupation: {
|
||||||
|
"@type": "Occupation",
|
||||||
|
name: "AI Implementation Expert",
|
||||||
|
description:
|
||||||
|
"Specializes in helping organizations implement practical AI systems that generate measurable business value.",
|
||||||
|
skills: [
|
||||||
|
"AI Strategy Development",
|
||||||
|
"LLM Implementation",
|
||||||
|
"AI Workflow Design",
|
||||||
|
"Change Management",
|
||||||
|
"ROI Analysis",
|
||||||
|
],
|
||||||
|
},
|
||||||
affiliation: {
|
affiliation: {
|
||||||
"@type": "Organization",
|
"@type": "Organization",
|
||||||
name: "AI Adopters Club",
|
name: "AI Adopters Club",
|
||||||
url: "https://aiadopters.club"
|
url: "https://aiadopters.club",
|
||||||
}
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const websiteJsonLd = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "WebSite",
|
||||||
|
name: "Kamil Banc",
|
||||||
|
url: "https://kbanc.com",
|
||||||
|
description:
|
||||||
|
"AI implementation insights, citation-ready claims, and frameworks from Kamil Banc.",
|
||||||
|
potentialAction: {
|
||||||
|
"@type": "SearchAction",
|
||||||
|
target: {
|
||||||
|
"@type": "EntryPoint",
|
||||||
|
urlTemplate: "https://kbanc.com/claims-library?q={search_term_string}",
|
||||||
|
},
|
||||||
|
"query-input": "required name=search_term_string",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default function HomePage() {
|
export default function HomePage() {
|
||||||
|
const articleCount = ALL_CLAIMS_DATA.length;
|
||||||
|
const claimCount = getTotalClaimsCount();
|
||||||
|
|
||||||
|
// JSON-LD is hardcoded string literals from trusted schema objects above - safe to inline
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<script
|
<script
|
||||||
type="application/ld+json"
|
type="application/ld+json"
|
||||||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(personJsonLd) }}
|
||||||
/>
|
/>
|
||||||
<div className="min-h-screen bg-background">
|
<script
|
||||||
<a href="#main-content" className="sr-only focus:not-sr-only focus:absolute focus:z-50 focus:p-4 focus:bg-background">
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(websiteJsonLd) }}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div className="min-h-screen bg-background flex flex-col items-center justify-center px-4 py-8 md:py-12">
|
||||||
|
<a
|
||||||
|
href="#main-content"
|
||||||
|
className="sr-only focus:not-sr-only focus:absolute focus:z-50 focus:p-4 focus:bg-background"
|
||||||
|
>
|
||||||
Skip to main content
|
Skip to main content
|
||||||
</a>
|
</a>
|
||||||
<StatsBar />
|
|
||||||
<Header />
|
<TerminalChrome>
|
||||||
<HowToUse />
|
<main id="main-content" className="space-y-8">
|
||||||
<main id="main-content">
|
{/* whoami */}
|
||||||
<ClaimsLibrary />
|
<section>
|
||||||
<Services />
|
<h1 className="terminal-prompt text-foreground text-lg md:text-xl font-bold">
|
||||||
|
whoami
|
||||||
|
</h1>
|
||||||
|
<p className="mt-2 text-foreground leading-relaxed">
|
||||||
|
kamil banc. i build things.
|
||||||
|
</p>
|
||||||
|
<p className="text-terminal-dim text-sm mt-1">
|
||||||
|
AI implementation for organizations that want measurable results, not slide decks.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Fluid simulation */}
|
||||||
|
<section>
|
||||||
|
<FluidSimulation />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* about.txt */}
|
||||||
|
<section>
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold">
|
||||||
|
cat about.txt
|
||||||
|
</h2>
|
||||||
|
<div className="mt-2 space-y-3 text-foreground leading-relaxed text-sm md:text-base">
|
||||||
|
<p>
|
||||||
|
I help companies stop treating AI like a science project and start treating it like infrastructure.
|
||||||
|
The newsletter reaches 10,000+ operators who want practical frameworks, not hype.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
This site is a claims library: {articleCount} articles, {claimCount} atomic claims,
|
||||||
|
each designed to be independently verifiable and citable by both humans and LLMs.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ls projects/ */}
|
||||||
|
<section>
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold">
|
||||||
|
ls projects/
|
||||||
|
</h2>
|
||||||
|
<nav className="mt-2 space-y-1" aria-label="Projects">
|
||||||
|
<Link
|
||||||
|
href="https://aiadopters.club"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
className="block text-terminal-cyan hover:glow-cyan transition-all"
|
||||||
|
>
|
||||||
|
ai-adopters-club/<span className="text-terminal-dim ml-2 text-xs">10K+ subscribers, weekly AI newsletter</span>
|
||||||
|
</Link>
|
||||||
|
<Link
|
||||||
|
href="/claims-library"
|
||||||
|
className="block text-terminal-cyan hover:glow-cyan transition-all"
|
||||||
|
>
|
||||||
|
claims-library/<span className="text-terminal-dim ml-2 text-xs">{claimCount} atomic claims, citation-ready</span>
|
||||||
|
</Link>
|
||||||
|
</nav>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* ls topics/ */}
|
||||||
|
<section>
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold">
|
||||||
|
ls topics/
|
||||||
|
</h2>
|
||||||
|
<nav className="mt-2 grid grid-cols-1 sm:grid-cols-2 gap-1" aria-label="Topics">
|
||||||
|
<Link href="/ai-strategy" className="text-terminal-cyan hover:glow-cyan text-sm">
|
||||||
|
ai-strategy/
|
||||||
|
</Link>
|
||||||
|
<Link href="/ai-implementation" className="text-terminal-cyan hover:glow-cyan text-sm">
|
||||||
|
ai-implementation/
|
||||||
|
</Link>
|
||||||
|
<Link href="/ai-tools" className="text-terminal-cyan hover:glow-cyan text-sm">
|
||||||
|
ai-tools/
|
||||||
|
</Link>
|
||||||
|
<Link href="/ai-business-applications" className="text-terminal-cyan hover:glow-cyan text-sm">
|
||||||
|
ai-business-applications/
|
||||||
|
</Link>
|
||||||
|
<Link href="/measuring-ai-roi" className="text-terminal-cyan hover:glow-cyan text-sm">
|
||||||
|
measuring-ai-roi/
|
||||||
|
</Link>
|
||||||
|
</nav>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* cat links.txt */}
|
||||||
|
<section>
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold">
|
||||||
|
cat links.txt
|
||||||
|
</h2>
|
||||||
|
<nav className="mt-2 space-y-1 text-sm" aria-label="External links">
|
||||||
|
<div>
|
||||||
|
<span className="text-terminal-dim">linkedin</span>
|
||||||
|
<span className="text-terminal-dim mx-2">-></span>
|
||||||
|
<a
|
||||||
|
href="https://www.linkedin.com/in/kbanc/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-terminal-cyan hover:glow-cyan"
|
||||||
|
>
|
||||||
|
linkedin.com/in/kbanc
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span className="text-terminal-dim">newsletter</span>
|
||||||
|
<span className="text-terminal-dim mx-2">-></span>
|
||||||
|
<a
|
||||||
|
href="https://aiadopters.club"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-terminal-cyan hover:glow-cyan"
|
||||||
|
>
|
||||||
|
aiadopters.club
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<span className="text-terminal-dim">x/twitter</span>
|
||||||
|
<span className="text-terminal-dim mx-2">-></span>
|
||||||
|
<a
|
||||||
|
href="https://x.com/kamilbanc"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="text-terminal-cyan hover:glow-cyan"
|
||||||
|
>
|
||||||
|
x.com/kamilbanc
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{/* Terminal nav */}
|
||||||
|
<nav
|
||||||
|
className="flex flex-wrap gap-3 pt-4 border-t border-border terminal-nav text-sm"
|
||||||
|
aria-label="Site navigation"
|
||||||
|
>
|
||||||
|
<Link href="/">[home]</Link>
|
||||||
|
<Link href="/claims-library">[claims]</Link>
|
||||||
|
<Link href="/about">[about]</Link>
|
||||||
|
<Link href="/faq">[faq]</Link>
|
||||||
|
<Link href="/how-i-built-this">[how-i-built-this]</Link>
|
||||||
|
</nav>
|
||||||
</main>
|
</main>
|
||||||
<Footer />
|
</TerminalChrome>
|
||||||
|
|
||||||
|
{/* Footer */}
|
||||||
|
<footer className="mt-8 text-center text-xs text-terminal-dim">
|
||||||
|
<p>
|
||||||
|
Content licensed under{" "}
|
||||||
|
<a
|
||||||
|
href="https://creativecommons.org/licenses/by/4.0/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
CC BY 4.0
|
||||||
|
</a>
|
||||||
|
{" "}by Kamil Banc
|
||||||
|
</p>
|
||||||
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -1,44 +0,0 @@
|
||||||
import { ExternalLink } from "lucide-react";
|
|
||||||
|
|
||||||
const Bio = () => {
|
|
||||||
return (
|
|
||||||
<section className="py-10 md:py-12 border-b border-border">
|
|
||||||
<div className="container max-w-4xl mx-auto px-5">
|
|
||||||
<div className="space-y-4">
|
|
||||||
<p className="text-base leading-relaxed">
|
|
||||||
I help organizations implement AI systems that actually work. I focus on real implementations that generate measurable value, not theoretical frameworks or vendor pitches.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p className="text-base leading-relaxed">
|
|
||||||
My work focuses on practical adoption patterns: what works, what fails, and why. I document implementation frameworks, measure outcomes, and share findings through the AI Adopters Club community.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p className="text-base leading-relaxed">
|
|
||||||
This library contains citation-ready claims from my research and consulting work. Each claim is backed by data, includes context, and is optimized for LLM extraction.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<div className="flex flex-wrap gap-4 pt-2">
|
|
||||||
<a
|
|
||||||
href="https://www.linkedin.com/in/kbanc/"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-accent hover:underline inline-flex items-center gap-1"
|
|
||||||
>
|
|
||||||
LinkedIn <ExternalLink className="h-3 w-3" />
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://aiadopters.club"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-accent hover:underline inline-flex items-center gap-1"
|
|
||||||
>
|
|
||||||
AI Adopters Club <ExternalLink className="h-3 w-3" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Bio;
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
interface BreadcrumbItem {
|
||||||
|
label: string;
|
||||||
|
href?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Breadcrumbs({ items }: { items: BreadcrumbItem[] }) {
|
||||||
|
// BreadcrumbList schema - all values are from compile-time props, no user input
|
||||||
|
const jsonLd = {
|
||||||
|
"@context": "https://schema.org",
|
||||||
|
"@type": "BreadcrumbList",
|
||||||
|
itemListElement: items.map((item, index) => ({
|
||||||
|
"@type": "ListItem",
|
||||||
|
position: index + 1,
|
||||||
|
name: item.label,
|
||||||
|
...(item.href ? { item: `https://kbanc.com${item.href}` } : {}),
|
||||||
|
})),
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<script
|
||||||
|
type="application/ld+json"
|
||||||
|
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||||||
|
/>
|
||||||
|
<nav aria-label="Breadcrumb" className="text-xs text-terminal-dim mb-4">
|
||||||
|
{items.map((item, index) => (
|
||||||
|
<span key={index}>
|
||||||
|
{index > 0 && <span className="mx-1">/</span>}
|
||||||
|
{item.href ? (
|
||||||
|
<Link
|
||||||
|
href={item.href}
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
{item.label}
|
||||||
|
</Link>
|
||||||
|
) : (
|
||||||
|
<span className="text-foreground">{item.label}</span>
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</nav>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
/**
|
||||||
|
* Maps fluid density to styled ASCII characters.
|
||||||
|
* Uses Unicode block elements: ░▒▓█ and space.
|
||||||
|
* Color intensity varies with density using HSL.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Block characters from lightest to densest
|
||||||
|
const BLOCKS = [" ", "\u2591", "\u2592", "\u2593", "\u2588"];
|
||||||
|
|
||||||
|
// Color palette: density maps through cyan -> green -> yellow -> white
|
||||||
|
function densityToColor(d: number): string {
|
||||||
|
if (d < 0.01) return "";
|
||||||
|
|
||||||
|
const clamped = Math.min(d, 1);
|
||||||
|
|
||||||
|
// Low density: dim cyan
|
||||||
|
// Mid density: bright green
|
||||||
|
// High density: warm yellow-white
|
||||||
|
if (clamped < 0.3) {
|
||||||
|
const t = clamped / 0.3;
|
||||||
|
const h = 190 - t * 48; // 190 (cyan) -> 142 (green)
|
||||||
|
const s = 60 + t * 20;
|
||||||
|
const l = 25 + t * 25;
|
||||||
|
return `hsl(${h},${s}%,${l}%)`;
|
||||||
|
} else if (clamped < 0.7) {
|
||||||
|
const t = (clamped - 0.3) / 0.4;
|
||||||
|
const h = 142 - t * 97; // 142 (green) -> 45 (yellow)
|
||||||
|
const s = 80 - t * 10;
|
||||||
|
const l = 50 + t * 15;
|
||||||
|
return `hsl(${h},${s}%,${l}%)`;
|
||||||
|
} else {
|
||||||
|
const t = (clamped - 0.7) / 0.3;
|
||||||
|
const h = 45 - t * 5; // 45 (yellow) -> 40 (warm white)
|
||||||
|
const s = 70 - t * 50;
|
||||||
|
const l = 65 + t * 25;
|
||||||
|
return `hsl(${h},${s}%,${l}%)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function densityToBlock(d: number): string {
|
||||||
|
if (d < 0.01) return " ";
|
||||||
|
const idx = Math.min(Math.floor(d * BLOCKS.length), BLOCKS.length - 1);
|
||||||
|
return BLOCKS[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface RenderTarget {
|
||||||
|
spans: HTMLSpanElement[];
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create persistent span elements inside a <pre> tag.
|
||||||
|
* Each cell gets its own span for efficient color updates.
|
||||||
|
*/
|
||||||
|
export function createRenderTarget(
|
||||||
|
pre: HTMLPreElement,
|
||||||
|
width: number,
|
||||||
|
height: number
|
||||||
|
): RenderTarget {
|
||||||
|
pre.textContent = "";
|
||||||
|
const spans: HTMLSpanElement[] = [];
|
||||||
|
|
||||||
|
for (let j = 0; j < height; j++) {
|
||||||
|
for (let i = 0; i < width; i++) {
|
||||||
|
const span = document.createElement("span");
|
||||||
|
span.textContent = " ";
|
||||||
|
pre.appendChild(span);
|
||||||
|
spans.push(span);
|
||||||
|
}
|
||||||
|
if (j < height - 1) {
|
||||||
|
pre.appendChild(document.createTextNode("\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return { spans, width, height };
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render density field to the pre-allocated spans.
|
||||||
|
* N, M are the inner grid dimensions (density array is (N+2)*(M+2)).
|
||||||
|
*/
|
||||||
|
export function renderDensity(
|
||||||
|
target: RenderTarget,
|
||||||
|
density: Float32Array,
|
||||||
|
N: number,
|
||||||
|
M: number
|
||||||
|
): void {
|
||||||
|
const { spans, width, height } = target;
|
||||||
|
|
||||||
|
for (let j = 0; j < height; j++) {
|
||||||
|
// Map render row to grid row (skip boundary cells)
|
||||||
|
const gj = 1 + Math.floor((j / height) * M);
|
||||||
|
for (let i = 0; i < width; i++) {
|
||||||
|
const gi = 1 + Math.floor((i / width) * N);
|
||||||
|
const idx = gi + (N + 2) * gj;
|
||||||
|
const d = density[idx];
|
||||||
|
const spanIdx = j * width + i;
|
||||||
|
const span = spans[spanIdx];
|
||||||
|
|
||||||
|
const char = densityToBlock(d);
|
||||||
|
const color = densityToColor(d);
|
||||||
|
|
||||||
|
if (span.textContent !== char) {
|
||||||
|
span.textContent = char;
|
||||||
|
}
|
||||||
|
if (color) {
|
||||||
|
if (span.style.color !== color) {
|
||||||
|
span.style.color = color;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (span.style.color) {
|
||||||
|
span.style.color = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,251 @@
|
||||||
|
/**
|
||||||
|
* Jos Stam's Stable Fluids - pure math, no DOM.
|
||||||
|
* Grid is (N+2) x (N+2) with boundary cells.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface FluidState {
|
||||||
|
N: number; // grid width (inner)
|
||||||
|
M: number; // grid height (inner)
|
||||||
|
size: number; // (N+2) * (M+2)
|
||||||
|
density: Float32Array;
|
||||||
|
densityPrev: Float32Array;
|
||||||
|
velocityX: Float32Array;
|
||||||
|
velocityXPrev: Float32Array;
|
||||||
|
velocityY: Float32Array;
|
||||||
|
velocityYPrev: Float32Array;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function createFluidState(N: number, M: number): FluidState {
|
||||||
|
const size = (N + 2) * (M + 2);
|
||||||
|
return {
|
||||||
|
N,
|
||||||
|
M,
|
||||||
|
size,
|
||||||
|
density: new Float32Array(size),
|
||||||
|
densityPrev: new Float32Array(size),
|
||||||
|
velocityX: new Float32Array(size),
|
||||||
|
velocityXPrev: new Float32Array(size),
|
||||||
|
velocityY: new Float32Array(size),
|
||||||
|
velocityYPrev: new Float32Array(size),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function IX(N: number, i: number, j: number): number {
|
||||||
|
return i + (N + 2) * j;
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBoundary(N: number, M: number, b: number, x: Float32Array): void {
|
||||||
|
const w = N + 2;
|
||||||
|
for (let j = 1; j <= M; j++) {
|
||||||
|
x[IX(N, 0, j)] = b === 1 ? -x[IX(N, 1, j)] : x[IX(N, 1, j)];
|
||||||
|
x[IX(N, N + 1, j)] = b === 1 ? -x[IX(N, N, j)] : x[IX(N, N, j)];
|
||||||
|
}
|
||||||
|
for (let i = 1; i <= N; i++) {
|
||||||
|
x[IX(N, i, 0)] = b === 2 ? -x[IX(N, i, 1)] : x[IX(N, i, 1)];
|
||||||
|
x[IX(N, i, M + 1)] = b === 2 ? -x[IX(N, i, M)] : x[IX(N, i, M)];
|
||||||
|
}
|
||||||
|
x[IX(N, 0, 0)] = 0.5 * (x[IX(N, 1, 0)] + x[IX(N, 0, 1)]);
|
||||||
|
x[IX(N, 0, M + 1)] = 0.5 * (x[IX(N, 1, M + 1)] + x[IX(N, 0, M)]);
|
||||||
|
x[IX(N, N + 1, 0)] = 0.5 * (x[IX(N, N, 0)] + x[IX(N, N + 1, 1)]);
|
||||||
|
x[IX(N, N + 1, M + 1)] = 0.5 * (x[IX(N, N, M + 1)] + x[IX(N, N + 1, M)]);
|
||||||
|
}
|
||||||
|
|
||||||
|
function linearSolve(
|
||||||
|
N: number,
|
||||||
|
M: number,
|
||||||
|
b: number,
|
||||||
|
x: Float32Array,
|
||||||
|
x0: Float32Array,
|
||||||
|
a: number,
|
||||||
|
c: number,
|
||||||
|
iterations: number
|
||||||
|
): void {
|
||||||
|
const cRecip = 1.0 / c;
|
||||||
|
for (let k = 0; k < iterations; k++) {
|
||||||
|
for (let j = 1; j <= M; j++) {
|
||||||
|
for (let i = 1; i <= N; i++) {
|
||||||
|
x[IX(N, i, j)] =
|
||||||
|
(x0[IX(N, i, j)] +
|
||||||
|
a *
|
||||||
|
(x[IX(N, i + 1, j)] +
|
||||||
|
x[IX(N, i - 1, j)] +
|
||||||
|
x[IX(N, i, j + 1)] +
|
||||||
|
x[IX(N, i, j - 1)])) *
|
||||||
|
cRecip;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setBoundary(N, M, b, x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function diffuse(
|
||||||
|
N: number,
|
||||||
|
M: number,
|
||||||
|
b: number,
|
||||||
|
x: Float32Array,
|
||||||
|
x0: Float32Array,
|
||||||
|
diff: number,
|
||||||
|
dt: number,
|
||||||
|
iterations: number
|
||||||
|
): void {
|
||||||
|
const a = dt * diff * N * M;
|
||||||
|
linearSolve(N, M, b, x, x0, a, 1 + 4 * a, iterations);
|
||||||
|
}
|
||||||
|
|
||||||
|
function advect(
|
||||||
|
N: number,
|
||||||
|
M: number,
|
||||||
|
b: number,
|
||||||
|
d: Float32Array,
|
||||||
|
d0: Float32Array,
|
||||||
|
velocX: Float32Array,
|
||||||
|
velocY: Float32Array,
|
||||||
|
dt: number
|
||||||
|
): void {
|
||||||
|
const dtx = dt * N;
|
||||||
|
const dty = dt * M;
|
||||||
|
|
||||||
|
for (let j = 1; j <= M; j++) {
|
||||||
|
for (let i = 1; i <= N; i++) {
|
||||||
|
let x = i - dtx * velocX[IX(N, i, j)];
|
||||||
|
let y = j - dty * velocY[IX(N, i, j)];
|
||||||
|
|
||||||
|
if (x < 0.5) x = 0.5;
|
||||||
|
if (x > N + 0.5) x = N + 0.5;
|
||||||
|
const i0 = Math.floor(x);
|
||||||
|
const i1 = i0 + 1;
|
||||||
|
|
||||||
|
if (y < 0.5) y = 0.5;
|
||||||
|
if (y > M + 0.5) y = M + 0.5;
|
||||||
|
const j0 = Math.floor(y);
|
||||||
|
const j1 = j0 + 1;
|
||||||
|
|
||||||
|
const s1 = x - i0;
|
||||||
|
const s0 = 1 - s1;
|
||||||
|
const t1 = y - j0;
|
||||||
|
const t0 = 1 - t1;
|
||||||
|
|
||||||
|
d[IX(N, i, j)] =
|
||||||
|
s0 * (t0 * d0[IX(N, i0, j0)] + t1 * d0[IX(N, i0, j1)]) +
|
||||||
|
s1 * (t0 * d0[IX(N, i1, j0)] + t1 * d0[IX(N, i1, j1)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setBoundary(N, M, b, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
function project(
|
||||||
|
N: number,
|
||||||
|
M: number,
|
||||||
|
velocX: Float32Array,
|
||||||
|
velocY: Float32Array,
|
||||||
|
p: Float32Array,
|
||||||
|
div: Float32Array,
|
||||||
|
iterations: number
|
||||||
|
): void {
|
||||||
|
for (let j = 1; j <= M; j++) {
|
||||||
|
for (let i = 1; i <= N; i++) {
|
||||||
|
div[IX(N, i, j)] =
|
||||||
|
(-0.5 *
|
||||||
|
(velocX[IX(N, i + 1, j)] -
|
||||||
|
velocX[IX(N, i - 1, j)] +
|
||||||
|
velocY[IX(N, i, j + 1)] -
|
||||||
|
velocY[IX(N, i, j - 1)])) /
|
||||||
|
Math.max(N, M);
|
||||||
|
p[IX(N, i, j)] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setBoundary(N, M, 0, div);
|
||||||
|
setBoundary(N, M, 0, p);
|
||||||
|
linearSolve(N, M, 0, p, div, 1, 4, iterations);
|
||||||
|
|
||||||
|
for (let j = 1; j <= M; j++) {
|
||||||
|
for (let i = 1; i <= N; i++) {
|
||||||
|
velocX[IX(N, i, j)] -=
|
||||||
|
0.5 * N * (p[IX(N, i + 1, j)] - p[IX(N, i - 1, j)]);
|
||||||
|
velocY[IX(N, i, j)] -=
|
||||||
|
0.5 * M * (p[IX(N, i, j + 1)] - p[IX(N, i, j - 1)]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setBoundary(N, M, 1, velocX);
|
||||||
|
setBoundary(N, M, 2, velocY);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function stepFluid(
|
||||||
|
state: FluidState,
|
||||||
|
dt: number,
|
||||||
|
diffusion: number,
|
||||||
|
viscosity: number,
|
||||||
|
iterations: number
|
||||||
|
): void {
|
||||||
|
const { N, M } = state;
|
||||||
|
|
||||||
|
// Velocity step
|
||||||
|
diffuse(N, M, 1, state.velocityXPrev, state.velocityX, viscosity, dt, iterations);
|
||||||
|
diffuse(N, M, 2, state.velocityYPrev, state.velocityY, viscosity, dt, iterations);
|
||||||
|
|
||||||
|
project(N, M, state.velocityXPrev, state.velocityYPrev, state.velocityX, state.velocityY, iterations);
|
||||||
|
|
||||||
|
advect(N, M, 1, state.velocityX, state.velocityXPrev, state.velocityXPrev, state.velocityYPrev, dt);
|
||||||
|
advect(N, M, 2, state.velocityY, state.velocityYPrev, state.velocityXPrev, state.velocityYPrev, dt);
|
||||||
|
|
||||||
|
project(N, M, state.velocityX, state.velocityY, state.velocityXPrev, state.velocityYPrev, iterations);
|
||||||
|
|
||||||
|
// Density step
|
||||||
|
diffuse(N, M, 0, state.densityPrev, state.density, diffusion, dt, iterations);
|
||||||
|
advect(N, M, 0, state.density, state.densityPrev, state.velocityX, state.velocityY, dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addSource(
|
||||||
|
state: FluidState,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
amount: number,
|
||||||
|
radius: number
|
||||||
|
): void {
|
||||||
|
const { N, M } = state;
|
||||||
|
const r2 = radius * radius;
|
||||||
|
for (let j = Math.max(1, y - radius); j <= Math.min(M, y + radius); j++) {
|
||||||
|
for (let i = Math.max(1, x - radius); i <= Math.min(N, x + radius); i++) {
|
||||||
|
const dx = i - x;
|
||||||
|
const dy = j - y;
|
||||||
|
const dist2 = dx * dx + dy * dy;
|
||||||
|
if (dist2 < r2) {
|
||||||
|
const falloff = 1 - dist2 / r2;
|
||||||
|
state.density[IX(N, i, j)] += amount * falloff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function addVelocity(
|
||||||
|
state: FluidState,
|
||||||
|
x: number,
|
||||||
|
y: number,
|
||||||
|
amountX: number,
|
||||||
|
amountY: number,
|
||||||
|
radius: number
|
||||||
|
): void {
|
||||||
|
const { N, M } = state;
|
||||||
|
const r2 = radius * radius;
|
||||||
|
for (let j = Math.max(1, y - radius); j <= Math.min(M, y + radius); j++) {
|
||||||
|
for (let i = Math.max(1, x - radius); i <= Math.min(N, x + radius); i++) {
|
||||||
|
const dx = i - x;
|
||||||
|
const dy = j - y;
|
||||||
|
const dist2 = dx * dx + dy * dy;
|
||||||
|
if (dist2 < r2) {
|
||||||
|
const falloff = 1 - dist2 / r2;
|
||||||
|
state.velocityX[IX(N, i, j)] += amountX * falloff;
|
||||||
|
state.velocityY[IX(N, i, j)] += amountY * falloff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function clearState(state: FluidState): void {
|
||||||
|
state.density.fill(0);
|
||||||
|
state.densityPrev.fill(0);
|
||||||
|
state.velocityX.fill(0);
|
||||||
|
state.velocityXPrev.fill(0);
|
||||||
|
state.velocityY.fill(0);
|
||||||
|
state.velocityYPrev.fill(0);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,110 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useRef, useState, useEffect } from "react";
|
||||||
|
import { useFluidSim } from "./use-fluid-sim";
|
||||||
|
|
||||||
|
// Grid dimensions: desktop vs mobile
|
||||||
|
const DESKTOP_GRID = { w: 80, h: 40 };
|
||||||
|
const MOBILE_GRID = { w: 40, h: 25 };
|
||||||
|
const MOBILE_BREAKPOINT = 768;
|
||||||
|
|
||||||
|
export default function FluidSimulation() {
|
||||||
|
const preRef = useRef<HTMLPreElement>(null);
|
||||||
|
const [isMobile, setIsMobile] = useState(false);
|
||||||
|
const [mounted, setMounted] = useState(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setMounted(true);
|
||||||
|
const check = () => setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
|
||||||
|
check();
|
||||||
|
window.addEventListener("resize", check);
|
||||||
|
return () => window.removeEventListener("resize", check);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const grid = isMobile ? MOBILE_GRID : DESKTOP_GRID;
|
||||||
|
|
||||||
|
const { toggleFaucet, clear } = useFluidSim(preRef, {
|
||||||
|
gridWidth: grid.w,
|
||||||
|
gridHeight: grid.h,
|
||||||
|
displayWidth: grid.w,
|
||||||
|
displayHeight: grid.h,
|
||||||
|
iterations: isMobile ? 4 : 8,
|
||||||
|
diffusion: 0.00001,
|
||||||
|
viscosity: 0.000001,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!mounted) {
|
||||||
|
return (
|
||||||
|
<div className="w-full border border-border bg-background">
|
||||||
|
<pre
|
||||||
|
className="text-xs leading-none select-none overflow-hidden p-0 m-0"
|
||||||
|
style={{
|
||||||
|
fontSize: isMobile ? "10px" : "11px",
|
||||||
|
lineHeight: "1",
|
||||||
|
}}
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
{Array(grid.h)
|
||||||
|
.fill(null)
|
||||||
|
.map((_, j) => (
|
||||||
|
<span key={j}>
|
||||||
|
{" ".repeat(grid.w)}
|
||||||
|
{j < grid.h - 1 ? "\n" : ""}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
</pre>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="w-full">
|
||||||
|
{/* The simulation canvas */}
|
||||||
|
<div className="border border-border bg-background overflow-hidden">
|
||||||
|
<pre
|
||||||
|
ref={preRef}
|
||||||
|
className="select-none cursor-crosshair overflow-hidden p-0 m-0 touch-none"
|
||||||
|
style={{
|
||||||
|
fontSize: isMobile ? "10px" : "11px",
|
||||||
|
lineHeight: "1",
|
||||||
|
letterSpacing: "0px",
|
||||||
|
}}
|
||||||
|
aria-hidden="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Controls hint */}
|
||||||
|
<div className="flex gap-4 mt-2 text-xs text-terminal-dim font-mono">
|
||||||
|
<button
|
||||||
|
onClick={toggleFaucet}
|
||||||
|
className="hover:text-terminal-green transition-colors"
|
||||||
|
>
|
||||||
|
[DRAG] Stir
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={toggleFaucet}
|
||||||
|
className="hover:text-terminal-green transition-colors"
|
||||||
|
>
|
||||||
|
[SPACE] Faucet
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={clear}
|
||||||
|
className="hover:text-terminal-green transition-colors"
|
||||||
|
>
|
||||||
|
[DBL-CLICK] Clear
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{/* Accessible description for screen readers */}
|
||||||
|
<section className="sr-only">
|
||||||
|
<h2>Interactive Fluid Simulation</h2>
|
||||||
|
<p>
|
||||||
|
A real-time Navier-Stokes fluid dynamics simulation rendered as ASCII
|
||||||
|
art. Drag to stir the fluid, press space to toggle a faucet, or
|
||||||
|
double-click to clear. This demonstrates computational fluid dynamics
|
||||||
|
running in the browser using Jos Stam's Stable Fluids algorithm.
|
||||||
|
</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,200 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useRef, useEffect, useCallback } from "react";
|
||||||
|
import {
|
||||||
|
createFluidState,
|
||||||
|
stepFluid,
|
||||||
|
addSource,
|
||||||
|
addVelocity,
|
||||||
|
clearState,
|
||||||
|
type FluidState,
|
||||||
|
} from "./fluid-solver";
|
||||||
|
import {
|
||||||
|
createRenderTarget,
|
||||||
|
renderDensity,
|
||||||
|
type RenderTarget,
|
||||||
|
} from "./ascii-renderer";
|
||||||
|
|
||||||
|
export interface FluidSimConfig {
|
||||||
|
gridWidth: number;
|
||||||
|
gridHeight: number;
|
||||||
|
displayWidth: number;
|
||||||
|
displayHeight: number;
|
||||||
|
diffusion?: number;
|
||||||
|
viscosity?: number;
|
||||||
|
iterations?: number;
|
||||||
|
dt?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useFluidSim(
|
||||||
|
preRef: React.RefObject<HTMLPreElement | null>,
|
||||||
|
config: FluidSimConfig
|
||||||
|
) {
|
||||||
|
const stateRef = useRef<FluidState | null>(null);
|
||||||
|
const renderRef = useRef<RenderTarget | null>(null);
|
||||||
|
const rafRef = useRef<number>(0);
|
||||||
|
const faucetRef = useRef(false);
|
||||||
|
const lastPointerRef = useRef<{ x: number; y: number } | null>(null);
|
||||||
|
const pointerDownRef = useRef(false);
|
||||||
|
|
||||||
|
const {
|
||||||
|
gridWidth,
|
||||||
|
gridHeight,
|
||||||
|
displayWidth,
|
||||||
|
displayHeight,
|
||||||
|
diffusion = 0.00001,
|
||||||
|
viscosity = 0.000001,
|
||||||
|
iterations = 8,
|
||||||
|
dt = 0.1,
|
||||||
|
} = config;
|
||||||
|
|
||||||
|
const init = useCallback(() => {
|
||||||
|
if (!preRef.current) return;
|
||||||
|
stateRef.current = createFluidState(gridWidth, gridHeight);
|
||||||
|
renderRef.current = createRenderTarget(
|
||||||
|
preRef.current,
|
||||||
|
displayWidth,
|
||||||
|
displayHeight
|
||||||
|
);
|
||||||
|
}, [preRef, gridWidth, gridHeight, displayWidth, displayHeight]);
|
||||||
|
|
||||||
|
const animate = useCallback(() => {
|
||||||
|
const state = stateRef.current;
|
||||||
|
const render = renderRef.current;
|
||||||
|
if (!state || !render) return;
|
||||||
|
|
||||||
|
// Faucet: continuous source at centre
|
||||||
|
if (faucetRef.current) {
|
||||||
|
const cx = Math.floor(gridWidth / 2);
|
||||||
|
const cy = Math.floor(gridHeight / 2);
|
||||||
|
addSource(state, cx, cy, 0.8, 3);
|
||||||
|
// Gentle upward drift
|
||||||
|
addVelocity(state, cx, cy, 0, -2, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ambient drift to keep things interesting
|
||||||
|
const time = Date.now() * 0.001;
|
||||||
|
const ax = Math.floor(gridWidth * 0.2);
|
||||||
|
const ay = Math.floor(gridHeight * 0.8);
|
||||||
|
addSource(state, ax, ay, 0.05, 2);
|
||||||
|
addVelocity(
|
||||||
|
state,
|
||||||
|
ax,
|
||||||
|
ay,
|
||||||
|
Math.sin(time) * 0.5,
|
||||||
|
-0.5 + Math.cos(time * 0.7) * 0.3,
|
||||||
|
2
|
||||||
|
);
|
||||||
|
|
||||||
|
stepFluid(state, dt, diffusion, viscosity, iterations);
|
||||||
|
|
||||||
|
// Gentle decay to prevent density buildup
|
||||||
|
for (let i = 0; i < state.size; i++) {
|
||||||
|
state.density[i] *= 0.995;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderDensity(render, state.density, gridWidth, gridHeight);
|
||||||
|
rafRef.current = requestAnimationFrame(animate);
|
||||||
|
}, [gridWidth, gridHeight, dt, diffusion, viscosity, iterations]);
|
||||||
|
|
||||||
|
// Pointer interaction: convert screen coords to grid coords
|
||||||
|
const handlePointerMove = useCallback(
|
||||||
|
(e: PointerEvent) => {
|
||||||
|
const state = stateRef.current;
|
||||||
|
const pre = preRef.current;
|
||||||
|
if (!state || !pre || !pointerDownRef.current) return;
|
||||||
|
|
||||||
|
const rect = pre.getBoundingClientRect();
|
||||||
|
const rx = (e.clientX - rect.left) / rect.width;
|
||||||
|
const ry = (e.clientY - rect.top) / rect.height;
|
||||||
|
|
||||||
|
const gx = Math.floor(rx * gridWidth) + 1;
|
||||||
|
const gy = Math.floor(ry * gridHeight) + 1;
|
||||||
|
|
||||||
|
if (gx < 1 || gx > gridWidth || gy < 1 || gy > gridHeight) return;
|
||||||
|
|
||||||
|
addSource(state, gx, gy, 0.6, 3);
|
||||||
|
|
||||||
|
if (lastPointerRef.current) {
|
||||||
|
const dx = (e.clientX - lastPointerRef.current.x) * 0.3;
|
||||||
|
const dy = (e.clientY - lastPointerRef.current.y) * 0.3;
|
||||||
|
addVelocity(state, gx, gy, dx, dy, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPointerRef.current = { x: e.clientX, y: e.clientY };
|
||||||
|
},
|
||||||
|
[preRef, gridWidth, gridHeight]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handlePointerDown = useCallback((e: PointerEvent) => {
|
||||||
|
pointerDownRef.current = true;
|
||||||
|
lastPointerRef.current = { x: e.clientX, y: e.clientY };
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handlePointerUp = useCallback(() => {
|
||||||
|
pointerDownRef.current = false;
|
||||||
|
lastPointerRef.current = null;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleKeyDown = useCallback(
|
||||||
|
(e: KeyboardEvent) => {
|
||||||
|
if (e.code === "Space") {
|
||||||
|
e.preventDefault();
|
||||||
|
faucetRef.current = !faucetRef.current;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
|
||||||
|
const handleDblClick = useCallback(() => {
|
||||||
|
if (stateRef.current) {
|
||||||
|
clearState(stateRef.current);
|
||||||
|
}
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
init();
|
||||||
|
|
||||||
|
const pre = preRef.current;
|
||||||
|
if (!pre) return;
|
||||||
|
|
||||||
|
// Start animation
|
||||||
|
rafRef.current = requestAnimationFrame(animate);
|
||||||
|
|
||||||
|
// Event listeners
|
||||||
|
pre.addEventListener("pointermove", handlePointerMove);
|
||||||
|
pre.addEventListener("pointerdown", handlePointerDown);
|
||||||
|
pre.addEventListener("pointerup", handlePointerUp);
|
||||||
|
pre.addEventListener("pointerleave", handlePointerUp);
|
||||||
|
pre.addEventListener("dblclick", handleDblClick);
|
||||||
|
window.addEventListener("keydown", handleKeyDown);
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
cancelAnimationFrame(rafRef.current);
|
||||||
|
pre.removeEventListener("pointermove", handlePointerMove);
|
||||||
|
pre.removeEventListener("pointerdown", handlePointerDown);
|
||||||
|
pre.removeEventListener("pointerup", handlePointerUp);
|
||||||
|
pre.removeEventListener("pointerleave", handlePointerUp);
|
||||||
|
pre.removeEventListener("dblclick", handleDblClick);
|
||||||
|
window.removeEventListener("keydown", handleKeyDown);
|
||||||
|
};
|
||||||
|
}, [
|
||||||
|
init,
|
||||||
|
animate,
|
||||||
|
handlePointerMove,
|
||||||
|
handlePointerDown,
|
||||||
|
handlePointerUp,
|
||||||
|
handleKeyDown,
|
||||||
|
handleDblClick,
|
||||||
|
preRef,
|
||||||
|
]);
|
||||||
|
|
||||||
|
return {
|
||||||
|
toggleFaucet: () => {
|
||||||
|
faucetRef.current = !faucetRef.current;
|
||||||
|
},
|
||||||
|
clear: () => {
|
||||||
|
if (stateRef.current) clearState(stateRef.current);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,12 @@
|
||||||
|
"use client";
|
||||||
|
|
||||||
|
import dynamic from "next/dynamic";
|
||||||
|
|
||||||
|
const FluidSimulation = dynamic(
|
||||||
|
() => import("@/components/FluidSimulation"),
|
||||||
|
{ ssr: false }
|
||||||
|
);
|
||||||
|
|
||||||
|
export default function FluidSimulationLoader() {
|
||||||
|
return <FluidSimulation />;
|
||||||
|
}
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
import { ExternalLink } from "lucide-react";
|
|
||||||
|
|
||||||
const Header = () => {
|
|
||||||
return (
|
|
||||||
<header className="border-b border-border py-10 md:py-12">
|
|
||||||
<div className="container max-w-[1920px] mx-auto px-6 md:px-8 lg:px-12">
|
|
||||||
<div className="grid grid-cols-1 lg:grid-cols-[1fr_auto] gap-8 lg:gap-12 items-end">
|
|
||||||
{/* Left Side: Photo + Title + Bio */}
|
|
||||||
<div className="space-y-6">
|
|
||||||
{/* Photo + Name/Title */}
|
|
||||||
<div className="flex flex-row gap-6 items-center">
|
|
||||||
<img
|
|
||||||
src="/kamil-banc.jpg"
|
|
||||||
alt="Kamil Banc"
|
|
||||||
className="w-24 h-24 md:w-32 md:h-32 rounded-lg object-cover flex-shrink-0"
|
|
||||||
/>
|
|
||||||
<div>
|
|
||||||
<h1 className="text-4xl md:text-5xl font-bold mb-2">Kamil Banc</h1>
|
|
||||||
<p className="text-xl text-secondary">AI Implementation Expert</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Bio Text */}
|
|
||||||
<div className="space-y-4">
|
|
||||||
<p className="text-base leading-relaxed">
|
|
||||||
I help organizations implement AI systems that actually work. I focus on real implementations that generate measurable value, not theoretical frameworks or vendor pitches.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p className="text-base leading-relaxed">
|
|
||||||
My work focuses on practical adoption patterns: what works, what fails, and why. I document implementation frameworks, measure outcomes, and share findings through the AI Adopters Club community.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p className="text-base leading-relaxed">
|
|
||||||
This library contains citation-ready claims from my research and consulting work. Each claim is backed by data, includes context, and is optimized for LLM extraction.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{/* Right Side: Premium CTA + Links */}
|
|
||||||
<div className="border border-border rounded-lg p-6 lg:w-80 flex-shrink-0 space-y-4">
|
|
||||||
<div>
|
|
||||||
<p className="text-sm text-muted-foreground mb-4">
|
|
||||||
Get access to enterprise case studies, premium workflows, and our AI chatbot trained on all assets.
|
|
||||||
</p>
|
|
||||||
<a
|
|
||||||
href="https://aiadopters.club/subscribe"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="bg-accent hover:bg-accent/90 text-accent-foreground font-medium px-4 py-2 rounded-lg transition-colors whitespace-nowrap text-center inline-flex items-center justify-center gap-2 w-full text-sm"
|
|
||||||
>
|
|
||||||
Unlock Premium
|
|
||||||
<ExternalLink className="h-3 w-3" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div className="flex flex-col gap-2 pt-2 border-t border-border">
|
|
||||||
<a
|
|
||||||
href="https://www.linkedin.com/in/kbanc/"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-accent hover:underline inline-flex items-center gap-1 text-sm"
|
|
||||||
>
|
|
||||||
LinkedIn <ExternalLink className="h-3 w-3" />
|
|
||||||
</a>
|
|
||||||
<a
|
|
||||||
href="https://aiadopters.club"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
className="text-accent hover:underline inline-flex items-center gap-1 text-sm"
|
|
||||||
>
|
|
||||||
AI Adopters Club <ExternalLink className="h-3 w-3" />
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</header>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default Header;
|
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
import Link from "next/link";
|
||||||
|
import { ALL_CLAIMS_DATA, type ClaimData } from "@/data/claims";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds 2-3 related claims by shared topics.
|
||||||
|
* Computed at build time (static generation).
|
||||||
|
*/
|
||||||
|
function getRelatedClaims(currentSlug: string, limit = 3): ClaimData[] {
|
||||||
|
const current = ALL_CLAIMS_DATA.find((c) => c.slug === currentSlug);
|
||||||
|
if (!current) return [];
|
||||||
|
|
||||||
|
const currentTopicIds = new Set(current.topics.map((t) => t.id));
|
||||||
|
|
||||||
|
const scored = ALL_CLAIMS_DATA
|
||||||
|
.filter((c) => c.slug !== currentSlug)
|
||||||
|
.map((c) => {
|
||||||
|
const sharedTopics = c.topics.filter((t) => currentTopicIds.has(t.id));
|
||||||
|
return { claim: c, score: sharedTopics.length };
|
||||||
|
})
|
||||||
|
.filter((s) => s.score > 0)
|
||||||
|
.sort((a, b) => b.score - a.score);
|
||||||
|
|
||||||
|
return scored.slice(0, limit).map((s) => s.claim);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RelatedClaims({ currentSlug }: { currentSlug: string }) {
|
||||||
|
const related = getRelatedClaims(currentSlug);
|
||||||
|
if (related.length === 0) return null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<section className="terminal-panel mt-8">
|
||||||
|
<h2 className="terminal-prompt text-foreground font-bold text-sm mb-4">
|
||||||
|
ls related/
|
||||||
|
</h2>
|
||||||
|
<div className="space-y-3">
|
||||||
|
{related.map((claim) => (
|
||||||
|
<div key={claim.slug} className="border-l border-border pl-4">
|
||||||
|
<Link
|
||||||
|
href={`/claims-library/${claim.slug}`}
|
||||||
|
className="text-terminal-cyan hover:underline text-sm"
|
||||||
|
>
|
||||||
|
{claim.title}
|
||||||
|
</Link>
|
||||||
|
<div className="flex gap-2 mt-1">
|
||||||
|
{claim.topics.map((t) => (
|
||||||
|
<span key={t.id} className="terminal-tag">
|
||||||
|
{t.id}
|
||||||
|
</span>
|
||||||
|
))}
|
||||||
|
<span className="text-terminal-dim text-xs">
|
||||||
|
{claim.claims.length} claims
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
export default function TerminalChrome({
|
||||||
|
title = "kbanc.com - bash",
|
||||||
|
children,
|
||||||
|
}: {
|
||||||
|
title?: string;
|
||||||
|
children: React.ReactNode;
|
||||||
|
}) {
|
||||||
|
return (
|
||||||
|
<div className="border border-border bg-background w-full max-w-4xl mx-auto">
|
||||||
|
{/* Window bar - decorative only */}
|
||||||
|
<div className="terminal-chrome" aria-hidden="true">
|
||||||
|
<span className="terminal-chrome-dot terminal-chrome-dot--close" />
|
||||||
|
<span className="terminal-chrome-dot terminal-chrome-dot--minimize" />
|
||||||
|
<span className="terminal-chrome-dot terminal-chrome-dot--maximize" />
|
||||||
|
<span className="ml-4 text-xs text-terminal-dim">{title}</span>
|
||||||
|
</div>
|
||||||
|
{/* Terminal content */}
|
||||||
|
<div className="p-6 md:p-8">{children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,45 @@
|
||||||
|
import Link from "next/link";
|
||||||
|
|
||||||
|
export default function TerminalFooter() {
|
||||||
|
return (
|
||||||
|
<footer className="border-t border-border mt-12 pt-6 pb-8">
|
||||||
|
<div className="max-w-4xl mx-auto px-6">
|
||||||
|
<nav
|
||||||
|
className="flex flex-wrap gap-3 mb-4 terminal-nav text-sm"
|
||||||
|
aria-label="Footer navigation"
|
||||||
|
>
|
||||||
|
<Link href="/">[home]</Link>
|
||||||
|
<Link href="/claims-library">[claims]</Link>
|
||||||
|
<Link href="/about">[about]</Link>
|
||||||
|
<Link href="/faq">[faq]</Link>
|
||||||
|
<Link href="/how-i-built-this">[how-i-built-this]</Link>
|
||||||
|
</nav>
|
||||||
|
<div className="text-xs text-terminal-dim space-y-1">
|
||||||
|
<p>
|
||||||
|
Content licensed under{" "}
|
||||||
|
<a
|
||||||
|
href="https://creativecommons.org/licenses/by/4.0/"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
CC BY 4.0
|
||||||
|
</a>
|
||||||
|
{" "}by Kamil Banc
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Source:{" "}
|
||||||
|
<a
|
||||||
|
href="https://aiadopters.club"
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener"
|
||||||
|
className="text-terminal-cyan hover:underline"
|
||||||
|
>
|
||||||
|
AI Adopters Club
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</footer>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,52 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import * as AccordionPrimitive from "@radix-ui/react-accordion";
|
|
||||||
import { ChevronDown } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const Accordion = AccordionPrimitive.Root;
|
|
||||||
|
|
||||||
const AccordionItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof AccordionPrimitive.Item>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<AccordionPrimitive.Item ref={ref} className={cn("border-b", className)} {...props} />
|
|
||||||
));
|
|
||||||
AccordionItem.displayName = "AccordionItem";
|
|
||||||
|
|
||||||
const AccordionTrigger = React.forwardRef<
|
|
||||||
React.ElementRef<typeof AccordionPrimitive.Trigger>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<AccordionPrimitive.Header className="flex">
|
|
||||||
<AccordionPrimitive.Trigger
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
<ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
|
|
||||||
</AccordionPrimitive.Trigger>
|
|
||||||
</AccordionPrimitive.Header>
|
|
||||||
));
|
|
||||||
AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName;
|
|
||||||
|
|
||||||
const AccordionContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof AccordionPrimitive.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<AccordionPrimitive.Content
|
|
||||||
ref={ref}
|
|
||||||
className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<div className={cn("pb-4 pt-0", className)}>{children}</div>
|
|
||||||
</AccordionPrimitive.Content>
|
|
||||||
));
|
|
||||||
|
|
||||||
AccordionContent.displayName = AccordionPrimitive.Content.displayName;
|
|
||||||
|
|
||||||
export { Accordion, AccordionItem, AccordionTrigger, AccordionContent };
|
|
||||||
|
|
@ -1,90 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import { Slot } from "@radix-ui/react-slot";
|
|
||||||
import { ChevronRight, MoreHorizontal } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const Breadcrumb = React.forwardRef<
|
|
||||||
HTMLElement,
|
|
||||||
React.ComponentPropsWithoutRef<"nav"> & {
|
|
||||||
separator?: React.ReactNode;
|
|
||||||
}
|
|
||||||
>(({ ...props }, ref) => <nav ref={ref} aria-label="breadcrumb" {...props} />);
|
|
||||||
Breadcrumb.displayName = "Breadcrumb";
|
|
||||||
|
|
||||||
const BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<"ol">>(
|
|
||||||
({ className, ...props }, ref) => (
|
|
||||||
<ol
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex flex-wrap items-center gap-1.5 break-words text-sm text-muted-foreground sm:gap-2.5",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
);
|
|
||||||
BreadcrumbList.displayName = "BreadcrumbList";
|
|
||||||
|
|
||||||
const BreadcrumbItem = React.forwardRef<HTMLLIElement, React.ComponentPropsWithoutRef<"li">>(
|
|
||||||
({ className, ...props }, ref) => (
|
|
||||||
<li ref={ref} className={cn("inline-flex items-center gap-1.5", className)} {...props} />
|
|
||||||
),
|
|
||||||
);
|
|
||||||
BreadcrumbItem.displayName = "BreadcrumbItem";
|
|
||||||
|
|
||||||
const BreadcrumbLink = React.forwardRef<
|
|
||||||
HTMLAnchorElement,
|
|
||||||
React.ComponentPropsWithoutRef<"a"> & {
|
|
||||||
asChild?: boolean;
|
|
||||||
}
|
|
||||||
>(({ asChild, className, ...props }, ref) => {
|
|
||||||
const Comp = asChild ? Slot : "a";
|
|
||||||
|
|
||||||
return <Comp ref={ref} className={cn("transition-colors hover:text-foreground", className)} {...props} />;
|
|
||||||
});
|
|
||||||
BreadcrumbLink.displayName = "BreadcrumbLink";
|
|
||||||
|
|
||||||
const BreadcrumbPage = React.forwardRef<HTMLSpanElement, React.ComponentPropsWithoutRef<"span">>(
|
|
||||||
({ className, ...props }, ref) => (
|
|
||||||
<span
|
|
||||||
ref={ref}
|
|
||||||
role="link"
|
|
||||||
aria-disabled="true"
|
|
||||||
aria-current="page"
|
|
||||||
className={cn("font-normal text-foreground", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
);
|
|
||||||
BreadcrumbPage.displayName = "BreadcrumbPage";
|
|
||||||
|
|
||||||
const BreadcrumbSeparator = ({ children, className, ...props }: React.ComponentProps<"li">) => (
|
|
||||||
<li role="presentation" aria-hidden="true" className={cn("[&>svg]:size-3.5", className)} {...props}>
|
|
||||||
{children ?? <ChevronRight />}
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
BreadcrumbSeparator.displayName = "BreadcrumbSeparator";
|
|
||||||
|
|
||||||
const BreadcrumbEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => (
|
|
||||||
<span
|
|
||||||
role="presentation"
|
|
||||||
aria-hidden="true"
|
|
||||||
className={cn("flex h-9 w-9 items-center justify-center", className)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<MoreHorizontal className="h-4 w-4" />
|
|
||||||
<span className="sr-only">More</span>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
BreadcrumbEllipsis.displayName = "BreadcrumbElipssis";
|
|
||||||
|
|
||||||
export {
|
|
||||||
Breadcrumb,
|
|
||||||
BreadcrumbList,
|
|
||||||
BreadcrumbItem,
|
|
||||||
BreadcrumbLink,
|
|
||||||
BreadcrumbPage,
|
|
||||||
BreadcrumbSeparator,
|
|
||||||
BreadcrumbEllipsis,
|
|
||||||
};
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import * as CheckboxPrimitive from "@radix-ui/react-checkbox";
|
|
||||||
import { Check } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const Checkbox = React.forwardRef<
|
|
||||||
React.ElementRef<typeof CheckboxPrimitive.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof CheckboxPrimitive.Root>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<CheckboxPrimitive.Root
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"peer h-4 w-4 shrink-0 rounded-sm border border-primary ring-offset-background data-[state=checked]:bg-primary data-[state=checked]:text-primary-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<CheckboxPrimitive.Indicator className={cn("flex items-center justify-center text-current")}>
|
|
||||||
<Check className="h-4 w-4" />
|
|
||||||
</CheckboxPrimitive.Indicator>
|
|
||||||
</CheckboxPrimitive.Root>
|
|
||||||
));
|
|
||||||
Checkbox.displayName = CheckboxPrimitive.Root.displayName;
|
|
||||||
|
|
||||||
export { Checkbox };
|
|
||||||
|
|
@ -1,132 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import { type DialogProps } from "@radix-ui/react-dialog";
|
|
||||||
import { Command as CommandPrimitive } from "cmdk";
|
|
||||||
import { Search } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import { Dialog, DialogContent } from "@/components/ui/dialog";
|
|
||||||
|
|
||||||
const Command = React.forwardRef<
|
|
||||||
React.ElementRef<typeof CommandPrimitive>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<CommandPrimitive
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex h-full w-full flex-col overflow-hidden rounded-md bg-popover text-popover-foreground",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
Command.displayName = CommandPrimitive.displayName;
|
|
||||||
|
|
||||||
interface CommandDialogProps extends DialogProps {}
|
|
||||||
|
|
||||||
const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
|
|
||||||
return (
|
|
||||||
<Dialog {...props}>
|
|
||||||
<DialogContent className="overflow-hidden p-0 shadow-lg">
|
|
||||||
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
|
|
||||||
{children}
|
|
||||||
</Command>
|
|
||||||
</DialogContent>
|
|
||||||
</Dialog>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const CommandInput = React.forwardRef<
|
|
||||||
React.ElementRef<typeof CommandPrimitive.Input>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<div className="flex items-center border-b px-3" cmdk-input-wrapper="">
|
|
||||||
<Search className="mr-2 h-4 w-4 shrink-0 opacity-50" />
|
|
||||||
<CommandPrimitive.Input
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
));
|
|
||||||
|
|
||||||
CommandInput.displayName = CommandPrimitive.Input.displayName;
|
|
||||||
|
|
||||||
const CommandList = React.forwardRef<
|
|
||||||
React.ElementRef<typeof CommandPrimitive.List>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<CommandPrimitive.List
|
|
||||||
ref={ref}
|
|
||||||
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
|
|
||||||
CommandList.displayName = CommandPrimitive.List.displayName;
|
|
||||||
|
|
||||||
const CommandEmpty = React.forwardRef<
|
|
||||||
React.ElementRef<typeof CommandPrimitive.Empty>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty>
|
|
||||||
>((props, ref) => <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />);
|
|
||||||
|
|
||||||
CommandEmpty.displayName = CommandPrimitive.Empty.displayName;
|
|
||||||
|
|
||||||
const CommandGroup = React.forwardRef<
|
|
||||||
React.ElementRef<typeof CommandPrimitive.Group>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<CommandPrimitive.Group
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
|
|
||||||
CommandGroup.displayName = CommandPrimitive.Group.displayName;
|
|
||||||
|
|
||||||
const CommandSeparator = React.forwardRef<
|
|
||||||
React.ElementRef<typeof CommandPrimitive.Separator>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<CommandPrimitive.Separator ref={ref} className={cn("-mx-1 h-px bg-border", className)} {...props} />
|
|
||||||
));
|
|
||||||
CommandSeparator.displayName = CommandPrimitive.Separator.displayName;
|
|
||||||
|
|
||||||
const CommandItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof CommandPrimitive.Item>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<CommandPrimitive.Item
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled=true]:pointer-events-none data-[selected='true']:bg-accent data-[selected=true]:text-accent-foreground data-[disabled=true]:opacity-50",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
|
|
||||||
CommandItem.displayName = CommandPrimitive.Item.displayName;
|
|
||||||
|
|
||||||
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
||||||
return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} />;
|
|
||||||
};
|
|
||||||
CommandShortcut.displayName = "CommandShortcut";
|
|
||||||
|
|
||||||
export {
|
|
||||||
Command,
|
|
||||||
CommandDialog,
|
|
||||||
CommandInput,
|
|
||||||
CommandList,
|
|
||||||
CommandEmpty,
|
|
||||||
CommandGroup,
|
|
||||||
CommandItem,
|
|
||||||
CommandShortcut,
|
|
||||||
CommandSeparator,
|
|
||||||
};
|
|
||||||
|
|
@ -1,178 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import * as ContextMenuPrimitive from "@radix-ui/react-context-menu";
|
|
||||||
import { Check, ChevronRight, Circle } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const ContextMenu = ContextMenuPrimitive.Root;
|
|
||||||
|
|
||||||
const ContextMenuTrigger = ContextMenuPrimitive.Trigger;
|
|
||||||
|
|
||||||
const ContextMenuGroup = ContextMenuPrimitive.Group;
|
|
||||||
|
|
||||||
const ContextMenuPortal = ContextMenuPrimitive.Portal;
|
|
||||||
|
|
||||||
const ContextMenuSub = ContextMenuPrimitive.Sub;
|
|
||||||
|
|
||||||
const ContextMenuRadioGroup = ContextMenuPrimitive.RadioGroup;
|
|
||||||
|
|
||||||
const ContextMenuSubTrigger = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ContextMenuPrimitive.SubTrigger>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubTrigger> & {
|
|
||||||
inset?: boolean;
|
|
||||||
}
|
|
||||||
>(({ className, inset, children, ...props }, ref) => (
|
|
||||||
<ContextMenuPrimitive.SubTrigger
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[state=open]:bg-accent data-[state=open]:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
|
|
||||||
inset && "pl-8",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
<ChevronRight className="ml-auto h-4 w-4" />
|
|
||||||
</ContextMenuPrimitive.SubTrigger>
|
|
||||||
));
|
|
||||||
ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
|
|
||||||
|
|
||||||
const ContextMenuSubContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ContextMenuPrimitive.SubContent>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.SubContent>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<ContextMenuPrimitive.SubContent
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
|
|
||||||
|
|
||||||
const ContextMenuContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ContextMenuPrimitive.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Content>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<ContextMenuPrimitive.Portal>
|
|
||||||
<ContextMenuPrimitive.Content
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md animate-in fade-in-80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
</ContextMenuPrimitive.Portal>
|
|
||||||
));
|
|
||||||
ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
|
|
||||||
|
|
||||||
const ContextMenuItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ContextMenuPrimitive.Item>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Item> & {
|
|
||||||
inset?: boolean;
|
|
||||||
}
|
|
||||||
>(({ className, inset, ...props }, ref) => (
|
|
||||||
<ContextMenuPrimitive.Item
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
|
|
||||||
inset && "pl-8",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
|
|
||||||
|
|
||||||
const ContextMenuCheckboxItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ContextMenuPrimitive.CheckboxItem>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.CheckboxItem>
|
|
||||||
>(({ className, children, checked, ...props }, ref) => (
|
|
||||||
<ContextMenuPrimitive.CheckboxItem
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
checked={checked}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
||||||
<ContextMenuPrimitive.ItemIndicator>
|
|
||||||
<Check className="h-4 w-4" />
|
|
||||||
</ContextMenuPrimitive.ItemIndicator>
|
|
||||||
</span>
|
|
||||||
{children}
|
|
||||||
</ContextMenuPrimitive.CheckboxItem>
|
|
||||||
));
|
|
||||||
ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;
|
|
||||||
|
|
||||||
const ContextMenuRadioItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ContextMenuPrimitive.RadioItem>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.RadioItem>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<ContextMenuPrimitive.RadioItem
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
||||||
<ContextMenuPrimitive.ItemIndicator>
|
|
||||||
<Circle className="h-2 w-2 fill-current" />
|
|
||||||
</ContextMenuPrimitive.ItemIndicator>
|
|
||||||
</span>
|
|
||||||
{children}
|
|
||||||
</ContextMenuPrimitive.RadioItem>
|
|
||||||
));
|
|
||||||
ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
|
|
||||||
|
|
||||||
const ContextMenuLabel = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ContextMenuPrimitive.Label>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Label> & {
|
|
||||||
inset?: boolean;
|
|
||||||
}
|
|
||||||
>(({ className, inset, ...props }, ref) => (
|
|
||||||
<ContextMenuPrimitive.Label
|
|
||||||
ref={ref}
|
|
||||||
className={cn("px-2 py-1.5 text-sm font-semibold text-foreground", inset && "pl-8", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
|
|
||||||
|
|
||||||
const ContextMenuSeparator = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ContextMenuPrimitive.Separator>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ContextMenuPrimitive.Separator>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<ContextMenuPrimitive.Separator ref={ref} className={cn("-mx-1 my-1 h-px bg-border", className)} {...props} />
|
|
||||||
));
|
|
||||||
ContextMenuSeparator.displayName = ContextMenuPrimitive.Separator.displayName;
|
|
||||||
|
|
||||||
const ContextMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
||||||
return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} />;
|
|
||||||
};
|
|
||||||
ContextMenuShortcut.displayName = "ContextMenuShortcut";
|
|
||||||
|
|
||||||
export {
|
|
||||||
ContextMenu,
|
|
||||||
ContextMenuTrigger,
|
|
||||||
ContextMenuContent,
|
|
||||||
ContextMenuItem,
|
|
||||||
ContextMenuCheckboxItem,
|
|
||||||
ContextMenuRadioItem,
|
|
||||||
ContextMenuLabel,
|
|
||||||
ContextMenuSeparator,
|
|
||||||
ContextMenuShortcut,
|
|
||||||
ContextMenuGroup,
|
|
||||||
ContextMenuPortal,
|
|
||||||
ContextMenuSub,
|
|
||||||
ContextMenuSubContent,
|
|
||||||
ContextMenuSubTrigger,
|
|
||||||
ContextMenuRadioGroup,
|
|
||||||
};
|
|
||||||
|
|
@ -1,95 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import * as DialogPrimitive from "@radix-ui/react-dialog";
|
|
||||||
import { X } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const Dialog = DialogPrimitive.Root;
|
|
||||||
|
|
||||||
const DialogTrigger = DialogPrimitive.Trigger;
|
|
||||||
|
|
||||||
const DialogPortal = DialogPrimitive.Portal;
|
|
||||||
|
|
||||||
const DialogClose = DialogPrimitive.Close;
|
|
||||||
|
|
||||||
const DialogOverlay = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DialogPrimitive.Overlay>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<DialogPrimitive.Overlay
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
||||||
|
|
||||||
const DialogContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DialogPrimitive.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<DialogPortal>
|
|
||||||
<DialogOverlay />
|
|
||||||
<DialogPrimitive.Content
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity data-[state=open]:bg-accent data-[state=open]:text-muted-foreground hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none">
|
|
||||||
<X className="h-4 w-4" />
|
|
||||||
<span className="sr-only">Close</span>
|
|
||||||
</DialogPrimitive.Close>
|
|
||||||
</DialogPrimitive.Content>
|
|
||||||
</DialogPortal>
|
|
||||||
));
|
|
||||||
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
||||||
|
|
||||||
const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
||||||
<div className={cn("flex flex-col space-y-1.5 text-center sm:text-left", className)} {...props} />
|
|
||||||
);
|
|
||||||
DialogHeader.displayName = "DialogHeader";
|
|
||||||
|
|
||||||
const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
||||||
<div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} />
|
|
||||||
);
|
|
||||||
DialogFooter.displayName = "DialogFooter";
|
|
||||||
|
|
||||||
const DialogTitle = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DialogPrimitive.Title>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<DialogPrimitive.Title
|
|
||||||
ref={ref}
|
|
||||||
className={cn("text-lg font-semibold leading-none tracking-tight", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
||||||
|
|
||||||
const DialogDescription = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DialogPrimitive.Description>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<DialogPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
|
|
||||||
));
|
|
||||||
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
||||||
|
|
||||||
export {
|
|
||||||
Dialog,
|
|
||||||
DialogPortal,
|
|
||||||
DialogOverlay,
|
|
||||||
DialogClose,
|
|
||||||
DialogTrigger,
|
|
||||||
DialogContent,
|
|
||||||
DialogHeader,
|
|
||||||
DialogFooter,
|
|
||||||
DialogTitle,
|
|
||||||
DialogDescription,
|
|
||||||
};
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import * as DropdownMenuPrimitive from "@radix-ui/react-dropdown-menu";
|
|
||||||
import { Check, ChevronRight, Circle } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const DropdownMenu = DropdownMenuPrimitive.Root;
|
|
||||||
|
|
||||||
const DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
|
|
||||||
|
|
||||||
const DropdownMenuGroup = DropdownMenuPrimitive.Group;
|
|
||||||
|
|
||||||
const DropdownMenuPortal = DropdownMenuPrimitive.Portal;
|
|
||||||
|
|
||||||
const DropdownMenuSub = DropdownMenuPrimitive.Sub;
|
|
||||||
|
|
||||||
const DropdownMenuRadioGroup = DropdownMenuPrimitive.RadioGroup;
|
|
||||||
|
|
||||||
const DropdownMenuSubTrigger = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {
|
|
||||||
inset?: boolean;
|
|
||||||
}
|
|
||||||
>(({ className, inset, children, ...props }, ref) => (
|
|
||||||
<DropdownMenuPrimitive.SubTrigger
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[state=open]:bg-accent focus:bg-accent",
|
|
||||||
inset && "pl-8",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
<ChevronRight className="ml-auto h-4 w-4" />
|
|
||||||
</DropdownMenuPrimitive.SubTrigger>
|
|
||||||
));
|
|
||||||
DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
|
|
||||||
|
|
||||||
const DropdownMenuSubContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<DropdownMenuPrimitive.SubContent
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
|
|
||||||
|
|
||||||
const DropdownMenuContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>
|
|
||||||
>(({ className, sideOffset = 4, ...props }, ref) => (
|
|
||||||
<DropdownMenuPrimitive.Portal>
|
|
||||||
<DropdownMenuPrimitive.Content
|
|
||||||
ref={ref}
|
|
||||||
sideOffset={sideOffset}
|
|
||||||
className={cn(
|
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
</DropdownMenuPrimitive.Portal>
|
|
||||||
));
|
|
||||||
DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
|
|
||||||
|
|
||||||
const DropdownMenuItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.Item>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
|
|
||||||
inset?: boolean;
|
|
||||||
}
|
|
||||||
>(({ className, inset, ...props }, ref) => (
|
|
||||||
<DropdownMenuPrimitive.Item
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
|
|
||||||
inset && "pl-8",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
|
|
||||||
|
|
||||||
const DropdownMenuCheckboxItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
|
|
||||||
>(({ className, children, checked, ...props }, ref) => (
|
|
||||||
<DropdownMenuPrimitive.CheckboxItem
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
checked={checked}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
||||||
<DropdownMenuPrimitive.ItemIndicator>
|
|
||||||
<Check className="h-4 w-4" />
|
|
||||||
</DropdownMenuPrimitive.ItemIndicator>
|
|
||||||
</span>
|
|
||||||
{children}
|
|
||||||
</DropdownMenuPrimitive.CheckboxItem>
|
|
||||||
));
|
|
||||||
DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
|
|
||||||
|
|
||||||
const DropdownMenuRadioItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<DropdownMenuPrimitive.RadioItem
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none transition-colors data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
||||||
<DropdownMenuPrimitive.ItemIndicator>
|
|
||||||
<Circle className="h-2 w-2 fill-current" />
|
|
||||||
</DropdownMenuPrimitive.ItemIndicator>
|
|
||||||
</span>
|
|
||||||
{children}
|
|
||||||
</DropdownMenuPrimitive.RadioItem>
|
|
||||||
));
|
|
||||||
DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
|
|
||||||
|
|
||||||
const DropdownMenuLabel = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.Label>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {
|
|
||||||
inset?: boolean;
|
|
||||||
}
|
|
||||||
>(({ className, inset, ...props }, ref) => (
|
|
||||||
<DropdownMenuPrimitive.Label
|
|
||||||
ref={ref}
|
|
||||||
className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
|
|
||||||
|
|
||||||
const DropdownMenuSeparator = React.forwardRef<
|
|
||||||
React.ElementRef<typeof DropdownMenuPrimitive.Separator>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<DropdownMenuPrimitive.Separator ref={ref} className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} />
|
|
||||||
));
|
|
||||||
DropdownMenuSeparator.displayName = DropdownMenuPrimitive.Separator.displayName;
|
|
||||||
|
|
||||||
const DropdownMenuShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
||||||
return <span className={cn("ml-auto text-xs tracking-widest opacity-60", className)} {...props} />;
|
|
||||||
};
|
|
||||||
DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
|
|
||||||
|
|
||||||
export {
|
|
||||||
DropdownMenu,
|
|
||||||
DropdownMenuTrigger,
|
|
||||||
DropdownMenuContent,
|
|
||||||
DropdownMenuItem,
|
|
||||||
DropdownMenuCheckboxItem,
|
|
||||||
DropdownMenuRadioItem,
|
|
||||||
DropdownMenuLabel,
|
|
||||||
DropdownMenuSeparator,
|
|
||||||
DropdownMenuShortcut,
|
|
||||||
DropdownMenuGroup,
|
|
||||||
DropdownMenuPortal,
|
|
||||||
DropdownMenuSub,
|
|
||||||
DropdownMenuSubContent,
|
|
||||||
DropdownMenuSubTrigger,
|
|
||||||
DropdownMenuRadioGroup,
|
|
||||||
};
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import * as LabelPrimitive from "@radix-ui/react-label";
|
|
||||||
import { Slot } from "@radix-ui/react-slot";
|
|
||||||
import { Controller, ControllerProps, FieldPath, FieldValues, FormProvider, useFormContext } from "react-hook-form";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import { Label } from "@/components/ui/label";
|
|
||||||
|
|
||||||
const Form = FormProvider;
|
|
||||||
|
|
||||||
type FormFieldContextValue<
|
|
||||||
TFieldValues extends FieldValues = FieldValues,
|
|
||||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
|
||||||
> = {
|
|
||||||
name: TName;
|
|
||||||
};
|
|
||||||
|
|
||||||
const FormFieldContext = React.createContext<FormFieldContextValue>({} as FormFieldContextValue);
|
|
||||||
|
|
||||||
const FormField = <
|
|
||||||
TFieldValues extends FieldValues = FieldValues,
|
|
||||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>,
|
|
||||||
>({
|
|
||||||
...props
|
|
||||||
}: ControllerProps<TFieldValues, TName>) => {
|
|
||||||
return (
|
|
||||||
<FormFieldContext.Provider value={{ name: props.name }}>
|
|
||||||
<Controller {...props} />
|
|
||||||
</FormFieldContext.Provider>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
const useFormField = () => {
|
|
||||||
const fieldContext = React.useContext(FormFieldContext);
|
|
||||||
const itemContext = React.useContext(FormItemContext);
|
|
||||||
const { getFieldState, formState } = useFormContext();
|
|
||||||
|
|
||||||
const fieldState = getFieldState(fieldContext.name, formState);
|
|
||||||
|
|
||||||
if (!fieldContext) {
|
|
||||||
throw new Error("useFormField should be used within <FormField>");
|
|
||||||
}
|
|
||||||
|
|
||||||
const { id } = itemContext;
|
|
||||||
|
|
||||||
return {
|
|
||||||
id,
|
|
||||||
name: fieldContext.name,
|
|
||||||
formItemId: `${id}-form-item`,
|
|
||||||
formDescriptionId: `${id}-form-item-description`,
|
|
||||||
formMessageId: `${id}-form-item-message`,
|
|
||||||
...fieldState,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
type FormItemContextValue = {
|
|
||||||
id: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
const FormItemContext = React.createContext<FormItemContextValue>({} as FormItemContextValue);
|
|
||||||
|
|
||||||
const FormItem = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
||||||
({ className, ...props }, ref) => {
|
|
||||||
const id = React.useId();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<FormItemContext.Provider value={{ id }}>
|
|
||||||
<div ref={ref} className={cn("space-y-2", className)} {...props} />
|
|
||||||
</FormItemContext.Provider>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
FormItem.displayName = "FormItem";
|
|
||||||
|
|
||||||
const FormLabel = React.forwardRef<
|
|
||||||
React.ElementRef<typeof LabelPrimitive.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof LabelPrimitive.Root>
|
|
||||||
>(({ className, ...props }, ref) => {
|
|
||||||
const { error, formItemId } = useFormField();
|
|
||||||
|
|
||||||
return <Label ref={ref} className={cn(error && "text-destructive", className)} htmlFor={formItemId} {...props} />;
|
|
||||||
});
|
|
||||||
FormLabel.displayName = "FormLabel";
|
|
||||||
|
|
||||||
const FormControl = React.forwardRef<React.ElementRef<typeof Slot>, React.ComponentPropsWithoutRef<typeof Slot>>(
|
|
||||||
({ ...props }, ref) => {
|
|
||||||
const { error, formItemId, formDescriptionId, formMessageId } = useFormField();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Slot
|
|
||||||
ref={ref}
|
|
||||||
id={formItemId}
|
|
||||||
aria-describedby={!error ? `${formDescriptionId}` : `${formDescriptionId} ${formMessageId}`}
|
|
||||||
aria-invalid={!!error}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
FormControl.displayName = "FormControl";
|
|
||||||
|
|
||||||
const FormDescription = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
|
|
||||||
({ className, ...props }, ref) => {
|
|
||||||
const { formDescriptionId } = useFormField();
|
|
||||||
|
|
||||||
return <p ref={ref} id={formDescriptionId} className={cn("text-sm text-muted-foreground", className)} {...props} />;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
FormDescription.displayName = "FormDescription";
|
|
||||||
|
|
||||||
const FormMessage = React.forwardRef<HTMLParagraphElement, React.HTMLAttributes<HTMLParagraphElement>>(
|
|
||||||
({ className, children, ...props }, ref) => {
|
|
||||||
const { error, formMessageId } = useFormField();
|
|
||||||
const body = error ? String(error?.message) : children;
|
|
||||||
|
|
||||||
if (!body) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<p ref={ref} id={formMessageId} className={cn("text-sm font-medium text-destructive", className)} {...props}>
|
|
||||||
{body}
|
|
||||||
</p>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
FormMessage.displayName = "FormMessage";
|
|
||||||
|
|
||||||
export { useFormField, Form, FormItem, FormLabel, FormControl, FormDescription, FormMessage, FormField };
|
|
||||||
|
|
@ -1,207 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import * as MenubarPrimitive from "@radix-ui/react-menubar";
|
|
||||||
import { Check, ChevronRight, Circle } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const MenubarMenu = MenubarPrimitive.Menu;
|
|
||||||
|
|
||||||
const MenubarGroup = MenubarPrimitive.Group;
|
|
||||||
|
|
||||||
const MenubarPortal = MenubarPrimitive.Portal;
|
|
||||||
|
|
||||||
const MenubarSub = MenubarPrimitive.Sub;
|
|
||||||
|
|
||||||
const MenubarRadioGroup = MenubarPrimitive.RadioGroup;
|
|
||||||
|
|
||||||
const Menubar = React.forwardRef<
|
|
||||||
React.ElementRef<typeof MenubarPrimitive.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Root>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<MenubarPrimitive.Root
|
|
||||||
ref={ref}
|
|
||||||
className={cn("flex h-10 items-center space-x-1 rounded-md border bg-background p-1", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
Menubar.displayName = MenubarPrimitive.Root.displayName;
|
|
||||||
|
|
||||||
const MenubarTrigger = React.forwardRef<
|
|
||||||
React.ElementRef<typeof MenubarPrimitive.Trigger>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Trigger>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<MenubarPrimitive.Trigger
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex cursor-default select-none items-center rounded-sm px-3 py-1.5 text-sm font-medium outline-none data-[state=open]:bg-accent data-[state=open]:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;
|
|
||||||
|
|
||||||
const MenubarSubTrigger = React.forwardRef<
|
|
||||||
React.ElementRef<typeof MenubarPrimitive.SubTrigger>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubTrigger> & {
|
|
||||||
inset?: boolean;
|
|
||||||
}
|
|
||||||
>(({ className, inset, children, ...props }, ref) => (
|
|
||||||
<MenubarPrimitive.SubTrigger
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[state=open]:bg-accent data-[state=open]:text-accent-foreground focus:bg-accent focus:text-accent-foreground",
|
|
||||||
inset && "pl-8",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
<ChevronRight className="ml-auto h-4 w-4" />
|
|
||||||
</MenubarPrimitive.SubTrigger>
|
|
||||||
));
|
|
||||||
MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;
|
|
||||||
|
|
||||||
const MenubarSubContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof MenubarPrimitive.SubContent>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.SubContent>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<MenubarPrimitive.SubContent
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;
|
|
||||||
|
|
||||||
const MenubarContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof MenubarPrimitive.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Content>
|
|
||||||
>(({ className, align = "start", alignOffset = -4, sideOffset = 8, ...props }, ref) => (
|
|
||||||
<MenubarPrimitive.Portal>
|
|
||||||
<MenubarPrimitive.Content
|
|
||||||
ref={ref}
|
|
||||||
align={align}
|
|
||||||
alignOffset={alignOffset}
|
|
||||||
sideOffset={sideOffset}
|
|
||||||
className={cn(
|
|
||||||
"z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
</MenubarPrimitive.Portal>
|
|
||||||
));
|
|
||||||
MenubarContent.displayName = MenubarPrimitive.Content.displayName;
|
|
||||||
|
|
||||||
const MenubarItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof MenubarPrimitive.Item>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Item> & {
|
|
||||||
inset?: boolean;
|
|
||||||
}
|
|
||||||
>(({ className, inset, ...props }, ref) => (
|
|
||||||
<MenubarPrimitive.Item
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center rounded-sm px-2 py-1.5 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
|
|
||||||
inset && "pl-8",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
MenubarItem.displayName = MenubarPrimitive.Item.displayName;
|
|
||||||
|
|
||||||
const MenubarCheckboxItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.CheckboxItem>
|
|
||||||
>(({ className, children, checked, ...props }, ref) => (
|
|
||||||
<MenubarPrimitive.CheckboxItem
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
checked={checked}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
||||||
<MenubarPrimitive.ItemIndicator>
|
|
||||||
<Check className="h-4 w-4" />
|
|
||||||
</MenubarPrimitive.ItemIndicator>
|
|
||||||
</span>
|
|
||||||
{children}
|
|
||||||
</MenubarPrimitive.CheckboxItem>
|
|
||||||
));
|
|
||||||
MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;
|
|
||||||
|
|
||||||
const MenubarRadioItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof MenubarPrimitive.RadioItem>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.RadioItem>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<MenubarPrimitive.RadioItem
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
||||||
<MenubarPrimitive.ItemIndicator>
|
|
||||||
<Circle className="h-2 w-2 fill-current" />
|
|
||||||
</MenubarPrimitive.ItemIndicator>
|
|
||||||
</span>
|
|
||||||
{children}
|
|
||||||
</MenubarPrimitive.RadioItem>
|
|
||||||
));
|
|
||||||
MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;
|
|
||||||
|
|
||||||
const MenubarLabel = React.forwardRef<
|
|
||||||
React.ElementRef<typeof MenubarPrimitive.Label>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Label> & {
|
|
||||||
inset?: boolean;
|
|
||||||
}
|
|
||||||
>(({ className, inset, ...props }, ref) => (
|
|
||||||
<MenubarPrimitive.Label
|
|
||||||
ref={ref}
|
|
||||||
className={cn("px-2 py-1.5 text-sm font-semibold", inset && "pl-8", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
MenubarLabel.displayName = MenubarPrimitive.Label.displayName;
|
|
||||||
|
|
||||||
const MenubarSeparator = React.forwardRef<
|
|
||||||
React.ElementRef<typeof MenubarPrimitive.Separator>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof MenubarPrimitive.Separator>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<MenubarPrimitive.Separator ref={ref} className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} />
|
|
||||||
));
|
|
||||||
MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;
|
|
||||||
|
|
||||||
const MenubarShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
|
|
||||||
return <span className={cn("ml-auto text-xs tracking-widest text-muted-foreground", className)} {...props} />;
|
|
||||||
};
|
|
||||||
MenubarShortcut.displayname = "MenubarShortcut";
|
|
||||||
|
|
||||||
export {
|
|
||||||
Menubar,
|
|
||||||
MenubarMenu,
|
|
||||||
MenubarTrigger,
|
|
||||||
MenubarContent,
|
|
||||||
MenubarItem,
|
|
||||||
MenubarSeparator,
|
|
||||||
MenubarLabel,
|
|
||||||
MenubarCheckboxItem,
|
|
||||||
MenubarRadioGroup,
|
|
||||||
MenubarRadioItem,
|
|
||||||
MenubarPortal,
|
|
||||||
MenubarSubContent,
|
|
||||||
MenubarSubTrigger,
|
|
||||||
MenubarGroup,
|
|
||||||
MenubarSub,
|
|
||||||
MenubarShortcut,
|
|
||||||
};
|
|
||||||
|
|
@ -1,120 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
|
|
||||||
import { cva } from "class-variance-authority";
|
|
||||||
import { ChevronDown } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const NavigationMenu = React.forwardRef<
|
|
||||||
React.ElementRef<typeof NavigationMenuPrimitive.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Root>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<NavigationMenuPrimitive.Root
|
|
||||||
ref={ref}
|
|
||||||
className={cn("relative z-10 flex max-w-max flex-1 items-center justify-center", className)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
<NavigationMenuViewport />
|
|
||||||
</NavigationMenuPrimitive.Root>
|
|
||||||
));
|
|
||||||
NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;
|
|
||||||
|
|
||||||
const NavigationMenuList = React.forwardRef<
|
|
||||||
React.ElementRef<typeof NavigationMenuPrimitive.List>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.List>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<NavigationMenuPrimitive.List
|
|
||||||
ref={ref}
|
|
||||||
className={cn("group flex flex-1 list-none items-center justify-center space-x-1", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
|
|
||||||
|
|
||||||
const NavigationMenuItem = NavigationMenuPrimitive.Item;
|
|
||||||
|
|
||||||
const navigationMenuTriggerStyle = cva(
|
|
||||||
"group inline-flex h-10 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus:outline-none disabled:pointer-events-none disabled:opacity-50 data-[active]:bg-accent/50 data-[state=open]:bg-accent/50",
|
|
||||||
);
|
|
||||||
|
|
||||||
const NavigationMenuTrigger = React.forwardRef<
|
|
||||||
React.ElementRef<typeof NavigationMenuPrimitive.Trigger>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Trigger>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<NavigationMenuPrimitive.Trigger
|
|
||||||
ref={ref}
|
|
||||||
className={cn(navigationMenuTriggerStyle(), "group", className)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}{" "}
|
|
||||||
<ChevronDown
|
|
||||||
className="relative top-[1px] ml-1 h-3 w-3 transition duration-200 group-data-[state=open]:rotate-180"
|
|
||||||
aria-hidden="true"
|
|
||||||
/>
|
|
||||||
</NavigationMenuPrimitive.Trigger>
|
|
||||||
));
|
|
||||||
NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
|
|
||||||
|
|
||||||
const NavigationMenuContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof NavigationMenuPrimitive.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Content>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<NavigationMenuPrimitive.Content
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"left-0 top-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 md:absolute md:w-auto",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;
|
|
||||||
|
|
||||||
const NavigationMenuLink = NavigationMenuPrimitive.Link;
|
|
||||||
|
|
||||||
const NavigationMenuViewport = React.forwardRef<
|
|
||||||
React.ElementRef<typeof NavigationMenuPrimitive.Viewport>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Viewport>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<div className={cn("absolute left-0 top-full flex justify-center")}>
|
|
||||||
<NavigationMenuPrimitive.Viewport
|
|
||||||
className={cn(
|
|
||||||
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
));
|
|
||||||
NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName;
|
|
||||||
|
|
||||||
const NavigationMenuIndicator = React.forwardRef<
|
|
||||||
React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof NavigationMenuPrimitive.Indicator>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<NavigationMenuPrimitive.Indicator
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm bg-border shadow-md" />
|
|
||||||
</NavigationMenuPrimitive.Indicator>
|
|
||||||
));
|
|
||||||
NavigationMenuIndicator.displayName = NavigationMenuPrimitive.Indicator.displayName;
|
|
||||||
|
|
||||||
export {
|
|
||||||
navigationMenuTriggerStyle,
|
|
||||||
NavigationMenu,
|
|
||||||
NavigationMenuList,
|
|
||||||
NavigationMenuItem,
|
|
||||||
NavigationMenuContent,
|
|
||||||
NavigationMenuTrigger,
|
|
||||||
NavigationMenuLink,
|
|
||||||
NavigationMenuIndicator,
|
|
||||||
NavigationMenuViewport,
|
|
||||||
};
|
|
||||||
|
|
@ -1,81 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import { ButtonProps, buttonVariants } from "@/components/ui/button";
|
|
||||||
|
|
||||||
const Pagination = ({ className, ...props }: React.ComponentProps<"nav">) => (
|
|
||||||
<nav
|
|
||||||
role="navigation"
|
|
||||||
aria-label="pagination"
|
|
||||||
className={cn("mx-auto flex w-full justify-center", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
Pagination.displayName = "Pagination";
|
|
||||||
|
|
||||||
const PaginationContent = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>(
|
|
||||||
({ className, ...props }, ref) => (
|
|
||||||
<ul ref={ref} className={cn("flex flex-row items-center gap-1", className)} {...props} />
|
|
||||||
),
|
|
||||||
);
|
|
||||||
PaginationContent.displayName = "PaginationContent";
|
|
||||||
|
|
||||||
const PaginationItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>(({ className, ...props }, ref) => (
|
|
||||||
<li ref={ref} className={cn("", className)} {...props} />
|
|
||||||
));
|
|
||||||
PaginationItem.displayName = "PaginationItem";
|
|
||||||
|
|
||||||
type PaginationLinkProps = {
|
|
||||||
isActive?: boolean;
|
|
||||||
} & Pick<ButtonProps, "size"> &
|
|
||||||
React.ComponentProps<"a">;
|
|
||||||
|
|
||||||
const PaginationLink = ({ className, isActive, size = "icon", ...props }: PaginationLinkProps) => (
|
|
||||||
<a
|
|
||||||
aria-current={isActive ? "page" : undefined}
|
|
||||||
className={cn(
|
|
||||||
buttonVariants({
|
|
||||||
variant: isActive ? "outline" : "ghost",
|
|
||||||
size,
|
|
||||||
}),
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
PaginationLink.displayName = "PaginationLink";
|
|
||||||
|
|
||||||
const PaginationPrevious = ({ className, ...props }: React.ComponentProps<typeof PaginationLink>) => (
|
|
||||||
<PaginationLink aria-label="Go to previous page" size="default" className={cn("gap-1 pl-2.5", className)} {...props}>
|
|
||||||
<ChevronLeft className="h-4 w-4" />
|
|
||||||
<span>Previous</span>
|
|
||||||
</PaginationLink>
|
|
||||||
);
|
|
||||||
PaginationPrevious.displayName = "PaginationPrevious";
|
|
||||||
|
|
||||||
const PaginationNext = ({ className, ...props }: React.ComponentProps<typeof PaginationLink>) => (
|
|
||||||
<PaginationLink aria-label="Go to next page" size="default" className={cn("gap-1 pr-2.5", className)} {...props}>
|
|
||||||
<span>Next</span>
|
|
||||||
<ChevronRight className="h-4 w-4" />
|
|
||||||
</PaginationLink>
|
|
||||||
);
|
|
||||||
PaginationNext.displayName = "PaginationNext";
|
|
||||||
|
|
||||||
const PaginationEllipsis = ({ className, ...props }: React.ComponentProps<"span">) => (
|
|
||||||
<span aria-hidden className={cn("flex h-9 w-9 items-center justify-center", className)} {...props}>
|
|
||||||
<MoreHorizontal className="h-4 w-4" />
|
|
||||||
<span className="sr-only">More pages</span>
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
PaginationEllipsis.displayName = "PaginationEllipsis";
|
|
||||||
|
|
||||||
export {
|
|
||||||
Pagination,
|
|
||||||
PaginationContent,
|
|
||||||
PaginationEllipsis,
|
|
||||||
PaginationItem,
|
|
||||||
PaginationLink,
|
|
||||||
PaginationNext,
|
|
||||||
PaginationPrevious,
|
|
||||||
};
|
|
||||||
|
|
@ -1,36 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
|
|
||||||
import { Circle } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const RadioGroup = React.forwardRef<
|
|
||||||
React.ElementRef<typeof RadioGroupPrimitive.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>
|
|
||||||
>(({ className, ...props }, ref) => {
|
|
||||||
return <RadioGroupPrimitive.Root className={cn("grid gap-2", className)} {...props} ref={ref} />;
|
|
||||||
});
|
|
||||||
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
|
|
||||||
|
|
||||||
const RadioGroupItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof RadioGroupPrimitive.Item>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>
|
|
||||||
>(({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<RadioGroupPrimitive.Item
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"aspect-square h-4 w-4 rounded-full border border-primary text-primary ring-offset-background focus:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<RadioGroupPrimitive.Indicator className="flex items-center justify-center">
|
|
||||||
<Circle className="h-2.5 w-2.5 fill-current text-current" />
|
|
||||||
</RadioGroupPrimitive.Indicator>
|
|
||||||
</RadioGroupPrimitive.Item>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
|
|
||||||
|
|
||||||
export { RadioGroup, RadioGroupItem };
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
import { GripVertical } from "lucide-react";
|
|
||||||
import * as ResizablePrimitive from "react-resizable-panels";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const ResizablePanelGroup = ({ className, ...props }: React.ComponentProps<typeof ResizablePrimitive.PanelGroup>) => (
|
|
||||||
<ResizablePrimitive.PanelGroup
|
|
||||||
className={cn("flex h-full w-full data-[panel-group-direction=vertical]:flex-col", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
const ResizablePanel = ResizablePrimitive.Panel;
|
|
||||||
|
|
||||||
const ResizableHandle = ({
|
|
||||||
withHandle,
|
|
||||||
className,
|
|
||||||
...props
|
|
||||||
}: React.ComponentProps<typeof ResizablePrimitive.PanelResizeHandle> & {
|
|
||||||
withHandle?: boolean;
|
|
||||||
}) => (
|
|
||||||
<ResizablePrimitive.PanelResizeHandle
|
|
||||||
className={cn(
|
|
||||||
"relative flex w-px items-center justify-center bg-border after:absolute after:inset-y-0 after:left-1/2 after:w-1 after:-translate-x-1/2 data-[panel-group-direction=vertical]:h-px data-[panel-group-direction=vertical]:w-full data-[panel-group-direction=vertical]:after:left-0 data-[panel-group-direction=vertical]:after:h-1 data-[panel-group-direction=vertical]:after:w-full data-[panel-group-direction=vertical]:after:-translate-y-1/2 data-[panel-group-direction=vertical]:after:translate-x-0 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-1 [&[data-panel-group-direction=vertical]>div]:rotate-90",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{withHandle && (
|
|
||||||
<div className="z-10 flex h-4 w-3 items-center justify-center rounded-sm border bg-border">
|
|
||||||
<GripVertical className="h-2.5 w-2.5" />
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</ResizablePrimitive.PanelResizeHandle>
|
|
||||||
);
|
|
||||||
|
|
||||||
export { ResizablePanelGroup, ResizablePanel, ResizableHandle };
|
|
||||||
|
|
@ -1,143 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
||||||
import { Check, ChevronDown, ChevronUp } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const Select = SelectPrimitive.Root;
|
|
||||||
|
|
||||||
const SelectGroup = SelectPrimitive.Group;
|
|
||||||
|
|
||||||
const SelectValue = SelectPrimitive.Value;
|
|
||||||
|
|
||||||
const SelectTrigger = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.Trigger
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
<SelectPrimitive.Icon asChild>
|
|
||||||
<ChevronDown className="h-4 w-4 opacity-50" />
|
|
||||||
</SelectPrimitive.Icon>
|
|
||||||
</SelectPrimitive.Trigger>
|
|
||||||
));
|
|
||||||
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
||||||
|
|
||||||
const SelectScrollUpButton = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.ScrollUpButton
|
|
||||||
ref={ref}
|
|
||||||
className={cn("flex cursor-default items-center justify-center py-1", className)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<ChevronUp className="h-4 w-4" />
|
|
||||||
</SelectPrimitive.ScrollUpButton>
|
|
||||||
));
|
|
||||||
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
||||||
|
|
||||||
const SelectScrollDownButton = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.ScrollDownButton
|
|
||||||
ref={ref}
|
|
||||||
className={cn("flex cursor-default items-center justify-center py-1", className)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<ChevronDown className="h-4 w-4" />
|
|
||||||
</SelectPrimitive.ScrollDownButton>
|
|
||||||
));
|
|
||||||
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
||||||
|
|
||||||
const SelectContent = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.Content>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
|
|
||||||
>(({ className, children, position = "popper", ...props }, ref) => (
|
|
||||||
<SelectPrimitive.Portal>
|
|
||||||
<SelectPrimitive.Content
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
||||||
position === "popper" &&
|
|
||||||
"data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
position={position}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<SelectScrollUpButton />
|
|
||||||
<SelectPrimitive.Viewport
|
|
||||||
className={cn(
|
|
||||||
"p-1",
|
|
||||||
position === "popper" &&
|
|
||||||
"h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</SelectPrimitive.Viewport>
|
|
||||||
<SelectScrollDownButton />
|
|
||||||
</SelectPrimitive.Content>
|
|
||||||
</SelectPrimitive.Portal>
|
|
||||||
));
|
|
||||||
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
||||||
|
|
||||||
const SelectLabel = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.Label>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.Label ref={ref} className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)} {...props} />
|
|
||||||
));
|
|
||||||
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
||||||
|
|
||||||
const SelectItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.Item>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
|
|
||||||
>(({ className, children, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.Item
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus:bg-accent focus:text-accent-foreground",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
||||||
<SelectPrimitive.ItemIndicator>
|
|
||||||
<Check className="h-4 w-4" />
|
|
||||||
</SelectPrimitive.ItemIndicator>
|
|
||||||
</span>
|
|
||||||
|
|
||||||
<SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
|
|
||||||
</SelectPrimitive.Item>
|
|
||||||
));
|
|
||||||
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
||||||
|
|
||||||
const SelectSeparator = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SelectPrimitive.Separator>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<SelectPrimitive.Separator ref={ref} className={cn("-mx-1 my-1 h-px bg-muted", className)} {...props} />
|
|
||||||
));
|
|
||||||
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
||||||
|
|
||||||
export {
|
|
||||||
Select,
|
|
||||||
SelectGroup,
|
|
||||||
SelectValue,
|
|
||||||
SelectTrigger,
|
|
||||||
SelectContent,
|
|
||||||
SelectLabel,
|
|
||||||
SelectItem,
|
|
||||||
SelectSeparator,
|
|
||||||
SelectScrollUpButton,
|
|
||||||
SelectScrollDownButton,
|
|
||||||
};
|
|
||||||
|
|
@ -1,107 +0,0 @@
|
||||||
import * as SheetPrimitive from "@radix-ui/react-dialog";
|
|
||||||
import { cva, type VariantProps } from "class-variance-authority";
|
|
||||||
import { X } from "lucide-react";
|
|
||||||
import * as React from "react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const Sheet = SheetPrimitive.Root;
|
|
||||||
|
|
||||||
const SheetTrigger = SheetPrimitive.Trigger;
|
|
||||||
|
|
||||||
const SheetClose = SheetPrimitive.Close;
|
|
||||||
|
|
||||||
const SheetPortal = SheetPrimitive.Portal;
|
|
||||||
|
|
||||||
const SheetOverlay = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SheetPrimitive.Overlay>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<SheetPrimitive.Overlay
|
|
||||||
className={cn(
|
|
||||||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
ref={ref}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
|
|
||||||
|
|
||||||
const sheetVariants = cva(
|
|
||||||
"fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-300 data-[state=open]:duration-500",
|
|
||||||
{
|
|
||||||
variants: {
|
|
||||||
side: {
|
|
||||||
top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
|
|
||||||
bottom:
|
|
||||||
"inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
|
|
||||||
left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
|
|
||||||
right:
|
|
||||||
"inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
defaultVariants: {
|
|
||||||
side: "right",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
interface SheetContentProps
|
|
||||||
extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>,
|
|
||||||
VariantProps<typeof sheetVariants> {}
|
|
||||||
|
|
||||||
const SheetContent = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Content>, SheetContentProps>(
|
|
||||||
({ side = "right", className, children, ...props }, ref) => (
|
|
||||||
<SheetPortal>
|
|
||||||
<SheetOverlay />
|
|
||||||
<SheetPrimitive.Content ref={ref} className={cn(sheetVariants({ side }), className)} {...props}>
|
|
||||||
{children}
|
|
||||||
<SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity data-[state=open]:bg-secondary hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none">
|
|
||||||
<X className="h-4 w-4" />
|
|
||||||
<span className="sr-only">Close</span>
|
|
||||||
</SheetPrimitive.Close>
|
|
||||||
</SheetPrimitive.Content>
|
|
||||||
</SheetPortal>
|
|
||||||
),
|
|
||||||
);
|
|
||||||
SheetContent.displayName = SheetPrimitive.Content.displayName;
|
|
||||||
|
|
||||||
const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
||||||
<div className={cn("flex flex-col space-y-2 text-center sm:text-left", className)} {...props} />
|
|
||||||
);
|
|
||||||
SheetHeader.displayName = "SheetHeader";
|
|
||||||
|
|
||||||
const SheetFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => (
|
|
||||||
<div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} />
|
|
||||||
);
|
|
||||||
SheetFooter.displayName = "SheetFooter";
|
|
||||||
|
|
||||||
const SheetTitle = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SheetPrimitive.Title>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<SheetPrimitive.Title ref={ref} className={cn("text-lg font-semibold text-foreground", className)} {...props} />
|
|
||||||
));
|
|
||||||
SheetTitle.displayName = SheetPrimitive.Title.displayName;
|
|
||||||
|
|
||||||
const SheetDescription = React.forwardRef<
|
|
||||||
React.ElementRef<typeof SheetPrimitive.Description>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<SheetPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} />
|
|
||||||
));
|
|
||||||
SheetDescription.displayName = SheetPrimitive.Description.displayName;
|
|
||||||
|
|
||||||
export {
|
|
||||||
Sheet,
|
|
||||||
SheetClose,
|
|
||||||
SheetContent,
|
|
||||||
SheetDescription,
|
|
||||||
SheetFooter,
|
|
||||||
SheetHeader,
|
|
||||||
SheetOverlay,
|
|
||||||
SheetPortal,
|
|
||||||
SheetTitle,
|
|
||||||
SheetTrigger,
|
|
||||||
};
|
|
||||||
|
|
@ -1,637 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import { Slot } from "@radix-ui/react-slot";
|
|
||||||
import { VariantProps, cva } from "class-variance-authority";
|
|
||||||
import { PanelLeft } from "lucide-react";
|
|
||||||
|
|
||||||
import { useIsMobile } from "@/hooks/use-mobile";
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
import { Button } from "@/components/ui/button";
|
|
||||||
import { Input } from "@/components/ui/input";
|
|
||||||
import { Separator } from "@/components/ui/separator";
|
|
||||||
import { Sheet, SheetContent } from "@/components/ui/sheet";
|
|
||||||
import { Skeleton } from "@/components/ui/skeleton";
|
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip";
|
|
||||||
|
|
||||||
const SIDEBAR_COOKIE_NAME = "sidebar:state";
|
|
||||||
const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7;
|
|
||||||
const SIDEBAR_WIDTH = "16rem";
|
|
||||||
const SIDEBAR_WIDTH_MOBILE = "18rem";
|
|
||||||
const SIDEBAR_WIDTH_ICON = "3rem";
|
|
||||||
const SIDEBAR_KEYBOARD_SHORTCUT = "b";
|
|
||||||
|
|
||||||
type SidebarContext = {
|
|
||||||
state: "expanded" | "collapsed";
|
|
||||||
open: boolean;
|
|
||||||
setOpen: (open: boolean) => void;
|
|
||||||
openMobile: boolean;
|
|
||||||
setOpenMobile: (open: boolean) => void;
|
|
||||||
isMobile: boolean;
|
|
||||||
toggleSidebar: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
const SidebarContext = React.createContext<SidebarContext | null>(null);
|
|
||||||
|
|
||||||
function useSidebar() {
|
|
||||||
const context = React.useContext(SidebarContext);
|
|
||||||
if (!context) {
|
|
||||||
throw new Error("useSidebar must be used within a SidebarProvider.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
const SidebarProvider = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
React.ComponentProps<"div"> & {
|
|
||||||
defaultOpen?: boolean;
|
|
||||||
open?: boolean;
|
|
||||||
onOpenChange?: (open: boolean) => void;
|
|
||||||
}
|
|
||||||
>(({ defaultOpen = true, open: openProp, onOpenChange: setOpenProp, className, style, children, ...props }, ref) => {
|
|
||||||
const isMobile = useIsMobile();
|
|
||||||
const [openMobile, setOpenMobile] = React.useState(false);
|
|
||||||
|
|
||||||
// This is the internal state of the sidebar.
|
|
||||||
// We use openProp and setOpenProp for control from outside the component.
|
|
||||||
const [_open, _setOpen] = React.useState(defaultOpen);
|
|
||||||
const open = openProp ?? _open;
|
|
||||||
const setOpen = React.useCallback(
|
|
||||||
(value: boolean | ((value: boolean) => boolean)) => {
|
|
||||||
const openState = typeof value === "function" ? value(open) : value;
|
|
||||||
if (setOpenProp) {
|
|
||||||
setOpenProp(openState);
|
|
||||||
} else {
|
|
||||||
_setOpen(openState);
|
|
||||||
}
|
|
||||||
|
|
||||||
// This sets the cookie to keep the sidebar state.
|
|
||||||
document.cookie = `${SIDEBAR_COOKIE_NAME}=${openState}; path=/; max-age=${SIDEBAR_COOKIE_MAX_AGE}`;
|
|
||||||
},
|
|
||||||
[setOpenProp, open],
|
|
||||||
);
|
|
||||||
|
|
||||||
// Helper to toggle the sidebar.
|
|
||||||
const toggleSidebar = React.useCallback(() => {
|
|
||||||
return isMobile ? setOpenMobile((open) => !open) : setOpen((open) => !open);
|
|
||||||
}, [isMobile, setOpen, setOpenMobile]);
|
|
||||||
|
|
||||||
// Adds a keyboard shortcut to toggle the sidebar.
|
|
||||||
React.useEffect(() => {
|
|
||||||
const handleKeyDown = (event: KeyboardEvent) => {
|
|
||||||
if (event.key === SIDEBAR_KEYBOARD_SHORTCUT && (event.metaKey || event.ctrlKey)) {
|
|
||||||
event.preventDefault();
|
|
||||||
toggleSidebar();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
window.addEventListener("keydown", handleKeyDown);
|
|
||||||
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
||||||
}, [toggleSidebar]);
|
|
||||||
|
|
||||||
// We add a state so that we can do data-state="expanded" or "collapsed".
|
|
||||||
// This makes it easier to style the sidebar with Tailwind classes.
|
|
||||||
const state = open ? "expanded" : "collapsed";
|
|
||||||
|
|
||||||
const contextValue = React.useMemo<SidebarContext>(
|
|
||||||
() => ({
|
|
||||||
state,
|
|
||||||
open,
|
|
||||||
setOpen,
|
|
||||||
isMobile,
|
|
||||||
openMobile,
|
|
||||||
setOpenMobile,
|
|
||||||
toggleSidebar,
|
|
||||||
}),
|
|
||||||
[state, open, setOpen, isMobile, openMobile, setOpenMobile, toggleSidebar],
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<SidebarContext.Provider value={contextValue}>
|
|
||||||
<TooltipProvider delayDuration={0}>
|
|
||||||
<div
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"--sidebar-width": SIDEBAR_WIDTH,
|
|
||||||
"--sidebar-width-icon": SIDEBAR_WIDTH_ICON,
|
|
||||||
...style,
|
|
||||||
} as React.CSSProperties
|
|
||||||
}
|
|
||||||
className={cn("group/sidebar-wrapper flex min-h-svh w-full has-[[data-variant=inset]]:bg-sidebar", className)}
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</TooltipProvider>
|
|
||||||
</SidebarContext.Provider>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SidebarProvider.displayName = "SidebarProvider";
|
|
||||||
|
|
||||||
const Sidebar = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
React.ComponentProps<"div"> & {
|
|
||||||
side?: "left" | "right";
|
|
||||||
variant?: "sidebar" | "floating" | "inset";
|
|
||||||
collapsible?: "offcanvas" | "icon" | "none";
|
|
||||||
}
|
|
||||||
>(({ side = "left", variant = "sidebar", collapsible = "offcanvas", className, children, ...props }, ref) => {
|
|
||||||
const { isMobile, state, openMobile, setOpenMobile } = useSidebar();
|
|
||||||
|
|
||||||
if (collapsible === "none") {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
className={cn("flex h-full w-[--sidebar-width] flex-col bg-sidebar text-sidebar-foreground", className)}
|
|
||||||
ref={ref}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isMobile) {
|
|
||||||
return (
|
|
||||||
<Sheet open={openMobile} onOpenChange={setOpenMobile} {...props}>
|
|
||||||
<SheetContent
|
|
||||||
data-sidebar="sidebar"
|
|
||||||
data-mobile="true"
|
|
||||||
className="w-[--sidebar-width] bg-sidebar p-0 text-sidebar-foreground [&>button]:hidden"
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"--sidebar-width": SIDEBAR_WIDTH_MOBILE,
|
|
||||||
} as React.CSSProperties
|
|
||||||
}
|
|
||||||
side={side}
|
|
||||||
>
|
|
||||||
<div className="flex h-full w-full flex-col">{children}</div>
|
|
||||||
</SheetContent>
|
|
||||||
</Sheet>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
className="group peer hidden text-sidebar-foreground md:block"
|
|
||||||
data-state={state}
|
|
||||||
data-collapsible={state === "collapsed" ? collapsible : ""}
|
|
||||||
data-variant={variant}
|
|
||||||
data-side={side}
|
|
||||||
>
|
|
||||||
{/* This is what handles the sidebar gap on desktop */}
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
"relative h-svh w-[--sidebar-width] bg-transparent transition-[width] duration-200 ease-linear",
|
|
||||||
"group-data-[collapsible=offcanvas]:w-0",
|
|
||||||
"group-data-[side=right]:rotate-180",
|
|
||||||
variant === "floating" || variant === "inset"
|
|
||||||
? "group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4))]"
|
|
||||||
: "group-data-[collapsible=icon]:w-[--sidebar-width-icon]",
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
className={cn(
|
|
||||||
"fixed inset-y-0 z-10 hidden h-svh w-[--sidebar-width] transition-[left,right,width] duration-200 ease-linear md:flex",
|
|
||||||
side === "left"
|
|
||||||
? "left-0 group-data-[collapsible=offcanvas]:left-[calc(var(--sidebar-width)*-1)]"
|
|
||||||
: "right-0 group-data-[collapsible=offcanvas]:right-[calc(var(--sidebar-width)*-1)]",
|
|
||||||
// Adjust the padding for floating and inset variants.
|
|
||||||
variant === "floating" || variant === "inset"
|
|
||||||
? "p-2 group-data-[collapsible=icon]:w-[calc(var(--sidebar-width-icon)_+_theme(spacing.4)_+2px)]"
|
|
||||||
: "group-data-[collapsible=icon]:w-[--sidebar-width-icon] group-data-[side=left]:border-r group-data-[side=right]:border-l",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
data-sidebar="sidebar"
|
|
||||||
className="flex h-full w-full flex-col bg-sidebar group-data-[variant=floating]:rounded-lg group-data-[variant=floating]:border group-data-[variant=floating]:border-sidebar-border group-data-[variant=floating]:shadow"
|
|
||||||
>
|
|
||||||
{children}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
Sidebar.displayName = "Sidebar";
|
|
||||||
|
|
||||||
const SidebarTrigger = React.forwardRef<React.ElementRef<typeof Button>, React.ComponentProps<typeof Button>>(
|
|
||||||
({ className, onClick, ...props }, ref) => {
|
|
||||||
const { toggleSidebar } = useSidebar();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Button
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="trigger"
|
|
||||||
variant="ghost"
|
|
||||||
size="icon"
|
|
||||||
className={cn("h-7 w-7", className)}
|
|
||||||
onClick={(event) => {
|
|
||||||
onClick?.(event);
|
|
||||||
toggleSidebar();
|
|
||||||
}}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<PanelLeft />
|
|
||||||
<span className="sr-only">Toggle Sidebar</span>
|
|
||||||
</Button>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
SidebarTrigger.displayName = "SidebarTrigger";
|
|
||||||
|
|
||||||
const SidebarRail = React.forwardRef<HTMLButtonElement, React.ComponentProps<"button">>(
|
|
||||||
({ className, ...props }, ref) => {
|
|
||||||
const { toggleSidebar } = useSidebar();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="rail"
|
|
||||||
aria-label="Toggle Sidebar"
|
|
||||||
tabIndex={-1}
|
|
||||||
onClick={toggleSidebar}
|
|
||||||
title="Toggle Sidebar"
|
|
||||||
className={cn(
|
|
||||||
"absolute inset-y-0 z-20 hidden w-4 -translate-x-1/2 transition-all ease-linear after:absolute after:inset-y-0 after:left-1/2 after:w-[2px] group-data-[side=left]:-right-4 group-data-[side=right]:left-0 hover:after:bg-sidebar-border sm:flex",
|
|
||||||
"[[data-side=left]_&]:cursor-w-resize [[data-side=right]_&]:cursor-e-resize",
|
|
||||||
"[[data-side=left][data-state=collapsed]_&]:cursor-e-resize [[data-side=right][data-state=collapsed]_&]:cursor-w-resize",
|
|
||||||
"group-data-[collapsible=offcanvas]:translate-x-0 group-data-[collapsible=offcanvas]:after:left-full group-data-[collapsible=offcanvas]:hover:bg-sidebar",
|
|
||||||
"[[data-side=left][data-collapsible=offcanvas]_&]:-right-2",
|
|
||||||
"[[data-side=right][data-collapsible=offcanvas]_&]:-left-2",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
SidebarRail.displayName = "SidebarRail";
|
|
||||||
|
|
||||||
const SidebarInset = React.forwardRef<HTMLDivElement, React.ComponentProps<"main">>(({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<main
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"relative flex min-h-svh flex-1 flex-col bg-background",
|
|
||||||
"peer-data-[variant=inset]:min-h-[calc(100svh-theme(spacing.4))] md:peer-data-[variant=inset]:m-2 md:peer-data-[state=collapsed]:peer-data-[variant=inset]:ml-2 md:peer-data-[variant=inset]:ml-0 md:peer-data-[variant=inset]:rounded-xl md:peer-data-[variant=inset]:shadow",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SidebarInset.displayName = "SidebarInset";
|
|
||||||
|
|
||||||
const SidebarInput = React.forwardRef<React.ElementRef<typeof Input>, React.ComponentProps<typeof Input>>(
|
|
||||||
({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<Input
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="input"
|
|
||||||
className={cn(
|
|
||||||
"h-8 w-full bg-background shadow-none focus-visible:ring-2 focus-visible:ring-sidebar-ring",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
SidebarInput.displayName = "SidebarInput";
|
|
||||||
|
|
||||||
const SidebarHeader = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(({ className, ...props }, ref) => {
|
|
||||||
return <div ref={ref} data-sidebar="header" className={cn("flex flex-col gap-2 p-2", className)} {...props} />;
|
|
||||||
});
|
|
||||||
SidebarHeader.displayName = "SidebarHeader";
|
|
||||||
|
|
||||||
const SidebarFooter = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(({ className, ...props }, ref) => {
|
|
||||||
return <div ref={ref} data-sidebar="footer" className={cn("flex flex-col gap-2 p-2", className)} {...props} />;
|
|
||||||
});
|
|
||||||
SidebarFooter.displayName = "SidebarFooter";
|
|
||||||
|
|
||||||
const SidebarSeparator = React.forwardRef<React.ElementRef<typeof Separator>, React.ComponentProps<typeof Separator>>(
|
|
||||||
({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<Separator
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="separator"
|
|
||||||
className={cn("mx-2 w-auto bg-sidebar-border", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
SidebarSeparator.displayName = "SidebarSeparator";
|
|
||||||
|
|
||||||
const SidebarContent = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="content"
|
|
||||||
className={cn(
|
|
||||||
"flex min-h-0 flex-1 flex-col gap-2 overflow-auto group-data-[collapsible=icon]:overflow-hidden",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SidebarContent.displayName = "SidebarContent";
|
|
||||||
|
|
||||||
const SidebarGroup = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(({ className, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="group"
|
|
||||||
className={cn("relative flex w-full min-w-0 flex-col p-2", className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SidebarGroup.displayName = "SidebarGroup";
|
|
||||||
|
|
||||||
const SidebarGroupLabel = React.forwardRef<HTMLDivElement, React.ComponentProps<"div"> & { asChild?: boolean }>(
|
|
||||||
({ className, asChild = false, ...props }, ref) => {
|
|
||||||
const Comp = asChild ? Slot : "div";
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Comp
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="group-label"
|
|
||||||
className={cn(
|
|
||||||
"flex h-8 shrink-0 items-center rounded-md px-2 text-xs font-medium text-sidebar-foreground/70 outline-none ring-sidebar-ring transition-[margin,opa] duration-200 ease-linear focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
||||||
"group-data-[collapsible=icon]:-mt-8 group-data-[collapsible=icon]:opacity-0",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
SidebarGroupLabel.displayName = "SidebarGroupLabel";
|
|
||||||
|
|
||||||
const SidebarGroupAction = React.forwardRef<HTMLButtonElement, React.ComponentProps<"button"> & { asChild?: boolean }>(
|
|
||||||
({ className, asChild = false, ...props }, ref) => {
|
|
||||||
const Comp = asChild ? Slot : "button";
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Comp
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="group-action"
|
|
||||||
className={cn(
|
|
||||||
"absolute right-3 top-3.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
||||||
// Increases the hit area of the button on mobile.
|
|
||||||
"after:absolute after:-inset-2 after:md:hidden",
|
|
||||||
"group-data-[collapsible=icon]:hidden",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
SidebarGroupAction.displayName = "SidebarGroupAction";
|
|
||||||
|
|
||||||
const SidebarGroupContent = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(
|
|
||||||
({ className, ...props }, ref) => (
|
|
||||||
<div ref={ref} data-sidebar="group-content" className={cn("w-full text-sm", className)} {...props} />
|
|
||||||
),
|
|
||||||
);
|
|
||||||
SidebarGroupContent.displayName = "SidebarGroupContent";
|
|
||||||
|
|
||||||
const SidebarMenu = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>(({ className, ...props }, ref) => (
|
|
||||||
<ul ref={ref} data-sidebar="menu" className={cn("flex w-full min-w-0 flex-col gap-1", className)} {...props} />
|
|
||||||
));
|
|
||||||
SidebarMenu.displayName = "SidebarMenu";
|
|
||||||
|
|
||||||
const SidebarMenuItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>(({ className, ...props }, ref) => (
|
|
||||||
<li ref={ref} data-sidebar="menu-item" className={cn("group/menu-item relative", className)} {...props} />
|
|
||||||
));
|
|
||||||
SidebarMenuItem.displayName = "SidebarMenuItem";
|
|
||||||
|
|
||||||
const sidebarMenuButtonVariants = cva(
|
|
||||||
"peer/menu-button flex w-full items-center gap-2 overflow-hidden rounded-md p-2 text-left text-sm outline-none ring-sidebar-ring transition-[width,height,padding] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 group-has-[[data-sidebar=menu-action]]/menu-item:pr-8 aria-disabled:pointer-events-none aria-disabled:opacity-50 data-[active=true]:bg-sidebar-accent data-[active=true]:font-medium data-[active=true]:text-sidebar-accent-foreground data-[state=open]:hover:bg-sidebar-accent data-[state=open]:hover:text-sidebar-accent-foreground group-data-[collapsible=icon]:!size-8 group-data-[collapsible=icon]:!p-2 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0",
|
|
||||||
{
|
|
||||||
variants: {
|
|
||||||
variant: {
|
|
||||||
default: "hover:bg-sidebar-accent hover:text-sidebar-accent-foreground",
|
|
||||||
outline:
|
|
||||||
"bg-background shadow-[0_0_0_1px_hsl(var(--sidebar-border))] hover:bg-sidebar-accent hover:text-sidebar-accent-foreground hover:shadow-[0_0_0_1px_hsl(var(--sidebar-accent))]",
|
|
||||||
},
|
|
||||||
size: {
|
|
||||||
default: "h-8 text-sm",
|
|
||||||
sm: "h-7 text-xs",
|
|
||||||
lg: "h-12 text-sm group-data-[collapsible=icon]:!p-0",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
defaultVariants: {
|
|
||||||
variant: "default",
|
|
||||||
size: "default",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const SidebarMenuButton = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
React.ComponentProps<"button"> & {
|
|
||||||
asChild?: boolean;
|
|
||||||
isActive?: boolean;
|
|
||||||
tooltip?: string | React.ComponentProps<typeof TooltipContent>;
|
|
||||||
} & VariantProps<typeof sidebarMenuButtonVariants>
|
|
||||||
>(({ asChild = false, isActive = false, variant = "default", size = "default", tooltip, className, ...props }, ref) => {
|
|
||||||
const Comp = asChild ? Slot : "button";
|
|
||||||
const { isMobile, state } = useSidebar();
|
|
||||||
|
|
||||||
const button = (
|
|
||||||
<Comp
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="menu-button"
|
|
||||||
data-size={size}
|
|
||||||
data-active={isActive}
|
|
||||||
className={cn(sidebarMenuButtonVariants({ variant, size }), className)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!tooltip) {
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof tooltip === "string") {
|
|
||||||
tooltip = {
|
|
||||||
children: tooltip,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Tooltip>
|
|
||||||
<TooltipTrigger asChild>{button}</TooltipTrigger>
|
|
||||||
<TooltipContent side="right" align="center" hidden={state !== "collapsed" || isMobile} {...tooltip} />
|
|
||||||
</Tooltip>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SidebarMenuButton.displayName = "SidebarMenuButton";
|
|
||||||
|
|
||||||
const SidebarMenuAction = React.forwardRef<
|
|
||||||
HTMLButtonElement,
|
|
||||||
React.ComponentProps<"button"> & {
|
|
||||||
asChild?: boolean;
|
|
||||||
showOnHover?: boolean;
|
|
||||||
}
|
|
||||||
>(({ className, asChild = false, showOnHover = false, ...props }, ref) => {
|
|
||||||
const Comp = asChild ? Slot : "button";
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Comp
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="menu-action"
|
|
||||||
className={cn(
|
|
||||||
"absolute right-1 top-1.5 flex aspect-square w-5 items-center justify-center rounded-md p-0 text-sidebar-foreground outline-none ring-sidebar-ring transition-transform peer-hover/menu-button:text-sidebar-accent-foreground hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 [&>svg]:size-4 [&>svg]:shrink-0",
|
|
||||||
// Increases the hit area of the button on mobile.
|
|
||||||
"after:absolute after:-inset-2 after:md:hidden",
|
|
||||||
"peer-data-[size=sm]/menu-button:top-1",
|
|
||||||
"peer-data-[size=default]/menu-button:top-1.5",
|
|
||||||
"peer-data-[size=lg]/menu-button:top-2.5",
|
|
||||||
"group-data-[collapsible=icon]:hidden",
|
|
||||||
showOnHover &&
|
|
||||||
"group-focus-within/menu-item:opacity-100 group-hover/menu-item:opacity-100 data-[state=open]:opacity-100 peer-data-[active=true]/menu-button:text-sidebar-accent-foreground md:opacity-0",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SidebarMenuAction.displayName = "SidebarMenuAction";
|
|
||||||
|
|
||||||
const SidebarMenuBadge = React.forwardRef<HTMLDivElement, React.ComponentProps<"div">>(
|
|
||||||
({ className, ...props }, ref) => (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="menu-badge"
|
|
||||||
className={cn(
|
|
||||||
"pointer-events-none absolute right-1 flex h-5 min-w-5 select-none items-center justify-center rounded-md px-1 text-xs font-medium tabular-nums text-sidebar-foreground",
|
|
||||||
"peer-hover/menu-button:text-sidebar-accent-foreground peer-data-[active=true]/menu-button:text-sidebar-accent-foreground",
|
|
||||||
"peer-data-[size=sm]/menu-button:top-1",
|
|
||||||
"peer-data-[size=default]/menu-button:top-1.5",
|
|
||||||
"peer-data-[size=lg]/menu-button:top-2.5",
|
|
||||||
"group-data-[collapsible=icon]:hidden",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
);
|
|
||||||
SidebarMenuBadge.displayName = "SidebarMenuBadge";
|
|
||||||
|
|
||||||
const SidebarMenuSkeleton = React.forwardRef<
|
|
||||||
HTMLDivElement,
|
|
||||||
React.ComponentProps<"div"> & {
|
|
||||||
showIcon?: boolean;
|
|
||||||
}
|
|
||||||
>(({ className, showIcon = false, ...props }, ref) => {
|
|
||||||
// Random width between 50 to 90%.
|
|
||||||
const width = React.useMemo(() => {
|
|
||||||
return `${Math.floor(Math.random() * 40) + 50}%`;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<div
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="menu-skeleton"
|
|
||||||
className={cn("flex h-8 items-center gap-2 rounded-md px-2", className)}
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
{showIcon && <Skeleton className="size-4 rounded-md" data-sidebar="menu-skeleton-icon" />}
|
|
||||||
<Skeleton
|
|
||||||
className="h-4 max-w-[--skeleton-width] flex-1"
|
|
||||||
data-sidebar="menu-skeleton-text"
|
|
||||||
style={
|
|
||||||
{
|
|
||||||
"--skeleton-width": width,
|
|
||||||
} as React.CSSProperties
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SidebarMenuSkeleton.displayName = "SidebarMenuSkeleton";
|
|
||||||
|
|
||||||
const SidebarMenuSub = React.forwardRef<HTMLUListElement, React.ComponentProps<"ul">>(
|
|
||||||
({ className, ...props }, ref) => (
|
|
||||||
<ul
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="menu-sub"
|
|
||||||
className={cn(
|
|
||||||
"mx-3.5 flex min-w-0 translate-x-px flex-col gap-1 border-l border-sidebar-border px-2.5 py-0.5",
|
|
||||||
"group-data-[collapsible=icon]:hidden",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
),
|
|
||||||
);
|
|
||||||
SidebarMenuSub.displayName = "SidebarMenuSub";
|
|
||||||
|
|
||||||
const SidebarMenuSubItem = React.forwardRef<HTMLLIElement, React.ComponentProps<"li">>(({ ...props }, ref) => (
|
|
||||||
<li ref={ref} {...props} />
|
|
||||||
));
|
|
||||||
SidebarMenuSubItem.displayName = "SidebarMenuSubItem";
|
|
||||||
|
|
||||||
const SidebarMenuSubButton = React.forwardRef<
|
|
||||||
HTMLAnchorElement,
|
|
||||||
React.ComponentProps<"a"> & {
|
|
||||||
asChild?: boolean;
|
|
||||||
size?: "sm" | "md";
|
|
||||||
isActive?: boolean;
|
|
||||||
}
|
|
||||||
>(({ asChild = false, size = "md", isActive, className, ...props }, ref) => {
|
|
||||||
const Comp = asChild ? Slot : "a";
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Comp
|
|
||||||
ref={ref}
|
|
||||||
data-sidebar="menu-sub-button"
|
|
||||||
data-size={size}
|
|
||||||
data-active={isActive}
|
|
||||||
className={cn(
|
|
||||||
"flex h-7 min-w-0 -translate-x-px items-center gap-2 overflow-hidden rounded-md px-2 text-sidebar-foreground outline-none ring-sidebar-ring aria-disabled:pointer-events-none aria-disabled:opacity-50 hover:bg-sidebar-accent hover:text-sidebar-accent-foreground focus-visible:ring-2 active:bg-sidebar-accent active:text-sidebar-accent-foreground disabled:pointer-events-none disabled:opacity-50 [&>span:last-child]:truncate [&>svg]:size-4 [&>svg]:shrink-0 [&>svg]:text-sidebar-accent-foreground",
|
|
||||||
"data-[active=true]:bg-sidebar-accent data-[active=true]:text-sidebar-accent-foreground",
|
|
||||||
size === "sm" && "text-xs",
|
|
||||||
size === "md" && "text-sm",
|
|
||||||
"group-data-[collapsible=icon]:hidden",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
SidebarMenuSubButton.displayName = "SidebarMenuSubButton";
|
|
||||||
|
|
||||||
export {
|
|
||||||
Sidebar,
|
|
||||||
SidebarContent,
|
|
||||||
SidebarFooter,
|
|
||||||
SidebarGroup,
|
|
||||||
SidebarGroupAction,
|
|
||||||
SidebarGroupContent,
|
|
||||||
SidebarGroupLabel,
|
|
||||||
SidebarHeader,
|
|
||||||
SidebarInput,
|
|
||||||
SidebarInset,
|
|
||||||
SidebarMenu,
|
|
||||||
SidebarMenuAction,
|
|
||||||
SidebarMenuBadge,
|
|
||||||
SidebarMenuButton,
|
|
||||||
SidebarMenuItem,
|
|
||||||
SidebarMenuSkeleton,
|
|
||||||
SidebarMenuSub,
|
|
||||||
SidebarMenuSubButton,
|
|
||||||
SidebarMenuSubItem,
|
|
||||||
SidebarProvider,
|
|
||||||
SidebarRail,
|
|
||||||
SidebarSeparator,
|
|
||||||
SidebarTrigger,
|
|
||||||
useSidebar,
|
|
||||||
};
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
import { useTheme } from "next-themes";
|
|
||||||
import { Toaster as Sonner, toast } from "sonner";
|
|
||||||
|
|
||||||
type ToasterProps = React.ComponentProps<typeof Sonner>;
|
|
||||||
|
|
||||||
const Toaster = ({ ...props }: ToasterProps) => {
|
|
||||||
const { theme = "system" } = useTheme();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Sonner
|
|
||||||
theme={theme as ToasterProps["theme"]}
|
|
||||||
className="toaster group"
|
|
||||||
toastOptions={{
|
|
||||||
classNames: {
|
|
||||||
toast:
|
|
||||||
"group toast group-[.toaster]:bg-background group-[.toaster]:text-foreground group-[.toaster]:border-border group-[.toaster]:shadow-lg",
|
|
||||||
description: "group-[.toast]:text-muted-foreground",
|
|
||||||
actionButton: "group-[.toast]:bg-primary group-[.toast]:text-primary-foreground",
|
|
||||||
cancelButton: "group-[.toast]:bg-muted group-[.toast]:text-muted-foreground",
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export { Toaster, toast };
|
|
||||||
|
|
@ -1,111 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
import * as ToastPrimitives from "@radix-ui/react-toast";
|
|
||||||
import { cva, type VariantProps } from "class-variance-authority";
|
|
||||||
import { X } from "lucide-react";
|
|
||||||
|
|
||||||
import { cn } from "@/lib/utils";
|
|
||||||
|
|
||||||
const ToastProvider = ToastPrimitives.Provider;
|
|
||||||
|
|
||||||
const ToastViewport = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ToastPrimitives.Viewport>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Viewport>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<ToastPrimitives.Viewport
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"fixed top-0 z-[100] flex max-h-screen w-full flex-col-reverse p-4 sm:bottom-0 sm:right-0 sm:top-auto sm:flex-col md:max-w-[420px]",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
ToastViewport.displayName = ToastPrimitives.Viewport.displayName;
|
|
||||||
|
|
||||||
const toastVariants = cva(
|
|
||||||
"group pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md border p-6 pr-8 shadow-lg transition-all data-[swipe=cancel]:translate-x-0 data-[swipe=end]:translate-x-[var(--radix-toast-swipe-end-x)] data-[swipe=move]:translate-x-[var(--radix-toast-swipe-move-x)] data-[swipe=move]:transition-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[swipe=end]:animate-out data-[state=closed]:fade-out-80 data-[state=closed]:slide-out-to-right-full data-[state=open]:slide-in-from-top-full data-[state=open]:sm:slide-in-from-bottom-full",
|
|
||||||
{
|
|
||||||
variants: {
|
|
||||||
variant: {
|
|
||||||
default: "border bg-background text-foreground",
|
|
||||||
destructive: "destructive group border-destructive bg-destructive text-destructive-foreground",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
defaultVariants: {
|
|
||||||
variant: "default",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
const Toast = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ToastPrimitives.Root>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Root> & VariantProps<typeof toastVariants>
|
|
||||||
>(({ className, variant, ...props }, ref) => {
|
|
||||||
return <ToastPrimitives.Root ref={ref} className={cn(toastVariants({ variant }), className)} {...props} />;
|
|
||||||
});
|
|
||||||
Toast.displayName = ToastPrimitives.Root.displayName;
|
|
||||||
|
|
||||||
const ToastAction = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ToastPrimitives.Action>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Action>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<ToastPrimitives.Action
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"inline-flex h-8 shrink-0 items-center justify-center rounded-md border bg-transparent px-3 text-sm font-medium ring-offset-background transition-colors group-[.destructive]:border-muted/40 hover:bg-secondary group-[.destructive]:hover:border-destructive/30 group-[.destructive]:hover:bg-destructive group-[.destructive]:hover:text-destructive-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 group-[.destructive]:focus:ring-destructive disabled:pointer-events-none disabled:opacity-50",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
{...props}
|
|
||||||
/>
|
|
||||||
));
|
|
||||||
ToastAction.displayName = ToastPrimitives.Action.displayName;
|
|
||||||
|
|
||||||
const ToastClose = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ToastPrimitives.Close>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Close>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<ToastPrimitives.Close
|
|
||||||
ref={ref}
|
|
||||||
className={cn(
|
|
||||||
"absolute right-2 top-2 rounded-md p-1 text-foreground/50 opacity-0 transition-opacity group-hover:opacity-100 group-[.destructive]:text-red-300 hover:text-foreground group-[.destructive]:hover:text-red-50 focus:opacity-100 focus:outline-none focus:ring-2 group-[.destructive]:focus:ring-red-400 group-[.destructive]:focus:ring-offset-red-600",
|
|
||||||
className,
|
|
||||||
)}
|
|
||||||
toast-close=""
|
|
||||||
{...props}
|
|
||||||
>
|
|
||||||
<X className="h-4 w-4" />
|
|
||||||
</ToastPrimitives.Close>
|
|
||||||
));
|
|
||||||
ToastClose.displayName = ToastPrimitives.Close.displayName;
|
|
||||||
|
|
||||||
const ToastTitle = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ToastPrimitives.Title>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Title>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<ToastPrimitives.Title ref={ref} className={cn("text-sm font-semibold", className)} {...props} />
|
|
||||||
));
|
|
||||||
ToastTitle.displayName = ToastPrimitives.Title.displayName;
|
|
||||||
|
|
||||||
const ToastDescription = React.forwardRef<
|
|
||||||
React.ElementRef<typeof ToastPrimitives.Description>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof ToastPrimitives.Description>
|
|
||||||
>(({ className, ...props }, ref) => (
|
|
||||||
<ToastPrimitives.Description ref={ref} className={cn("text-sm opacity-90", className)} {...props} />
|
|
||||||
));
|
|
||||||
ToastDescription.displayName = ToastPrimitives.Description.displayName;
|
|
||||||
|
|
||||||
type ToastProps = React.ComponentPropsWithoutRef<typeof Toast>;
|
|
||||||
|
|
||||||
type ToastActionElement = React.ReactElement<typeof ToastAction>;
|
|
||||||
|
|
||||||
export {
|
|
||||||
type ToastProps,
|
|
||||||
type ToastActionElement,
|
|
||||||
ToastProvider,
|
|
||||||
ToastViewport,
|
|
||||||
Toast,
|
|
||||||
ToastTitle,
|
|
||||||
ToastDescription,
|
|
||||||
ToastClose,
|
|
||||||
ToastAction,
|
|
||||||
};
|
|
||||||
|
|
@ -1,24 +0,0 @@
|
||||||
import { useToast } from "@/hooks/use-toast";
|
|
||||||
import { Toast, ToastClose, ToastDescription, ToastProvider, ToastTitle, ToastViewport } from "@/components/ui/toast";
|
|
||||||
|
|
||||||
export function Toaster() {
|
|
||||||
const { toasts } = useToast();
|
|
||||||
|
|
||||||
return (
|
|
||||||
<ToastProvider>
|
|
||||||
{toasts.map(function ({ id, title, description, action, ...props }) {
|
|
||||||
return (
|
|
||||||
<Toast key={id} {...props}>
|
|
||||||
<div className="grid gap-1">
|
|
||||||
{title && <ToastTitle>{title}</ToastTitle>}
|
|
||||||
{description && <ToastDescription>{description}</ToastDescription>}
|
|
||||||
</div>
|
|
||||||
{action}
|
|
||||||
<ToastClose />
|
|
||||||
</Toast>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
<ToastViewport />
|
|
||||||
</ToastProvider>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
@ -1,3 +0,0 @@
|
||||||
import { useToast, toast } from "@/hooks/use-toast";
|
|
||||||
|
|
||||||
export { useToast, toast };
|
|
||||||
|
|
@ -1,186 +0,0 @@
|
||||||
import * as React from "react";
|
|
||||||
|
|
||||||
import type { ToastActionElement, ToastProps } from "@/components/ui/toast";
|
|
||||||
|
|
||||||
const TOAST_LIMIT = 1;
|
|
||||||
const TOAST_REMOVE_DELAY = 1000000;
|
|
||||||
|
|
||||||
type ToasterToast = ToastProps & {
|
|
||||||
id: string;
|
|
||||||
title?: React.ReactNode;
|
|
||||||
description?: React.ReactNode;
|
|
||||||
action?: ToastActionElement;
|
|
||||||
};
|
|
||||||
|
|
||||||
const actionTypes = {
|
|
||||||
ADD_TOAST: "ADD_TOAST",
|
|
||||||
UPDATE_TOAST: "UPDATE_TOAST",
|
|
||||||
DISMISS_TOAST: "DISMISS_TOAST",
|
|
||||||
REMOVE_TOAST: "REMOVE_TOAST",
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
let count = 0;
|
|
||||||
|
|
||||||
function genId() {
|
|
||||||
count = (count + 1) % Number.MAX_SAFE_INTEGER;
|
|
||||||
return count.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
type ActionType = typeof actionTypes;
|
|
||||||
|
|
||||||
type Action =
|
|
||||||
| {
|
|
||||||
type: ActionType["ADD_TOAST"];
|
|
||||||
toast: ToasterToast;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: ActionType["UPDATE_TOAST"];
|
|
||||||
toast: Partial<ToasterToast>;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: ActionType["DISMISS_TOAST"];
|
|
||||||
toastId?: ToasterToast["id"];
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
type: ActionType["REMOVE_TOAST"];
|
|
||||||
toastId?: ToasterToast["id"];
|
|
||||||
};
|
|
||||||
|
|
||||||
interface State {
|
|
||||||
toasts: ToasterToast[];
|
|
||||||
}
|
|
||||||
|
|
||||||
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
|
|
||||||
|
|
||||||
const addToRemoveQueue = (toastId: string) => {
|
|
||||||
if (toastTimeouts.has(toastId)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeout = setTimeout(() => {
|
|
||||||
toastTimeouts.delete(toastId);
|
|
||||||
dispatch({
|
|
||||||
type: "REMOVE_TOAST",
|
|
||||||
toastId: toastId,
|
|
||||||
});
|
|
||||||
}, TOAST_REMOVE_DELAY);
|
|
||||||
|
|
||||||
toastTimeouts.set(toastId, timeout);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const reducer = (state: State, action: Action): State => {
|
|
||||||
switch (action.type) {
|
|
||||||
case "ADD_TOAST":
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
|
|
||||||
};
|
|
||||||
|
|
||||||
case "UPDATE_TOAST":
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
toasts: state.toasts.map((t) => (t.id === action.toast.id ? { ...t, ...action.toast } : t)),
|
|
||||||
};
|
|
||||||
|
|
||||||
case "DISMISS_TOAST": {
|
|
||||||
const { toastId } = action;
|
|
||||||
|
|
||||||
// ! Side effects ! - This could be extracted into a dismissToast() action,
|
|
||||||
// but I'll keep it here for simplicity
|
|
||||||
if (toastId) {
|
|
||||||
addToRemoveQueue(toastId);
|
|
||||||
} else {
|
|
||||||
state.toasts.forEach((toast) => {
|
|
||||||
addToRemoveQueue(toast.id);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
toasts: state.toasts.map((t) =>
|
|
||||||
t.id === toastId || toastId === undefined
|
|
||||||
? {
|
|
||||||
...t,
|
|
||||||
open: false,
|
|
||||||
}
|
|
||||||
: t,
|
|
||||||
),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
case "REMOVE_TOAST":
|
|
||||||
if (action.toastId === undefined) {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
toasts: [],
|
|
||||||
};
|
|
||||||
}
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
toasts: state.toasts.filter((t) => t.id !== action.toastId),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const listeners: Array<(state: State) => void> = [];
|
|
||||||
|
|
||||||
let memoryState: State = { toasts: [] };
|
|
||||||
|
|
||||||
function dispatch(action: Action) {
|
|
||||||
memoryState = reducer(memoryState, action);
|
|
||||||
listeners.forEach((listener) => {
|
|
||||||
listener(memoryState);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
type Toast = Omit<ToasterToast, "id">;
|
|
||||||
|
|
||||||
function toast({ ...props }: Toast) {
|
|
||||||
const id = genId();
|
|
||||||
|
|
||||||
const update = (props: ToasterToast) =>
|
|
||||||
dispatch({
|
|
||||||
type: "UPDATE_TOAST",
|
|
||||||
toast: { ...props, id },
|
|
||||||
});
|
|
||||||
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
|
|
||||||
|
|
||||||
dispatch({
|
|
||||||
type: "ADD_TOAST",
|
|
||||||
toast: {
|
|
||||||
...props,
|
|
||||||
id,
|
|
||||||
open: true,
|
|
||||||
onOpenChange: (open) => {
|
|
||||||
if (!open) dismiss();
|
|
||||||
},
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return {
|
|
||||||
id: id,
|
|
||||||
dismiss,
|
|
||||||
update,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function useToast() {
|
|
||||||
const [state, setState] = React.useState<State>(memoryState);
|
|
||||||
|
|
||||||
React.useEffect(() => {
|
|
||||||
listeners.push(setState);
|
|
||||||
return () => {
|
|
||||||
const index = listeners.indexOf(setState);
|
|
||||||
if (index > -1) {
|
|
||||||
listeners.splice(index, 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}, [state]);
|
|
||||||
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
toast,
|
|
||||||
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export { useToast, toast };
|
|
||||||
|
|
@ -5,7 +5,8 @@ export interface Topic {
|
||||||
id: string;
|
id: string;
|
||||||
label: string;
|
label: string;
|
||||||
description: string;
|
description: string;
|
||||||
color: string; // Tailwind color class
|
color: string; // Terminal-style color class
|
||||||
|
slug: string; // URL slug for topic page
|
||||||
}
|
}
|
||||||
|
|
||||||
export const TOPICS = {
|
export const TOPICS = {
|
||||||
|
|
@ -13,31 +14,36 @@ export const TOPICS = {
|
||||||
id: "strategy",
|
id: "strategy",
|
||||||
label: "AI Strategy",
|
label: "AI Strategy",
|
||||||
description: "Strategic planning and implementation approaches for AI adoption",
|
description: "Strategic planning and implementation approaches for AI adoption",
|
||||||
color: "bg-blue-100 text-blue-800",
|
color: "text-terminal-cyan",
|
||||||
|
slug: "ai-strategy",
|
||||||
},
|
},
|
||||||
TOOLS: {
|
TOOLS: {
|
||||||
id: "tools",
|
id: "tools",
|
||||||
label: "AI Tools",
|
label: "AI Tools",
|
||||||
description: "Practical tools and platforms for AI implementation",
|
description: "Practical tools and platforms for AI implementation",
|
||||||
color: "bg-green-100 text-green-800",
|
color: "text-terminal-green",
|
||||||
|
slug: "ai-tools",
|
||||||
},
|
},
|
||||||
MEASUREMENT: {
|
MEASUREMENT: {
|
||||||
id: "measurement",
|
id: "measurement",
|
||||||
label: "ROI & Measurement",
|
label: "ROI & Measurement",
|
||||||
description: "Measuring AI impact and return on investment",
|
description: "Measuring AI impact and return on investment",
|
||||||
color: "bg-purple-100 text-purple-800",
|
color: "text-terminal-magenta",
|
||||||
|
slug: "measuring-ai-roi",
|
||||||
},
|
},
|
||||||
IMPLEMENTATION: {
|
IMPLEMENTATION: {
|
||||||
id: "implementation",
|
id: "implementation",
|
||||||
label: "Implementation",
|
label: "Implementation",
|
||||||
description: "Hands-on implementation techniques and frameworks",
|
description: "Hands-on implementation techniques and frameworks",
|
||||||
color: "bg-orange-100 text-orange-800",
|
color: "text-terminal-yellow",
|
||||||
|
slug: "ai-implementation",
|
||||||
},
|
},
|
||||||
BUSINESS: {
|
BUSINESS: {
|
||||||
id: "business",
|
id: "business",
|
||||||
label: "Business Applications",
|
label: "Business Applications",
|
||||||
description: "Real-world business use cases and applications",
|
description: "Real-world business use cases and applications",
|
||||||
color: "bg-pink-100 text-pink-800",
|
color: "text-terminal-red",
|
||||||
|
slug: "ai-business-applications",
|
||||||
},
|
},
|
||||||
} as const;
|
} as const;
|
||||||
|
|
||||||
|
|
@ -74,3 +80,8 @@ export function getArticleCountByTopic(topicId: string): number {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get topic by ID
|
||||||
|
export function getTopicById(id: string): Topic | undefined {
|
||||||
|
return Object.values(TOPICS).find((t) => t.id === id);
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import type { Config } from "tailwindcss";
|
import type { Config } from "tailwindcss";
|
||||||
|
|
||||||
const config: Config = {
|
const config: Config = {
|
||||||
darkMode: ["class"],
|
|
||||||
content: [
|
content: [
|
||||||
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
|
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
|
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
|
||||||
|
|
@ -9,6 +8,9 @@ const config: Config = {
|
||||||
],
|
],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
|
fontFamily: {
|
||||||
|
mono: ["JetBrains Mono", "Menlo", "Monaco", "Consolas", "monospace"],
|
||||||
|
},
|
||||||
colors: {
|
colors: {
|
||||||
border: "hsl(var(--border))",
|
border: "hsl(var(--border))",
|
||||||
input: "hsl(var(--input))",
|
input: "hsl(var(--input))",
|
||||||
|
|
@ -43,6 +45,15 @@ const config: Config = {
|
||||||
DEFAULT: "hsl(var(--card))",
|
DEFAULT: "hsl(var(--card))",
|
||||||
foreground: "hsl(var(--card-foreground))",
|
foreground: "hsl(var(--card-foreground))",
|
||||||
},
|
},
|
||||||
|
terminal: {
|
||||||
|
green: "hsl(var(--terminal-green))",
|
||||||
|
cyan: "hsl(var(--terminal-cyan))",
|
||||||
|
yellow: "hsl(var(--terminal-yellow))",
|
||||||
|
red: "hsl(var(--terminal-red))",
|
||||||
|
magenta: "hsl(var(--terminal-magenta))",
|
||||||
|
dim: "hsl(var(--terminal-dim))",
|
||||||
|
bright: "hsl(var(--terminal-bright))",
|
||||||
|
},
|
||||||
},
|
},
|
||||||
borderRadius: {
|
borderRadius: {
|
||||||
lg: "var(--radius)",
|
lg: "var(--radius)",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue