The international Go programming language conference for Singapore and Southeast Asia!
npm install
npm run devThe site runs at http://localhost:4321. Changes to TOML data files and Astro components hot-reload automatically.
Built with Astro 5 and Tailwind CSS v4. Conference data lives in TOML files under src/data/ — you edit those to update speakers, schedule, workshops, and sponsors. No CMS required.
src/
├── assets/images/ # Speaker photos + sponsor logos (optimized at build)
│ ├── speakers/
│ └── sponsors/
├── components/ # Shared Astro components
│ └── index/ # Home-page-only components
├── data/ # TOML data files (edit these to update content)
│ ├── content.toml # Hero text, tickets, CoC, footer, sponsor CTA
│ ├── speakers.toml # Speaker profiles
│ ├── schedule.toml # Conference day schedule
│ ├── workshops.toml # Workshop details
│ └── sponsors.toml # Sponsor tiers and logos
├── layouts/
│ └── BaseLayout.astro # Shared HTML shell (head, header, footer)
├── lib/
│ ├── data.ts # Centralized TOML loading (don't import TOML elsewhere)
│ └── images.ts # Speaker image helpers
├── pages/ # Routes: /, /speakers, /schedule, /workshops, /404
├── styles/
│ └── global.css # Tailwind v4 theme + custom CSS
├── config.ts # Site config: URL, nav, eventStatus
├── env.d.ts # TypeScript declarations
└── types.ts # Data shape interfaces
public/
├── img/ # Hero images, wave backgrounds, mascot, patterns
└── (favicons)
All conference content lives in TOML files under src/data/. You can edit these with any text editor. Multiline text uses triple quotes ("""). Markdown formatting (links, bold, lists) works inside triple-quoted fields.
After editing, run npm run build to verify everything compiles correctly.
Edit src/data/content.toml. This file contains hero text, ticket info, code of conduct, footer details, and the sponsor CTA. No code changes needed — just edit the text values.
Example — update the conference date:
[hero]
conferenceDate = "22–24 January 2026"- Add the speaker's photo to
src/assets/images/speakers/(JPG, JPEG, WebP, or PNG) - Add an entry to
src/data/speakers.toml:
[[speakers]]
id = "jane-doe"
name = "Jane Doe"
company = "Acme Corp"
image = "jane-doe.jpg"
topicTitle = "Building Resilient Go Services"
topicLink = "/schedule#jane-doe"
keynote = false
socialUrl = "https://twitter.com/janedoe"
description = """Jane is a senior engineer at Acme Corp specializing in distributed systems."""The image filename must match a file in src/assets/images/speakers/. A mismatch crashes the build.
The id field becomes the URL anchor (/speakers#jane-doe), so use lowercase kebab-case.
Add an entry to src/data/schedule.toml:
[[schedule]]
id = "jane-doe"
title = "Building Resilient Go Services"
time = "2:00 PM"
type = "talk"
recordingUrl = ""
description = """Talk description with **markdown** support."""
[[schedule.speakers]]
name = "Jane Doe"
link = "/speakers#jane-doe"
image = "jane-doe.jpg"The type field must be one of: talk, break, or meta. The speakers field is always an array — use [[schedule.speakers]] even for a single speaker.
- Add the instructor's photo to
src/assets/images/speakers/(if not already there from the speakers list) - Add an entry to
src/data/workshops.toml:
[[workshops]]
id = "intro-to-go"
title = "Introduction to Go"
speaker = "Jane Doe"
speakerLink = "/speakers#jane-doe"
speakerImage = "jane-doe.jpg"
date = "22 January 2026"
time = "9:30am to 5:30pm"
venueRegistration = "registration starts at 9:00am"
venueMapUrl = ""
additional = ""
speakerBio = """Instructor bio text..."""
description = """Workshop description with **markdown** support..."""
prerequisites = """
- Complete the [Go Tour](https://go.dev/tour/welcome/1)
- Have a functioning Go environment installed
"""
venue = """
**IMDA Pixel Innovation Hub**
10 Central Exchange Green
Singapore 138649
"""- Add the sponsor's logo to
src/assets/images/sponsors/(PNG, JPG, or WebP — not SVG) - Add an entry to
src/data/sponsors.tomlunder the appropriate tier:
[[platinum]]
name = "Acme Corp"
logo = "acme.png"Available tiers: [[platinum]], [[diversity]], [[gold]], [[workshop]]. They display in that order on the site regardless of file order.
Edit the eventStatus field in src/config.ts:
eventStatus: "upcoming" as EventStatus,Three states:
| Status | Ticket UI | Header CTA | Home Banner |
|---|---|---|---|
"upcoming" |
Hidden | Hidden | None |
"live" |
Tito widget visible | "Get Your Tickets" | None |
"archived" |
Hidden | "Watch Recordings" | "Thank you!" banner |
Only set "live" after the Tito event (gopherconsg/2026) has been created on ti.to. Setting it before will cause widget errors.
flowchart TD
TOML["TOML Data Files<br/>src/data/*.toml"] --> DataTS["src/lib/data.ts<br/>Centralized imports + type casts"]
DataTS --> Components["Astro Components<br/>src/components/"]
Config["src/config.ts<br/>siteConfig, isLive, isArchived"] --> Components
Images["src/assets/images/<br/>speakers/, sponsors/"] --> ImagesTS["src/lib/images.ts<br/>Glob + helpers"]
ImagesTS --> Components
Components --> Pages["Astro Pages<br/>src/pages/"]
Pages --> BaseLayout["BaseLayout.astro<br/>Head, Header, Footer, Scripts"]
GlobalCSS["src/styles/global.css<br/>Tailwind v4 @theme + custom CSS"] --> BaseLayout
- TOML for data, not content collections. Editors already know TOML from the Hugo-era sites. Files are imported directly via
vite-plugin-tomland typed with TypeScript interfaces. - Two-tier images. Speaker photos and sponsor logos go in
src/assets/images/for Astro's build-time optimization. Hero backgrounds and wave layers stay inpublic/img/as plain files for CSSbackground-imageusage. - Centralized data loading. All TOML imports happen in
src/lib/data.ts. Components never import TOML files directly — they use typed exports likeimport { speakers } from "@/lib/data". - No client-side framework. Two inline
<script>blocks handle all interactivity (mobile nav toggle, copy-link-to-clipboard). No React, no Vue, no Astro islands. - Tailwind v4 CSS-first. Theme tokens are defined in
@theme {}insidesrc/styles/global.css. There is notailwind.config.js.
- Create
src/pages/your-page.astro - Use
BaseLayoutwithtitleanddescriptionprops:
---
import BaseLayout from "@/layouts/BaseLayout.astro";
---
<BaseLayout title="Your Page" description="Description for SEO">
<section class="container" style="padding: 3rem 0;">
<h2>Your Page</h2>
<!-- content -->
</section>
</BaseLayout>- Add a nav entry in
src/config.ts→siteConfig.navarray
Pages only provide slot content. Header and Footer are rendered by BaseLayout — never import them directly.
Speaker and sponsor images use Astro's <Image /> component, which requires statically analyzable imports. You cannot use dynamic string paths like `../assets/${filename}`.
Instead, use the centralized helpers:
// Speaker images (centralized in src/lib/images.ts)
import { speakerImages, resolveSpeakerImage } from "@/lib/images";
const img = resolveSpeakerImage(speakerImages, "dave-cheney.jpg"); // throws if missingHero and background images in public/img/ are referenced directly in CSS or plain <img> tags — they do not go through <Image />.
Tailwind v4 uses CSS-first configuration. All theme tokens live in src/styles/global.css:
@import "tailwindcss";
@theme {
--color-brand-blue: #14c8e0;
--color-brand-red: #ee4059;
--color-link-blue: #0f71bb;
--font-display: "Dangrek", "Inter", "Helvetica Neue", Arial, sans-serif;
--font-heading: "Merriweather", Georgia, serif;
--font-body: "Helvetica Neue", Arial, ui-sans-serif, system-ui, sans-serif;
}Custom properties defined in @theme auto-generate utility classes (e.g., --color-brand-blue → bg-brand-blue).
The primary responsive breakpoint is md: (768px), used consistently across all components.
| Command | Description |
|---|---|
npm run dev |
Start dev server at localhost:4321 |
npm run build |
Production build (primary verification step) |
npm run preview |
Preview production build locally |
npm run lint |
Run Biome linter (biome check .) |
npm run format |
Auto-format with Biome (biome format --write .) |
Copyright (c) 2026 The GopherCon Singapore Organisers.
GopherCon Singapore is run under the auspices of CU Society (UEN: T18SS0020F).
The Gopher character is based on the Go mascot designed by Renee French and copyrighted under the Creative Commons Attribution 3.0 licence.