<feed xmlns='http://www.w3.org/2005/Atom'>
<title>nebbet.no/internal/admin/server.go, branch main</title>
<subtitle>[no description]</subtitle>
<id>https://git.ivar.systems/nebbet.no/atom?h=main</id>
<link rel='self' href='https://git.ivar.systems/nebbet.no/atom?h=main'/>
<link rel='alternate' type='text/html' href='https://git.ivar.systems/nebbet.no/'/>
<updated>2026-04-04T14:51:05Z</updated>
<entry>
<title>feat: wire MediaHandler routes and govips lifecycle</title>
<updated>2026-04-04T14:51:05Z</updated>
<author>
<name>ivar</name>
<email>i@oiee.no</email>
</author>
<published>2026-04-04T14:51:05Z</published>
<link rel='alternate' type='text/html' href='https://git.ivar.systems/nebbet.no/commit/?id=87deaec8c519ee477439922f1cbecb8c90cbe5af'/>
<id>urn:sha1:87deaec8c519ee477439922f1cbecb8c90cbe5af</id>
<content type='text'>
- Add RegisterUploadRoute to admin Server (POST /admin/upload/image, auth-protected)
- Import govips/v2 and internal/media in main.go
- Replace static /media/ file handler with mediaSrv.HandleServe for on-the-fly image conversion
- Call vips.Startup/Shutdown around server lifetime

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>fix: make slug rename and content update atomic via RenameAndUpsertPost</title>
<updated>2026-04-04T14:36:18Z</updated>
<author>
<name>ivar</name>
<email>i@oiee.no</email>
</author>
<published>2026-04-04T14:36:18Z</published>
<link rel='alternate' type='text/html' href='https://git.ivar.systems/nebbet.no/commit/?id=0d8f53520a2143b22e2246ab1ec25e0860e90dad'/>
<id>urn:sha1:0d8f53520a2143b22e2246ab1ec25e0860e90dad</id>
<content type='text'>
Previously RenamePost + UpsertPost were two separate DB calls; a failure
between them left the post at the new slug with stale content. The new
RenameAndUpsertPost method does both in a single transaction.

Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>fix: remove spurious os.IsNotExist check on DB error in handleDelete</title>
<updated>2026-04-04T14:33:49Z</updated>
<author>
<name>ivar</name>
<email>i@oiee.no</email>
</author>
<published>2026-04-04T14:33:49Z</published>
<link rel='alternate' type='text/html' href='https://git.ivar.systems/nebbet.no/commit/?id=8a093aacd162d3fd9f142b53aab9edfa061fd66a'/>
<id>urn:sha1:8a093aacd162d3fd9f142b53aab9edfa061fd66a</id>
<content type='text'>
</content>
</entry>
<entry>
<title>feat: support slug editing and rename in admin UI with redirect and cache invalidation</title>
<updated>2026-04-04T14:31:32Z</updated>
<author>
<name>ivar</name>
<email>i@oiee.no</email>
</author>
<published>2026-04-04T14:31:32Z</published>
<link rel='alternate' type='text/html' href='https://git.ivar.systems/nebbet.no/commit/?id=275d6fce19a33b68abb22ed41ded58fa65df1834'/>
<id>urn:sha1:275d6fce19a33b68abb22ed41ded58fa65df1834</id>
<content type='text'>
Co-Authored-By: Claude Sonnet 4.6 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Fix: set HTML template on Gin engine for template rendering</title>
<updated>2026-04-03T12:47:45Z</updated>
<author>
<name>ivar</name>
<email>i@oiee.no</email>
</author>
<published>2026-04-03T12:47:45Z</published>
<link rel='alternate' type='text/html' href='https://git.ivar.systems/nebbet.no/commit/?id=49b5af2bded29e559b3710dc6e172f979321fbd0'/>
<id>urn:sha1:49b5af2bded29e559b3710dc6e172f979321fbd0</id>
<content type='text'>
The embedded templates were being parsed but not registered with the Gin
engine's HTMLRender, causing 500 errors on admin UI requests. Now
SetHTMLTemplate is called to register the parsed template set so
Gin can render them properly.

Verified:
- Build succeeds with no errors
- Binary contains embedded template strings
- Admin UI pages load and render correctly
- All template files (base, list, form, error) work as expected
</content>
</entry>
<entry>
<title>feat: embed admin templates into binary with //go:embed</title>
<updated>2026-04-03T12:46:05Z</updated>
<author>
<name>ivar</name>
<email>i@oiee.no</email>
</author>
<published>2026-04-03T12:46:05Z</published>
<link rel='alternate' type='text/html' href='https://git.ivar.systems/nebbet.no/commit/?id=a46309ac64261814d931f538fad373ea8a4f0e95'/>
<id>urn:sha1:a46309ac64261814d931f538fad373ea8a4f0e95</id>
<content type='text'>
Move admin templates from templates/admin/*.html to internal/admin/templates/*.html
and embed them using //go:embed directive. This removes the runtime dependency on
having template files on disk, allowing the templates to be compiled into the binary.

Changes:
- Add embed import and //go:embed directive for templates
- Change ParseGlob() to ParseFS() to load from embedded filesystem
- Copy templates to internal/admin/templates/ for embedding

Co-Authored-By: Claude Haiku 4.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>refactor: convert admin handlers to Gin context-based signatures</title>
<updated>2026-04-03T12:22:23Z</updated>
<author>
<name>ivar</name>
<email>i@oiee.no</email>
</author>
<published>2026-04-03T12:22:23Z</published>
<link rel='alternate' type='text/html' href='https://git.ivar.systems/nebbet.no/commit/?id=33310be68544d3381ac6e9899790f4a106e17e8f'/>
<id>urn:sha1:33310be68544d3381ac6e9899790f4a106e17e8f</id>
<content type='text'>
- Remove old ServeHTTP method (no longer needed with Gin routing)
- Update all 6 handler methods to use *gin.Context instead of http.ResponseWriter, *http.Request
- Convert handler signatures: handleList, handleNew, handleNewPost, handleEdit, handleDelete
- Remove render() helper (use c.HTML() directly)
- Update renderError() to accept gin.Context instead of http.ResponseWriter
- Update postFromForm() to extract form data from gin.Context using c.PostForm()
- Update main.go to use adminSrv.NewServer() and adminSrv.Engine()
- All handlers now use Gin methods: c.HTML(), c.PostForm(), c.Param(), c.Redirect()
- Path parameters now extracted via c.Param("slug") instead of function arguments
- HTTP status codes and error handling fully migrated to Gin patterns

Build verified: go build ./cmd/nebbet succeeds

Co-Authored-By: Claude Haiku 4.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>refactor: implement auth middleware for Gin</title>
<updated>2026-04-03T12:19:55Z</updated>
<author>
<name>ivar</name>
<email>i@oiee.no</email>
</author>
<published>2026-04-03T12:19:55Z</published>
<link rel='alternate' type='text/html' href='https://git.ivar.systems/nebbet.no/commit/?id=a8914a8f18c345e934bce93b37845a9dfe0ad73e'/>
<id>urn:sha1:a8914a8f18c345e934bce93b37845a9dfe0ad73e</id>
<content type='text'>
Replace the old checkAuth() method with a Gin middleware function that validates
Basic Auth credentials. The authMiddleware() now handles authentication at the
middleware level rather than per-handler, supporting graceful degradation when
no auth file is configured.

The middleware:
- Skips auth if AuthFile is empty or doesn't exist
- Extracts Basic Auth credentials from the request
- Verifies credentials using the auth package
- Returns 401 with WWW-Authenticate header on failure
- Calls c.Next() to pass control to handlers on success

Co-Authored-By: Claude Haiku 4.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>refactor: add Gin routing infrastructure with NewServer constructor</title>
<updated>2026-04-03T12:18:30Z</updated>
<author>
<name>ivar</name>
<email>i@oiee.no</email>
</author>
<published>2026-04-03T12:18:30Z</published>
<link rel='alternate' type='text/html' href='https://git.ivar.systems/nebbet.no/commit/?id=6797cafba0059558da475426f9ca69299dd956b5'/>
<id>urn:sha1:6797cafba0059558da475426f9ca69299dd956b5</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Fault if not able to authenticate user</title>
<updated>2026-03-31T16:31:06Z</updated>
<author>
<name>ivar</name>
<email>i@oiee.no</email>
</author>
<published>2026-03-31T16:31:06Z</published>
<link rel='alternate' type='text/html' href='https://git.ivar.systems/nebbet.no/commit/?id=1f799efb15a80f5aedee975fe8b4af5415b1fd78'/>
<id>urn:sha1:1f799efb15a80f5aedee975fe8b4af5415b1fd78</id>
<content type='text'>
</content>
</entry>
</feed>
