Secure QR Event Pass
Generate a compact event pass whose URL contains a short ticket ID and an HMAC signature. The rendered QR code is produced by this exact payload—not a mock image.

Complete app
app.star
load("hash.star", "hash")
load("hmac.star", "hmac")
load("qrcode.star", "qrcode")
load("render.star", "render")
load("schema.star", "schema")
load("secret.star", "secret")
load("time.star", "time")
ENCRYPTED_SIGNING_KEY = "..."
DEFAULT_EVENT_TIME = "2026-03-18T19:30:00Z"
def main(config):
attendee = config.str("attendee", "Cruise")
event_time = time.parse_time(
config.str("event_time", DEFAULT_EVENT_TIME),
)
key = secret.decrypt(ENCRYPTED_SIGNING_KEY) or "demo-secret"
ticket_id = hash.sha256("%s|%s" % (attendee, event_time.unix))[0:4]
signature = hmac.sha256(key, ticket_id)[0:6]
payload = "https://spx.dev/p/%s?s=%s" % (ticket_id, signature)
code = qrcode.generate(
url = payload,
size = "large",
color = "#ffffff",
background = "#000000",
)
return render.Root(
child = render.Padding(
pad = (1, 0, 0, 0),
child = render.Row(
children = [
render.Padding(
pad = (0, 1, 0, 2),
child = render.Image(src = code),
),
render.Box(width = 3, height = 1),
render.Column(
children = [
render.Padding(
pad = (0, 1, 0, 0),
child = render.WrappedText(
"Leelo multi pass",
width = 32,
height = 17,
font = "CG-pixel-3x5-mono",
linespacing = 1,
color = "#fbbf24",
),
),
render.Box(width = 1, height = 1),
render.Text(
attendee,
font = "CG-pixel-4x5-mono",
color = "#ffffff",
),
render.Box(width = 1, height = 1),
render.Text(
event_time.format("Jan 02"),
font = "CG-pixel-3x5-mono",
color = "#94a3b8",
),
],
),
],
),
),
)
def get_schema():
return schema.Schema(
version = "1",
fields = [
schema.Text(
id = "attendee",
name = "Attendee",
desc = "Name printed on the pass.",
icon = "text",
default = "Cruise",
),
schema.DateTime(
id = "event_time",
name = "Event time",
desc = "Date and time printed on the pass.",
icon = "calendar",
),
],
)
How it works
DateTimesupplies an ISO timestamp, whichtime.parse_time()turns into a value.- SHA-256 creates a stable ticket ID without putting the attendee name in the URL.
- HMAC signs that ID with a decrypted secret so the server can reject forged passes.
qrcode.generate()produces the actual image bytes consumed byrender.Image.
The shortened hashes fit this display but are intentionally small for the tutorial. Use longer server-validated values for real admission systems, and replace the demo fallback with a required encrypted signing key.