Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork88
A developer blog starter for 2021 (Next.js + React + TypeScript + Markdown + syntax highlighting)
License
colinhacks/devii
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
A developer blog starter for 2020.
Next.js
React
TypeScript
Markdown
syntax highlighting
SEO
RSS generation
if you're happy and you know it, star this repo
- Works as a Markdown-based static-site generator out of the box: just add new blog posts to
/md/blog
- Supports exporting to fully static assets (powered by Next.js)
- Hot reload (powered by Next.js)
- Makes it easy to write custom pages/code in React + TypeScript
- Provides a
Markdown.tsx
component with support for GitHub-style syntax highlighting - Automatic RSS feed generation
- SEO best practices (title tag, meta tags, canonical URLs)
Read more about the motivation + design behind Devii athttps://colinhacks.com/blog/devii.
This repo contains the code forhttps://devii.dev.
devii.dev serves as both the documentation AND a working demo of Devii. After you clone/fork it, you can look through the code to learn how Devii works. Then you can rip out everything you don't like, customize everything else, and build your own tools and components on top of the foundation Devii provides!
Your personal website is the online manifestation of you. Devii doesn't really provide much out of the box. It provides some nice Medium-style default styles for your blog posts and some tools for loading/rendering Markdown. But you'll have to implement your own homepage more or less from scratch. And that's the point! Don't settle for some theme. Build something that represents you.
To get started:
- Fork this repo
git clone git@github.com:yourusername/devii.git my-blogcd my-blogyarn
- Start the development server with
yarn dev
. This should start a server onhttp://localhost:3000
.
The core of this repo isNext.js. We chose Next.js because it's the simplest, most elegant way to generate a static version of a React-based website. The documentation is excellent; read it first:Next.js Documentation.
Here's is an abbreviated version of the project structure. Certain config files (next.config.js
,next-end.d.ts
,.gitignore
) have been removed for simplicity.
.├── README.md├── public // all static assets (images, css, etc) go here├── pages // every .tsx component in this dir becomes a page of the final site| ├── index.tsx // the home page (which has access to the list of all blog posts)| ├── blog| ├── [blog].md // a template component that renders the blog posts under `/md/blog`├── md| ├── blog| ├── devii.md // this page! ├── whatever.md // every MD file in this directory becomes a blog post├── components| ├── BlogPost.tsx| ├── Code.tsx| ├── Footer.tsx| ├── Header.tsx| ├── Markdown.tsx| ├── Meta.tsx| ├── <various>├── loader.ts // contains utility functions for loading/parsing Markdown├── node_modules├── tsconfig.json├── package.json
Next.js generates a new webpage for each file in thepages
directory. If you want to add an About page to your blog, just addabout.tsx
insidepages
and start writing the page.
By default the repo only contains two pages: a home page (/pages/index.tsx
) and a blog page (/pages/[blog].md
).
The file[blog].ts
follows the Next.js convention of using square brackets to indicate adynamic route.
The home page is intentionally minimal. You can put whatever you want inindex.tsx
; one of our goals in designing Devii was to place no restrictions on the developer. Use your imagination! Your website is the online manifestion of you. You can use whatever npm packages or styling libraries you like.
Devii is unopinionated about styling. Because your Devii site is a standard React app under the hood, you can use your favorite library fromnpm
to do styling.
Devii provides certain styles by default, notably in the Markdown renderer (/components/Markdown.tsx
). Those styles are implemented using Next's built-in styling solutionstyled-jsx
. Unfortunately it was necessary to make those styles global, sincestyled-jsx
doesn't play nice with third-party components (in this casereact-markdown
).
Feel free to re-implemement the built-in styles with your library of choice If you choose to use a separate styling library (emotion is pretty glorious) then you could re-implement the default styles
Just add a Markdown file undermd/blog/
to create a new blog post:
- Create a new Markdown file called
foo.md
within the/md/blog
directory - Add in some basic Markdown content
- Then go to
http://localhost:3000/blog/foo
. You should see the new post.
Every Markdown file can include a "frontmatter block" containing various metadata. Devii provides aloadPost
utility that loads a Markdown file, parses it's frontmatter metadata, and returns a structuredPostData
object:
typePostData={path:string;title?:string;subtitle?:string;description?:string;// used for SEOcanonicalUrl?:string;// used for SEOdatePublished?:number;// Unix timestampauthor?:string;authorPhoto?:string;authorHandle?:string;// twitter handletags?:string[];bannerPhoto?:string;thumbnailPhoto?:string;};
For example, here is the frontmatter blog from the sample blog post (md/blog/the-ultimate-tech-stack.md
):
---title: Introducing Deviisubtitle: Bringing the power of React, TypeScript, and static generation to dev blogs everywheredatePublished: 1589064522569author: Ben Bitdiddletags: - Devii - BlogsauthorPhoto: /img/profile.jpgbannerPhoto: /img/brook.jpgthumbnailPhoto: /img/brook.jpg---
View/loader.ts
to see how this works.
Just add your Google Analytics ID (e.g. 'UA-999999999-1') toglobals.ts
and Devii will automatically add the appropriate Google Analytics snippet to your site. Go to/pages/_app.ts
to see how this works or customize this behavior.
The Markdown renderer (Markdown.tsx
) provides a default style inspired by Medium. Just modify the CSS inMarkdown.tsx
to customize the design to your liking.
You can easily drop code blocks into your blog posts using triple-backtick syntax (just like GitHub). No more embedding CodePen iframes! 🚀
Works out-of-the-box for all programming languages. Specify your language with a "language tag". So this:
```ts // pretty neat huh? const test = (arg: string) => { return arg.length > 5; }; ```
turns into
// pretty neat huh?consttest=(arg:string)=>{returnarg.length>5;};
View/components/Code.tsx
to see how this works or customize this behavior.
You don't need to understand all of this to use Devii. Consider this an "advanced guide" you can use if you want to customize the structure of the site.
Markdown posts are loaded during Next.js static build step. Check out theData Fetching documentation to learn more about this.
Here's the short version: if export a function calledgetStaticProps
from one of your page components, Next.js will execute that function, take the result, and pass theprops
property (which should be another object) into your page as props.
You can dynamically load and parse a Markdown file usingloadMarkdownFile
, a utility function implemented inloader.ts
. It is an async function that returns aPostData
TypeScript object containing all the metadata keys listed above:
For an example of this, check out thegetStaticProps
implementation from the homepage. The function callsloadBlogPosts
- a utilty function that loadsevery blog posts in the/md/blog/
directory, parses them, and returnsPostData[]
.
exportconstgetStaticProps=async()=>{constposts=awaitloadBlogPosts();return{props:{ posts}};};
There are a few utility functions inloader.ts
that Devii uses. All functions areasync! All functions accept arelative path which is expected to be _relative to themd/
directory. For instanceloadPost('blog/test.md'
) would load/md/blog/test.md
.
loadPost
loads/parses a Markdown file and returns aPostData
loadBlogPosts
: loads/parses all the files in/md/blog/
. ReturnsPostData[]
. Used inindex.tsx
to load/render a list of all published blog postsloadMarkdownFile
: loads a Markdown file but doesn't parse it. Returns the string content. Useful if you want to implement some parts of a page in Markdown and other parts in ReactloadMarkdownFiles
: accepts aglob pattern and loads all the files inside/md/
whose names match the pattern. Used internally byloadBlogPosts
You can generate a fully static version of your site usingyarn build && yarn export
. This step is entirely powered by Next.js. The static site is exported to theout
directory.
After it's generated, use your static file hosting service of choice (Vercel, Netlify, Firebase Hosting, Amazon S3) to deploy your site.
There is aglobals.ts
file in the project root containing some settings/configuration metadata about your site:
yourName
: Your name, used for the copyright tags in the footer and the RSS feed, e.g. Alyssa P. HackersiteName
: The title of your blog, e.g.Alyssa's Cool Blog
;siteDescription
: A short description, used in themeta
description tag, e.g. 'I write about code 'n stuff';siteCreationDate
: Used in the generated RSS feed. Use this format: 'March 3, 2020 04:00:00 GMT';twitterHandle
: The twitter handle for you or your blog/company, used in the Twitter meta tags. Include the @ symbol, e.g. '@alyssaphacker';email
: Your email, used as the "webMaster" and "managingEditor" field of the generated RSS feed, e.g.alyssa@example.com
;url
: The base URL of your website, used to "compute" default canonical links from relative paths, e.g. 'https://alyssaphacker.com';accentColor
: The header and footer background color, e.g.#4fc2b4
;
An RSS feed is auto-generated from your blog post feed. This feed is generated using therss
module (for converting JSON to RSS format) andshowdown
for converting the markdown files to RSS-compatible HTML.
For RSS generation to work, all your posts must contain adatePublished
timestamp in their frontmatter metadata. To examine or customize the RSS generation, check out therssUtil.ts
file in the root directory.
Every blog post page automatically populated meta tags based on the post metadata. This includes atitle
tag,meta
tags,og:
tags, Twitter metadata, and alink
tag containing the canonical URL.
The default value of the canonical URL is computed by concatenating the value of yoururl
config (see Global Configs above) and the relative path of your post. Verify that the canonical URL is exactly equivalent to the URL in the browser when visiting your live site, otherwise your site's SEO may suffer.
There's nothing "under the hood" here. You can view and modify all the files that provide the functionality listed above. Devii just provides a project scaffold, some Markdown-loading loading utilities (inloader.ts
), and some sensible styling defaults (especially inMarkdown.tsx
).
To get started customizing, check out the source code ofindex.tsx
(the home page),BlogPost.tsx
(the blog post template), andMarkdown.tsx
(the Markdown renderer).
Head to the GitHub repo to get started:https://github.com/colinhacks/devii. If you like this project, leave a ⭐️star⭐️ to help more people find Devii 😎
Starts the development server. Equivalent tonext dev
.
Creates an optimized build of your site. Equivalent tonext build
.
Exports your site to static files. All files are written to/out
. Use your static file hosting service of choice (Firebase Hosting, Amazon S3, Vercel) to deploy your site. Equivalent tonext export
.
About
A developer blog starter for 2021 (Next.js + React + TypeScript + Markdown + syntax highlighting)
Topics
Resources
License
Uh oh!
There was an error while loading.Please reload this page.
Stars
Watchers
Forks
Sponsor this project
Uh oh!
There was an error while loading.Please reload this page.
Packages0
Uh oh!
There was an error while loading.Please reload this page.
Contributors4
Uh oh!
There was an error while loading.Please reload this page.