diff --git a/.gitignore b/.gitignore
index d816e73..ad5742a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+.hugo_build.lock
assets/mastodon-archive/*.json
assets/mastodon-archive/avatar.*
assets/mastodon-archive/header.*
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..410193f
--- /dev/null
+++ b/README.md
@@ -0,0 +1 @@
+# hugo-content-adapter-mastodon
\ No newline at end of file
diff --git a/content/mastodon-archive/_content.gotmpl b/content/mastodon-archive/_content.gotmpl
new file mode 100644
index 0000000..8ca5afc
--- /dev/null
+++ b/content/mastodon-archive/_content.gotmpl
@@ -0,0 +1,166 @@
+{{ with resources.GetMatch "mastodon-archive/avatar.*" }}
+
+ {{ $avatar_content := dict "mediaType" .MediaType.Type "value" .Content }}
+ {{ $avatar_resource := dict
+ "path" (printf "avatar.%s" (index .MediaType.Suffixes 0))
+ "content" $avatar_content
+ }}
+ {{ $.AddResource $avatar_resource }}
+
+{{ end }}
+
+{{ with resources.GetMatch "mastodon-archive/header.*" }}
+
+ {{ $header_content := dict "mediaType" .MediaType.Type "value" .Content }}
+ {{ $header_resource := dict
+ "path" (printf "header.%s" (index .MediaType.Suffixes 0))
+ "content" $header_content
+ }}
+ {{ $.AddResource $header_resource }}
+
+{{ end }}
+
+{{ with unmarshal (resources.Get "mastodon-archive/actor.json") }}
+
+ {{ $account_page := dict
+ "path" "."
+ "kind" "section"
+ "title" .name
+ "summary" (.summary | plainify)
+ "content" (dict
+ "mediaType" "text/html"
+ "value" ""
+ )
+ "type" "mastodon"
+ "layout" "user"
+ "params" (dict
+ "mastodon" (dict
+ "_model" "Account"
+ "username" .preferredUsername
+ "created_at" (.published | time)
+ "note" .summary
+ "display_name" .name
+ )
+ )
+ }}
+ {{ $.AddPage $account_page }}
+
+{{ end }}
+
+{{ with unmarshal (resources.Get "mastodon-archive/outbox.json") }}
+
+ {{ $total := .totalItems }}
+ {{ $activities := last 1000 .orderedItems }}
+
+ {{ range $activities }}
+
+ {{ $published := .published | time }}
+
+ {{/* Extract database ID to use as a path later */}}
+ {{ $status_id :=
+ .id
+ | strings.TrimPrefix .actor
+ | strings.TrimPrefix "/statuses/"
+ | strings.TrimSuffix "/activity"
+ }}
+
+ {{/* Calculate Mastodon-style visibility scope */}}
+ {{ $followers := printf "%s/followers" .actor }}
+ {{ $visibility := "direct" }}
+ {{ if or
+ (in .to "https://www.w3.org/ns/activitystreams#Public")
+ (in .to "as:Public")
+ (in .to "Public")
+ }}
+ {{ $visibility = "public" }}
+ {{ else if or
+ (in .cc "https://www.w3.org/ns/activitystreams#Public")
+ (in .cc "as:Public")
+ (in .cc "Public")
+ }}
+ {{ $visibility = "unlisted" }}
+ {{ else if or
+ (in .to $followers)
+ (in .cc $followers)
+ }}
+ {{ $visibility = "private" }}
+ {{ end }}
+
+ {{/* Convert Create activities into a status */}}
+ {{ if eq .type "Create" }}
+
+ {{/* Initialize Hugo Page and add it */}}
+ {{ $page := dict
+ "path" $status_id
+ "content" (dict
+ "mediaType" "text/html"
+ "value" .object.content
+ )
+ "dates" (dict
+ "date" $published
+ )
+ "type" "mastodon"
+ "layout" "status"
+ "params" (dict
+ "mastodon" (dict
+ "_model" "Status"
+ "_post_type" "original"
+ "id" $status_id
+ "visibility" $visibility
+ "spoiler_text" .object.summary
+ )
+ )
+ }}
+ {{ $.AddPage $page }}
+
+ {{ else if eq .type "Announce" }}
+
+ {{ $page := dict
+ "path" $status_id
+ "dates" (dict
+ "date" $published
+ )
+ "type" "mastodon"
+ "layout" "status"
+ "params" (dict
+ "mastodon" (dict
+ "_model" "Status"
+ "_post_type" "reblog"
+ "_reblog_of_uri" .object
+ )
+ )
+ }}
+ {{ $.AddPage $page }}
+
+ {{ else }}
+
+ {{ $page := dict
+ "path" $status_id
+ "dates" (dict
+ "date" $published
+ )
+ "params" (dict
+ "mastodon" (dict
+ "_model" ""
+ "_post_type" "unknown"
+ )
+ )
+ }}
+ {{ $.AddPage $page }}
+
+ {{ end }}
+
+ {{/* Add the activity as a resource */}}
+
+ {{ $resource := dict
+ "path" (printf "%s/activity" $status_id)
+ "content" (dict
+ "mediaType" "application/json"
+ "value" (jsonify .)
+ )
+ }}
+ {{ $.AddResource $resource }}
+
+ {{ end }}
+
+{{ end }}
\ No newline at end of file
diff --git a/content/mastodon-live-activitypub/_content.gotmpl b/content/mastodon-live-activitypub/_content.gotmpl
new file mode 100644
index 0000000..a98f7b9
--- /dev/null
+++ b/content/mastodon-live-activitypub/_content.gotmpl
@@ -0,0 +1,72 @@
+{{ $actor_data := dict }}
+{{ $actor_url := "https://mastodon.social/users/trwnh.json" }}
+{{ with resources.GetRemote $actor_url }}
+ {{ with .Err }}
+ {{ errorf "Unable to get remote resource %s: %s" $actor_url . }}
+ {{ else }}
+ {{ $actor_data = . | unmarshal }}
+ {{ end }}
+{{ else }}
+ {{ errorf "Unable to get remote resource %s" $actor_url }}
+{{ end }}
+
+{{ with $actor_data }}
+
+ {{ $username := .preferredUsername }}
+
+ {{/* Fetch and save avatar */}}
+ {{ $avatar_url := .icon.url }}
+ {{ with resources.GetRemote $avatar_url }}
+ {{ with .Err }}
+ {{ warnf "Unable to get avatar from %s with error: %s" $avatar_url . }}
+ {{ else }}
+ {{ $avatar_content := dict "mediaType" .MediaType.Type "value" .Content }}
+ {{ $avatar_resource := dict
+ "path" (printf "avatar.%s" (index .MediaType.Suffixes 0))
+ "content" $avatar_content
+ }}
+ {{ $.AddResource $avatar_resource }}
+ {{ end }}
+ {{ end }}
+
+ {{/* Fetch and save header */}}
+ {{ $header_url := .image.url }}
+ {{ with resources.GetRemote $header_url }}
+ {{ with .Err }}
+ {{ warnf "Unable to get header from %s with error: %s" $avatar_url . }}
+ {{ else }}
+ {{ $header_content := dict "mediaType" .MediaType.Type "value" .Content }}
+ {{ $header_resource := dict
+ "path" (printf "header.%s" (index .MediaType.Suffixes 0))
+ "content" $header_content
+ }}
+ {{ $.AddResource $header_resource }}
+ {{ end }}
+ {{ end }}
+
+ {{/* Add account page */}}
+ {{ $account_page := dict
+ "path" "."
+ "kind" "section"
+ "title" .name
+ "summary" (.summary | plainify)
+ "content" (dict
+ "mediaType" "text/html"
+ "value" ""
+ )
+ "type" "mastodon"
+ "layout" "user"
+ "params" (dict
+ "mastodon" (dict
+ "_model" "Account"
+ "username" .preferredUsername
+ "created_at" (.published | time)
+ "note" .summary
+ "display_name" .name
+
+ )
+ )
+ }}
+ {{ $.AddPage $account_page }}
+
+{{ end }}
\ No newline at end of file
diff --git a/hugo.toml b/hugo.toml
new file mode 100644
index 0000000..56e4dc4
--- /dev/null
+++ b/hugo.toml
@@ -0,0 +1,7 @@
+baseURL = 'https://example.org/'
+languageCode = 'en-us'
+title = 'My New Hugo Site'
+
+[caches.getresource]
+dir = ':resourceDir/_cache/:project'
+maxage = -1
\ No newline at end of file
diff --git a/layouts/mastodon/baseof.html b/layouts/mastodon/baseof.html
new file mode 100644
index 0000000..7349dcc
--- /dev/null
+++ b/layouts/mastodon/baseof.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+ {{.Title}}
+ {{ block "head" . }}
+ {{ end }}
+
+{{ block "body" . }}
+
+
+
+{{ end }}
+
\ No newline at end of file
diff --git a/layouts/mastodon/status.html b/layouts/mastodon/status.html
new file mode 100644
index 0000000..0161bdd
--- /dev/null
+++ b/layouts/mastodon/status.html
@@ -0,0 +1,38 @@
+{{ define "head" }}
+
+{{ end }}
+
+{{ define "body" }}
+
+
+ Mastodon/Status view
+
+ Status
+
+ {{ with .Params.mastodon.spoiler_text }}
+ {{.}}
+ {{ end }}
+
+ {{ with .Content }}
+ {{.}}
+ {{ end }}
+
+ Status params
+
+
+ {{ range $k, $v := .Params.mastodon }}
+ - {{$k}}
+ - {{$v}}
+ {{ end }}
+
+
+ Activity
+ {{ with .Resources.Get "activity" }}
+ {{.Content | unmarshal | jsonify (dict "indent" " ") }}
+ {{ end }}
+
+
+
+{{ end }}
\ No newline at end of file
diff --git a/layouts/mastodon/statuses.html b/layouts/mastodon/statuses.html
new file mode 100644
index 0000000..6ae68ab
--- /dev/null
+++ b/layouts/mastodon/statuses.html
@@ -0,0 +1,28 @@
+{{ define "head" }}
+
+{{ end }}
+
+{{ define "body" }}
+
+
+ Mastodon/Statuses view
+
+ {{ range where .RegularPages.ByDate "Params.mastodon.visibility" "public" }}
+ -
+ {{ with .Params.mastodon._reblog_of_uri }}
+
Reblogged {{ . }}
+ {{ else }}
+ {{ with .Params.mastodon.spoiler_text }}
+ {{.}}
+ {{ end }}
+ {{.Content}}
+ {{ end }}
+ {{.Permalink}}
+
+ {{ end }}
+
+
+
+{{ end }}
\ No newline at end of file
diff --git a/layouts/mastodon/user.html b/layouts/mastodon/user.html
new file mode 100644
index 0000000..0bb8c06
--- /dev/null
+++ b/layouts/mastodon/user.html
@@ -0,0 +1,226 @@
+{{ define "head" }}
+
+{{ end }}
+
+{{ define "body" }}
+
+
+ Mastodon/User view
+
+ Account
+
+ {{ $header := .Resources.GetMatch "header.*" }}
+ {{ with $header }}
+
+ {{ else }}
+
+ {{ end }}
+ {{ $avatar := .Resources.GetMatch "avatar.*" }}
+ {{ with $avatar }}
+
+ {{ end }}
+
+
+
{{ .Params.mastodon.display_name }}
+
{{ .Params.mastodon.note | safeHTML }}
+
Created
+
+
+
+ Statuses
+ {{ with where .RegularPages "Params.mastodon.visibility" "public" }}
+
+ {{ range . }}
+ -
+ {{ partial "mastodon/status.html" (dict "status_ctx" . "account_ctx" $) }}
+
+ {{ end }}
+
+ {{ else }}
+ No statuses
+ {{ end }}
+
+
+
+{{ end }}
\ No newline at end of file
diff --git a/layouts/partials/mastodon/status.html b/layouts/partials/mastodon/status.html
new file mode 100644
index 0000000..7fb188d
--- /dev/null
+++ b/layouts/partials/mastodon/status.html
@@ -0,0 +1,18 @@
+{{ $status := .status_ctx }}
+{{ $account := .account_ctx }}
+{{ $avatar := $account.Resources.GetMatch "avatar.*" }}
+
+
+
+ {{ with $status.Params.mastodon.spoiler_text }}
+ {{ . }}
+ {{ end }}
+
+
+ {{ $status.Content }}
+
+
\ No newline at end of file