diff --git a/.gitignore b/.gitignore
index a19ee22c..0cf5fe15 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,5 @@ sites/.wrangler/
genjwks.out
/nix/vm-data
blog/build/
+build/
+.wrangler/
diff --git a/.tangled/workflows/deploy-blog.yml b/.tangled/workflows/deploy-blog.yml
index fab9681e..21915336 100644
--- a/.tangled/workflows/deploy-blog.yml
+++ b/.tangled/workflows/deploy-blog.yml
@@ -16,14 +16,14 @@ steps:
mkdir -p appview/pages/static
touch appview/pages/static/x
- - name: build blog cmd
- command: |
- go build -o blog.out ./cmd/blog
-
- name: generate css
command: |
tailwindcss -i input.css -o appview/pages/static/tw.css
+ - name: build blog cmd
+ command: |
+ go build -o blog.out ./cmd/blog
+
- name: build static site
command: |
./blog.out build
diff --git a/appview/pages/funcmap.go b/appview/pages/funcmap.go
index 1ffe5841..73caa97a 100644
--- a/appview/pages/funcmap.go
+++ b/appview/pages/funcmap.go
@@ -521,6 +521,9 @@ func (p *Pages) AvatarUrl(actor, size string) string {
}
secret := p.avatar.SharedSecret
+ if secret == "" {
+ return ""
+ }
h := hmac.New(sha256.New, []byte(secret))
h.Write([]byte(did))
signature := hex.EncodeToString(h.Sum(nil))
diff --git a/blog/templates/index.html b/blog/templates/index.html
index b2c84f08..a41c556f 100644
--- a/blog/templates/index.html
+++ b/blog/templates/index.html
@@ -37,11 +37,14 @@
+ {{ $hasAvatar := false }}{{ range $authors }}{{ if tinyAvatar .Handle }}{{ $hasAvatar = true }}{{ end }}{{ end }}
+ {{ if $hasAvatar }}
{{ range $authors }}
-

+ {{ $av := tinyAvatar .Handle }}{{ if $av }}

{{ end }}
{{ end }}
+ {{ end }}
{{ range $i, $a := $authors }}
{{ if gt $i 0 }}&{{ end }}
diff --git a/cmd/blog/main.go b/cmd/blog/main.go
index ebb4e020..867386ef 100644
--- a/cmd/blog/main.go
+++ b/cmd/blog/main.go
@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"io"
+ "io/fs"
"log/slog"
"net/http"
"os"
@@ -84,9 +85,7 @@ func runBuild(ctx context.Context, logger *slog.Logger) error {
return fmt.Errorf("rendering index: %w", err)
}
- // posts — each at build//index.html directly (no /blog/ prefix)
for _, post := range posts {
- post := post
postDir := filepath.Join(outDir, post.Meta.Slug)
if err := os.MkdirAll(postDir, 0755); err != nil {
return err
@@ -98,7 +97,7 @@ func runBuild(ctx context.Context, logger *slog.Logger) error {
}
}
- // atom feed — at build/feed.xml
+ // atom feed
baseURL := "https://blog.tangled.org"
atom, err := blog.AtomFeed(posts, baseURL)
if err != nil {
@@ -108,10 +107,38 @@ func runBuild(ctx context.Context, logger *slog.Logger) error {
return fmt.Errorf("writing feed: %w", err)
}
+ // copy embedded static assets into build/static/ so Cloudflare Pages
+ // can serve them from the same origin as the built HTML
+ staticSrc, err := fs.Sub(pages.Files, "static")
+ if err != nil {
+ return fmt.Errorf("accessing embedded static dir: %w", err)
+ }
+ if err := copyFS(staticSrc, filepath.Join(outDir, "static")); err != nil {
+ return fmt.Errorf("copying static assets: %w", err)
+ }
+
logger.Info("build complete", "dir", outDir)
return nil
}
+// copyFS copies all files from src into destDir, preserving directory structure.
+func copyFS(src fs.FS, destDir string) error {
+ return fs.WalkDir(src, ".", func(path string, d fs.DirEntry, err error) error {
+ if err != nil {
+ return err
+ }
+ dest := filepath.Join(destDir, path)
+ if d.IsDir() {
+ return os.MkdirAll(dest, 0755)
+ }
+ data, err := fs.ReadFile(src, path)
+ if err != nil {
+ return err
+ }
+ return os.WriteFile(dest, data, 0644)
+ })
+}
+
func runServe(ctx context.Context, logger *slog.Logger, addr string) error {
cfg, err := config.LoadConfig(ctx)
if err != nil {