Write once, publish everywhere. That was the goal when I built my personal blog.
For years, I published articles directly on DEV.to because of its amazing developer community and reach. But I also wanted a blog on my own domain where I had complete control over the design, branding, and user experience.
Instead of maintaining two separate blogs, I decided to make DEV.to my CMS and let my website fetch articles automatically using the DEV.to API.
The result is my personal blog:
π https://blog.ashraful.dev/
Every time I publish a new article on DEV.to, it automatically appears on my website. No copy-pasting. No duplicated content. No extra work. :contentReference[oaicite:0]{index=0}
The Problem
Initially, my workflow looked like this:
- Write the article.
- Publish it on DEV.to.
- Copy the Markdown.
- Paste it into my website.
- Fix formatting.
- Publish again.
This wasn't difficult, but it was repetitive.
Every blog post required maintaining two separate copies of the same content.
Eventually, I asked myself:
Why am I manually copying content when DEV.to already provides an API?
That simple question completely changed my blogging workflow.
Why I Chose DEV.to
There are many blogging platforms available:
- Medium
- Hashnode
- Ghost
- WordPress
- Notion
I chose DEV.to because:
- It has a large developer community.
- Articles are easily discoverable.
- Markdown support is excellent.
- It provides a free public API.
- I don't need to manage another CMS. :contentReference[oaicite:1]{index=1}
Instead of building an admin panel for my blog, I simply use DEV.to as the content management system.
The Architecture
My setup is surprisingly simple.
Write Article
β
βΌ
DEV.to
β
DEV.to API
β
βΌ
Personal Website
(blog.ashraful.dev)
My website never stores blog posts locally.
Instead, it fetches them directly from the DEV.to API whenever needed.
This keeps everything synchronized automatically.
Fetching Articles
DEV.to exposes a public endpoint for fetching a user's published articles.
Example:
GET https://dev.to/api/articles?username=YOUR_USERNAME
In JavaScript:
const response = await fetch(
"https://dev.to/api/articles?username=ashraful"
);
const posts = await response.json();
The response includes useful metadata like:
- Title
- Description
- Cover image
- Published date
- Tags
- Reading time
- Slug
- URL
No authentication is required for public articles. :contentReference[oaicite:2]{index=2}
Loading a Single Blog Post
Listing articles is only half the job.
When a visitor clicks on an article, the website fetches its full content.
The API endpoint looks like this:
GET https://dev.to/api/articles/{username}/{slug}
Example:
GET https://dev.to/api/articles/ashraful/my-awesome-post
The response contains:
- Markdown
- Rendered HTML
- Cover image
- Metadata
- Reactions
- Comments count
The most important field for me is:
{
"body_markdown": "# My Blog Post..."
}
That's exactly what I render on my website. :contentReference[oaicite:3]{index=3}
Rendering Markdown
Once I receive the Markdown, I render it like any normal Markdown document.
This gives me complete control over:
- Typography
- Code highlighting
- Tables
- Images
- Custom components
Because the original content is still Markdown, I don't lose any formatting.
My Publishing Workflow
Publishing a new article has become incredibly simple.
Write Article
β
βΌ
Publish to DEV.to
β
βΌ
Done β
That's it.
There's no second publishing step.
The website automatically displays the new article because it always reads from the API.
Benefits of This Approach
Single Source of Truth
There's only one copy of every article.
I never have to wonder:
"Which version is the latest?"
DEV.to is always the source.
No Duplicate Work
Before:
Publish to DEV.to
β
Copy Markdown
β
Paste into Website
β
Publish Again
Now:
Publish to DEV.to
β
Finished
One click instead of many.
Better SEO
One concern when publishing content on multiple websites is duplicate content.
The good news is that DEV.to supports canonical URLs, allowing search engines to understand which version should be treated as the original. This helps avoid SEO issues when cross-posting articles. :contentReference[oaicite:4]{index=4}
Custom Design
Although the content comes from DEV.to, my website has its own:
- Layout
- Branding
- Navigation
- Theme
- Search
- Reading experience
Visitors get a consistent experience while I continue using DEV.to as the backend.
Performance Considerations
Calling an external API on every request isn't always ideal.
To improve performance, you can:
- Cache API responses.
- Use Incremental Static Regeneration (ISR).
- Pre-render popular articles.
- Refresh the cache periodically.
This reduces API requests while keeping content up to date.
Error Handling
Whenever you depend on an external API, you should plan for failures.
For example:
- API downtime
- Rate limits
- Network issues
- Invalid responses
A simple fallback page or cached copy can greatly improve the user experience.
Why I Like This Setup
This approach gives me the best of both worlds.
I get:
- The reach of DEV.to.
- A fully customized personal website.
- No CMS maintenance.
- No duplicate content management.
- One publishing workflow.
Most importantly, I spend my time writing instead of maintaining content in multiple places.
Could You Do the Same?
Absolutely.
If you already publish on DEV.to, you can build your own blog in just a few hours using its public API.
Whether you're using:
- Next.js
- React
- Vue
- Nuxt
- Svelte
- Astro
the process is almost identical:
- Fetch articles.
- Display the list.
- Fetch a single article by slug.
- Render the Markdown.
- Style it however you like.
The API is simple, well documented, and perfect for personal portfolio websites. :contentReference[oaicite:5]{index=5}
Final Thoughts
Building my blog around the DEV.to API has been one of the simplest yet most rewarding improvements to my personal website.
Instead of managing two separate publishing platforms, I now have a single workflow: write once, publish once, and let the API do the rest.
If you're already sharing technical articles on DEV.to and want a blog on your own domain, I highly recommend giving this approach a try. It's lightweight, developer-friendly, and removes a lot of repetitive workβletting you focus on what matters most: writing great content.
Top comments (0)