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

testimonials

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: 19 Imported by: 0

README

Testimonials

Quotes from customers or partners, with the author's name, role and organisation and an optional photo.

Testimonials are kept in a list ordered by hand and published one by one. Show them on a page of their own, or a few on any page with a template function. Use one instance per list, for example reviews and partners.

Add it to the site

app.Use(
    testimonials.Module("reviews", "Reviews"),
)

The key (reviews) is the instance's name in URLs and templates and must be unique on the site. The title (Reviews) is what editors see in the admin navigation and the page editor. The module has no options.

Place it on a page

In the admin, open a page and choose the instance under Shows on this page. With the page at /reviews:

Address Template Shows
/reviews reviews/list.gohtml all published testimonials, in their order

Templates are looked up by instance key first, then by module type, so testimonials/list.gohtml serves every Testimonials instance that has no design of its own. Generate a starting point with every field of the data:

task templates -- reviews

A minimal list:

{{/* @dot github.com/donseba/go-webthings/modules/testimonials.ListView */}}
<h1>{{.Title}}</h1>

{{range .Testimonials}}
    <figure>
        <blockquote>{{.Quote}}</blockquote>
        <figcaption>
            {{with .PhotoURL}}<img src="{{image . "96x96 crop"}}" width="96" height="96" alt="">{{end}}
            {{.Author}}{{with .Role}}, {{.}}{{end}}{{with .Organisation}}, {{.}}{{end}}
        </figcaption>
    </figure>
{{end}}

.Title is the published title of the page. The quote is plain text, not Markdown. .PhotoURL is the photo as pages show it, at most 1600 pixels wide, with .PhotoSrcset, .PhotoWidth and .PhotoHeight for an img tag of that size and .PhotoOriginalURL for the uploaded file; image makes the small square above from it. All are empty for a testimonial without a photo.

A testimonial appears in each language it has a quote in.

Show testimonials anywhere

The testimonials template function returns the first published testimonials in the current language, in their order, up to a limit; a limit of 0 or less returns all. It works on every page, also when the instance is not placed on a page.

{{range testimonials "reviews" 3}}
    <blockquote>{{.Quote}} — {{.Author}}</blockquote>
{{end}}

<a href="{{moduleURL "reviews"}}">All reviews</a>

To show a different choice on every visit, see Random below.

Content API

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

Endpoint Route name Answers with
/api/v1/reviews/testimonials api.reviews.testimonials The published testimonials, in the editors' order, as a list
/api/v1/reviews/testimonials/{id} api.reviews.testimonial One testimonial

A testimonial has its id, the quote as plain text, the author, the role and organisation in the language of the answer, the photo as an image object, null without one, and url, api_url and updated_at. Testimonials have no page of their own: url is the page the instance is placed on, null while it is on none.

/testimonials/{id} sends a Last-Modified: the latest change of the testimonial, of the page the instance is on and of its photo. A testimonial whose photo was deleted gets none, and so does every testimonial 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/reviews; /admin is the default admin path).

  • A testimonial has the author's name, which is required, and a photo from the media library, shared by all languages. Per language it has the quote and the author's role and organisation.
  • The order in the admin (Move up, Move down) is the order on the site and in testimonials.
  • There are no revisions: saving changes the testimonial at once, also when it is published. Publish and Unpublish show or hide it; publishing needs a quote in the site's default language.
  • Move to trash moves a testimonial to the trash, where it can be restored or deleted for good.
  • A photo that a testimonial uses cannot be deleted from the media library, also while the testimonial is in the trash.

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

Testimonials are not part of the site search. The page they are placed on is in sitemap.xml like any other page.

From Go

testimonials.Of(app, "reviews") returns the instance once the app has started:

reviews := testimonials.Of(app, "reviews")

all, err := reviews.List(ctx, "en")
picked, err := reviews.Random(ctx, "en", 3)

Random returns up to a number of published testimonials in random order; 0 or less returns all of them, shuffled. There is no template function for it; a site adds one through Config.Funcs:

randomReviews := func(ctx context.Context, limit int) []testimonials.Testimonial {
    service, ok := frontend.ServiceOf[*testimonials.Service](ctx, "reviews")
    if !ok {
        return nil
    }

    list, _ := service.Random(ctx, frontend.Locale(ctx), limit)

    return list
}

app := webthings.New(webthings.Config{
    Funcs: []template.FuncMap{{"randomReviews": randomReviews}},
})

Templates then use {{range randomReviews 2}}.

Store() gives write access for imports and seed data, through the same rules the admin uses. New testimonials are saved unpublished:

store := reviews.Store()

item, err := store.Save(ctx, content.Draft[testimonials.Fields, testimonials.Text]{
    Fields: testimonials.Fields{Author: "Alice"},
    Translations: []content.Translation[testimonials.Text]{
        {Locale: "en", Text: testimonials.Text{Quote: "They built our website in a week.", Organisation: "Acme"}},
    },
})
if err != nil {
    return err
}

err = store.Publish(ctx, item.ID, "", "en")
  • People presents your own team, with photos and roles.
  • Lists keeps other short ordered content, such as services or features.
  • Banners shows hero slides and notices next to them on the home page.

Documentation

Overview

Package testimonials shows quotes from customers or partners: a quote, the author's name, role and organisation, and an optional photo. Testimonials are kept in a manually ordered list and published one by one. Add an instance with:

app.Use(testimonials.Module("testimonials", "Testimonials"))

When the module is mounted on a page, the website renders testimonials/list.gohtml with a ListView as its data. Every template can also show testimonials, for example on the home page, without mounting the module:

{{range testimonials "testimonials" 3}}<blockquote>{{.Quote}} — {{.Author}}</blockquote>{{end}}

The limit counts from the top of the list; 0 or less shows all of them. From Go, Of(app, key).List returns the same list and Random a random choice.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Module

func Module(key, title string) webthings.Module

Module adds a Testimonials 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 APITestimonial

type APITestimonial struct {
	ID           string     `json:"id"`
	Quote        string     `json:"quote"`
	Author       string     `json:"author"`
	Role         string     `json:"role"`
	Organisation string     `json:"organisation"`
	Photo        *api.Image `json:"photo"`
	// URL is the page that lists the testimonials, null while the instance
	// is on no page; testimonials have no page of their own. APIURL is the
	// testimonial in the API.
	URL       *string   `json:"url"`
	APIURL    string    `json:"api_url"`
	UpdatedAt time.Time `json:"updated_at"`
}

APITestimonial is a published testimonial in the content API (see package api), at /api/v1/<key>/testimonials/{id} and in the list of /api/v1/<key>/testimonials. Quote is plain text, as the editors wrote it.

type Fields

type Fields struct {
	Photo  string `db:"photo_id,null"`
	Author string `db:"author"`
}

Fields are the language-independent parts of a testimonial.

type Item

type Item = content.Item[Fields, Text]

Item is a testimonial with its translations, as the store keeps it.

type ListView

type ListView struct {
	// Title is the title of the page the module is mounted on.
	Title        string
	Testimonials []Testimonial
}

ListView is the data of testimonials/list.gohtml.

type Service

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

Service is one Testimonials instance, for the website's own code.

func Of

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

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

func (*Service) List

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

List returns the published testimonials that have a quote in locale, in their order.

func (*Service) Random

func (s *Service) Random(ctx context.Context, locale string, limit int) ([]Testimonial, error)

Random returns up to limit published testimonials in locale, in random order, for example to show a few on the home page. A limit of 0 or less returns all of them, shuffled.

func (*Service) Store

func (s *Service) Store() content.Store[Fields, Text]

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

type Testimonial

type Testimonial struct {
	ID           string
	Quote        string
	Author       string
	Role         string
	Organisation string
	// PhotoURL is the photo as pages show it, at most media.ImageWidth
	// wide (see frontend.Frontend.Image); PhotoSrcset lists smaller
	// copies for a srcset attribute, PhotoWidth and PhotoHeight are the
	// size of PhotoURL and PhotoOriginalURL is the uploaded file, for
	// downloads. All are empty when the testimonial has no photo.
	PhotoURL         string
	PhotoSrcset      string
	PhotoOriginalURL string
	PhotoWidth       int
	PhotoHeight      int
}

Testimonial is a published testimonial as templates see it.

type Text

type Text struct {
	Quote        string `db:"quote"`
	Role         string `db:"author_role"`
	Organisation string `db:"organisation"`
}

Text is a testimonial in one language. Only the quote is required.

Jump to

Keyboard shortcuts

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