Initial commit: Hugo static site for nerdy events
Some checks failed
Build Hugo Site / build (push) Failing after 19s

- Custom cyberpunk/console theme with pure CSS
- Event management with RSS and iCal calendar feeds
- Gitea workflow for automated deployment
- Complete documentation and setup instructions

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-06-04 13:53:50 -06:00
commit 217e4a5de5
32 changed files with 2292 additions and 0 deletions

View File

@@ -0,0 +1,11 @@
<div class="ascii-border">
<pre>
+===================================================================+
</pre>
</div>
<p class="prompt">NERDER.LAND {{ now.Year }} - Connecting the tech underground</p>
<p style="margin-top: 1rem; font-size: 0.8rem;">
<a href="{{ "events/feed.xml" | absURL }}">📡 RSS Feed</a> |
<a href="{{ "events/calendar.ics" | absURL }}">📅 Calendar Subscription</a> |
<a href="mailto:{{ .Site.Params.eventSubmissionEmail | default "events@nerder.land" }}?subject=Event Submission&body=Please include:%0A%0AEvent Name:%0ADate & Time:%0ALocation:%0ADescription:%0AOrganizer:%0AContact Info:%0ACost:%0ARegistration URL (if any):">📧 Submit an Event</a>
</p>

View File

@@ -0,0 +1,10 @@
{{ if .IsHome }}
<h1>{{ site.Title }}</h1>
<div class="ascii-border">
<pre>
+===================================================================+
</pre>
</div>
{{ else }}
<h2><a href="{{ "/" | relURL }}">{{ site.Title }}</a></h2>
{{ end }}

29
layouts/baseof.html Normal file
View File

@@ -0,0 +1,29 @@
<!DOCTYPE html>
<html lang="{{ or site.Language.LanguageCode }}" dir="{{ or site.Language.LanguageDirection `ltr` }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{ if .IsHome }}{{ site.Title }}{{ else }}{{ .Title }} - {{ site.Title }}{{ end }}</title>
<link rel="stylesheet" href="{{ "css/style.css" | relURL }}">
<!-- RSS Feeds -->
<link rel="alternate" type="application/rss+xml" title="{{ site.Title }} - All Content" href="{{ "feed.xml" | absURL }}">
<link rel="alternate" type="application/rss+xml" title="{{ site.Title }} - Events" href="{{ "events/feed.xml" | absURL }}">
<!-- Calendar Feeds -->
<link rel="alternate" type="text/calendar" title="{{ site.Title }} - Events Calendar" href="{{ "events/calendar.ics" | absURL }}">
</head>
<body>
<div class="container">
<header>
{{ partial "header.html" . }}
</header>
<main>
{{ block "main" . }}{{ end }}
</main>
<footer>
{{ partial "footer.html" . }}
</footer>
</div>
</body>
</html>

View File

@@ -0,0 +1,48 @@
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//NERDER.LAND//Event Calendar//EN
NAME:{{ .Site.Title }} Events
X-WR-CALNAME:{{ .Site.Title }} Events
DESCRIPTION:{{ .Site.Params.description }}
TIMEZONE-ID:America/Denver
BEGIN:VTIMEZONE
TZID:America/Denver
BEGIN:DAYLIGHT
TZOFFSETFROM:-0700
TZOFFSETTO:-0600
TZNAME:MDT
DTSTART:20250309T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:-0600
TZOFFSETTO:-0700
TZNAME:MST
DTSTART:20251102T020000
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
END:STANDARD
END:VTIMEZONE
{{- range .RegularPages }}
BEGIN:VEVENT
UID:{{ .File.UniqueID }}@{{ $.Site.BaseURL | replaceRE "^https?://" "" }}
DTSTART;TZID=America/Denver:{{ .Params.date | dateFormat "20060102T150405" }}
{{- if .Params.end_date }}
DTEND;TZID=America/Denver:{{ .Params.end_date | dateFormat "20060102T150405" }}
{{- else }}
DTEND;TZID=America/Denver:{{ .Params.date.Add (time.ParseDuration "2h") | dateFormat "20060102T150405" }}
{{- end }}
DTSTAMP:{{ now | dateFormat "20060102T150405Z" }}
SUMMARY:{{ .Title }}
DESCRIPTION:{{ .Summary | replaceRE "\n" "\\n" | replaceRE "," "\\," }}
{{- if .Params.location }}
LOCATION:{{ .Params.location | replaceRE "," "\\," }}
{{- end }}
URL:{{ .Permalink }}
{{- if .Params.organizer }}
ORGANIZER:{{ .Params.organizer | replaceRE "," "\\," }}
{{- end }}
STATUS:CONFIRMED
TRANSP:OPAQUE
END:VEVENT
{{- end }}
END:VCALENDAR

39
layouts/events/rss.xml Normal file
View File

@@ -0,0 +1,39 @@
{{- $pctx := . -}}
{{- if .IsHome -}}{{ $pctx = .Site }}{{- end -}}
{{- $pages := slice -}}
{{- if or $.IsHome $.IsSection -}}
{{- $pages = $pctx.RegularPages -}}
{{- else -}}
{{- $pages = $pctx.Pages -}}
{{- end -}}
{{- $limit := .Site.Config.Services.RSS.Limit -}}
{{- if ge $limit 1 -}}
{{- $pages = $pages | first $limit -}}
{{- end -}}
{{- printf "<?xml version=\"1.0\" encoding=\"utf-8\" standalone=\"yes\"?>" | safeHTML }}
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
<channel>
<title>{{ if eq .Title .Site.Title }}{{ .Site.Title }}{{ else }}{{ with .Title }}{{.}} on {{ end }}{{ .Site.Title }}{{ end }}</title>
<link>{{ .Permalink }}</link>
<description>{{ .Site.Params.description | default "Recent events" }}</description>
<generator>Hugo -- gohugo.io</generator>{{ with .Site.LanguageCode }}
<language>{{.}}</language>{{end}}{{ with .Site.Author.email }}
<managingEditor>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</managingEditor>{{end}}{{ with .Site.Author.email }}
<webMaster>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</webMaster>{{end}}{{ with .Site.Copyright }}
<copyright>{{.}}</copyright>{{end}}{{ if not .Date.IsZero }}
<lastBuildDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</lastBuildDate>{{ end }}
{{- with .OutputFormats.Get "RSS" -}}
{{ printf "<atom:link href=%q rel=\"self\" type=%q />" .Permalink .MediaType | safeHTML }}
{{- end -}}
{{ range $pages }}
<item>
<title>{{ .Title }}</title>
<link>{{ .Permalink }}</link>
<pubDate>{{ .Date.Format "Mon, 02 Jan 2006 15:04:05 -0700" | safeHTML }}</pubDate>
{{ with .Site.Author.email }}<author>{{.}}{{ with $.Site.Author.name }} ({{.}}){{end}}</author>{{end}}
<guid>{{ .Permalink }}</guid>
<description>{{ with .Params.location }}📍 {{ . }} | {{ end }}{{ with .Params.date }}🗓️ {{ dateFormat "January 2, 2006 at 3:04 PM MST" . }} | {{ end }}{{ with .Params.cost }}💰 {{ . }} | {{ end }}{{ .Summary | html }}</description>
</item>
{{ end }}
</channel>
</rss>

View File

@@ -0,0 +1,98 @@
{{ define "main" }}
<article class="event-detail">
<div class="ascii-border">
<pre>
+==================================================================+
| EVENT DETAILS |
+==================================================================+
</pre>
</div>
<h1>{{ .Title }}</h1>
<div class="event-meta">
<div class="meta-item">
<span class="meta-label">Date & Time</span>
<span class="meta-value">{{ .Params.date | dateFormat "Monday, January 2, 2006 at 3:04 PM MST" }}</span>
</div>
{{ if .Params.end_date }}
<div class="meta-item">
<span class="meta-label">End Time</span>
<span class="meta-value">{{ .Params.end_date | dateFormat "Monday, January 2, 2006 at 3:04 PM MST" }}</span>
</div>
{{ end }}
<div class="meta-item">
<span class="meta-label">Timezone</span>
<span class="meta-value">Mountain Time (UTC-6)</span>
</div>
{{ if .Params.location }}
<div class="meta-item">
<span class="meta-label">Location</span>
<span class="meta-value">{{ .Params.location }}</span>
</div>
{{ end }}
{{ if .Params.organizer }}
<div class="meta-item">
<span class="meta-label">Organizer</span>
<span class="meta-value">{{ .Params.organizer }}</span>
</div>
{{ end }}
{{ if .Params.capacity }}
<div class="meta-item">
<span class="meta-label">Capacity</span>
<span class="meta-value">{{ .Params.capacity }} people</span>
</div>
{{ end }}
{{ if .Params.cost }}
<div class="meta-item">
<span class="meta-label">Cost</span>
<span class="meta-value">{{ .Params.cost }}</span>
</div>
{{ end }}
</div>
<div class="event-content">
{{ .Content }}
</div>
{{ if .Params.registration_url }}
<div class="registration">
<div class="ascii-border">
<pre>
+--------------------------------------------------------------+
| REGISTRATION |
+--------------------------------------------------------------+
</pre>
</div>
<p class="prompt"><a href="{{ .Params.registration_url }}">Register for this event</a></p>
</div>
{{ end }}
{{ if .Params.contact }}
<div class="contact">
<h3>Contact Information</h3>
<p>{{ .Params.contact }}</p>
</div>
{{ end }}
<div class="calendar-actions">
<div class="ascii-border">
<pre>
+--------------------------------------------------------------+
| ADD TO CALENDAR |
+--------------------------------------------------------------+
</pre>
</div>
<p class="prompt">
<a href="{{ .RelPermalink }}calendar.ics" download>📅 Download Event (.ics)</a>
</p>
</div>
</article>
{{ end }}

48
layouts/events/single.ics Normal file
View File

@@ -0,0 +1,48 @@
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//NERDER.LAND//Event Calendar//EN
NAME:{{ .Title }}
X-WR-CALNAME:{{ .Title }}
TIMEZONE-ID:America/Denver
BEGIN:VTIMEZONE
TZID:America/Denver
BEGIN:DAYLIGHT
TZOFFSETFROM:-0700
TZOFFSETTO:-0600
TZNAME:MDT
DTSTART:20250309T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:-0600
TZOFFSETTO:-0700
TZNAME:MST
DTSTART:20251102T020000
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
UID:{{ .File.UniqueID }}@{{ .Site.BaseURL | replaceRE "^https?://" "" }}
DTSTART;TZID=America/Denver:{{ .Params.date | dateFormat "20060102T150405" }}
{{- if .Params.end_date }}
DTEND;TZID=America/Denver:{{ .Params.end_date | dateFormat "20060102T150405" }}
{{- else }}
DTEND;TZID=America/Denver:{{ .Params.date.Add (time.ParseDuration "2h") | dateFormat "20060102T150405" }}
{{- end }}
DTSTAMP:{{ now | dateFormat "20060102T150405Z" }}
SUMMARY:{{ .Title }}
DESCRIPTION:{{ .Content | plainify | replaceRE "\n" "\\n" | replaceRE "," "\\," }}
{{- if .Params.location }}
LOCATION:{{ .Params.location | replaceRE "," "\\," }}
{{- end }}
URL:{{ .Permalink }}
{{- if .Params.organizer }}
ORGANIZER:{{ .Params.organizer | replaceRE "," "\\," }}
{{- end }}
{{- if .Params.contact }}
CONTACT:{{ .Params.contact | replaceRE "," "\\," }}
{{- end }}
STATUS:CONFIRMED
TRANSP:OPAQUE
END:VEVENT
END:VCALENDAR

44
layouts/home.html Normal file
View File

@@ -0,0 +1,44 @@
{{ define "main" }}
<div class="intro">
<p class="prompt">{{ .Site.Params.description | default "Welcome to the underground tech scene." }}</p>
</div>
<div class="ascii-border">
<pre>
+==================================================================+
| UPCOMING EVENTS |
+==================================================================+
</pre>
</div>
{{ $futureEvents := where .Site.RegularPages "Section" "events" }}
{{ $futureEvents := where $futureEvents "Params.date" "ge" now }}
{{ $futureEvents := $futureEvents.ByParam "date" }}
{{ if $futureEvents }}
<ul class="event-list">
{{ range $futureEvents }}
<li class="event-item">
<div class="event-date">{{ .Params.date | dateFormat "Monday, January 2, 2006 at 3:04 PM MST" }}</div>
<h3 class="event-title">
<a href="{{ .RelPermalink }}">{{ .Title }}</a>
</h3>
{{ if .Params.location }}
<div class="event-location">📍 {{ .Params.location }}</div>
{{ end }}
{{ if .Params.cost }}
<div class="event-cost">💰 {{ .Params.cost }}</div>
{{ end }}
<div class="event-description">{{ .Summary }}</div>
<div class="event-link">
<a href="{{ .RelPermalink }}">View Details →</a>
</div>
</li>
{{ end }}
</ul>
{{ else }}
<div class="no-events">
<p class="prompt">No upcoming events found. Check back later for more cyberpunk gatherings!</p>
</div>
{{ end }}
{{ end }}

76
layouts/single.html Normal file
View File

@@ -0,0 +1,76 @@
{{ define "main" }}
<article class="event-detail">
<div class="ascii-border">
+==================================================================+
| EVENT DETAILS |
+==================================================================+
</div>
<h1>{{ .Title }}</h1>
<div class="event-meta">
<div class="meta-item">
<span class="meta-label">Date & Time</span>
<span class="meta-value">{{ .Params.date | dateFormat "Monday, January 2, 2006 at 3:04 PM" }}</span>
</div>
{{ if .Params.end_date }}
<div class="meta-item">
<span class="meta-label">End Time</span>
<span class="meta-value">{{ .Params.end_date | dateFormat "Monday, January 2, 2006 at 3:04 PM" }}</span>
</div>
{{ end }}
{{ if .Params.location }}
<div class="meta-item">
<span class="meta-label">Location</span>
<span class="meta-value">{{ .Params.location }}</span>
</div>
{{ end }}
{{ if .Params.organizer }}
<div class="meta-item">
<span class="meta-label">Organizer</span>
<span class="meta-value">{{ .Params.organizer }}</span>
</div>
{{ end }}
{{ if .Params.capacity }}
<div class="meta-item">
<span class="meta-label">Capacity</span>
<span class="meta-value">{{ .Params.capacity }} people</span>
</div>
{{ end }}
{{ if .Params.cost }}
<div class="meta-item">
<span class="meta-label">Cost</span>
<span class="meta-value">{{ .Params.cost }}</span>
</div>
{{ end }}
</div>
<div class="event-content">
{{ .Content }}
</div>
{{ if .Params.registration_url }}
<div class="registration">
<div class="ascii-border">
+--------------------------------------------------------------+
| REGISTRATION |
+--------------------------------------------------------------+
</div>
<p class="prompt"><a href="{{ .Params.registration_url }}">Register for this event</a></p>
</div>
{{ end }}
{{ if .Params.contact }}
<div class="contact">
<h3>Contact Information</h3>
<p>{{ .Params.contact }}</p>
</div>
{{ end }}
</article>
{{ end }}