[{"data":1,"prerenderedAt":38},["ShallowReactive",2],{"article-how-i-built-my-personal-blog-using-the-devto-api-142a":3},{"type_of":4,"id":5,"title":6,"description":7,"readable_publish_date":8,"slug":9,"path":10,"url":11,"comments_count":12,"public_reactions_count":12,"collection_id":13,"published_timestamp":14,"language":15,"subforem_id":16,"positive_reactions_count":12,"cover_image":17,"social_image":18,"canonical_url":19,"created_at":14,"edited_at":20,"crossposted_at":13,"published_at":14,"last_comment_at":14,"reading_time_minutes":21,"tag_list":22,"tags":23,"body_html":27,"body_markdown":28,"user":29},"article",4193660,"How I Built My Personal Blog Using the DEV.to API","Write once, publish everywhere. That was the goal when I built my personal blog.   For years, I...","Jul 21","how-i-built-my-personal-blog-using-the-devto-api-142a","\u002Fashraful\u002Fhow-i-built-my-personal-blog-using-the-devto-api-142a","https:\u002F\u002Fdev.to\u002Fashraful\u002Fhow-i-built-my-personal-blog-using-the-devto-api-142a",0,null,"2026-07-21T06:42:56Z","en",1,"https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=1000,height=420,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7rthla1i36vwt0w2g259.png","https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=1200,height=627,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7rthla1i36vwt0w2g259.png","https:\u002F\u002Fblog.ashraful.dev\u002Farticle\u002Fhow-i-built-my-personal-blog-using-the-devto-api-142a","2026-07-21T06:43:30Z",4,"devto, blogging, resources",[24,25,26],"devto","blogging","resources","\u003Cblockquote>\n\u003Cp>\u003Cstrong>Write once, publish everywhere.\u003C\u002Fstrong> That was the goal when I built my personal blog.\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\n\u003Cp>For years, I published articles directly on \u003Cstrong>DEV.to\u003C\u002Fstrong> 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.\u003C\u002Fp>\n\n\u003Cp>Instead of maintaining two separate blogs, I decided to make \u003Cstrong>DEV.to my CMS\u003C\u002Fstrong> and let my website fetch articles automatically using the DEV.to API.\u003C\u002Fp>\n\n\u003Cp>The result is my personal blog:\u003C\u002Fp>\n\n\u003Cp>👉 \u003Cstrong>\u003Ca href=\"https:\u002F\u002Fblog.ashraful.dev\u002F\" target=\"_blank\" rel=\"noopener noreferrer\">https:\u002F\u002Fblog.ashraful.dev\u002F\u003C\u002Fa>\u003C\u002Fstrong>\u003C\u002Fp>\n\n\u003Cp>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}\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"the-problem\" href=\"#the-problem\">\n  \u003C\u002Fa>\n  The Problem\n\u003C\u002Fh1>\n\n\u003Cp>Initially, my workflow looked like this:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Write the article.\u003C\u002Fli>\n\u003Cli>Publish it on DEV.to.\u003C\u002Fli>\n\u003Cli>Copy the Markdown.\u003C\u002Fli>\n\u003Cli>Paste it into my website.\u003C\u002Fli>\n\u003Cli>Fix formatting.\u003C\u002Fli>\n\u003Cli>Publish again.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>This wasn't difficult, but it was repetitive.\u003C\u002Fp>\n\n\u003Cp>Every blog post required maintaining two separate copies of the same content.\u003C\u002Fp>\n\n\u003Cp>Eventually, I asked myself:\u003C\u002Fp>\n\n\u003Cblockquote>\n\u003Cp>Why am I manually copying content when DEV.to already provides an API?\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\n\u003Cp>That simple question completely changed my blogging workflow.\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"why-i-chose-devto\" href=\"#why-i-chose-devto\">\n  \u003C\u002Fa>\n  Why I Chose DEV.to\n\u003C\u002Fh1>\n\n\u003Cp>There are many blogging platforms available:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Medium\u003C\u002Fli>\n\u003Cli>Hashnode\u003C\u002Fli>\n\u003Cli>Ghost\u003C\u002Fli>\n\u003Cli>WordPress\u003C\u002Fli>\n\u003Cli>Notion\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>I chose DEV.to because:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>It has a large developer community.\u003C\u002Fli>\n\u003Cli>Articles are easily discoverable.\u003C\u002Fli>\n\u003Cli>Markdown support is excellent.\u003C\u002Fli>\n\u003Cli>It provides a free public API.\u003C\u002Fli>\n\u003Cli>I don't need to manage another CMS. :contentReference[oaicite:1]{index=1}\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Instead of building an admin panel for my blog, I simply use DEV.to as the content management system.\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"the-architecture\" href=\"#the-architecture\">\n  \u003C\u002Fa>\n  The Architecture\n\u003C\u002Fh1>\n\n\u003Cp>My setup is surprisingly simple.\u003Cbr>\n\u003C\u002Fp>\n\n\u003Cdiv class=\"highlight js-code-highlight\">\n\u003Cpre class=\"highlight plaintext\">\u003Ccode>            Write Article\n                  │\n                  ▼\n              DEV.to\n                  │\n            DEV.to API\n                  │\n                  ▼\n          Personal Website\n      (blog.ashraful.dev)\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"highlight__panel js-actions-panel\">\n\u003Cdiv class=\"highlight__panel-action js-fullscreen-code-action\">\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\">\u003Ctitle>Enter fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\">\u003Ctitle>Exit fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\n\n\n\u003Cp>My website never stores blog posts locally.\u003C\u002Fp>\n\n\u003Cp>Instead, it fetches them directly from the DEV.to API whenever needed.\u003C\u002Fp>\n\n\u003Cp>This keeps everything synchronized automatically.\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"fetching-articles\" href=\"#fetching-articles\">\n  \u003C\u002Fa>\n  Fetching Articles\n\u003C\u002Fh1>\n\n\u003Cp>DEV.to exposes a public endpoint for fetching a user's published articles.\u003C\u002Fp>\n\n\u003Cp>Example:\u003Cbr>\n\u003C\u002Fp>\n\n\u003Cdiv class=\"highlight js-code-highlight\">\n\u003Cpre class=\"highlight plaintext\">\u003Ccode>GET https:\u002F\u002Fdev.to\u002Fapi\u002Farticles?username=YOUR_USERNAME\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"highlight__panel js-actions-panel\">\n\u003Cdiv class=\"highlight__panel-action js-fullscreen-code-action\">\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\">\u003Ctitle>Enter fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\">\u003Ctitle>Exit fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\n\n\n\u003Cp>In JavaScript:\u003Cbr>\n\u003C\u002Fp>\n\n\u003Cdiv class=\"highlight js-code-highlight\">\n\u003Cpre class=\"highlight javascript\">\u003Ccode>\u003Cspan class=\"kd\">const\u003C\u002Fspan> \u003Cspan class=\"nx\">response\u003C\u002Fspan> \u003Cspan class=\"o\">=\u003C\u002Fspan> \u003Cspan class=\"k\">await\u003C\u002Fspan> \u003Cspan class=\"nf\">fetch\u003C\u002Fspan>\u003Cspan class=\"p\">(\u003C\u002Fspan>\n  \u003Cspan class=\"dl\">\"\u003C\u002Fspan>\u003Cspan class=\"s2\">https:\u002F\u002Fdev.to\u002Fapi\u002Farticles?username=ashraful\u003C\u002Fspan>\u003Cspan class=\"dl\">\"\u003C\u002Fspan>\n\u003Cspan class=\"p\">);\u003C\u002Fspan>\n\n\u003Cspan class=\"kd\">const\u003C\u002Fspan> \u003Cspan class=\"nx\">posts\u003C\u002Fspan> \u003Cspan class=\"o\">=\u003C\u002Fspan> \u003Cspan class=\"k\">await\u003C\u002Fspan> \u003Cspan class=\"nx\">response\u003C\u002Fspan>\u003Cspan class=\"p\">.\u003C\u002Fspan>\u003Cspan class=\"nf\">json\u003C\u002Fspan>\u003Cspan class=\"p\">();\u003C\u002Fspan>\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"highlight__panel js-actions-panel\">\n\u003Cdiv class=\"highlight__panel-action js-fullscreen-code-action\">\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\">\u003Ctitle>Enter fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\">\u003Ctitle>Exit fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\n\n\n\u003Cp>The response includes useful metadata like:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Title\u003C\u002Fli>\n\u003Cli>Description\u003C\u002Fli>\n\u003Cli>Cover image\u003C\u002Fli>\n\u003Cli>Published date\u003C\u002Fli>\n\u003Cli>Tags\u003C\u002Fli>\n\u003Cli>Reading time\u003C\u002Fli>\n\u003Cli>Slug\u003C\u002Fli>\n\u003Cli>URL\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>No authentication is required for public articles. :contentReference[oaicite:2]{index=2}\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"loading-a-single-blog-post\" href=\"#loading-a-single-blog-post\">\n  \u003C\u002Fa>\n  Loading a Single Blog Post\n\u003C\u002Fh1>\n\n\u003Cp>Listing articles is only half the job.\u003C\u002Fp>\n\n\u003Cp>When a visitor clicks on an article, the website fetches its full content.\u003C\u002Fp>\n\n\u003Cp>The API endpoint looks like this:\u003Cbr>\n\u003C\u002Fp>\n\n\u003Cdiv class=\"highlight js-code-highlight\">\n\u003Cpre class=\"highlight plaintext\">\u003Ccode>GET https:\u002F\u002Fdev.to\u002Fapi\u002Farticles\u002F{username}\u002F{slug}\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"highlight__panel js-actions-panel\">\n\u003Cdiv class=\"highlight__panel-action js-fullscreen-code-action\">\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\">\u003Ctitle>Enter fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\">\u003Ctitle>Exit fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\n\n\n\u003Cp>Example:\u003Cbr>\n\u003C\u002Fp>\n\n\u003Cdiv class=\"highlight js-code-highlight\">\n\u003Cpre class=\"highlight plaintext\">\u003Ccode>GET https:\u002F\u002Fdev.to\u002Fapi\u002Farticles\u002Fashraful\u002Fmy-awesome-post\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"highlight__panel js-actions-panel\">\n\u003Cdiv class=\"highlight__panel-action js-fullscreen-code-action\">\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\">\u003Ctitle>Enter fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\">\u003Ctitle>Exit fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\n\n\n\u003Cp>The response contains:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Markdown\u003C\u002Fli>\n\u003Cli>Rendered HTML\u003C\u002Fli>\n\u003Cli>Cover image\u003C\u002Fli>\n\u003Cli>Metadata\u003C\u002Fli>\n\u003Cli>Reactions\u003C\u002Fli>\n\u003Cli>Comments count\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>The most important field for me is:\u003Cbr>\n\u003C\u002Fp>\n\n\u003Cdiv class=\"highlight js-code-highlight\">\n\u003Cpre class=\"highlight json\">\u003Ccode>\u003Cspan class=\"p\">{\u003C\u002Fspan>\u003Cspan class=\"w\">\n  \u003C\u002Fspan>\u003Cspan class=\"nl\">\"body_markdown\"\u003C\u002Fspan>\u003Cspan class=\"p\">:\u003C\u002Fspan>\u003Cspan class=\"w\"> \u003C\u002Fspan>\u003Cspan class=\"s2\">\"# My Blog Post...\"\u003C\u002Fspan>\u003Cspan class=\"w\">\n\u003C\u002Fspan>\u003Cspan class=\"p\">}\u003C\u002Fspan>\u003Cspan class=\"w\">\n\u003C\u002Fspan>\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"highlight__panel js-actions-panel\">\n\u003Cdiv class=\"highlight__panel-action js-fullscreen-code-action\">\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\">\u003Ctitle>Enter fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\">\u003Ctitle>Exit fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\n\n\n\u003Cp>That's exactly what I render on my website. :contentReference[oaicite:3]{index=3}\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"rendering-markdown\" href=\"#rendering-markdown\">\n  \u003C\u002Fa>\n  Rendering Markdown\n\u003C\u002Fh1>\n\n\u003Cp>Once I receive the Markdown, I render it like any normal Markdown document.\u003C\u002Fp>\n\n\u003Cp>This gives me complete control over:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Typography\u003C\u002Fli>\n\u003Cli>Code highlighting\u003C\u002Fli>\n\u003Cli>Tables\u003C\u002Fli>\n\u003Cli>Images\u003C\u002Fli>\n\u003Cli>Custom components\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Because the original content is still Markdown, I don't lose any formatting.\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"my-publishing-workflow\" href=\"#my-publishing-workflow\">\n  \u003C\u002Fa>\n  My Publishing Workflow\n\u003C\u002Fh1>\n\n\u003Cp>Publishing a new article has become incredibly simple.\u003Cbr>\n\u003C\u002Fp>\n\n\u003Cdiv class=\"highlight js-code-highlight\">\n\u003Cpre class=\"highlight plaintext\">\u003Ccode>Write Article\n      │\n      ▼\nPublish to DEV.to\n      │\n      ▼\nDone ✅\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"highlight__panel js-actions-panel\">\n\u003Cdiv class=\"highlight__panel-action js-fullscreen-code-action\">\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\">\u003Ctitle>Enter fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\">\u003Ctitle>Exit fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\n\n\n\u003Cp>That's it.\u003C\u002Fp>\n\n\u003Cp>There's no second publishing step.\u003C\u002Fp>\n\n\u003Cp>The website automatically displays the new article because it always reads from the API.\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"benefits-of-this-approach\" href=\"#benefits-of-this-approach\">\n  \u003C\u002Fa>\n  Benefits of This Approach\n\u003C\u002Fh1>\n\n\u003Ch2>\n  \u003Ca name=\"single-source-of-truth\" href=\"#single-source-of-truth\">\n  \u003C\u002Fa>\n  Single Source of Truth\n\u003C\u002Fh2>\n\n\u003Cp>There's only one copy of every article.\u003C\u002Fp>\n\n\u003Cp>I never have to wonder:\u003C\u002Fp>\n\n\u003Cblockquote>\n\u003Cp>\"Which version is the latest?\"\u003C\u002Fp>\n\u003C\u002Fblockquote>\n\n\u003Cp>DEV.to is always the source.\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch2>\n  \u003Ca name=\"no-duplicate-work\" href=\"#no-duplicate-work\">\n  \u003C\u002Fa>\n  No Duplicate Work\n\u003C\u002Fh2>\n\n\u003Cp>Before:\u003Cbr>\n\u003C\u002Fp>\n\n\u003Cdiv class=\"highlight js-code-highlight\">\n\u003Cpre class=\"highlight plaintext\">\u003Ccode>Publish to DEV.to\n\n↓\n\nCopy Markdown\n\n↓\n\nPaste into Website\n\n↓\n\nPublish Again\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"highlight__panel js-actions-panel\">\n\u003Cdiv class=\"highlight__panel-action js-fullscreen-code-action\">\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\">\u003Ctitle>Enter fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\">\u003Ctitle>Exit fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\n\n\n\u003Cp>Now:\u003Cbr>\n\u003C\u002Fp>\n\n\u003Cdiv class=\"highlight js-code-highlight\">\n\u003Cpre class=\"highlight plaintext\">\u003Ccode>Publish to DEV.to\n\n↓\n\nFinished\n\u003C\u002Fcode>\u003C\u002Fpre>\n\u003Cdiv class=\"highlight__panel js-actions-panel\">\n\u003Cdiv class=\"highlight__panel-action js-fullscreen-code-action\">\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-on\">\u003Ctitle>Enter fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M16 3h6v6h-2V5h-4V3zM2 3h6v2H4v4H2V3zm18 16v-4h2v6h-6v-2h4zM4 19h4v2H2v-6h2v4z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n    \u003Csvg xmlns=\"http:\u002F\u002Fwww.w3.org\u002F2000\u002Fsvg\" width=\"20px\" height=\"20px\" viewbox=\"0 0 24 24\" class=\"highlight-action crayons-icon highlight-action--fullscreen-off\">\u003Ctitle>Exit fullscreen mode\u003C\u002Ftitle>\n    \u003Cpath d=\"M18 7h4v2h-6V3h2v4zM8 9H2V7h4V3h2v6zm10 8v4h-2v-6h6v2h-4zM8 15v6H6v-4H2v-2h6z\">\u003C\u002Fpath>\n\u003C\u002Fsvg>\n\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\u003C\u002Fdiv>\n\n\n\n\u003Cp>One click instead of many.\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch2>\n  \u003Ca name=\"better-seo\" href=\"#better-seo\">\n  \u003C\u002Fa>\n  Better SEO\n\u003C\u002Fh2>\n\n\u003Cp>One concern when publishing content on multiple websites is duplicate content.\u003C\u002Fp>\n\n\u003Cp>The good news is that DEV.to supports \u003Cstrong>canonical URLs\u003C\u002Fstrong>, 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}\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch2>\n  \u003Ca name=\"custom-design\" href=\"#custom-design\">\n  \u003C\u002Fa>\n  Custom Design\n\u003C\u002Fh2>\n\n\u003Cp>Although the content comes from DEV.to, my website has its own:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Layout\u003C\u002Fli>\n\u003Cli>Branding\u003C\u002Fli>\n\u003Cli>Navigation\u003C\u002Fli>\n\u003Cli>Theme\u003C\u002Fli>\n\u003Cli>Search\u003C\u002Fli>\n\u003Cli>Reading experience\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Visitors get a consistent experience while I continue using DEV.to as the backend.\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"performance-considerations\" href=\"#performance-considerations\">\n  \u003C\u002Fa>\n  Performance Considerations\n\u003C\u002Fh1>\n\n\u003Cp>Calling an external API on every request isn't always ideal.\u003C\u002Fp>\n\n\u003Cp>To improve performance, you can:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Cache API responses.\u003C\u002Fli>\n\u003Cli>Use Incremental Static Regeneration (ISR).\u003C\u002Fli>\n\u003Cli>Pre-render popular articles.\u003C\u002Fli>\n\u003Cli>Refresh the cache periodically.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>This reduces API requests while keeping content up to date.\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"error-handling\" href=\"#error-handling\">\n  \u003C\u002Fa>\n  Error Handling\n\u003C\u002Fh1>\n\n\u003Cp>Whenever you depend on an external API, you should plan for failures.\u003C\u002Fp>\n\n\u003Cp>For example:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>API downtime\u003C\u002Fli>\n\u003Cli>Rate limits\u003C\u002Fli>\n\u003Cli>Network issues\u003C\u002Fli>\n\u003Cli>Invalid responses\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>A simple fallback page or cached copy can greatly improve the user experience.\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"why-i-like-this-setup\" href=\"#why-i-like-this-setup\">\n  \u003C\u002Fa>\n  Why I Like This Setup\n\u003C\u002Fh1>\n\n\u003Cp>This approach gives me the best of both worlds.\u003C\u002Fp>\n\n\u003Cp>I get:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>The reach of DEV.to.\u003C\u002Fli>\n\u003Cli>A fully customized personal website.\u003C\u002Fli>\n\u003Cli>No CMS maintenance.\u003C\u002Fli>\n\u003Cli>No duplicate content management.\u003C\u002Fli>\n\u003Cli>One publishing workflow.\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>Most importantly, I spend my time writing instead of maintaining content in multiple places.\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"could-you-do-the-same\" href=\"#could-you-do-the-same\">\n  \u003C\u002Fa>\n  Could You Do the Same?\n\u003C\u002Fh1>\n\n\u003Cp>Absolutely.\u003C\u002Fp>\n\n\u003Cp>If you already publish on DEV.to, you can build your own blog in just a few hours using its public API.\u003C\u002Fp>\n\n\u003Cp>Whether you're using:\u003C\u002Fp>\n\n\u003Cul>\n\u003Cli>Next.js\u003C\u002Fli>\n\u003Cli>React\u003C\u002Fli>\n\u003Cli>Vue\u003C\u002Fli>\n\u003Cli>Nuxt\u003C\u002Fli>\n\u003Cli>Svelte\u003C\u002Fli>\n\u003Cli>Astro\u003C\u002Fli>\n\u003C\u002Ful>\n\n\u003Cp>the process is almost identical:\u003C\u002Fp>\n\n\u003Col>\n\u003Cli>Fetch articles.\u003C\u002Fli>\n\u003Cli>Display the list.\u003C\u002Fli>\n\u003Cli>Fetch a single article by slug.\u003C\u002Fli>\n\u003Cli>Render the Markdown.\u003C\u002Fli>\n\u003Cli>Style it however you like.\u003C\u002Fli>\n\u003C\u002Fol>\n\n\u003Cp>The API is simple, well documented, and perfect for personal portfolio websites. :contentReference[oaicite:5]{index=5}\u003C\u002Fp>\n\n\n\u003Chr>\n\n\u003Ch1>\n  \u003Ca name=\"final-thoughts\" href=\"#final-thoughts\">\n  \u003C\u002Fa>\n  Final Thoughts\n\u003C\u002Fh1>\n\n\u003Cp>Building my blog around the DEV.to API has been one of the simplest yet most rewarding improvements to my personal website.\u003C\u002Fp>\n\n\u003Cp>Instead of managing two separate publishing platforms, I now have a single workflow: write once, publish once, and let the API do the rest.\u003C\u002Fp>\n\n\u003Cp>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.\u003C\u002Fp>\n\n","> **Write once, publish everywhere.** That was the goal when I built my personal blog.\n\nFor 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.\n\nInstead 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.\n\nThe result is my personal blog:\n\n👉 **https:\u002F\u002Fblog.ashraful.dev\u002F**\n\nEvery 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}\n\n---\n\n# The Problem\n\nInitially, my workflow looked like this:\n\n1. Write the article.\n2. Publish it on DEV.to.\n3. Copy the Markdown.\n4. Paste it into my website.\n5. Fix formatting.\n6. Publish again.\n\nThis wasn't difficult, but it was repetitive.\n\nEvery blog post required maintaining two separate copies of the same content.\n\nEventually, I asked myself:\n\n> Why am I manually copying content when DEV.to already provides an API?\n\nThat simple question completely changed my blogging workflow.\n\n---\n\n# Why I Chose DEV.to\n\nThere are many blogging platforms available:\n\n- Medium\n- Hashnode\n- Ghost\n- WordPress\n- Notion\n\nI chose DEV.to because:\n\n- It has a large developer community.\n- Articles are easily discoverable.\n- Markdown support is excellent.\n- It provides a free public API.\n- I don't need to manage another CMS. :contentReference[oaicite:1]{index=1}\n\nInstead of building an admin panel for my blog, I simply use DEV.to as the content management system.\n\n---\n\n# The Architecture\n\nMy setup is surprisingly simple.\n\n```text\n            Write Article\n                  │\n                  ▼\n              DEV.to\n                  │\n            DEV.to API\n                  │\n                  ▼\n          Personal Website\n      (blog.ashraful.dev)\n```\n\nMy website never stores blog posts locally.\n\nInstead, it fetches them directly from the DEV.to API whenever needed.\n\nThis keeps everything synchronized automatically.\n\n---\n\n# Fetching Articles\n\nDEV.to exposes a public endpoint for fetching a user's published articles.\n\nExample:\n\n```text\nGET https:\u002F\u002Fdev.to\u002Fapi\u002Farticles?username=YOUR_USERNAME\n```\n\nIn JavaScript:\n\n```javascript\nconst response = await fetch(\n  \"https:\u002F\u002Fdev.to\u002Fapi\u002Farticles?username=ashraful\"\n);\n\nconst posts = await response.json();\n```\n\nThe response includes useful metadata like:\n\n- Title\n- Description\n- Cover image\n- Published date\n- Tags\n- Reading time\n- Slug\n- URL\n\nNo authentication is required for public articles. :contentReference[oaicite:2]{index=2}\n\n---\n\n# Loading a Single Blog Post\n\nListing articles is only half the job.\n\nWhen a visitor clicks on an article, the website fetches its full content.\n\nThe API endpoint looks like this:\n\n```text\nGET https:\u002F\u002Fdev.to\u002Fapi\u002Farticles\u002F{username}\u002F{slug}\n```\n\nExample:\n\n```text\nGET https:\u002F\u002Fdev.to\u002Fapi\u002Farticles\u002Fashraful\u002Fmy-awesome-post\n```\n\nThe response contains:\n\n- Markdown\n- Rendered HTML\n- Cover image\n- Metadata\n- Reactions\n- Comments count\n\nThe most important field for me is:\n\n```json\n{\n  \"body_markdown\": \"# My Blog Post...\"\n}\n```\n\nThat's exactly what I render on my website. :contentReference[oaicite:3]{index=3}\n\n---\n\n# Rendering Markdown\n\nOnce I receive the Markdown, I render it like any normal Markdown document.\n\nThis gives me complete control over:\n\n- Typography\n- Code highlighting\n- Tables\n- Images\n- Custom components\n\nBecause the original content is still Markdown, I don't lose any formatting.\n\n---\n\n# My Publishing Workflow\n\nPublishing a new article has become incredibly simple.\n\n```text\nWrite Article\n      │\n      ▼\nPublish to DEV.to\n      │\n      ▼\nDone ✅\n```\n\nThat's it.\n\nThere's no second publishing step.\n\nThe website automatically displays the new article because it always reads from the API.\n\n---\n\n# Benefits of This Approach\n\n## Single Source of Truth\n\nThere's only one copy of every article.\n\nI never have to wonder:\n\n> \"Which version is the latest?\"\n\nDEV.to is always the source.\n\n---\n\n## No Duplicate Work\n\nBefore:\n\n```plaintext\nPublish to DEV.to\n\n↓\n\nCopy Markdown\n\n↓\n\nPaste into Website\n\n↓\n\nPublish Again\n```\n\nNow:\n\n```plaintext\nPublish to DEV.to\n\n↓\n\nFinished\n```\n\nOne click instead of many.\n\n---\n\n## Better SEO\n\nOne concern when publishing content on multiple websites is duplicate content.\n\nThe 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}\n\n---\n\n## Custom Design\n\nAlthough the content comes from DEV.to, my website has its own:\n\n- Layout\n- Branding\n- Navigation\n- Theme\n- Search\n- Reading experience\n\nVisitors get a consistent experience while I continue using DEV.to as the backend.\n\n---\n\n# Performance Considerations\n\nCalling an external API on every request isn't always ideal.\n\nTo improve performance, you can:\n\n- Cache API responses.\n- Use Incremental Static Regeneration (ISR).\n- Pre-render popular articles.\n- Refresh the cache periodically.\n\nThis reduces API requests while keeping content up to date.\n\n---\n\n# Error Handling\n\nWhenever you depend on an external API, you should plan for failures.\n\nFor example:\n\n- API downtime\n- Rate limits\n- Network issues\n- Invalid responses\n\nA simple fallback page or cached copy can greatly improve the user experience.\n\n---\n\n# Why I Like This Setup\n\nThis approach gives me the best of both worlds.\n\nI get:\n\n- The reach of DEV.to.\n- A fully customized personal website.\n- No CMS maintenance.\n- No duplicate content management.\n- One publishing workflow.\n\nMost importantly, I spend my time writing instead of maintaining content in multiple places.\n\n---\n\n# Could You Do the Same?\n\nAbsolutely.\n\nIf you already publish on DEV.to, you can build your own blog in just a few hours using its public API.\n\nWhether you're using:\n\n- Next.js\n- React\n- Vue\n- Nuxt\n- Svelte\n- Astro\n\nthe process is almost identical:\n\n1. Fetch articles.\n2. Display the list.\n3. Fetch a single article by slug.\n4. Render the Markdown.\n5. Style it however you like.\n\nThe API is simple, well documented, and perfect for personal portfolio websites. :contentReference[oaicite:5]{index=5}\n\n---\n\n# Final Thoughts\n\nBuilding my blog around the DEV.to API has been one of the simplest yet most rewarding improvements to my personal website.\n\nInstead of managing two separate publishing platforms, I now have a single workflow: write once, publish once, and let the API do the rest.\n\nIf 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.",{"name":30,"username":31,"twitter_username":32,"github_username":33,"user_id":34,"website_url":35,"profile_image":36,"profile_image_90":37},"Mohamad Ashraful Islam","ashraful","_ashraful","iashraful",30490,"https:\u002F\u002Fashraful.dev","https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=640,height=640,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F30490%2F9dc1ef64-0233-43b5-9127-79affd83cc43.jpg","https:\u002F\u002Fmedia2.dev.to\u002Fdynamic\u002Fimage\u002Fwidth=90,height=90,fit=cover,gravity=auto,format=auto\u002Fhttps%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F30490%2F9dc1ef64-0233-43b5-9127-79affd83cc43.jpg",1784633123716]