|
1 | | -# Hashnode-source-from-github-template |
2 | | -A template with boilerplate structure for Hashnode's Github as source feature |
| 1 | +# Publish to Hashnode from GitHub |
3 | 2 |
|
4 | | -Please note: A **README.md** at the root is always ignored. |
| 3 | +Write blog posts as markdown files in this repository. Push to main, and they publish to your Hashnode publication through the [Publish to Hashnode GitHub Action](https://github.com/Hashnode/publish-github-action). |
5 | 4 |
|
6 | | -If you don't find a log in your publication dashboard on Hashnode, but have made a commit to your connected repo, then make sure |
| 5 | +Publishing via the API requires a publication on [Hashnode Pro](https://hashnode.com/pro). |
7 | 6 |
|
8 | | -* the file ends with .md extension, we support markdown files only. |
9 | | -* you have connected the same repo as you made a commit to. |
10 | | -* you added the correct blog domain in your markdown file. |
11 | | -* Frontmatter: Make sure each article has these details at the top of the file. |
12 | | -* A **README.md** at the root is always ignored. |
| 7 | +## Setup |
13 | 8 |
|
14 | | -## Supported front matter fields and their description |
| 9 | +1. Click **Use this template** to create your own copy of this repository. |
| 10 | +2. Generate a Personal Access Token in [Settings → Developer](https://hashnode.com/settings/developer) on Hashnode. |
| 11 | +3. In your new repository, add the token as a secret named `HASHNODE_PAT` (Settings → Secrets and variables → Actions). |
| 12 | +4. Open `.github/workflows/publish-to-hashnode.yml` and replace `YOUR_BLOG.hashnode.dev` with your publication host. |
| 13 | +5. Edit `posts/example-post.md` or add a new `.md` file under `posts/`, commit, and push. |
15 | 14 |
|
16 | | -``` |
| 15 | +That's it. Each push publishes new files and updates changed ones. The workflow's run summary shows what happened to every file. |
| 16 | + |
| 17 | +## Writing posts |
| 18 | + |
| 19 | +Every post is a markdown file with YAML frontmatter. Only `title` is required. Set a stable `slug`: it is how a file stays linked to its published post across pushes. |
| 20 | + |
| 21 | +A post using every supported field: |
| 22 | + |
| 23 | +```yaml |
17 | 24 | --- |
18 | | -# Post Title |
19 | | -# String | *REQUIRED* |
20 | | -# Ex: Top 4 React UI Libraries for 2023 |
21 | | -title: Example title here |
22 | | - |
23 | | -# Post Slug |
24 | | -# What is slug? https://www.semrush.com/blog/what-is-a-url-slug |
25 | | -# String | *REQUIRED* |
26 | | -# Ex: top-4-react-ui-libraries-for-2023 |
27 | | -# - This is the URL of the post. It should be unique and should not be used by any other post. |
28 | | -# - If you use the same slug of an existing post, the existing post will be updated. |
29 | | -# - In order to let users update the post SLUG, we depend on the post slug as well |
30 | | -# as it's path in the repo. |
31 | | -# - If you change both path and slug of the post, the post will be treated as a new post and |
32 | | -# will be published with a new slug. |
33 | | -# - If you change only the slug of the post, the post will be updated with the new slug. |
34 | | -# - If you change only the path of the post, the post will be will be updated with new path |
35 | | -# and any other changes along with it if any. |
36 | | -slug: example-slug |
37 | | - |
38 | | -# Tags |
39 | | -# String (comma-separated tag slugs) | *REQUIRED* |
40 | | -# Ex: reactjs, css, python, nodejs |
41 | | -# Upto 5 tag slugs |
42 | | -# - You can find tags information from here https://github.com/Hashnode/support/blob/main/misc/tags.json |
43 | | -# You can also update a post to edit this later. |
44 | | -tags: reactjs, css, python, nodejs |
45 | | - |
46 | | -# Publication Domain (hashnode.dev subdomain or your custom domain) |
47 | | -# String | *REQUIRED* |
48 | | -# Ex: townhall.hashnode.com |
49 | | -# - This can also be a hashnode.dev subdomain as well. |
50 | | -# - The publication domain name that you want to publish the post to. |
51 | | -# This should be a valid domain name only. |
52 | | -# - You should be an ADMIN of the publication to publish. |
53 | | -domain: example.hashnode.dev |
54 | | - |
55 | | -# Subtitle of the post |
56 | | -# String | Optional |
57 | | -# Ex: A curated list of the best React UI libraries for 2023 |
58 | | -subtitle: |
59 | | - |
60 | | -# Cover Image URL of the post |
61 | | -# String | Optional |
62 | | -# Note: You must upload the image to Hashnode's CDN, before you can use it here. |
63 | | -# Ex: https://cdn.hashnode.com/res/hashnode/image/upload/v1681132538878/itnaYF1h-.png |
64 | | -# - To upload, Login to Hashnode and go to https://hashnode.com/uploader |
65 | | -# Use the URL that is generated after the upload. |
66 | | -cover: |
67 | | - |
68 | | -# Should the post be ignored? When true it will not be picked up by Hashnode. |
69 | | -# Boolean | Optional |
70 | | -# Default value: false |
71 | | -# Ex: true |
72 | | -# - It's useful when you want to keep the post in your repo but don't |
73 | | -# want it to be picked up by Hashnode. |
74 | | -ignorePost: |
75 | | - |
76 | | -# Publish on behalf of a team publication member |
77 | | -# Username of the publication member |
78 | | -# String | Optional | *WORKS WITH TEAM PUBLICATION ONLY* |
79 | | -# Ex: sandeep |
80 | | -# - This resembles the Change of author from draft settings of a |
81 | | -# team publication in Hashnode editor. |
82 | | -# - Fails if the user is not a member of the team publication or |
83 | | -# if the publication is not a team publication |
84 | | -publishAs: |
85 | | - |
86 | | -# Canonical URL of the post |
87 | | -# String | Optional |
88 | | -# What is a canonical URL? https://moz.com/learn/seo/canonicalization |
89 | | -# Ex: https://www.hashnode.com/post/top-4-react-ui-libraries-for-2023 |
90 | | -# - This is equivalent to original URL option present in draft settings |
91 | | -# of a post in Hashnode editor. |
92 | | -# - This is useful when you want to publish a post that is already |
93 | | -# published on another platform. |
94 | | -canonical: |
95 | | - |
96 | | - |
97 | | -# Hide from Hashnode Community |
98 | | -# Boolean | Optional |
99 | | -# Default value: false // by default the post will be visible in the Hashnode's public feed. |
100 | | -# Ex: true |
101 | | -# - This is equivalent to "HIDE ARTICLE FROM HASHNODE FEED" option |
102 | | -# present in draft settings of a post in Hashnode editor. |
103 | | -# - This is useful when you want to publish a post to your publication |
104 | | -# only but hide it from the Hashnode's public feed. |
105 | | -# - You can also update a post to enable/disable this later. |
106 | | -hideFromHashnodeCommunity: |
107 | | - |
108 | | -# SEO Title |
109 | | -# String | Optional |
110 | | -# Ex: Top 4 React UI Libraries for 2023 |
111 | | -# - This is equivalent to SEO TITLE option present in draft settings |
112 | | -# of a post in Hashnode editor. |
113 | | -# - You can also update a post to update this later. |
114 | | -seoTitle: |
115 | | - |
116 | | -# SEO Description |
117 | | -# String | Optional |
118 | | -# Ex: A curated list of the best React UI libraries for 2023 |
119 | | -# - This is equivalent to SEO DESCRIPTION option present in |
120 | | -# draft settings of a post in Hashnode editor. |
121 | | -# - You can also update a post to update this later. |
122 | | -seoDescription: |
123 | | - |
124 | | -# Disable comments for a post |
125 | | -# Boolean | Optional |
126 | | -# Default value: false // by default the comments will be enabled for the post. |
127 | | -# Ex: true |
128 | | -# - This is equivalent to "DISABLE COMMENTS" option present in |
129 | | -# draft settings of a post in Hashnode editor. |
130 | | -# - You can also update a post to enable/disable this later. |
131 | | -disableComments: |
132 | | - |
133 | | -# Slug of the series that you want your post to be a part of |
134 | | -# String | Optional |
135 | | -# Ex: react-series |
136 | | -# - This is equivalent to "ADD TO A SERIES" option present in |
137 | | -# draft settings of a post in Hashnode editor. |
138 | | -# - If invalid series is given, the post will not be added to any series. |
139 | | -# - You can update the post again to correct it later. |
140 | | -# - You can find series information from the series section in your publication dashboard. |
141 | | -# You can also edit the series information from there. |
142 | | -seriesSlug: // slug of the series |
143 | | - |
144 | | -# Table of contents |
145 | | -# Boolean | Optional |
146 | | -# Default value: false // by default the table of contents will not be added to the post. |
147 | | -# Ex: true |
148 | | -# - This is equivalent to "GENERATE TABLE OF CONTENTS" option |
149 | | -# present in draft settings of a post in Hashnode editor. |
150 | | -# - If true, the table of contents will be added to the post. |
151 | | -# - You can also update a post to enable/disable this later. |
152 | | -enableToc: |
153 | | - |
154 | | -# Save post as draft |
155 | | -# Boolean | Optional |
156 | | -# Default value: false // by default the post will be published. |
157 | | -# Ex: true |
158 | | -# - If true, the post will be saved as a draft. |
159 | | -# - You can also update a draft with all the above attributes. |
160 | | -# - This draft will be available under Drafts section of the |
161 | | -# left sidebar in your publication dashboard. |
162 | | -# - Note: Once you remove this attribute, the post will be |
163 | | -# published and removed from drafts automatically. |
164 | | -# - This follows the same rules as a post create and update |
165 | | -# flow as well as the slug rules mentioned since |
166 | | -# beginning of this manual. |
167 | | -saveAsDraft: |
168 | | - |
169 | | - |
170 | | -# Note: |
171 | | -# This is in beta currently |
172 | | -# Newsletter and Post scheduling is NOT supported as of now. |
173 | | - |
| 25 | +title: How I built my blog |
| 26 | +slug: how-i-built-my-blog |
| 27 | +subtitle: A tour of the stack |
| 28 | +tags: javascript, nextjs, web-dev |
| 29 | +cover: ./images/cover.png |
| 30 | +seriesSlug: building-in-public |
| 31 | +canonical: https://example.com/original |
| 32 | +seoTitle: How I built my blog with Next.js |
| 33 | +seoDescription: A walkthrough of the stack behind my blog. |
| 34 | +ogImage: https://example.com/og.png |
| 35 | +enableToc: true |
| 36 | +disableComments: false |
| 37 | +publishedAt: 2026-07-01T09:00:00Z |
| 38 | +saveAsDraft: false |
| 39 | +ignorePost: false |
| 40 | +hideFromCommunity: false |
| 41 | +publishAs: someusername |
| 42 | +coAuthors: user1, user2 |
| 43 | +domain: other-blog.hashnode.dev |
174 | 44 | --- |
175 | | -``` |
176 | | -* List of tags can be found here https://github.com/Hashnode/support/blob/main/misc/tags.json |
177 | | -* Make sure you haven't included **ignorePost** in the frontmatter by mistake. |
178 | | -* Uninstalling app via Github will remove it from all the publications that the repo was connected to. If you want to specifically remove the installation from a particular publication, do it from it's Dashboard (GitHub section). |
179 | | -* You cannot create a new draft or a post with already published slugs |
180 | | -* Do note that maximum of 10 file changes are respected in one particular commit. |
| 45 | +``` |
181 | 46 |
|
| 47 | +| Field | Notes | |
| 48 | +| --------------------------------------- | ----------------------------------------------------------------------------------- | |
| 49 | +| `title` | Required | |
| 50 | +| `slug` | Defaults to a slug of the title. Keep it stable. It is the update key | |
| 51 | +| `subtitle` | Shown under the title | |
| 52 | +| `tags` | Comma-separated or YAML list of tag slugs, max 15. Unknown tags are created | |
| 53 | +| `cover` | Cover image URL, or a repo path that gets uploaded to the CDN (alias: `coverImage`) | |
| 54 | +| `seriesSlug` | Slug of an existing series in your publication | |
| 55 | +| `canonical` | Canonical URL if the article was first published elsewhere (alias: `canonicalUrl`) | |
| 56 | +| `seoTitle`, `seoDescription`, `ogImage` | SEO and Open Graph overrides | |
| 57 | +| `enableToc` | Show a table of contents | |
| 58 | +| `disableComments` | Disable comments on the post | |
| 59 | +| `publishedAt` | ISO 8601 date, backdates the post | |
| 60 | +| `saveAsDraft` | Create a draft instead of publishing (new posts only) | |
| 61 | +| `ignorePost` | Skip this file entirely | |
| 62 | +| `hideFromCommunity` | Delist the post from feeds (alias: `hideFromHashnodeCommunity`) | |
| 63 | +| `publishAs` | Username of a publication member to publish as (team publications) | |
| 64 | +| `coAuthors` | Usernames of publication members, max 4 | |
| 65 | +| `domain` | Optional per-file publication override | |
182 | 66 |
|
| 67 | +## Good to know |
183 | 68 |
|
| 69 | +- **Create vs update.** The action looks up your `slug` in the publication. Found, the post is updated in place; not found, a new post is published. If your slug is already taken by another post, the API assigns a suffixed slug and the run summary warns you. |
| 70 | +- **Images.** Relative image paths (body and `cover`) upload to the Hashnode CDN automatically and resolve relative to the markdown file; a leading `/` resolves from the repository root. Supported: jpg, png, gif, webp, avif, up to 8 MB each. SVG is not supported. Absolute URLs pass through untouched. |
| 71 | +- **Drafts.** `saveAsDraft: true` creates a draft for new posts. Re-pushing the same file while it is still a draft creates another draft, so publish or remove the flag once done. |
| 72 | +- **Deletes.** Deleting a markdown file never deletes the post. Manage published posts from your dashboard. |
| 73 | +- Up to 10 changed files are processed per push by default (the `max-files` input raises it). |
0 commit comments