diff --git a/.gitmodules b/.gitmodules
index e411f7f..1a43215 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,3 +1,6 @@
[submodule "themes/academic"]
path = themes/academic
url = https://github.com/gcushen/hugo-academic.git
+[submodule "themes/mainroad"]
+ path = themes/mainroad
+ url = https://github.com/vimux/mainroad
diff --git a/config.toml b/config.toml
new file mode 100644
index 0000000..01789fa
--- /dev/null
+++ b/config.toml
@@ -0,0 +1,78 @@
+baseurl = "/"
+title = "Rocket Nine Labs"
+languageCode = "en-us"
+paginate = "10" # Number of posts per page
+theme = "mainroad"
+disqusShortname = "" # Enable Disqus comments by entering your Disqus shortname
+googleAnalytics = "" # Enable Google Analytics by entering your tracking id
+
+[Author] # Used in authorbox
+ name = "Trevor Slocum"
+ bio = "Trevor is a software developer and system administrator."
+ avatar = "http://www.gravatar.com/avatar/5e7cc07a69488c7110d8a4f6df94c1b7?s=200"
+
+[Params]
+ subtitle = "" # Subtitle of your site. Used in site header
+ description = "Personal blog of Trevor Slocum, open source developer." # Site description. Used in meta description
+ copyright = "Trevor Slocum" # Footer copyright holder, otherwise will use site title
+ opengraph = true # Enable OpenGraph if true
+ twitter_cards = false # Enable Twitter Cards if true
+ readmore = false # Show "Read more" button in list if true
+ authorbox = true # Show authorbox at bottom of pages if true
+ toc = true # Enable Table of Contents
+ post_navigation = true # Show post navigation at bottom of pages if true
+ post_meta = ["date", "categories", "translations"] # Order of post meta information
+ mainSections = ["post", "blog", "news"] # Specify section pages to show on home page and the "Recent articles" widget
+ dateformat = "2006-01-02" # Change the format of dates
+ mathjax = false # Enable MathJax
+ mathjaxPath = "https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.6/MathJax.js" # Specify MathJax path
+ mathjaxConfig = "TeX-AMS-MML_HTMLorMML" # Specify MathJax config
+ highlightColor = "#e22d30" # Override highlight color
+ customCSS = ["css/custom.css"] # Include custom CSS files
+ customJS = ["js/custom.js"] # Include custom JS files
+
+[Params.sidebar]
+ home = "right" # Configure layout for home page
+ list = "left" # Configure layout for list pages
+ single = false # Configure layout for single pages
+ # Enable widgets in given order
+ widgets = ["social", "recent"]
+
+[Params.widgets]
+ recent_num = 5 # Set the number of articles in the "Recent articles" widget
+ tags_counter = false # Enable counter for each tag in "Tags" widget
+
+[Params.widgets.social]
+# # Enable parts of social widget
+# facebook = "username"
+# twitter = "username"
+# instagram = "username"
+# linkedin = "username"
+# telegram = "username"
+# github = "tslocum"
+# gitlab = "tslocum"
+# bitbucket = "username"
+ email = "trevor@rocketnine.space"
+
+# Custom social links
+[[Params.widgets.social.custom]]
+ title = "Public inbox"
+ url = "https://lists.sr.ht/~tslocum/public-inbox"
+
+[[Params.widgets.social.custom]]
+ title = "Sourcehut"
+ url = "https://git.sr.ht/~tslocum"
+
+[[Params.widgets.social.custom]]
+ title = "GitLab"
+ url = "https://gitlab.com/tslocum"
+
+[[Params.widgets.social.custom]]
+ title = "GitHub"
+ url = "https://github.com/tslocum"
+
+[[menu.main]]
+ name = "Home"
+ weight = -110
+ identifier = "Home"
+ url = "/"
diff --git a/config/_default/config.toml b/configold/_default/config.toml
similarity index 100%
rename from config/_default/config.toml
rename to configold/_default/config.toml
diff --git a/config/_default/languages.toml b/configold/_default/languages.toml
similarity index 100%
rename from config/_default/languages.toml
rename to configold/_default/languages.toml
diff --git a/config/_default/menus.toml b/configold/_default/menus.toml
similarity index 100%
rename from config/_default/menus.toml
rename to configold/_default/menus.toml
diff --git a/config/_default/params.toml b/configold/_default/params.toml
similarity index 100%
rename from config/_default/params.toml
rename to configold/_default/params.toml
diff --git a/content/donate/_index.md b/content/donate/_index.md
new file mode 100644
index 0000000..b2340e8
--- /dev/null
+++ b/content/donate/_index.md
@@ -0,0 +1,11 @@
+---
+title: Donate
+authorbox: false
+sidebar: true
+menu: main
+toc: false
+weight: 20
+paginate: 0
+---
+
+Please consider donating via [LiberaPay](https://liberapay.com/rocketnine.space).
diff --git a/content/home/about.md b/content/home/about.md
deleted file mode 100644
index 13d4539..0000000
--- a/content/home/about.md
+++ /dev/null
@@ -1,14 +0,0 @@
-+++
-# About widget.
-widget = "about" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = true # Activate this widget? true/false
-weight = 20 # Order that this section will appear in.
-
-title = "Biography"
-
-# Choose the user profile to display
-# This should be the username of a profile in your `content/authors/` folder.
-# See https://sourcethemes.com/academic/docs/get-started/#introduce-yourself
-author = "admin"
-+++
diff --git a/content/home/accomplishments.md b/content/home/accomplishments.md
deleted file mode 100644
index 6187c01..0000000
--- a/content/home/accomplishments.md
+++ /dev/null
@@ -1,51 +0,0 @@
-+++
-# Accomplishments widget.
-widget = "accomplishments" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = false # Activate this widget? true/false
-weight = 50 # Order that this section will appear.
-
-title = "Accomplishments"
-subtitle = ""
-
-# Date format
-# Refer to https://sourcethemes.com/academic/docs/customization/#date-format
-date_format = "Jan 2006"
-
-# Accomplishments.
-# Add/remove as many `[[item]]` blocks below as you like.
-# `title`, `organization` and `date_start` are the required parameters.
-# Leave other parameters empty if not required.
-# Begin/end multi-line descriptions with 3 quotes `"""`.
-
-[[item]]
- organization = "Coursera"
- organization_url = "https://www.coursera.org"
- title = "Neural Networks and Deep Learning"
- url = ""
- certificate_url = "https://www.coursera.org"
- date_start = "2018-10-01"
- date_end = ""
- description = ""
-
-[[item]]
- organization = "edX"
- organization_url = "https://www.edx.org"
- title = "Blockchain Fundamentals"
- url = "https://www.edx.org/professional-certificate/uc-berkeleyx-blockchain-fundamentals"
- certificate_url = "https://www.edx.org"
- date_start = "2018-03-01"
- date_end = ""
- description = "Formulated informed blockchain models, hypotheses, and use cases."
-
-[[item]]
- organization = "DataCamp"
- organization_url = "https://www.datacamp.com"
- title = "Object-Oriented Programming in R: S3 and R6 Course"
- url = ""
- certificate_url = "https://www.datacamp.com"
- date_start = "2017-07-01"
- date_end = "2017-12-21"
- description = ""
-
-+++
diff --git a/content/home/contact.md b/content/home/contact.md
deleted file mode 100644
index 6459d09..0000000
--- a/content/home/contact.md
+++ /dev/null
@@ -1,20 +0,0 @@
-+++
-# Contact widget.
-widget = "contact" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = true # Activate this widget? true/false
-weight = 130 # Order that this section will appear.
-
-title = "Contact"
-subtitle = ""
-
-# Automatically link email and phone?
-autolink = true
-
-# Email form provider
-# 0: Disable email form
-# 1: Netlify (requires that the site is hosted by Netlify)
-# 2: formspree.io
-email_form = 2
-+++
-
diff --git a/content/home/experience.md b/content/home/experience.md
deleted file mode 100644
index 79a125f..0000000
--- a/content/home/experience.md
+++ /dev/null
@@ -1,44 +0,0 @@
-+++
-# Experience widget.
-widget = "experience" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = false # Activate this widget? true/false
-weight = 40 # Order that this section will appear.
-
-title = "Experience"
-subtitle = ""
-
-# Date format for experience
-# Refer to https://sourcethemes.com/academic/docs/customization/#date-format
-date_format = "Jan 2006"
-
-# Experiences.
-# Add/remove as many `[[experience]]` blocks below as you like.
-# Required fields are `title`, `company`, and `date_start`.
-# Leave `date_end` empty if it's your current employer.
-# Begin/end multi-line descriptions with 3 quotes `"""`.
-[[experience]]
- title = "CEO"
- company = "GenCoin"
- company_url = ""
- location = "California"
- date_start = "2017-01-01"
- date_end = ""
- description = """
- Responsibilities include:
-
- * Analysing
- * Modelling
- * Deploying
- """
-
-[[experience]]
- title = "Professor"
- company = "University X"
- company_url = ""
- location = "California"
- date_start = "2016-01-01"
- date_end = "2016-12-31"
- description = """Taught electronic engineering and researched semiconductor physics."""
-
-+++
diff --git a/content/home/featured.md b/content/home/featured.md
deleted file mode 100644
index 6420c8f..0000000
--- a/content/home/featured.md
+++ /dev/null
@@ -1,64 +0,0 @@
-+++
-# A Featured Publications section created with the Featured Content widget.
-# This section displays publications from `content/publication/` which have
-# `featured = true` in their front matter.
-
-widget = "featured" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = false # Activate this widget? true/false
-weight = 80 # Order that this section will appear.
-
-title = "Featured Publications"
-subtitle = ""
-
-[content]
- # Page type to display. E.g. post, talk, or publication.
- page_type = "publication"
-
- # Choose how much pages you would like to display (0 = all pages)
- count = 0
-
- # Page order. Descending (desc) or ascending (asc) date.
- order = "desc"
-
- # Filter posts by a taxonomy term.
- [content.filters]
- tag = ""
- category = ""
- publication_type = ""
-
-[design]
- # Toggle between the various page layout types.
- # 1 = List
- # 2 = Compact
- # 3 = Card
- # 4 = Citation (publication only)
- view = 3
-
-[design.background]
- # Apply a background color, gradient, or image.
- # Uncomment (by removing `#`) an option to apply it.
- # Choose a light or dark text color by setting `text_color_light`.
- # Any HTML color name or Hex value is valid.
-
- # Background color.
- # color = "navy"
-
- # Background gradient.
- # gradient_start = "DeepSkyBlue"
- # gradient_end = "SkyBlue"
-
- # Background image.
- # image = "background.jpg" # Name of image in `static/img/`.
- # image_darken = 0.6 # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.
-
- # Text color (true=light or false=dark).
- # text_color_light = true
-
-[advanced]
- # Custom CSS.
- css_style = ""
-
- # CSS class.
- css_class = ""
-+++
diff --git a/content/home/hero.md b/content/home/hero.md
deleted file mode 100644
index 7b5bda0..0000000
--- a/content/home/hero.md
+++ /dev/null
@@ -1,55 +0,0 @@
-+++
-# Hero widget.
-widget = "hero" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = false # This file represents a page section.
-active = false # Activate this widget? true/false
-weight = 10 # Order that this section will appear.
-
-title = "Academic"
-
-# Hero image (optional). Enter filename of an image in the `static/img/` folder.
-hero_media = "hero-academic.png"
-
-[design.background]
- # Apply a background color, gradient, or image.
- # Uncomment (by removing `#`) an option to apply it.
- # Choose a light or dark text color by setting `text_color_light`.
- # Any HTML color name or Hex value is valid.
-
- # Background color.
- # color = "navy"
-
- # Background gradient.
- gradient_start = "#4bb4e3"
- gradient_end = "#2b94c3"
-
- # Background image.
- # image = "" # Name of image in `static/img/`.
- # image_darken = 0.6 # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.
-
- # Text color (true=light or false=dark).
- text_color_light = true
-
-# Call to action links (optional).
-# Display link(s) by specifying a URL and label below. Icon is optional for `[cta]`.
-# Remove a link/note by deleting a cta/note block.
-[cta]
- url = "https://sourcethemes.com/academic/docs/install/"
- label = "Get Started"
- icon_pack = "fas"
- icon = "download"
-
-[cta_alt]
- url = "https://sourcethemes.com/academic/"
- label = "View Documentation"
-
-# Note. An optional note to show underneath the links.
-[cta_note]
- label = 'Latest release'
-+++
-
-**The Best Way to Create the Website You Want from Markdown (or Jupyter/RStudio)**
-
-Build **Anything** with Widgets
-
-Star
diff --git a/content/home/index.md b/content/home/index.md
deleted file mode 100644
index ef8bad5..0000000
--- a/content/home/index.md
+++ /dev/null
@@ -1,5 +0,0 @@
-+++
-# Homepage
-type = "widget_page"
-headless = true # Homepage is headless, other widget pages are not.
-+++
diff --git a/content/home/people.md b/content/home/people.md
deleted file mode 100644
index 94a1b0b..0000000
--- a/content/home/people.md
+++ /dev/null
@@ -1,19 +0,0 @@
-+++
-# People widget.
-widget = "people" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = false # Activate this widget? true/false
-weight = 68 # Order that this section will appear.
-
-title = "People"
-subtitle = ""
-
-# List user groups to display.
-# Edit each user's `user_groups` to add them to one or more of these groups.
-user_groups = ["Principal Investigators",
- "Researchers",
- "Grad Students",
- "Administration",
- "Visitors",
- "Alumni"]
-+++
diff --git a/content/home/posts.md b/content/home/posts.md
deleted file mode 100644
index 12b3b6f..0000000
--- a/content/home/posts.md
+++ /dev/null
@@ -1,67 +0,0 @@
-+++
-# A Recent Blog Posts section created with the Pages widget.
-# This section displays recent blog posts from `content/post/`.
-
-widget = "pages" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = true # Activate this widget? true/false
-weight = 60 # Order that this section will appear.
-
-title = "Recent Posts"
-subtitle = ""
-
-[content]
- # Page type to display. E.g. post, talk, or publication.
- page_type = "post"
-
- # Choose how much pages you would like to display (0 = all pages)
- count = 5
-
- # Choose how many pages you would like to offset by
- offset = 0
-
- # Page order. Descending (desc) or ascending (asc) date.
- order = "desc"
-
- # Filter posts by a taxonomy term.
- [content.filters]
- tag = ""
- category = ""
- publication_type = ""
- exclude_featured = false
-
-[design]
- # Toggle between the various page layout types.
- # 1 = List
- # 2 = Compact
- # 3 = Card
- # 4 = Citation (publication only)
- view = 2
-
-[design.background]
- # Apply a background color, gradient, or image.
- # Uncomment (by removing `#`) an option to apply it.
- # Choose a light or dark text color by setting `text_color_light`.
- # Any HTML color name or Hex value is valid.
-
- # Background color.
- # color = "navy"
-
- # Background gradient.
- # gradient_start = "DeepSkyBlue"
- # gradient_end = "SkyBlue"
-
- # Background image.
- # image = "background.jpg" # Name of image in `static/img/`.
- # image_darken = 0.6 # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.
-
- # Text color (true=light or false=dark).
- # text_color_light = true
-
-[advanced]
- # Custom CSS.
- css_style = ""
-
- # CSS class.
- css_class = ""
-+++
diff --git a/content/home/projects.md b/content/home/projects.md
deleted file mode 100644
index 86bd567..0000000
--- a/content/home/projects.md
+++ /dev/null
@@ -1,77 +0,0 @@
-+++
-# A Projects section created with the Portfolio widget.
-widget = "portfolio" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = true # Activate this widget? true/false
-weight = 65 # Order that this section will appear.
-
-title = "Projects"
-subtitle = ""
-
-[content]
- # Page type to display. E.g. project.
- page_type = "project"
-
- # Filter toolbar (optional).
- # Add or remove as many filters (`[[content.filter_button]]` instances) as you like.
- # To show all items, set `tag` to "*".
- # To filter by a specific tag, set `tag` to an existing tag name.
- # To remove toolbar, delete/comment all instances of `[[content.filter_button]]` below.
-
- # Default filter index (e.g. 0 corresponds to the first `[[filter_button]]` instance below).
- filter_default = 0
-
- # [[content.filter_button]]
- # name = "All"
- # tag = "*"
-
- # [[content.filter_button]]
- # name = "Deep Learning"
- # tag = "Deep Learning"
-
- # [[content.filter_button]]
- # name = "Other"
- # tag = "Demo"
-
-[design]
- # Choose how many columns the section has. Valid values: 1 or 2.
- columns = "2"
-
- # Toggle between the various page layout types.
- # 1 = List
- # 2 = Compact
- # 3 = Card
- # 5 = Showcase
- view = 2
-
- # For Showcase view, flip alternate rows?
- flip_alt_rows = false
-
-[design.background]
- # Apply a background color, gradient, or image.
- # Uncomment (by removing `#`) an option to apply it.
- # Choose a light or dark text color by setting `text_color_light`.
- # Any HTML color name or Hex value is valid.
-
- # Background color.
- # color = "navy"
-
- # Background gradient.
- # gradient_start = "DeepSkyBlue"
- # gradient_end = "SkyBlue"
-
- # Background image.
- # image = "background.jpg" # Name of image in `static/img/`.
- # image_darken = 0.6 # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.
-
- # Text color (true=light or false=dark).
- # text_color_light = true
-
-[advanced]
- # Custom CSS.
- css_style = ""
-
- # CSS class.
- css_class = ""
-+++
-
diff --git a/content/home/publications.md b/content/home/publications.md
deleted file mode 100644
index 07a11f4..0000000
--- a/content/home/publications.md
+++ /dev/null
@@ -1,71 +0,0 @@
-+++
-# A Recent Publications section created with the Pages widget.
-# This section displays recent blog posts from `content/publication/`.
-
-widget = "pages" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = false # Activate this widget? true/false
-weight = 90 # Order that this section will appear.
-
-title = "Recent Publications"
-subtitle = ""
-
-[content]
- # Page type to display. E.g. post, talk, or publication.
- page_type = "publication"
-
- # Choose how much pages you would like to display (0 = all pages)
- count = 5
-
- # Choose how many pages you would like to offset by
- offset = 0
-
- # Page order. Descending (desc) or ascending (asc) date.
- order = "desc"
-
- # Filter posts by a taxonomy term.
- [content.filters]
- tag = ""
- category = ""
- publication_type = ""
- exclude_featured = false
-
-[design]
- # Toggle between the various page layout types.
- # 1 = List
- # 2 = Compact
- # 3 = Card
- # 4 = Citation (publication only)
- view = 2
-
-[design.background]
- # Apply a background color, gradient, or image.
- # Uncomment (by removing `#`) an option to apply it.
- # Choose a light or dark text color by setting `text_color_light`.
- # Any HTML color name or Hex value is valid.
-
- # Background color.
- # color = "navy"
-
- # Background gradient.
- # gradient_start = "DeepSkyBlue"
- # gradient_end = "SkyBlue"
-
- # Background image.
- # image = "background.jpg" # Name of image in `static/img/`.
- # image_darken = 0.6 # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.
-
- # Text color (true=light or false=dark).
- # text_color_light = true
-
-[advanced]
- # Custom CSS.
- css_style = ""
-
- # CSS class.
- css_class = ""
-+++
-
-{{% alert note %}}
-Quickly discover relevant content by [filtering publications]({{< ref "/publication/_index.md" >}}).
-{{% /alert %}}
diff --git a/content/home/skills.md b/content/home/skills.md
deleted file mode 100644
index bc0e4f1..0000000
--- a/content/home/skills.md
+++ /dev/null
@@ -1,35 +0,0 @@
-+++
-# A Skills section created with the Featurette widget.
-widget = "featurette" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = false # Activate this widget? true/false
-weight = 30 # Order that this section will appear.
-
-title = "Skills"
-subtitle = ""
-
-# Showcase personal skills or business features.
-#
-# Add/remove as many `[[feature]]` blocks below as you like.
-#
-# For available icons, see: https://sourcethemes.com/academic/docs/widgets/#icons
-
-[[feature]]
- icon = "r-project"
- icon_pack = "fab"
- name = "R"
- description = "90%"
-
-[[feature]]
- icon = "chart-line"
- icon_pack = "fas"
- name = "Statistics"
- description = "100%"
-
-[[feature]]
- icon = "camera-retro"
- icon_pack = "fas"
- name = "Photography"
- description = "10%"
-
-+++
diff --git a/content/home/slider.md b/content/home/slider.md
deleted file mode 100644
index 6ddc3be..0000000
--- a/content/home/slider.md
+++ /dev/null
@@ -1,54 +0,0 @@
-+++
-# Slider widget.
-widget = "slider" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = false # Activate this widget? true/false
-weight = 1 # Order that this section will appear.
-
-# Slide interval.
-# Use `false` to disable animation or enter a time in ms, e.g. `5000` (5s).
-interval = false
-
-# Slide height (optional).
-# E.g. `500px` for 500 pixels or `calc(100vh - 70px)` for full screen.
-height = ""
-
-# Slides.
-# Duplicate an `[[item]]` block to add more slides.
-[[item]]
- title = "Hello"
- content = "I am center aligned :smile:"
- align = "center" # Choose `center`, `left`, or `right`.
-
- # Overlay a color or image (optional).
- # Deactivate an option by commenting out the line, prefixing it with `#`.
- overlay_color = "#666" # An HTML color value.
- overlay_img = "headers/bubbles-wide.jpg" # Image path relative to your `static/img/` folder.
- overlay_filter = 0.5 # Darken the image. Value in range 0-1.
-
- # Call to action button (optional).
- # Activate the button by specifying a URL and button label below.
- # Deactivate by commenting out parameters, prefixing lines with `#`.
- cta_label = "Get Academic"
- cta_url = "https://sourcethemes.com/academic/"
- cta_icon_pack = "fas"
- cta_icon = "graduation-cap"
-
-[[item]]
- title = "Left"
- content = "I am left aligned :smile:"
- align = "left"
-
- overlay_color = "#555" # An HTML color value.
- overlay_img = "" # Image path relative to your `static/img/` folder.
- overlay_filter = 0.5 # Darken the image. Value in range 0-1.
-
-[[item]]
- title = "Right"
- content = "I am right aligned :smile:"
- align = "right"
-
- overlay_color = "#333" # An HTML color value.
- overlay_img = "" # Image path relative to your `static/img/` folder.
- overlay_filter = 0.5 # Darken the image. Value in range 0-1.
-+++
diff --git a/content/home/tags.md b/content/home/tags.md
deleted file mode 100644
index d550a28..0000000
--- a/content/home/tags.md
+++ /dev/null
@@ -1,22 +0,0 @@
-+++
-# Tag Cloud widget.
-widget = "tag_cloud" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = false # Activate this widget? true/false
-weight = 120 # Order that this section will appear.
-
-title = "Popular Topics"
-subtitle = ""
-
-[content]
- # Choose the taxonomy from `config.toml` to display (e.g. tags, categories)
- taxonomy = "tags"
-
- # Choose how many tags you would like to display (0 = all tags)
- count = 20
-
-[design]
- # Minimum and maximum font sizes (1.0 = 100%).
- font_size_min = 0.7
- font_size_max = 2.0
-+++
diff --git a/content/home/talks.md b/content/home/talks.md
deleted file mode 100644
index 4d2c0d3..0000000
--- a/content/home/talks.md
+++ /dev/null
@@ -1,69 +0,0 @@
-+++
-# A Recent and Upcoming Talks section created with the Pages widget.
-# This section displays recent talks from `content/talk/`.
-
-widget = "pages" # See https://sourcethemes.com/academic/docs/page-builder/
-headless = true # This file represents a page section.
-active = false # Activate this widget? true/false
-weight = 70 # Order that this section will appear.
-
-title = "Recent & Upcoming Talks"
-subtitle = ""
-
-[content]
- # Page type to display. E.g. post, talk, or publication.
- page_type = "talk"
-
- # Choose how much pages you would like to display (0 = all pages)
- count = 5
-
- # Choose how many pages you would like to offset by
- offset = 0
-
- # Page order. Descending (desc) or ascending (asc) date.
- order = "desc"
-
- # Filter posts by a taxonomy term.
- [content.filters]
- tag = ""
- category = ""
- publication_type = ""
- exclude_featured = false
- exclude_past = false
- exclude_future = false
-
-[design]
- # Toggle between the various page layout types.
- # 1 = List
- # 2 = Compact
- # 3 = Card
- # 4 = Citation (publication only)
- view = 2
-
-[design.background]
- # Apply a background color, gradient, or image.
- # Uncomment (by removing `#`) an option to apply it.
- # Choose a light or dark text color by setting `text_color_light`.
- # Any HTML color name or Hex value is valid.
-
- # Background color.
- # color = "navy"
-
- # Background gradient.
- # gradient_start = "DeepSkyBlue"
- # gradient_end = "SkyBlue"
-
- # Background image.
- # image = "background.jpg" # Name of image in `static/img/`.
- # image_darken = 0.6 # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.
-
- # Text color (true=light or false=dark).
- # text_color_light = true
-
-[advanced]
- # Custom CSS.
- css_style = ""
-
- # CSS class.
- css_class = ""
-+++
diff --git a/content/post/tetris-1.md b/content/post/tetris-1.md
index 9e354fe..75b2804 100644
--- a/content/post/tetris-1.md
+++ b/content/post/tetris-1.md
@@ -43,7 +43,7 @@ The number of blocks a mino has is also known as its rank.
Tetris is played on an [X-Y grid](https://en.wikipedia.org/wiki/Cartesian_coordinate_system).
We will store Minos as slices of points.
-```go
+{{< highlight go >}}
type Point struct {
X, Y int
}
@@ -56,7 +56,7 @@ func (p Point) Reflect() Point { return Point{-p.X, p.Y} }
type Mino []Point
var minoT = Mino{{0, 0}, {1, 0}, {2, 0}, {1, 1}}
-```
+{{< / highlight >}}
## Generation
@@ -69,7 +69,7 @@ To compare minos efficiently while generating, we will compare their string repr
We will define a String method which sorts the coordinates before printing.
This allows us to compare duplicate minos just by checking their string values.
-```go
+{{< highlight go >}}
func (m Mino) Len() int { return len(m) }
func (m Mino) Swap(i, j int) { m[i], m[j] = m[j], m[i] }
func (m Mino) Less(i, j int) bool {
@@ -96,11 +96,11 @@ func (m Mino) String() string {
return b.String()
}
-```
+{{< / highlight >}}
Origin returns a translated mino located at 0,0 and with positive coordinates only.
-```go
+{{< highlight go >}}
func (m Mino) minCoords() (int, int) {
minx := m[0].X
miny := m[0].Y
@@ -128,13 +128,13 @@ func (m Mino) Origin() Mino {
return newMino
}
-```
+{{< / highlight >}}
Another transformation is applied not only to help identify duplicate minos, but also to retrieve their initial rotation, as [pieces should spawn flat-side down](https://tetris.wiki/Super_Rotation_System).
The flattest side is calculated and a flattened mino is returned.
-```go
+{{< highlight go >}}
func (m Mino) Flatten() Mino {
var (
w, h = m.Size()
@@ -185,11 +185,11 @@ func (m Mino) Flatten() Mino {
return newMino
}
-```
+{{< / highlight >}}
Variations returns the three other rotations of a mino.
-```go
+{{< highlight go >}}
func (m Mino) Variations() []Mino {
v := make([]Mino, 3)
for i := 0; i < 3; i++ {
@@ -204,11 +204,11 @@ func (m Mino) Variations() []Mino {
return v
}
-```
+{{< / highlight >}}
Canonical returns a flattened mino translated to 0,0.
-```go
+{{< highlight go >}}
func (m Mino) Canonical() Mino {
var (
ms = m.Origin().String()
@@ -231,13 +231,13 @@ func (m Mino) Canonical() Mino {
return v[c].Origin().Flatten().Origin()
}
-```
+{{< / highlight >}}
### Generating new minos
Neighborhood returns the [Von Neumann neighborhood](https://en.wikipedia.org/wiki/Von_Neumann_neighborhood) of a point.
-```go
+{{< highlight go >}}
func (p Point) Neighborhood() []Point {
return []Point{
{p.X - 1, p.Y},
@@ -245,11 +245,11 @@ func (p Point) Neighborhood() []Point {
{p.X + 1, p.Y},
{p.X, p.Y + 1}}
}
-```
+{{< / highlight >}}
NewPoints calculates the neighborhood of each point of a mino and returns only the new points.
-```go
+{{< highlight go >}}
func (m Mino) HasPoint(p Point) bool {
for _, mp := range m {
if mp == p {
@@ -275,11 +275,11 @@ func (m Mino) NewPoints() []Point {
return newPoints
}
-```
+{{< / highlight >}}
NewMinos returns a new mino for every new neighborhood point of a supplied mino.
-```go
+{{< highlight go >}}
func (m Mino) NewMinos() []Mino {
points := m.NewPoints()
@@ -290,11 +290,11 @@ func (m Mino) NewMinos() []Mino {
return minos
}
-```
+{{< / highlight >}}
Generate procedurally generates minos of a supplied rank.
-```go
+{{< highlight go >}}
func Generate(rank int) ([]Mino, error) {
switch {
case rank < 0:
@@ -333,7 +333,7 @@ func Generate(rank int) ([]Mino, error) {
func monomino() Mino {
return Mino{{0, 0}}
}
-```
+{{< / highlight >}}
# Matrix
@@ -343,7 +343,7 @@ The matrix is typically 10 blocks wide and 20 blocks high.
A block is an integer representing the contents of a single X-Y coordinate on the matrix.
-```go
+{{< highlight go >}}
type Block int
const (
@@ -356,7 +356,7 @@ const (
BlockSolidGreen
BlockSolidOrange
)
-```
+{{< / highlight >}}
The matrix will be stored as a slice of blocks.
The zero-value of Block is a blank space.
@@ -364,7 +364,7 @@ The zero-value of Block is a blank space.
The matrix has a width, height and buffer height.
The buffer is additional space above the visible playfield.
-```go
+{{< highlight go >}}
type Matrix struct {
W int // Width
H in // Height
@@ -383,11 +383,11 @@ func NewMatrix(w int, h int, b int) *Matrix {
return &m
}
-```
+{{< / highlight >}}
To retrieve the contents of a point, we calculate its index by multiplying the Y coordinate with the matrix width and adding the X coordinate.
-```go
+{{< highlight go >}}
func I(x int, y int, w int) int {
if x < 0 || x >= w || y < 0 {
log.Panicf("failed to retrieve index for %d,%d width %d: invalid coordinates", x, y, w)
@@ -404,4 +404,4 @@ func (m *Matrix) Block(x int, y int) Block {
index := I(x, y, m.W)
return m.M[index]
}
-```
+{{< / highlight >}}
diff --git a/content/post/tview-and-you.md b/content/post/tview-and-you.md
index c1ab7d2..dcf2700 100644
--- a/content/post/tview-and-you.md
+++ b/content/post/tview-and-you.md
@@ -4,24 +4,15 @@ date: 2019-11-08T01:42:18-07:00
categories: [tutorial]
---
-
+[](https://github.com/rivo/tview/tree/master/demos/presentation)
-This is an introduction to using [tview](https://github.com/rivo/tview) to create rich terminal-based user interfaces with [Go](https://golang.org).
+This is an introduction to using [tview](https://github.com/rivo/tview) (or [cview](https://git.sr.ht/~tslocum/cview)) to create rich terminal-based user interfaces with [Go](https://golang.org).
-## Contents
-
-* [Primitives](#primitives)
-* [Widgets](#widgets)
- * [Elements](#widget-elements)
- * [Containers](#widget-containers)
-* [Thread Safety](#thread-safety)
-* [Example Application](#example-application)
-
-# Primitives
+## Primitives
The [Primitive](https://godoc.org/github.com/rivo/tview#Primitive) interface is as follows:
-```go
+{{< highlight go >}}
type Primitive interface {
Draw(screen tcell.Screen)
GetRect() (int, int, int, int)
@@ -31,18 +22,18 @@ type Primitive interface {
Blur()
GetFocusable() Focusable
}
-```
+{{< / highlight >}}
[Box](https://godoc.org/github.com/rivo/tview#Box) is the only primitive implemented.
It has a size, padding amount, optional border, optional title and background color.
-# Widgets
+## Widgets
Widgets are structs which embed a [Box](https://godoc.org/github.com/rivo/tview#Box) and build upon it.
From the [TextView](https://godoc.org/github.com/rivo/tview#TextView) declaration:
-```go
+{{< highlight go >}}
type TextView struct {
*Box
@@ -54,58 +45,58 @@ type TextView struct {
// ...
}
-```
+{{< / highlight >}}
Some widgets allow nesting other widgets within them, such as [Grid](https://godoc.org/github.com/rivo/tview#Grid).
Most widget commands may be chained together:
-```go
+{{< highlight go >}}
nameLabel := tview.NewTextView().
SetTextAlign(tview.AlignRight).
SetDynamicColors(true).
SetWrap(true).
SetWordWrap(true).
SetText("Please enter your name:")
-```
+{{< / highlight >}}
New widgets may be defined, as documented in the [Primitive demo](https://github.com/rivo/tview/tree/master/demos/primitive).
-## Widget Elements
+### Widget Elements
---
[**Button**](https://godoc.org/github.com/rivo/tview#Button) is a labeled box that triggers an action when selected.
-```go
+{{< highlight go >}}
button := tview.NewButton("OK").SetSelectedFunc(func() {
pressedOK()
})
-```
+{{< / highlight >}}
---
[**Checkbox**](https://godoc.org/github.com/rivo/tview#Checkbox) holds a label and boolean value which may be checked and unchecked.
-```go
+{{< highlight go >}}
checkbox := tview.NewCheckbox().SetLabel("Toggle value with Enter: ")
-```
+{{< / highlight >}}
---
[**DropDown**](https://godoc.org/github.com/rivo/tview#DropDown) holds one or more options which may be selected as a dropdown list.
-```go
+{{< highlight go >}}
dropdown := tview.NewDropDown().
SetLabel("Select an option with Enter: ").
SetOptions([]string{"Foo", "Bar", "Baz"}, nil)
-```
+{{< / highlight >}}
---
[**InputField**](https://godoc.org/github.com/rivo/tview#InputField) is a box where text may be entered.
-```go
+{{< highlight go >}}
inputField := tview.NewInputField().
SetLabel("Name: ").
SetPlaceholder("John Smith").
@@ -113,13 +104,13 @@ inputField := tview.NewInputField().
SetDoneFunc(func(key tcell.Key) {
processName()
})
-```
+{{< / highlight >}}
---
[**Modal**](https://godoc.org/github.com/rivo/tview#Modal) is a centered message window which may have one or more buttons.
-```go
+{{< highlight go >}}
modal := tview.NewModal().
SetText("Are you sure you want to exit?").
AddButtons([]string{"Cancel", "Quit"}).
@@ -128,23 +119,23 @@ modal := tview.NewModal().
app.Stop()
}
})
-```
+{{< / highlight >}}
---
[**TextView**](https://godoc.org/github.com/rivo/tview#TextView) is a box containing text.
[Colored text](https://godoc.org/github.com/rivo/tview#hdr-Colors) is supported when enabled.
-```go
+{{< highlight go >}}
textView := tview.NewTextView().
SetWrap(true).
SetWordWrap(true).
SetText("Hello, World!")
-```
+{{< / highlight >}}
---
-## Widget Containers
+### Widget Containers
---
@@ -190,7 +181,7 @@ See the [TreeView demo](https://github.com/rivo/tview/tree/master/demos/treeview
---
-# Thread Safety
+## Thread Safety
**Most tview functions cannot safely be called from any thread except the main one**.
@@ -205,13 +196,13 @@ One exception is [TextView.Write](https://godoc.org/github.com/rivo/tview#TextVi
Below is an example of setting a new root primitive from another goroutine.
-```go
+{{< highlight go >}}
app.QueueUpdateDraw(func() {
app.SetRoot(appGrid, true)
})
-```
+{{< / highlight >}}
-# Example Application
+## Example Application
A tview application is constructed of a running [Application](https://godoc.org/github.com/rivo/tview#Application) with at least one root widget.
@@ -223,13 +214,13 @@ In this example, the root is a Grid containing a label, an input and a submit bu
Install tview if you haven't already:
-```command
+{{< highlight command >}}
go get -u github.com/rivo/tview
-```
+{{< / highlight >}}
Then create a file named greet.go:
-```go
+{{< highlight go >}}
package main
import (
@@ -318,4 +309,4 @@ func main() {
log.Fatal(err)
}
}
-```
+{{< / highlight >}}
diff --git a/content/projects/_index.md b/content/projects/_index.md
new file mode 100644
index 0000000..a48e246
--- /dev/null
+++ b/content/projects/_index.md
@@ -0,0 +1,23 @@
+---
+title: Projects
+authorbox: false
+sidebar: true
+menu: main
+toc: false
+weight: 10
+---
+
+| Name | Description |
+| --- | --- |
+| [cview](https://git.sr.ht/~tslocum/cview) | Terminal-based user interface toolkit |
+| [ditty](https://git.sr.ht/~tslocum/ditty) | Audio player |
+| [gmenu](https://git.sr.ht/~tslocum/gmenu) | Desktop application launcher |
+| [gophast](https://git.sr.ht/~tslocum/gophast) | Download manager and accelerator
+| [harmony](https://git.sr.ht/~tslocum/harmony) | Voice and text communications platform
+| [joker](https://git.sr.ht/~tslocum/joker) | Playing card library
+| [Meditation Assistant](https://gitlab.com/tslocum/meditationassistant) | Feature packed meditation session timer and recorder
+| [netris](https://git.sr.ht/~tslocum/netris) | Multiplayer Tetris clone
+| [sage](https://git.sr.ht/~tslocum/sage) | Markov chain IRC bot
+| [sshtargate](https://git.sr.ht/~tslocum/sshtargate) | Host SSH portals to applications
+| [stick](https://git.sr.ht/~tslocum/stick) | Shareable Git-backed Markdown-formatted notes
+| [TinyIB](https://gitlab.com/tslocum/tinyib) | Lightweight image board |
diff --git a/static/index.webmanifest b/static/index.webmanifest
new file mode 100644
index 0000000..d5e541f
--- /dev/null
+++ b/static/index.webmanifest
@@ -0,0 +1,18 @@
+{
+ "name": "Rocket Nine Labs",
+ "short_name": "Rocket Nine Labs",
+ "lang": "en-us",
+ "theme_color": "#2962ff",
+ "background_color": "#2962ff",
+ "icons": [{
+ "src": "../img/icon-192.png",
+ "sizes": "192x192",
+ "type": "image/png"
+ }, {
+ "src": "../img/icon-512.png",
+ "sizes": "512x512",
+ "type": "image/png"
+ }],
+ "display": "standalone",
+ "start_url": "/?utm_source=web_app_manifest"
+}
diff --git a/themes/mainroad b/themes/mainroad
new file mode 160000
index 0000000..2b05d4b
--- /dev/null
+++ b/themes/mainroad
@@ -0,0 +1 @@
+Subproject commit 2b05d4b1956591cdf2fc692776be3b5efdde777c