Skip to content

foundation/inky-example-go

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Inky Example Suite: Go

Ten runnable, numbered examples showing how to use the Inky email framework from Go, via the github.com/foundation/inky-go binding — from the smallest possible transform up to a transactional-email capstone and a CMS-templating-engine integration.

This is a Stage C port of the reference PHP suite (inky-example-php): the same ten examples, against the same required output markers, defined in that repo's SUITE.md (the language-neutral porting contract). Only driver code differs; templates, SCSS themes, layouts, includes, and JSON fixtures are copied verbatim from the PHP repo.

Requires Inky v2. See the main inky repo.

Requirements

  • Go >= 1.21 (developed against 1.25)
  • A Rust toolchain, to build the libinky shared library:
    cd ../inky && cargo build -p inky-ffi --release
    (this repo must be checked out as a sibling of inky/ and inky-go/ — the replace directive in go.mod and the dylib lookup below both assume that layout)
  • github.com/foundation/inky-go, pulled in via a local replace directive in go.mod pointing at ../inky-go
  • github.com/flosch/pongo2/v6 (pulled in automatically by go mod download) — used only by example 10

Environment: CGO_LDFLAGS / DYLD_LIBRARY_PATH

Every go build/go run/go test invocation in this repo needs the Rust-built libinky dylib on both the linker's and the dynamic loader's search path:

export CGO_LDFLAGS="-L/Users/joeworkman/Developer/inky/target/release"
export DYLD_LIBRARY_PATH=/Users/joeworkman/Developer/inky/target/release   # macOS
# export LD_LIBRARY_PATH=/Users/joeworkman/Developer/inky/target/release  # Linux

inky-go's cgo directive links -linky against the default /usr/local/lib; CGO_LDFLAGS above adds target/release to the search path ahead of that default so the locally-built dylib is found without installing it system-wide. cmd/runall spawns every example (and its verify/) as a go run subprocess; since os/exec inherits the parent process's environment by default, setting these two variables once, on the top-level invocation, is sufficient — no per-subprocess wiring needed.

Runtime requirements re-verified for Go (this port's own "Task 1")

The PHP suite's SUITE.md asks every Stage C port to re-verify two things in its own binding/runtime:

  1. Does the local path-dependency mechanism break the dylib lookup? No. Go's replace directive in go.mod (replace github.com/foundation/inky-go => /Users/joeworkman/Developer/inky-go) is the Go analogue of Composer's symlinked path repository — but unlike that PHP case (which happened to work only because PHP resolves __DIR__ through the symlink to the binding's real location before its relative dylib lookup runs), there is no such question to re-verify here at all: inky-go's cgo LDFLAGS are resolved by the linker via the CGO_LDFLAGS environment variable at build time, not by walking a relative path computed from the package's own source location. The replace directive works exactly as documented, no special wiring needed.
  2. Does the stability-policy question (PHP's minimum-stability: dev / prefer-stable: true) have a Go equivalent? No. Go modules have no "stability tag" resolution step the way Composer does — a replace directive to a local filesystem path is used verbatim regardless of what version string appears in the corresponding require line (this repo's go.mod uses the standard v0.0.0-00010101000000-000000000000 placeholder pseudo-version for that require, satisfied entirely by the replace). Nothing to configure.

60-second quick start

cd ../inky && cargo build -p inky-ffi --release   # build libinky once
cd ../inky-example-go
export CGO_LDFLAGS="-L$(cd ../inky && pwd)/target/release"
export DYLD_LIBRARY_PATH="$(cd ../inky && pwd)/target/release"   # macOS; use LD_LIBRARY_PATH on Linux
go run ./cmd/runall            # runs every examples/*/main.go, writes dist/
go run ./cmd/runall -verify    # same, plus each example's verify/main.go

go run ./cmd/runall -verify prints NN-name: ok for all ten examples. Output lands in dist/NN-name/ (gitignored).

The ten examples

# Name Teaches
01-quickstart quickstart The smallest possible thing Inky does: inky.Transform turns a <button> into table markup, no layout or data involved.
02-build-pipeline build-pipeline The full build pipeline in one call: shared layout + includes + a linked SCSS theme, all resolved and inlined.
03-data-merge data-merge Merging JSON data into a template: variables, a conditional, and a loop rendered as real <tr> rows.
04-theming theming Building the identical template twice with a different linked SCSS theme each time.
05-plain-text plain-text Deriving a plain-text alternative alongside the HTML for multipart transactional email.
06-validate-gate validate-gate Using inky.Validate as a pre-send CI gate: block on errors, let warnings through.
07-migrate migrate Upgrading a v1 Inky template to v2 syntax programmatically, with a reviewable change report.
08-outlook-hybrid outlook-hybrid Building for Outlook desktop: hybrid column layout, bulletproof VML buttons, <outlook>/<not-outlook> branching.
09-transactional transactional (capstone) A real three-email transactional set (welcome, receipt, password reset) built through emailrenderer.EmailRenderer, a small production-shaped service type.
10-twig-cms twig-cms Integrating Inky into a Jinja2-family CMS templating engine (this port uses pongo2, not Go's text/template — see that example's header comment for why): both valid processing orders, timed, plus the one <raw> rule that makes the fast path safe.

Run any single example directly, e.g. go run ./examples/03-data-merge — every main.go is a self-contained, top-to-bottom tutorial with comments at each decision point. Each example also has its own verify/ smoke test, e.g. go run ./examples/03-data-merge/verify.

For CMS / templating-engine integrators

If you're wiring Inky into a Twig/Jinja2-family CMS engine, start at 09-transactional to see the production-shaped emailrenderer.EmailRenderer wrapper (emailrenderer/emailrenderer.go), then read 10-twig-cms for the CMS-specific question: should the templating engine or Inky run first? Both orders are implemented, timed, and proven to agree — see that example's main.go and newsletter.inky.pongo2 header comment for the full trade-off, including the one <raw>-plus-InlineCSS: false rule that makes the faster, build-once-per-template order safe.

Layout

go.mod                  replace -> ../inky-go; pongo2 dependency
internal/support/        the Go analogue of bootstrap.php: ExampleDir()/Dist() helpers every example uses
emailrenderer/           small production-shaped render/theme/cache wrapper (example 09; the pattern example 10 adapts by hand)
shared/                  brand layout, includes, SCSS themes used by examples 01-08
examples/NN-name/        one directory per example: main.go (tutorial) + verify/main.go (smoke test)
examples/09-transactional/emails/   self-contained base-root template tree (see below)
examples/10-twig-cms/emails/        self-contained base-root template tree (see below)
dist/                    build output (generated, gitignored)
cmd/runall/              runs every example (go run ./cmd/runall [-verify])
cmd/send/                multipart send demo reading example 05's output

Two fixture conventions (by design, not an inconsistency)

  • Examples 01–08 reference shared fixtures (brand layout, includes, SCSS themes) in shared/ at the repo root, via ../../shared/... traversals from each example's examples/NN-name/ directory (which is passed as basePath to inky.Build) — two levels up, not one; see the PHP suite's SUITE.md "Runtime requirements" §2 for why (basePath is always the original directory passed to inky.Build, never re-derived per included file). This keeps eight independent lessons from each carrying their own copy of the same handful of bytes.
  • Examples 09 and 10 (the capstones) each ship a self-contained emails/ tree instead — one basePath containing its own layouts/, themes/, and includes/ copies, with every internal src/href written root-relative (no ../ anywhere inside the tree). This models the shape a real CMS integration actually looks like on disk: one directory an app points its renderer at, self-contained, that a deployment can copy or version as a unit. See emails/layouts/main.html's own header comment in each capstone for the exact resolution rule.

Documentation

About

Example: Using Inky email framework with go

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors