Skip to main content

Ship the Course Site with Appliku

The course you've been reading is itself a static site built with Docusaurus. This final chapter publishes it. You'll configure the build, deploy it as a static site through Appliku, attach a custom domain with HTTPS, and add a CI hook so any future edits under docs/ ship automatically.

Prerequisites

  • The course content under docs/ builds cleanly locally:

    cd ~/code/k8slearn
    npm install
    npm run build

    If you see onBrokenLinks: 'throw' errors, fix them before moving on. Appliku will fail the same way.

  • An Appliku account (appliku.com).

Step 1 — Local build sanity check

docusaurus.config.js should already have:

onBrokenLinks: 'throw',
markdown: {
hooks: {
onBrokenMarkdownLinks: 'throw',
},
},

Run:

npm run build
# - Generates static files in build/
# - Throws on any unresolved internal link or markdown link

Serve locally to confirm the output is browsable:

npm run serve
# Listening at http://localhost:3000

Open http://localhost:3000, click through several chapters, hit Back, and confirm there are no 404s.

Step 2 — Pick the deployed URL

You have two reasonable options:

  • k8slearn.<your-domain>, a subdomain of the same domain you used for the app.
  • A brand-new domain.

The rest of this chapter assumes k8slearn.example.com.

Step 3 — Create the Appliku application

Appliku's docs and AI-readable manifest live at appliku.com/llms.txt. Follow them for the exact UI steps. The high-level flow is:

  1. Create application → type Static Site.
  2. Connect repository: pick your GitHub account, select the k8slearn repo.
  3. Branch: master.
  4. Build command: npm ci && npm run build
  5. Output directory: build
  6. Node version: 20.
  7. Custom domain: k8slearn.example.com. Appliku will prompt you to add an A (or CNAME) record at your DNS host pointing at the Appliku ingress.
  8. TLS: Appliku provisions a Let's Encrypt certificate once DNS resolves.

You can also use the appliku CLI per the AGENTS notes in this repo. The CLI is the easiest way to wire up a new application if you already have an Appliku team and workspace:

appliku login
appliku app create --team applikuapps --name k8slearn --type static \
--repo <OWNER>/k8slearn --branch master \
--build-command "npm ci && npm run build" \
--output-dir build \
--node-version 20
appliku app domain add --app k8slearn k8slearn.example.com

Step 4 — Verify the first deploy

After the build job in Appliku finishes:

curl -sI https://k8slearn.example.com/ | head -n3
# HTTP/2 200
# server: ...
# content-type: text/html

curl -s https://k8slearn.example.com/ | grep -i '<title>'
# <title>Kubernetes From Zero to Production</title>

Walk the chapters in the deployed site the way a new reader would. Every internal link must work; the build would have failed otherwise, but it's worth confirming the navbar and sidebar render correctly across desktop and mobile widths.

Step 5 — Auto-deploy on push to master

The Appliku application is configured to redeploy on every push to master. Test it:

echo "" >> docs/intro.md
git commit -am "docs: trigger auto-deploy"
git push origin master

Watch the deploy in the Appliku dashboard (or appliku app deploy logs --app k8slearn --follow). The new build should appear at https://k8slearn.example.com/ within ~2 minutes.

Step 6 — Gate docs/ changes on a CI build check

Even with Appliku building on push, you want broken docs blocked before merge so master never embarrasses you. Note this is the k8slearn repository (the course site itself), not the expressapp repository where Part 6's PR gate lives. Each repo gets its own workflow.

Create .github/workflows/docs.yml in this repo:

name: docs

on:
pull_request:
branches: [master]
paths:
- 'docs/**'
- 'src/**'
- 'static/**'
- 'docusaurus.config.js'
- 'sidebars.js'
- 'package.json'
- 'package-lock.json'
- '.github/workflows/docs.yml'
push:
branches: [master]
paths:
- 'docs/**'
- 'src/**'
- 'static/**'
- 'docusaurus.config.js'
- 'sidebars.js'
- 'package.json'
- 'package-lock.json'

permissions:
contents: read

jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- run: npm ci
- name: Build (onBrokenLinks and onBrokenMarkdownLinks set to throw)
run: npm run build

This file is already checked in at .github/workflows/docs.yml in this repository. Make it a required check on master:

gh api -X PUT "repos/<OWNER>/k8slearn/branches/master/protection" \
-F 'required_status_checks.contexts[]=build' \
-F required_status_checks.strict=true \
-F enforce_admins=true \
-F required_pull_request_reviews.required_approving_review_count=1 \
-F required_linear_history=true \
-F allow_force_pushes=false \
-F allow_deletions=false \
-F restrictions=

(The job is named build inside the docs workflow, so the required-context name is build.)

Verify with a PR that contains a broken link:

git checkout -b docs/broken-link-test
echo "[broken](./nope.md)" >> docs/intro.md
git commit -am "test broken link"
git push -u origin docs/broken-link-test
gh pr create --fill
gh pr checks --watch
# the docs build fails with: Docusaurus found broken links

Close the PR without merging and delete the branch.

Step 7 — Optional: Appliku deploy webhook from CI

Appliku redeploys on push by default. If you want CI to be the trigger (e.g. only after another check passes), add a webhook step at the end of the docs job. From the Appliku dashboard, copy the deploy hook URL and store it as a secret:

gh secret set APPLIKU_DEPLOY_HOOK --body "https://appliku.com/deploy/<token>"

Add to .github/workflows/pr.yml in the docs job, after the build:

- name: Trigger Appliku deploy
if: github.ref == 'refs/heads/master' && steps.changed.outputs.run == 'true'
run: |
curl -fsSL -X POST "${{ secrets.APPLIKU_DEPLOY_HOOK }}"

This is belt-and-suspenders. Appliku also reacts to the push, so keep one or the other for clarity.

Step 8 — Update the orientation chapter

Once the site is live at its real URL, the orientation chapter's Course Map and intro can stop saying "the course is hosted at TBD". Update the URL in docusaurus.config.js and re-deploy:

url: 'https://k8slearn.example.com',

(baseUrl stays /.)

What you have at this point

  • A complete, public, HTTPS-secured course site at your chosen domain.
  • A CI pipeline that blocks merges with broken docs.
  • Auto-deploys on push to master.
  • Everything else you built across chapters 01–13: two clusters, Express app on TLS, GitOps with ArgoCD, observability, hardening, backups, restore drill, all running on bills you understand.

Completion signal

  • https://k8slearn.example.com/ returns the course homepage over HTTPS with a valid certificate.
  • Editing any docs/*.md file on master produces a new deploy on Appliku without manual steps.
  • A PR introducing a broken markdown link is blocked at the docs check.

Congratulations, the course is shipped.