<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Adenuga Adewumi Efe</title>
    <description>The latest articles on DEV Community by Adenuga Adewumi Efe (@braincodes).</description>
    <link>https://dev.to/braincodes</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1222873%2F6fbcb355-143d-4674-8fc0-ed10305ef581.jpeg</url>
      <title>DEV Community: Adenuga Adewumi Efe</title>
      <link>https://dev.to/braincodes</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/braincodes"/>
    <language>en</language>
    <item>
      <title>How I Automated My Next.js Deployments to cPanel with GitHub Actions (and All the Debugging That Came With It)</title>
      <dc:creator>Adenuga Adewumi Efe</dc:creator>
      <pubDate>Thu, 19 Jun 2025 21:46:58 +0000</pubDate>
      <link>https://dev.to/braincodes/how-i-automated-my-nextjs-deployments-to-cpanel-with-github-actions-and-all-the-debugging-that-1kic</link>
      <guid>https://dev.to/braincodes/how-i-automated-my-nextjs-deployments-to-cpanel-with-github-actions-and-all-the-debugging-that-1kic</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;From FileZilla frustration to smooth, automated deployments — this is a full walkthrough of how I connected GitHub Actions to my cPanel hosting to deploy a Next.js site via FTP. Along the way, I hit some common roadblocks, and I’ll show you how I solved them.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  💡 The Problem: Manual Deployments Were Driving Me Nuts
&lt;/h2&gt;

&lt;p&gt;As a web developer managing multiple sites, I’ve always preferred fast, reliable workflows. But when working with clients who host on &lt;strong&gt;shared hosting with cPanel&lt;/strong&gt;, deployment always ended up like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build the site locally&lt;/li&gt;
&lt;li&gt;Open FileZilla&lt;/li&gt;
&lt;li&gt;Drag and drop the build folder into &lt;code&gt;public_html&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Hope nothing breaks&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That workflow might work for basic static HTML, but I was building modern sites with &lt;strong&gt;React&lt;/strong&gt; and later &lt;strong&gt;Next.js&lt;/strong&gt;. And I knew I needed something more reliable.&lt;/p&gt;

&lt;p&gt;So I asked myself:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;em&gt;"Can I connect my GitHub repo directly to cPanel and let it auto-deploy via FTP?"&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Turns out — yes. But it took some debugging.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 Step 1: Choose the Deployment Approach
&lt;/h2&gt;

&lt;p&gt;After researching a few methods, I settled on:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ &lt;strong&gt;GitHub Actions + FTP (via SamKirkland’s FTP-Deploy-Action)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This combo works well if:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You’re on &lt;strong&gt;shared hosting&lt;/strong&gt; (no SSH/SFTP access)&lt;/li&gt;
&lt;li&gt;You want to deploy from &lt;code&gt;main&lt;/code&gt; branch&lt;/li&gt;
&lt;li&gt;You can generate a static site (like from Create React App or exported Next.js)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🏗️ Step 2: Setting Up the Next.js App for Static Hosting
&lt;/h2&gt;

&lt;p&gt;This part &lt;strong&gt;depends heavily&lt;/strong&gt; on whether you’re using &lt;strong&gt;React (CRA)&lt;/strong&gt; or &lt;strong&gt;Next.js&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  🟢 If You're Using Create React App (CRA)
&lt;/h3&gt;

&lt;p&gt;You're in luck. Just run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm run build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It creates a &lt;code&gt;build/&lt;/code&gt; folder — this is what you'll upload via FTP.&lt;/p&gt;

&lt;h3&gt;
  
  
  🔵 If You're Using Next.js (like me)
&lt;/h3&gt;

&lt;p&gt;Here’s where things get tricky. Next.js doesn't generate static files by default — it expects a Node.js server to render pages.&lt;/p&gt;

&lt;p&gt;To make it work on cPanel (which doesn’t run Node.js), you &lt;strong&gt;must export the app statically&lt;/strong&gt;:&lt;/p&gt;

&lt;h4&gt;
  
  
  Step-by-step:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Edit &lt;code&gt;next.config.js&lt;/code&gt;:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;export&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;trailingSlash&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;nextConfig&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;In &lt;code&gt;package.json&lt;/code&gt;, update your build script:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="nl"&gt;"build"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"next build &amp;amp;&amp;amp; next-sitemap"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;❌ Don’t use &lt;code&gt;next export&lt;/code&gt; directly. As of Next 15, &lt;code&gt;next export&lt;/code&gt; is &lt;strong&gt;deprecated&lt;/strong&gt; when using App Router.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;ol&gt;
&lt;li&gt;Now running &lt;code&gt;npm run build&lt;/code&gt; will generate an &lt;code&gt;out/&lt;/code&gt; folder — the folder we’ll deploy via FTP.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  🐛 Issue I Faced
&lt;/h3&gt;

&lt;p&gt;Initially, I used &lt;code&gt;next export&lt;/code&gt; like I did in older Next.js projects. That caused this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: `next export` has been removed in favor of output: 'export' in next.config.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Solution: Just define &lt;code&gt;output: 'export'&lt;/code&gt; and run &lt;code&gt;next build&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔐 Step 3: Set Up Secrets in GitHub
&lt;/h2&gt;

&lt;p&gt;Go to your repo &amp;gt; Settings &amp;gt; Secrets &amp;gt; Actions &amp;gt; New Secret:&lt;/p&gt;

&lt;p&gt;You’ll need these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FTP_SERVER&lt;/code&gt; → Use your server IP (not the domain, unless it resolves correctly)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FTP_USERNAME&lt;/code&gt; → FTP user (e.g., &lt;code&gt;deployment@yourdomain.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FTP_PASSWORD&lt;/code&gt; → FTP password&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FTP_SERVER_DIR&lt;/code&gt; → The path where you want files deployed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  🐛 Issue I Faced
&lt;/h3&gt;

&lt;p&gt;I initially set &lt;code&gt;FTP_SERVER&lt;/code&gt; to &lt;code&gt;ftp.afrojazzfestivalnigeria.com&lt;/code&gt;, but got this error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;getaddrinfo ENOTFOUND ftp.afrojazzfestivalnigeria.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Solution: Use your &lt;strong&gt;server IP address&lt;/strong&gt; instead.&lt;/p&gt;

&lt;p&gt;Another gotcha:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Error: server-dir should be a folder (must end with /)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ Solution: Always make sure &lt;code&gt;FTP_SERVER_DIR&lt;/code&gt; ends with a &lt;code&gt;/&lt;/code&gt;, e.g. &lt;code&gt;/public_html/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Later, I found out my FTP account was &lt;strong&gt;already scoped to the addon domain folder&lt;/strong&gt;, so I could just use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FTP_SERVER_DIR=/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  ⚙️ Step 4: GitHub Actions Workflow File
&lt;/h2&gt;

&lt;p&gt;Here’s my final working &lt;code&gt;.github/workflows/deploy.yml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🚀 Deploy to cPanel via FTP&lt;/span&gt;

&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;main&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-and-deploy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;📥 Checkout&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🧱 Install Dependencies&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm install&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;🛠️ Build App&lt;/span&gt;
        &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;npm run build&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;📤 Deploy via FTP&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;SamKirkland/FTP-Deploy-Action@v4.3.4&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;server&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.FTP_SERVER }}&lt;/span&gt;
          &lt;span class="na"&gt;username&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.FTP_USERNAME }}&lt;/span&gt;
          &lt;span class="na"&gt;password&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.FTP_PASSWORD }}&lt;/span&gt;
          &lt;span class="na"&gt;server-dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.FTP_SERVER_DIR }}&lt;/span&gt;
          &lt;span class="na"&gt;local-dir&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;out/&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧪 Final Test — and It Worked!
&lt;/h2&gt;

&lt;p&gt;After pushing to &lt;code&gt;main&lt;/code&gt;, I watched the GitHub Actions tab light up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Dependencies installed&lt;/li&gt;
&lt;li&gt;✅ App built to &lt;code&gt;out/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ FTP deploy complete&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Logged into cPanel — the files were there. Opened the domain in my browser — &lt;strong&gt;live site&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Lessons Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Next.js requires **&lt;/strong&gt;&lt;code&gt;output: 'export'&lt;/code&gt;**** for static builds**&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;You cannot use **&lt;/strong&gt;&lt;code&gt;"use client"&lt;/code&gt;**** with *&lt;strong&gt;&lt;em&gt;&lt;code&gt;generateStaticParams()&lt;/code&gt;&lt;/em&gt;&lt;/strong&gt;* in the same file** — split client/server components&lt;/li&gt;
&lt;li&gt;Use your &lt;strong&gt;IP&lt;/strong&gt; instead of &lt;code&gt;ftp.domain.com&lt;/code&gt; if DNS isn’t resolving&lt;/li&gt;
&lt;li&gt;Always end your &lt;code&gt;server-dir&lt;/code&gt; with a &lt;code&gt;/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Don’t overthink it — once it works, you can reuse it everywhere&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  💬 Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;This whole process turned a frustrating manual task into a smooth developer experience. Now I just push to GitHub and let Actions do the rest.&lt;/p&gt;

&lt;p&gt;I hope this guide saves you a few hours of trial and error.&lt;/p&gt;

&lt;p&gt;If it helped, leave a ⭐ on &lt;a href="https://github.com/SamKirkland/FTP-Deploy-Action" rel="noopener noreferrer"&gt;SamKirkland's action&lt;/a&gt; and let me know how yours went!&lt;/p&gt;




&lt;p&gt;🔗 &lt;strong&gt;Want to see the site?&lt;/strong&gt; &lt;a href="https://afrojazzfestivalnigeria.com" rel="noopener noreferrer"&gt;Visit afrojazzfestivalnigeria.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;📬 &lt;strong&gt;Got questions?&lt;/strong&gt; Reach out on &lt;a href="https://www.linkedin.com/in/adenuga-adewumi-efe-ab7731211/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt; or leave a comment on my post!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Embracing the Alté in Development: My Journey as an Alté Developer</title>
      <dc:creator>Adenuga Adewumi Efe</dc:creator>
      <pubDate>Fri, 30 Aug 2024 22:27:24 +0000</pubDate>
      <link>https://dev.to/braincodes/embracing-the-alte-in-development-my-journey-as-an-alte-developer-1ch9</link>
      <guid>https://dev.to/braincodes/embracing-the-alte-in-development-my-journey-as-an-alte-developer-1ch9</guid>
      <description>&lt;p&gt;In the world of music, the term “Alté” signifies a movement of artists who blend multiple genres, pushing creative boundaries and embracing eclectic, unconventional styles. It’s more than just a sound — it’s an identity, a mindset that challenges the norm. As a developer, I’ve adopted this same philosophy, but instead of blending musical notes, I blend coding languages, design principles, and creative processes. This is why I consider myself an “Alté Developer.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Fusion of Creativity and Code&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Being an Alté Developer means more than just writing code — it’s about creating experiences. In my journey, I’ve worn many hats: developer, UI/UX designer, animator, software engineer, data scientist, and graphics designer. Each role demands a different skill set, but they all share a common thread — creativity. Just as Alté musicians mix genres to craft something unique, I mix languages, frameworks, and design methodologies to build products that are as innovative as they are functional.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why I Chose to Be an Alté Developer&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Traditional paths never quite resonated with me. The idea of sticking to a single programming language or focusing solely on development felt limiting. I wanted more — I wanted to explore the intersections of technology and creativity, to see how far I could push the boundaries of what’s possible in the digital space. By embracing the Alté mindset, I found the freedom to experiment, to blend elements of design and development in ways that aren’t always conventional but are always effective.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Beyond Development: The Art of UI/UX and Design&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As an Alté Developer, I don’t just stop at writing functional code. I delve into the user experience, ensuring that the interfaces I create are intuitive and engaging. UI/UX design isn’t just about making things look good; it’s about solving problems in a way that feels seamless to the user. It’s about understanding the user’s journey and crafting every step with care. In this sense, developing a UI/UX design is as much an art as it is a science, and it’s this blend of disciplines that fuels my passion for the work I do.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Power of Multidisciplinary Skills&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My work as a graphics designer and animator further enhances my development process. Whether it’s creating dynamic visual content or developing data-driven applications, these skills allow me to approach problems from different angles, ensuring that the final product is not only functional but also visually compelling. The versatility that comes with being an Alté Developer means that I can take a holistic approach to projects, combining technical expertise with artistic flair to deliver truly unique results.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion: The Alté Developer as a New Breed&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In a world where specialization is often valued over versatility, the Alté Developer stands as a testament to the power of a multidisciplinary approach. By merging creativity with technology, I’ve carved out a niche that allows me to express my full range of skills. It’s not just about being a developer; it’s about being a creator, an innovator, and a problem-solver. This is what it means to be an Alté Developer — a role that embraces the richness of diversity in skills and the beauty of innovation in every project.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>programming</category>
      <category>frontend</category>
    </item>
  </channel>
</rss>
