Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ability to display images on paywalls #623

Merged
merged 1 commit into from
Jan 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 6 additions & 3 deletions src/app/blog/rag-pipeline-tutorial/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import cloneExampleSite from '@/images/rag-pipeline-tutorial-clone-example-site.
import docsSanity from '@/images/rag-pipeline-tutorial-docs-sanity.webp';
import queryIndex from '@/images/rag-pipeline-tutorial-query-index.webp';
import chunking from '@/images/chunking.webp';
import ragPipelineElements from '@/images/rag-tutorial-elements.webp';

import { createMetadata } from '@/utils/createMetadata';
import { ArticleLayout } from '@/components/ArticleLayout';
Expand All @@ -24,9 +25,11 @@ export const articleMetadata = {
price: 2000,
previewLength: 450,
previewElements: 52,
paywallHeader: "Building RAG Pipelines: The Most In-Demand Gen AI Skill",
paywallBody: "Every company wants developers who can build RAG applications. Get a complete, production-ready tutorial that teaches you exactly how to build a RAG pipeline with the latest tech stack: Vercel AI SDK, OpenAI embeddings, and Pinecone vector search.",
buttonText: "Unlock the full tutorial ($20)"
paywallHeader: "Master RAG Development: The Complete Package",
paywallBody: "Get everything you need to build production-ready RAG applications: a step-by-step tutorial, ready-to-use Jupyter notebook for data processing, and a complete Next.js example site. Perfect for developers who want to add the most in-demand Gen AI skill to their toolkit.",
buttonText: "Get the complete package ($20)",
paywallImage: ragPipelineElements,
paywallImageAlt: "The complete RAG development package: Tutorial, Jupyter Notebook, and Example Site"
};

export const metadata = createMetadata(articleMetadata);
Expand Down
9 changes: 8 additions & 1 deletion src/components/ArticleContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useState, useEffect, useCallback } from 'react'
import { useSession } from 'next-auth/react'
import Paywall from './Paywall'
import React from 'react'
import { StaticImageData } from 'next/image'

interface ArticleContentProps {
children: React.ReactNode
Expand All @@ -16,6 +17,8 @@ interface ArticleContentProps {
paywallHeader?: string
paywallBody?: string
buttonText?: string
paywallImage?: string | StaticImageData
paywallImageAlt?: string
}

export default function ArticleContent({
Expand All @@ -28,7 +31,9 @@ export default function ArticleContent({
previewElements = 3,
paywallHeader,
paywallBody,
buttonText
buttonText,
paywallImage,
paywallImageAlt
}: ArticleContentProps) {
const { data: session } = useSession()
const [hasPurchased, setHasPurchased] = useState(false)
Expand Down Expand Up @@ -91,6 +96,8 @@ export default function ArticleContent({
paywallHeader={paywallHeader}
paywallBody={paywallBody}
buttonText={buttonText}
image={paywallImage}
imageAlt={paywallImageAlt}
/>
</>
)
Expand Down
5 changes: 5 additions & 0 deletions src/components/ArticleLayout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import NewsletterWrapper from '@/components/NewsletterWrapper'
import FollowButtons from '@/components/FollowButtons'
import { Suspense } from 'react'
import ArticleContent from './ArticleContent'
import { StaticImageData } from 'next/image'

interface ArticleLayoutProps {
children: React.ReactNode
Expand All @@ -21,6 +22,8 @@ interface ArticleLayoutProps {
paywallHeader?: string
paywallBody?: string
buttonText?: string
paywallImage?: string | StaticImageData
paywallImageAlt?: string
}
}

Expand Down Expand Up @@ -57,6 +60,8 @@ export function ArticleLayout({
paywallHeader={metadata.paywallHeader}
paywallBody={metadata.paywallBody}
buttonText={metadata.buttonText}
paywallImage={metadata.paywallImage}
paywallImageAlt={metadata.paywallImageAlt}
>
{children}
</ArticleContent>
Expand Down
50 changes: 35 additions & 15 deletions src/components/Paywall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useSession } from 'next-auth/react'
import { useState } from 'react'
import { Button } from './Button'
import { useRouter } from 'next/navigation'
import Image, { StaticImageData } from 'next/image'

interface PaywallProps {
price: number
Expand All @@ -12,6 +13,8 @@ interface PaywallProps {
paywallHeader?: string
paywallBody?: string
buttonText?: string
image?: StaticImageData | string
imageAlt?: string
}

export default function Paywall({
Expand All @@ -20,7 +23,9 @@ export default function Paywall({
title,
paywallHeader,
paywallBody,
buttonText
buttonText,
image,
imageAlt = "Article preview image"
}: PaywallProps) {
const { data: session } = useSession()
const router = useRouter()
Expand All @@ -45,21 +50,36 @@ export default function Paywall({

return (
<div className="my-8 p-8 bg-gradient-to-br from-zinc-100 to-zinc-200 dark:from-zinc-800 dark:to-zinc-900 rounded-xl shadow-xl border border-zinc-300 dark:border-zinc-700">
<h3 className="text-2xl font-bold mb-6 text-center text-zinc-900 dark:text-zinc-100">
{paywallHeader || "Hands-on knowledge is valuable"}
</h3>
<div className="flex flex-col gap-6">
<h3 className="text-2xl font-bold text-zinc-900 dark:text-zinc-100">
{paywallHeader || "Hands-on knowledge is valuable"}
</h3>

<div className="text-center">
<p className="mb-6 text-lg text-zinc-700 dark:text-zinc-300">
{paywallBody || "Purchase to read the full content and support its independent creator."}
</p>
<Button
onClick={handlePurchase}
disabled={loading}
className="w-full sm:w-auto px-8 py-3 text-lg bg-gradient-to-r from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-700 transition-all duration-300"
>
{loading ? 'Processing...' : buttonText || `Purchase for $${(price / 100).toFixed(2)}`}
</Button>
{image && (
<div className="w-full relative">
<Image
src={image}
alt={imageAlt}
className="rounded-lg shadow-md w-full"
width={800}
height={400}
style={{ objectFit: 'cover' }}
/>
</div>
)}

<div className="text-center">
<p className="mb-6 text-lg text-zinc-700 dark:text-zinc-300">
{paywallBody || "Purchase to read the full content and support its independent creator."}
</p>
<Button
onClick={handlePurchase}
disabled={loading}
className="w-full sm:w-auto px-8 py-3 text-lg bg-gradient-to-r from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-700 transition-all duration-300"
>
{loading ? 'Processing...' : buttonText || `Purchase for $${(price / 100).toFixed(2)}`}
</Button>
</div>
</div>
</div>
)
Expand Down
Binary file added src/images/rag-tutorial-elements.webp
Binary file not shown.
Loading