This content originally appeared on DEV Community and was authored by Muhammad Ahmad
Let's clone dev.to with the actual dev.to api to get the posts and lists.
Overview
This application is built with the following technologies:
Live demo: https://dev-to-clone-ma.vercel.app
Github repo: https://github.com/MA-Ahmad/dev.to-clone
Breaking down the layout of Dev.to
- Top navbar
- Left sidebar
- Posts section
- Right sidebar
I'll discuss some components code here otherwise this article will become very long.
1. Setup the Project
Create a Next.js app
yarn create next-app --typescript
Install chakra-ui
yarn add @chakra-ui/react @emotion/react@^11 @emotion/styled@^11 framer-motion@^4
2. Start coding
Top navbar
const Navbar = () => {
return (
<Box
py="2"
boxShadow="sm"
border="0 solid #e5e7eb"
position="fixed"
top="0"
bg="#fff"
width="100%"
zIndex="1"
>
<Container>
<HStack spacing={4}>
<Image src="/assets/images/logo.svg" />
<Input
maxW="26rem"
placeholder="Search..."
borderColor="#b5bdc4"
borderRadius="5px"
d={{ base: "none", md: "block" }}
/>
<Spacer />
<HStack spacing={3}>
<Button
color="#fff"
borderRadius="4px"
bg="#3b49df"
_hover={{ bg: "#323ebe" }}
>
Create a post
</Button>
<IconButton>
<Image src="/assets/images/notification.svg" />
</IconButton>
<IconButton>
<Image src="/assets/images/bell.svg" />
</IconButton>
<Avatar
size={"sm"}
src={"https://avatars2.githubusercontent.com/u/37842853?v=4"}
/>
</HStack>
</HStack>
</Container>
</Box>
);
};
Left sidebar
Links section
const Links = () => {
return (
<Box as="nav">
<LinkButton>
<Image src="/assets/images/sidebar/home.svg" mr="3" />
Home
</LinkButton>
<LinkButton>
<Image src="/assets/images/sidebar/reading.svg" mr="3" />
Reading List
</LinkButton>
<LinkButton>
<Image src="/assets/images/sidebar/tag.svg" mr="3" />
Tags
</LinkButton>
<LinkButton>
<Text fontWeight="normal" color="#4d5760" ml="2.3rem">
More...
</Text>
</LinkButton>
</Box>
);
};
Tags section
const Tags = () => {
return (
<Box mt="6">
<Flex pl="2" py="4">
<Heading as="h3" fontSize="1rem">
My Tags
</Heading>
<Spacer />
<Image src="/assets/settings.svg" />
</Flex>
<Box maxH="50vh" overflowY="auto">
<TagList>
{[
"Nextjs",
"react",
"javascript",
"ruby",
"ruby on rails",
"css",
"beginners",
"html",
"typescript"
]}
</TagList>
</Box>
</Box>
);
};
Posts section
End point for showing feed https://dev.to/stories/feed
Post card component
<Box
mt="3"
as="article"
bg="white"
borderRadius="md"
overflow="hidden"
border="1px solid #08090a1a"
>
{headerImage ? <Image src={headerImage} /> : ""}
<Grid templateColumns="max-content 1fr" gap={2} p={4}>
<Image src={userProfile} w="8" borderRadius="full" />
<Box>
<VStack align="flex-start" spacing={0}>
<Text color="#4d5760" fontSize="14px" fontWeight="500">
{username}
</Text>
<Text color="#4d5760" fontSize="12px">
{publishedDate}
</Text>
</VStack>
<Heading fontSize={headerImage ? "30px" : "24px"} mt="3">
<Link
href={postLink}
_hover={{ color: "#323ebe", textDecoration: "none" }}
isExternal
>
{title}
</Link>
</Heading>
<HStack mt="3" fontSize="14px" color="#64707d">
{tagList.map((tag, idx) => (
<Text as={Link} key={idx}>
#{tag}
</Text>
))}
</HStack>
<HStack mt={3}>
<Button
leftIcon={<Image src="/assets/images/like.svg" />}
ml={-2}
bg="transparent"
padding="6px 8px"
height="auto"
fontWeight="normal"
fontSize="14px"
lineHeight="1.2"
borderRadius="4px"
_hover={{ bg: "#f6f6f6" }}
>
{reactionCount} reactions
</Button>
<Button
leftIcon={<Image src="/assets/images/comment.svg" />}
bg="transparent"
padding="6px 8px"
height="auto"
fontWeight="normal"
fontSize="14px"
lineHeight="1.2"
borderRadius="4px"
_hover={{ bg: "#f6f6f6" }}
>
{commentCount} comments
</Button>
<Spacer />
<Text fontSize="12px">{readingTime} min read</Text>
<Button
bg="#d2d6db"
padding="8px 12px"
height="auto"
fontWeight="normal"
fontSize="14px"
_hover={{ bg: "#b5bdc4" }}
>
Save
</Button>
</HStack>
</Box>
</Grid>
</Box>
Right sidebar
End point for showing list https://dev.to/api/listings
const List = () => {
const { data, error } = useSWR("https://dev.to/api/listings", fetcher);
if (error) return <Box>failed to load</Box>;
if (!data)
return (
<Box as="section" bg="white" borderRadius="md" border="1px solid #E2E4E6" width="100%">
<ListHeading />
{[1, 2, 3, 4, 5].map(id => {
return (
<Box borderBottom="1px solid #E2E4E6" width="100%" p="3">
<Skeleton height="15vh" borderRadius="5px" width="100%" />
</Box>
);
})}
</Box>
);
return (
<Box as="section" bg="white" borderRadius="md" border="1px solid #E2E4E6">
<ListHeading />
{data.slice(0, 7).map(list => (
<ListBox title={list.title} category={list.category} slug={list.slug} />
))}
</Box>
);
}
Responsiveness
This content originally appeared on DEV Community and was authored by Muhammad Ahmad
Muhammad Ahmad | Sciencx (2021-06-26T14:24:05+00:00) Dev.to clone built with Next.js & Chakra UI. Retrieved from https://www.scien.cx/2021/06/26/dev-to-clone-built-with-next-js-chakra-ui/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.