A static Next.js export with a <Image> component renders blank on cPanel. The file path is correct. The image file is there. The problem is that next/image calls an optimisation API at request time, and that API doesn’t exist in a static export served from a shared host. The fix is one line in next.config.js: unoptimized: true. That fix is chapter four of the static-next-cpanel course — and it’s there because no tutorial for shared-hosting Next.js deployments documents it in context.
That’s the gap the course fills.
Why shared hosting is underdocumented
The people writing Next.js deployment guides have migrated to Vercel, Netlify, or a VPS. The infrastructure they deploy to is managed: image optimisation is a service, routing is handled by the platform, the server configuration is abstracted away. The documentation ecosystem reflects their infrastructure.
The developers still on cPanel shared hosting — which is most of the people paying for web hosting — are working in a different environment. LiteSpeed instead of Nginx. .htaccess configuration instead of server-level routing rules. FTP deploys instead of Git-connected CI. The tutorials don’t cover this because the authors aren’t there.
The result is that a cPanel deployment of a static Next.js site breaks in three predictable places, and fixing each one requires piecing together answers from Stack Overflow threads, GitHub issues, and forum posts that are individually incomplete and collectively inconsistent.
The three places it breaks
next/image. The <Image> component uses Next.js’s Image Optimisation API, which runs at request time on the server. A static export doesn’t have a server. The optimisation step never happens, and the component renders nothing. Setting unoptimized: true in next.config.js bypasses the API and serves the source image directly. The trade-off is explicit: you lose responsive image generation, so you take responsibility for sizing source assets appropriately. One flag. One trade-off. Not difficult — just undocumented on the static-export path.
LiteSpeed and .htaccess. cPanel runs LiteSpeed, not Apache. LiteSpeed has broad compatibility with Apache’s .htaccess syntax, but the compatibility isn’t complete. Configuration that works on an Apache-based host may silently fail on LiteSpeed, or fail with an opaque permission error. A static Next.js export needs specific .htaccess rules to handle clean URL routing — resolving /about to the about/index.html the build produced. Getting those rules right on LiteSpeed is different from getting them right on Apache. Most of the relevant Stack Overflow answers were written for Apache.
The trailing-slash 404. This one intersects with the .htaccess problem. A static export produces about/index.html, but a request to /about/ with a trailing slash doesn’t automatically resolve to that file on a LiteSpeed host without the right configuration. Neither does a request to a non-existent route necessarily land on the 404.html the build produced. The result is that some URL variants return the host’s default error page instead of the site’s. Fixing it means understanding both what the static export produces and how LiteSpeed resolves paths — two things that are usually documented separately.
The fourth topic in the course is the GitHub Actions FTP deploy. Not a bug — a missing automation layer. The default path for a static export on cPanel is to build locally and FTP the output directory by hand. That works for a first deployment. The course’s final chapter covers the GitHub Actions workflow that rebuilds and deploys on every push to the main branch, using a cPanel FTP credential and the right working directory. It’s not complicated. It’s just not documented for the static Next.js to cPanel shape specifically.
What the course is
static-next-cpanel is the second course in the /learning/ section on captainrandom.co.uk, on the ship-it track: practical, deployment-oriented, not introductory. It assumes you know Next.js and have decided to deploy to cPanel shared hosting — either because you already pay for it, because a client requires it, or because you want a zero-cost production environment until there’s revenue to justify moving.
Eight chapters. Chapters one through three cover the static export setup and the cPanel environment. Chapters four through eight cover the three breaking points above and the GitHub Actions deploy. All eight went live on 2026-07-09 in two passes: the first three via one ultracode Workflow run from the existing curriculum spec, then four through eight via a second. The curriculum spec came first; the chapter content was generated against it.
What it doesn’t cover
Out of scope, explicitly:
- Vercel, Netlify, or any managed Next.js host
- Server-rendered pages or API routes (static export only; those require a Node.js runtime the shared host doesn’t provide)
- VPS deployments (different server stack, different problem set)
- Image optimisation configuration beyond the
unoptimizedflag
The course’s usefulness depends on knowing when it applies. If you’re on a VPS running Nginx, the LiteSpeed .htaccess content isn’t relevant. If you need server-side rendering, static export is the wrong starting point.
Why a course rather than a post
The three problems need to be understood in relation to each other. The .htaccess configuration affects how 404s are handled. The unoptimized flag interacts with how you structure image assets in the build output. The FTP deploy workflow needs to push the right directory. These aren’t independent fixes applied in isolation — they’re a deployment configuration that works as a system.
A Stack Overflow answer can document a fix. A course documents the system.
The course is at /learning/static-next-cpanel. The learning hub it sits in shipped its navigation infrastructure — site-wide full-text search, prerequisite chips at chapter heads, a live programme atlas — on 2026-07-03. The course is searchable and each chapter surfaces its dependencies at the top.
The documentation gap is real. The shared-hosting developers are real. Eight chapters cover the three places every cPanel Next.js deploy hits first.



