Help us shape the future of Go! Take the 2026 Go Developer Survey

gallery

package
v0.1.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Nov 1, 2026 License: MIT Imports: 22 Imported by: 0

README

Photo albums: a title, a Markdown description and a cover per album, with images picked from the media library.

Use one instance per gallery, for example photos for event pictures and work for a portfolio. Each has its own albums, admin section and templates. Captions and alt text are not kept in the album: they are the images' own title and alt text in the media library, per language.

Add it to the site

app.Use(
    gallery.Module("photos", "Photos"),
)

The key (photos) is the instance's name in URLs and templates and must be unique on the site. The title (Photos) is what editors see in the admin navigation and the page editor.

Place it on a page

In the admin, open a page and choose the instance under Shows on this page. The page then serves the albums below its own address; with the page at /photos:

Address Template Shows
/photos photos/list.gohtml the published albums, in the order set in the admin
/photos/<slug> photos/album.gohtml one album with its images

Templates are looked up by instance key first, then by module type, so gallery/album.gohtml serves every Gallery instance that has no design of its own. Generate starting points with every field of the data:

task templates -- photos

The list gets a gallery.ListView. Its albums have a CoverURL (the cover, or the first image when no cover is set) and an ImageCount, but no Images; those are only loaded on the album page. A minimal album page:

{{/* @dot github.com/donseba/go-webthings/modules/gallery.Album */}}
<h1>{{.Title}}</h1>
{{.Description}}

{{range .Images}}
    <figure>
        <a href="{{.LargeURL}}">
            <img src="{{.URL}}" srcset="{{.Srcset}}" sizes="(max-width: 40rem) 100vw, 50vw" alt="{{.Alt}}" width="{{.Width}}" height="{{.Height}}" loading="lazy">
        </a>
        {{with .Title}}<figcaption>{{.}}</figcaption>{{end}}
    </figure>
{{end}}

URL is the image as pages show it, at most 1600 pixels wide, Srcset lists smaller copies, and Width and Height are the size of URL. LargeURL is a copy at most 2400 pixels wide, for the image on its own, such as in a lightbox, and OriginalURL is the uploaded file, for downloads. An album's cover comes the same way, as CoverURL, CoverSrcset, CoverWidth, CoverHeight and CoverOriginalURL, without a large copy. image and srcset make other sizes from these addresses, such as a square thumbnail: {{image .URL "400x400 crop"}}.

An album appears in each language it has a title and slug for. Albums are only reachable while the instance is placed on a page.

Show albums anywhere

albums returns the published albums in the current language, without their images. album returns one album with its images, or nothing, for a carousel or a strip of photos on another page. Its slug may be the album's slug in any language.

{{range albums "photos"}}
    <a href="{{.URL}}"><img src="{{image .CoverURL "300x200 crop"}}" width="300" height="200" alt=""> {{.Title}}</a>
{{end}}

{{with album "photos" "summer-fair"}}
    {{range .Images}}<img src="{{image .URL "800x500 crop"}}" width="800" height="500" alt="{{.Alt}}">{{end}}
{{end}}

Links point to the page the instance is placed on. An instance that only feeds carousels does not need a page; .URL is then empty.

Content API

While the site's content API is on (Config.API), /api/v1/<key>/albums serves the published albums as JSON, in the language of ?locale=, or the site's default language without it. With the instance photos:

Endpoint Route name Answers with
/api/v1/photos/albums api.photos.albums The published albums, in the editors' order, as a list
/api/v1/photos/albums?slug=<slug> The album with that slug
/api/v1/photos/albums/{id} api.photos.album One album, with its description and images

An album has its id, slug and title, its cover, the cover image or else the first image, as an image object, null for an album without images, its image_count, its page as url, null while the instance is on no page, api_url and updated_at. /albums/{id} adds description_html, when the album has a description, and images: the album's images in their order, each an image object with its id and title in the media library.

/albums/{id} sends a Last-Modified: the latest change of the album, of the page the instance is on and of the album's media, its cover, its images and those in its description. An album with an image that was deleted gets none, and so does every album while the instance is on no page; the lists get none either; see Caching.

Editing

Each instance has its own section in the admin (/admin/photos; /admin is the default admin path) with the list of albums.

  • An album has an optional cover image and a set of images, ticked in a list of every image in the media library, by file name. Upload new photos to the library first. Per language it has a title, a Web address, made from the title when left empty, and a Markdown description.
  • Images keep their order in the album; newly ticked images are added at the end. Image order on the overview moves an album's images up and down. An album holds at most 500 images.
  • Captions and alt text are edited in the media library. An image used by an album cannot be deleted from the library, also while the album is in the trash.
  • Albums have no drafts or revisions: saving changes the album at once, also when it is published. New albums start unpublished at the end of the list. Publish and Unpublish show or hide an album; publishing needs a title and a web address in the site's default language.
  • The move buttons on the overview set the order of the albums on the site.
  • Move to trash moves an album to the trash, where it can be restored or deleted for good. Its web addresses are free again meanwhile; restoring is refused when another album has taken one.

Editors' rights are set per instance in the groups' permission matrix.

Published albums appear in the site search by title and description, and are listed in sitemap.xml.

Links to addresses on the site in the descriptions of published albums count for Links to a page: the editor of a page lists the albums that link to it, and Pages › Broken links lists their links that lead nowhere.

The editor of a published album lists the published content that links to the album and asks before it is unpublished or moved to the trash. With the redirects module, editors who may create redirects also get Unpublish and redirect, and saving a published album with a new Web address redirects its old address to the new one; see Links to an item.

From Go

gallery.Of(app, "photos") returns the instance once the app has started:

photos := gallery.Of(app, "photos")

all, err := photos.Albums(ctx, "en")

fair, err := photos.Album(ctx, "en", "summer-fair")

While the instance is on no page in that language, both still return the albums, with an empty URL.

Store() gives write access for imports and seed data, through the same rules the admin uses. Images come from the media library:

asset, err := app.Media.Upload(ctx, "harbour.jpg", file)
if err != nil {
    return err
}

store := photos.Store()

album, err := store.Save(ctx, content.Draft[gallery.AlbumFields, gallery.AlbumText]{
    Fields: gallery.AlbumFields{
        Images: content.IDs{asset.ID},
    },
    Translations: []content.Translation[gallery.AlbumText]{
        {
            Locale: "en",
            Text: gallery.AlbumText{
                Slug:  "harbour",
                Title: "The harbour",
            },
        },
    },
})
if err != nil {
    return err
}

err = store.Publish(ctx, album.ID, "", "en")
  • Lists keeps short entries with one image each, such as services or features.
  • Banners shows hero slides and notices.
  • Events and Publishing have one image per event or post; album adds a whole album to any template.

Documentation

Overview

Package gallery shows photo albums. An album has a translated title, slug and Markdown description, an optional cover image and an ordered list of images from the media library. Captions and alt text are the images' own per-language title and alt text in the library. Add one instance per gallery, for example:

app.Use(gallery.Module("photos", "Photos"))

Mounted on a page, the module serves two templates:

  • gallery/list.gohtml at the page itself, with a ListView of the published albums (without their images).
  • gallery/album.gohtml at /{slug}, with an Album including its Images.

Album.CoverURL is the cover image, or the first image when no cover is set. Images are shown as copies at most media.ImageWidth wide with a srcset (see frontend.Frontend.Image); Image.LargeURL is a copy for a lightbox and Image.OriginalURL the uploaded file. The album form chooses the images and adds new ones at the end; "Image order" in the admin moves them up and down.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Module

func Module(key, title string) webthings.Module

Module adds a Gallery instance. key is used in URLs of the admin and must be unique on the site; title is shown in the admin and the page editor.

Types

type APIAlbum

type APIAlbum struct {
	ID    string `json:"id"`
	Slug  string `json:"slug"`
	Title string `json:"title"`
	// DescriptionHTML is the album's description as HTML (api.HTML); only
	// the album's own endpoint has it.
	DescriptionHTML string `json:"description_html,omitempty"`
	// Cover is the cover image, or the first image when the editors chose
	// none; null for an album without images.
	Cover      *api.Image `json:"cover"`
	ImageCount int        `json:"image_count"`
	// URL is the album's page, null while the gallery is on no page; APIURL
	// the album in the API.
	URL       *string   `json:"url"`
	APIURL    string    `json:"api_url"`
	UpdatedAt time.Time `json:"updated_at"`
}

APIAlbum is a published album in the content API (see package api), in the list of /api/v1/<key>/albums and, with its images, at /api/v1/<key>/albums/{id} (APIAlbumImages).

type APIAlbumImages

type APIAlbumImages struct {
	APIAlbum

	Images []APIImage `json:"images"`
}

APIAlbumImages is a published album with its images in their order, at /api/v1/<key>/albums/{id}.

type APIImage

type APIImage struct {
	ID    string `json:"id"`
	Title string `json:"title"`

	api.Image
}

APIImage is an image of an album: its media library ID, its title in the request's language and the image as pages show it (api.Image).

type Album

type Album struct {
	ID          string
	Title       string
	Description template.HTML
	// URL is the album's page, empty when the gallery is on no page.
	URL string
	// CoverURL is the cover as pages show it, at most media.ImageWidth wide;
	// CoverSrcset lists smaller copies for a srcset attribute, CoverWidth
	// and CoverHeight are the size of CoverURL and CoverOriginalURL is the
	// uploaded file. All are empty for an album without images.
	CoverURL         string
	CoverSrcset      string
	CoverOriginalURL string
	CoverWidth       int
	CoverHeight      int
	ImageCount       int
	Images           []Image
}

Album is a published album as templates see it. Images is only filled on the album page.

type AlbumFields

type AlbumFields struct {
	Cover  string      `db:"cover_id,null"`
	Images content.IDs `db:"image_ids"`
}

AlbumFields are the language-independent parts of an album.

type AlbumItem

type AlbumItem = content.Item[AlbumFields, AlbumText]

AlbumItem is an album with its translations, as the store keeps it.

type AlbumText

type AlbumText struct {
	Slug        string `db:"slug"`
	Title       string `db:"title"`
	Description string `db:"description"`
}

AlbumText is an album in one language. Description is Markdown.

type Image

type Image struct {
	ID string
	// URL is the image as pages show it, at most media.ImageWidth wide, and
	// Srcset smaller copies for a srcset attribute; Width and Height are the
	// size of URL.
	URL    string
	Srcset string
	Width  int
	Height int
	// LargeURL is a copy at most media.LargeImageWidth wide, for the image
	// on its own, such as in a lightbox.
	LargeURL string
	// OriginalURL is the uploaded file, for downloads.
	OriginalURL string
	Title       string
	Alt         string
}

Image is one image of an album. Title and Alt come from the media library in the page's language.

type ImageRow

type ImageRow struct {
	Name string
	// URL shows the image; it is empty when the file is no longer in the
	// media library.
	URL string
	// Moves are the image's up and down arrows; nil without the right to
	// edit albums.
	Moves []admin.Move
}

ImageRow is one image of an album.

type ImagesView

type ImagesView struct {
	Title   string
	BackURL string
	EditURL string
	Images  []ImageRow
}

ImagesView is the data of templates/admin/images.gohtml: the images of one album in order.

type ListView

type ListView struct {
	Title  string
	Albums []Album
}

ListView is the data of gallery/list.gohtml.

type OrderAlbum

type OrderAlbum struct {
	Title string
	// URL opens the images of the album.
	URL    string
	Images int
}

OrderAlbum is one album on the order screen.

type OrderView

type OrderView struct {
	BackURL string
	// BackLabel names the albums overview BackURL leads to, as a
	// translation key.
	BackLabel string
	Albums    []OrderAlbum
}

OrderView is the data of templates/admin/order.gohtml: the albums whose images can be put in order.

type Service

type Service struct {
	// contains filtered or unexported fields
}

Service is one Gallery instance, for the website's own code (for example albums on the home page).

func Of

func Of(app *webthings.App, key string) *Service

Of returns the Gallery instance with key from a started app, or nil.

func (*Service) Album

func (s *Service) Album(ctx context.Context, locale, slug string) (Album, error)

Album returns one published album with its images, for example for a carousel on another page. The slug may be from any language; the album is returned in locale.

func (*Service) Albums

func (s *Service) Albums(ctx context.Context, locale string) ([]Album, error)

Albums returns the published albums in locale in their admin order, for use outside the module's own pages. Links point to the page the module is mounted on; they are empty when it is on no page.

func (*Service) Store

func (s *Service) Store() content.Store[AlbumFields, AlbumText]

Store gives write access to this instance's albums, for imports and seeds. Admin edits go through the same store.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL