Setting up a new project and connecting up everything takes a lot of time. So I decided to create a starter template with my favorite tech stack for easy use.
theodorusclarence / ts-nextjs-tailwind-starter
🔋 Next.js + Tailwind CSS + TypeScript starter and boilerplate packed with useful development features
What's Inside
1. Installed Packages
-
clsx, utility for constructing
className
strings conditionally. - react-icons, svg react icons of popular icon packs.
2. UnstyledLink Component
Used as a component for Next.js Link. Will render out Next/Link if the href started with /
or #
, else will render an a
tag with target='_blank'
. Also add a cursor style for outside links.
I found that by using this component, it simplifies the boilerplate for Next.js Link which uses Link
and a
tag.
// src/components/UnstyledLink.tsx
import clsx from 'clsx';
import Link, { LinkProps } from 'next/link';
export type UnstyledLinkProps = {
href: string;
children: React.ReactNode;
openNewTab?: boolean;
className?: string;
} & React.ComponentPropsWithoutRef<'a'> &
LinkProps;
export default function UnstyledLink({
children,
href,
openNewTab,
className,
...rest
}: UnstyledLinkProps) {
const isNewTab =
openNewTab !== undefined
? openNewTab
: href && !href.startsWith('/') && !href.startsWith('#');
if (!isNewTab) {
return (
<Link href={href}>
<a {...rest} className={className}>
{children}
</a>
</Link>
);
}
return (
<a
target='_blank'
rel='noopener noreferrer'
href={href}
{...rest}
className={clsx(className, 'cursor-[ne-resize]')}
>
{children}
</a>
);
}
3. CustomLink Component
Using the UnstyledLink component, we can extend it to a new Component with all the default styles. Here are some styles that I baked into the starter for easy use.
4. Absolute Import
I'm a fan of Vue style absolute import, so I also added the configuration on tsconfig.json, so we can just do importing like so.
import Nav from '../../../components/Nav';
simplified to
import Nav from '@/components/Nav';
5. Seo Component
Configure the default in src/components/Seo.tsx
. If you want to use the default, just add <Seo />
on top of your page.
You can also customize it per page by overriding the title, description as props
<Seo
title='Next.js Tailwind Starter'
description='your description'
/>
or if you want to still keep the title like %s | Next.js Tailwind Starter
, you can use templateTitle
props.
Here is the Seo component that I'm using, you can just simply change the defaults and you're good to go
// src/components/Seo.tsx
import Head from 'next/head';
import { useRouter } from 'next/router';
const defaultMeta = {
title: 'Next.js Tailwind Starter',
site_name: 'Next.js Tailwind Starter',
description: 'A template for Next.js and Tailwindcss by Theodorus Clarence',
url: 'https://theodorusclarence.com',
image: 'https://theodorusclarence.com/favicon/large-og.jpg',
type: 'website',
robots: 'follow, index',
};
type SeoProps = {
date?: string;
templateTitle?: string;
} & Partial<typeof defaultMeta>;
export default function Seo(props: SeoProps) {
const router = useRouter();
const meta = {
...defaultMeta,
...props,
};
meta['title'] = props.templateTitle
? `${props.templateTitle} | ${meta.site_name}`
: meta.title;
return (
<Head>
<title>{meta.title}</title>
<meta name='robots' content={meta.robots} />
<meta content={meta.description} name='description' />
<meta property='og:url' content={`${meta.url}${router.asPath}`} />
<link rel='canonical' href={`${meta.url}${router.asPath}`} />
{/* Open Graph */}
<meta property='og:type' content={meta.type} />
<meta property='og:site_name' content={meta.site_name} />
<meta property='og:description' content={meta.description} />
<meta property='og:title' content={meta.title} />
<meta name='image' property='og:image' content={meta.image} />
{/* Twitter */}
<meta name='twitter:card' content='summary_large_image' />
<meta name='twitter:site' content='@th_clarence' />
<meta name='twitter:title' content={meta.title} />
<meta name='twitter:description' content={meta.description} />
<meta name='twitter:image' content={meta.image} />
{meta.date && (
<>
<meta property='article:published_time' content={meta.date} />
<meta
name='publish_date'
property='og:publish_date'
content={meta.date}
/>
<meta
name='author'
property='article:author'
content='Theodorus Clarence'
/>
</>
)}
</Head>
);
}
6. Custom 404 Page
The Next.js default 404 is pretty simple, so I added some base styles, and some flickering animation.
7. Workspace Snippets
Snippets such as React Import, useState, useEffect, React Component, and Next.js Pages with Seo import included. View more
8. Husky, Prettier, Lint, and Commitlint Configured
I installed 3 Husky hooks including:
- pre-commit, running eslint and format the code using prettier
- commit-msg, running commitlint to ensure the use of Conventional Commit for commit messages
- post-merge, running
yarn
everygit pull
or after merge to ensure all new packages are installed and ready to go
9. Default Favicon Declaration
Use Favicon Generator and then overwrite the files in /public/favicon
10. Default Tailwind CSS Base Styles
There are default styles for responsive heading sizes, and .layout
to support a max-width for larger screen size. Find more about it on my blog post
11. Preloaded & Self Hosted Inter Fonts
Inter is a variable fonts, that is self hosted and preloaded in this starter.
theodorusclarence / ts-nextjs-tailwind-starter
🔋 Next.js + Tailwind CSS + TypeScript starter and boilerplate packed with useful development features
Check it out on github! Please do open a PR if you want to contribute! Let me know if there are something that can be improved.
Star ⭐ is much appreciated!
Top comments (2)
This is amazing. It is truly useful and I've learned a lot from it.
Thanks a lot!