Skip to content

dipidup/Missing_Palette

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

385 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Missing Palette - Site Build System

Everything in your site that isn't hand-coded HTML is now generated by Python scripts that run automatically on every commit.

              your repo (dipidup/Missing_Palette on GitHub)
              ┌────────────────────────────────────────────┐
              │                                            │
   ┌──────────┴──────────┐    ┌──────────────────────┐    │
   │  img/gallery/*.jpg  │    │  Google Sheets       │    │
   │  (you upload)       │───►│  (gallery rows)      │────┤
   └─────────────────────┘    └──────────────────────┘    │
                                                          │
   ┌─────────────────────┐                                │
   │  posts/*.md         │────────────────────────────────┤
   │  (you write)        │                                │
   └─────────────────────┘                                │
                                                          │
   ┌─────────────────────┐                                │
   │  img/blog/*.jpg     │────────────────────────────────┤
   │  (you upload)       │                                │
   └─────────────────────┘                                │
                                                          ▼
                                            ┌──────────────────────┐
                                            │  GitHub Actions      │
                                            │  runs all 3 builders │
                                            └──────────┬───────────┘
                                                       │
                              ┌────────────────────────┼────────────────────────┐
                              ▼                        ▼                        ▼
                  ┌────────────────────┐   ┌────────────────────┐   ┌────────────────────┐
                  │  gallery.html      │   │  blog/<slug>.html  │   │  blog.html         │
                  │  (cards regen'd)   │   │  (one per post)    │   │  (cards regen'd)   │
                  └────────────────────┘   └────────────────────┘   └────────────────────┘

What's in this delivery

posts/
  Ghat.md
  hostel4.html
  watercolor-portrait-guide.md
  (your future posts go here as .md files)

scripts/
  build_post.py                  - converts posts/*.md -> blog/*.html
  build_blog.py                  - regenerates the cards in blog.html
  build_gallery.py               - regenerates the gallery grid in gallery.html
  sync_layout.py                 - propagates <nav> + <footer> from index.html
                                   into every other page (run after editing nav/footer)
  convert_gallery_images.py      - emits .webp + .avif siblings for img/gallery/*.jpg
                                   (run after dropping in new gallery images)
  cleanup_pass.py                - one-off site-wide content sanitizer
  _add_blog_markers.py           - one-time setup (adds AUTO:POSTS markers)
  _add_gallery_markers.py        - one-time setup (adds AUTO:GALLERY markers)
  _convert_existing_html_to_md.py - one-time setup (already run for you)

.github/workflows/
  build-site.yml                 - runs all builds on every commit + hourly

README.md                        - this file

You also get the rebuilt:

blog/Ghat.html
blog/hostel4.html
blog/watercolor-portrait-guide.html
blog.html (with AUTO:POSTS markers + freshly generated cards)

These should be committed alongside the .md files - they're the deployed artifacts users see, and the build pipeline keeps regenerating them.


ONE-TIME SETUP (10 minutes on your laptop)

Step 1 - copy these files into your repo

In dipidup/Missing_Palette, place each file at this path:

posts/Ghat.md                       -> repo root /posts/
posts/hostel4.md                    -> repo root /posts/
posts/watercolor-portrait-guide.md  -> repo root /posts/
scripts/build_post.py               -> repo root /scripts/
scripts/build_blog.py               -> repo root /scripts/
scripts/_add_blog_markers.py        -> repo root /scripts/
.github/workflows/build-site.yml    -> create the folders
blog.html                           -> replace the existing one (has markers now)
blog/Ghat.html                      -> replace
blog/hostel4.html                   -> replace
blog/watercolor-portrait-guide.html -> replace

If you already have .github/workflows/build-gallery.yml from the older setup, DELETE IT - the new build-site.yml does everything (gallery + blog).

Step 2 - create img/blog/ folder

In your repo root, create an empty img/blog/ folder. Future blog post images will live here. (Existing posts use images from img/gallery/, which is fine.)

Step 3 - commit and push

git add posts scripts .github blog blog.html
git commit -m "Add blog build system"
git push

GitHub Actions will run the workflow once. Check the Actions tab to confirm it completes green. If anything fails, the log will tell you what.


DAILY USE - HOW TO ADD A NEW BLOG POST

You write Markdown, GitHub does the rest.

From your laptop (recommended for new posts)

  1. Make a new file posts/your-slug.md (e.g. posts/monsoon-2026.md).
  2. Copy the frontmatter block from one of the existing .md files and edit it.
  3. Drop any images into img/blog/ (or reference existing ones in img/gallery/).
  4. Write the post body in Markdown.
  5. git add posts/your-slug.md img/blog/* && git commit -m "New post" && git push
  6. Wait ~60 seconds. The post is live at https://missingpalette.com/blog/your-slug.html and a card automatically appears on the journal index.

Markdown reference

---
title: "Your title (with *emphasis* if you want)"
slug: "your-slug"
subtitle: "One-line subtitle below the h1."
category: "Memoir"
description: "One sentence. Used for SEO and social previews."
hero_image: "/img/blog/hero.jpg"
hero_caption: "Caption shown under the hero."
read_time: "6 min read"
status: "published"
---

This is the lead paragraph. It renders larger and italic.

A regular paragraph. Use **bold** and *italic* freely.
Inline links: [text](/gallery.html), [external](https://example.com).

## A section heading with *emphasis*

H2 emphasis renders crimson italic.

### A sub-heading

H3 for sub-points.

> A pull-quote. The single sentence you want a reader to remember.

- **Bold lead** - the rest is the supporting text
- **Same shape** - keep bullets parallel

![Caption text](/img/blog/photo.jpg)

---

Final paragraph. Pull the thread together.

Hindi text in captions and body

Inline:

The painting is called <span class="hi">भण्डि बाबा</span>.

Inside a figure caption (use raw HTML for the figure if Hindi is needed in the caption, since markdown image syntax doesn't preserve span classes):

<figure class="post-image">
    <img src="/img/blog/photo.jpg" alt="">
    <figcaption class="post-image-caption">
        <span class="hi">बनारसी सुबह</span> · Subah - dawn at the ghat.
    </figcaption>
</figure>

Drafts

Set status: "draft" in frontmatter to skip a post in the build. The .md file stays in the repo but no HTML is generated and no card appears in the index.


WORKFLOW: PHONE

What you can do from phone (GitHub mobile app or any web editor):

  • Toggle a post's status from draft to published or back
  • Change a post's hero_image (point to a different image already in img/)
  • Reorder posts on the index (rename slugs, OR switch to sheet-driven mode - see "Sheet mode" below)
  • Edit small typos in any post body

What is painful from phone (don't try this):

  • Writing a new long-form post (markdown editor on phone is not fun)
  • Uploading images that need to live in img/blog/

SHEET MODE (optional)

Default mode reads posts/*.md frontmatter for ordering (alphabetical by slug).

If you want to control ORDER from a phone via Google Sheets, switch to sheet mode. Useful for promoting a recent post to the top, or hiding a post without deleting the file.

To enable:

  1. Add a "Posts" tab to your existing gallery sheet with these columns:
slug order featured
Ghat 1 yes
hostel4 2 no
watercolor-portrait-guide 3 no
  1. Publish the sheet to web as CSV. Get the URL of the Posts tab specifically (it'll have a gid= parameter for the tab).

  2. In your repo, edit .github/workflows/build-site.yml. In the "Build blog index" step, change to:

      - name: Build blog index (cards in blog.html)
        env:
          BLOG_SOURCE: sheet
          BLOG_SHEET_CSV_URL: https://docs.google.com/spreadsheets/d/YOUR_SHEET_ID/export?format=csv&gid=YOUR_TAB_GID
        run: python3 scripts/build_blog.py
  1. Commit. Now the sheet is the source of truth for blog index order.

In sheet mode, an unlisted slug = hidden. Adding a row to the sheet for a slug that has a posts/<slug>.md file = visible in the index.


TROUBLESHOOTING

"Build failed in GitHub Actions" Open the Actions tab on github.com, click the failed run, find the red step. Most common cause: a typo in YAML frontmatter (forgot a closing quote, etc). The error message will tell you which file.

"My post isn't showing up on the index"

  • Did you set status: "published" (not "draft")?
  • Did posts/your-slug.md get committed?
  • Did the action complete successfully?
  • Check blog.html after the build: did your card get added between the <!-- AUTO:POSTS-START --> and <!-- AUTO:POSTS-END --> markers?

"Image not loading on the post"

  • Check the path. If your image lives at img/blog/foo.jpg, the markdown reference should be ![](/img/blog/foo.jpg) - leading slash matters.
  • Spaces in filenames work but get URL-encoded automatically.

"I want to edit the post layout / template" Edit POST_TEMPLATE.html. The build script uses it as the wrapper. Run python3 scripts/build_post.py to rebuild every post against the new template.

"My em-dash and the AI tells came back in the rebuilt HTML" The build script uses POST_TEMPLATE.html as the wrapper. If POST_TEMPLATE has LLM-template phrases in it, every post inherits them. Edit POST_TEMPLATE.html once, rerun build_post.py, all posts update.


SITE MAP

Top-level pages (hand-coded HTML, edit directly):

index.html         - homepage (hero + about + commissions + contact)
gallery.html       - full artwork grid (auto-regenerated; see AUTO:GALLERY markers)
blog.html          - journal index (auto-regenerated; see AUTO:POSTS markers)
events.html        - workshops & private sessions (Plan an Event)
exhibitions.html   - exhibitions, press, awards
products.html      - art materials I recommend (Amazon affiliate links)
register.html      - class registration (embedded form)
legal.html         - terms, copyright, DMCA
privacy.html       - privacy policy

Blog posts live in blog/ and are generated from posts/*.md. Don't hand-edit the blog/*.html files — re-run scripts/build_post.py instead.

POST_TEMPLATE.html is the wrapper used by the build script; edit it to change the look of every post at once.

The whole site shares three CSS files (missingpalette.css, _v2, _v4) and one JS file (missingpalette.js).

index.html is the source of truth for the <nav> and <footer> blocks. After editing either one, run python scripts/sync_layout.py to propagate the change into every other page in one go. Add --check to dry-run (exits non-zero if anything is out of sync — useful in CI).

404.html is a stripped-down page (no footer) so GitHub Pages can serve it on any unknown URL. It's intentionally excluded from sync_layout.py.


LOCAL DEVELOPMENT

Serve the site over http://localhost so root-relative paths (/img/..., /css/...) resolve. From the repo root:

# Python 3 (no install needed)
python -m http.server 8000

# then visit http://localhost:8000

The build scripts need Python 3 and a couple of small libs:

pip install pyyaml markdown
pip install Pillow                  # for scripts/convert_gallery_images.py
pip install pillow-avif-plugin      # optional, enables AVIF output

After dropping new images into img/gallery/, run:

python scripts/convert_gallery_images.py

This generates .webp and .avif siblings next to each .jpg. The <picture> tags in gallery.html automatically serve the modern format to browsers that support it (most do), and fall back to the JPEG on the rest.


CRAWLERS & AI

robots.txt blocks the major AI training crawlers (GPTBot, ClaudeBot, CCBot, Google-Extended, PerplexityBot, Bytespider, Diffbot, FacebookBot, etc.). If you notice a new one in your access logs, add it as another User-agent: <name> / Disallow: / block.

sitemap.xml is hand-maintained for top-level pages and includes per-page <image:image> annotations for SEO. When you add a new gallery image, update the corresponding entries here too — there is no automation for the sitemap yet.


REPO HYGIENE

  • Archive 01/ holds the previous version of the site. Don't edit; it's kept for reference only and is excluded from robots.txt.
  • .DS_Store files (macOS metadata) get re-created automatically on macOS. Add them to .gitignore if you haven't already.
  • thumb.jpg is the canonical social/open-graph image referenced from every page. Replace it (keep the same filename) to update social previews site-wide.

About

A repository to learn and create my website which'll display my artworks.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors