460 lines
No EOL
22 KiB
HTML
460 lines
No EOL
22 KiB
HTML
---
|
|
title: "Mastodon documentation revamp"
|
|
summary: "Reorganizing the documentation for the Mastodon Project, while also rewriting significant portions of it."
|
|
author: "Abdullah Tarawneh"
|
|
date: "2020-01-04"
|
|
start: "Aug 2019"
|
|
end: "Jan 2020"
|
|
at: "Mastodon"
|
|
position: "Information Architect / Documentation Specialist"
|
|
tags: ["mastodon", "documentation", "information architecture", "rest api"]
|
|
category: "Work"
|
|
cover: "/images/cover/mastodocs.jpg"
|
|
---
|
|
|
|
<main id="mastodon">
|
|
<header class="page-header section">
|
|
<div class="container">
|
|
<svg xmlns="http://www.w3.org/2000/svg" width="64" height="64" viewBox="0 0 216.4144 232.00976">
|
|
<path fill="#fff" d="M211.80734 139.0875c-3.18125 16.36625-28.4925 34.2775-57.5625 37.74875-15.15875 1.80875-30.08375 3.47125-45.99875 2.74125-26.0275-1.1925-46.565-6.2125-46.565-6.2125 0 2.53375.15625 4.94625.46875 7.2025 3.38375 25.68625 25.47 27.225 46.39125 27.9425 21.11625.7225 39.91875-5.20625 39.91875-5.20625l.8675 19.09s-14.77 7.93125-41.08125 9.39c-14.50875.7975-32.52375-.365-53.50625-5.91875C9.23234 213.82 1.40609 165.31125.20859 116.09125c-.365-14.61375-.14-28.39375-.14-39.91875 0-50.33 32.97625-65.0825 32.97625-65.0825C49.67234 3.45375 78.20359.2425 107.86484 0h.72875c29.66125.2425 58.21125 3.45375 74.8375 11.09 0 0 32.975 14.7525 32.975 65.0825 0 0 .41375 37.13375-4.59875 62.915"/>
|
|
<path fill="#3088d4" d="M177.50984 80.077v60.94125h-24.14375v-59.15c0-12.46875-5.24625-18.7975-15.74-18.7975-11.6025 0-17.4175 7.5075-17.4175 22.3525v32.37625H96.20734V85.42325c0-14.845-5.81625-22.3525-17.41875-22.3525-10.49375 0-15.74 6.32875-15.74 18.7975v59.15H38.90484V80.077c0-12.455 3.17125-22.3525 9.54125-29.675 6.56875-7.3225 15.17125-11.07625 25.85-11.07625 12.355 0 21.71125 4.74875 27.8975 14.2475l6.01375 10.08125 6.015-10.08125c6.185-9.49875 15.54125-14.2475 27.8975-14.2475 10.6775 0 19.28 3.75375 25.85 11.07625 6.36875 7.3225 9.54 17.22 9.54 29.675"/>
|
|
</svg>
|
|
<h1 class="title">I reorganized and rewrote the docs for an open-source project with millions of users.
|
|
</h1>
|
|
</div>
|
|
</header>
|
|
<section class="section" id="about">
|
|
<div class="container">
|
|
<h2 class="title">About the client</h2>
|
|
<p><a href="https://joinmastodon.org" target="_blank">Mastodon</a> is a free and libre open-source software
|
|
project that aims to let anyone easily host their own Twitter-like social media website. Started in 2016,
|
|
the project has since grown due to various migrations, usually spurred by the failures and mistakes of the
|
|
dominant, centralized social platforms.</p>
|
|
<p>I have been using Mastodon since November 2016 -- you can <a href="https://mastodon.social/@trwnh"
|
|
target="_blank">view my profile at mastodon.social/@trwnh</a> if you would like -- and I have grown to
|
|
quite enjoy my experience there over the years. It reminds me a lot of the early days of Twitter... before
|
|
<a href="/blog/twitter-not-social" target="_blank">they gave up on being a social network</a>, anyway.</p>
|
|
<p>One of the things I love most about the culture on there is that it's very much focused on people rather
|
|
than content or engagement. This significantly lowers social friction and makes everyone more or less
|
|
approachable. So approachable, in fact, that I could casually reply to the creator and founder of Mastodon
|
|
and get this gig out of nowhere:</p>
|
|
|
|
<div class="conversation">
|
|
<!--
|
|
<iframe src="https://mastodon.social/@Gargron/102640868158739158/embed" class="mastodon-embed"
|
|
style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe>
|
|
<script src="https://mastodon.social/embed.js" async="async"></script>
|
|
|
|
<iframe src="https://mastodon.social/@trwnh/102640952580526770/embed" class="mastodon-embed"
|
|
style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe>
|
|
<script src="https://mastodon.social/embed.js" async="async"></script>
|
|
|
|
<iframe src="https://mastodon.social/@Gargron/102641022258942590/embed" class="mastodon-embed"
|
|
style="max-width: 100%; border: 0" width="400" allowfullscreen="allowfullscreen"></iframe>
|
|
<script src="https://mastodon.social/embed.js" async="async"></script>
|
|
-->
|
|
|
|
<article style="width: 100%; max-width: 80ch; padding: 1em; background: #313543; color: #fff; border-bottom: 1px solid #393f4f;">
|
|
<a target="_blank" href="https://mastodon.social/@Gargron" style="color: inherit; text-decoration: none; display: flex; margin-bottom: 15px;">
|
|
<div style="border-radius: 4px; overflow: hidden; margin-right: 10px; width: 48px; height: 48px;">
|
|
{{< people/gargron >}}
|
|
</div>
|
|
<div style="line-height: 1.5">
|
|
<div style="font-weight: 500;">Eugen</div>
|
|
<div style="color: #d9e1e8">@Gargron@mastodon.social</div>
|
|
</div>
|
|
</a>
|
|
<div style="font-size: 19px; line-height: 24px;">
|
|
<p style="margin-bottom: 25px;">
|
|
I really want the Mastodon documentation to have a good structure rather than just all information thrown together in a pile. I'm not sure how though.
|
|
</p>
|
|
<a target="_blank" href="https://mastodon.social/@Gargron/102640868158739158" style="font-size: 14px; line-height: 18px; margin-top: 25px; color: #606984; display: block;">August 18, 2019, 7:42 PM</a>
|
|
</div>
|
|
</article>
|
|
|
|
<article style="width: 100%; max-width: 80ch; padding: 1em; background: #313543; color: #fff; border-bottom: 1px solid #393f4f;">
|
|
<a target="_blank" href="https://mastodon.social/@trwnh" style="color: inherit; text-decoration: none; display: flex; margin-bottom: 15px;">
|
|
<img src="/images/people/avatar.png" width=48 height=48 alt="trwnh's avatar" style="border-radius: 4px; margin-right: 10px; width: 48px; height: 48px;">
|
|
<div style="line-height: 1.5">
|
|
<div style="font-weight: 500;">infinite love ⴳ</div>
|
|
<div style="color: #d9e1e8">@trwnh@mastodon.social</div>
|
|
</div>
|
|
</a>
|
|
<div style="font-size: 19px; line-height: 24px;">
|
|
<p style="margin-bottom: 25px;">
|
|
<a style="color: #d9e1e8" href="https://mastodon.social/@Gargron">@Gargron</a> i'd be willing to take a stab at it, having just cleaned up a lot of docs for pixelfed. it's still incomplete but it's much less messy than it used to be. i would need to sit down and try to map it out with you first, though.
|
|
</p>
|
|
<a target="_blank" href="https://mastodon.social/@trwnh/102640952580526770" style="font-size: 14px; line-height: 18px; margin-top: 25px; color: #606984; display: block;">August 18, 2019, 8:04 PM</a>
|
|
</div>
|
|
</article>
|
|
|
|
<article style="width: 100%; max-width: 80ch; padding: 1em; background: #313543; color: #fff;">
|
|
<a target="_blank" href="https://mastodon.social/@Gargron" style="color: inherit; text-decoration: none; display: flex; margin-bottom: 15px;">
|
|
<div style="border-radius: 4px; overflow: hidden; margin-right: 10px; width: 48px; height: 48px;">
|
|
{{< people/gargron >}}
|
|
</div>
|
|
<div style="line-height: 1.5">
|
|
<div style="font-weight: 500;">Eugen</div>
|
|
<div style="color: #d9e1e8">@Gargron@mastodon.social</div>
|
|
</div>
|
|
</a>
|
|
<div style="font-size: 19px; line-height: 24px;">
|
|
<p style="margin-bottom: 25px;">
|
|
<a style="color: #d9e1e8" href="https://mastodon.social/@trwnh">@trwnh</a> Okay, let's do it. Paid, of course.
|
|
</p>
|
|
<a target="_blank" href="https://mastodon.social/@Gargron/102641022258942590" style="font-size: 14px; line-height: 18px; margin-top: 25px; color: #606984; display: block;">August 18, 2019, 8:21 PM</a>
|
|
</div>
|
|
</article>
|
|
|
|
</div>
|
|
|
|
<p>So... yeah, that's how this all happened.</p>
|
|
</div>
|
|
</section>
|
|
<!--
|
|
<section class="section" id="overview">
|
|
<div class="container">
|
|
<h2 class="title">So, what did all this entail?</h2>
|
|
<section id="ia">
|
|
<h3 class="subtitle">Information Architecture</h3>
|
|
<p></p>
|
|
</section>
|
|
<section id="writing">
|
|
<h3 class="subtitle">Documentation Writing</h3>
|
|
<p></p>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
-->
|
|
<section class="section" id="process">
|
|
<div class="container">
|
|
<h2 class="title">Let me show you what I did.</h2>
|
|
<section id="user">
|
|
<h3 class="subtitle">A brand new user guide</h3>
|
|
<div class="structure">
|
|
<div class="old card">
|
|
<h4 class="card__head">User guide</h4>
|
|
<ul class="card__body">
|
|
<li>Basics</li>
|
|
<li>Decentralization</li>
|
|
<li>Privacy</li>
|
|
<li>Moderation</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<p>Many of the pages in the old user guide did not actually deal with teaching people how to use Mastodon,
|
|
so the content within them was reworked into a more general landing page that explained the benefits of
|
|
Mastodon. This new landing page explains the basics of microblogging and federation, before moving into
|
|
the practical implications that these decisions have for user freedom, privacy, and safety. Select
|
|
quotations were included from previously published promotional material on the Mastodon blog.</p>
|
|
|
|
<div class="structure">
|
|
<div class="new card">
|
|
<h4 class="card__head">What is Mastodon?</h4>
|
|
<ul class="card__body">
|
|
<li>What is a microblog?</li>
|
|
<li>What is federation?</li>
|
|
<li>What is ActivityPub?</li>
|
|
<li>Practical implications</li>
|
|
<ul>
|
|
<li>Choice of server provider and policy</li>
|
|
<li>Funding and monetization</li>
|
|
<li>Interoperability between different software</li>
|
|
<li>Free/libre software</li>
|
|
</ul>
|
|
<li>Choose your path</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<p>After this, an entirely new user guide was outlined from scratch, covering the user life cycle from start
|
|
to end (or new beginning).</p>
|
|
|
|
<div class="structure">
|
|
<div class="new card">
|
|
<h4 class="card__head">Using Mastodon</h4>
|
|
<ul class="card__body">
|
|
<li>Signing up for a new account</li>
|
|
<li>Setting up your profile</li>
|
|
<li>Posting toots</li>
|
|
<li>Using the network features</li>
|
|
<li>Dealing with unwanted content</li>
|
|
<li>Promoting yourself and others</li>
|
|
<li>Set your preferences</li>
|
|
<li>More settings</li>
|
|
<li>Using Mastodon externally</li>
|
|
<li>Moving or leaving accounts</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<p>
|
|
With the information architecture phase done, writing the user guide was a straightforward task.
|
|
Explanations of each feature and setting were added to the appropriate pages, as well as screenshots
|
|
demonstrating proper usage. Tip boxes are included throughout in order to highlight important points.
|
|
</p>
|
|
|
|
</section>
|
|
<section id="admin">
|
|
<h3 class="subtitle">A more expressive admin guide</h3>
|
|
<div class="structure">
|
|
<div class="old card">
|
|
<h4 class="card__head">Admin guide</h4>
|
|
<ul class="card__body">
|
|
<li>Installation</li>
|
|
<li>Configuration</li>
|
|
<li>Post-installation steps</li>
|
|
<li>Scaling up</li>
|
|
<li>Optional features</li>
|
|
<li>Upgrading to a new release</li>
|
|
<li>Migrating servers</li>
|
|
<li>Troubleshooting</li>
|
|
</ul>
|
|
</div>
|
|
<div class="new card">
|
|
<h4 class="card__head">Running Mastodon</h4>
|
|
<ul class="card__body">
|
|
<li>Preparing your machine</li>
|
|
<li>Installing from source</li>
|
|
<li>Configuring your environment</li>
|
|
<li>Installing optional features</li>
|
|
<li>Setting up your new instance</li>
|
|
<li>Using the admin CLI</li>
|
|
<li>Upgrading to a new release</li>
|
|
<li>Backing up your server</li>
|
|
<li>Migrating to a new machine</li>
|
|
<li>Scaling up your server</li>
|
|
<li>Moderation actions</li>
|
|
<li>Troubleshooting errors</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<p>This section was mostly straightened out already, but could still use some improvements. A
|
|
pre-installation page was split out from the old installation page. Backup instructions were moved out of
|
|
"Optional features" and into a dedicated page. Pages were added for moderation and CLI usage.</p>
|
|
</section>
|
|
<section id="dev">
|
|
<h3 class="subtitle">Giving developers more complete documentation</h3>
|
|
<div class="structure">
|
|
<div class="old card">
|
|
<h4 class="card__head">Development guide</h4>
|
|
<ul class="card__body">
|
|
<li>Overview</li>
|
|
<li>ActivityPub compliance</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<p>The old "overview" page contained a mixture of information about setting up a dev environment, libraries
|
|
used, code structure, and useful commands to run for testing.</p>
|
|
<p>The first step in cleaning this up was to split this page into multiple discrete pages, each with its own
|
|
purpose. As "development" is a vague term, two new sections were created to replace it: one for client
|
|
development (merged with API), and one for server development. The old "overview" pages were nested under
|
|
the server development section, as they dealt primarily with server development.</p>
|
|
<p>Next, "ActivityPub compliance" was moved into a dedicated section for spec compliance, and pages were
|
|
created for documenting how various significant specifications were used and implemented within Mastodon.
|
|
</p>
|
|
<div class="structure">
|
|
<div class="new card">
|
|
<h4 class="card__head">Contributing to Mastodon</h4>
|
|
<ul class="card__body">
|
|
<li>Technical overview</li>
|
|
<li>Setting up a dev environment</li>
|
|
<li>Code structure</li>
|
|
<li>Routes</li>
|
|
</ul>
|
|
</div>
|
|
<div class="new card">
|
|
<h4 class="card__head">Spec compliance</h4>
|
|
<ul class="card__body">
|
|
<li>ActivityPub</li>
|
|
<li>WebFinger</li>
|
|
<li>Security</li>
|
|
<li>Microformats</li>
|
|
<li>OAuth</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<p>
|
|
While the basics of ActivityPub federation were already written, the format of the old document simply
|
|
pointed toward the server-to-server spec, as well as HTTP Signatures and Linked Data Signatures (with no
|
|
real explanation beyond that). Therefore, I rewrote this page into multiple separate pages, each
|
|
detailing the spec in question. The "ActivityPub" page now covers status federation and profile
|
|
federation, the properties and types used in each, HTML payload sanitization, namespacing, and extensions
|
|
(with sample payloads). "WebFinger" explains what, why, and how to use WebFinger for actor URI
|
|
resolution. "Security" explains HTTP and LD signatures. "Microformats" explains the use of Microformats
|
|
2.0 and how they may be parsed, and "OAuth" covers the endpoints and flows implemented within Mastodon
|
|
for obtaining a token.
|
|
</p>
|
|
</section>
|
|
<section id="api">
|
|
<h3 class="subtitle">Helping client apps use the API</h3>
|
|
<div class="structure">
|
|
<div class="old card">
|
|
<h4 class="card__head">API Overview</h4>
|
|
<ul class="card__body">
|
|
<li>Guidelines</li>
|
|
<li>Libraries</li>
|
|
<li>Authentication</li>
|
|
<li>Permissions</li>
|
|
<li>Entities</li>
|
|
<li>Parameters</li>
|
|
<li>Streaming API</li>
|
|
<li>Web Push API</li>
|
|
</ul>
|
|
</div>
|
|
<div class="old card">
|
|
<h4 class="card__head">REST API</h4>
|
|
<ul class="card__body">
|
|
<li>Accounts</li>
|
|
<li>Apps</li>
|
|
<li>...</li>
|
|
<li>Timelines</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<p>This was the majority of the work. Mastodon's REST API documentation was really messy, and it showed.
|
|
Finding something generally entailed flipping back and forth between multiple pages and searching within
|
|
them, and each page was very long.</p>
|
|
<p>The first step was to promote methods and entities into their own sections. The "Entities" page was split
|
|
into multiple pages, one per entity, and alphabetized. Tables were converted into headings, to allow for
|
|
providing more information about each field.</p>
|
|
<p>Methods were grouped by namespace rather than by feature-set, and with one level of nesting depending on
|
|
whether the methods within pertained to accounts, statuses, timelines, notifications, etc. The pages for
|
|
the Streaming and Web Push APIs were moved out of the overview section and into the methods section.</p>
|
|
<p>Finally, a new section was created for a client development guide. The guide would cover the basics of
|
|
REST API, how to make requests, how responses are structured, and authentication/authorization.</p>
|
|
<div class="structure new">
|
|
<div class="new card">
|
|
<h4 class="card__head">Developing Mastodon Apps</h4>
|
|
<ul class="card__body">
|
|
<li>Getting started with the API</li>
|
|
<li>Playing with public data</li>
|
|
<li>Obtaining client app access</li>
|
|
<li>Logging in with an account</li>
|
|
<li>Guidelines and best practices</li>
|
|
<li>Libraries and implementations</li>
|
|
</ul>
|
|
</div>
|
|
<div class="new card">
|
|
<h4 class="card__head">REST API</h4>
|
|
<ul class="card__body">
|
|
<li>OAuth Scopes</li>
|
|
</ul>
|
|
</div>
|
|
<div class="new card methods">
|
|
<h4 class="card__head">API Methods</h4>
|
|
<ul class="card__body">
|
|
<li>apps</li>
|
|
<ul>
|
|
<li>oauth</li>
|
|
</ul>
|
|
<li>accounts</li>
|
|
<ul>
|
|
<li>bookmarks</li>
|
|
<li>favourites</li>
|
|
<li>mutes</li>
|
|
<li>...</li>
|
|
</ul>
|
|
<li>statuses</li>
|
|
<ul>
|
|
<li>media</li>
|
|
<li>polls</li>
|
|
<li>scheduled_statuses</li>
|
|
</ul>
|
|
<li>timelines</li>
|
|
<ul>
|
|
<li>conversations</li>
|
|
<li>lists</li>
|
|
<li>markers</li>
|
|
<li>streaming</li>
|
|
</ul>
|
|
<li>notifications</li>
|
|
<ul>
|
|
<li>push</li>
|
|
</ul>
|
|
<li>search</li>
|
|
<li>instance</li>
|
|
<ul>
|
|
<li>trends</li>
|
|
<li>directory</li>
|
|
<li>custom_emoji</li>
|
|
</ul>
|
|
<li>admin</li>
|
|
<li>proofs</li>
|
|
<li>oembed</li>
|
|
</ul>
|
|
</div>
|
|
<div class="new card entities">
|
|
<h4 class="card__head">API Entities</h4>
|
|
<ul class="card__body">
|
|
<li>Account</li>
|
|
<li>Activity</li>
|
|
<li>Admin::Account</li>
|
|
<li>Admin::Report</li>
|
|
<li>...</li>
|
|
<li>Status</li>
|
|
<li>Tag</li>
|
|
<li>Token</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<p>Writing this section taught me a lot about the basics of REST APIs, understanding HTTP requests and
|
|
responses, providing parameters, and how OAuth works -- all information that I included in the client
|
|
development guide.</p>
|
|
<p>While documenting the REST API, I had to consult the Ruby on Rails routing config file extensively, so I
|
|
took it as an opportunity to write a page about how routes work and how to read the routes file.</p>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
<section class="section" id="outcomes">
|
|
<div class="container">
|
|
<h2 class="title">The results were very much appreciated.</h2>
|
|
<blockquote class="praise">
|
|
bless you for being here to work on the docs btw it's a big relief
|
|
</blockquote>
|
|
<div class="attribution">
|
|
{{< people/gargron >}}
|
|
<cite><em>Eugen "Gargron" Rochko</em><br>Mastodon founder<br>& lead developer</cite>
|
|
</div>
|
|
<section class="benefit one">
|
|
<h3 class="subtitle">There was much less missing information.</h3>
|
|
<p>During the information architecture phase, a new skeleton was created as a proposed alternative structure.
|
|
This process made the existing gaps in the old structure more obvious, and therefore those gaps could be
|
|
filled during the technical writing phase.</p>
|
|
</section>
|
|
<section class="benefit two">
|
|
<h3 class="subtitle">It was also easier to make additions in an appropriate place.</h3>
|
|
<p>For example, the following pages were added after completion:</p>
|
|
<ul>
|
|
<li>"Rate limits" was added under "REST API", describing how to deal with rate limits on requests made to
|
|
the REST API.</li>
|
|
<li>"Bug bounties and responsible disclosure" was added under "Contributing to Mastodon", describing where
|
|
serious issues should be reported if found.</li>
|
|
<li>"Running your own server" was added under "Using Mastodon", describing the reasons why a user might want
|
|
to run their own server and linking to the "Running Mastodon" section.</li>
|
|
</ul>
|
|
<p>The clear structure left in place by my information architecture work meant that it was almost immediately
|
|
clear where to add these pages.</p>
|
|
</section>
|
|
<section class="benefit three">
|
|
<h3 class="subtitle">The quality and formatting of the docs was vastly improved.</h3>
|
|
<p>Methods now include the HTTP verb, endpoint, description, return type, OAuth scope, version history, request
|
|
parameters, and sample response code and payload.</p>
|
|
<p>Entities now include example payloads, as well as each attribute and its description, type, and version
|
|
history.</p>
|
|
</section>
|
|
</div>
|
|
</section>
|
|
<hr class="separator">
|
|
<section class="section" id="cta">
|
|
<div class="container">
|
|
<h2 class="title">Maybe you'd appreciate me doing something similar for you?</h2>
|
|
<img src="/images/cover/mastodocs.jpg" alt="Mastodon documentation landing page">
|
|
<div class="buttons">
|
|
<a href="https://docs.joinmastodon.org" class="demo button"><svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512" width=16><path fill="currentColor" d="M336.5 160C322 70.7 287.8 8 248 8s-74 62.7-88.5 152h177zM152 256c0 22.2 1.2 43.5 3.3 64h185.3c2.1-20.5 3.3-41.8 3.3-64s-1.2-43.5-3.3-64H155.3c-2.1 20.5-3.3 41.8-3.3 64zm324.7-96c-28.6-67.9-86.5-120.4-158-141.6 24.4 33.8 41.2 84.7 50 141.6h108zM177.2 18.4C105.8 39.6 47.8 92.1 19.3 160h108c8.7-56.9 25.5-107.8 49.9-141.6zM487.4 192H372.7c2.1 21 3.3 42.5 3.3 64s-1.2 43-3.3 64h114.6c5.5-20.5 8.6-41.8 8.6-64s-3.1-43.5-8.5-64zM120 256c0-21.5 1.2-43 3.3-64H8.6C3.2 212.5 0 233.8 0 256s3.2 43.5 8.6 64h114.6c-2-21-3.2-42.5-3.2-64zm39.5 96c14.5 89.3 48.7 152 88.5 152s74-62.7 88.5-152h-177zm159.3 141.6c71.4-21.2 129.4-73.7 158-141.6h-108c-8.8 56.9-25.6 107.8-50 141.6zM19.3 352c28.6 67.9 86.5 120.4 158 141.6-24.4-33.8-41.2-84.7-50-141.6h-108z"/></svg>Check out the live
|
|
version</a>
|
|
<a href="mailto:a@trwnh.com" class="email button primary"><svg version="1.1" viewBox="0 -256 1850 1850" width=16 height=16 xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"> <g transform="matrix(1 0 0 -1 30.373 1252.3)"> <path d="m1792 826v-794q0-66-47-113t-113-47h-1472q-66 0-113 47t-47 113v794q44-49 101-87 362-246 497-345 57-42 92.5-65.5t94.5-48 110-24.5h2q51 0 110 24.5t94.5 48 92.5 65.5q170 123 498 345 57 39 100 87zm0 294q0-79-49-151t-122-123q-376-261-468-325-10-7-42.5-30.5t-54-38-52-32.5-57.5-27-50-9h-2q-23 0-50 9t-57.5 27-52 32.5-54 38-42.5 30.5q-91 64-262 182.5t-205 142.5q-62 42-117 115.5t-55 136.5q0 78 41.5 130t118.5 52h1472q65 0 112.5-47t47.5-113z" fill="currentColor"/> </g> </svg>Email me a proposal</a>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
</main> |