DEV Community

Cover image for Next.js + Tailwind CSS + TypeScript Starter Template
Theodorus Clarence
Theodorus Clarence

Posted on

Next.js + Tailwind CSS + TypeScript Starter Template

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.

banner

GitHub logo theodorusclarence / ts-nextjs-tailwind-starter

A starter for Next.js, Tailwind CSS, and Typescript with Absolute Import, Seo, Link component, pre-configured with Husky

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

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.
customlink

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';
Enter fullscreen mode Exit fullscreen mode

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'
/>
Enter fullscreen mode Exit fullscreen mode

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>
  );
}
Enter fullscreen mode Exit fullscreen mode

6. Custom 404 Page

The Next.js default 404 is pretty simple, so I added some base styles, and some flickering animation.
404

7. Workspace Snippets

Snippets such as React Import, useState, useEffect, React Component, and Next.js Pages with Seo import included. View more

workspace-snippets

8. Husky, Prettier, Lint, and Commitlint Configured

I installed 3 Husky hooks including:

  1. pre-commit, running eslint and format the code using prettier
  2. commit-msg, running commitlint to ensure the use of Conventional Commit for commit messages
  3. post-merge, running yarn every git 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.

GitHub logo theodorusclarence / ts-nextjs-tailwind-starter

A starter for Next.js, Tailwind CSS, and Typescript with Absolute Import, Seo, Link component, pre-configured with Husky

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!

Discussion (0)