5 Horizons Starter Theme
Bare-bones WordPress starter for new 5 Horizons builds. Bootstrap CSS is loaded for the grid only (bootstrap-grid.min.css — containers, rows/cols, flex/spacing/display utilities; no component styles). The Bootstrap JS bundle (with Popper) is loaded too, so modals/collapse/dropdowns are available — their CSS isn’t, so style them yourself or switch to full bootstrap.min.css in inc/enqueue.php. Swiper is loaded for sliders (front end and editor). Pages are built from Genesis Custom Blocks.
What’s in theme/
| Path | Purpose |
|---|---|
style.css | Theme header only — rename per project |
functions.php | Thin bootstrap; requires the files in inc/ |
inc/setup.php | Theme supports, editor styles, menus (Primary, Footer Links), image sizes, sidebar |
inc/enqueue.php | Google Fonts, Bootstrap grid + JS, Swiper, css/theme.css, js/theme.js; editor assets |
inc/customizer.php | Tag Manager head/body scripts, Theme Colors → --color-* CSS variables |
header.php / footer.php | Logo + primary nav (mobile drawer) / copyright + footer links |
index.php, single.php, archive.php, search.php, 404.php | Minimal loops in a .container > .row > .col-12 grid |
page.php | Just the_content() — blocks bring their own .container so backgrounds can go full width |
blocks/ | Genesis Custom Block templates (empty — add your own) |
scss/ | theme.scss → @import "custom"; everything lives in _custom.scss. editor-style.scss imports theme + editor tweaks |
js/theme.js | Mobile nav, generic Swiper init (initSwipers()), stub for block init functions |
js/editor-reinit.js | Re-runs block init functions inside the block editor |
Starting a new project
- Copy this repo (download the ZIP — don’t clone) and initialize it as a new repo.
- Update
theme/style.css(Theme Name, Description). - Set fonts in
fivehd_google_fonts_url()(inc/enqueue.php) and$font-body/$font-headinginscss/_custom.scss. - Set default colors in
fivehd_color_defaults()(inc/customizer.php) and the matching fallbacks at the top of_custom.scss. - Use Node 22 (
nvm use— the repo’s.nvmrcpins it; Node >= 20.19 is required), thennpm install, thennpm startto build + watch SCSS (ornpm run buildonce). Build is Gulp 5 + Dart Sass + Autoprefixer (gulpfile.mjs). - In WP Admin: set the logo (Customizer → Site Identity), assign the Primary Menu and Footer Links menus.
Adding a block
Full walkthrough: docs/genesis-custom-blocks-workflow.md. Short version:
- Template: create
theme/blocks/block-{slug}.php. Wrap the markup in<section class="{slug}"><div class="container"><div class="row">…. - Fields: WP Admin → Custom Blocks → Add New, slug
{slug}, field names matching what the template reads (block_value()/block_field()). - Styles: add a
/*Block Name*/section to the Blocks area at the bottom ofscss/_custom.scss. - JS (only if needed): add an idempotent
init{Name}()function tojs/theme.js, call it onDOMContentLoaded, expose it onwindow, and add its name toINIT_FUNCTIONSinjs/editor-reinit.js. Never use inline<script>in block markup — it doesn’t run in the editor.
Sliders (Swiper)
Any .swiper is initialized automatically by initSwipers() (front end and editor):
<div class="swiper-slider-wrap">
<div class="swiper" data-swiper='{"slidesPerView": 1, "breakpoints": {"768": {"slidesPerView": 3}}}'>
<div class="swiper-wrapper">
<div class="swiper-slide">…</div>
</div>
</div>
<div class="swiper-pagination"></div>
<div class="swiper-button-prev"></div>
<div class="swiper-button-next"></div>
</div>
data-swiper (optional) is JSON merged over the defaults (1 per view, 30px gap, loop, arrows/pagination if present). For a slider that needs its own logic, add swiper--custom and write a dedicated init function. Bump the version with FIVEHD_SWIPER_VER in functions.php.
Deploying (GitLab → WP Engine)
- Create staging + production SFTP users at WP Engine with path
/wp-content. - Rename
.gitlab-ci.yml.template→.gitlab-ci.ymland fill inTHEME_DIRand the two hosts. - Add
WPENGINE_PROD_USER/PASSandWPENGINE_STAGING_USER/PASSin GitLab → Settings → CI/CD → Variables (protected + masked). - Pushes to
stagingdeploy to staging; pushes tomaindeploy to production (deploy.sharchives the previous theme folder first).
Upload on save (VS Code)
.vscode/sftp.json (git-ignored) is set up for the Natizyskunk SFTP extension: fill in host, username, password and theme folder for each profile (staging is the default; switch with SFTP: Set Profile). Saving any file in theme/ uploads it, and the watcher also uploads Gulp’s output in theme/css/ whenever npm start rebuilds it. A fresh clone won’t have this file – copy it from another project or recreate it.
(Sublime users: copy theme/sftp-config.example.json to theme/sftp-config.json, also git-ignored.)