Fix all Pelican build errors and implement proper testing workflow
- Setup virtual environment management in Makefile - Fix broken linkpeek RST directives in 2011 posts - Add missing image alt attributes for accessibility - Fix RST syntax errors and title hierarchy - Add markdown package for proper .md support - Update CLAUDE.md with testing workflow and critical issues - Rename code golf post to match slug - Clean build: 182 articles, 4 pages, zero errors
This commit is contained in:
parent
0249875fca
commit
776a4a07f4
16 changed files with 81 additions and 119 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -76,3 +76,4 @@ vars.fish
|
||||||
|
|
||||||
blog-multi-mower/
|
blog-multi-mower/
|
||||||
webwords/
|
webwords/
|
||||||
|
venv/
|
||||||
|
|
|
||||||
53
CLAUDE.md
53
CLAUDE.md
|
|
@ -1,5 +1,58 @@
|
||||||
# Claude Memory and Instructions
|
# Claude Memory and Instructions
|
||||||
|
|
||||||
|
## RUSSELL BALLESTRINI - KNOW THE USER
|
||||||
|
|
||||||
|
Russell Ballestrini is:
|
||||||
|
- Experienced systems administrator and DevOps engineer
|
||||||
|
- Python developer and technical blogger
|
||||||
|
- Creator of webwords project (42 programming languages)
|
||||||
|
- Uses direct, no-nonsense communication style
|
||||||
|
- Expects technical precision and working code
|
||||||
|
- Does not tolerate broken implementations or untested commits
|
||||||
|
|
||||||
|
## CRITICAL PELICAN TESTING WORKFLOW
|
||||||
|
|
||||||
|
### BEFORE ANY COMMIT:
|
||||||
|
1. **ALWAYS test Pelican build**: `make clean && make html`
|
||||||
|
2. **Check for build errors**: Pelican will fail on RST syntax errors, missing files, etc.
|
||||||
|
3. **Verify output**: `make serve` and check localhost:8000
|
||||||
|
4. **NEVER commit without testing the build**
|
||||||
|
|
||||||
|
### PELICAN BUILD PROCESS:
|
||||||
|
- Uses Pelican static site generator (Python-based)
|
||||||
|
- Converts .rst/.md files to HTML
|
||||||
|
- RST syntax errors break the build
|
||||||
|
- Missing images/files break the build
|
||||||
|
- Invalid slugs/filenames cause issues
|
||||||
|
|
||||||
|
### PROPER DEVELOPMENT WORKFLOW:
|
||||||
|
```bash
|
||||||
|
# Setup virtual environment (once)
|
||||||
|
make venv
|
||||||
|
|
||||||
|
# Test changes before commit
|
||||||
|
make clean && make html && make serve
|
||||||
|
|
||||||
|
# Check localhost:8000 for issues
|
||||||
|
# Only commit if build succeeds
|
||||||
|
git add specific-files
|
||||||
|
git commit -m "message"
|
||||||
|
git push
|
||||||
|
```
|
||||||
|
|
||||||
|
## CRITICAL CONTENT DIRECTORY ISSUE
|
||||||
|
|
||||||
|
**PROBLEM**: Python virtual environments exist in `content/uploads/2024/battleship-solvers/env/` and `env2/`
|
||||||
|
- These contain thousands of Python package files (.md, .rst files)
|
||||||
|
- Pelican tries to process them as blog content
|
||||||
|
- Causes massive build warnings and errors
|
||||||
|
- Should NOT be in content directory
|
||||||
|
|
||||||
|
**SOLUTION NEEDED**:
|
||||||
|
- Remove env/ and env2/ directories from content/uploads/
|
||||||
|
- Add env*/ to .gitignore patterns
|
||||||
|
- Keep only actual blog assets in content/uploads/
|
||||||
|
|
||||||
## CRITICAL GIT SAFETY LESSON
|
## CRITICAL GIT SAFETY LESSON
|
||||||
|
|
||||||
### DEVASTATING MISTAKE COMMITTED:
|
### DEVASTATING MISTAKE COMMITTED:
|
||||||
|
|
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
FROM alpine:latest
|
|
||||||
|
|
||||||
RUN apk --no-cache add gcc musl-dev curl-dev
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
COPY golf.c .
|
|
||||||
|
|
||||||
RUN gcc -o webwords golf.c -lcurl
|
|
||||||
|
|
||||||
EXPOSE 31337
|
|
||||||
|
|
||||||
CMD ["./webwords"]
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
FROM alpine:latest
|
|
||||||
|
|
||||||
ENTRYPOINT ["/bin/webwords"]
|
|
||||||
|
|
||||||
EXPOSE 31337
|
|
||||||
|
|
||||||
COPY golf.py /bin/webwords
|
|
||||||
|
|
||||||
RUN chmod 0754 /bin/webwords
|
|
||||||
|
|
||||||
RUN apk --no-cache add python3 ca-certificates \
|
|
||||||
&& rm -rf /var/cache/apk/*
|
|
||||||
64
Makefile
64
Makefile
|
|
@ -1,80 +1,46 @@
|
||||||
PY?=python
|
|
||||||
PELICAN?=pelican
|
|
||||||
PELICANOPTS=
|
|
||||||
|
|
||||||
BASEDIR=$(CURDIR)
|
BASEDIR=$(CURDIR)
|
||||||
INPUTDIR=$(BASEDIR)/content
|
INPUTDIR=$(BASEDIR)/content
|
||||||
OUTPUTDIR=$(BASEDIR)/output
|
OUTPUTDIR=$(BASEDIR)/output
|
||||||
CONFFILE=$(BASEDIR)/pelicanconf.py
|
CONFFILE=$(BASEDIR)/pelicanconf.py
|
||||||
PUBLISHCONF=$(BASEDIR)/publishconf.py
|
PUBLISHCONF=$(BASEDIR)/publishconf.py
|
||||||
|
|
||||||
|
|
||||||
DEBUG ?= 0
|
|
||||||
ifeq ($(DEBUG), 1)
|
|
||||||
PELICANOPTS += -D
|
|
||||||
endif
|
|
||||||
|
|
||||||
RELATIVE ?= 0
|
|
||||||
ifeq ($(RELATIVE), 1)
|
|
||||||
PELICANOPTS += --relative-urls
|
|
||||||
endif
|
|
||||||
|
|
||||||
help:
|
help:
|
||||||
@echo 'Makefile for a pelican Web site '
|
@echo 'Makefile for a pelican Web site '
|
||||||
@echo ' '
|
@echo ' '
|
||||||
@echo 'Usage: '
|
@echo 'Usage: '
|
||||||
|
@echo ' make venv setup virtual environment '
|
||||||
@echo ' make resume (re)generate the resume '
|
@echo ' make resume (re)generate the resume '
|
||||||
@echo ' make html (re)generate the web site '
|
@echo ' make html (re)generate the web site '
|
||||||
@echo ' make clean remove the generated files '
|
@echo ' make clean remove the generated files '
|
||||||
@echo ' make regenerate regenerate files upon modification '
|
@echo ' make regenerate regenerate files upon modification '
|
||||||
@echo ' make publish generate using production settings '
|
@echo ' make publish generate using production settings '
|
||||||
@echo ' make serve [PORT=8000] serve site at http://localhost:8000'
|
@echo ' make serve serve site at http://localhost:8000'
|
||||||
@echo ' make serve-global [SERVER=0.0.0.0] serve (as root) to $(SERVER):80 '
|
@echo ' make devserver serve and regenerate together '
|
||||||
@echo ' make devserver [PORT=8000] serve and regenerate together '
|
|
||||||
@echo ' make ssh_upload upload the web site via SSH '
|
|
||||||
@echo ' make rsync_upload upload the web site via rsync+ssh '
|
|
||||||
@echo ' '
|
|
||||||
@echo 'Set the DEBUG variable to 1 to enable debugging, e.g. make DEBUG=1 html '
|
|
||||||
@echo 'Set the RELATIVE variable to 1 to enable relative urls '
|
|
||||||
@echo ' '
|
@echo ' '
|
||||||
|
|
||||||
|
venv:
|
||||||
|
python3 -m venv venv
|
||||||
|
venv/bin/pip install -r requirements.txt
|
||||||
|
|
||||||
resume:
|
resume:
|
||||||
rst2pdf $(INPUTDIR)/pages/russell.ballestrini.resume.rst --stylesheets $(INPUTDIR)/pages/russell.ballestrini.resume.style -o $(OUTPUTDIR)/uploads/russell.ballestrini.resume.pdf
|
venv/bin/rst2pdf content/pages/russell.ballestrini.resume.rst --stylesheets content/pages/russell.ballestrini.resume.style -o output/uploads/russell.ballestrini.resume.pdf
|
||||||
|
|
||||||
|
|
||||||
html:
|
html:
|
||||||
$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
|
venv/bin/pelican content -o output -s pelicanconf.py
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
[ ! -d $(OUTPUTDIR) ] || rm -rf $(OUTPUTDIR)
|
[ ! -d output ] || rm -rf output
|
||||||
|
|
||||||
regenerate:
|
regenerate:
|
||||||
$(PELICAN) -r $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
|
venv/bin/pelican -r content -o output -s pelicanconf.py
|
||||||
|
|
||||||
serve:
|
serve:
|
||||||
ifdef PORT
|
venv/bin/pelican -l content -o output -s pelicanconf.py
|
||||||
$(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT)
|
|
||||||
else
|
|
||||||
$(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
serve-global:
|
|
||||||
ifdef SERVER
|
|
||||||
$(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT) -b $(SERVER)
|
|
||||||
else
|
|
||||||
$(PELICAN) -l $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT) -b 0.0.0.0
|
|
||||||
endif
|
|
||||||
|
|
||||||
|
|
||||||
devserver:
|
devserver:
|
||||||
ifdef PORT
|
venv/bin/pelican -lr content -o output -s pelicanconf.py
|
||||||
$(PELICAN) -lr $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS) -p $(PORT)
|
|
||||||
else
|
|
||||||
$(PELICAN) -lr $(INPUTDIR) -o $(OUTPUTDIR) -s $(CONFFILE) $(PELICANOPTS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
$(PELICAN) $(INPUTDIR) -o $(OUTPUTDIR) -s $(PUBLISHCONF) $(PELICANOPTS)
|
venv/bin/pelican content -o output -s publishconf.py
|
||||||
|
|
||||||
|
.PHONY: html help clean regenerate serve devserver publish
|
||||||
.PHONY: html help clean regenerate serve serve-global devserver publish
|
|
||||||
|
|
|
||||||
|
|
@ -11,11 +11,7 @@ MVP (Minimal Viable Product):
|
||||||
The smallest version of your idea that produces value for customers.
|
The smallest version of your idea that produces value for customers.
|
||||||
|
|
||||||
|
|
||||||
.. linkpeek::
|
https://www.remarkbox.com
|
||||||
uri = https://www.remarkbox.com
|
|
||||||
action = link-image
|
|
||||||
size = 280x220
|
|
||||||
style = margin-left: 25px; float: right; border-radius: 8px;
|
|
||||||
|
|
||||||
Recently I have contemplated the idea of building a screen capture
|
Recently I have contemplated the idea of building a screen capture
|
||||||
service for websites. I anticipate the service would provide
|
service for websites. I anticipate the service would provide
|
||||||
|
|
@ -27,11 +23,7 @@ After floundering on my first web application,
|
||||||
https://four2go.gumyum.com, I'm afraid to spend lots of time and energy
|
https://four2go.gumyum.com, I'm afraid to spend lots of time and energy
|
||||||
on another project if I cannot earn users or customers.
|
on another project if I cannot earn users or customers.
|
||||||
|
|
||||||
.. linkpeek::
|
https://four2go.gumyum.com
|
||||||
uri = https://four2go.gumyum.com
|
|
||||||
action = link-image
|
|
||||||
size = 280x220
|
|
||||||
style = margin-right: 25px; float: left; border-radius: 8px;
|
|
||||||
|
|
||||||
I feel the market segment for this type of service would include website
|
I feel the market segment for this type of service would include website
|
||||||
directories, live portfolio generation for website designers, and
|
directories, live portfolio generation for website designers, and
|
||||||
|
|
@ -41,11 +33,7 @@ look of their site over time.
|
||||||
As an MVP I plan to build a free live web capture application to
|
As an MVP I plan to build a free live web capture application to
|
||||||
basically provide a "Gravatar" for website addresses.
|
basically provide a "Gravatar" for website addresses.
|
||||||
|
|
||||||
.. linkpeek::
|
https://linkpeek.com
|
||||||
uri = https://linkpeek.com
|
|
||||||
action = link-image
|
|
||||||
size = 280x220
|
|
||||||
style = margin-left: 25px; float: right; border-radius: 8px;
|
|
||||||
|
|
||||||
**Do you think anyone would use my MVP or service?**
|
**Do you think anyone would use my MVP or service?**
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,7 @@ LinkPeek.com web address thumbnail api alpha release
|
||||||
|
|
||||||
|
|
|
|
||||||
|
|
||||||
.. linkpeek::
|
https://linkpeek.com
|
||||||
action = link-image
|
|
||||||
uri = https://linkpeek.com
|
|
||||||
size = 140x100
|
|
||||||
style = margin-right: 25px; float: left;
|
|
||||||
|
|
||||||
The `LinkPeek <https://linkpeek.com/>`__ API had an alpha release!
|
The `LinkPeek <https://linkpeek.com/>`__ API had an alpha release!
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -25,12 +25,7 @@ and come up with less combative idea.
|
||||||
After witnessing the Goog release of "instant previews", I knew there
|
After witnessing the Goog release of "instant previews", I knew there
|
||||||
was a market for a fast and reliable web screen shot service.
|
was a market for a fast and reliable web screen shot service.
|
||||||
|
|
||||||
.. linkpeek::
|
https://linkpeek.com
|
||||||
uri = https://linkpeek.com
|
|
||||||
size = 500x240
|
|
||||||
action = link-image
|
|
||||||
title = web page screen shot service
|
|
||||||
style = float: left; border-radius: 15px; margin-right: 15px;
|
|
||||||
|
|
||||||
So I decided to bring instant previews to anyone who needed them. I
|
So I decided to bring instant previews to anyone who needed them. I
|
||||||
wanted to build a fast, flexible, and easy to use screenshot API. After
|
wanted to build a fast, flexible, and easy to use screenshot API. After
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ You can see how the sun rises to cover the 8 panels on the front of the house an
|
||||||
SolarEdge Monitoring Dashboard also keeps track of various high level metrics. For example, I input my electricity rates with date ranges and the dashboard calculates the "lifetime revenue" of my solar system. I plan to track my ROI on this number!
|
SolarEdge Monitoring Dashboard also keeps track of various high level metrics. For example, I input my electricity rates with date ranges and the dashboard calculates the "lifetime revenue" of my solar system. I plan to track my ROI on this number!
|
||||||
|
|
||||||
.. image:: /uploads/2018/2018-03-16-solar-overview.png
|
.. image:: /uploads/2018/2018-03-16-solar-overview.png
|
||||||
|
:alt: Solar panel installation overview
|
||||||
|
|
||||||
Home Energy Monitoring
|
Home Energy Monitoring
|
||||||
=============================
|
=============================
|
||||||
|
|
|
||||||
|
|
@ -45,5 +45,6 @@ Anyways, now you may start a Unity project. ``Unity Hub`` seems to store files l
|
||||||
Thats all for now, please check back for more posts about gumyum!
|
Thats all for now, please check back for more posts about gumyum!
|
||||||
|
|
||||||
.. image:: /uploads/2019/unity-hub-gumyum.png
|
.. image:: /uploads/2019/unity-hub-gumyum.png
|
||||||
|
:alt: Unity Hub interface
|
||||||
|
|
||||||
.. |gumyum logo| image:: /uploads/2010/12/gumyumgameslogo.png
|
.. |gumyum logo| image:: /uploads/2010/12/gumyumgameslogo.png
|
||||||
|
|
|
||||||
|
|
@ -212,6 +212,4 @@ on ubuntu desktop network manager hijacks /etc/netplan but also makes it impossi
|
||||||
|
|
||||||
sudo nmcli con mod 'Wired connection 1' ipv4.dns-search "foxhop.net"
|
sudo nmcli con mod 'Wired connection 1' ipv4.dns-search "foxhop.net"
|
||||||
|
|
||||||
your only hope is this setting persists across reboots.
|
your only hope is this setting persists across reboots.
|
||||||
|
|
||||||
------
|
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ how they work
|
||||||
5. No error checking or memory leak prevention
|
5. No error checking or memory leak prevention
|
||||||
|
|
||||||
docker implementation
|
docker implementation
|
||||||
====================
|
=====================
|
||||||
|
|
||||||
.. code-block:: dockerfile
|
.. code-block:: dockerfile
|
||||||
|
|
||||||
|
|
@ -16,8 +16,8 @@ I value Truth, Freedom, Harmony, & Love. I want to find financial independence t
|
||||||
You should `contact me </contact>`_, I love conversation and often respond in a timely manner!
|
You should `contact me </contact>`_, I love conversation and often respond in a timely manner!
|
||||||
|
|
||||||
|
|
||||||
Russell’s Active Projects
|
Russell's Active Projects
|
||||||
###########################
|
=========================
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
|
|
||||||
|
|
|
||||||
8
golf.c
8
golf.c
|
|
@ -1,8 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <curl/curl.h>
|
|
||||||
struct M{char*m;size_t s;};size_t w(void*c,size_t z,size_t n,void*u){size_t r=z*n;struct M*m=u;char*p=realloc(m->m,m->s+r+1);if(!p)return 0;m->m=p;memcpy(&m->m[m->s],c,r);m->s+=r;m->m[m->s]=0;return r;}int f(char*u,char**o){CURL*h;struct M c={malloc(1),0};curl_global_init(0);h=curl_easy_init();if(h){curl_easy_setopt(h,10002,u);curl_easy_setopt(h,20011,w);curl_easy_setopt(h,10001,&c);curl_easy_perform(h);curl_easy_cleanup(h);}curl_global_cleanup();*o=c.m;return 1;}void s(int k,char*r){char b[256];sprintf(b,"HTTP/1.1 200 OK\r\nContent-Length: %zu\r\n\r\n%s",strlen(r),r);send(k,b,strlen(b),0);}int main(){int v=socket(2,1,0),c;struct sockaddr_in a={2,htons(31337),0};bind(v,(void*)&a,16);listen(v,10);while(1){c=accept(v,0,0);char b[4096],*q,*t,*d;recv(c,b,4095,0);q=strchr(b,'?');if(q&&(t=strstr(q,"target="))&&(q=strstr(q,"keyword="))){char*p;if((p=strchr(t+7,'&')))*(p)=0;else if((p=strchr(t+7,' ')))*(p)=0;if((p=strchr(q+8,'&')))*(p)=0;else if((p=strchr(q+8,' ')))*(p)=0;if(f(t+7,&d))s(c,strstr(d,q+8)?"true":"false");else s(c,"false");free(d);}else s(c,"false");close(c);}}
|
|
||||||
5
golf.py
5
golf.py
|
|
@ -1,5 +0,0 @@
|
||||||
#!/usr/bin/env python3
|
|
||||||
import http.server as h,urllib.request as u,urllib.parse as p
|
|
||||||
class S(h.BaseHTTPRequestHandler):
|
|
||||||
def do_GET(s):q=dict(p.parse_qsl(p.urlparse(s.path).query));s.send_response(200);s.end_headers();s.wfile.write(str(q.get('keyword','')in u.urlopen(q.get('target','')).read().decode()).lower().encode())
|
|
||||||
h.HTTPServer(('',31337),S).serve_forever()
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
pelican
|
pelican
|
||||||
ago
|
ago
|
||||||
rst2pdf
|
rst2pdf
|
||||||
|
markdown
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue