add a blog (#371)

This commit is contained in:
Vish (Ishaya) Abrams 2024-11-12 09:26:53 -07:00 committed by GitHub
parent b633287590
commit fd22ffaf17
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
29 changed files with 483 additions and 9 deletions

View File

@ -1 +1 @@
3.3.0
3.3.5

View File

@ -3,6 +3,7 @@ source 'http://rubygems.org'
ruby File.read('.ruby-version').strip
gem 'sinatra'
gem 'builder'
gem 'thin'
gem 'maruku'
gem 'i18n'

View File

@ -2,13 +2,14 @@ GEM
remote: http://rubygems.org/
specs:
base64 (0.2.0)
builder (3.3.0)
concurrent-ruby (1.2.2)
daemons (1.4.1)
eventmachine (1.2.7)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
maruku (0.7.3)
mustermann (3.0.0)
mustermann (3.0.3)
ruby2_keywords (~> 0.0.1)
rack (2.2.8.1)
rack-protection (3.2.0)
@ -28,12 +29,13 @@ GEM
daemons (~> 1.0, >= 1.0.9)
eventmachine (~> 1.0, >= 1.0.4)
rack (>= 1, < 3)
tilt (2.3.0)
tilt (2.4.0)
PLATFORMS
ruby
DEPENDENCIES
builder
i18n
maruku
rack-ssl-enforcer
@ -42,7 +44,7 @@ DEPENDENCIES
thin
RUBY VERSION
ruby 3.3.0p0
ruby 3.3.5p100
BUNDLED WITH
2.4.10

13
blog/blog.md Normal file
View File

@ -0,0 +1,13 @@
## [Twelve-Factor App Methodology is now Open Source](/blog/open-source-announcement)
###### 12 Nov, 2024
### [Yehuda Katz](https://github.com/wycats)
![Yehuda Katz](/images/bios/yehuda.jpg) **Join us in modernizing the twelve-factor app manifesto together.** As a community of app, framework and platform developers, were working together to refresh this foundational document for the modern era. While its not software were working on, well use familiar processes like pull requests, issues, and reviews to collaborate together in the [twelve-factor project repo](https://github.com/twelve-factor/twelve-factor).
This initiative builds on a strong foundation laid by Heroku when they originally created "The Twelve-Factor App" all the way back in 2011, a time when container-based deployment was still just emerging. Back then, developers could get apps running on their local machines, but common development mistakes often made it challenging to deploy those apps to production. **[read on...](/blog/open-source-announcement)**
## [Narrow Conduits and the Application-Platform Interface](/blog/narrow-conduits)
###### 12 Nov, 2024
### [Vish Abrams](https://github.com/vishvananda)
![Vish Abrams](/images/bios/vish.jpg) Welcome to the twelve-factor maintainters blog. As stated in [our announcemnt](/blog/open-source-announcement), some of our posts will analyze the manifesto more generically. This is the first post in that vein, where we dive into the interface between the application and the platform.
It is well understood that defining a clear contract between parts of a system allows one to shed cognitive load on either side of the contract. This has been called the "narrow-waist" principle which has some unfortunate connotations, so we'll refer to it as the "narrow-conduit" principle. This principle is especially valuable when the humans on either side of the conduit have dramatically different concerns. **[read on...](/blog/narrow-conduits)**

27
blog/community.md Normal file
View File

@ -0,0 +1,27 @@
# Welcome to the Twelve-Factor community!
Thank you for your interest in the twelve-factor manifesto. Here are some suggestions for getting started with the community:
1. **Familiarize Yourself with the Project**
- Begin by reviewing the [Twelve-Factor Manifesto](https://12factor.net) to
see the current state.
- Check out the [Twelve-Factor Vision](https://github.com/twelve-factor/twelve-factor/blob/main/VISION.md) to understand the
project's goals and principles.
- Take a look at the [Twelve-Factor Governance document](https://github.com/twelve-factor/twelve-factor/blob/main/GOVERNANCE.md) to
familiarize yourself with how we operate.
2. **Join the Discussion**
- Participate in discussions on [open issues](https://github.com/twelve-factor/twelve-factor/issues).
- Broader discussions often happen on the [mailing
list](https://groups.google.com/g/twelve-factor)
- Near real-time collaboration happens on
[discord](https://discord.gg/9HFMDMt95z)
- Respectful dialogue and collaboration a key to our community's success.
3. **Find an Area to Contribute**
- Contributions come in many forms: documentation, bug fixes, new features,
or participating in discussions.
- Look for open issues on our GitHub repository that are tagged as [good
first issue](https://github.com/twelve-factor/twelve-factor/issues?q=is%3Aissue+is%3Aopen+label%3Agood+first+issue)
for beginners, or explore areas where you feel you can provide value.
- More details can be found in [The Contributing document](https://github.com/twelve-factor/twelve-factor/blob/main/CONTRIBUTING.md).

51
blog/maintainers.md Normal file
View File

@ -0,0 +1,51 @@
# Maintainers
## Vish Abrams
### Heroku/Salesforce
![Vish Abrams](/images/bios/vish.jpg) Vish Abrams is Chief Architect at Heroku, a subsidiary of Salesforce. Formerly he helped Oracle create their cloud, where he focused on virtualization, containerization, and machine learning. He was also NASA Nebula Technical Lead during the creation of Nova, one of the founding OpenStack projects, and was a member of both the OpenStack board and technical committee.
## Evan Anderson
### Stacklok (independent)
![Evan Anderson](/images/bios/evan.jpg) Evan worked for about 15 years in Google's cloud, with about 10 years in the public cloud. During that time, he was a founding member of the Google Compute Engine team, then worked on App Engine (control plane API), Cloud Functions, and Knative/Cloud Run. In 2019, he moved to VMware, where he spent 4 years on VMware Tandy, VMwares cloud-native developer platform. Hes also the author of "Designing Serverless Applications with Knative", and has held many leadership roles in Knative over the years.
## Gail Frederick
### Heroku/Salesforce
![Gail Frederick](/images/bios/gail.jpg) As Heroku CTO, Gail is a Salesforce leader known for her technical excellence and drive to deliver. She stewards the opinionated magic that is Herokus developer platform. Prior to Heroku, Gail led engineering for Salesforce DX. Her values are integrity, impact, and joy.
Previously, VP Engineering at eBay, where she was the 2019 winner of the John Donahoe Award, eBays highest leadership award, for building a new $3B annual GMB business by reinventing eBays developer ecosystem.
Member of 2024 Curve Power List of 50 LGBTQ+ women and non-binary leaders. Formerly, executive advisory board member of Lesbians Who Tech, Business Governing Board member of OpenAPI Initiative at the Linux Foundation, and represented eBay at the founding of the Facebook-led Libra Initiative.
Gail holds 9 software patents.
## Steren Giannini
### Google Cloud
![Steren Giannini](/images/bios/steren.jpg) Steren is an engineer turned product manager. He is leading product management for Google Cloud's serverless portfolio (Cloud Run, Cloud Run functions, App Engine). He is a founding member of Cloud Run.
[https://twitter.com/steren](https://twitter.com/steren)
[https://www.linkedin.com/in/steren](https://www.linkedin.com/in/steren)
[https://steren.fr](https://steren.fr)
## Brian Hammons
### AWS
![Brian Hammons](/images/bios/brian.jpg) Brian Hammons, a Principal Solutions Architect at AWS, is an original member of the launch team for Amazon EKS. He has held crucial roles in growing the service from its inception including co-founding projects such as eksworkshop.com, Data on EKS (DoEKS), and CNOE. Brian leads Application Modernization and Developer Productivity practice areas for AWS Strategic Industries as well as the Open Source Technical Field Community (TFC) of AWS Worldwide Specialists (WWSO).
## Grace Jansen
### IBM
![Grace Jansen](/images/bios/grace.jpg) Grace is a Java Champion and Developer Advocate at IBM. She has been with IBM since graduating with a Degree in Biology. Grace enjoys bringing a varied perspective to her projects and using her knowledge of biological systems to simplify complex software patterns. As a developer advocate, Grace builds POCs, demos, sample applications and tutorials. She is a regular presenter at international conferences and has authored a book on reactive systems.
## Yehuda Katz
### Heroku/Salesforce
![Yehuda Katz](/images/bios/yehuda.jpg) Yehuda is a True Believer in the power of the open web, especially when the web evolves as a collaboration between browser vendors, framework authors and application developers.
He is one of the creators of [Ember.js](http://www.emberjs.com/?ref=yehudakatz.com), and a retired member of the [Rust](http://www.rust-lang.org/?ref=yehudakatz.com), the Ruby on Rails and jQuery Core Teams. He is an occasional member of ECMAScript's TC39 standards committee, and a former member of the W3C's TAG ([Technical Architecture Group](http://www.w3.org/2001/tag/?ref=yehudakatz.com)).
He was the co-author of the [Extensible Web Manifesto](https://extensiblewebmanifesto.org/?ref=yehudakatz.com), of which he is still very proud.
## Joe Kutner
### Salesforce
![Joe Kutner](/images/bios/joe.jpg) Joe is co-founder of the Cloud Native Buildpacks project, which aims to make containerization more secure and developer friendly. He started the project in 2018 while working as DX Architect at Salesforce Heroku, and today is the DX Architect for Salesforces Hyperforce platform.
## Terence Lee
### Heroku/Salesforce
![Terence Lee](/images/bios/terence.jpg) Terence is an architect at Heroku where he helped create Classic Buildpacks and then later co-founded Cloud Native Buildpacks, a CNCF Incubation Project. In the Ruby community he's been a maintainer on projects such as Ruby itself, Bundler, and Resque, but is mostly known for getting people together for \#rubykaraoke. When hes not going to an awesome event, he lives in Austin, TX where it's acceptable to eat a taco for every meal of the day.
## James Ward
### AWS
![James Ward](/images/bios/james.jpg) Professional software developer since 1997, with much of that time spent helping developers build software that doesn't suck. A Typed Pure Functional Programming zealot who often compromises on his ideals to just get stuff done. Currently a Developer Advocate for AWS.
## Brett Weaver
### Intuit
![Brett Weaver](/images/bios/brett.jpg) Brett Weaver is a Distinguished Engineer at Intuit. He has spent the last twenty two odd years at Intuit in various software development and systems engineer roles. He has been focused on building distributed, scalable architectures for Intuits flagship products including Quickbooks and TurboTax. Most recently, Brett has been leading architecture for Intuits internal services platform.

22
blog/narrow-conduits.md Normal file
View File

@ -0,0 +1,22 @@
# Narrow Conduits and the Application-Platform Interface
###### 12 Nov, 2024
### [Vish Abrams](https://github.com/vishvananda)
![Vish Abrams](/images/bios/vish.jpg) Welcome to the twelve-factor maintainters blog. As stated in [our announcemnt](/blog/open-source-announcement), some of our posts will analyze the manifesto more generically. This is the first post in that vein, where we dive into the interface between the application and the platform.
It is well understood that defining a clear contract between parts of a system allows one to shed cognitive load on either side of the contract. This has been called the "narrow-waist" principle which has some unfortunate connotations, so we'll refer to it as the "narrow-conduit" principle. This principle is especially valuable when the humans on either side of the conduit have dramatically different concerns.
One way to think about twelve-factor as a whole is a narrow conduit between the application developer and the platform developer. The Manifesto provides other conduits as well, but this is a good place to start the discussion. Historically, for application developers this interface was source code, and the source code was ultimately handed off to an operations team. As software evolved through the era of DevOps, the hand-off morphed from code into a container image, with the development team generally taking on the container building duties.
As systems have become more distributed, the deployment and management of multiple containers have become the developers concern, with many companies focusing operations teams on building and maintaining a platform and development teams operating the systems themselves.
This has led to application developers writing code for container orchestration systems directly, often relying on templating systems like helm or infrastructure as code systems like terraform to do the heavy lifting. The challenge with this approach is that the world of the application developer is no longer simple. Development, build, and deployment concerns are all mixed together. We no longer have a narrow conduit.
In an ideal world an application developer would only need to worry about their source code and the platform would take care of everything else. Reducing the conduit aperture back to this level is challenging because it means eliminating features. It is necessary to ask: what functionality can we sacrifice on the altar of simplicity.
Ultimately, what we are looking for is a perfect balance: enough functionality to solve real problems, but not so much that we fall into the sea of complexity. The de-facto interface that has evolved between an application developer and the platform, the container orchestration system, is actually the wrong interface. It works, but it does not provide the cleanest and most valuable contract between the two worlds. Application developers should optimally stay focused on their application code. They need clear interfaces to be able to refer to connected systems from within the code. The container is a useful artifact for deployment consistency, but its existence is an implementation detail of the platform.
Instead, the contract needs to focus on how platform information makes its way into application code. For example: how does the application code know where it is reachable on the internet? How does it securely connect with other systems? It is the role of the platform to provide a mechanism for configuration information. Conversely, it is the role of the application to be built in a way that it can be deployed anywhere and scaled automatically so the platform can do its job.
One of the primary purposes of the twelve-factor update is to refresh this contract between the application and the platform in a way that makes both application developers and platform developers lives easier. Without this agreement, applications become special snowflakes that are both unmaintainable and un-operatable.
One of the most challenging aspects of this change is managing expectations for engineers that feel like they are losing something. Having access to a full orchestration system allows application developers to build anything, and shrinking the interface means reducing their power. The payoff is worth the loss: less application complexity and simplified operations. The cat is running wild, but we all benefit if we can find a way to coax it back into the bag.

View File

@ -0,0 +1,28 @@
# Twelve-Factor App Methodology is now Open Source
###### 12 Nov, 2024
### [Yehuda Katz](https://github.com/wycats)
![Yehuda Katz](/images/bios/yehuda.jpg) **Join us in modernizing the twelve-factor app manifesto together.** As a community of app, framework and platform developers, were working together to refresh this foundational document for the modern era. While its not software were working on, well use familiar processes like pull requests, issues, and reviews to collaborate together in the [twelve-factor project repo](https://github.com/twelve-factor/twelve-factor).
This initiative builds on a strong foundation laid by Heroku when they originally created "The Twelve-Factor App" all the way back in 2011, a time when container-based deployment was still just emerging. Back then, developers could get apps running on their local machines, but common development mistakes often made it challenging to deploy those apps to production.
The twelve-factor app started from a basic goal: you should be able to develop your app locally following your frameworks documentation and deploy it to production without tailoring it to a specific platform. To make this vision a reality, Twelve-Factor documented common pitfalls Heroku observed and organized them into a philosophy for building applications *designed* for deployment without *thinking* about deployment.
The philosophy of Twelve-Factor turned out to be surprisingly timeless. More than a decade later, people still find its insights valuable, and its often cited as a solid set of best practices for application development. But while the *concepts* remain relevant, many of the *details* have started to show their age.
Together with the community, we have begun an effort to refresh Twelve-Factor so people can apply its timeless concepts within the modern ecosystem. With Open Source governance, the refreshed Twelve-Factor will be a living document that evolves with the community, staying relevant as technology evolves.
Its been exciting to see the interest from the broader community and the collaboration that's starting to take shape. Our initial call for participation brought so many folks to the conversation and we are honored to have an amazing initial set of [maintainers](/community) to kick off the project. Together we have been collaborating to define the projects purpose and governance while taking the first steps to refine and modernize the principles.
The Twelve-Factor community is excited to continue this work. Meet our [maintainers](/community) and hear from them on their excitement and interest in the project:
"The twelve-factor application definition was an early signpost on the direction of serverless and best practices for writing distributed applications. Twelve-Factor and the Heroku experience were key inspirations for Knative and Google Cloud Run, and Im excited to be able to give back in updating these practices for the next generation of developers."
Evan Anderson (Independent)
"The twelve-factor principles captured a powerful simplicity that has influenced how we design applications for scalability and resilience. In updating these ideas, Im focused on clarifying what makes a twelve-factor app distinct and effective in a cloud-native world, maintaining that balance between restriction and operational power. By doubling down on these boundaries, we can ensure the manifesto remains as impactful today as it was in its first chapter." Vish Abrams (Chief Architect, Heroku)
“When I first encountered the twelve-factor application principles, it felt like a light bulb went off, and things clicked in my understanding of service development. These insights, drawn from both my own experience and the collective knowledge of others, have been instrumental in advancing system design in Intuit, as well as across the industry. I believe that, through collaboration with the community, we have a unique opportunity to shape the future of service and platform development for years to come.”
Brett Weaver (Distinguished Engineer, Intuit)
Well be sharing monthly updates on this blog about the changes were making as a community and whats next for the project. Youll also find analysis and discussion of the factors and software development more broadly. We plan to dive into trade-off discussions, explore Twelve-Factor from different perspectives, clarify the underlying principles were relying on, and provide case studies of twelve-factor implementations. The first analysis post is about [Narrow Conduits and the Application-Platform Interface](/blog/narrow-conduits).
Have an idea youd like to share or discuss? Join us on [Discord](https://discord.gg/9HFMDMt95z) wed love to see you at an upcoming community meeting.

3
blog/posts.md Normal file
View File

@ -0,0 +1,3 @@
## All Posts
### [Twelve-Factor App Methodology is now Open Source](/blog/open-source-announcement) by Yehuda Katz *12 Nov, 2024*
### [Narrow Conduits and the Application-Platform Interface](/blog/narrow-conduits) by Vish Abrams *12 Nov, 2024*

View File

@ -35,7 +35,7 @@
max-width: none;
}
article h1, article h2, article h3, article p, article table {
article h1, article h2, article h3, article h6, article p, article table {
padding-left: 15px;
padding-right: 15px;
}
@ -84,7 +84,7 @@
max-width: 480px;
}
article h1, article h2, article h3, article p, article table {
article h1, article h2, article h3, article h6, article p, article table {
padding-left: 15px;
padding-right: 15px;
text-align: left;
@ -118,4 +118,36 @@
padding-left: 0;
padding-right: 0;
}
.header-container {
justify-content: space-between;
padding: 1rem;
}
.title-wrapper {
flex: 1;
text-align: center;
}
.header-container h1 {
font-size: 18px; /* Slightly smaller font for small screens */
}
.top-nav {
position: static;
margin-left: auto;
display: flex;
margin-top: 1em;
justify-content: center;
}
.top-nav ul {
display: flex;
flex-direction: row;
}
.top-nav li {
margin-left: 0.5rem; /* Reduce spacing for small screens */
margin-right: 0.5rem; /* Reduce spacing for small screens */
}
}

View File

@ -173,4 +173,107 @@ article img.full {
height: 17px;
margin-bottom: -2px !important;
margin-right: 5px;
}
.header-container {
position: relative;
justify-content: space-between;
align-items: center;
padding: 1rem;
padding-right: 2rem;
box-sizing: border-box;
width: 100%;
}
.title-wrapper {
flex: 1;
text-align: center;
}
.header-container h1 {
margin: 0;
}
.top-nav {
position: absolute;
right: 2rem; /* Position the navigation links on the right side */
top: 25%;
transform: translateY(-25%); /* Vertically center-align the links */
z-index: 2;
}
.top-nav ul {
display: flex;
list-style: none;
margin: 0;
padding: 0;
}
.top-nav li {
margin-left: 1rem;
}
.top-nav a {
text-decoration: none;
color: #fff;
font-size: 14px;
}
.top-nav a:hover {
text-decoration: underline;
}
.github-button {
margin-top: -4px;
margin-left: -4px;
display: flex;
align-items: center;
background-color: #0366d6; /* GitHub blue color */
color: #ffffff;
padding: 6px 12px;
border-radius: 20px; /* Rounded corners */
transition: background-color 0.3s ease;
}
a.github-button:hover {
background-color: #024ea2; /* Darker blue on hover */
text-decoration: none;
}
.github-logo {
width: 20px;
height: 20px;
margin-right: 6px;
}
.blog img {
float: left;
margin-right: 15px;
margin-bottom: 10px;
width: 100px;
height: auto;
border-radius: 5px;
margin-left: 0px;
}
.blog h6 {
color: darkgray;
font-size: 0.9em; /* Make it slightly smaller than default heading sizes */
font-weight: normal; /* Make it less bold to differentiate from main headings */
margin-top: 0; /* Remove extra margin at the top */
margin-bottom: 5px; /* Minimal spacing below the date */
}
.maintainers img {
float: left;
margin-right: 15px;
margin-bottom: 10px;
width: 100px;
height: auto;
border-radius: 5px;
margin-left: 0px;
}
.maintainers h2 {
clear: both;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 93 KiB

BIN
public/images/bios/evan.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

BIN
public/images/bios/gail.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

BIN
public/images/bios/joe.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

BIN
public/images/bios/vish.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

View File

@ -0,0 +1 @@
<svg width="98" height="96" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M48.854 0C21.839 0 0 22 0 49.217c0 21.756 13.993 40.172 33.405 46.69 2.427.49 3.316-1.059 3.316-2.362 0-1.141-.08-5.052-.08-9.127-13.59 2.934-16.42-5.867-16.42-5.867-2.184-5.704-5.42-7.17-5.42-7.17-4.448-3.015.324-3.015.324-3.015 4.934.326 7.523 5.052 7.523 5.052 4.367 7.496 11.404 5.378 14.235 4.074.404-3.178 1.699-5.378 3.074-6.6-10.839-1.141-22.243-5.378-22.243-24.283 0-5.378 1.94-9.778 5.014-13.2-.485-1.222-2.184-6.275.486-13.038 0 0 4.125-1.304 13.426 5.052a46.97 46.97 0 0 1 12.214-1.63c4.125 0 8.33.571 12.213 1.63 9.302-6.356 13.427-5.052 13.427-5.052 2.67 6.763.97 11.816.485 13.038 3.155 3.422 5.015 7.822 5.015 13.2 0 18.905-11.404 23.06-22.324 24.283 1.78 1.548 3.316 4.481 3.316 9.126 0 6.6-.08 11.897-.08 13.526 0 1.304.89 2.853 3.316 2.364 19.412-6.52 33.405-24.935 33.405-46.691C97.707 22 75.788 0 48.854 0z" fill="#24292f"/></svg>

After

Width:  |  Height:  |  Size: 963 B

5
views/blog.erb Normal file
View File

@ -0,0 +1,5 @@
<section class="abstract" id="post">
<article class="blog">
<%= render_post('blog') %>
</article>
</section>

11
views/community.erb Normal file
View File

@ -0,0 +1,11 @@
<section class="abstract" id="post">
<article>
<%= render_post('community') %>
</article>
</section>
<section class="concrete">
<article class="maintainers">
<%= render_post('maintainers') %>
</article>
</section>

View File

@ -8,7 +8,9 @@
<meta name="author" content="Adam Wiggins">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="images/favicon.ico">
<link rel="canonical" href="<%= request.url %>">
<%= alternate_links %>
<link rel="shortcut icon" href="/images/favicon.ico">
<link rel="stylesheet" href="/css/screen.css" media="screen">
<link rel="stylesheet" href="/css/mobile.css" media="screen">
@ -30,7 +32,35 @@
<% end %>
<header>
<h1><a href="./" title="The Twelve-Factor App">The Twelve-Factor App</a></h1>
<div class="header-container">
<% if request.path_info.start_with?('/blog') %>
<div class="title-wrapper">
<h1><a href="/blog" title="The Twelve-Factor Blog">The Twelve-Factor Blog</a></h1>
</div>
<div class="top-nav">
<ul>
<li><a href="/">App</a></li>
<li><a href="/community">Community</a></li>
<li><a href="https://github.com/twelve-factor/twelve-factor" class="github-button">
<img src="/images/github-mark.svg" alt="GitHub logo" class="github-logo">GitHub
</a></li>
</ul>
</div>
<% else %>
<div class="title-wrapper">
<h1><a href="/" title="The Twelve-Factor App">The Twelve-Factor App</a></h1>
</div>
<div class="top-nav">
<ul>
<li><a href="/blog">Blog</a></li>
<li><a href="/community">Community</a></li>
<li><a href="https://github.com/twelve-factor/twelve-factor" class="github-button">
<img src="/images/github-mark.svg" alt="GitHub logo" class="github-logo">GitHub
</a></li>
</ul>
</div>
<% end %>
</div>
</header>
<%= yield %>

5
views/login.erb Normal file
View File

@ -0,0 +1,5 @@
<form action="/login" method="POST">
<h2><%= @error_message %></h2>
<label>Password: <input type="password" name="password"></label>
<button type="submit">Submit</button>
</form>

9
views/post.erb Normal file
View File

@ -0,0 +1,9 @@
<section class="abstract" id="post">
<article class="blog">
<%= render_post(@post) %>
</article>
</section>
<section class="concrete">
<article><%= render_post('posts') %></article>
</section>

133
web.rb
View File

@ -13,8 +13,27 @@ end
before do
I18n.locale = I18n.default_locale
if request.host == 'www.12factor.com'
redirect request.url.sub("//www.", "//"), 301
end
if ENV['PASSWORD']
unless session[:authorized]
@error_message = nil
unless params[:password] == ENV['PASSWORD']
unless request.path == '/login' || request.path == '/favicon.ico'
session[:original_path] = request.path
end
@error_message = 'Please enter the password to continue.' if params[:password]
halt erb(:login, layout: false)
end
session[:authorized] = true
end
end
end
enable :sessions
before '/:locale/*' do
locale = params[:locale].to_sym
if locale != I18n.default_locale && I18n.available_locales.include?(locale)
@ -23,19 +42,124 @@ before '/:locale/*' do
end
end
post '/login' do
if params[:password] == ENV['PASSWORD']
session[:authorized] = true
redirect session[:original_path] || '/'
else
@error_message = 'Incorrect password, please try again.'
erb :login, layout: false
end
end
get '/' do
erb :home
end
get '/blog' do
erb :blog
end
get '/community' do
erb :community
end
TOC = %w(codebase dependencies config backing-services build-release-run processes port-binding concurrency disposability dev-prod-parity logs admin-processes)
POSTS = %w(open-source-announcement narrow-conduits)
get '/blog/:post' do |post|
halt 404 unless POSTS.include?(post)
@post = post
erb :post
end
MAIN_PATHS = %w(/ /blog /community)
# Generate XML Sitemap
get '/sitemap.xml' do
content_type 'application/xml'
# Generate the sitemap XML
builder do |xml|
xml.instruct! :xml, version: "1.0", encoding: "UTF-8"
xml.urlset xmlns: "http://www.sitemaps.org/schemas/sitemap/0.9" do
# Generate URLs for each main path
MAIN_PATHS.each do |path|
I18n.available_locales.each do |locale|
loc = locale == I18n.default_locale ? path : "/#{locale}#{path}"
xml.url do
xml.loc URI.join(request.base_url, loc).to_s
xml.lastmod Time.now.strftime("%Y-%m-%d")
xml.changefreq 'weekly'
xml.priority '0.8'
end
end
end
# Generate URLs for each Twelve-Factor topic
TOC.each do |factor|
I18n.available_locales.each do |locale|
loc = locale == I18n.default_locale ? "/#{factor}" : "/#{locale}/#{factor}"
xml.url do
xml.loc URI.join(request.base_url, loc).to_s
xml.lastmod Time.now.strftime("%Y-%m-%d")
xml.changefreq 'monthly'
xml.priority '0.6'
end
end
end
# Generate URLs for each blog post
POSTS.each do |post|
I18n.available_locales.each do |locale|
loc = locale == I18n.default_locale ? "/blog/#{post}" : "/#{locale}/blog/#{post}"
xml.url do
xml.loc URI.join(request.base_url, loc).to_s
xml.lastmod Time.now.strftime("%Y-%m-%d")
xml.changefreq 'monthly'
xml.priority '0.7'
end
end
end
end
end
end
get '/:factor' do |factor|
halt 404 unless TOC.include?(factor)
@factor = factor
erb :factor
end
end
helpers do
def alternate_links
links = [
"<link rel=\"alternate\" hreflang=\"x-default\" href=\"#{default_url}\">"
]
links += I18n.available_locales.map do |locale|
href = locale == I18n.default_locale ? default_url : locale_url(locale)
"<link rel=\"alternate\" hreflang=\"#{locale}\" href=\"#{href}\">"
end
links.join("\n")
end
def default_url
uri = URI(request.url)
uri.path = request.path_info
uri.to_s
end
def locale_url(locale)
uri = URI(request.url)
uri.path = "/#{locale}#{request.path_info}"
uri.to_s
end
def render_markdown(file)
markdown = File.read("content/#{I18n.locale}/#{file}.md", :encoding => 'utf-8')
Maruku.new(markdown).to_html
@ -43,6 +167,13 @@ helpers do
puts "No content for #{I18n.locale}/#{file}, skipping"
end
def render_post(file)
markdown = File.read("blog/#{file}.md", :encoding => 'utf-8')
Maruku.new(markdown).to_html
rescue Errno::ENOENT
puts "No content for #{I18n.locale}/#{file}, skipping"
end
def render_prev(factor)
idx = TOC.index(factor)
return if idx == 0