index.html the one-pager (~52 KB), plain static HTML
assets/style.css all styling, shared by the one-pager and the blog
covers/ journal cover art, 760 px wide
_data/covers.yml the cover list — the page is generated from this
_data/people.yml current lab members — the People page is generated from this
member_form.docx the form you send to a new member
img/ PI photo
news.html the blog index (served at /news/ , not /news.html)
404.html custom not-found page (permalink pinned — see the trap below)
og.png 1200x630 link-preview card. Referenced by index.html's
og:image/twitter:image. If you rename or delete it, every
share on LINE, Slack, X, or Facebook shows a broken image.
robots.txt points crawlers at the sitemap
img/og/ 1200x630 landscape share cards, one per cover
tools/make_og_cards.py regenerates them from _data/covers.yml
_posts/ one markdown file per post <- the part you edit often
_layouts/ page shell for blog pages
_config.yml Jekyll settings
Two halves, deliberately:
layout: null front matter so
Jekyll runs Liquid in it — that is what pulls the two latest posts onto the home page.
Because of that, **never paste a literal /covers/FILE.jpg)
``
feed.xml updates. You never touch news.html.You can do all of this from a phone. There is no local install and no build command.
Suggested tags: Cover, Paper, Talk, People, Lab.
Every post page has LinkedIn / Facebook / X / Copy link buttons under the article. Click one, or paste the post URL into a post on either platform. The preview card is generated from the page’s Open Graph tags.
Never point image: at a file in covers/. Journal covers are portrait (760x999).
Facebook and LinkedIn want 1.91:1 landscape, so a portrait cover gets centre-cropped into
a letterbox that cuts off the top and bottom of the artwork. Point at the pre-built
landscape card instead:
image: /img/og/Batteries_and_Supercaps_2026.jpg # 1200x630, cover + caption
Posts with no image: fall back to og.png, which is always a safe default.
Making a card for a new cover. Add the cover to _data/covers.yml first, then either
ask Claude for the card, or run it yourself:
pip install pillow pyyaml fonttools
python tools/make_og_cards.py # reads _data/covers.yml, writes img/og/*.jpg
If the preview looks wrong or stale, the platform has cached the old tags. Force a refresh:
Paste the URL, click Inspect / Scrape Again. LinkedIn caches for about 7 days and there is no way around it other than the inspector, so check the preview before you post, not after.
A post does not have to be an essay. Three sentences announcing a cover is a post. The failure mode for an academic blog is not posts that are too short, it is a “Latest news, March 2024” banner sitting on a 2026 site. Short and alive beats long and abandoned.
img/news/ (Add file → Upload files → drag). Lowercase, no spaces:
2026-08-glovebox.jpg.
With a caption:
<figure>
<img src="/img/news/2026-08-glovebox.jpg" alt="Short description">
<figcaption>The caption readers actually see.</figcaption>
</figure>
Paths start with / because baseurl is "" and the site sits at the root of
www.skhgroup.net. covers/ is for journal cover art only; put post photos in img/news/.
One <h2> and one <div class="note"> in id="publications". Change both together or
they will disagree. Refresh the “July 2026” date at the same time.
1. .page is hidden by default. The one-pager is a JS tab switcher:
.page{display:none} and JS adds .on to whichever section the hash selects. Blog pages
have no such JS, so _layouts/default.html wraps content in <div class="page on">.
Drop the on and the blog renders as a nav and a footer with nothing between them.
permalink: in _config.yml ends with a /. In Jekyll that turns on pretty URLs for
every HTML page, not just posts: news.html is built to /news/index.html and
/news.html returns 404. index.html and feed.xml are exempt, which is why the site
root kept working and only the News link broke.
news.html now pins its own permalink: /news/ in the front matter, so it no longer
depends on that setting. Link to /news/, never /news.html.
404.html pins permalink: /404.html for the same reason. GitHub Pages only serves a
custom 404 from that exact path; without the pin Jekyll would build it to /404/ and you
would silently get GitHub’s generic error page back.
Commit to github.com/soorathep/Test. GitHub Pages rebuilds on every push. If images do
not appear, the folder is missing or misnamed: paths are case-sensitive.
Two settings live in _config.yml and nowhere else:
baseurl: "/Test" matches the repo name. Rename the repo and this must change, or every
blog link 404s. If you point skhgroup.net at Pages, set it to "".home_url: "index.html" is what the nav links back to. Renaming the
one-pager to index.html (recommended eventually, it gives you a clean / URL) means
changing this one line.If the blog breaks after a rename, it is one of those two lines.
covers/ and img/.Claude cannot reach the repo. Two ways to work:
Give Claude the source, not a summary: the CV, the publisher’s cover file, the Scopus page. Every error worth fixing in this file so far came from someone paraphrasing a source instead of reading it.