Skip to content
Typst Template

Typst Template

How to render a PDF from a Typst template and Go data with template.Apply and hand it to the browser with wnd.ExportFiles. The template and its data types live in the typst sub package.

package main

import (
	"go.wdy.de/nago/application"
	"go.wdy.de/nago/application/template"
	"go.wdy.de/nago/application/user"
	"go.wdy.de/nago/example/cmd/tutorial-71-template/typst"
	"go.wdy.de/nago/presentation/core"
	"go.wdy.de/nago/presentation/ui"
	"go.wdy.de/nago/presentation/ui/alert"
	"go.wdy.de/nago/web/vuejs"
)

func main() {
	application.Configure(func(cfg *application.Configurator) {
		cfg.SetApplicationID("de.worldiety.tutorial_71")
		cfg.Serve(vuejs.Dist())

		cfg.SetDecorator(cfg.NewScaffold().Decorator())

		cfg.RootViewWithDecoration(".", func(wnd core.Window) core.View {
			return ui.VStack(
				ui.PrimaryButton(func() {
					buf, err := template.Apply(user.SU(), typst.Template, template.TypstPDF, template.ExecOptions{Model: typst.ExampleData()})
					if err != nil {
						alert.ShowBannerError(wnd, err)
						return
					}

					wnd.ExportFiles(core.ExportFileBytes("doc.pdf", buf))
				}).Title("Run typst"),
			).Frame(ui.Frame{}.MatchScreen())
		})

	}).Run()
}

example.go

package typst

func ExampleData() Report {
	return Report{
		Title:    "Test",
		Subtitle: "Subtest",
		Author: Author{
			Name: "Max Mustermann",
			Birthday: Date{
				Year:  2000,
				Month: 5,
				Day:   1,
			},
			Address: Address{
				Street: "Nordseestr. 1",
				City:   "26131 Oldenburg",
			},
		},
		Company: Company{
			Name: "worldiety GmbH",
			Address: Address{
				Street: "Nordseestr. 2",
				City:   "26131 Oldenburg",
			},
		},
		Trainer: "Muster Maxmann",
		Training: Training{
			Start: Date{
				Year:  2020,
				Month: 8,
				Day:   1,
			},
			End: Date{
				Year:  2023,
				Month: 8,
				Day:   1,
			},
		},
		Entries: []Entry{
			{
				Kind: Day,
				Date: Date{
					Year:  2020,
					Month: 8,
					Day:   1,
				},
				Tasks: []Task{
					{
						Description:       "Lorem Ipsum",
						DurationInMinutes: 30,
					},
					{
						Description:       "Lorem Ipsum",
						DurationInMinutes: 90,
					},
					{
						Description:       "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
						DurationInMinutes: 120,
					},
					{
						Description:       "Lorem Ipsum",
						DurationInMinutes: 30,
					},
				},
				Place: "Betrieb",
			},
			{
				Kind: Day,
				Date: Date{
					Year:  2020,
					Month: 8,
					Day:   2,
				},
				Tasks: []Task{
					{
						Description:       "Lorem Ipsum",
						DurationInMinutes: 30,
					},
					{
						Description:       "Lorem Ipsum",
						DurationInMinutes: 90,
					},
					{
						Description:       "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.",
						DurationInMinutes: 120,
					},
					{
						Description:       "Lorem Ipsum",
						DurationInMinutes: 30,
					},
				},
				Place: "Betrieb",
			},
			{
				Kind: Signature,
				Date: Date{
					Year:  2020,
					Month: 8,
					Day:   31,
				},
				Tasks: []Task{},
				Place: "Schule",
			},
		},
	}
}

template.go

package typst

import (
	"embed"
)

//go:embed main.typ.tpl logo.png aubina.typ
var Template embed.FS

type Address struct {
	Street string
	City   string
}

type Author struct {
	Name     string
	Birthday Date
	Address  Address
}
type Company struct {
	Name    string
	Address Address
}
type Date struct {
	Year  int
	Month int
	Day   int
}
type Training struct {
	Start Date
	End   Date
}

type Task struct {
	Description       string
	DurationInMinutes int
}

type EntryKind int

const (
	Day EntryKind = iota
	Signature
)

type Entry struct {
	Kind  EntryKind
	Date  Date
	Tasks []Task
	Place string
}
type Report struct {
	Title    string
	Subtitle string
	Author   Author
	Company  Company
	Trainer  string
	Training Training
	Entries  []Entry
}

View on GitHub ↗ · run it with go run go.wdy.de/nago/example/cmd/tutorial-71-template@latest