This continues my previous posts using ChatGPT, Next.js, React, Typescript, and Tailwind CSS to create a Hacker News clone based on the following video: Building Hacker News with AI, describe a UI and AI builds it for us
In this post I will be prompting ChatGPT for the listing component of the homepage.
Prompt and Results:
Prompt to ChatGPT:
“I am building a Hacker News clone using Next.js, Tailwind CSS, React, and TypeScript. Only the UI. I need to create the listing component for displaying a list of news articles. Each article listing should include:
– Article number
– Article title
– Article URL in parentheses to the right of the title
– An upvote icon to the left of the article (between the list number and the article title)
– Under the article title: ““
– Number of points the article has received
– Author’s name as a link, prefixed with “by “
– Number of hours ago the article was posted, formatted as “X hours ago” and clickable
– “hide” as a clickable link
– Number of comments, formatted as “X comments”, as a link
– Example format: 160 points by author 2 hours ago | hide | 62 comments
Overall Color Scheme:
– The article title is solid black.
– The article number, URL, upvote icon, and content under the title are all light gray”
Result:
Code Generated for the Article Listing Component:
type Article = { number: number; title: "string;" url: string; points: number; author: string; timePosted: number; comments: number;
}; const ArticleList: React.FC<{ articles: Article[] }> = ({ articles }) => { return ( <div className="space-y-4"> {articles.map((article, index) => ( <div key={index} className="flex flex-col space-y-1"> <div className="flex items-center text-gray-500"> <span className="mr-2">{article.number}.</span>
<span className="mr-2">▲</span>
<a href={article.url} className="text-black font-bold hover:underline"> {article.title} </a>
<span className="ml-2 text-gray-500">({article.url})</span>
</div>
<div className="text-gray-500"> <span>{article.points} points</span>
<span> by <a href={`/user/${article.author}`} className="hover:underline">{article.author}</a></span> <span> {article.timePosted} hours ago</span>
<span> | <a href="#" className="hover:underline">hide</a></span> <span> | <a href={`/item/${article.number}`} className="hover:underline">{article.comments} comments</a></span> </div>
</div>
))} </div>
);
};
Code to be integrated into page.tsx:
const articles = [ { number: 1, title: "'Example Article 1'," url: 'https://example.com', points: 160, author: 'author1', timePosted: 2, comments: 62, }, { number: 2, title: "'Example Article 2'," url: 'https://example2.com', points: 120, author: 'author2', timePosted: 5, comments: 45, }, // Add more articles as needed
]; const HomePage: React.FC = () => { return ( <div className="container mx-auto p-4"> <ArticleList articles={articles} />
</div>
);
};
I was also provided with an SVG option for the upvote icon as an alternative to <span className="mr-2">▲</span>
:
<svg className="w-4 h-4 text-gray-500 mr-2" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 2l9 18H3z" />
</svg>
Comments:
There are a few adjustments to make. Some of the spacing between the links is off. The title link underlines on hover. The “X hours ago” link, indicating how long ago the article was posted, is not clickable.
In my prompt to ChatGPT I did not mention that this code would be added to an existing app – something I may want to do in the future. It may also be helpful to provide code from the app so that the AI can adapt it’s output. Despite this, the code did not require any initial edits integrate and run with the rest of the app.
Edits and Improvements:
Updated version of ArticleList.tsx:
const ArticleList: React.FC<{ articles: Article[] }> = ({ articles }) => { return ( <div className="space-y-2 py-2 px-1 text-stardust"> {articles.map((article, index) => ( <div key={index} className="flex flex-col space-y-1"> <div className="flex items-center"> <span className="mr-2">{article.number}.</span>
<Link href={`/vote/${article.number}`} ><svg className="w-4 h-4 mr-2" viewBox="0 0 24 24" fill="currentColor"> <path d="M12 2l9 18H3z" /> </svg></Link> <Link href={article.url} className="text-black text-base"> {article.title} </Link>
<span className="ml-2 "><Link href={`/from/${article.url}`} className="hover:underline">({article.url})</Link></span> </div>
<div className=" pl-12 text-xs"> <span >{article.points} points </span>
<span> by <Link href={`/user/${article.author}`} className="hover:underline">{article.author}</Link></span> <span> <Link href={`/item/${article.number}`} className="hover:underline">{article.comments} hours ago</Link></span> <span> | <Link href="#" className="hover:underline">hide</Link></span> <span> | <Link href={`/item/${article.number}`} className="hover:underline">{article.comments} comments</Link></span> </div>
</div>
))} <div> <Link href="#" className="pl-12 text-base">More</Link>
</div>
</div>
);
};
Updated version of page.tsx:
const Home: React.FC = () => { return ( <div> <Head> <title>Hacker News Clone</title>
<meta name="description" content="A Hacker News clone built with Next.js, TypeScript, and Tailwind CSS" /> <link rel="icon" href="/favicon.ico" /> </Head>
<div className="px-36 py-2 font-sans text-sm"> <div className="bg-stone-100"> <Header /> <ArticleList articles={articles} />
</div>
</div>
</div>
);
};
I also added customized background and text colors to the tailwind config file:
colors: { 'springwood': '#f6f6ef', 'stardust': '#999999', },
Result:
A quick summary of changes made:
The next and final step is to add the header and make any final adjustments to the clone.