{"id":27729957,"url":"https://github.com/ositaka/nextjs-blog-tailwind-starter","last_synced_at":"2025-04-28T05:01:57.413Z","repository":{"id":258335081,"uuid":"863219560","full_name":"ositaka/nextjs-blog-tailwind-starter","owner":"ositaka","description":"🚀 Next.js 14 Blog Starter with Tailwind CSS, Contentlayer, \u0026 Decap CMS","archived":false,"fork":false,"pushed_at":"2024-10-16T18:17:15.000Z","size":15220,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-10-18T14:05:48.549Z","etag":null,"topics":["contentlayer","decap-cms","nextjs","responsive","tailwindcss","typescript"],"latest_commit_sha":null,"homepage":"https://design-code.tips","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ositaka.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-09-25T23:33:04.000Z","updated_at":"2024-10-16T18:17:19.000Z","dependencies_parsed_at":"2024-10-19T02:20:39.120Z","dependency_job_id":null,"html_url":"https://github.com/ositaka/nextjs-blog-tailwind-starter","commit_stats":null,"previous_names":["ositaka/nextjs-blog-tailwind-starter"],"tags_count":0,"template":true,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ositaka%2Fnextjs-blog-tailwind-starter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ositaka%2Fnextjs-blog-tailwind-starter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ositaka%2Fnextjs-blog-tailwind-starter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ositaka%2Fnextjs-blog-tailwind-starter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ositaka","download_url":"https://codeload.github.com/ositaka/nextjs-blog-tailwind-starter/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251254262,"owners_count":21559791,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["contentlayer","decap-cms","nextjs","responsive","tailwindcss","typescript"],"created_at":"2025-04-28T05:01:38.858Z","updated_at":"2025-04-28T05:01:57.325Z","avatar_url":"https://github.com/ositaka.png","language":"TypeScript","funding_links":[],"categories":["Starter Template"],"sub_categories":[],"readme":"# 🚀 Next.js 14 Blog Starter with Tailwind CSS, Contentlayer, \u0026 Decap CMS\n\n[![Netlify Status](https://api.netlify.com/api/v1/badges/51784f6e-1f73-4db9-ad5e-c0c514a47181/deploy-status)](https://app.netlify.com/sites/nextjs-blog-tailwind-starter/deploys)\n\nWelcome to the [**design-code.tips**](https://design-code.tips/) Next.js starter! \n\nThis open-source starter template is built with **Next.js 14**, **Tailwind CSS**, **Contentlayer**, and **Decap CMS**. It's designed to be a simple and customizable way to launch a modern blog, with support for MDX and multiple categories like Code Blog, Inspiration, Podcasts, Tools, and Resources.\n\n![Starter Cover Preview](/starter-cover.png)\n\n[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/ositaka/nextjs-blog-tailwind-starter/)\n[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/ositaka/nextjs-blog-tailwind-starter/)\n\n---\n\n## 💻 Starter Preview\n\n![Homepage in light and dark modes](/starter-preview.png)\n\n## ✨ Features\n\n- 🛠️ **Next.js 14**: Fast, modern React framework for production-ready web applications.\n- 🎨 **Tailwind CSS**: Utility-first CSS for rapid UI development.\n- 📄 **MDX Support**: Write your blog posts in Markdown with JSX components.\n- 🗂️ **Contentlayer**: Simple content management with files as data.\n- 📋 **Decap CMS**: Easily manage your posts through a friendly CMS interface.\n- 🏷️ **Categories**: Pre-configured sections for Code Blog, Inspiration, Podcasts, and Tools.\n- 🖼️ **Optimized Images**: Use the `\u003cExportedImage /\u003e` component from the [`next-image-export-optimizer`](https://www.npmjs.com/package/next-image-export-optimizer) package for optimized image handling in static exports, replacing the default Next.js `\u003cImage /\u003e` component for better control over image quality, formats (like WEBP), and cache settings.\n- 🌗 **Dark/Light Mode**: Automatically adapts to the user's operating system settings.\n\n## 📦 Tech Stack\n\n- **Next.js 14**\n- **Tailwind CSS**\n- **MDX**\n- **Contentlayer**\n- **Decap CMS**\n\n## 🚀 Quick Start\n\nFollow these steps to get the project up and running:\n\n1. **Clone the repository**:\n\n   ```bash\n   git clone https://github.com/ositaka/nextjs-blog-tailwind-starter\n   cd nextjs-blog-tailwind-starter\n   ```\n\n2. **Install dependencies:**\n\n   ```bash\n   npm install\n   ```\n\n3. **Run the development server:**\n\n   ```bash\n   npm run dev\n   ```\n\n   Open http://localhost:3000 in your browser to see the app running.\n\n---\n\n## ✍️ Writing Content (without CMS)\n\nYou can create different types of content (like blog posts or podcasts) in separate folders under `content/`. Each folder corresponds to a category in your blog.\n\nContent is written in **MDX** format and managed using [**Contentlayer**](https://contentlayer.dev/). To create a new post, add an `.mdx` file in the appropriate folder inside `content/` for each category:\n\n```\ncontent/\n  ├── blog/\n  ├── inspiration/\n  ├── podcasts/\n  ├── resources/\n  └── tools/\n```\n\nEach post supports frontmatter fields like `title`, `description`, `date`, and `featured`.\n\nExample frontmatter for a blog post:\n\n```md\n---\ntemplateKey: blog\ntitle: \u003e\n  Custom Scrollbar with CSS (WebKit)\ndate: 2021-06-19T19:28:37.629Z\nfeatured: true\ndescription: \u003e\n  Learn how to customize the scrollbar with CSS for WebKit browsers, providing a visually appealing design for scrollable elements on your website.\ntags:\n  - web-development\n  - css\n---\n\nYour markdown content here...\n```\n\nExample inspiration post, with a video:\n\n```md\n---\ntemplateKey: inspiration\ntitle: \u003e\n  2Advanced Studios — Flash website in 2003\ndate: 2003-03-03T15:04:10.000Z\nfeatured: true\ndescription: \u003e\n  An old flash website (v4) of 2advanced.com, that has inspired me quite a lot in my teenage years.\ntags:\n  - animation\n  - flash\n  - website\nimage: /media/2advanced-flash-website-v4-2003.jpg\n---\n\n\u003cVideo src=\"/media/2advanced-flash-website-v4-2003.mp4\" /\u003e\n\n## © 2003 Advanced Studios\n\nCurrently, the 2Advanced Studios are closed for real, since some years already.\n```\n\n## 🖥️ Decap CMS\n\n### Run the CMS server\n\nTo use [Decap CMS](https://decapcms.org/), you'll need to run its server alongside your Next.js development server. This can be done by running the following command **in a separate terminal**:\n\n```bash\nnpx decap-server\n```\n\nYou can then access the CMS at http://localhost:3000/admin/index.html.\n\n\u003e [!NOTE]  \n\u003e If you'd like to test the CMS locally, set `local_backend: true` in `public/admin/config.yml`. Don't forget to restart the server after making changes.\n\n\u003e [!TIP]  \n\u003e For more information, refer to the [Decap CMS documentation](https://decapcms.org/docs/). If you'd like to see an advanced example of how to use Decap CMS, check out this [Decap CMS `config.yml` example](https://github.com/decaporg/decap-cms/blob/main/dev-test/config.yml).\n\n### Screenshots\n\n![Decap CMS - Screenshot](/screenshot--cms1.png)\n![Decap CMS - Screenshot](/screenshot--cms2.png)\n\n---\n\n## 📖 Configuration\n\nCustomize the project to suit your needs by editing the following files:\n\n- [`config.js`](https://github.com/ositaka/nextjs-blog-tailwind-starter/blob/main/config.js): Your Bleg Starter configuration.\n- [`tailwind.config.js`](https://github.com/ositaka/nextjs-blog-tailwind-starter/blob/main/tailwind.config.js): Tailwind CSS configuration.\n- [`next.config.js`](https://github.com/ositaka/nextjs-blog-tailwind-starter/blob/main/next.config.js): Next.js custom settings.\n- [`next-seo.config.js`](https://github.com/ositaka/nextjs-blog-tailwind-starter/blob/main/next-seo.config.js): SEO configuration for Next.js.\n- [`contentlayer.config.js`](https://github.com/ositaka/nextjs-blog-tailwind-starter/blob/main/contentlayer.config.ts): Contentlayer configuration for MDX files.\n- [`public/admin/config.yml`](https://github.com/ositaka/nextjs-blog-tailwind-starter/blob/main/public/admin/config.yml): Decap CMS configuration.\n\n### `next.config.js`:\n\n- The project uses the [**`next-image-export-optimizer`**](https://www.npmjs.com/package/next-image-export-optimizer) package to enhance image handling in static exports.\n- Custom settings for image optimization:\n  - **Image Folder**: Images are stored in the `public/media` folder.\n  - **Export Settings**: Optimized images are exported to the `out/` folder.\n  - **Quality**: Image quality is set to **75%**.\n  - **WEBP Format**: By default, the images are converted to **WEBP** for improved performance.\n  - **Blurred Placeholder**: Blurry placeholders are enabled for a smoother loading experience. To disable this, set `nextImageExportOptimizer_generateAndUseBlurImages` to `false` in your `.next.config.js` file, and pass `placeholder=\"empty\"` to all `\u003cExportedImage\u003e` components.\n\n\u003e [!NOTE]  \n\u003e Replace Next.js `\u003cImage /\u003e` components with `\u003cExportedImage /\u003e` to leverage these optimizations.\n\nExample usage:\n\n```tsx\nimport ExportedImage from 'next-image-export-optimizer'\n\n\u003cExportedImage\n  src=\"/media/example.jpg\"\n  alt=\"Example Image\"\n  width={800}\n  height={600}\n  placeholder=\"blur\"\n/\u003e\n```\n\n### TypeScript and Contentlayer Integration\n\nThis project uses [**Contentlayer**](https://contentlayer.dev/) to [automatically generate TypeScript types for your content](https://contentlayer.dev/docs/concepts/type-safety). The configuration is managed in the `contentlayer.config.ts` file located at the root of the project. Each document type (e.g., Blog, Inspiration, Podcasts, Tools, Pages) has its own structure and generated types, ensuring type safety when working with content in your components.\n\nBelow is an example of the TypeScript types generated for the **Blog** document:\n\n```ts\nimport { defineDocumentType, makeSource } from 'contentlayer2/source-files'\n\nconst Blog = defineDocumentType(() =\u003e ({\n  name: 'Blog',\n  filePathPattern: `blog/*.md`,\n  contentType: 'markdown',\n  fields: {\n    title: { type: 'string', required: true },\n    date: { type: 'date', required: false },\n    description: { type: 'string', required: false },\n    tags: { type: 'json', required: false },\n    templateKey: { type: 'string', required: true },\n    featured: { type: 'boolean', required: false },\n  },\n  computedFields: {\n    slug: {\n      type: 'string',\n      resolve: (doc) =\u003e doc._raw.sourceFileName.replace(/\\.md/, ''),\n    },\n  },\n}))\n\nexport default makeSource({\n  contentDirPath: 'content',\n  documentTypes: [Page, Blog, Inspiration, Podcasts, Tools, Resources],\n  disableImportAliasWarning: true,\n})\n```\n\n\u003e [!NOTE]  \n\u003e The `slug` field is automatically computed from the filename, removing the `.md` extension.\n\n#### Where to Find the Generated Types\n\nThe types are generated into the `./.contentlayer` directory and can be used throughout the application. Simply import the types from there:\n\n```tsx\nimport { allBlogs, Blog } from '../../.contentlayer/generated')\nimport { pick } from '@contentlayer2/client'\n```\n\n#### Working with Content in Components\n\nWhen working with content in your components, you can use the generated types to ensure type safety. For example, when mapping over blog posts:\n\n```tsx\nlet blogs = allBlogs.map((blog) =\u003e pick(blog, ['title', 'date', 'slug', 'description', 'templateKey'])\n```\n\nIn this example, `allBlogs` is an array of `Blog` types, and we're using the `pick` function to select specific fields from each blog post.\n\n#### Type Assertion\n\nWhen working with content from `allBlogs`, you can assert the type to ensure it's a `Blog` type:\n\n```tsx\nconst blog = allBlogs.find((b) =\u003e b.slug === params.slug) as Blog\n```\n\nThis way, you can access the fields of the `Blog` type without any issues.\n\n#### Passing Content to Components\n\nWhen passing content to components, you can use the `Blog` type to ensure the correct structure:\n\n```tsx\n\u003cBlogPostCard key={post.slug} post={post as Blog} /\u003e\n```\n\nWith these types in place, you can benefit from strong typing and auto-completion when working with your content.\n\n---\n\n## 🚀 Deploy\n\nDeploy your own instance of this blog starter project using one of the following providers:\n\n[![Deploy to Netlify](https://www.netlify.com/img/deploy/button.svg)](https://app.netlify.com/start/deploy?repository=https://github.com/ositaka/nextjs-blog-tailwind-starter/)\n[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/import/project?template=https://github.com/ositaka/nextjs-blog-tailwind-starter/)\n\n\u003e [!NOTE]  \n\u003e If you encounter errors related to **`sharp`** during deployment, please try removing the `package-lock.json` file, as this can sometimes resolve issues with Sharp's dependencies.\n\n### Setting up Netlify Identity with Decap CMS\n\nIf you're deploying your site with Netlify and using Decap CMS for content management, you'll need to enable [Netlify Identity](https://docs.netlify.com/security/secure-access-to-sites/identity/) to allow users to log in to the CMS at /admin.\n\n1. **Enable Identity**:\n\n   - Go to your site's dashboard on [Netlify](https://www.netlify.com/), navigate to the \"Identity\" tab, and click Enable Identity.\n\n2. **Configure Git Gateway**:\n\n   - In the Identity settings, enable Git Gateway. This will allow your CMS to interact with the repository via OAuth authentication.\n\n3. **Invite Users**:\n\n   - Invite yourself or other team members to the CMS. Go to the \"Identity\" tab, click Invite Users, and send invites via email.\n\n4. **Login Access**:\n\n   - Once enabled, users can log in to the /admin panel using their Netlify Identity credentials.\n\nHere's a preview of how this might look in your `config.yml` for Decap CMS:\n\n```yaml\nbackend:\n  name: git-gateway\n  branch: main\n```\n\nTo enable Netlify Identity in this starter project, the following component is used in the `layout.tsx` file:\n\n```tsx\n\u003cNetlifyIdentityRedirect /\u003e\n```\n\nThis component automatically redirects users to the login page if they are not authenticated.\n\n\u003e [!TIP]  \n\u003e For more information on setting up Netlify Identity with Decap CMS, visit the [Decap CMS documentation – Choosing a Backend](https://decapcms.org/docs/choosing-a-backend).\n\n---\n\n## 📄 License\n\nThis project is licensed under the MIT License. See the [LICENSE](/LICENSE) file for details.\n\n---\n\n## 📣 Contributing\n\nContributions are welcome! Here are some ways you can help improve the project:\n\n- **Bug Fixes**: If you encounter any issues, please submit an issue or pull request to address it.\n- **Feature Additions**: Have an idea for a new feature? Open an issue to discuss it or submit a pull request with your implementation.\n- **Documentation Improvements**: Help us enhance the README by suggesting edits or additional information.\n\n### How to Contribute\n\n1. Fork the repository\n2. Create a new branch (`git checkout -b feature/your-feature-name`)\n3. Make your changes\n4. Push to your branch (`git push origin feature/your-feature-name`)\n5. Create a pull request\n\nThank you for considering contributing to the project!\n\n## 🔗 Links\n\n- [Demo](https://nextjs-blog-tailwind-starter.netlify.app/)\n- [Documentation](https://github.com/ositaka/nextjs-blog-tailwind-starter/blob/main/README.md)\n- [GitHub Repo](https://github.com/ositaka/nextjs-blog-tailwind-starter)\n\n---\n\n## 🙌 Acknowledgments\n\nBuilt with ❤️ in 🇵🇹 and 🇧🇪 using [Next.js](https://nextjs.org/) (an amazing open-source React framework), [Tailwind CSS](https://tailwindcss.com/) (for rapid UI development), [Contentlayer](https://contentlayer.dev/) (for managing content), and [Decap CMS](https://decapcms.org/) (for a user-friendly content management experience).\n\nA big thank you to the communities behind these projects for their hard work and dedication!\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fositaka%2Fnextjs-blog-tailwind-starter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fositaka%2Fnextjs-blog-tailwind-starter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fositaka%2Fnextjs-blog-tailwind-starter/lists"}