<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Coder Legion - Recent posts tagged blog</title>
<link>https://coderlegion.com/tag/blog</link>
<description>Powered by Question2Answer</description>
<item>
<title>Top Ahrefs &amp; Semrush Alternatives for Small Bloggers on a Budget</title>
<link>https://coderlegion.com/31300/top-ahrefs-semrush-alternatives-for-small-bloggers-on-a-budget</link>
<description>&lt;p&gt;Ahrefs and Semrush are popular SEO platforms, but their subscription costs can be difficult for small bloggers to justify, particularly when a website is still building its audience. Paying for advanced keyword research, competitor analysis, backlink reports, and rank tracking may not make financial sense when a blog publishes only a few articles each month.&lt;/p&gt;
&lt;p&gt;Fortunately, bloggers have other options. Some tools provide free website performance reports and technical SEO checks, while others offer keyword suggestions, backlink analysis, competitor research, and rank tracking through affordable subscriptions.&lt;/p&gt;
&lt;p&gt;The best alternative depends on what a blogger needs to accomplish. Someone who wants to discover search queries that already bring visitors to a website has different requirements from someone researching competitors or planning a link-building campaign.&lt;/p&gt;
&lt;p&gt;This guide examines six alternatives to Ahrefs and Semrush, covering their main uses, limitations, and suitability for small publishing businesses. The selection prioritizes practical SEO capabilities, free access where available, and subscription options that independent bloggers can evaluate before committing to a recurring expense.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Google Search Console: Best Free Alternative for Measuring Search Performance&lt;br&gt;
Google Search Console is one of the first tools a blogger should use before paying for an SEO subscription. It provides information about how a website performs in Google Search, including impressions, clicks, click-through rates, and average search positions.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Unlike commercial SEO platforms, Search Console reports data about the website owner's own property rather than providing a complete commercial research database for analyzing competitors.&lt;/p&gt;
&lt;p&gt;Key features include:&lt;/p&gt;
&lt;p&gt;Search performance reports showing clicks, impressions, click-through rates, and average positions.&lt;/p&gt;
&lt;p&gt;Queries and pages reports that help identify which content receives visibility in Google Search.&lt;/p&gt;
&lt;p&gt;Indexing reports for investigating pages that Google has discovered or processed.&lt;/p&gt;
&lt;p&gt;Tools for inspecting individual URLs and checking indexing information.&lt;/p&gt;
&lt;p&gt;Sitemaps and other features that help website owners communicate with Google about their content.&lt;/p&gt;
&lt;p&gt;Google provides Search Console without a subscription fee. Its official documentation and access point are available through Google Search Console.&lt;/p&gt;
&lt;p&gt;Why small bloggers should consider it&lt;/p&gt;
&lt;p&gt;Suppose a blogger publishes articles about personal finance, technology, or travel. Search Console can reveal queries that generate impressions even when those queries produce relatively few clicks. The blogger can investigate whether the relevant article adequately answers the searcher's question, whether its title accurately describes its content, and whether its introduction addresses the topic directly.&lt;/p&gt;
&lt;p&gt;The same data can help identify older articles that deserve updating. A post that continues to appear in search results may offer an opportunity to improve its usefulness and presentation.&lt;/p&gt;
&lt;p&gt;Limitations&lt;/p&gt;
&lt;p&gt;Search Console does not replace a commercial keyword research platform. It is not designed to provide a comprehensive database of competitors' backlinks, estimated traffic, or keyword rankings across the entire market. Its search performance reports also concern Google Search, not every search engine.&lt;/p&gt;
&lt;p&gt;Verdict: Start here if your priority is understanding your website's actual performance in Google Search without adding another monthly subscription.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Bing Webmaster Tools: Best Free Option for Additional SEO Research&lt;br&gt;
Bing Webmaster Tools offers another free resource for bloggers who want to monitor website performance and investigate technical SEO issues.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Its official platform includes search performance information, backlink analysis, keyword research, site scanning, and diagnostic reports. These capabilities make it useful for bloggers who want more than a basic analytics dashboard.&lt;/p&gt;
&lt;p&gt;The platform is available through Bing Webmaster Tools.&lt;/p&gt;
&lt;p&gt;Key features include:&lt;/p&gt;
&lt;p&gt;Keyword research: Explore search phrases and available search-volume information.&lt;/p&gt;
&lt;p&gt;Backlink analysis: Examine referring pages, domains, and anchor text associated with your website.&lt;/p&gt;
&lt;p&gt;Site Scan: Identify common technical issues through website crawling.&lt;/p&gt;
&lt;p&gt;SEO reports: Review findings related to website health and potential optimization problems.&lt;/p&gt;
&lt;p&gt;Search performance reports: Investigate how your website performs in Bing search results.&lt;/p&gt;
&lt;p&gt;Why small bloggers should consider it&lt;/p&gt;
&lt;p&gt;A blogger can use Bing Webmaster Tools to discover keyword ideas, examine links pointing to a website, and identify technical problems without immediately paying for a large SEO suite.&lt;/p&gt;
&lt;p&gt;It is particularly useful alongside Google Search Console. Each platform provides information associated with its own search ecosystem, allowing publishers to monitor more than one search engine.&lt;/p&gt;
&lt;p&gt;For example, a blogger could use Google's reports to investigate pages receiving impressions and Bing's keyword research features to explore additional search phrases. The resulting research can inform future articles and updates to existing content.&lt;/p&gt;
&lt;p&gt;Limitations&lt;/p&gt;
&lt;p&gt;Bing Webmaster Tools is not a complete substitute for Ahrefs or Semrush when conducting extensive competitor research. Its reports focus on the website and search ecosystem covered by the platform. Backlink and keyword information should not be assumed to match the coverage of a commercial SEO database.&lt;/p&gt;
&lt;p&gt;Verdict: A strong free addition for bloggers who want keyword research, backlink information, and technical diagnostics without purchasing another subscription.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ubersuggest: Best for Bloggers Seeking an Affordable All-in-One Tool&lt;br&gt;
Ubersuggest is a commercial SEO platform that offers keyword research, competitor analysis, backlink information, rank tracking, and website auditing. It is worth considering for bloggers who prefer to manage several SEO tasks within one interface rather than rely entirely on separate free tools.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The platform also provides limited free access to keyword research features. Its available subscription plans and usage allowances can be reviewed on the official Ubersuggest pricing page.&lt;/p&gt;
&lt;p&gt;Key features include:&lt;/p&gt;
&lt;p&gt;Keyword suggestions for researching potential article topics.&lt;/p&gt;
&lt;p&gt;Keyword metrics and search-volume estimates.&lt;/p&gt;
&lt;p&gt;Competitor research for exploring websites and their organic search visibility.&lt;/p&gt;
&lt;p&gt;Backlink reports for examining links and referring domains.&lt;/p&gt;
&lt;p&gt;Rank tracking for monitoring selected keywords.&lt;/p&gt;
&lt;p&gt;Site audits for identifying technical and on-page SEO problems.&lt;/p&gt;
&lt;p&gt;Why small bloggers should consider it&lt;/p&gt;
&lt;p&gt;Ubersuggest can help consolidate several routine publishing tasks. Instead of researching topics in one tool, checking backlinks in another, and monitoring rankings elsewhere, a blogger can use its available features for a broader view of SEO performance.&lt;/p&gt;
&lt;p&gt;Consider a website that publishes tutorials about WordPress, website hosting, and digital marketing. Before writing an article, its owner can research related keywords, examine competing pages, and identify potential opportunities for a more useful article. After publication, rank tracking and site audits can help monitor the website's progress.&lt;/p&gt;
&lt;p&gt;Ubersuggest offers paid options intended for different levels of website ownership and usage. Its pricing page lists an Individual plan at $29 per month and a Business plan at $49 per month under its monthly billing options. Prices and plan features can change, so check the current terms before subscribing.&lt;/p&gt;
&lt;p&gt;Limitations&lt;/p&gt;
&lt;p&gt;Ubersuggest is not a complete replacement for every capability available in Ahrefs or Semrush. Database coverage, reporting limits, tracked keyword allowances, and backlink information may differ. The right comparison should focus on the specific reports a blogger needs rather than the total number of features advertised.&lt;/p&gt;
&lt;p&gt;Its estimates should also be treated as research indicators, not as guaranteed measurements of future traffic.&lt;/p&gt;
&lt;p&gt;Verdict: A practical option for independent bloggers who want keyword research, competitor analysis, rank tracking, and site auditing in one paid platform without immediately committing to a higher-priced enterprise-oriented subscription.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Mangools: Best for Keyword Research and Search Result Analysis&lt;br&gt;
Mangools is a collection of SEO tools designed to help users research keywords, inspect search engine results pages, monitor rankings, and examine backlink profiles. Its products include KWFinder, SERPChecker, SERPWatcher, LinkMiner, and SiteProfiler.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;For small bloggers, Mangools is worth considering when keyword selection and search result analysis are more important than having every advanced SEO function in a single platform.&lt;/p&gt;
&lt;p&gt;Its current products and subscription options are listed on the official Mangools website.&lt;/p&gt;
&lt;p&gt;Key features include:&lt;/p&gt;
&lt;p&gt;KWFinder: Research keywords and discover related search terms.&lt;/p&gt;
&lt;p&gt;SERPChecker: Examine search results for a target keyword.&lt;/p&gt;
&lt;p&gt;SERPWatcher: Monitor keyword rankings.&lt;/p&gt;
&lt;p&gt;LinkMiner: Investigate backlinks.&lt;/p&gt;
&lt;p&gt;SiteProfiler: Review website-level SEO information.&lt;/p&gt;
&lt;p&gt;Why small bloggers should consider it&lt;/p&gt;
&lt;p&gt;Keyword research can help a blogger decide which articles deserve attention before investing hours in writing. Mangools provides a collection of tools for examining keyword opportunities and the pages competing for search visibility.&lt;/p&gt;
&lt;p&gt;For example, a blogger covering budget laptops could research a specific product category, examine the search results, and compare competing pages before deciding whether to publish a buying guide, comparison article, or troubleshooting tutorial.&lt;/p&gt;
&lt;p&gt;The SERP analysis tools can also help publishers investigate the types of pages appearing for a query. This is useful when deciding whether an article should answer a question directly, compare products, or provide a detailed tutorial.&lt;/p&gt;
&lt;p&gt;Mangools offers multiple subscription tiers with different usage limits. Its current pricing page lists a Basic plan, with keyword research, rank tracking, backlink analysis, and site analysis allowances varying by plan. Review the current billing terms and limits before purchasing.&lt;/p&gt;
&lt;p&gt;Limitations&lt;/p&gt;
&lt;p&gt;Mangools is a collection of specialized SEO tools, not a complete replacement for every feature in Ahrefs or Semrush. The number of searches, keyword suggestions, tracked rankings, and backlink records available depends on the subscription.&lt;/p&gt;
&lt;p&gt;Verdict: Consider Mangools if you want dedicated keyword research and search result analysis tools without needing a large marketing platform.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Google Keyword Planner: Best for Generating Keyword Ideas&lt;br&gt;
Google Keyword Planner is a keyword research tool available through Google Ads. Although its primary purpose is planning advertising campaigns, bloggers can also use it to discover search terms and investigate keyword demand.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Access is available through Google Ads Keyword Planner.&lt;/p&gt;
&lt;p&gt;Key features include:&lt;/p&gt;
&lt;p&gt;Discovering keyword ideas related to a product, service, topic, or website.&lt;/p&gt;
&lt;p&gt;Reviewing estimated search volumes and trends.&lt;/p&gt;
&lt;p&gt;Examining suggested keywords for a particular market.&lt;/p&gt;
&lt;p&gt;Refining research using available geographic and language settings.&lt;/p&gt;
&lt;p&gt;Organizing keyword ideas for further research.&lt;/p&gt;
&lt;p&gt;Why small bloggers should consider it&lt;/p&gt;
&lt;p&gt;A blogger does not necessarily need an expensive SEO platform to develop a list of relevant article topics. Keyword Planner can help generate ideas and investigate the language people use when searching for information.&lt;/p&gt;
&lt;p&gt;Suppose you run a website about email marketing. You could begin with a broad topic such as email automation and examine related phrases covering tutorials, software comparisons, and common problems. Those ideas can become candidates for future articles.&lt;/p&gt;
&lt;p&gt;Keyword Planner can also be useful for identifying related topics that a website has not covered yet. A blogger can combine these suggestions with existing website performance data from Google Search Console to decide which subjects deserve further investigation.&lt;/p&gt;
&lt;p&gt;Limitations&lt;/p&gt;
&lt;p&gt;Keyword Planner is designed for advertising research rather than comprehensive organic SEO analysis. It does not provide the same combination of competitor backlink intelligence, organic traffic estimates, and technical auditing offered by all-in-one SEO platforms.&lt;/p&gt;
&lt;p&gt;Its search-volume figures should also be interpreted according to the information and ranges available in the account. Advertising estimates are not guarantees of organic traffic.&lt;/p&gt;
&lt;p&gt;Verdict: A useful option for bloggers who primarily need keyword ideas and demand estimates, particularly when combined with free website performance data.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ahrefs Free Tools: Best for Basic Website SEO Checks&lt;br&gt;
Although this article focuses on alternatives to Ahrefs and Semrush, Ahrefs itself provides a free account with limited access to selected tools. That option deserves consideration because some bloggers may not need a complete replacement for the paid platform.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;According to Ahrefs' official documentation, its free account includes access to Site Explorer and Site Audit for verified websites, along with other tools such as Web Analytics and its SEO Toolbar. Usage limits apply.&lt;/p&gt;
&lt;p&gt;Details are available on the official Ahrefs pricing page.&lt;/p&gt;
&lt;p&gt;Key features include:&lt;/p&gt;
&lt;p&gt;Backlink and keyword information for websites you own and verify.&lt;/p&gt;
&lt;p&gt;Site audits that identify technical and on-page SEO issues.&lt;/p&gt;
&lt;p&gt;Website analytics with specified usage limits.&lt;/p&gt;
&lt;p&gt;Selected SEO Toolbar metrics and on-page information.&lt;/p&gt;
&lt;p&gt;Limited access to other Ahrefs features.&lt;/p&gt;
&lt;p&gt;Why small bloggers should consider it&lt;/p&gt;
&lt;p&gt;A blogger who already has access to free tools from Google and Bing may only need occasional backlink checks and technical audits. Ahrefs Free can help cover some of those requirements without immediately requiring a paid subscription.&lt;/p&gt;
&lt;p&gt;For example, a publisher can use Site Audit to investigate technical issues on a verified website, then use Search Console to monitor search performance. This combination provides useful information without requiring the blogger to pay for every available SEO feature.&lt;/p&gt;
&lt;p&gt;Limitations&lt;/p&gt;
&lt;p&gt;The free account has significant restrictions. Ahrefs' documentation identifies limitations on report access, crawl credits, and available data. Its free account does not provide unrestricted access to the commercial keyword research and competitor analysis functions available through paid plans.&lt;/p&gt;
&lt;p&gt;It is therefore better understood as a supplementary resource than as a complete substitute for Ahrefs' paid platform.&lt;/p&gt;
&lt;p&gt;Verdict: Worth trying if you want selected Ahrefs capabilities while keeping your SEO expenses low.&lt;/p&gt;
&lt;p&gt;How to Choose the Right Ahrefs or Semrush Alternative&lt;br&gt;
The right choice depends on your website's stage of development, your publishing schedule, and the SEO tasks you perform most often.&lt;/p&gt;
&lt;p&gt;Main Requirement&lt;/p&gt;
&lt;p&gt;Recommended Tool&lt;/p&gt;
&lt;p&gt;Monitor actual Google Search performance&lt;/p&gt;
&lt;p&gt;Google Search Console&lt;/p&gt;
&lt;p&gt;Access free keyword research and backlink information&lt;/p&gt;
&lt;p&gt;Bing Webmaster Tools&lt;/p&gt;
&lt;p&gt;Combine keyword research, rank tracking, and site audits&lt;/p&gt;
&lt;p&gt;Ubersuggest&lt;/p&gt;
&lt;p&gt;Research keywords and examine search results&lt;/p&gt;
&lt;p&gt;Mangools&lt;/p&gt;
&lt;p&gt;Generate keyword ideas and examine search demand&lt;/p&gt;
&lt;p&gt;Google Keyword Planner&lt;/p&gt;
&lt;p&gt;Run basic audits and inspect selected backlink data&lt;/p&gt;
&lt;p&gt;Ahrefs Free&lt;/p&gt;
&lt;p&gt;These tools are not identical. Their databases, reporting methods, search coverage, and usage limits differ. Compare the specific functions you need rather than assuming that a lower-priced subscription provides the same data as Ahrefs or Semrush.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Start with free tools&lt;br&gt;
Before purchasing an SEO subscription, set up Google Search Console and Bing Webmaster Tools. Both provide useful information without a paid SEO subscription.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Use them to identify existing search queries, monitor website performance, and investigate technical issues. These initial steps can help establish which additional capabilities your website actually needs.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Identify the features you use regularly&lt;br&gt;
Write down the tasks you perform each week. These might include researching keywords, checking competitors, tracking rankings, investigating backlinks, and auditing your website.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you primarily research article topics, a keyword research tool may be sufficient. If you regularly analyze competitor link profiles, you will need a tool with suitable backlink reporting.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Compare total costs and usage limits&lt;br&gt;
Do not compare subscriptions on price alone. Check how many websites you can manage, how many keywords you can track, whether backlink reports are included, and how frequently ranking data updates.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Review monthly and annual billing separately. Annual subscriptions may have lower effective monthly costs but require a larger upfront payment. Confirm the current price, renewal terms, cancellation policy, and any applicable taxes before subscribing.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Test tools against real publishing tasks&lt;br&gt;
Use a tool to research a topic you genuinely intend to cover. Check whether it provides enough keyword ideas, useful search result information, and actionable data for your website.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Repeat the test with another tool before deciding. This approach is more useful than selecting software based on feature counts or promotional claims.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Remember that SEO tools do not guarantee rankings&lt;br&gt;
SEO software provides research data and diagnostic information. It cannot guarantee that a page will rank highly or attract a particular number of visitors.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Google's official SEO Starter Guide emphasizes creating useful, reliable, people-first content and making websites easier for search engines to crawl and understand.&lt;/p&gt;
&lt;p&gt;Use SEO tools to inform editorial decisions, not as a substitute for original research, accurate information, useful writing, and a technically accessible website.&lt;/p&gt;
&lt;p&gt;Final Verdict&lt;br&gt;
Small bloggers do not need to purchase the most expensive SEO platform simply because established publishers use it.&lt;/p&gt;
&lt;p&gt;Google Search Console and Bing Webmaster Tools are the best starting points for bloggers who need to control costs. They provide useful website performance, keyword research, backlink, and diagnostic capabilities without requiring a paid SEO subscription.&lt;/p&gt;
&lt;p&gt;Ubersuggest is worth evaluating when you want a broader collection of SEO functions in one paid tool. Mangools is another option for keyword research, search result analysis, and rank tracking. Google Keyword Planner is useful for generating keyword ideas, while Ahrefs Free can cover selected auditing and backlink research tasks.&lt;/p&gt;
&lt;p&gt;The most sensible approach is to start with free tools, identify the limitations that interfere with your publishing workflow, and pay for additional capabilities only when you need them. That keeps SEO expenses under control while giving you practical data to guide your content strategy.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/31300/top-ahrefs-semrush-alternatives-for-small-bloggers-on-a-budget</guid>
<pubDate>Fri, 16 Oct 2026 07:53:18 +0000</pubDate>
</item>
<item>
<title>Hermes: Autonomous AI Agents for Career Growth and Opportunity Exploration</title>
<link>https://coderlegion.com/30732/hermes-autonomous-ai-agents-for-career-growth-and-opportunity-exploration</link>
<description>&lt;p&gt;Hermes: Building Autonomous AI Agents for Career Growth and Opportunity Exploration&lt;br&gt;
Building AI that does more than answer questions&lt;/p&gt;
&lt;p&gt;Career development is becoming increasingly difficult to navigate.&lt;/p&gt;
&lt;p&gt;For many people, improving their career does not simply mean finding a job. It can involve identifying suitable opportunities, understanding whether their existing skills are relevant, preparing applications, learning new skills, communicating with recruiters, evaluating different possibilities, and continuously looking for better opportunities.&lt;/p&gt;
&lt;p&gt;At the same time, people whose income is limited or uncertain may also want to explore additional sources of income.&lt;/p&gt;
&lt;p&gt;The challenge is not simply a lack of information.&lt;/p&gt;
&lt;p&gt;There is already an enormous amount of information available.&lt;/p&gt;
&lt;p&gt;The challenge is the time, effort, cost, and uncertainty involved in turning that information into useful and validated action.&lt;/p&gt;
&lt;p&gt;This led to a question:&lt;/p&gt;
&lt;p&gt;Can an AI system continuously observe opportunities, reason about them, take controlled actions, measure the results, and learn from those results while helping people improve their career prospects and explore additional opportunities with less unnecessary cost and risk?&lt;/p&gt;
&lt;p&gt;That question became the starting point for Hermes.&lt;/p&gt;
&lt;p&gt;What is Hermes?&lt;/p&gt;
&lt;p&gt;Hermes is an autonomous AI-agent platform designed around a simple principle:&lt;/p&gt;
&lt;p&gt;An intelligent system should not only generate an answer. It should be able to observe, reason, act, evaluate the outcome, and improve from experience.&lt;/p&gt;
&lt;p&gt;The platform provides a common foundation for autonomous agents operating in different domains.&lt;/p&gt;
&lt;p&gt;Two major applications currently demonstrate this architecture:&lt;/p&gt;
&lt;p&gt;• Job Application Agent&lt;br&gt;
• Algorithmic Trading Agent&lt;/p&gt;
&lt;p&gt;The two agents solve very different problems, but they share the same underlying idea:&lt;/p&gt;
&lt;p&gt;Observe → Reason → Act → Measure → Learn&lt;/p&gt;
&lt;p&gt;The Regional Problem&lt;/p&gt;
&lt;p&gt;West Bengal has experienced decades of industrial contraction, factory closures, lockouts, and business relocation. The consequences of these changes are not limited to individual employment events.&lt;/p&gt;
&lt;p&gt;For workers and families, changes in employment can affect salary levels, financial stability, and the ability to invest in career development.&lt;/p&gt;
&lt;p&gt;At the same time, professional career assistance, training, application services, and other forms of support can require money that people may not always be comfortable spending.&lt;/p&gt;
&lt;p&gt;This creates a practical problem.&lt;/p&gt;
&lt;p&gt;A person trying to improve their career may need to:&lt;/p&gt;
&lt;p&gt;• Search across multiple job platforms&lt;br&gt;
• Understand different job descriptions&lt;br&gt;
• Determine whether their skills match&lt;br&gt;
• Identify skill gaps&lt;br&gt;
• Prepare applications&lt;br&gt;
• Customize their CV&lt;br&gt;
• Communicate with recruiters&lt;br&gt;
• Follow up on applications&lt;br&gt;
• Prepare for interviews&lt;br&gt;
• Learn new skills&lt;br&gt;
• Evaluate alternative career paths&lt;/p&gt;
&lt;p&gt;Much of this work is repetitive and requires continuous attention.&lt;/p&gt;
&lt;p&gt;There is also another dimension.&lt;/p&gt;
&lt;p&gt;Someone looking to improve their financial position may want to explore additional income opportunities. But exploring an opportunity should not mean immediately risking scarce financial resources.&lt;/p&gt;
&lt;p&gt;The goal should instead be to research, evaluate, and validate possibilities before committing significant time or money.&lt;/p&gt;
&lt;p&gt;This led to the broader problem that Hermes attempts to address:&lt;/p&gt;
&lt;p&gt;How can technology make career enhancement and opportunity exploration more accessible by reducing unnecessary time, effort, and cost while improving decision quality and introducing controlled validation before higher-risk actions?&lt;/p&gt;
&lt;p&gt;Hermes is our exploration of that problem.&lt;/p&gt;
&lt;p&gt;Agent 1: The Job Application Agent&lt;/p&gt;
&lt;p&gt;The first major application of Hermes focuses on career development.&lt;/p&gt;
&lt;p&gt;The Job Application Agent is designed to automate and assist with a large part of the employment-search workflow.&lt;/p&gt;
&lt;p&gt;Instead of treating a job posting as a simple text document, the system processes the opportunity through multiple stages.&lt;/p&gt;
&lt;p&gt;Job Discovery&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Job Description Understanding&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Qualification&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Skill Matching&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Skill-Gap Analysis&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Application Preparation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;ATS and Application Automation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Application Tracking&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Outcome Analysis&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Learning&lt;/p&gt;
&lt;p&gt;The objective is not simply to find more jobs.&lt;/p&gt;
&lt;p&gt;It is to help identify opportunities that are more relevant to the candidate and reduce unnecessary effort in the application process.&lt;/p&gt;
&lt;p&gt;Understanding the Job&lt;/p&gt;
&lt;p&gt;A job description can contain much more than a list of keywords.&lt;/p&gt;
&lt;p&gt;The system analyzes requirements such as:&lt;/p&gt;
&lt;p&gt;• Required skills&lt;br&gt;
• Preferred skills&lt;br&gt;
• Experience requirements&lt;br&gt;
• Eligibility conditions&lt;br&gt;
• Role characteristics&lt;br&gt;
• Technology requirements&lt;br&gt;
• Other relevant constraints&lt;/p&gt;
&lt;p&gt;This creates a structured representation of the opportunity that can then be evaluated against available candidate evidence.&lt;/p&gt;
&lt;p&gt;Qualification Is Not Left Entirely to an AI Model&lt;/p&gt;
&lt;p&gt;One important design decision in the Job Application Agent is that critical qualification decisions should not depend entirely on an unconstrained AI response.&lt;/p&gt;
&lt;p&gt;The system contains deterministic qualification logic.&lt;/p&gt;
&lt;p&gt;The qualification process considers multiple dimensions, including:&lt;/p&gt;
&lt;p&gt;Eligibility&lt;br&gt;
Candidate evidence&lt;br&gt;
Job quality&lt;br&gt;
Career fit&lt;br&gt;
Application-channel readiness&lt;/p&gt;
&lt;p&gt;The system can classify opportunities into states such as:&lt;/p&gt;
&lt;p&gt;• QUALIFIED&lt;br&gt;
• CONDITIONAL&lt;br&gt;
• NEAR_MISS&lt;br&gt;
• REJECT&lt;br&gt;
• INSUFFICIENT_DATA&lt;/p&gt;
&lt;p&gt;This creates a more explainable boundary between AI-assisted reasoning and deterministic decision logic.&lt;/p&gt;
&lt;p&gt;The objective is not to make every candidate appear qualified.&lt;/p&gt;
&lt;p&gt;The objective is to make the evaluation more useful and consistent.&lt;/p&gt;
&lt;p&gt;Semantic Skill Matching&lt;/p&gt;
&lt;p&gt;A simple keyword search can produce misleading results.&lt;/p&gt;
&lt;p&gt;Two technologies may be related without being interchangeable.&lt;/p&gt;
&lt;p&gt;Likewise, a candidate may possess transferable knowledge that is relevant even when the exact keyword does not appear in their existing CV.&lt;/p&gt;
&lt;p&gt;Hermes therefore uses semantic skill relationships to distinguish between:&lt;/p&gt;
&lt;p&gt;• Equivalent skills&lt;br&gt;
• Related technologies&lt;br&gt;
• Transferable skills&lt;br&gt;
• Explicit incompatibilities&lt;br&gt;
• Genuine missing requirements&lt;/p&gt;
&lt;p&gt;This allows the system to reason about skill gaps instead of simply counting matching words.&lt;/p&gt;
&lt;p&gt;Tailored Applications&lt;/p&gt;
&lt;p&gt;Once an opportunity has been evaluated, the system can prepare application material around the specific job.&lt;/p&gt;
&lt;p&gt;The objective is to avoid treating one generic CV as the correct representation for every opportunity.&lt;/p&gt;
&lt;p&gt;The workflow can include:&lt;/p&gt;
&lt;p&gt;Job Description&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Relevant Candidate Evidence&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Skill and Experience Selection&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Tailored CV&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;ATS Preparation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Application Submission&lt;/p&gt;
&lt;p&gt;This allows the application process to be adapted to the actual requirements of each opportunity.&lt;/p&gt;
&lt;p&gt;Application Tracking and Outcomes&lt;/p&gt;
&lt;p&gt;An autonomous system should not stop after generating an application.&lt;/p&gt;
&lt;p&gt;It needs to know what happened afterward.&lt;/p&gt;
&lt;p&gt;The Job Application Agent tracks application activity and outcomes.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;Application&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Submitted&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Recruiter or ATS Outcome&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Interview / Rejection / No Response&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Outcome Data&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Learning&lt;/p&gt;
&lt;p&gt;This feedback can then be used to improve future opportunity selection and application strategies.&lt;/p&gt;
&lt;p&gt;Learning From Application Outcomes&lt;/p&gt;
&lt;p&gt;Every application creates an opportunity to learn.&lt;/p&gt;
&lt;p&gt;Over time, the system can study patterns related to:&lt;/p&gt;
&lt;p&gt;• Which opportunities were relevant&lt;br&gt;
• Which applications produced responses&lt;br&gt;
• Which skills were frequently requested&lt;br&gt;
• Which skill gaps repeatedly appeared&lt;br&gt;
• Which application approaches produced better outcomes&lt;br&gt;
• Which opportunities resulted in interviews or other positive signals&lt;/p&gt;
&lt;p&gt;The goal is to gradually improve the system's ability to prioritize useful opportunities and reduce wasted effort.&lt;/p&gt;
&lt;p&gt;This creates an outcome-driven learning loop rather than a simple application generator.&lt;/p&gt;
&lt;p&gt;Agent 2: Algorithmic Trading Research&lt;/p&gt;
&lt;p&gt;The second application explores a very different type of opportunity: algorithmic trading.&lt;/p&gt;
&lt;p&gt;This component requires a different safety philosophy.&lt;/p&gt;
&lt;p&gt;The objective is not to tell financially vulnerable people to trade.&lt;/p&gt;
&lt;p&gt;The objective is to investigate whether autonomous research and learning systems can discover, evaluate, and validate algorithmic trading skills in a controlled environment.&lt;/p&gt;
&lt;p&gt;The architecture therefore begins with research rather than real-money execution.&lt;/p&gt;
&lt;p&gt;Historical Market Data&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Market Research&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Feature Extraction&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Pattern and Hypothesis Discovery&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Candidate Trading Skill&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Historical Validation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Paper Trading&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Outcome Measurement&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Learning and Reflection&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Further Validation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Potential Future Controlled Execution&lt;/p&gt;
&lt;p&gt;Why Paper Trading Matters&lt;/p&gt;
&lt;p&gt;Paper trading is not the final objective.&lt;/p&gt;
&lt;p&gt;It is a controlled evaluation stage.&lt;/p&gt;
&lt;p&gt;Historical data can help determine whether a trading idea would have behaved differently under historical market conditions.&lt;/p&gt;
&lt;p&gt;Paper trading provides another layer of evaluation by allowing the system to observe strategy behavior without immediately exposing real capital to an unvalidated approach.&lt;/p&gt;
&lt;p&gt;The intended progression is:&lt;/p&gt;
&lt;p&gt;Research&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Historical Validation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Paper Validation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Risk Validation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Potential Future Real Execution&lt;/p&gt;
&lt;p&gt;Any future transition toward real algorithmic option-chain execution should remain behind explicit validation and risk controls.&lt;/p&gt;
&lt;p&gt;Market Intelligence and Option-Chain Research&lt;/p&gt;
&lt;p&gt;The trading system is designed to work with much more than a simple price chart.&lt;/p&gt;
&lt;p&gt;The research layer includes areas such as:&lt;/p&gt;
&lt;p&gt;• Historical tick data&lt;br&gt;
• Option-chain information&lt;br&gt;
• Implied volatility&lt;br&gt;
• Realized volatility&lt;br&gt;
• IV surface&lt;br&gt;
• IV skew&lt;br&gt;
• IV term structure&lt;br&gt;
• Gamma exposure&lt;br&gt;
• Vanna&lt;br&gt;
• Charm&lt;br&gt;
• Market gaps&lt;br&gt;
• Market microstructure&lt;br&gt;
• Option Greeks&lt;br&gt;
• Pattern research&lt;br&gt;
• Outcome labeling&lt;/p&gt;
&lt;p&gt;These signals are not treated as guarantees of future market movement.&lt;/p&gt;
&lt;p&gt;Instead, they become inputs into a broader research and validation process.&lt;/p&gt;
&lt;p&gt;A trading hypothesis must earn its way through validation.&lt;/p&gt;
&lt;p&gt;The Common Learning Architecture&lt;/p&gt;
&lt;p&gt;Although employment automation and algorithmic trading appear unrelated, they expose an important common pattern.&lt;/p&gt;
&lt;p&gt;For the Job Application Agent:&lt;/p&gt;
&lt;p&gt;Opportunity&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Understanding&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Evaluation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Application&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Outcome&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Learning&lt;/p&gt;
&lt;p&gt;For the Trading Agent:&lt;/p&gt;
&lt;p&gt;Market Observation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Research&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Hypothesis&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Validation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Paper Trade&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Outcome&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Learning&lt;/p&gt;
&lt;p&gt;For Hermes:&lt;/p&gt;
&lt;p&gt;Observe&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Reason&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Plan&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Act&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Verify&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Measure Outcome&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Reflect&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Improve&lt;/p&gt;
&lt;p&gt;The domain changes.&lt;/p&gt;
&lt;p&gt;The learning architecture remains.&lt;/p&gt;
&lt;p&gt;AI Does Not Mean Removing Control&lt;/p&gt;
&lt;p&gt;One of the central engineering principles behind Hermes is that autonomy should not mean uncontrolled behavior.&lt;/p&gt;
&lt;p&gt;Different decisions require different levels of freedom.&lt;/p&gt;
&lt;p&gt;Some tasks benefit from AI reasoning.&lt;/p&gt;
&lt;p&gt;Other tasks should remain deterministic.&lt;/p&gt;
&lt;p&gt;AI-assisted reasoning can be used for activities such as:&lt;/p&gt;
&lt;p&gt;• Understanding complex information&lt;br&gt;
• Generating hypotheses&lt;br&gt;
• Research&lt;br&gt;
• Reasoning about alternatives&lt;br&gt;
• Reflection on outcomes&lt;/p&gt;
&lt;p&gt;Deterministic controls can handle areas such as:&lt;/p&gt;
&lt;p&gt;• Eligibility constraints&lt;br&gt;
• Risk limits&lt;br&gt;
• Execution permissions&lt;br&gt;
• Validation requirements&lt;br&gt;
• Safety gates&lt;br&gt;
• Kill switches&lt;/p&gt;
&lt;p&gt;This separation becomes particularly important when an agent can take actions rather than simply produce text.&lt;/p&gt;
&lt;p&gt;A Provider-Independent AI Architecture&lt;/p&gt;
&lt;p&gt;Hermes is designed around a provider-independent AI layer.&lt;/p&gt;
&lt;p&gt;Rather than embedding one model directly into every application, the platform uses a common AI routing architecture.&lt;/p&gt;
&lt;p&gt;Tasks can be classified according to their purpose, including areas such as:&lt;/p&gt;
&lt;p&gt;• Coding&lt;br&gt;
• Code review&lt;br&gt;
• Reasoning&lt;br&gt;
• Research&lt;br&gt;
• Trading research&lt;br&gt;
• General work&lt;br&gt;
• Reflexion&lt;/p&gt;
&lt;p&gt;The routing layer determines which configured model capability should handle the task.&lt;/p&gt;
&lt;p&gt;This creates a separation between agent logic and AI model infrastructure.&lt;/p&gt;
&lt;p&gt;It also allows the underlying model infrastructure to evolve without requiring every agent to be redesigned.&lt;/p&gt;
&lt;p&gt;Why This Architecture Matters&lt;/p&gt;
&lt;p&gt;The goal of Hermes is not to create a single-purpose chatbot.&lt;/p&gt;
&lt;p&gt;It is to create infrastructure for building agents that can operate through complete feedback loops.&lt;/p&gt;
&lt;p&gt;A conventional AI workflow might look like:&lt;/p&gt;
&lt;p&gt;Question → Answer&lt;/p&gt;
&lt;p&gt;An autonomous workflow can look like:&lt;/p&gt;
&lt;p&gt;Goal&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Observe&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Reason&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Plan&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Act&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Observe Result&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Evaluate&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Learn&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Improve Next Action&lt;/p&gt;
&lt;p&gt;That difference is fundamental.&lt;/p&gt;
&lt;p&gt;The system is not evaluated only by how good its answer looks.&lt;/p&gt;
&lt;p&gt;It can also be evaluated by what happens after the answer is used.&lt;/p&gt;
&lt;p&gt;What We Are Trying to Achieve&lt;/p&gt;
&lt;p&gt;Hermes is not intended to promise employment.&lt;/p&gt;
&lt;p&gt;It is not intended to guarantee income.&lt;/p&gt;
&lt;p&gt;It is not intended to eliminate financial risk.&lt;/p&gt;
&lt;p&gt;The trading component is also not intended to encourage people to immediately put money into markets.&lt;/p&gt;
&lt;p&gt;Instead, the project explores a more practical goal:&lt;/p&gt;
&lt;p&gt;Can autonomous AI reduce the cost and effort of career development and opportunity research while helping people make better-informed decisions and validate possibilities before taking larger risks?&lt;/p&gt;
&lt;p&gt;For career development, that means reducing repetitive work and helping people focus more on relevant opportunities.&lt;/p&gt;
&lt;p&gt;For additional income exploration, that means researching and validating possibilities rather than immediately committing scarce resources.&lt;/p&gt;
&lt;p&gt;What Makes the Project Interesting&lt;/p&gt;
&lt;p&gt;The interesting part of Hermes is not simply that it uses AI.&lt;/p&gt;
&lt;p&gt;AI is already capable of generating text, summarizing documents, and answering questions.&lt;/p&gt;
&lt;p&gt;The more difficult engineering problem is creating a system that can:&lt;/p&gt;
&lt;p&gt;• Understand its environment&lt;br&gt;
• Choose appropriate actions&lt;br&gt;
• Use external tools&lt;br&gt;
• Maintain state&lt;br&gt;
• Verify results&lt;br&gt;
• Collect outcomes&lt;br&gt;
• Learn from previous attempts&lt;br&gt;
• Operate within explicit safety boundaries&lt;/p&gt;
&lt;p&gt;The Job Application Agent and Algorithmic Trading Agent provide two very different environments in which to test this architecture.&lt;/p&gt;
&lt;p&gt;From Automation to Learning Systems&lt;/p&gt;
&lt;p&gt;The long-term direction of Hermes is to move from isolated automation toward systems that improve through experience.&lt;/p&gt;
&lt;p&gt;The intended learning loop is:&lt;/p&gt;
&lt;p&gt;Experience&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Outcome&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Reflection&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;New or Improved Skill&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Validation&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;Better Action&lt;/p&gt;
&lt;p&gt;↓&lt;/p&gt;
&lt;p&gt;New Experience&lt;/p&gt;
&lt;p&gt;The system does not assume that its first strategy is correct.&lt;/p&gt;
&lt;p&gt;It gathers evidence.&lt;/p&gt;
&lt;p&gt;It evaluates outcomes.&lt;/p&gt;
&lt;p&gt;It improves.&lt;/p&gt;
&lt;p&gt;Then it validates again.&lt;/p&gt;
&lt;p&gt;The Road Ahead&lt;/p&gt;
&lt;p&gt;There is still significant work ahead.&lt;/p&gt;
&lt;p&gt;The next stages include:&lt;/p&gt;
&lt;p&gt;• Expanding autonomous learning capabilities&lt;br&gt;
• Improving skill-gap and opportunity analysis&lt;br&gt;
• Strengthening outcome-based learning&lt;br&gt;
• Improving trading-skill validation&lt;br&gt;
• Increasing research coverage&lt;br&gt;
• Strengthening safety and risk controls&lt;br&gt;
• Expanding model-provider support&lt;br&gt;
• Improving observability and evaluation&lt;br&gt;
• Moving validated capabilities toward carefully controlled real-world execution&lt;/p&gt;
&lt;p&gt;The principle remains the same:&lt;/p&gt;
&lt;p&gt;Build first.&lt;/p&gt;
&lt;p&gt;Measure.&lt;/p&gt;
&lt;p&gt;Learn.&lt;/p&gt;
&lt;p&gt;Validate.&lt;/p&gt;
&lt;p&gt;Then expand.&lt;/p&gt;
&lt;p&gt;Conclusion&lt;/p&gt;
&lt;p&gt;Hermes started with a simple question:&lt;/p&gt;
&lt;p&gt;What if AI could do more than tell us what to do? What if it could help carry out the work, observe what happened, and learn from the result?&lt;/p&gt;
&lt;p&gt;The Job Application Agent applies that idea to career development.&lt;/p&gt;
&lt;p&gt;The Algorithmic Trading Agent applies it to controlled research into a potential additional income pathway.&lt;/p&gt;
&lt;p&gt;They are very different domains, but they share the same underlying architecture:&lt;/p&gt;
&lt;p&gt;Observe → Reason → Act → Measure → Learn&lt;/p&gt;
&lt;p&gt;The objective is not to promise a guaranteed job or guaranteed income.&lt;/p&gt;
&lt;p&gt;It is to explore how autonomous AI can make career enhancement and opportunity exploration more accessible, systematic, and less wasteful, while keeping important actions behind appropriate validation and safety controls.&lt;/p&gt;
&lt;p&gt;That is what we are building with Hermes.&lt;/p&gt;
&lt;p&gt;Project Links&lt;/p&gt;
&lt;p&gt;GitHub Repository: &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/methakon/my-job-agent&quot;&gt;https://github.com/methakon/my-job-agent&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Live Demo: &lt;a rel=&quot;nofollow&quot; href=&quot;https://berhampore.in&quot;&gt;https://berhampore.in&lt;/a&gt; (password protected will provide sublink letter)&lt;/p&gt;
&lt;p&gt;Video Demonstration:  comming soon &lt;/p&gt;
&lt;p&gt;About the Project&lt;/p&gt;
&lt;p&gt;Hermes is an evolving autonomous AI-agent platform. The project is being developed as a practical exploration of how AI agents can move beyond conversational assistance toward systems that can observe environments, perform actions, evaluate outcomes, and continuously improve through validated experience.&lt;/p&gt;
&lt;p&gt;Build first. Measure. Learn. Validate. Then expand.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/30732/hermes-autonomous-ai-agents-for-career-growth-and-opportunity-exploration</guid>
<pubDate>Sun, 11 Oct 2026 18:15:05 +0000</pubDate>
</item>
<item>
<title>How to Streamline Your Blogging Workflow with Automation Tools</title>
<link>https://coderlegion.com/29075/how-to-streamline-your-blogging-workflow-with-automation-tools</link>
<description>&lt;p&gt;Running a blog involves far more than writing articles. A typical publishing process can include topic research, content planning, drafting, editing, SEO checks, image preparation, publishing, social media promotion, analytics, and follow-up tasks. When every step is handled manually, even a small publishing schedule can consume a significant amount of time.&lt;/p&gt;
&lt;p&gt;Automation tools can reduce the repetitive work involved in this process. They can move information between applications, trigger tasks when specific events occur, schedule content for publication, and distribute new posts across multiple channels.&lt;/p&gt;
&lt;p&gt;The objective is not to automate every part of blogging. Writing, editorial judgment, fact-checking, and strategic decisions still require human oversight. The practical goal is to automate predictable administrative tasks so more time can be spent producing useful content.&lt;/p&gt;
&lt;p&gt;Start by Mapping the Blogging Workflow&lt;br&gt;
Before connecting a collection of automation tools, document how a blog currently operates.&lt;/p&gt;
&lt;p&gt;A basic workflow might look like this:&lt;/p&gt;
&lt;p&gt;Find a topic.&lt;br&gt;
Research the subject.&lt;br&gt;
Add the idea to a content calendar.&lt;br&gt;
Create an outline.&lt;br&gt;
Write the article.&lt;br&gt;
Edit and fact-check it.&lt;br&gt;
Optimize the headline, metadata, links, and images.&lt;br&gt;
Upload the article to the content management system.&lt;br&gt;
Schedule or publish it.&lt;br&gt;
Promote it on social media.&lt;br&gt;
Record performance data.&lt;br&gt;
Identify opportunities for future updates.&lt;br&gt;
The most useful automation opportunities are usually the repetitive transitions between these stages.&lt;/p&gt;
&lt;p&gt;For example, a new content idea could automatically create a task in a project-management database. When an article reaches an approved status, an automation could notify the editor. After publication, another workflow could send the article to a social media scheduling platform.&lt;/p&gt;
&lt;p&gt;Mapping the process first prevents a common mistake: adding automation without understanding the workflow it is supposed to improve.&lt;/p&gt;
&lt;p&gt;Use a Central Content Calendar&lt;br&gt;
A content calendar provides a single location for tracking ideas, assignments, deadlines, publishing dates, and article status.&lt;/p&gt;
&lt;p&gt;Tools such as Notion can be connected to automation platforms so that database activity triggers actions elsewhere. Zapier, for example, can use new Notion database items as triggers and create new database items or pages as actions.&lt;/p&gt;
&lt;p&gt;A blogging database could include fields such as:&lt;/p&gt;
&lt;p&gt;Article title&lt;br&gt;
Primary keyword&lt;br&gt;
Content category&lt;br&gt;
Writer&lt;br&gt;
Editor&lt;br&gt;
Status&lt;br&gt;
Draft deadline&lt;br&gt;
Publication date&lt;br&gt;
Target URL&lt;br&gt;
Social promotion status&lt;br&gt;
Update date&lt;br&gt;
The important point is consistency. Every article should move through the same defined stages rather than relying on scattered notes, email messages, and spreadsheets.&lt;/p&gt;
&lt;p&gt;Automate Repetitive Administrative Tasks&lt;br&gt;
Automation platforms are particularly useful when a task follows a predictable trigger-action pattern.&lt;/p&gt;
&lt;p&gt;Zapier describes its workflows as combinations of triggers and actions. A trigger starts the workflow, while subsequent actions perform predefined tasks. Its current platform supports thousands of applications and also provides AI-assisted workflow creation.&lt;/p&gt;
&lt;p&gt;Consider a simple example. A writer changes an article's status in a content database from &quot;Draft&quot; to &quot;Ready for Review.&quot; That change could trigger a notification to an editor.&lt;/p&gt;
&lt;p&gt;Another workflow could create a task when a new content idea is added to a database.&lt;/p&gt;
&lt;p&gt;These automations do not write the article. They eliminate repetitive coordination work.&lt;/p&gt;
&lt;p&gt;That distinction matters. Automation should handle predictable processes while editorial decisions remain under human control.&lt;/p&gt;
&lt;p&gt;Connect Your Content Calendar to WordPress&lt;br&gt;
WordPress provides built-in scheduling, allowing posts and pages to be configured for publication at a future date and time. The WordPress.com documentation also notes that the site's timezone affects when scheduled content is published.&lt;/p&gt;
&lt;p&gt;For publishers who want a more connected workflow, WordPress can also be integrated with automation platforms.&lt;/p&gt;
&lt;p&gt;Zapier's WordPress integration supports triggers and actions associated with posts, comments, users, and media. This can allow events inside WordPress to trigger activities in other applications.&lt;/p&gt;
&lt;p&gt;For example, a content operation could use an automation to:&lt;/p&gt;
&lt;p&gt;Create a WordPress draft from an approved content record.&lt;br&gt;
Notify a team when a post is published.&lt;br&gt;
Record a newly published URL in a content database.&lt;br&gt;
Trigger a downstream social media workflow.&lt;br&gt;
The automation should be tested carefully before being used for production publishing. A faulty workflow can duplicate content, publish incomplete drafts, or send incorrect information to other platforms.&lt;/p&gt;
&lt;p&gt;Automate Social Media Distribution&lt;br&gt;
Publishing an article is only one part of content distribution. Social media promotion can introduce another series of repetitive tasks, particularly for publishers managing multiple channels.&lt;/p&gt;
&lt;p&gt;Buffer provides a WordPress integration that can automatically add newly published blog posts to a social media queue. Its documentation describes a workflow in which a new WordPress post can be sent to Buffer automatically after publication.&lt;/p&gt;
&lt;p&gt;Buffer can also connect with automation services such as Zapier, Make, IFTTT, and n8n. These integrations can use triggers and actions to create posts or ideas and move information into Buffer without requiring every step to be performed manually.&lt;/p&gt;
&lt;p&gt;A practical workflow could therefore look like:&lt;/p&gt;
&lt;p&gt;New WordPress post → automation trigger → social media draft → scheduled distribution.&lt;/p&gt;
&lt;p&gt;The editorial team can still review the social copy before publication. Automation simply moves the information from one stage to another.&lt;/p&gt;
&lt;p&gt;Use AI Where It Saves Time, Not Where Accuracy Matters Most&lt;br&gt;
AI tools can assist with several parts of a blogging workflow, including brainstorming, outlining, summarization, headline variations, content repurposing, and routine editing.&lt;/p&gt;
&lt;p&gt;However, AI-generated material should not bypass editorial review. Automated output can contain factual errors, unsupported claims, incorrect terminology, or information that is no longer current.&lt;/p&gt;
&lt;p&gt;A more reliable workflow is to use AI as an assistant within defined stages.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;Topic research → human verification → AI-assisted outline → human-written or reviewed draft → fact-checking → editing → publication.&lt;/p&gt;
&lt;p&gt;This approach separates productivity gains from editorial responsibility.&lt;/p&gt;
&lt;p&gt;AI can also be incorporated into broader automation workflows. Zapier currently provides AI features that can help users create workflows and troubleshoot workflow errors, while its automation system remains based on defined triggers and actions.&lt;/p&gt;
&lt;p&gt;Build Automated Content Notifications&lt;br&gt;
Team communication is another area where automation can reduce unnecessary manual work.&lt;/p&gt;
&lt;p&gt;Suppose an article moves into an &quot;Approved&quot; status. Instead of an employee checking the content calendar repeatedly, the workflow could send a notification to the person responsible for publication.&lt;/p&gt;
&lt;p&gt;Similar triggers could notify a team when:&lt;/p&gt;
&lt;p&gt;A draft is ready for editing.&lt;br&gt;
An article has been approved.&lt;br&gt;
A scheduled publication date is approaching.&lt;br&gt;
A post has gone live.&lt;br&gt;
A social media draft has been created.&lt;br&gt;
A required content field is missing.&lt;br&gt;
These small automations become more valuable as the publishing operation grows.&lt;/p&gt;
&lt;p&gt;Automate Reporting Without Automating the Analysis&lt;br&gt;
Blogging produces large amounts of performance information. Traffic, search visibility, conversions, engagement, and social activity can become difficult to track manually.&lt;/p&gt;
&lt;p&gt;Automation can help collect or organize this information, but the interpretation should remain deliberate.&lt;/p&gt;
&lt;p&gt;For example, a workflow might transfer selected campaign information into a reporting spreadsheet or database. The content team can then review the data and decide which topics deserve additional coverage or updating.&lt;/p&gt;
&lt;p&gt;The goal is not to create a dashboard full of numbers. The goal is to reduce the administrative work required to obtain the information needed for editorial decisions.&lt;/p&gt;
&lt;p&gt;Keep Human Review at Critical Checkpoints&lt;br&gt;
The biggest mistake in blogging automation is treating automation as a replacement for editorial judgment.&lt;/p&gt;
&lt;p&gt;Several checkpoints should remain under human control:&lt;/p&gt;
&lt;p&gt;Factual verification&lt;br&gt;
Source evaluation&lt;br&gt;
Legal or compliance review&lt;br&gt;
Final editing&lt;br&gt;
Brand voice&lt;br&gt;
Sensitive topics&lt;br&gt;
Claims about products or companies&lt;br&gt;
Final publication approval&lt;br&gt;
Automation should make these checkpoints easier to manage, not eliminate them.&lt;/p&gt;
&lt;p&gt;A useful principle is simple: automate the process around the content, but maintain human responsibility for the content itself.&lt;/p&gt;
&lt;p&gt;Start With One Workflow&lt;br&gt;
A blogging operation does not need dozens of automations on the first day.&lt;/p&gt;
&lt;p&gt;Start with one repetitive process that occurs frequently and has a clear trigger and predictable outcome.&lt;/p&gt;
&lt;p&gt;For example:&lt;/p&gt;
&lt;p&gt;New blog post published → automatically create a social media draft.&lt;/p&gt;
&lt;p&gt;Once that workflow operates reliably, another can be added:&lt;/p&gt;
&lt;p&gt;New approved content idea → automatically create an assignment in the project-management system.&lt;/p&gt;
&lt;p&gt;Then another:&lt;/p&gt;
&lt;p&gt;Article marked ready for review → automatically notify the editor.&lt;/p&gt;
&lt;p&gt;This incremental approach makes it easier to identify errors and measure whether an automation is actually saving time.&lt;/p&gt;
&lt;p&gt;The Goal Is a More Efficient Publishing System&lt;br&gt;
Blogging automation works best when it removes repetitive administrative work without removing editorial control.&lt;/p&gt;
&lt;p&gt;A modern workflow can combine a content database, an AI assistant, an automation platform, WordPress, and a social media scheduling service. Notion can manage structured content information, Zapier can connect applications and trigger actions, WordPress can handle scheduled publishing, and Buffer can help distribute published content across social channels.&lt;/p&gt;
&lt;p&gt;The most effective setup will depend on the publication's size, publishing frequency, team structure, and existing software.&lt;/p&gt;
&lt;p&gt;The important first step is not buying more software. It is identifying which blogging tasks are repetitive, predictable, and time-consuming. Those tasks are the strongest candidates for automation.&lt;/p&gt;
&lt;p&gt;Once those processes are documented and connected, bloggers and content teams can spend less time moving information between applications and more time researching, writing, editing, and improving the content that audiences actually read.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/29075/how-to-streamline-your-blogging-workflow-with-automation-tools</guid>
<pubDate>Tue, 29 Sep 2026 13:10:42 +0000</pubDate>
</item>
<item>
<title>How to Find SEO Issues Before Publishing a Blog Post</title>
<link>https://coderlegion.com/27844/how-to-find-seo-issues-before-publishing-a-blog-post</link>
<description>&lt;p&gt;Publishing an article without a final SEO check can lead to indexing, ranking, speed, and internal-linking problems.&lt;br&gt;
Here’s a quick pre-publishing SEO checklist you can use before hitting “Publish.”&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Check Search Intent&lt;/strong&gt;&lt;br&gt;
Make sure your article actually answers what people are searching for. Look at the current search results and identify the questions and information users expect.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;**Optimize the Title &amp;amp; Meta &lt;/strong&gt;Description**&lt;br&gt;
Your title should clearly explain the page topic and include your primary keyword naturally. Write a useful meta description that encourages clicks without keyword stuffing.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Review Your Headings&lt;/strong&gt;&lt;br&gt;
Use a logical structure:&lt;br&gt;
H1 → H2 → H3&lt;br&gt;
Each section should cover a specific part of the topic.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check Keyword Usage&lt;/strong&gt;&lt;br&gt;
Use your primary and related keywords naturally. Don't repeat a keyword just to increase keyword density.&lt;br&gt;
Focus on answering the reader's question thoroughly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check Internal Links&lt;/strong&gt;&lt;br&gt;
Add relevant links to other articles and tools on your website. Internal linking helps readers discover related content and helps search engines understand your site's structure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimize Images&lt;/strong&gt;&lt;br&gt;
Before publishing:&lt;br&gt;
Compress large images&lt;br&gt;
Use descriptive filenames&lt;br&gt;
Add useful alt text&lt;br&gt;
Avoid unnecessarily large dimensions&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test Mobile &amp;amp; Page Speed&lt;/strong&gt;&lt;br&gt;
Check how the page looks on mobile and test its performance. Pay particular attention to layout shifts, large images, and unnecessary scripts.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check Indexing &amp;amp; Canonical&lt;/strong&gt;&lt;br&gt;
Make sure the page isn't accidentally set to noindex and that the canonical URL points to the correct page.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Check Structured Data&lt;/strong&gt;&lt;br&gt;
If structured data is relevant to your content, validate it before publishing. Don't add schema simply because it exists—use markup that accurately describes the page.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Use Google Search Console After Publishing&lt;/strong&gt;&lt;br&gt;
Once the article is live, inspect the URL in Search Console and monitor:&lt;br&gt;
Impressions&lt;br&gt;
Clicks&lt;br&gt;
Queries&lt;br&gt;
Average position&lt;br&gt;
Indexing status&lt;br&gt;
SEO doesn't end when you publish. Publishing is the beginning of the measurement phase.&lt;br&gt;
&lt;strong&gt;Final checklist&lt;/strong&gt;&lt;br&gt;
Before publishing, ask:&lt;br&gt;
Does this article satisfy search intent?&lt;br&gt;
Is the information genuinely useful?&lt;br&gt;
Is the page technically accessible?&lt;br&gt;
Are internal links relevant?&lt;br&gt;
Does it work well on mobile?&lt;br&gt;
Can Google understand the page?&lt;br&gt;
A simple checklist like this can catch many SEO problems before they become ranking problems.&lt;br&gt;
Related: If you want to audit your pages after publishing, try an SEO analyzer to identify technical and on-page issues.&lt;/li&gt;
&lt;/ol&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/27844/how-to-find-seo-issues-before-publishing-a-blog-post</guid>
<pubDate>Sun, 20 Sep 2026 14:53:38 +0000</pubDate>
</item>
<item>
<title>Should Your Business Have a Blog? The Honest Answer</title>
<link>https://coderlegion.com/26308/should-your-business-have-a-blog-the-honest-answer</link>
<description>&lt;p&gt;&quot;You should be blogging&quot; is advice given to nearly every business regardless of what they actually do, which is exactly why it's worth questioning rather than accepting automatically. A blog is a real, ongoing commitment, and for some businesses it's genuinely one of the highest-leverage things they can do. For others, it's a slow drain on time that never produces a meaningful return. Here's how to actually tell which situation you're in.&lt;/p&gt;
&lt;h3 id=&quot;what-a-blog-actually-does-when-it-works&quot;&gt;What a Blog Actually Does, When It Works&lt;/h3&gt;
&lt;p&gt;A business blog's real function is capturing search traffic for the specific questions your potential customers are already asking, before they know your specific business exists. Someone searching &quot;how much does a website cost&quot; isn't searching for you by name, they're searching for an answer, and a genuinely useful post answering that question is how a stranger becomes aware you exist in the first place.&lt;/p&gt;
&lt;p&gt;Done well, this compounds over time in a way paid advertising doesn't. A well-ranking post keeps bringing in visitors for years after it's published, without ongoing spend, which is fundamentally different from ad traffic that stops the moment the budget does.&lt;/p&gt;
&lt;h3 id=&quot;why-it-fails-for-a-lot-of-businesses&quot;&gt;Why It Fails for a Lot of Businesses&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Publishing without a real strategy behind it.&lt;/strong&gt; A blog with no clear picture of what specific questions its actual customers are searching for tends to produce content that satisfies nobody, too generic to rank well, too unfocused to convert the traffic it does get.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Inconsistency.&lt;/strong&gt; A blog with three posts, the last one from over a year ago, actively signals neglect rather than helping at all, undermining trust more than an absent blog would have. Half-committing is often worse than not starting.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Content that doesn't match how the business actually makes money.&lt;/strong&gt; A blog can drive real traffic and still contribute nothing to revenue if the topics never connect back to what the business actually sells or the decisions its real customers are making.&lt;/p&gt;
&lt;h3 id=&quot;the-real-question-does-your-business-have-genuine-search-demand&quot;&gt;The Real Question: Does Your Business Have Genuine Search Demand&lt;/h3&gt;
&lt;p&gt;This is the question that actually determines whether blogging makes sense, more than any generic advice about content marketing. Some businesses serve markets where real people are actively searching for answers related to what that business does, web development, health topics, financial questions, genuinely broad categories with real search volume behind specific questions. Other businesses serve markets where almost nobody is searching anything relevant, a highly local service with no informational search behavior around it, a business reached almost entirely through referral or existing relationships rather than search.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A blog makes sense if:&lt;/strong&gt; real people are genuinely searching questions related to what you do, your sales cycle benefits from building trust and demonstrating expertise before a first conversation, or you're competing in a market where content-driven authority genuinely influences buying decisions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A blog probably doesn't make sense, at least not as a priority, if:&lt;/strong&gt; your actual customer base finds you almost entirely through referral or existing relationships, there's minimal genuine search volume for anything related to what you do, or the time a blog would require is better spent on something with a clearer, faster return for your specific business right now.&lt;/p&gt;
&lt;h3 id=&quot;what-doing-it-well-actually-requires&quot;&gt;What &quot;Doing It Well&quot; Actually Requires&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Genuine topic research&lt;/strong&gt;, not guessing at what might be interesting, actually finding what your real potential customers are searching, and answering those specific questions directly and thoroughly.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Real consistency&lt;/strong&gt;, a realistic, sustainable publishing rhythm you can actually maintain, rather than an ambitious schedule that collapses after a month and leaves a visibly abandoned blog behind.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Content that connects back to what you actually offer.&lt;/strong&gt; Not every post needs a hard sell, but a consistent pattern of content that never relates back to your actual business rarely converts, regardless of how much traffic it generates.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Patience with the actual timeline.&lt;/strong&gt; Blog content typically takes months, not weeks, to start producing meaningful search traffic, and treating it as a quick-win channel usually leads to abandoning it right before it would have started working.&lt;/p&gt;
&lt;h3 id=&quot;what-to-do-instead-if-a-blog-genuinely-isn-t-the-right-fit&quot;&gt;What to Do Instead, If a Blog Genuinely Isn't the Right Fit&lt;/h3&gt;
&lt;p&gt;Not every business needs to force this specific channel. Referral programs, direct outreach, partnerships, or paid channels with a faster, clearer feedback loop can be a genuinely better use of the same time and effort for a business whose actual customers aren't finding solutions through search behavior in the first place. The honest goal is matching effort to where your specific customers actually are, not defaulting to blogging because it's common generic advice.&lt;/p&gt;
&lt;h3 id=&quot;frequently-asked-questions&quot;&gt;Frequently Asked Questions&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;How long does it take for a business blog to start producing real results?&lt;/strong&gt;&lt;br&gt;
Meaningful organic traffic typically takes several months to begin building, and real, consistent results often take closer to a year of sustained, genuinely useful publishing. This is one of the biggest reasons blogs get abandoned prematurely, right around the point they'd realistically start working.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;How often should a business actually publish blog content?&lt;/strong&gt;&lt;br&gt;
A sustainable, realistic cadence maintained consistently outperforms an ambitious schedule that collapses after a few months. Once every week or two, genuinely maintained for a year, produces far more real value than daily posting for a month followed by silence.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Can a blog work for a very niche or local business?&lt;/strong&gt;&lt;br&gt;
Yes, if there's genuine search demand around the specific niche or local area, even at a smaller volume than a broader market would have. The key question stays the same regardless of niche size, is there real search behavior to capture, not whether the specific topic sounds broad enough to justify a blog.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;If you're trying to figure out whether a blog is actually the right investment for your specific business, I'm happy to give an honest read on whether the search demand is genuinely there.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Get in touch:&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://pixelanas.com/contact&quot;&gt;https://pixelanas.com/contact&lt;/a&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;Anas, full-stack Next.js developer building SaaS products and premium templates. X: &lt;a rel=&quot;nofollow&quot; href=&quot;https://x.com/ASheikh69751&quot;&gt;@ASheikh69751&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/26308/should-your-business-have-a-blog-the-honest-answer</guid>
<pubDate>Sun, 06 Sep 2026 08:41:57 +0000</pubDate>
</item>
<item>
<title>next-mdx-remote-client Guide for Next.js 16 (2026)</title>
<link>https://coderlegion.com/25579/next-mdx-remote-client-guide-for-next-js-16-2026</link>
<description>&lt;p&gt;If you followed &lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/blog/mdx-remote-nextjs-16-guide&quot;&gt;our original MDX blog setup guide&lt;/a&gt;, you already have a working blog powered by &lt;code&gt;next-mdx-remote&lt;/code&gt;. There's just one problem: HashiCorp archived that repo on April 9, 2026. The package still runs fine today — nothing breaks overnight — but it's now frozen. No new features, no security patches, no fixes if a future Next.js or React release changes something it depends on.&lt;/p&gt;
&lt;p&gt;That's not a reason to panic, but it is a reason to plan your next move. The community's answer is &lt;strong&gt;&lt;code&gt;next-mdx-remote-client&lt;/code&gt;&lt;/strong&gt; — an actively maintained fork that keeps the same mental model (compile MDX on the server, render it as React) while fixing several rough edges the original never got around to, including a proper built-in error boundary and support for &lt;code&gt;export&lt;/code&gt; statements inside MDX on the App Router.&lt;/p&gt;
&lt;p&gt;This guide walks through the same MDX blog setup as before, rebuilt from scratch on &lt;code&gt;next-mdx-remote-client&lt;/code&gt; — content folder, typed data layer, custom components, syntax highlighting, and dynamic SEO metadata — so you can migrate confidently or start fresh if you're building a new Next.js 16 blog today.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;Note: This guide targets the &lt;strong&gt;App Router&lt;/strong&gt; using &lt;code&gt;next-mdx-remote-client&lt;/code&gt;'s React Server Component API (the &lt;code&gt;/rsc&lt;/code&gt; subpath). If you're on the Pages Router, the package has a separate, isolated API for that too — see the &lt;a rel=&quot;nofollow&quot; href=&quot;#page-router-faq&quot;&gt;FAQ&lt;/a&gt; at the end.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id=&quot;why-next-mdx-remote-client-instead-of-next-mdx-remote&quot;&gt;Why next-mdx-remote-client Instead of next-mdx-remote?&lt;/h2&gt;
&lt;p&gt;Both packages solve the same problem: MDX content stored &lt;em&gt;outside&lt;/em&gt; your &lt;code&gt;app&lt;/code&gt; folder — a &lt;code&gt;content/blogs&lt;/code&gt; directory, a database, a CMS — rendered through one dynamic &lt;code&gt;[slug]&lt;/code&gt; route, instead of every post being its own route file under &lt;code&gt;@next/mdx&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;While the original &lt;code&gt;next-mdx-remote&lt;/code&gt; was the long-time standard for this pattern, its archiving means developers need a modern alternative. &lt;code&gt;next-mdx-remote-client&lt;/code&gt; has emerged as the community's go-to, actively maintained drop-in replacement built specifically for the App Router. A few concrete differences that actually matter day to day:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Feature &lt;/th&gt;&lt;th&gt;&lt;code&gt;next-mdx-remote&lt;/code&gt; &lt;/th&gt;&lt;th&gt;&lt;code&gt;next-mdx-remote-client&lt;/code&gt;&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;Actively maintained &lt;/td&gt;&lt;td&gt;❌ Archived April 2026 &lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Built-in error handling in App Router &lt;/td&gt;&lt;td&gt;❌ You wrap it yourself &lt;/td&gt;&lt;td&gt;✅ &lt;code&gt;onError&lt;/code&gt; prop&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;export&lt;/code&gt; statements from MDX in App Router &lt;/td&gt;&lt;td&gt;❌ &lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Get frontmatter + scope without a separate parse step &lt;/td&gt;&lt;td&gt;❌ &lt;/td&gt;&lt;td&gt;✅ (&lt;code&gt;evaluate&lt;/code&gt; function)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Utility to read frontmatter without compiling &lt;/td&gt;&lt;td&gt;❌ &lt;/td&gt;&lt;td&gt;✅ &lt;code&gt;getFrontmatter&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;MDX version &lt;/td&gt;&lt;td&gt;3 &lt;/td&gt;&lt;td&gt;3&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;&lt;strong&gt;What &quot;built-in error handling&quot; actually buys you:&lt;/strong&gt; with &lt;code&gt;next-mdx-remote&lt;/code&gt;, a broken MDX file (a stray &lt;code&gt;{&lt;/code&gt; in an expression, an unclosed JSX tag) throws during render, and it's on you to catch it with an &lt;code&gt;ErrorBoundary&lt;/code&gt;. &lt;code&gt;next-mdx-remote-client&lt;/code&gt;'s &lt;code&gt;MDXRemote&lt;/code&gt; component takes an &lt;code&gt;onError&lt;/code&gt; prop directly, so a bad post shows a friendly fallback instead of crashing the whole page — which matters a lot the first time a typo in frontmatter takes down your blog in production.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;Tip:&lt;/strong&gt; &lt;code&gt;next-mdx-remote-client&lt;/code&gt; requires &lt;strong&gt;React 19.1+&lt;/strong&gt; and is tested against &lt;strong&gt;Next.js 15 and 16&lt;/strong&gt;. If your project is still on React 18, install the &lt;code&gt;@^1&lt;/code&gt; tag instead — see &lt;a rel=&quot;nofollow&quot; href=&quot;#step-1-install-dependencies&quot;&gt;Step 1&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;a-quick-word-on-security&quot;&gt;A Quick Word on Security&lt;/h3&gt;
&lt;p&gt;Before writing any code: MDX compiles to executable JavaScript. That's what makes &lt;code&gt;&amp;lt;Component /&amp;gt;&lt;/code&gt; tags work inside your Markdown, but it also means rendering MDX from a source you don't fully control (user submissions, an open CMS) can enable XSS or even remote code execution — this is true of every MDX renderer, not something specific to this package.&lt;/p&gt;
&lt;p&gt;For a personal or team blog where you're the only one writing &lt;code&gt;.mdx&lt;/code&gt; files, this isn't a practical concern — you already trust your own content. If you ever accept MDX from outside contributors, strip dangerous expressions at the remark stage first (the maintainer's own &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/ipikuka/remark-mdx-remove-expressions&quot;&gt;&lt;code&gt;remark-mdx-remove-expressions&lt;/code&gt;&lt;/a&gt; plugin is built for exactly this) rather than trying to sanitize after the fact.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;/h3&gt;
&lt;p&gt;This guide uses:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Next.js 16&lt;/strong&gt; with the App Router&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;React 19.2+&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TypeScript&lt;/strong&gt; in strict mode&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Node.js 20.9+&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;We'll build:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MDX files stored in a &lt;code&gt;content/blogs&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;A reusable &lt;code&gt;getAllPosts()&lt;/code&gt; / &lt;code&gt;getPostBySlug()&lt;/code&gt; data layer&lt;/li&gt;
&lt;li&gt;Custom-styled MDX components (headings, code blocks, links, tables)&lt;/li&gt;
&lt;li&gt;Syntax highlighting with &lt;code&gt;sugar-high&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;remark-gfm&lt;/code&gt; for GitHub-flavored Markdown (tables, strikethrough, task lists)&lt;/li&gt;
&lt;li&gt;Built-in error handling via &lt;code&gt;onError&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Dynamic SEO metadata and JSON-LD structured data per post&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2 id=&quot;step-1-install-dependencies&quot;&gt;Step 1: Install Dependencies&lt;/h2&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install next-mdx-remote-client gray-matter remark-gfm reading-time sugar-high
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Since when this matters is the whole point of this migration, be explicit about which major version you need:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;# React 19 projects (the default for new Next.js 16 apps)
npm install next-mdx-remote-client@^2

# React 18 projects
npm install next-mdx-remote-client@^1
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;What each package does:&lt;/strong&gt;&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Package &lt;/th&gt;&lt;th&gt;Purpose&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;next-mdx-remote-client&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Compiles and renders MDX strings as React, with built-in error handling&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;gray-matter&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Parses frontmatter for the post-listing data layer&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;remark-gfm&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Adds GitHub-flavored Markdown — tables, strikethrough, task lists&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;reading-time&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Calculates estimated reading time from post content&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;sugar-high&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Lightweight, zero-client-JS syntax highlighter for code blocks&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;&lt;p&gt;⚠️ &lt;strong&gt;Common Mistake:&lt;/strong&gt; Importing from &lt;code&gt;next-mdx-remote-client&lt;/code&gt; directly. The package splits its App Router and Pages Router code into &lt;strong&gt;separate, isolated subpaths&lt;/strong&gt; — for the App Router you always import from &lt;code&gt;next-mdx-remote-client/rsc&lt;/code&gt;, never the bare package name. We'll use that subpath throughout this guide.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-2-content-folder-and-frontmatter-unchanged-&quot;&gt;Step 2: Content Folder and Frontmatter (Unchanged)&lt;/h3&gt;
&lt;p&gt;If you're migrating from the original guide, this part doesn't change at all — &lt;code&gt;next-mdx-remote-client&lt;/code&gt; reads the same MDX files.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;content/blogs/hello-world.mdx
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-md&quot;&gt;---
title: &quot;Hello World: My First MDX Post&quot;
description: &quot;A short example post to test out the next-mdx-remote-client setup.&quot;
publishedAt: &quot;2026-08-20&quot;
tags: [&quot;MDX&quot;, &quot;Next.js&quot;]
featured: false
---

## Hello World

This is my **first** MDX post rendered with `next-mdx-remote-client`.

- It supports Markdown
- It supports *React components*
- It even supports tables (thanks to remark-gfm)

| Feature            | Supported |
| ------------------ | --------- |
| Tables             | ✅       |
| Code blocks        | ✅       |
| Custom components  | ✅       |
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Keep frontmatter field names consistent across every post (&lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;publishedAt&lt;/code&gt;, &lt;code&gt;tags&lt;/code&gt;). A typo like &lt;code&gt;date&lt;/code&gt; instead of &lt;code&gt;publishedAt&lt;/code&gt; on one file will silently break sorting for that post, since your data layer expects an exact key.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id=&quot;step-3-build-the-data-layer&quot;&gt;Step 3: Build the Data Layer&lt;/h2&gt;
&lt;p&gt;This file reads every &lt;code&gt;.mdx&lt;/code&gt; file from disk, parses frontmatter with &lt;code&gt;gray-matter&lt;/code&gt;, and returns typed post objects for your listing page. This part still uses &lt;code&gt;gray-matter&lt;/code&gt; on purpose — it's what powers the blog index (&lt;code&gt;getAllPosts&lt;/code&gt;), which needs frontmatter &lt;em&gt;without&lt;/em&gt; compiling MDX for every post just to render a list.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// lib/posts.ts
import fs from &quot;fs&quot;;
import path from &quot;path&quot;;
import matter from &quot;gray-matter&quot;;
import readingTime from &quot;reading-time&quot;;

const POSTS_PATH = path.join(process.cwd(), &quot;content/blogs&quot;);

export type Post = {
  slug: string;
  title: string;
  description: string;
  publishedAt: string;
  updatedAt?: string;
  tags: string[];
  readingTime: string;
  content: string;
};

export function getAllPosts(): Post[] {
  const files = fs.readdirSync(POSTS_PATH);

  const posts = files.map((file) =&amp;gt; {
    const filePath = path.join(POSTS_PATH, file);
    const fileContent = fs.readFileSync(filePath, &quot;utf-8&quot;);

    const { data, content } = matter(fileContent);

    const slug = file.replace(/\.mdx$/, &quot;&quot;);

    return {
      slug,
      title: data.title,
      description: data.description,
      publishedAt: data.publishedAt,
      updatedAt: data.updatedAt,
      tags: data.tags || [],
      readingTime: readingTime(content).text,
      content,
    };
  });

  return posts.sort(
    (a, b) =&amp;gt;
      new Date(b.publishedAt).getTime() - new Date(a.publishedAt).getTime()
  );
}

export function getPostBySlug(slug: string) {
  return getAllPosts().find((post) =&amp;gt; post.slug === slug);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;Tip — an alternative worth knowing:&lt;/strong&gt; &lt;code&gt;next-mdx-remote-client&lt;/code&gt; ships its own &lt;code&gt;getFrontmatter&lt;/code&gt; utility that reads frontmatter &lt;strong&gt;without&lt;/strong&gt; compiling the MDX, using the same &lt;code&gt;vfile-matter&lt;/code&gt; extractor internally:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;import { getFrontmatter } from &quot;next-mdx-remote-client/utils&quot;;

const { frontmatter, strippedSource } = getFrontmatter&amp;lt;Post&amp;gt;(fileContent);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It's isolated in its own subpath and costs almost nothing to import, so it's a reasonable way to drop the &lt;code&gt;gray-matter&lt;/code&gt; dependency entirely if you're starting fresh. This guide keeps &lt;code&gt;gray-matter&lt;/code&gt; since it's already a common dependency in most Next.js content setups and behaves identically either way.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;Tip:&lt;/strong&gt; &lt;code&gt;lib/posts.ts&lt;/code&gt; uses Node's &lt;code&gt;fs&lt;/code&gt; module, so it only runs on the server — inside Server Components, &lt;code&gt;generateStaticParams&lt;/code&gt;, or &lt;code&gt;generateMetadata&lt;/code&gt;. Never import it into a &lt;code&gt;&quot;use client&quot;&lt;/code&gt; component.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-4-create-custom-mdx-components&quot;&gt;Step 4: Create Custom MDX Components&lt;/h3&gt;
&lt;p&gt;The component map itself is unchanged from a &lt;code&gt;next-mdx-remote&lt;/code&gt; setup — this is standard &lt;code&gt;@mdx-js/mdx&lt;/code&gt; behavior, and &lt;code&gt;next-mdx-remote-client&lt;/code&gt; uses the same convention.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;// mdx-components.tsx
import React, { ComponentPropsWithoutRef } from &quot;react&quot;;
import Link from &quot;next/link&quot;;
import { highlight } from &quot;sugar-high&quot;;
import type { MDXComponents } from &quot;next-mdx-remote-client/rsc&quot;;

type HeadingProps = ComponentPropsWithoutRef&amp;lt;&quot;h1&quot;&amp;gt;;
type ParagraphProps = ComponentPropsWithoutRef&amp;lt;&quot;p&quot;&amp;gt;;
type ListProps = ComponentPropsWithoutRef&amp;lt;&quot;ul&quot;&amp;gt;;
type AnchorProps = ComponentPropsWithoutRef&amp;lt;&quot;a&quot;&amp;gt;;
type BlockquoteProps = ComponentPropsWithoutRef&amp;lt;&quot;blockquote&quot;&amp;gt;;

export const mdxComponents: MDXComponents = {
  h1: (props: HeadingProps) =&amp;gt; (
    &amp;lt;h1 className=&quot;scroll-m-20 text-4xl font-bold tracking-tight lg:text-5xl&quot; {...props} /&amp;gt;
  ),
  h2: (props: HeadingProps) =&amp;gt; (
    &amp;lt;h2 className=&quot;scroll-m-20 mt-16 pb-2 text-3xl font-semibold tracking-tight&quot; {...props} /&amp;gt;
  ),
  h3: (props: HeadingProps) =&amp;gt; (
    &amp;lt;h3 className=&quot;scroll-m-20 mt-12 text-2xl font-semibold tracking-tight&quot; {...props} /&amp;gt;
  ),
  p: (props: ParagraphProps) =&amp;gt; (
    &amp;lt;p className=&quot;text-gray-800 dark:text-zinc-300&quot; {...props} /&amp;gt;
  ),
  ul: (props: ListProps) =&amp;gt; (
    &amp;lt;ul className=&quot;text-gray-800 dark:text-zinc-300 list-disc pl-5 space-y-1&quot; {...props} /&amp;gt;
  ),
  a: ({ href, children, ...props }: AnchorProps) =&amp;gt; {
    const className = &quot;text-blue-500 hover:text-blue-700&quot;;

    if (href?.startsWith(&quot;/&quot;)) {
      return (
        &amp;lt;Link href={href} className={className} {...props}&amp;gt;
          {children}
        &amp;lt;/Link&amp;gt;
      );
    }

    return (
      &amp;lt;a href={href} target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; className={className} {...props}&amp;gt;
        {children}
      &amp;lt;/a&amp;gt;
    );
  },
  code: ({ children, ...props }: ComponentPropsWithoutRef&amp;lt;&quot;code&quot;&amp;gt;) =&amp;gt; {
    const codeHTML = highlight(String(children));
    return &amp;lt;code dangerouslySetInnerHTML={{ __html: codeHTML }} {...props} /&amp;gt;;
  },
  blockquote: (props: BlockquoteProps) =&amp;gt; (
    &amp;lt;blockquote className=&quot;ml-[0.075em] border-l-3 border-green-400 pl-4 text-gray-700&quot; {...props} /&amp;gt;
  ),
};
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;What's different here from a &lt;code&gt;next-mdx-remote&lt;/code&gt; setup:&lt;/strong&gt; the &lt;code&gt;MDXComponents&lt;/code&gt; type now comes from &lt;code&gt;next-mdx-remote-client/rsc&lt;/code&gt; instead of &lt;code&gt;mdx/types&lt;/code&gt; — the package re-exports it so you don't need a separate import. Everything else, including the special &lt;code&gt;wrapper&lt;/code&gt; key if you want to wrap MDX content in a container element, works exactly the same way.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-5-build-the-dynamic-blog-route&quot;&gt;Step 5: Build the Dynamic Blog Route&lt;/h3&gt;
&lt;p&gt;This is where the actual migration happens. Swap the import source and add the &lt;code&gt;onError&lt;/code&gt; prop — the rest of the route looks familiar if you've built this with &lt;code&gt;next-mdx-remote&lt;/code&gt; before.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;// app/blog/[slug]/page.tsx
import { Suspense } from &quot;react&quot;;
import { notFound } from &quot;next/navigation&quot;;
import { MDXRemote, type MDXRemoteOptions } from &quot;next-mdx-remote-client/rsc&quot;;
import remarkGfm from &quot;remark-gfm&quot;;
import { getAllPosts, getPostBySlug } from &quot;@/lib/posts&quot;;
import { mdxComponents } from &quot;@/mdx-components&quot;;
import ErrorComponent from &quot;@/components/error-component&quot;;

interface BlogPostPageProps {
  params: Promise&amp;lt;{ slug: string }&amp;gt;;
}

// Pre-renders every post at build time (Static Site Generation)
export async function generateStaticParams() {
  const posts = getAllPosts();
  return posts.map((post) =&amp;gt; ({ slug: post.slug }));
}

export async function generateMetadata({ params }: BlogPostPageProps) {
  const { slug } = await params;
  const post = getPostBySlug(slug);

  if (!post) return {};

  return {
    title: post.title,
    description: post.description,
  };
}

const mdxOptions: MDXRemoteOptions = {
  mdxOptions: {
    remarkPlugins: [remarkGfm],
  },
};

export default async function BlogPostPage({ params }: BlogPostPageProps) {
  const { slug } = await params;
  const post = getPostBySlug(slug);

  if (!post) {
    notFound();
  }

  return (
    &amp;lt;article className=&quot;prose dark:prose-invert mx-auto&quot;&amp;gt;
      &amp;lt;h1&amp;gt;{post.title}&amp;lt;/h1&amp;gt;

      &amp;lt;Suspense fallback={&amp;lt;p&amp;gt;Loading post…&amp;lt;/p&amp;gt;}&amp;gt;
        &amp;lt;MDXRemote
          source={post.content}
          components={mdxComponents}
          options={mdxOptions}
          onError={ErrorComponent}
        /&amp;gt;
      &amp;lt;/Suspense&amp;gt;
    &amp;lt;/article&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Create Error component&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;// components/error-component.tsx

'use client'

export default function ErrorComponent({ error }: { error: unknown | Error }) {
    return (
        &amp;lt;div className=&quot;rounded-xl border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive&quot;&amp;gt;
            &amp;lt;pre&amp;gt;
                &amp;lt;code&amp;gt;
                    {typeof error === &quot;string&quot;
                        ? error
                        : error instanceof Error
                            ? error.message
                            : String(error)}
                &amp;lt;/code&amp;gt;
            &amp;lt;/pre&amp;gt;
        &amp;lt;/div&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;What's actually new compared to &lt;code&gt;next-mdx-remote&lt;/code&gt;:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;import { MDXRemote } from &quot;next-mdx-remote-client/rsc&quot;&lt;/code&gt;&lt;/strong&gt; — the App Router entry point. Importing from the bare package name here would pull in the Pages Router code path instead, which won't work.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; is required, not optional.&lt;/strong&gt; &lt;code&gt;MDXRemote&lt;/code&gt; is an &lt;code&gt;async&lt;/code&gt; Server Component under the hood — it returns a &lt;code&gt;Promise&amp;lt;React.JSX.Element&amp;gt;&lt;/code&gt; — so it needs a Suspense boundary the same way any other async Server Component does.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;onError={ErrorComponent}&lt;/code&gt;&lt;/strong&gt; is the headline feature from &lt;a rel=&quot;nofollow&quot; href=&quot;#why-next-mdx-remote-client-instead-of-next-mdx-remote&quot;&gt;earlier&lt;/a&gt;. If this specific post's MDX fails to &lt;strong&gt;compile&lt;/strong&gt; — a syntax error like an unclosed tag, or a bad frontmatter parse — &lt;code&gt;MDXRemote&lt;/code&gt; catches it internally and renders &lt;code&gt;ErrorComponent&lt;/code&gt; in its place, instead of taking down the whole page.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;options.mdxOptions.remarkPlugins&lt;/code&gt;&lt;/strong&gt; still works exactly the way &lt;code&gt;next-mdx-remote&lt;/code&gt; did — &lt;code&gt;remark-gfm&lt;/code&gt; plugs in the same way for tables and GFM syntax.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;⚠️ &lt;strong&gt;Common Mistake:&lt;/strong&gt; Forgetting the &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; wrapper. Since &lt;code&gt;MDXRemote&lt;/code&gt; is async, rendering it directly without a Suspense boundary will throw a build error telling you an async component needs one — this is a hard requirement of the package, not a style suggestion.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;Tip:&lt;/strong&gt; Notice &lt;code&gt;onError&lt;/code&gt; catches compile/render errors caught by the package's internal handling, but the README is explicit that &lt;strong&gt;evaluating the compiled module itself doesn't throw except syntax errors&lt;/strong&gt; — some render-time errors from a broken custom component can still escape and need a real React &lt;code&gt;&amp;lt;ErrorBoundary&amp;gt;&lt;/code&gt; around your route if you want to be fully defensive. For a typical blog where you control every MDX file, &lt;code&gt;onError&lt;/code&gt; alone covers the realistic failure cases (a bad frontmatter reference, a malformed table, an unclosed tag).&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;If you want to deep dive into &lt;strong&gt;Error Handling in Next.js&lt;/strong&gt;, I've full guide covering this topic &lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/blog/error-handling-in-nextjs-16&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-6-want-frontmatter-and-scope-inside-jsx-use-evaluate-instead&quot;&gt;Step 6: Want Frontmatter and Scope Inside JSX? Use &lt;code&gt;evaluate&lt;/code&gt; Instead&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;MDXRemote&lt;/code&gt; component above is enough if you only need frontmatter and custom data &lt;em&gt;inside&lt;/em&gt; the MDX body (e.g. &lt;code&gt;# {frontmatter.title}&lt;/code&gt; written directly in the &lt;code&gt;.mdx&lt;/code&gt; file). If you need that data &lt;strong&gt;outside&lt;/strong&gt; the MDX, in your page's own JSX — for a byline, a reading-time badge, a table of contents component — reach for the lower-level &lt;code&gt;evaluate&lt;/code&gt; function instead.&lt;/p&gt;
&lt;p&gt;Update &lt;code&gt;lib/posts.ts&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;// lib/posts.ts
export const getSource = async (filename: string): Promise&amp;lt;string | undefined&amp;gt; =&amp;gt; {
    const sourcePath = path.join(POSTS_PATH, filename);
    if (!fs.existsSync(sourcePath)) return;
    return await fs.promises.readFile(sourcePath, &quot;utf8&quot;);
};
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;// app/blog/[slug]/page.tsx (alternative using evaluate)
import { Suspense } from &quot;react&quot;;
import { evaluate, type EvaluateOptions } from &quot;next-mdx-remote-client/rsc&quot;;
import remarkGfm from &quot;remark-gfm&quot;;
import { getSource } from &quot;@/lib/posts&quot;;
import { mdxComponents } from &quot;@/mdx-components&quot;;
import ErrorComponent from &quot;@/components/error-component&quot;;

interface BlogPostPageProps {
    params: Promise&amp;lt;{ slug: string }&amp;gt;;
}

type Frontmatter = {
  title: string;
  description: string;
};

const mdxOptions: MDXRemoteOptions = {
    parseFrontmatter: true,
    mdxOptions: {
        remarkPlugins: [remarkGfm],
    },
};

export default async function BlogPostPage({ params }: BlogPostPageProps) {
    const { slug } = await params;
    const source = await getSource(`${slug}.mdx`)!;

    if (!source) return &amp;lt;ErrorComponent error=&quot;The source could not found!&quot; /&amp;gt;;

  const { content, frontmatter, error } = await evaluate&amp;lt;Frontmatter&amp;gt;({
    source,
    options: mdxOptions,
    components: mdxComponents,
  });

    if (error) return &amp;lt;ErrorComponent error={error} /&amp;gt;;

  return (
    &amp;lt;article className=&quot;prose dark:prose-invert mx-auto&quot;&amp;gt;
      &amp;lt;h1&amp;gt;{frontmatter.title}&amp;lt;/h1&amp;gt;
            &amp;lt;Suspense fallback={&amp;lt;p&amp;gt;Loading post…&amp;lt;/p&amp;gt;}&amp;gt;
                {content}
            &amp;lt;/Suspense&amp;gt;
    &amp;lt;/article&amp;gt;
  );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;What's happening here:&lt;/strong&gt; &lt;code&gt;evaluate&lt;/code&gt; returns &lt;code&gt;{ content, mod, frontmatter, scope, error }&lt;/code&gt; all at once — &lt;code&gt;content&lt;/code&gt; is the compiled MDX JSX (still needs its own &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt;), &lt;code&gt;frontmatter&lt;/code&gt; is typed and available immediately for use in your surrounding JSX, and &lt;code&gt;error&lt;/code&gt; is a plain object you check yourself instead of a component prop. This is the tool to reach for whenever you need frontmatter or a table-of-contents object &lt;em&gt;before&lt;/em&gt; the MDX renders, not just inside it — the &lt;code&gt;MDXRemote&lt;/code&gt; component genuinely can't do this on the App Router, since it doesn't hand you the frontmatter as a return value at all.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;Tip:&lt;/strong&gt; Passing &lt;code&gt;parseFrontmatter: true&lt;/code&gt; here means &lt;code&gt;evaluate&lt;/code&gt; extracts frontmatter itself — you could skip &lt;code&gt;gray-matter&lt;/code&gt; entirely for a page that only needs a single post. This guide's &lt;code&gt;lib/posts.ts&lt;/code&gt; still uses &lt;code&gt;gray-matter&lt;/code&gt; separately because the blog &lt;strong&gt;index&lt;/strong&gt; page needs frontmatter for every post at once, without compiling every post's MDX just to list titles.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-7-add-json-ld-structured-data-optional-but-great-for-seo-&quot;&gt;Step 7: Add JSON-LD Structured Data (Optional, but Great for SEO)&lt;/h3&gt;
&lt;p&gt;Unchanged from the original setup — this is a Next.js &lt;code&gt;&amp;lt;Script&amp;gt;&lt;/code&gt; tag, not something the MDX package touches.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;// app/blog/[slug]/page.tsx (addition)
import Script from &quot;next/script&quot;;

&amp;lt;Script
  type=&quot;application/ld+json&quot;
  dangerouslySetInnerHTML={{
    __html: JSON.stringify({
      &quot;@context&quot;: &quot;https://schema.org&quot;,
      &quot;@type&quot;: &quot;BlogPosting&quot;,
      headline: post.title,
      description: post.description,
      datePublished: post.publishedAt,
      author: { &quot;@type&quot;: &quot;Person&quot;, name: &quot;Your Name&quot; },
    }),
  }}
/&amp;gt;;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-8-style-blog-content-with-tailwind-typography&quot;&gt;Step 8: Style Blog Content with Tailwind Typography&lt;/h3&gt;
&lt;p&gt;Also unchanged — MDX content renders as plain, unstyled HTML by default regardless of which remote-MDX package compiled it.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install @tailwindcss/typography
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;/* app/globals.css */
@import &quot;tailwindcss&quot;;

@plugin &quot;@tailwindcss/typography&quot;;

:root {
  --sh-class: #7aa2f7;
  --sh-sign: #89ddff;
  --sh-string: #9ece6a;
  --sh-keyword: #bb9af7;
  --sh-comment: #acacac;
  --sh-jsxliterals: #7aa2f7;
  --sh-property: #73daca;
  --sh-entity: #e0af68;
  --sh-identifier: #fff;
}

@layer base {
  code:not(pre code) {
    background-color: var(--color-gray-100);
  }

  code:not(pre code) span {
    font-weight: 600;
    color: black !important;
  }

  table {
    display: block;
    max-width: fit-content;
    overflow-x: auto;
    white-space: nowrap;
    text-align: left;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;migrating-an-existing-next-mdx-remote-setup-checklist&quot;&gt;Migrating an Existing next-mdx-remote Setup: Checklist&lt;/h3&gt;
&lt;p&gt;If you already have the original guide's setup running in production, here's the exact diff:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;[ ] &lt;code&gt;npm uninstall next-mdx-remote&lt;/code&gt; and &lt;code&gt;npm install next-mdx-remote-client@^2&lt;/code&gt; (or &lt;code&gt;@^1&lt;/code&gt; on React 18)&lt;/li&gt;
&lt;li&gt;[ ] Remove &lt;code&gt;transpilePackages: ['next-mdx-remote']&lt;/code&gt; from &lt;code&gt;next.config.mjs&lt;/code&gt; if present — it's not needed for &lt;code&gt;next-mdx-remote-client&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[ ] Change &lt;code&gt;import { MDXRemote } from &quot;next-mdx-remote/rsc&quot;&lt;/code&gt; to &lt;code&gt;import { MDXRemote } from &quot;next-mdx-remote-client/rsc&quot;&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;[ ] Change &lt;code&gt;options={{ mdxOptions: { remarkPlugins: [remarkGfm] } }}&lt;/code&gt; to a typed &lt;code&gt;MDXRemoteOptions&lt;/code&gt; object (optional, but gets you autocomplete)&lt;/li&gt;
&lt;li&gt;[ ] Add an &lt;code&gt;onError&lt;/code&gt; component and pass it as a prop — you're no longer required to hand-roll this yourself&lt;/li&gt;
&lt;li&gt;[ ] Confirm your route already wraps &lt;code&gt;&amp;lt;MDXRemote /&amp;gt;&lt;/code&gt; in &lt;code&gt;&amp;lt;Suspense&amp;gt;&lt;/code&gt; — &lt;code&gt;next-mdx-remote&lt;/code&gt;'s RSC component was also async, so this requirement doesn't actually change&lt;/li&gt;
&lt;li&gt;[ ] &lt;code&gt;mdx-components.tsx&lt;/code&gt;, &lt;code&gt;lib/posts.ts&lt;/code&gt;, your &lt;code&gt;.mdx&lt;/code&gt; content files, and your Tailwind Typography setup all need &lt;strong&gt;zero changes&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For most blogs, this is a genuinely small migration — the package was designed as a drop-in-shaped replacement, not a rewrite.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;frequently-asked-questions-1&quot;&gt;Frequently Asked Questions&lt;/h3&gt;
&lt;h4 id=&quot;is-next-mdx-remote-client-a-fork-or-a-completely-separate-project-&quot;&gt;Is next-mdx-remote-client a fork or a completely separate project?&lt;/h4&gt;
&lt;p&gt;It's a from-scratch package built independently in 2024, in the spirit of &lt;code&gt;@mdx-js/mdx&lt;/code&gt;, rather than a literal code fork — but it's positioned and documented as a direct alternative to &lt;code&gt;next-mdx-remote&lt;/code&gt;, with a published &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/ipikuka/next-mdx-remote-client/blob/main/migration_guide.md&quot;&gt;migration guide&lt;/a&gt; for exactly this switch.&lt;/p&gt;
&lt;h4 id=&quot;do-i-need-to-change-my-mdx-content-files-at-all-&quot;&gt;Do I need to change my .mdx content files at all?&lt;/h4&gt;
&lt;p&gt;No. &lt;code&gt;next-mdx-remote-client&lt;/code&gt; compiles the same MDX syntax, reads the same frontmatter format, and works with the same custom component map. The migration is entirely in your route and import statements, not your content.&lt;/p&gt;
&lt;h4 id=&quot;can-i-still-use-next-mdx-remote-utils-style-frontmatter-parsing-without-gray-matter-&quot;&gt;Can I still use next-mdx-remote/utils-style frontmatter parsing without gray-matter?&lt;/h4&gt;
&lt;p&gt;Yes — use &lt;code&gt;getFrontmatter&lt;/code&gt; from &lt;code&gt;next-mdx-remote-client/utils&lt;/code&gt;, shown in &lt;a rel=&quot;nofollow&quot; href=&quot;#step-3-build-the-data-layer&quot;&gt;Step 3&lt;/a&gt;. It's isolated in its own subpath specifically so it costs almost nothing to import, and the maintainer notes it works fine even if you're still on plain &lt;code&gt;next-mdx-remote&lt;/code&gt; elsewhere in your app.&lt;/p&gt;
&lt;h4 id=&quot;what-s-the-difference-between-mdxremote-and-evaluate-&quot;&gt;What's the difference between MDXRemote and evaluate?&lt;/h4&gt;
&lt;p&gt;&lt;code&gt;MDXRemote&lt;/code&gt; is the simpler option when you only need frontmatter and scope data &lt;em&gt;inside&lt;/em&gt; the MDX body itself. &lt;code&gt;evaluate&lt;/code&gt; is lower-level and returns &lt;code&gt;frontmatter&lt;/code&gt;, &lt;code&gt;scope&lt;/code&gt;, and exported &lt;code&gt;mod&lt;/code&gt; data directly to your page's JSX — reach for it when a byline, reading-time badge, or table-of-contents component outside the MDX needs that data. See &lt;a rel=&quot;nofollow&quot; href=&quot;#step-6-want-frontmatter-and-scope-inside-jsx-use-evaluate-instead&quot;&gt;Step 6&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id=&quot;page-router-faq&quot;&gt;Does this work with the Pages Router too?&lt;/h3&gt;
&lt;p&gt;Yes, but through a completely separate, isolated API — &lt;code&gt;serialize&lt;/code&gt; (server-side, in &lt;code&gt;getStaticProps&lt;/code&gt;), plus &lt;code&gt;hydrate&lt;/code&gt; and &lt;code&gt;MDXClient&lt;/code&gt; (client-side) — imported from &lt;code&gt;next-mdx-remote-client/serialize&lt;/code&gt; and &lt;code&gt;next-mdx-remote-client/csr&lt;/code&gt; rather than &lt;code&gt;/rsc&lt;/code&gt;. The App Router and Pages Router code paths don't share internals.&lt;/p&gt;
&lt;h4 id=&quot;is-next-mdx-remote-actually-broken-right-now-&quot;&gt;Is next-mdx-remote actually broken right now?&lt;/h4&gt;
&lt;p&gt;No — HashiCorp archived the repository, meaning it's read-only with no further commits, but the last published version (&lt;code&gt;6.0.0&lt;/code&gt;) still installs and runs normally today. Nothing forces an immediate migration. The reason to move is that any future Next.js, React, or &lt;code&gt;@mdx-js/mdx&lt;/code&gt; change that breaks compatibility will never get a fix from the original package.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;wrapping-up&quot;&gt;Wrapping Up&lt;/h3&gt;
&lt;p&gt;The move from &lt;code&gt;next-mdx-remote&lt;/code&gt; to &lt;code&gt;next-mdx-remote-client&lt;/code&gt; is a narrow, mechanical change for most blogs: swap the package, swap one import path, add an &lt;code&gt;onError&lt;/code&gt; handler, and everything else — your content folder, your data layer, your custom components, your Tailwind Typography setup — keeps working exactly as it did. What you get in exchange is a package that's still receiving updates, plus a real error boundary for MDX rendering that the original never shipped.&lt;/p&gt;
&lt;p&gt;If you're starting a brand-new Next.js 16 blog today rather than migrating one, just start here directly — there's no reason to build on the archived package first.&lt;/p&gt;
&lt;h3 id=&quot;useful-resources&quot;&gt;Useful Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/ipikuka/next-mdx-remote-client&quot;&gt;next-mdx-remote-client GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/ipikuka/next-mdx-remote-client/blob/main/migration_guide.md&quot;&gt;next-mdx-remote-client Migration Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/remarkjs/remark-gfm&quot;&gt;remark-gfm Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/tailwindlabs/tailwindcss-typography&quot;&gt;Tailwind Typography Plugin Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;continue-learning&quot;&gt;Continue Learning&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/blog/mdx-remote-nextjs-16-guide&quot;&gt;Complete MDX Blog Setup with next-mdx-remote and Next.js 16 (original guide)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/blog/nextjs-16-routing-guide&quot;&gt;Next.js 16 Routing Explained: A Complete Beginner's Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/blog/server-vs-client-components-nextjs-16&quot;&gt;Server vs Client Components in Next.js 16&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/blog/technical-seo-checklist&quot;&gt;The Complete Technical SEO Checklist for Next.js Developers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;free-developer-tools&quot;&gt;Free Developer Tools&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/tools/meta-tag-generator&quot;&gt;Meta Tag Generator for Next.js &amp;amp; HTML&lt;/a&gt; — generate SEO meta tags, Open Graph tags, Twitter Cards, and JSON-LD instantly for each post.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/tools/json-ld-generator&quot;&gt;JSON-LD Generator for Next.js &amp;amp; HTML&lt;/a&gt; — generate BlogPosting structured data checked live against Google's Rich Results requirements.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📦 &lt;strong&gt;Source Code:&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/Muhammad-Ali-sma/next-mdx-remote-client-nextjs-16-setup&quot;&gt;View on GitHub&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/25579/next-mdx-remote-client-guide-for-next-js-16-2026</guid>
<pubDate>Fri, 28 Aug 2026 03:40:16 +0000</pubDate>
</item>
<item>
<title>Complete MDX Blog Setup with next-mdx-remote and Next.js 16 (2026 Beginner Guide)</title>
<link>https://coderlegion.com/23799/complete-mdx-blog-setup-with-next-mdx-remote-and-next-js-16-2026-beginner-guide</link>
<description>&lt;p&gt;If you've ever tried writing blog posts in plain Markdown inside a Next.js app, you've probably hit a wall pretty fast. Plain Markdown can't render React components, can't handle custom styled code blocks, and definitely can't drop in an interactive widget in the middle of a paragraph.&lt;/p&gt;
&lt;p&gt;That's exactly the gap MDX fills — and &lt;code&gt;next-mdx-remote&lt;/code&gt; is the easiest way to load MDX content that lives outside your &lt;code&gt;app&lt;/code&gt; folder (like a &lt;code&gt;content/blogs&lt;/code&gt; directory) and render it as real React.&lt;/p&gt;
&lt;p&gt;In this guide, you'll build a complete, production-ready blog setup using &lt;code&gt;next-mdx-remote&lt;/code&gt; in Next.js 16 — the same setup powering this very blog. By the end, you'll have:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;MDX files stored in a &lt;code&gt;content/blogs&lt;/code&gt; folder&lt;/li&gt;
&lt;li&gt;A reusable &lt;code&gt;getAllPosts()&lt;/code&gt; / &lt;code&gt;getPostBySlug()&lt;/code&gt; data layer&lt;/li&gt;
&lt;li&gt;Custom-styled MDX components (headings, code blocks, links, tables)&lt;/li&gt;
&lt;li&gt;Syntax highlighting with &lt;code&gt;sugar-high&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;remark-gfm&lt;/code&gt; for GitHub-flavored Markdown (tables, strikethrough, task lists)&lt;/li&gt;
&lt;li&gt;Dynamic SEO metadata and JSON-LD structured data per post&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;why-mdxremote-instead-of-next-mdx-&quot;&gt;Why MDXRemote Instead of @next/mdx?&lt;/h3&gt;
&lt;p&gt;Next.js offers two different ways to work with MDX, and beginners often mix them up.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;@next/mdx&lt;/code&gt;&lt;/strong&gt; treats &lt;code&gt;.mdx&lt;/code&gt; files as actual pages/routes. You'd create a file like &lt;code&gt;app/blog/my-post/page.mdx&lt;/code&gt; and Next.js compiles it into a route at build time. This works, but it means every blog post is a route file living inside &lt;code&gt;app/&lt;/code&gt; — awkward if you want a &lt;code&gt;content/&lt;/code&gt; folder, dynamic &lt;code&gt;[slug]&lt;/code&gt; routes, or to pull posts from a CMS/database later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&lt;code&gt;next-mdx-remote&lt;/code&gt;&lt;/strong&gt; lets you store MDX content &lt;em&gt;anywhere&lt;/em&gt; — a &lt;code&gt;content/blogs&lt;/code&gt; folder, a database, a CMS — and render it through a single dynamic route like &lt;code&gt;app/blog/[slug]/page.tsx&lt;/code&gt;. You read the raw MDX string yourself (usually with the filesystem), then hand it to the &lt;code&gt;&amp;lt;MDXRemote /&amp;gt;&lt;/code&gt; component to compile and render.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;Tip:&lt;/strong&gt; If you want a handful of static pages (like a docs page), &lt;code&gt;@next/mdx&lt;/code&gt; is simpler. If you're building a blog with many posts and dynamic routing, &lt;code&gt;next-mdx-remote&lt;/code&gt; is the better fit — it's what we'll use here.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;what-we-re-building&quot;&gt;What We're Building&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;content/
  blogs/
    hello-world.mdx
    another-post.mdx

lib/
  posts.ts        → reads MDX files, parses frontmatter, sorts posts

app/
  blog/
    [slug]/
      page.tsx              → dynamic route rendering MDXRemote
      opengraph-image.tsx    → auto-generated OG image per post

mdx-components.tsx  → custom styled components used inside MDX
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Prerequisites: Next.js 16 (App Router), TypeScript in strict mode, and Tailwind CSS for styling. If your project doesn't already have these, scaffold one with &lt;code&gt;npx create-next-app@latest&lt;/code&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;Step 1: Install Dependencies&lt;/h3&gt;
&lt;p&gt;Run the following command to install everything this setup needs:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install next-mdx-remote gray-matter remark-gfm reading-time sugar-high
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Here's what each package actually does:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Package &lt;/th&gt;&lt;th&gt;Purpose&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;next-mdx-remote&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Compiles and renders MDX strings as React on the server&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;gray-matter&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Parses frontmatter (the &lt;code&gt;---&lt;/code&gt; block at the top of your &lt;code&gt;.mdx&lt;/code&gt; files)&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;remark-gfm&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Adds GitHub-flavored Markdown — tables, strikethrough, task lists&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;reading-time&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Calculates estimated reading time from post content&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;&lt;code&gt;sugar-high&lt;/code&gt; &lt;/td&gt;&lt;td&gt;Lightweight syntax highlighter for code blocks (no client JS needed)&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;blockquote&gt;&lt;p&gt;⚠️ &lt;strong&gt;Common Mistake:&lt;/strong&gt; Don't confuse &lt;code&gt;next-mdx-remote&lt;/code&gt; with &lt;code&gt;next-mdx-remote/rsc&lt;/code&gt;. The base package is for the Pages Router / client components. For the App Router with Server Components (which is what we want in Next.js 16), you import from &lt;code&gt;next-mdx-remote/rsc&lt;/code&gt; instead. We'll use that import throughout this guide.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-2-configure-next-config-mjs-optional-&quot;&gt;Step 2: Configure next.config.mjs (Optional)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-js&quot;&gt;// next.config.mjs

/** @type {import('next').NextConfig} */
const nextConfig = {
    pageExtensions: ['js', 'jsx', 'md', 'mdx', 'ts', 'tsx'],
    transpilePackages: ['next-mdx-remote'],
}

export default nextConfig
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;What's happening here:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;pageExtensions&lt;/code&gt; tells Next.js that &lt;code&gt;.md&lt;/code&gt; and &lt;code&gt;.mdx&lt;/code&gt; files can also be treated as pages, alongside the usual &lt;code&gt;.ts&lt;/code&gt;/&lt;code&gt;.tsx&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;transpilePackages: ['next-mdx-remote']&lt;/code&gt; makes sure Next.js properly transpiles the package rather than trying to treat it as pre-built.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-3-create-the-content-folder&quot;&gt;Step 3: Create the Content Folder&lt;/h3&gt;
&lt;p&gt;This is where your actual blog posts will live as plain &lt;code&gt;.mdx&lt;/code&gt; files.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;content/blogs/hello-world.mdx
&lt;/code&gt;&lt;/pre&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;---
title: &quot;Hello World: My First MDX Post&quot;
description: &quot;A short example post to test out the MDXRemote setup in Next.js 16.&quot;
publishedAt: &quot;2026-07-01&quot;
tags: [&quot;MDX&quot;, &quot;Next.js&quot;]
featured: false
---

## Hello World

This is my **first** MDX post rendered with `next-mdx-remote`.

- It supports Markdown
- It supports *React components*
- It even supports tables (thanks to remark-gfm)

| Feature            | Supported |
| ------------------ | --------- |
| Tables             | ✅       |
| Code blocks        | ✅       |
| Custom components  | ✅       |

const greeting: string = &quot;Hello from MDX!&quot;;
console.log(greeting);
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Understanding the frontmatter block:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The section between the &lt;code&gt;---&lt;/code&gt; lines at the top is called &lt;em&gt;frontmatter&lt;/em&gt;. It's plain YAML metadata that describes the post — title, description, publish date, tags — without being part of the rendered content itself. &lt;code&gt;gray-matter&lt;/code&gt; (installed earlier) is the library that separates this metadata from the actual MDX body.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;⚠️ &lt;strong&gt;Common Mistake:&lt;/strong&gt; Keep your frontmatter field names consistent across every post (&lt;code&gt;title&lt;/code&gt;, &lt;code&gt;description&lt;/code&gt;, &lt;code&gt;publishedAt&lt;/code&gt;, &lt;code&gt;tags&lt;/code&gt;, &lt;code&gt;featured&lt;/code&gt;). If one file has &lt;code&gt;date&lt;/code&gt; and another has &lt;code&gt;publishedAt&lt;/code&gt;, your sorting and metadata logic will silently break for that post.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-4-build-the-data-layer-lib-posts-ts-&quot;&gt;Step 4: Build the Data Layer (lib/posts.ts)&lt;/h3&gt;
&lt;p&gt;This file is the heart of the whole setup — it reads every &lt;code&gt;.mdx&lt;/code&gt; file from disk, parses the frontmatter, and returns clean, typed post objects your pages can use.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ts&quot;&gt;// lib/posts.ts
import fs from &quot;fs&quot;;
import path from &quot;path&quot;;
import matter from &quot;gray-matter&quot;;
import readingTime from &quot;reading-time&quot;;

const POSTS_PATH = path.join(process.cwd(), &quot;content/blogs&quot;);

export type Post = {
  slug: string;
  title: string;
  description: string;
  publishedAt: string;
  updatedAt?: string;
  tags: string[];
  coverImage?: string;
  readingTime: string;
  content: string;
};

export function getAllPosts(): Post[] {
  const files = fs.readdirSync(POSTS_PATH);

  const posts = files.map((file) =&amp;gt; {
    const filePath = path.join(POSTS_PATH, file);
    const fileContent = fs.readFileSync(filePath, &quot;utf-8&quot;);

    const { data, content } = matter(fileContent);

    const slug = file.replace(/\.mdx$/, &quot;&quot;);

    return {
      slug,
      title: data.title,
      description: data.description,
      publishedAt: data.publishedAt,
      tags: data.tags || [],
      coverImage: data.coverImage || &quot;&quot;,
      readingTime: readingTime(content).text,
      content,
    };
  });

  return posts.sort(
    (a, b) =&amp;gt;
      new Date(b.publishedAt).getTime() -
      new Date(a.publishedAt).getTime()
  );
}

export function getPostBySlug(slug: string) {
  return getAllPosts().find((post) =&amp;gt; post.slug === slug);
}

export function extractFirstImage(content: string) {
  const regex = /!\[.*?\]\((.*?)\)/;
  const match = content.match(regex);
  return match?.[1] || null;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Breaking this down line by line:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;fs.readdirSync(POSTS_PATH)&lt;/code&gt; reads the filenames of every &lt;code&gt;.mdx&lt;/code&gt; file inside &lt;code&gt;content/blogs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;matter(fileContent)&lt;/code&gt; splits each file into &lt;code&gt;data&lt;/code&gt; (the frontmatter object) and &lt;code&gt;content&lt;/code&gt; (the raw MDX body below the frontmatter).&lt;/li&gt;
&lt;li&gt;&lt;code&gt;slug&lt;/code&gt; is derived directly from the filename — &lt;code&gt;hello-world.mdx&lt;/code&gt; becomes the slug &lt;code&gt;hello-world&lt;/code&gt;, which later becomes the URL &lt;code&gt;/blog/hello-world&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;readingTime(content).text&lt;/code&gt; automatically calculates something like &lt;code&gt;&quot;3 min read&quot;&lt;/code&gt; based on word count — no manual math needed.&lt;/li&gt;
&lt;li&gt;Posts are sorted newest-first by comparing &lt;code&gt;publishedAt&lt;/code&gt; dates.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;extractFirstImage()&lt;/code&gt; is a small helper that scans the Markdown content for the first &lt;code&gt;![alt](url)&lt;/code&gt; image — handy for auto-generating Open Graph preview images later.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;Tip:&lt;/strong&gt; Because this uses &lt;code&gt;fs&lt;/code&gt; (Node's filesystem module), it can only run on the server — inside Server Components, &lt;code&gt;generateStaticParams&lt;/code&gt;, or &lt;code&gt;generateMetadata&lt;/code&gt;. Never import &lt;code&gt;lib/posts.ts&lt;/code&gt; into a &lt;code&gt;&quot;use client&quot;&lt;/code&gt; component.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-5-create-custom-mdx-components&quot;&gt;Step 5: Create Custom MDX Components&lt;/h3&gt;
&lt;p&gt;By default, MDX renders plain, unstyled HTML tags (&lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;p&amp;gt;&lt;/code&gt;, &lt;code&gt;&amp;lt;code&amp;gt;&lt;/code&gt;, etc). To make your blog actually look good, you override these tags with your own styled versions.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;// mdx-components.tsx
import React, { ComponentPropsWithoutRef } from 'react';
import Link from 'next/link';
import { highlight } from 'sugar-high';

type HeadingProps = ComponentPropsWithoutRef&amp;lt;'h1'&amp;gt;;
type ParagraphProps = ComponentPropsWithoutRef&amp;lt;'p'&amp;gt;;
type ListProps = ComponentPropsWithoutRef&amp;lt;'ul'&amp;gt;;
type ListItemProps = ComponentPropsWithoutRef&amp;lt;'li'&amp;gt;;
type AnchorProps = ComponentPropsWithoutRef&amp;lt;'a'&amp;gt;;
type BlockquoteProps = ComponentPropsWithoutRef&amp;lt;'blockquote'&amp;gt;;

const components = {
    h1: (props: HeadingProps) =&amp;gt; (
        &amp;lt;h1 className=&quot;scroll-m-20 text-4xl font-bold tracking-tight lg:text-5xl&quot; {...props} /&amp;gt;
    ),
    h2: (props: HeadingProps) =&amp;gt; (
        &amp;lt;h2 className=&quot;scroll-m-20 mt-16 pb-2 text-3xl font-semibold tracking-tight&quot; {...props} /&amp;gt;
    ),
    h3: (props: HeadingProps) =&amp;gt; (
        &amp;lt;h3 className=&quot;scroll-m-20 mt-12 text-2xl font-semibold tracking-tight&quot; {...props} /&amp;gt;
    ),
    p: (props: ParagraphProps) =&amp;gt; (
        &amp;lt;p className=&quot;text-gray-800 dark:text-zinc-300&quot; {...props} /&amp;gt;
    ),
    ul: (props: ListProps) =&amp;gt; (
        &amp;lt;ul className=&quot;text-gray-800 dark:text-zinc-300 list-disc pl-5 space-y-1&quot; {...props} /&amp;gt;
    ),
    li: (props: ListItemProps) =&amp;gt; &amp;lt;li className=&quot;pl-1&quot; {...props} /&amp;gt;,
    a: ({ href, children, ...props }: AnchorProps) =&amp;gt; {
        const className = 'text-blue-500 hover:text-blue-700';

        // Internal links use Next.js's Link for client-side navigation
        if (href?.startsWith('/')) {
            return &amp;lt;Link href={href} className={className} {...props}&amp;gt;{children}&amp;lt;/Link&amp;gt;;
        }

        // External links open in a new tab
        return (
            &amp;lt;a href={href} target=&quot;_blank&quot; rel=&quot;noopener noreferrer&quot; className={className} {...props}&amp;gt;
                {children}
            &amp;lt;/a&amp;gt;
        );
    },
    code: ({ children, ...props }: ComponentPropsWithoutRef&amp;lt;'code'&amp;gt;) =&amp;gt; {
        const codeHTML = highlight(String(children));
        return &amp;lt;code dangerouslySetInnerHTML={{ __html: codeHTML }} {...props} /&amp;gt;;
    },
    blockquote: (props: BlockquoteProps) =&amp;gt; (
        &amp;lt;blockquote className=&quot;ml-[0.075em] border-l-3 border-green-400 pl-4 text-gray-700&quot; {...props} /&amp;gt;
    ),
    em: (props: ComponentPropsWithoutRef&amp;lt;'em'&amp;gt;) =&amp;gt; (
        &amp;lt;em className=&quot;font-medium&quot; {...props} /&amp;gt;
    ),
};

declare global {
    type MDXProvidedComponents = typeof components;
}

export { components };
export function useMDXComponents(): MDXProvidedComponents {
    return components;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;What's happening here:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Every key in the &lt;code&gt;components&lt;/code&gt; object (&lt;code&gt;h1&lt;/code&gt;, &lt;code&gt;p&lt;/code&gt;, &lt;code&gt;code&lt;/code&gt;, etc.) maps directly to that HTML tag name inside your MDX files. Write &lt;code&gt;# My Heading&lt;/code&gt; in MDX, and it renders through your custom &lt;code&gt;h1&lt;/code&gt; component automatically.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;code&lt;/code&gt; component is the interesting one — instead of plain unstyled text, it runs the code through &lt;code&gt;sugar-high&lt;/code&gt;'s &lt;code&gt;highlight()&lt;/code&gt; function, which returns syntax-highlighted HTML. This gives you colored code blocks with &lt;strong&gt;zero client-side JavaScript&lt;/strong&gt;, since &lt;code&gt;sugar-high&lt;/code&gt; runs entirely at render time on the server.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;a&lt;/code&gt; component checks whether a link is internal (starts with &lt;code&gt;/&lt;/code&gt;) or external. Internal links use Next.js's &lt;code&gt;&amp;lt;Link&amp;gt;&lt;/code&gt; for fast client-side navigation; external links get &lt;code&gt;target=&quot;_blank&quot;&lt;/code&gt; so readers don't lose your site.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;⚠️ &lt;strong&gt;Common Mistake:&lt;/strong&gt; Forgetting to style the &lt;code&gt;code&lt;/code&gt; component is the #1 reason MDX blogs look broken — code blocks renders with no formatting. Always wire up a syntax highlighter here.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-6-build-the-dynamic-blog-route&quot;&gt;Step 6: Build the Dynamic Blog Route&lt;/h3&gt;
&lt;p&gt;This is where everything comes together — reading the post, compiling the MDX, and rendering it.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;// app/blog/[slug]/page.tsx
import { notFound } from &quot;next/navigation&quot;;
import { MDXRemote } from &quot;next-mdx-remote/rsc&quot;;
import remarkGfm from &quot;remark-gfm&quot;;
import { getAllPosts, getPostBySlug } from &quot;@/lib/posts&quot;;
import { components } from &quot;@/mdx-components&quot;;

interface BlogPostPageProps {
    params: Promise&amp;lt;{ slug: string }&amp;gt;;
}

// Pre-renders every post at build time (Static Site Generation)
export async function generateStaticParams() {
    const posts = getAllPosts();
    return posts.map((post) =&amp;gt; ({ slug: post.slug }));
}

export async function generateMetadata({ params }: BlogPostPageProps) {
    const { slug } = await params;
    const post = getPostBySlug(slug);

    if (!post) return {};

    return {
        title: post.title,
        description: post.description,
    };
}

export default async function BlogPostPage({ params }: BlogPostPageProps) {
    const { slug } = await params;
    const post = getPostBySlug(slug);

    if (!post) {
        notFound();
    }

    return (
        &amp;lt;article className=&quot;prose dark:prose-invert mx-auto&quot;&amp;gt;
            &amp;lt;h1&amp;gt;{post.title}&amp;lt;/h1&amp;gt;

            &amp;lt;MDXRemote
                source={post.content}
                components={components}
                options={{
                    mdxOptions: {
                        remarkPlugins: [remarkGfm],
                    },
                }}
            /&amp;gt;
        &amp;lt;/article&amp;gt;
    );
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Understanding each piece:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;generateStaticParams()&lt;/code&gt;&lt;/strong&gt; tells Next.js every possible &lt;code&gt;slug&lt;/code&gt; value ahead of time, so it can statically generate every blog post page at build time instead of rendering it on every request. This is what makes MDX blogs built this way extremely fast.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;generateMetadata()&lt;/code&gt;&lt;/strong&gt; dynamically sets the &lt;code&gt;&amp;lt;title&amp;gt;&lt;/code&gt; and meta description per post — critical for SEO, since every post needs its own unique tags rather than a single site-wide default.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;notFound()&lt;/code&gt;&lt;/strong&gt; triggers Next.js's built-in 404 page if someone visits a slug that doesn't exist in &lt;code&gt;content/blogs&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;&amp;lt;MDXRemote source={...} /&amp;gt;&lt;/code&gt;&lt;/strong&gt; is doing the real work: it takes the raw MDX string (&lt;code&gt;post.content&lt;/code&gt;), compiles it into React on the server, and renders it — swapping in your custom &lt;code&gt;components&lt;/code&gt; along the way.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;remarkPlugins: [remarkGfm]&lt;/code&gt;&lt;/strong&gt; enables GitHub-flavored Markdown syntax &lt;em&gt;inside this specific render call&lt;/em&gt; — tables, &lt;code&gt;~~strikethrough~~&lt;/code&gt;, and &lt;code&gt;- [ ] task lists&lt;/code&gt; all now work in your MDX files.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote&gt;&lt;p&gt;💡 &lt;strong&gt;Tip:&lt;/strong&gt; &lt;code&gt;MDXRemote&lt;/code&gt; from &lt;code&gt;next-mdx-remote/rsc&lt;/code&gt; is an &lt;strong&gt;async Server Component&lt;/strong&gt;. It streams and renders entirely on the server — no MDX compiler code ever ships to the browser, which keeps your client bundle small.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-7-add-json-ld-structured-data-optional-but-great-for-seo--1&quot;&gt;Step 7: Add JSON-LD Structured Data (Optional, but Great for SEO)&lt;/h3&gt;
&lt;p&gt;To help Google understand each post is a blog article (and potentially show rich snippets), add structured data using Next.js's &lt;code&gt;&amp;lt;Script&amp;gt;&lt;/code&gt; component.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;// app/blog/[slug]/page.tsx (addition)
import Script from &quot;next/script&quot;;

&amp;lt;&amp;gt;
&amp;lt;article&amp;gt;
rest of the code
&amp;lt;/article&amp;gt;
&amp;lt;Script
    type=&quot;application/ld+json&quot;
    dangerouslySetInnerHTML={{
        __html: JSON.stringify({
            &quot;@context&quot;: &quot;https://schema.org&quot;,
            &quot;@type&quot;: &quot;BlogPosting&quot;,
            headline: post.title,
            description: post.description,
            datePublished: post.publishedAt,
            author: { &quot;@type&quot;: &quot;Person&quot;, name: &quot;Your Name&quot; },
        }),
    }}
/&amp;gt;
&amp;lt;/&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This injects a &lt;code&gt;&amp;lt;script type=&quot;application/ld+json&quot;&amp;gt;&lt;/code&gt; tag containing structured metadata search engines can parse directly — no visible UI change, just better SEO.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;step-8-update-global-css&quot;&gt;Step 8: Update &lt;code&gt;global.css&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;Blog content renders as plain HTML elements with no default styling, so headings, paragraphs, and lists will look unstyled out of the box. The Tailwind Typography plugin fixes this in one line.&lt;/p&gt;
&lt;p&gt;Install it:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm install @tailwindcss/typography
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add the plugin to your global CSS:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-css&quot;&gt;/* app/globals.css */
@import &quot;tailwindcss&quot;;

@plugin &quot;@tailwindcss/typography&quot;;

:root{
  /* your other styles */

  /* add code blocks styling */
  --sh-class: #7aa2f7;
  --sh-sign: #89ddff;
  --sh-string: #9ece6a;
  --sh-keyword: #bb9af7;
  --sh-comment: #acacac;
  --sh-jsxliterals: #7aa2f7;
  --sh-property: #73daca;
  --sh-entity: #e0af68;
  --sh-identifier: #fff;
}

@layer base {
  * {
    @apply border-border outline-ring/50;
  }

  body {
    @apply bg-background text-foreground;
  }

  button:not(:disabled),
  [role=&quot;button&quot;]:not(:disabled) {
    cursor: pointer;
  }

  pre::-webkit-scrollbar {
    display: none;
  }

  code:not(pre code) {
    background-color: var(--color-gray-100);
  }

  code:not(pre code) span {
    font-weight: 600;
    color: black !important;
  }

  hr {
    color: var(--color-gray-200);
  }

  /* Remove Safari input shadow on mobile */
  input[type='text'],
  input[type='email'] {
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
  }

  table {
    display: block;
    max-width: fit-content;
    overflow-x: auto;
    white-space: nowrap;
    text-align: left;
  }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;testing-your-setup&quot;&gt;Testing Your Setup&lt;/h3&gt;
&lt;p&gt;Start your dev server:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;npm run dev
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then visit:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-txt&quot;&gt;http://localhost:3000/blog/hello-world
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;You should see your MDX post fully rendered with styled headings, a working table, and a syntax-highlighted code block.&lt;/p&gt;
&lt;blockquote&gt;&lt;p&gt;⚠️ &lt;strong&gt;Common Mistake:&lt;/strong&gt; If you get a &quot;module not found: fs&quot; error, you've likely imported &lt;code&gt;lib/posts.ts&lt;/code&gt; inside a Client Component (&lt;code&gt;&quot;use client&quot;&lt;/code&gt;). The &lt;code&gt;fs&lt;/code&gt; module only works on the server — remove the client directive or move the data fetching to a Server Component / route handler.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h3 id=&quot;bonus-dynamic-open-graph-images&quot;&gt;Bonus: Dynamic Open Graph Images&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-tsx&quot;&gt;// app/blog/[slug]/opengraph-image.tsx
import { ImageResponse } from 'next/og';

export const runtime = 'edge'; // Use Edge Runtime for faster generation
export const alt = 'Blog Post Preview';
export const size = { width: 1200, height: 630 };
export const contentType = 'image/png';

export default async function Image({ params }: { params: Promise&amp;lt;{ slug: string; }&amp;gt; }) {
    const title = (await params).slug.replace(/-/g, ' ');
    
    return new ImageResponse(
        (
            &amp;lt;div
                style={{
                    height: &quot;100%&quot;,
                    width: &quot;100%&quot;,
                    display: &quot;flex&quot;,
                    flexDirection: &quot;column&quot;,
                    justifyContent: &quot;space-between&quot;,
                    backgroundColor: &quot;#fff&quot;,
                    padding: &quot;60px&quot;,
                }}
            &amp;gt;

                &amp;lt;div
                    style={{
                        fontSize: 44,
                        display: 'flex',
                        alignItems: 'center',
                        fontWeight: 'bold',
                        gap: '15px'
                    }}
                &amp;gt;
                    &amp;lt;svg xmlns=&quot;http://www.w3.org/2000/svg&quot; width=&quot;64&quot; height=&quot;64&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;green&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&amp;gt;&amp;lt;path d=&quot;M12.83 2.18a2 2 0 0 0-1.66 0L2.6 6.08a1 1 0 0 0 0 1.83l8.58 3.91a2 2 0 0 0 1.66 0l8.58-3.9a1 1 0 0 0 0-1.83z&quot; /&amp;gt;&amp;lt;path d=&quot;M2 12a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 12&quot; /&amp;gt;&amp;lt;path d=&quot;M2 17a1 1 0 0 0 .58.91l8.6 3.91a2 2 0 0 0 1.65 0l8.58-3.9A1 1 0 0 0 22 17&quot; /&amp;gt;&amp;lt;/svg&amp;gt;
                    &amp;lt;span&amp;gt;Website Name&amp;lt;/span&amp;gt;
                &amp;lt;/div&amp;gt;

                &amp;lt;div
                    style={{
                        fontSize: 64,
                        fontWeight: 700,
                        lineHeight: 1.1,
                        maxWidth: 900,
                        textTransform: 'capitalize'
                    }}
                &amp;gt;
                    {title}
                &amp;lt;/div&amp;gt;

                &amp;lt;div
                    style={{
                        fontSize: 28,
                        opacity: 0.7,
                    }}
                &amp;gt;
                    example.com
                &amp;lt;/div&amp;gt;
            &amp;lt;/div&amp;gt;
        ),
        { ...size }
    );
}

&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h3 id=&quot;frequently-asked-questions-2&quot;&gt;Frequently Asked Questions&lt;/h3&gt;
&lt;h4 id=&quot;can-i-use-next-mdx-remote-with-the-pages-router-&quot;&gt;Can I use next-mdx-remote with the Pages Router?&lt;/h4&gt;
&lt;p&gt;Yes, but you'd import from &lt;code&gt;next-mdx-remote&lt;/code&gt; (not the &lt;code&gt;/rsc&lt;/code&gt; subpath) and use &lt;code&gt;getStaticProps&lt;/code&gt;/&lt;code&gt;getStaticPaths&lt;/code&gt; instead of &lt;code&gt;generateStaticParams&lt;/code&gt;. The &lt;code&gt;/rsc&lt;/code&gt; version shown in this guide is built specifically for the App Router's Server Components.&lt;/p&gt;
&lt;h4 id=&quot;do-i-need-next-mdx-if-i-m-already-using-mdxremote-&quot;&gt;Do I need @next/mdx if I'm already using MDXRemote?&lt;/h4&gt;
&lt;p&gt;Not strictly — &lt;code&gt;MDXRemote&lt;/code&gt; compiles MDX at runtime regardless of your &lt;code&gt;next.config.mjs&lt;/code&gt; setup. But registering &lt;code&gt;.mdx&lt;/code&gt; as a page extension avoids editor/tooling quirks and keeps the door open if you ever want static &lt;code&gt;.mdx&lt;/code&gt; route files too.&lt;/p&gt;
&lt;h4 id=&quot;how-do-i-add-images-inside-my-mdx-posts-&quot;&gt;How do I add images inside my MDX posts?&lt;/h4&gt;
&lt;p&gt;Just use standard Markdown image syntax: &lt;code&gt;![alt text](/path/to/image.png)&lt;/code&gt;. If you want Next.js's optimized &lt;code&gt;&amp;lt;Image&amp;gt;&lt;/code&gt; component instead, add an &lt;code&gt;img&lt;/code&gt; key to your &lt;code&gt;components&lt;/code&gt; object in &lt;code&gt;mdx-components.tsx&lt;/code&gt; that renders &lt;code&gt;next/image&lt;/code&gt; under the hood.&lt;/p&gt;
&lt;h4 id=&quot;why-is-my-code-block-not-syntax-highlighted-&quot;&gt;Why is my code block not syntax highlighted?&lt;/h4&gt;
&lt;p&gt;Double-check that your &lt;code&gt;code&lt;/code&gt; component in &lt;code&gt;mdx-components.tsx&lt;/code&gt; is running the content through &lt;code&gt;sugar-high&lt;/code&gt;'s &lt;code&gt;highlight()&lt;/code&gt; function. If you copy-pasted code but forgot this override, code blocks fall back to plain unstyled text.&lt;/p&gt;
&lt;h4 id=&quot;can-i-fetch-mdx-content-from-a-cms-instead-of-the-filesystem-&quot;&gt;Can I fetch MDX content from a CMS instead of the filesystem?&lt;/h4&gt;
&lt;p&gt;Yes — that's actually one of the biggest advantages of &lt;code&gt;next-mdx-remote&lt;/code&gt; over &lt;code&gt;@next/mdx&lt;/code&gt;. Since &lt;code&gt;MDXRemote&lt;/code&gt; just needs a raw MDX string, you can fetch that string from Contentful, Sanity, a database, or anywhere else instead of &lt;code&gt;fs.readFileSync&lt;/code&gt;. The rest of the setup stays identical.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id=&quot;wrapping-up-1&quot;&gt;Wrapping Up&lt;/h3&gt;
&lt;p&gt;You now have a complete, production-ready MDX blog setup running on Next.js 16 — MDX files stored cleanly in &lt;code&gt;content/blogs&lt;/code&gt;, a typed data layer for reading and sorting posts, custom-styled components, GitHub-flavored Markdown support, and per-post SEO metadata.&lt;/p&gt;
&lt;p&gt;From here, natural next steps include adding tag-based filtering, a search feature, or auto-generated Open Graph images per post using &lt;code&gt;next/og&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;helpful-resources&quot;&gt;Helpful Resources&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://nextjs.org/docs/app/guides/mdx&quot;&gt;Next.js MDX Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://www.npmjs.com/package/next-mdx-remote&quot;&gt;next-mdx-remote Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/remarkjs/remark-gfm&quot;&gt;remark-gfm Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/jonschlinkert/gray-matter&quot;&gt;gray-matter Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/huozhi/sugar-high&quot;&gt;sugar-high Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/tailwindlabs/tailwindcss-typography&quot;&gt;Tailwind Typography Plugin Docs&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;related-guides&quot;&gt;Related Guides&lt;/h3&gt;
&lt;p&gt;If you'd like to keep building out your Next.js stack, these guides pair well with this one:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/blog/saas-starter-architecture-nextjs&quot;&gt;SaaS Starter Architecture with Next.js 2026&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/blog/nextjs-16-supabase-todo-app&quot;&gt;Build a Todo App with Next.js 16 and Supabase (2026 Guide)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/blog/how-to-add-clerk-authentication-in-nextjs-16&quot;&gt;How to Add Clerk Authentication in Next.js 16 (2026 Guide)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/blog/resend-nextjs-16-guide&quot;&gt;How to Setup Resend Email in Next.js 16 (2026 Complete Beginner Guide)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;try-these-free-developer-tools&quot;&gt;Try These Free Developer Tools&lt;/h3&gt;
&lt;p&gt;While you're here, a couple of free tools that pair naturally with a fresh MDX blog setup like this one:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/tools/meta-tag-generator&quot;&gt;Meta Tag Generator for Next.js &amp;amp; HTML&lt;/a&gt; — generate SEO meta tags, Open Graph tags, Twitter Cards, canonical URLs, and JSON-LD structured data instantly. Handy for wiring up per-post metadata like the &lt;code&gt;generateMetadata()&lt;/code&gt; function above.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/tools/rls-policy-generator&quot;&gt;Supabase RLS Policy Generator&lt;/a&gt; — if your next project pairs this blog setup with a Supabase backend, generate secure, performance-optimized Row Level Security policies in seconds.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://devstacked.tech/tools/zod-schema-generator&quot;&gt;Zod Schema Generator&lt;/a&gt; — generate Zod schemas instantly from JSON or TypeScript. Includes smart inference, live validation, React Hook Form, Next.js API Routes, and Server Actions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;📦 &lt;strong&gt;Source Code:&lt;/strong&gt; &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/Muhammad-Ali-sma/next-mdx-setup&quot;&gt;View on GitHub&lt;/a&gt;&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/23799/complete-mdx-blog-setup-with-next-mdx-remote-and-next-js-16-2026-beginner-guide</guid>
<pubDate>Thu, 30 Jul 2026 19:00:00 +0000</pubDate>
</item>
<item>
<title>Embracing the World of AI as a Gen X'r</title>
<link>https://coderlegion.com/20319/embracing-the-world-of-ai-as-a-gen-xr</link>
<description>&lt;h2 id=&quot;embracing-the-world-of-ai-as-a-gen-x-r&quot;&gt;&lt;strong&gt;Embracing the World of AI as a Gen X’r&lt;/strong&gt;&lt;/h2&gt;
&lt;p&gt; is my ongoing chronicle of what happens when someone who grew up on mixtapes, arcades, and a 14.4k dial-up modem finally admits that AI isn’t a fad — it’s the next evolution of the tech we’ve been tinkering with since the days of FrontPage and floppy disks.&lt;/p&gt;
&lt;p&gt;This &lt;a rel=&quot;nofollow&quot; href=&quot;https://bit.ly/genx-meets-ai&quot;&gt;series&lt;/a&gt; is part nostalgia tour, part mid‑career reboot, part reminder that Gen X has always adapted, even when we pretended we weren’t paying attention. If I want to keep moving forward in tech, I can’t keep dodging AI — I have to learn it, experiment with it, and figure out how it fits into the world I’ve been building since my introduction to MS-DOS and “&lt;strong&gt;Hello, World&lt;/strong&gt;.” These posts capture that journey: the curiosity, the skepticism, the humor, and the quiet determination to stay in the game rather than age out of it.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://bit.ly/genx-meets-ai&quot;&gt;Embracing the Wonderful World of AI as a Gen X'r&lt;/a&gt;&lt;/p&gt;
</description>
<category>Discussions</category>
<guid isPermaLink="true">https://coderlegion.com/20319/embracing-the-world-of-ai-as-a-gen-xr</guid>
<pubDate>Thu, 11 Jun 2026 16:10:26 +0000</pubDate>
</item>
<item>
<title>My blog series 'Embracing the World of AI'</title>
<link>https://coderlegion.com/18937/my-blog-series-embracing-the-world-of-ai</link>
<description>&lt;p&gt;My new blog series '&lt;strong&gt;Embracing the World of AI&lt;/strong&gt; (as a Gen Xer) is now up on my &lt;a rel=&quot;nofollow&quot; href=&quot;https://bit.ly/42iJsc3&quot;&gt;website&lt;/a&gt;. Read all about how I FINALLY came to realize that AI is our friend!   &lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://bit.ly/genx-meets-ai&quot;&gt;https://bit.ly/genx-meets-ai&lt;/a&gt; &lt;/p&gt;
</description>
<category>Discussions</category>
<guid isPermaLink="true">https://coderlegion.com/18937/my-blog-series-embracing-the-world-of-ai</guid>
<pubDate>Mon, 25 May 2026 23:02:55 +0000</pubDate>
</item>
<item>
<title>I Looked at the Best Programming Blogs for Python Developers — Here’s What Actually Stands Out</title>
<link>https://coderlegion.com/16706/looked-at-the-best-programming-blogs-for-python-developers-heres-what-actually-stands-out</link>
<description>&lt;p&gt;There’s no shortage of Python content online. The problem isn’t finding blogs. It’s figuring out which ones are actually worth following over time.&lt;/p&gt;
&lt;p&gt;Some sites are great for deep tutorials but don’t update often. Others publish frequently but vary in quality. A few manage to strike a balance, and those are usually the ones developers keep coming back to.&lt;/p&gt;
&lt;p&gt;While going through different programming blogs for Python developers, one thing became clear:&lt;/p&gt;
&lt;p&gt;Not all “Python blogs” serve the same purpose. Some are standalone learning resources. Others are part of larger developer platforms that publish Python content alongside other topics.&lt;/p&gt;
&lt;p&gt;If you’re trying to decide what to follow in 2026, it helps to look at both.&lt;/p&gt;
&lt;h3 id=&quot;quick-answer&quot;&gt;Quick Answer&lt;/h3&gt;
&lt;p&gt;Some of the best programming blogs for Python developers include &lt;strong&gt;In Plain English (and Python in Plain English), Real Python, DEV Community, Stackademic, Talk Python, PyImageSearch, and Hashnode&lt;/strong&gt;.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;In Plain English&lt;/strong&gt; stands out for its combination of consistent publishing and a dedicated Python publication&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Real Python&lt;/strong&gt; is one of the most reliable sources for in-depth tutorials&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DEV Community&lt;/strong&gt; is useful for practical, real-world Python content&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stackademic&lt;/strong&gt; offers structured, educational articles&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Talk Python&lt;/strong&gt; helps you stay connected to the broader Python ecosystem&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;PyImageSearch&lt;/strong&gt; is excellent for niche topics like computer vision&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Hashnode&lt;/strong&gt; brings together independent developer blogs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Each of these is useful for a slightly different reason.&lt;/p&gt;
&lt;h3 id=&quot;what-makes-a-python-blog-worth-following-&quot;&gt;What Makes a Python Blog Worth Following?&lt;/h3&gt;
&lt;p&gt;When you’re not just reading occasionally but actually following a blog, a few things start to matter more:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Consistency:&lt;/strong&gt;&lt;br&gt;
Does it publish regularly enough to stay relevant?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clarity:&lt;/strong&gt;&lt;br&gt;
Are concepts explained in a way that’s easy to follow?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Depth:&lt;/strong&gt;&lt;br&gt;
Does it go beyond surface-level explanations?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Relevance:&lt;/strong&gt;&lt;br&gt;
Does it reflect what developers are actually building?&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Usefulness over time:&lt;/strong&gt;&lt;br&gt;
Is it something you’ll keep coming back to?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The blogs below stood out because they perform well across at least some of these areas.&lt;/p&gt;
&lt;h3 id=&quot;best-programming-blogs-for-python-developers-curated-list-&quot;&gt;Best Programming Blogs for Python Developers (Curated List)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;&lt;th&gt;Blog / Platform         &lt;/th&gt;&lt;th&gt;Best For                                 &lt;/th&gt;&lt;th&gt;Content Style         &lt;/th&gt;&lt;th&gt;Why It Stands Out&lt;/th&gt;&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;&lt;td&gt;In Plain English        &lt;/td&gt;&lt;td&gt;Consistent Python content + distribution &lt;/td&gt;&lt;td&gt;Accessible tutorials  &lt;/td&gt;&lt;td&gt;Combines ecosystem + dedicated Python publication&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Real Python             &lt;/td&gt;&lt;td&gt;Deep learning                            &lt;/td&gt;&lt;td&gt;Structured tutorials  &lt;/td&gt;&lt;td&gt;High-quality, in-depth content&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;DEV Community (Python)  &lt;/td&gt;&lt;td&gt;Practical insights                       &lt;/td&gt;&lt;td&gt;Community-driven      &lt;/td&gt;&lt;td&gt;Real-world use cases and discussions&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Stackademic             &lt;/td&gt;&lt;td&gt;Structured learning                      &lt;/td&gt;&lt;td&gt;Educational guides    &lt;/td&gt;&lt;td&gt;Clear progression and explanations&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Talk Python             &lt;/td&gt;&lt;td&gt;Ecosystem awareness                      &lt;/td&gt;&lt;td&gt;Blog + podcast        &lt;/td&gt;&lt;td&gt;Industry trends and updates&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;PyImageSearch           &lt;/td&gt;&lt;td&gt;Niche depth                              &lt;/td&gt;&lt;td&gt;Specialized tutorials &lt;/td&gt;&lt;td&gt;Strong focus on computer vision&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td&gt;Hashnode (Python blogs) &lt;/td&gt;&lt;td&gt;Diverse perspectives                     &lt;/td&gt;&lt;td&gt;Independent blogs     &lt;/td&gt;&lt;td&gt;Wide range of voices&lt;/td&gt;&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 id=&quot;1-in-plain-english-a-consistent-python-content-ecosystem-plus-a-dedicated-python-blog-&quot;&gt;1. In Plain English — A Consistent Python Content Ecosystem (Plus a Dedicated Python Blog)&lt;/h3&gt;
&lt;p&gt;If you’re looking for something to follow consistently, &lt;a rel=&quot;nofollow&quot; href=&quot;https://plainenglish.io/&quot;&gt;&lt;strong&gt;In Plain English&lt;/strong&gt;&lt;/a&gt; is one of the more dependable options.&lt;/p&gt;
&lt;p&gt;What makes it different is that it operates as a broader developer content ecosystem rather than a single blog.&lt;/p&gt;
&lt;p&gt;On one level, it publishes Python-related articles directly on its main platform. These include:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;tutorials&lt;/li&gt;
&lt;li&gt;practical guides&lt;/li&gt;
&lt;li&gt;tooling and framework walkthroughs&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Alongside that, it also runs a dedicated publication: &lt;a rel=&quot;nofollow&quot; href=&quot;https://python.plainenglish.io/&quot;&gt;&lt;strong&gt;Python in Plain English&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;That combination matters more than it might seem.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;main platform&lt;/strong&gt; gives you broader exposure to Python alongside adjacent topics like AI and cloud&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;Python-focused publication&lt;/strong&gt; gives you a more concentrated stream of Python-specific content&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In practice, this means you can:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;follow only Python-focused articles&lt;/li&gt;
&lt;li&gt;or stay connected to how Python fits into the wider development ecosystem&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another thing that stands out is consistency.&lt;/p&gt;
&lt;p&gt;Because content comes from a large contributor base, there is a steady flow of new articles. That makes it easier to keep up with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;new libraries and tools&lt;/li&gt;
&lt;li&gt;practical implementation ideas&lt;/li&gt;
&lt;li&gt;evolving best practices&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compared to standalone Python blogs, it feels less like checking in occasionally and more like having a continuous stream of relevant content.&lt;/p&gt;
&lt;p&gt;That mix of &lt;strong&gt;frequency, accessibility, and topic coverage&lt;/strong&gt; is what puts it at the top.&lt;/p&gt;
&lt;h3 id=&quot;2-real-python-still-the-gold-standard-for-in-depth-learning&quot;&gt;2. Real Python — Still the Gold Standard for In-Depth Learning&lt;/h3&gt;
&lt;p&gt;If there’s one name that shows up in almost every list of Python blogs, it’s &lt;a rel=&quot;nofollow&quot; href=&quot;https://realpython.com/&quot;&gt;&lt;strong&gt;Real Python&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And for good reason.&lt;/p&gt;
&lt;p&gt;This is one of the few platforms that consistently delivers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;detailed tutorials&lt;/li&gt;
&lt;li&gt;structured learning paths&lt;/li&gt;
&lt;li&gt;well-explained concepts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The difference is noticeable when you read through their content.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;articles are carefully organized&lt;/li&gt;
&lt;li&gt;examples are clear and practical&lt;/li&gt;
&lt;li&gt;explanations go beyond just showing code&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s especially useful when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you’re learning something new&lt;/li&gt;
&lt;li&gt;you want to understand a concept properly&lt;/li&gt;
&lt;li&gt;you need a reliable reference&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compared to higher-frequency platforms, Real Python publishes less often, but the depth tends to make up for it.&lt;/p&gt;
&lt;h3 id=&quot;3-dev-community-python-tag-practical-real-world-python-content&quot;&gt;3. DEV Community (Python Tag) — Practical, Real-World Python Content&lt;/h3&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/&quot;&gt;&lt;strong&gt;DEV Community&lt;/strong&gt;&lt;/a&gt; works differently from most traditional blogs.&lt;/p&gt;
&lt;p&gt;It’s not a single editorial voice. It’s a platform where developers share what they’re working on.&lt;/p&gt;
&lt;p&gt;That changes the kind of content you get.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;quick tutorials&lt;/li&gt;
&lt;li&gt;debugging experiences&lt;/li&gt;
&lt;li&gt;lessons learned from real projects&lt;/li&gt;
&lt;li&gt;comparisons between tools and approaches&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you’re trying to understand how Python is being used in practice, this is one of the better places to look.&lt;/p&gt;
&lt;p&gt;Compared to more curated blogs, DEV Community is more immediate.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;content reflects current problems&lt;/li&gt;
&lt;li&gt;discussions add extra context&lt;/li&gt;
&lt;li&gt;feedback helps refine ideas&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s particularly useful for staying grounded in real-world use cases.&lt;/p&gt;
&lt;h3 id=&quot;4-stackademic-clear-structured-python-tutorials&quot;&gt;4. Stackademic — Clear, Structured Python Tutorials&lt;/h3&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://stackademic.com/&quot;&gt;&lt;strong&gt;Stackademic&lt;/strong&gt;&lt;/a&gt; leans more toward structured, educational content.&lt;/p&gt;
&lt;p&gt;The difference shows in how tutorials are written.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;concepts are introduced step by step&lt;/li&gt;
&lt;li&gt;explanations are given proper space&lt;/li&gt;
&lt;li&gt;articles tend to build on ideas rather than jump straight to results&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For Python developers, this makes it useful when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;you want a more guided learning experience&lt;/li&gt;
&lt;li&gt;you prefer clarity over speed&lt;/li&gt;
&lt;li&gt;you are trying to connect different concepts&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Compared to DEV Community, it feels more curated and more consistent in tone.&lt;/p&gt;
&lt;h3 id=&quot;5-talk-python-staying-connected-to-the-python-ecosystem&quot;&gt;5. Talk Python — Staying Connected to the Python Ecosystem&lt;/h3&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://talkpython.fm/&quot;&gt;&lt;strong&gt;Talk Python&lt;/strong&gt;&lt;/a&gt; is slightly different from the others because it combines a blog with a podcast.&lt;/p&gt;
&lt;p&gt;That gives it a broader perspective.&lt;/p&gt;
&lt;p&gt;Instead of focusing only on tutorials, it also covers:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;industry trends&lt;/li&gt;
&lt;li&gt;new tools and libraries&lt;/li&gt;
&lt;li&gt;insights from people in the Python community&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;It’s a good way to stay updated on what’s happening beyond just code.&lt;/p&gt;
&lt;p&gt;If you want to understand where Python is heading, not just how to use it, this is worth following.&lt;/p&gt;
&lt;h3 id=&quot;6-pyimagesearch-deep-dive-into-computer-vision&quot;&gt;6. PyImageSearch — Deep Dive into Computer Vision&lt;/h3&gt;
&lt;p&gt;If your interests lean toward computer vision, &lt;a rel=&quot;nofollow&quot; href=&quot;https://pyimagesearch.com/&quot;&gt;&lt;strong&gt;PyImageSearch&lt;/strong&gt;&lt;/a&gt; is one of the most useful niche Python blogs.&lt;/p&gt;
&lt;p&gt;The content is focused and technical.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;image processing&lt;/li&gt;
&lt;li&gt;deep learning&lt;/li&gt;
&lt;li&gt;OpenCV-based tutorials&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;What stands out is the depth within that niche.&lt;/p&gt;
&lt;p&gt;Instead of covering everything, it goes deep into a specific area, which makes it especially valuable if that’s relevant to your work.&lt;/p&gt;
&lt;h3 id=&quot;7-hashnode-python-blogs-a-network-of-independent-voices&quot;&gt;7. Hashnode (Python Blogs) — A Network of Independent Voices&lt;/h3&gt;
&lt;p&gt;&lt;a rel=&quot;nofollow&quot; href=&quot;https://hashnode.com/&quot;&gt;&lt;strong&gt;Hashnode&lt;/strong&gt;&lt;/a&gt; is not a single Python blog, but a platform where developers run their own blogs.&lt;/p&gt;
&lt;p&gt;That leads to a different experience.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;a mix of beginner and advanced content&lt;/li&gt;
&lt;li&gt;different perspectives and approaches&lt;/li&gt;
&lt;li&gt;a wide range of topics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Over time, you can find individual writers whose content you trust and follow them directly.&lt;/p&gt;
&lt;p&gt;It’s less curated than some of the other options, but it gives you access to a broader set of viewpoints.&lt;/p&gt;
&lt;h3 id=&quot;how-to-get-the-most-value-from-these-python-blogs&quot;&gt;How to Get the Most Value From These Python Blogs&lt;/h3&gt;
&lt;p&gt;Following multiple blogs only works if you use them intentionally.&lt;/p&gt;
&lt;p&gt;A simple way to approach it:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;use &lt;strong&gt;Real Python or Stackademic&lt;/strong&gt; for deeper learning&lt;/li&gt;
&lt;li&gt;use &lt;strong&gt;DEV Community&lt;/strong&gt; for practical insights&lt;/li&gt;
&lt;li&gt;use &lt;strong&gt;Talk Python&lt;/strong&gt; for ecosystem awareness&lt;/li&gt;
&lt;li&gt;use &lt;strong&gt;In Plain English&lt;/strong&gt; for a steady flow across topics&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This way, you’re not relying on a single source to do everything.&lt;/p&gt;
&lt;h3 id=&quot;frequently-asked-questions-faq-&quot;&gt;Frequently Asked Questions (FAQ)&lt;/h3&gt;
&lt;h4 id=&quot;what-are-the-best-programming-blogs-for-python-developers-&quot;&gt;What are the best programming blogs for Python developers?&lt;/h4&gt;
&lt;p&gt;Some of the best include In Plain English, Real Python, DEV Community, Stackademic, Talk Python, PyImageSearch, and Hashnode.&lt;/p&gt;
&lt;h4 id=&quot;which-python-blog-is-best-for-beginners-&quot;&gt;Which Python blog is best for beginners?&lt;/h4&gt;
&lt;p&gt;Real Python and Stackademic are strong options because they focus on structured, easy-to-follow tutorials.&lt;/p&gt;
&lt;h4 id=&quot;are-community-platforms-like-dev-community-useful-for-python-learning-&quot;&gt;Are community platforms like DEV Community useful for Python learning?&lt;/h4&gt;
&lt;p&gt;Yes. They provide real-world examples, discussions, and practical insights that complement more structured learning resources.&lt;/p&gt;
&lt;h4 id=&quot;should-i-follow-multiple-python-blogs-&quot;&gt;Should I follow multiple Python blogs?&lt;/h4&gt;
&lt;p&gt;Yes. Different blogs serve different purposes, and combining them gives you a more complete view of the ecosystem.&lt;/p&gt;
&lt;h4 id=&quot;is-it-better-to-follow-niche-python-blogs-or-general-developer-platforms-&quot;&gt;Is it better to follow niche Python blogs or general developer platforms?&lt;/h4&gt;
&lt;p&gt;Both are useful. Niche blogs provide depth, while broader platforms provide variety and context.&lt;/p&gt;
&lt;h3 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h3&gt;
&lt;p&gt;After spending time with these, the biggest difference wasn’t just in content quality, but in how each one fits into your routine.&lt;/p&gt;
&lt;p&gt;Some are the kind you open when you’re trying to learn something properly. Others are easier to check in on regularly and pick up ideas as you go.&lt;/p&gt;
&lt;p&gt;That makes a difference in what you actually end up using.&lt;/p&gt;
&lt;p&gt;Instead of trying to find the single best Python blog, it’s more useful to figure out which combination you’ll realistically keep coming back to.&lt;/p&gt;
</description>
<category>Articles</category>
<guid isPermaLink="true">https://coderlegion.com/16706/looked-at-the-best-programming-blogs-for-python-developers-heres-what-actually-stands-out</guid>
<pubDate>Tue, 05 May 2026 05:46:29 +0000</pubDate>
</item>
<item>
<title>Building This Blog: A Modern Next.js Blog with Markdown</title>
<link>https://coderlegion.com/14658/building-this-blog-a-modern-next-js-blog-with-markdown</link>
<description>
&lt;p&gt;&lt;img src=&quot;https://blog.ratnesh-maurya.com/images/blog/building-blog.jpg&quot; alt=&quot;Building This Blog: A Modern Next.js Blog with Markdown&quot;&gt;&lt;/p&gt;&lt;h1&gt;Building This Blog: an MDX&amp;#8209;powered Next.js blog&lt;/h1&gt;
&lt;p&gt;This blog is a small, opinionated setup for writing long&amp;#8209;form content that feels good to read and fun to build on.&lt;/p&gt;
&lt;p&gt;Under the hood it uses static generation, MDX, and a theme&amp;#8209;aware UI that works in both light and dark modes.&lt;/p&gt;
&lt;p&gt;Everything after the frontmatter is pure &lt;strong&gt;MDX&lt;/strong&gt;. Components like &lt;code&gt;Callout&lt;/code&gt;, &lt;code&gt;Steps&lt;/code&gt;, architecture diagrams, flows, and charts are all React components rendered directly in the post body.&lt;/p&gt;
&lt;h2&gt;Stack I ended up with&lt;/h2&gt;
&lt;p&gt;I wanted something fast, simple, and easy to reason about over years&amp;mdash;not weeks.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;The site is a static App Router app. Routes like `/blog/[slug]`, `/til/[slug]`, `/technical-terms/[slug]` are statically generated at build time.


TypeScript keeps the content layer and components honest. Tailwind + CSS variables handle layout and theming.


All long&amp;#8209;form content lives in the repo inside content/, written as `.md` or `.mdx` files with frontmatter.


Views, upvotes, and UTM events are stored in Supabase and surfaced through a custom analytics dashboard.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;How content works&lt;/h2&gt;
&lt;p&gt;All posts are simple files in the repo&amp;mdash;no CMS required.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-markdown&quot;&gt;---
title: &quot;Your Post Title&quot;
description: &quot;Post description&quot;
date: &quot;2024-01-20&quot;
author: &quot;Your Name&quot;
tags: [&quot;tag1&quot;, &quot;tag2&quot;]
category: &quot;Category&quot;
featured: true
---

Your content here...
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Markdown (&lt;code&gt;.md&lt;/code&gt;)&lt;/strong&gt; posts go through a Remark pipeline and are rendered as HTML.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MDX (&lt;code&gt;.mdx&lt;/code&gt;)&lt;/strong&gt; posts are compiled at runtime in the page using &lt;code&gt;next-mdx-remote/rsc&lt;/code&gt;, with a shared component map.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For posts that need diagrams, flows, or charts, I use &lt;code&gt;.mdx&lt;/code&gt; and drop in components like ArchitectureCard, FlowStep, and DemoBarChart.&lt;/p&gt;
&lt;h3&gt;Authoring flow&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;Add a new `.md` or `.mdx` file to content/blog/ with frontmatter for SEO, tags, and images.


Run npm run dev and iterate on copy, diagrams, and layout until the post feels polished.


Push to the main branch. The build step generates static HTML for every route and updates search data + OG images.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Architecture of the blog&lt;/h2&gt;
&lt;p&gt;At a high level, the blog is just three pieces: browser, Next.js, and Supabase.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Readers get fully rendered HTML from the CDN, with minimal JavaScript on top for upvotes, analytics, and small interactions.


Next.js statically generates pages for blog posts, TIL entries, technical terms, and lists. It also exposes a few API routes for analytics.


Supabase stores per&amp;#8209;page views, upvotes, and UTM events that feed the analytics dashboard and charts.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Request&amp;ndash;response flow for a page view&lt;/h2&gt;
&lt;p&gt;Here&amp;rsquo;s how a single blog page view flows through the system.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;The CDN serves a pre&amp;#8209;rendered HTML page that was generated at build time.


Next.js hydrates the page; components like the upvote button, custom cursor, and view counter start working.


A lightweight request records the view / upvote in Supabase without blocking the reader.


Aggregated stats are used to power Recharts visualizations on the analytics page.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2&gt;Visualizing traffic with charts&lt;/h2&gt;
&lt;p&gt;The same Recharts setup used in the analytics dashboard is available inside MDX posts.&lt;/p&gt;
&lt;p&gt;Charts are plain React components exposed to MDX. They respect the global theme and use the same accent palette as the rest of the site.&lt;/p&gt;
&lt;h2&gt;Performance before and after&lt;/h2&gt;
&lt;p&gt;Static export plus small tweaks around assets made a noticeable difference in user&amp;#8209;facing numbers.&lt;/p&gt;
&lt;h2&gt;Why this setup works for me&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Files as the source of truth&lt;/strong&gt; &amp;ndash; I can write posts in a text editor, version them in git, and refactor them like any other code.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Static by default&lt;/strong&gt; &amp;ndash; Most pages are static HTML, which is great for speed and reliability.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MDX when I need power&lt;/strong&gt; &amp;ndash; Architecture diagrams, flows, and charts are just components; I only reach for them when a post really needs them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Theme&amp;#8209;aware UI&lt;/strong&gt; &amp;ndash; Components use the same CSS variables as the rest of the app, so they look good in both light and dark modes.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;If you want to explore the implementation details, the full source code is on &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/ratnesh-maurya/blog.ratnesh-maurya.com&quot;&gt;GitHub&lt;/a&gt;. You could clone it, point it at your own content folder, and have a similar blog running in minutes.&lt;/p&gt;
</description>
<category>Other</category>
<guid isPermaLink="true">https://coderlegion.com/14658/building-this-blog-a-modern-next-js-blog-with-markdown</guid>
<pubDate>Tue, 21 Apr 2026 21:12:52 +0000</pubDate>
</item>
<item>
<title>Why Engineers Must Become Multipliers in the AI-Era</title>
<link>https://coderlegion.com/7508/why-engineers-must-become-multipliers-in-the-ai-era</link>
<description>&lt;h1&gt;Why Engineers Must Become Multipliers in the AI Era&lt;/h1&gt;
&lt;h2&gt;The Shift in What Makes a Good Engineer&lt;/h2&gt;
&lt;p&gt;
Ten years ago, being an engineer was mostly about knowing HTML, CSS, JavaScript, and one frontend framework. Today, the expectations have changed. It's no longer enough to just write code  companies now want engineers who can think, communicate, solve real problems, and create impact beyond their own tasks.
&lt;/p&gt;
&lt;h2&gt;How Software Development Has Changed&lt;/h2&gt;
&lt;h3&gt;Better Tools, Faster Prototyping&lt;/h3&gt;
&lt;p&gt;
Modern tools allow even non-technical people to build simple prototypes. But real products still require strong fundamentals: security, scalability, and maintainability.
&lt;/p&gt;
&lt;h3&gt;AI-Assisted Engineering&lt;/h3&gt;
&lt;p&gt;
AI accelerates development, but engineers still need to understand &lt;strong&gt;what&lt;/strong&gt; to build, &lt;strong&gt;why&lt;/strong&gt; to build it, and &lt;strong&gt;how&lt;/strong&gt; to build it correctly.
&lt;/p&gt;
&lt;h2&gt;Engineers Now Own More Than Just the “How”&lt;/h2&gt;
&lt;p&gt;
In many startups, engineers lead their own projects and make product decisions. This shift means engineers must understand the problem, own the solution, and deliver impact — not just follow requirements.
&lt;/p&gt;
&lt;h2&gt;What Is an Engineering Multiplier?&lt;/h2&gt;
&lt;p&gt;
An Engineering Multiplier is someone who increases the productivity and effectiveness of everyone around them. They don’t just code — they elevate the entire team.
&lt;/p&gt;
&lt;h3&gt;1. Improving Team Efficiency&lt;/h3&gt;
&lt;p&gt;
They remove friction, simplify processes, and help others move faster.
&lt;/p&gt;
&lt;h3&gt;2. Sharing Knowledge&lt;/h3&gt;
&lt;p&gt;
They document, mentor, and help teammates level up.
&lt;/p&gt;
&lt;h3&gt;3. Raising the Quality Bar&lt;/h3&gt;
&lt;p&gt;
High-quality work naturally pushes others toward better standards.
&lt;/p&gt;
&lt;h3&gt;4. Helping Teams Make Better Decisions&lt;/h3&gt;
&lt;p&gt;
They understand trade-offs and connect engineering choices to business goals.
&lt;/p&gt;
&lt;h3&gt;5. Empowering Others&lt;/h3&gt;
&lt;p&gt;
They don’t just solve problems — they help others learn how to solve them too.
&lt;/p&gt;
&lt;h2&gt;What Job Requirements Actually Mean Today&lt;/h2&gt;
&lt;p&gt;
Long lists of technologies in job posts don’t mean you must know everything. Companies want people who can learn quickly, solve problems, communicate well, and adapt. Essentially — they want multipliers.
&lt;/p&gt;
&lt;h2&gt;What Multiplier Skills Look Like in Practice&lt;/h2&gt;
&lt;p&gt;
Multipliers are resourceful. They combine existing knowledge with problem-solving and collaboration. They know how to learn anything they need by leveraging experience, AI tools, and people around them.
&lt;/p&gt;
&lt;h2&gt;A Simple Analogy: Building a House&lt;/h2&gt;
&lt;p&gt;
When you hire a contractor, you don’t count how many nails they hammer. You care about quality, timelines, and communication. Great engineers work the same way — they focus on outcomes and smooth collaboration.
&lt;/p&gt;
&lt;h2&gt;The Trend of Flatter Organizations&lt;/h2&gt;
&lt;p&gt;
Many companies are reducing layers of management. Engineers are expected to be more autonomous and take more ownership. Multipliers thrive in this environment.
&lt;/p&gt;
&lt;h2&gt;Final Thoughts&lt;/h2&gt;
&lt;p&gt;
AI isn’t replacing engineers — it’s redefining what great engineering looks like. The best engineers today don’t just code. They communicate, prioritize, collaborate, and multiply the impact of their team. The future belongs to Engineering Multipliers.
&lt;/p&gt;
&lt;p&gt; Read the full blog here: &lt;a rel=&quot;nofollow&quot; href=&quot;https://newsletter.eng-leadership.com/p/why-engineers-must-become-multipliers&quot;&gt;blog&lt;/a&gt;&lt;/p&gt;
</description>
<category>Web Dev</category>
<guid isPermaLink="true">https://coderlegion.com/7508/why-engineers-must-become-multipliers-in-the-ai-era</guid>
<pubDate>Wed, 19 Nov 2025 11:44:42 +0000</pubDate>
</item>
<item>
<title>Some Ranting on Dev.to and Opinion on UI Design</title>
<link>https://coderlegion.com/4418/some-ranting-on-dev-to-and-opinion-on-ui-design</link>
<description>&lt;h3 id=&quot;overview&quot;&gt;Overview&lt;/h3&gt;
&lt;p&gt;Each platform strives to provide its best and each has its pros and cons. Some are simple technical issues - like the Markdown editor of CoderLegion, some are serious design flaws (like there is no way to manage brushes in Affinity Photo).&lt;/p&gt;
&lt;p&gt;Today I was going to comb my thoughts and write something on Dev.to and was shocked so see this.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/wfpe796dwxkwuqik1l3d.png&quot; alt=&quot;Side Bar&quot;&gt;&lt;/p&gt;
&lt;p&gt;This ugly new feature is driving me mad.&lt;/p&gt;
&lt;h3 id=&quot;distracting-side-bar&quot;&gt;Distracting Side Bar&lt;/h3&gt;
&lt;p&gt;It's one of the things I don't like about Discord/Slack. The interface is so clustered with irrelevant things or buttons that I rarely click on or need. And &lt;strong&gt;there are too many colors&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;Now Dev.to is completely ruining the used-to-be quiet and focused writing experience. Just look at the screenshot below:&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://dev-to-uploads.s3.amazonaws.com/uploads/articles/mu85wvs6nio0ouccjun0.png&quot; alt=&quot;Heavy Distraction&quot;&gt;&lt;/p&gt;
&lt;p&gt;It's honestly so annoying I can't bear staying on this site any second longer. What's worse, because of this total distraction, I almost forgot what I was about to write.&lt;/p&gt;
&lt;h3 id=&quot;alternatives&quot;&gt;Alternatives&lt;/h3&gt;
&lt;p&gt;I would love to officially moving to CoderLegion for canonical Dev Logs, but the image uploading experience is also not smooth. So that's a dilemma.&lt;/p&gt;
&lt;p&gt;We have the official Methodox Blog on WordPress. For those who aren't familiar with its content management system - it requires uploading images to the blog server for every single thing you display (or else use plugins) and is really inconvenient if one just want to share quick screenshots.&lt;/p&gt;
&lt;p&gt;Medium is actually great writing experience, but its design feels more suited for literature work than for tech.&lt;/p&gt;
&lt;h3 id=&quot;ideal-scenario&quot;&gt;Ideal Scenario&lt;/h3&gt;
&lt;p&gt;Here I propose a concept &quot;QuietSpace&quot; for distraction-free blogging.&lt;/p&gt;
&lt;p&gt;Key ideas:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Medium style editing interface&lt;/li&gt;
&lt;li&gt;Dev.to style Markdown and easy image uploading through dropping and pasting, single button Preview&lt;/li&gt;
&lt;li&gt;CDN for blog contents&lt;/li&gt;
&lt;li&gt;GitHub style support for video and YouTube embedding.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Key formatting elements:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fully support tables (a issue in both CoderLegion and Medium)&lt;/li&gt;
&lt;li&gt;Fully support images gifs and videos (through CDN link) (an issue in Dev.to)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Web editor, optional desktop editor. No dedicated subdomain: url path for user. No ads, central explore and save articles. May even be paid writing experience at $5 per month. Easy sharing, simple commenting.&lt;/p&gt;
&lt;p&gt;Used for: DevLog.&lt;/p&gt;
&lt;p&gt;Derivation: dedicated blog-style web hosting, like the simplest form of Word Press.&lt;/p&gt;
&lt;h3 id=&quot;summary&quot;&gt;Summary&lt;/h3&gt;
&lt;p&gt;There are many blogging and posting platforms and each has distinct features. As a developer we seek a balance between publicity, platform friendliness and technical satisfaction. I think the best platform has to be customized for custom needs. While generic customizable frameworks exist, the customization process right now still take too much tweaking. Will AI solve this problem? I doubt it, as I see missing pieces in basic infrastructure that's not easily addressed with smart agents.&lt;/p&gt;
&lt;h3 id=&quot;follow-up&quot;&gt;Follow Up&lt;/h3&gt;
&lt;p&gt;I was writing this post bearing in mind I have to suffer the new UI update of Dev.to - life felt truly like a compromise. &lt;/p&gt;
&lt;p&gt;However, the dev team addressed the issue within an hour! I didn't even expect them to notice my post. Salute To Dev.To Dev Team! See discussion on &lt;a rel=&quot;nofollow&quot; href=&quot;https://dev.to/methodoxdivooka/whats-going-on-5en4&quot;&gt;the post on Dev.to&lt;/a&gt;.&lt;/p&gt;
</description>
<category>IDEs &amp; Code Editors</category>
<guid isPermaLink="true">https://coderlegion.com/4418/some-ranting-on-dev-to-and-opinion-on-ui-design</guid>
<pubDate>Mon, 04 Aug 2025 19:43:11 +0000</pubDate>
</item>
</channel>
</rss>