feat: custom lang highlight, images dir, width bump, first post

- Wire up Ergon and ArchASM custom highlight.js languages
- Serve /content/images/ for post image embeds
- Blog width 820px -> 1040px to match landing page
- First real blog post: "Why make a blog?"

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>
This commit is contained in:
2026-06-24 16:22:37 +03:00
parent a2ed073569
commit 723fc7deb8
6 changed files with 212 additions and 1 deletions

View File

@@ -18,6 +18,8 @@ const pageTpl = `<!DOCTYPE html>
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;600&family=Inter:wght@300;500;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="/src/thirdparty/highlight/default.min.css">
<script src="/src/thirdparty/highlight/highlight.min.js"></script>
<script src="/src/lang/ergon.js"></script>
<script src="/src/lang/archasm.js"></script>
<style>
:root {
--bg: #05030a;
@@ -35,7 +37,7 @@ const pageTpl = `<!DOCTYPE html>
font-family: "Inter", system-ui, sans-serif;
display: flex; justify-content: center;
}
.wrap { position: relative; z-index: 1; width: 100%; max-width: 820px; padding: 32px 20px 40px; }
.wrap { position: relative; z-index: 1; width: 100%; max-width: 1040px; padding: 32px 20px 40px; }
header {
display: flex; justify-content: space-between; align-items: center;
gap: 24px; padding: 18px 22px; border-radius: 18px;

60
content/posts/blog-why.md Normal file
View File

@@ -0,0 +1,60 @@
# Why make a blog?
2026-06-24
### Not a scientist
There are ways for people working in software to influence the world, get their thoughts and work to do something other than take up drive space:
1. Make OSS
2. Make a product
3. Become a YouTuber
4. Publish research papers
5. Get a job
Now, that list sounds fun, doesn't it?
#### So why not?
---
There are contentions about points 1 and 2, that I will discuss a little bit later.
**YouTuber**? That's fun, that's engaging. Do people like watching someone rant for many minutes instead of reading text at their own pace? Someone, probably.
But: YouTube requires schedules (hell), script-to-finished-video pipeline (suffering) and a subject matter that has a level of refinement high enough to warrant visualization throughout (despair).
**I am no researcher.** Well, from academic perspective. I do research all the time, and it's not about earth's flatness. But academic resources, peers to review things, and actual discipline and time to make a full-fledged paper are things yours truly, regrettably, lacks. For now.
Science is what I crave. But becoming a researcher is... Well, university/institute path is in the works, let's say.
**No job for now.** Apparently back-end engineering is now a collection of rites and incantations with a chance of passing at around single-digit percent per interview, if you even get one.
This leaves me with the dumb, but time-tested format of having a blog.
And - a good excuse to make the website an actual website instead of a static html placeholder page.
I like discussion. It's important to get out of modern echo chambers, especially the LLM-powered ones.
You can find me [@pierre:chaosmith.systems](matrix:u/@pierre:chaosmith.systems)
If any necessity arises, I will create a Space there. Or a group chat. Not sure what human group communication is like nowadays.
---
---
```ergon
BEGIN_TICK 1
LET Blog = CREATE NODE Outlet
SET NODE Blog.author = "Pierre De Lancre"
SET NODE Blog.name = "Chaosmith Systems"
LET Pierre = CREATE NODE Human
SET NODE Pierre.name = "G[REDACTED] G[REDACTED]"
SET NODE Pierre.alias = "Pierre De Lancre"
SET NODE Pierre.birthYear = 2000
LET Bond = CREATE EDGE Authorship WITH Pierre Blog
SET Bond.dateStart = 1782305654
SET Bond.reason = "Discussion"
END_TICK
```

View File

@@ -5,4 +5,5 @@ services:
- "8993:8000"
volumes:
- ./content/posts:/app/content/posts
- ./content/images:/app/content/images
restart: unless-stopped

View File

@@ -16,6 +16,7 @@ func main() {
http.ServeFile(w, r, "ABSTRACTS.png")
})
mux.Handle("/src/", http.StripPrefix("/src/", http.FileServer(http.Dir("src"))))
mux.Handle("/content/images/", http.StripPrefix("/content/images/", http.FileServer(http.Dir("content/images"))))
if err := blog.RegisterRoutes(mux, "content/posts"); err != nil {
log.Fatalf("blog: %v", err)

76
src/lang/archasm.js Normal file
View File

@@ -0,0 +1,76 @@
hljs.registerLanguage('archasm', function(hljs) {
return {
name: 'ArchASM',
aliases: ['archasm'],
keywords: {
keyword: `
NOP HALT
PRINT PRINT_TOP
JMP JZ JNZ
ENTER LEAVE LGET LSET
BEGIN_TICK END_TICK
SAVE_GRID LOAD_GRID LOAD_ONT
PUSH_INT PUSH_FLOAT PUSH_BOOL PUSH_SYM
PACK_VALUE
UNPACK_VALUE_INT UNPACK_VALUE_FLOAT
UNPACK_VALUE_BOOL UNPACK_VALUE_SYM
IADD ISUB ADD SUB MUL DIV IMUL IDIV
EQ LT NOT
SWAP OVER ROT NROT DUP2 NIP TUCK
POP DUP
CREATE_NODE CREATE_EDGE
DELETE_NODE DELETE_EDGE
SET_NODE_PROPERTY GET_NODE_PROPERTY
UNSET_NODE_PROPERTY
SET_EDGE_PROPERTY GET_EDGE_PROPERTY
UNSET_EDGE_PROPERTY
ADD_INCIDENT_NODE REMOVE_INCIDENT_NODE
SET_INCIDENCE
FIND_INCIDENTS
GET_NODE_TYPE GET_EDGE_TYPE
GET_EDGE_ARITY GET_EDGE_NODE_AT
TRY_GET_NODE_PROPERTY
TRY_GET_EDGE_PROPERTY
GET_TIMELINE GET_ORIGIN_TICK
IS_MAIN GET_CURRENT_TICK
PUSH_VIEW POP_VIEW
EMIT_CLAIM EMIT_EDGE_CLAIM
CALL RET
ITER_EDGES_BY_TYPE
ITER_NODES_BY_TYPE
ITER_INCIDENT_EDGES
ITER_PROP_EQ
ITER_NEXT
ITER_EDGE_ROLE_NODES
`,
type: 'int float bool string'
},
contains: [
{
scope: 'comment',
begin: /\bNOTE\b/,
end: '$'
},
{
scope: 'meta',
begin: /^(SYMBOL)\b/
},
{
scope: 'symbol',
match: /^[A-Za-z_][A-Za-z0-9_]*:/
},
hljs.QUOTE_STRING_MODE,
hljs.NUMBER_MODE,
{
scope: 'operator',
match: /=/
}
]
};
});

71
src/lang/ergon.js Normal file
View File

@@ -0,0 +1,71 @@
hljs.registerLanguage('ergon', function(hljs) {
return {
name: 'Ergon',
aliases: ['ergon', 'agont'],
keywords: {
keyword: `
DECLARE TYPE EDGE RULE FUNCTION PROPERTY AXIOMATIC
PARAMS RETURNS
BEGIN_TICK END_TICK
LET SET CREATE PRINT
LOOP OVER DO END
IF THEN ELSE
RETURN CALL
SAVE GRID LOAD VM LOCAL
BRANCH SWITCH MAIN EXPORT PRUNE LIST DIFF
FIND GET ADD REMOVE
CONDITION EXPECTS CHANGED UNLESS AS
FOR INFER
FIELD REQUIRED OPTIONAL ROLE
WHERE
IS OF IN TO FROM WITH
INCIDENT TARGET BASELINE
AT TICK
PROP BY ID
NODE NODES EDGE EDGES
WEIGHT PRIORITY
LOGICAL STATEFUL WEIGHTED
AND OR NOT
`,
type: 'string int float bool void',
literal: 'TRUE FALSE',
built_in: '@timeline @is_main @origin_tick @current_tick'
},
contains: [
{
scope: 'comment',
begin: /\bNOTE\b/,
end: '$'
},
hljs.QUOTE_STRING_MODE,
hljs.NUMBER_MODE,
{
scope: 'variable',
match: /\b[A-Z][A-Z0-9_]*\b/
},
{
scope: 'title',
match: /\b[a-z][a-zA-Z0-9_]*\b/
},
{
scope: 'built_in',
match: /@(timeline|is_main|origin_tick|current_tick)\b/
},
{
scope: 'operator',
match: /!=|<=|>=|=|<|>|\+|-|\*|\//
}
]
};
});