~gitpocket/gitpocket

feat(web): pocket logo and a configurable site name in the header

commit
166b9f360ead7fbb7d71ae5cf3697464af63b19a browse tree
parent
e4187bfa1c0a55da0f6ce940e185ea72e3e5d85e
author
james <j@cpl0.zip>
signature
Verified ~james signed with a key registered by ~james
date
2026-11-13 10:08 UTC

5 files changed, +11 −7

README.md modified

@@ -70,7 +70,7 @@ The `keys` command runs as root and opens the database read only and answers ssh
7070 sudo -u git gitpocket -root /srv/gitpocket invite
7171 ```
7272
73-If you would rather let anyone sign up then `serve -open` skips the invite step entirely. `gitpocket user <name>` creates an account from the command line with the password read from stdin, and `-ssh-user` changes the account name that appears in clone URLs if you did not call yours `git`.
73+If you would rather let anyone sign up then `serve -open` skips the invite step entirely. `gitpocket user <name>` creates an account from the command line with the password read from stdin, and `-ssh-user` changes the account name that appears in clone URLs if you did not call yours `git`. The header shows `-name`, which defaults to gitpocket, while `-host` stays the hostname used in clone URLs and feeds.
7474
7575 Mail is configured in `smtp.json` under the root directory and is read once at startup. Plain SMTP takes `host`, `port`, `user`, `password`, `from` and `starttls`, but many VPS providers block every outbound submission port, so `api` and `key` post each message as JSON to a Resend compatible HTTPS endpoint instead.
7676

main.go modified

@@ -17,7 +17,7 @@ func main() {
1717 flag.Usage = func() {
1818 fmt.Fprintln(os.Stderr, `usage: gitpocket [-root dir] command
1919
20- serve [-listen addr] [-host name] [-open] [-ssh-user name] run the web server
20+ serve [-listen addr] [-host name] [-name text] [-open] [-ssh-user name] run the web server
2121 keys user home type key sshd AuthorizedKeysCommand
2222 shell user forced command for ssh git access
2323 invite print a single use registration code
@@ -173,13 +173,14 @@ func serve(root string, args []string) {
173173 fs := flag.NewFlagSet("serve", flag.ExitOnError)
174174 listen := fs.String("listen", "127.0.0.1:3200", "address to listen on")
175175 host := fs.String("host", "localhost", "public hostname used in clone urls")
176+ name := fs.String("name", "gitpocket", "site name shown in the header")
176177 open := fs.Bool("open", false, "allow registration without an invite")
177178 sshUser := fs.String("ssh-user", "git", "unix user that serves git over ssh, shown in clone urls")
178179 fs.Parse(args)
179180 store := mustStore(root)
180181 srv := &http.Server{
181182 Addr: *listen,
182- Handler: newServer(store, root, *host, *open, *sshUser).handler(),
183+ Handler: newServer(store, root, *host, *name, *open, *sshUser).handler(),
183184 ReadHeaderTimeout: 10 * time.Second,
184185 }
185186 log.Printf("gitpocket listening on %s for %s", *listen, *host)

static/style.css modified

@@ -292,7 +292,7 @@ a.label{opacity:.75}a.label.on,a.label:hover{opacity:1;text-decoration:none}
292292 .linkbutton{background:none;border:0;padding:0;font:inherit;color:var(--muted);cursor:pointer}
293293 .linkbutton:hover{color:var(--del);text-decoration:underline}
294294 nav.site .brand{display:inline-flex;align-items:center;gap:.4rem}
295-.logo{width:1.45rem;height:1.45rem;fill:var(--fg)}.logo .wave{fill:none;stroke:var(--fg);stroke-width:2;stroke-linecap:round}
295+.logo{width:1.75rem;height:1.75rem;fill:#fff}.logo .pocket{fill:var(--fg)}.logo .branch{fill:none;stroke:#fff;stroke-width:1.5;stroke-linecap:round}
296296 .landing{margin:0}
297297 .landing>p{margin:.2rem 0 1rem}
298298 .landing a.arrow{text-decoration:underline}

templates/layout.html modified

@@ -17,7 +17,7 @@
1717 <body{{if .Fluid}} class="fluid"{{end}}>
1818 <header>
1919 <nav class="site">
20-<a class="brand" href="/"><svg class="logo" viewBox="0 0 24 24" aria-hidden="true"><path class="wave" d="M3 6.5c1.5-1.6 3-1.6 4.5 0s3 1.6 4.5 0 3-1.6 4.5 0 3 1.6 4.5 0"/><path d="M2.5 10.5h19a9.5 9.5 0 0 1-19 0z"/></svg>{{.Host}}</a>
20+<a class="brand" href="/"><svg class="logo" viewBox="0 0 24 24" aria-hidden="true"><path class="pocket" d="M3.5 3.5h17v9.5c0 4.4-3.8 8-8.5 8s-8.5-3.6-8.5-8z"/><circle cx="9" cy="9" r="1.6"/><circle cx="9" cy="16" r="1.6"/><circle cx="15" cy="11.5" r="1.6"/><path class="branch" d="M9 10.6v3.8M15 13.1c0 1.6-2.2 2.2-4.4 2.6"/></svg>{{.Name}}</a>
2121 <a href="/projects">projects</a>
2222 <span class="spacer"></span>
2323 {{if .User}}<span>Logged in as <a href="/~{{.User.Name}}">~{{.User.Name}}</a> — <form method="post" action="/logout"><button>Log out</button></form></span>{{else}}<span class="auth"><a href="/login">Log in</a> — <a href="/register">Register</a></span>{{end}}

web.go modified

@@ -44,6 +44,7 @@ type Server struct {
4444 store *Store
4545 root string
4646 host string
47+ name string
4748 sshUser string
4849 open bool
4950 pages map[string]*template.Template
@@ -57,14 +58,15 @@ type page struct {
5758 Title string
5859 User *User
5960 Host string
61+ Name string
6062 SSHUser string
6163 Error string
6264 Math bool
6365 Data any
6466 }
6567
66-func newServer(store *Store, root, host string, open bool, sshUser string) *Server {
67- s := &Server{store: store, root: root, host: host, open: open, sshUser: sshUser, mailer: loadMailer(root), pages: map[string]*template.Template{}, limiter: newLimiter(10, 5*time.Minute)}
68+func newServer(store *Store, root, host, name string, open bool, sshUser string) *Server {
69+ s := &Server{store: store, root: root, host: host, name: name, open: open, sshUser: sshUser, mailer: loadMailer(root), pages: map[string]*template.Template{}, limiter: newLimiter(10, 5*time.Minute)}
6870 funcs := template.FuncMap{
6971 "short": func(h string) string {
7072 if len(h) > 10 {
@@ -135,6 +137,7 @@ func newServer(store *Store, root, host string, open bool, sshUser string) *Serv
135137
136138 func (s *Server) render(w http.ResponseWriter, r *http.Request, name string, p page) {
137139 p.Host = s.host
140+ p.Name = s.name
138141 p.SSHUser = s.sshUser
139142 p.Version = s.version
140143 if d, ok := p.Data.(map[string]any); ok && d["File"] == true {