In this article, we'll get acquainted with TypeScript, tailwind and the dev.to api in a super friendly. As you'll see, its super simple to get started.
I finally decided to put together a blog / portfolio. Right now it's super simple and retrieves articles from my dev.to account. It uses Next.JS, Tailwind CSS and TypeScript.
In the directory you'd like to create your project run
npx create-next-app@latest .
Go ahead and select yes for using TypeScript & ESLint
Now lets add Tailwind
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
Configure your template paths
//tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
"./pages/**/*.{js,ts,jsx,tsx}",
"./components/**/*.{js,ts,jsx,tsx}",
],
theme: {
extend: {},
},
plugins: [],
}
Add the Tailwind directives to your CSS
//globals.css
@tailwind base;
@tailwind components;
@tailwind utilities;
Since we're using TypeScript, we can alter out tsconfig to make it nicer to import from our folders
//tsconfig.json
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/components/*": ["components/*"],
"@/types/*": ["types/*"]
},
...
}
Lets create a interface in a declaration file for the data we get back from our api, it's not all off the data we get back from the api, but it will give us nice autocomplete on the data we do care about
//devto.d.ts
export interface IDevtoPost {
id: number;
title: string;
description: string;
readable_publish_date: string;
url: string;
edited_at: string;
published_at: string;
}
We can then import that interface easily thanks to the modifications we made in our tsconfig
pages/index.tsx
...
import { IDevtoPost } from '@/types/devto';
...
Now we'll export a function which will retrieve the data from our api on every request. We'll use axios to help use call our api, so you'll need to install axios before using the following code.
npm install axios
pages/index.tsx
...
export async function getServerSideProps() {
const res = await axios.get(
'https://dev.to/api/articles?username=<YOUR USERNAME>'
);
return {
props: {
posts: res.data,
},
};
}
...
Let's now consume that data in our page and give it a structure with our interface
pages/index.tsx
...
export default function Home({ posts }: { posts: IDevtoPost[] }) {
return <></>;
}
...
We use prop deconstructing to pass the posts into our page and define the data that comes back from getServerSideProps, as an array of IDevtoPost interfaces with : { posts: IDevtoPost[] }
Bellow is the data we get back from getServerSideProps, just to give you an idea
Now lets create a post component to display that data, this one will utilize the tailwind library (for the sake of time, I won't go into detail on every component I've created here).
components/post
import { IDevtoPost } from '@/types/devto';
import Link from 'next/link';
const post = ({ post }: { post: IDevtoPost }) => {
return (
<div className="w-11/12 h-30 flex flex-col bg-gray-50 dark:bg-black mt-6 mb-2 border border-gray-200 hover:scale-110">
<h2 className="mt-4 mb-1 ml-4 text-sm sm:text-base"> {post.title} </h2>
<span className="ml-4 mb-1 italic text-xs sm:text-sm">
Publish date: {post.readable_publish_date}
</span>
<Link href={post.url} className="mb-4">
<span className="ml-4 italic text-xs">Read on Dev.to</span>
</Link>
</div>
);
};
export default post;
We import our interface again and define the structure of the data the component receives, except this time, it's not an array of interfaces, but just the interface itself, since we'll map through the posts array.
The brief overview of tailwind CSS is, it's shorthand vanilla CSS. In the bellow code
-
w-11/12
is the equivalent ofwidth: 91.666667%;
-
flex
is the equivalent ofdisplay: flex
-
flex-col
is the equivalent offlex-direction: column
<div className="w-11/12 h-30 flex flex-col bg-gray-50 dark:bg-black mt-6 mb-2 border border-gray-200 hover:scale-110">
Tailwind includes a dark variant that lets you style your site differently when dark mode is enabled. By default this uses the prefers-color-scheme CSS media feature, but you can also build sites that support toggling dark mode manually using the ‘class’ strategy.
therefore
dark:bg-black
is the equivalent ofbackground-color: black;
when the users preference through an operating system setting (e.g. light or dark mode) or a user agent setting.hover:scale-110
will scale to 1.1 when hovered
Out of the box, tailwind does not understand scale-110
however we can extend the tailwind theme
//tailwind.config.js
...
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx}',
'./components/**/*.{js,ts,jsx,tsx}',
],
theme: {
extend: {
scale: {
110: '1.1',
},
},
},
};
See more in the Tailwind docs
and check out this cheetsheet for more help.
Finally to not make this article too long, lets just quickly touch on we can utilize an earlier technique we used and import our post component and map over the data we received
pages/index.tsx
...
import Post from '@/components/post';
export default function Home({ posts }: { posts: IDevtoPost[] }) {
return (<>
{posts.map((post) => (
<Post key={post.id} post={post} />
))}
</>)
you can view the complete code here
you can also view the final project here
Top comments (0)