
Security Fundamentals
Turtles, Clams, and Cyber Threat Actors: Shell Usage
The Socket Threat Research Team uncovers how threat actors weaponize shell techniques across npm, PyPI, and Go ecosystems to maintain persistence and exfiltrate data.
Burgher is a static site generator that makes it easy to create photo galleries from your existing folder structure. Instead of requiring you to reorganize your photos or maintain a separate structure, burgher works with how you already organize your photos.
Key features:
Let's look at example structure of the gallery files:
.
├── Baltics
│ ├── Helsinki
│ │ ├── X-T5-2023-05-29 09.31.13.jpg
│ │ ├── X-T5-2023-05-30 19.24.16.jpg
│ │ ├── _Ruoholahti
│ │ │ ├── X-T5-2023-05-30 11.12.54.jpg
│ │ ├── _Suomenlinna
│ │ │ ├── X-T5-2023-05-29 11.05.40.jpg
│ │ │ └── X-T5-2023-05-29 11.54.06.jpg
│ │ └── info.md
│ ├── Lithuania
│ │ ├── _Countryside
│ │ │ ├── X-T5-2023-05-24 09.11.12.jpg
│ │ │ └── X-T5-2023-05-24 14.49.27.jpg
│ │ ├── _Druskininkai
│ │ │ └── X-T5-2023-05-22 08.43.41.jpg
│ │ ├── _Spit
│ │ │ ├── main.jpg
│ │ │ └── info.md
│ │ └── _Vilnius
│ │ └── main.jpg
│ └── Riga
└ ...
Features:
main.jpg
is used as a cover image for the albuminfo.md
is used to provide description about the album_
prefixed folders are treated as embedded albums - they get rendered as part of the main album but they can have their own info.md
and cover image and they also get link on their own..hidden
empty file will not be indexed in the main page and will only be accessible with the main link pip install burgher
from pathlib import Path
from burgher.feed import Feed
from burgher import FrontMatterNode, StaticFolderNode, Gallery
from burgher import App
# this is the list of directories that will trigger rebuild of all template nodes
# if any file changes.
check_paths = [
Path("templates/"),
Path("static/"),
]
out = Path("../build/")
PHOTO_DIR = Path("/home/user/photos/public/")
app = App(
name="appname",
template_dir="/templates",
output_path=out,
domain="http://example.com",
check_paths=check_paths,
# context db is json file that persists between builds
# it is used to cache metadata for photos and other content to improve build performance
context_db_path=Path("../example.json"),
)
app.register(
# register directory with markdown files that will be rendered into html
pages=FrontMatterNode.from_folder(
"pages",
template_name="page.html"
),
# static files - these will be simply copied
static=StaticFolderNode("static"),
# register gallery, here we specify output file, so that the gallery is a root of the site
gallery=Gallery(PHOTO_DIR,
output_file="index.html",
source_file="index.md"
),
rss=Feed(root_gallery=PHOTO_DIR),
)
# generate the site
app.generate()
and generate website via
python app.py
Node
- Base node class that others inherit fromStaticNode
- Copies a single file without modificationStaticFolderNode
- Copies an entire folder structure without modificationBlogRoot
- Creates blog structure with listing index and page notesTemplateNode
- Renders a Jinja2 template with contextMarkdownNode
- Renders markdown content into HTMLFrontMatterNode
- Markdown with YAML frontmatter for metadataGallery
- Root node for the galleryAlbum
- Folder with pictures or other albumsPicture
- Handles image files with EXIF data and metadataThumb
- Creates thumbnail versions of imagesFeed
- Generates RSS/Atom feedsStats
- Generates statistics pagesEach node type can be configured with various options and composed together to build complex static sites. Nodes can have parent-child relationships and share context data.
The node system creates a graph that mirrors your site's file organization:
Node
corresponds to a file or directory in your siteThe context database is used to cache metadata for photos and other content to improve build performance:
When building the site:
The context caching provides significant performance benefits:
The context DB is stored as a JSON file that persists between builds. This allows incremental builds to be much faster than regenerating all metadata each time.
For blogs there is a blog root node:
from pathlib import Path
from burgher import App, BlogRoot, StaticFolderNode
blog_folder = Path('blog_entries')
check_paths = [
Path("./templates/"),
Path("./static/"),
]
blog = App(...) # as before
blog.register(
index=BlogRoot(source_file=blog_folder / "index.md", post_folder=blog_folder / "posts"),
)
blog.generate()
This is the structure expected for the blog:
.
├── index.md
└── posts
├── entry1.assets
│ └── 2021-03-08 12.27.28.jpg
├── entry1.md
└── xps-setup.md
The index has special markdown attributes:
---
title: "Blog title"
title_post: "Blog"
go_back_title: "blog"
---
# Blog
Some info about the blog
FAQs
Burgher - a static site generator focused on galleries
We found that burgher demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security Fundamentals
The Socket Threat Research Team uncovers how threat actors weaponize shell techniques across npm, PyPI, and Go ecosystems to maintain persistence and exfiltrate data.
Security News
At VulnCon 2025, NIST scrapped its NVD consortium plans, admitted it can't keep up with CVEs, and outlined automation efforts amid a mounting backlog.
Product
We redesigned our GitHub PR comments to deliver clear, actionable security insights without adding noise to your workflow.