Repository: oddbird/oddleventy
Pull request #819: Office Hours Service
Author: login: SondraE
Created: 2025-03-05T21:33:35Z | Merged: 2025-03-06T17:06:12Z

## Related Issue(s)
[541](https://github.com/oddbird/oddleventy/issues/541)

## Steps to test/reproduce
/services/consulting/



Diff:
diff --git a/content/services/consulting.md b/content/services/consulting.md
new file mode 100644
index 000000000..1eb86de5d
--- /dev/null
+++ b/content/services/consulting.md
@@ -0,0 +1,218 @@
+---
+title: Office Hours Coaching
+sub: Coaching designers and developers in web best practices
+index: Office Hours Coaching
+image:
+  src: pages/open-sign.jpg
+  alt: door with an open sign
+  position: 20% 40%
+action:
+  text: Request office hours coaching »
+  url: /contact/
+summary: |
+    We love helping people solve
+    complex technology and design problems!
+    Schedule a chat
+    with your favorite OddBird
+    for 1 hour or multiple sessions
+    about anything related to
+    brand or UX Design, CSS,
+    JavaScript, Django, or Python.
+---
+
+{% import 'embed.macros.njk' as embed %}
+{% import 'quotes.macros.njk' as quotes %}
+{% import 'layout.macros.njk' as layout %}
+
+{% call layout.block(
+  name='full',
+  attrs={'class': 'has-angles'}
+) %}
+
+## What to Expect ...
+
+{% call layout.grid('inner') %}
+
+{% call layout.block('column') %}
+
+### Expert Code Review
+
+Chat with top developers
+working at the cutting edge
+of front-end, design systems,
+and W3C standards.
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### Troubleshooting Help
+
+Get a new perspective
+on a thorny design or development issue,
+and find ways to make your app
+more performant and scalable.
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### More Intuitive Designs
+
+Talk through quick and easy options
+to make your website or app
+more accessible and intuitive
+for the people who visit.
+
+{% endcall %}
+
+{% endcall %}
+
+{% endcall %}
+
+{{ layout.title('Topics') }}
+
+{% call embed.media_block(
+  media=embed.screen(
+    fill='hsl(202.5, 7.5%, 42%)',
+    content=embed.img(
+      src='work/medcurbside/medcurbside-phone.jpg',
+      alt='medcurbside welcome screen',
+      sizes='media'
+    )
+  )
+) %}
+
+{% call layout.grid('narrow-columns') %}
+
+{% call layout.block('column') %}
+
+### Languages & Tools
+
+- CSS & Sass
+- Accessible HTML
+- JavaScript (Svelte, Vue, React, Node)
+- Python, FastAPI, & Django
+- OddTools (OddContrast, Polyfills)
+- WordPress
+- Figma
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### Design & Structure
+
+- Brand & Logo Design
+- UX/UI Design
+- Design Systems & Component Libraries
+- Product Messaging
+
+{% endcall %}
+
+{% endcall %}
+
+{% endcall %}
+
+{% call layout.block('fancy-list') %}
+
+## How It Works ...
+
+- **Step 1** \
+  Send us a message
+  requesting office hours coaching
+  including the topic or issue
+  you'd like to talk about.
+- **Step 2** \
+  We'll reply with our recommendation
+  for the OddBird who can help out,
+  as well as links to schedule and pay.
+- **Step 3** \
+  Schedule a date/time
+  that works well for you.
+- **Step 4** \
+  Pay for ongoing coaching
+  or individual sessions.
+- **Step 5** \
+  Send any materials or code
+  you'd like us to review
+ before the video call.
+
+ [Get expert help](/contact/)
+
+{% endcall %}
+
+{{ quotes.find(
+  collections.all,
+  slugs=['pleasant', 'best-in-the-world']
+) }}
+
+{{ layout.title('Services') }}
+
+{% call embed.media_block(
+  media=embed.screen(
+    notch='0',
+    content=embed.img(
+      src='work/quarqrace/trig-phone.jpg',
+      alt='trig race screen',
+      sizes='media'
+    )
+  )
+) %}
+
+{% call layout.grid('narrow-columns') %}
+
+{% call layout.block('column') %}
+
+### Ongoing Coaching
+
+When you buy a package,
+you can use it anytime for up to a year.
+Schedule recurring sessions
+or use as needed.
+Buy in bulk for a discount.
+
+- 7–10 hours at $230/hour
+- 11–14 hours at $220/hour
+- 15+ hours at $210/hour
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### One-Time Session
+
+If you need a single session
+for a quick tip or question,
+we’re here for you.
+Schedule single hour-long sessions
+at times that work well for you.
+
+- individual 1 hour sessions at $250/hour
+
+{% endcall %}
+
+{% endcall %}
+
+{% endcall %}
+
+{{ quotes.find(
+  collections.all,
+  slugs=['exemplary', 'curious']
+) }}
+
+## Request Office Hours Coaching
+
+[Meet the Birds](/about/#meet-the-birds)
+to learn more
+about our individual
+experience and expertise.
+
+To schedule your first session,
+send us a message that includes
+the topic you'd like to talk about.
+We're here,
+and happy to help
+whenever you need us.
+
+[Send a message](/contact/)
diff --git a/content/services/index.njk b/content/services/index.njk
index c7cb53022..47237e2c3 100644
--- a/content/services/index.njk
+++ b/content/services/index.njk
@@ -5,6 +5,7 @@ services:
   - /services/development/
   - /services/planning/
   - /services/design-systems/
+  - /services/consulting/
 summary: |
   **Let’s solve real problems for your business and users** --
   pairing your industry-expertise
diff --git a/content/work/cfoshare.md b/content/work/cfoshare.md
index d09a3938f..8c5e366a6 100644
--- a/content/work/cfoshare.md
+++ b/content/work/cfoshare.md
@@ -14,6 +14,7 @@ press:
       OddBird is very pleasant to work with and responsive.
       I’m not an expert in web development,
       so I really appreciated that.
+    slug: pleasant
     name: LJ Suzuki
     face: lj-suzuki.jpg
     url: https://cfoshare.org/
diff --git a/src/filters/pages.js b/src/filters/pages.js
index 8f4fc055b..2f8cfe1c7 100644
--- a/src/filters/pages.js
+++ b/src/filters/pages.js
@@ -336,7 +336,8 @@ params:
 */
 export const addCallToAction = (pageURL) =>
   _.isString(pageURL) &&
-  (pageURL.startsWith('/work/') || pageURL.startsWith('/services/'));
+  (pageURL.startsWith('/work/') || pageURL.startsWith('/services/')) &&
+  pageURL !== '/services/consulting/';
 
 /* @docs
 label: isType
diff --git a/src/images/pages/open-sign.jpg b/src/images/pages/open-sign.jpg
new file mode 100644
index 000000000..4ea022b4f
Binary files /dev/null and b/src/images/pages/open-sign.jpg differ
diff --git a/test/js/pages.test.js b/test/js/pages.test.js
index e91d7316b..0dc7d3647 100644
--- a/test/js/pages.test.js
+++ b/test/js/pages.test.js
@@ -147,6 +147,11 @@ describe('page filters', () => {
       expect(addCallToAction(exampleURL)).toBe(true);
     });
 
+    test('returns false for services consulting URL', () => {
+      const exampleURL = '/services/consulting/';
+      expect(addCallToAction(exampleURL)).toBe(false);
+    });
+
     test('returns false for blog URL', () => {
       const exampleURL = '/blog/';
       expect(addCallToAction(exampleURL)).toBe(false);


Reviews:
user: login: jamesnw
body: LGTM!
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T01:35:20Z
user: login: jgerigmeyer
body: I made some minor wording tweaks in https://github.com/oddbird/oddleventy/commit/d8b1cb87c5f71dbb0b17731425253cbe8e632263, but if those look okay to you @SondraE I'm fine with you merging this.
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-06T16:59:51Z
user: login: mirisuzanne
body: Overall looks good. @SondraE I left a few small comments.
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T18:19:55Z
user: login: SondraE
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-06T22:08:11Z
user: login: mirisuzanne
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-06T22:19:32Z

Review comments:
diff_hunk: @@ -0,0 +1,218 @@
+---
+title: Office Hours Coaching
+sub: Coaching designers and developers in web best practices
+index: Office Hours Coaching
+image:
+  src: pages/open-sign.jpg
+  alt: door with an open sign
+  position: 20% 40%
+action:
+  text: Request office hours coaching »
+  url: /contact/
+summary: |
+    We love helping people solve
+    complex technology and design problems!
+    Schedule a chat
+    with your favorite OddBird
+    for 1 hour or multiple sessions
+    about anything related to
+    brand or UX Design, CSS,
+    JavaScript, Django, or Python.
+---
+
+{% import 'embed.macros.njk' as embed %}
+{% import 'quotes.macros.njk' as quotes %}
+{% import 'layout.macros.njk' as layout %}
+
+{% call layout.block(
+  name='full',
+  attrs={'class': 'has-angles'}
+) %}
+
+## What to Expect ...
+
+{% call layout.grid('inner') %}
+
+{% call layout.block('column') %}
+
+### Expert Code Review
+
+Chat with top developers
+working at the cutting edge
+of front-end, design systems,
+and W3C standards.
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### Troubleshooting Help
+
+Get a new perspective
+on a thorny design or development issue,
+and find ways to make your app
+more performant and scalable.
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### More Intuitive Designs
+
+Talk through quick and easy options
+to make your website or app
+more accessible and intuitive
+for the people who visit.
+
+{% endcall %}
+
+{% endcall %}
+
+{% endcall %}
+
+{{ layout.title('Topics') }}
+
+{% call embed.media_block(
+  media=embed.screen(
+    fill='hsl(202.5, 7.5%, 42%)',
+    content=embed.img(
+      src='work/medcurbside/medcurbside-phone.jpg',
+      alt='medcurbside welcome screen',
+      sizes='media'
+    )
+  )
+) %}
+
+{% call layout.grid('narrow-columns') %}
+
+{% call layout.block('column') %}
+
+### Languages & Tools
+
+- CSS & Sass
+- Accessible HTML
+- JavaScript (Svelte, Vue, React, Node)
+- Python, FastAPI, & Django
+- OddTools (OddContrast, Polyfills)
+- WordPress
+- Figma
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### Design & Structure
+
+- Brand & Logo Design
+- UX/UI Design
+- Design Systems & Component Libraries
+- Product Messaging
+
+{% endcall %}
+
+{% endcall %}
+
+{% endcall %}
+
+{% call layout.block('fancy-list') %}
+
+## How It Works ...
+
+- **Step 1** \
+  Send us a message
+  requesting office hours coaching
+  including the topic or issue
+  you'd like to talk about.
+- **Step 2** \
+  We'll reply with our recommendation
+  for the OddBird who can help out,
+  as well as links to schedule and pay.
+- **Step 3** \
+  Schedule a date/time
+  that works well for you.
+- **Step 4** \
+  Pay for ongoing coaching
+  or individual sessions.
+- **Step 5** \
+  Send any materials or code
+  you'd like us to review
+ before the video call.
+
+ [Get expert help](/contact/)
+
+{% endcall %}
+
+{{ quotes.find(
+  collections.all,
+  slugs=['pleasant', 'best-in-the-world']
+) }}
+
+{{ layout.title('Services') }}
path: content/services/consulting.md
user: login: mirisuzanne
body: I wonder if there's another word for this section? Maybe it's just that I got here from a list of services already - so I think of "office hours" as the service. 
created_at: 2025-03-06T18:18:52Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,218 @@
+---
+title: Office Hours Coaching
+sub: Coaching designers and developers in web best practices
+index: Office Hours Coaching
+image:
+  src: pages/open-sign.jpg
+  alt: door with an open sign
+  position: 20% 40%
+action:
+  text: Request office hours coaching »
+  url: /contact/
+summary: |
+    We love helping people solve
+    complex technology and design problems!
+    Schedule a chat
+    with your favorite OddBird
+    for 1 hour or multiple sessions
+    about anything related to
+    brand or UX Design, CSS,
+    JavaScript, Django, or Python.
+---
+
+{% import 'embed.macros.njk' as embed %}
+{% import 'quotes.macros.njk' as quotes %}
+{% import 'layout.macros.njk' as layout %}
+
+{% call layout.block(
+  name='full',
+  attrs={'class': 'has-angles'}
+) %}
+
+## What to Expect ...
+
+{% call layout.grid('inner') %}
+
+{% call layout.block('column') %}
+
+### Expert Code Review
+
+Chat with top developers
+working at the cutting edge
+of front-end, design systems,
+and W3C standards.
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### Troubleshooting Help
+
+Get a new perspective
+on a thorny design or development issue,
+and find ways to make your app
+more performant and scalable.
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### More Intuitive Designs
+
+Talk through quick and easy options
+to make your website or app
+more accessible and intuitive
+for the people who visit.
+
+{% endcall %}
+
+{% endcall %}
+
+{% endcall %}
+
+{{ layout.title('Topics') }}
+
+{% call embed.media_block(
+  media=embed.screen(
+    fill='hsl(202.5, 7.5%, 42%)',
+    content=embed.img(
+      src='work/medcurbside/medcurbside-phone.jpg',
+      alt='medcurbside welcome screen',
+      sizes='media'
+    )
+  )
+) %}
+
+{% call layout.grid('narrow-columns') %}
+
+{% call layout.block('column') %}
+
+### Languages & Tools
+
+- CSS & Sass
+- Accessible HTML
+- JavaScript (Svelte, Vue, React, Node)
+- Python, FastAPI, & Django
+- OddTools (OddContrast, Polyfills)
+- WordPress
+- Figma
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### Design & Structure
+
+- Brand & Logo Design
+- UX/UI Design
+- Design Systems & Component Libraries
+- Product Messaging
+
+{% endcall %}
+
+{% endcall %}
+
+{% endcall %}
+
+{% call layout.block('fancy-list') %}
+
+## How It Works ...
+
+- **Step 1** \
+  Send us a message
+  requesting office hours coaching
+  including the topic or issue
+  you'd like to talk about.
+- **Step 2** \
+  We'll reply with our recommendation
+  for the OddBird who can help out,
+  as well as links to schedule and pay.
+- **Step 3** \
+  Schedule a date/time
+  that works well for you.
+- **Step 4** \
+  Pay for ongoing coaching
+  or individual sessions.
+- **Step 5** \
+  Send any materials or code
+  you'd like us to review
+ before the video call.
+
+ [Get expert help](/contact/)
+
+{% endcall %}
+
+{{ quotes.find(
+  collections.all,
+  slugs=['pleasant', 'best-in-the-world']
+) }}
+
+{{ layout.title('Services') }}
+
+{% call embed.media_block(
+  media=embed.screen(
+    notch='0',
+    content=embed.img(
+      src='work/quarqrace/trig-phone.jpg',
+      alt='trig race screen',
+      sizes='media'
+    )
+  )
+) %}
+
+{% call layout.grid('narrow-columns') %}
+
+{% call layout.block('column') %}
+
+### Ongoing Coaching
+
+When you buy a package,
+you can use it anytime for up to a year.
+Schedule recurring sessions
+or use as needed.
+Buy in bulk for a discount.
+
+- 7–10 hours at $230/hour
+- 11–14 hours at $220/hour
+- 15+ hours at $210/hour
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### One-Time Session
path: content/services/consulting.md
user: login: mirisuzanne
body: Left a figma comment on this, not a high priority.
created_at: 2025-03-06T18:19:33Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,218 @@
+---
+title: Office Hours Coaching
+sub: Coaching designers and developers in web best practices
+index: Office Hours Coaching
+image:
+  src: pages/open-sign.jpg
+  alt: door with an open sign
+  position: 20% 40%
+action:
+  text: Request office hours coaching »
+  url: /contact/
+summary: |
+    We love helping people solve
+    complex technology and design problems!
+    Schedule a chat
+    with your favorite OddBird
+    for 1 hour or multiple sessions
+    about anything related to
+    brand or UX Design, CSS,
+    JavaScript, Django, or Python.
+---
+
+{% import 'embed.macros.njk' as embed %}
+{% import 'quotes.macros.njk' as quotes %}
+{% import 'layout.macros.njk' as layout %}
+
+{% call layout.block(
+  name='full',
+  attrs={'class': 'has-angles'}
+) %}
+
+## What to Expect ...
+
+{% call layout.grid('inner') %}
+
+{% call layout.block('column') %}
+
+### Expert Code Review
+
+Chat with top developers
+working at the cutting edge
+of front-end, design systems,
+and W3C standards.
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### Troubleshooting Help
+
+Get a new perspective
+on a thorny design or development issue,
+and find ways to make your app
+more performant and scalable.
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### More Intuitive Designs
+
+Talk through quick and easy options
+to make your website or app
+more accessible and intuitive
+for the people who visit.
+
+{% endcall %}
+
+{% endcall %}
+
+{% endcall %}
+
+{{ layout.title('Topics') }}
+
+{% call embed.media_block(
+  media=embed.screen(
+    fill='hsl(202.5, 7.5%, 42%)',
+    content=embed.img(
+      src='work/medcurbside/medcurbside-phone.jpg',
+      alt='medcurbside welcome screen',
+      sizes='media'
+    )
+  )
+) %}
+
+{% call layout.grid('narrow-columns') %}
+
+{% call layout.block('column') %}
+
+### Languages & Tools
+
+- CSS & Sass
+- Accessible HTML
+- JavaScript (Svelte, Vue, React, Node)
+- Python, FastAPI, & Django
+- OddTools (OddContrast, Polyfills)
+- WordPress
+- Figma
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### Design & Structure
+
+- Brand & Logo Design
+- UX/UI Design
+- Design Systems & Component Libraries
+- Product Messaging
+
+{% endcall %}
+
+{% endcall %}
+
+{% endcall %}
+
+{% call layout.block('fancy-list') %}
+
+## How It Works ...
+
+- **Step 1** \
+  Send us a message
+  requesting office hours coaching
+  including the topic or issue
+  you'd like to talk about.
+- **Step 2** \
+  We'll reply with our recommendation
+  for the OddBird who can help out,
+  as well as links to schedule and pay.
+- **Step 3** \
+  Schedule a date/time
+  that works well for you.
+- **Step 4** \
+  Pay for ongoing coaching
+  or individual sessions.
+- **Step 5** \
+  Send any materials or code
+  you'd like us to review
+ before the video call.
+
+ [Get expert help](/contact/)
+
+{% endcall %}
+
+{{ quotes.find(
+  collections.all,
+  slugs=['pleasant', 'best-in-the-world']
+) }}
+
+{{ layout.title('Services') }}
path: content/services/consulting.md
user: login: SondraE
body: Maybe "Hours" or "Packages" or "Time Bank"?
created_at: 2025-03-06T22:08:11Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,218 @@
+---
+title: Office Hours Coaching
+sub: Coaching designers and developers in web best practices
+index: Office Hours Coaching
+image:
+  src: pages/open-sign.jpg
+  alt: door with an open sign
+  position: 20% 40%
+action:
+  text: Request office hours coaching »
+  url: /contact/
+summary: |
+    We love helping people solve
+    complex technology and design problems!
+    Schedule a chat
+    with your favorite OddBird
+    for 1 hour or multiple sessions
+    about anything related to
+    brand or UX Design, CSS,
+    JavaScript, Django, or Python.
+---
+
+{% import 'embed.macros.njk' as embed %}
+{% import 'quotes.macros.njk' as quotes %}
+{% import 'layout.macros.njk' as layout %}
+
+{% call layout.block(
+  name='full',
+  attrs={'class': 'has-angles'}
+) %}
+
+## What to Expect ...
+
+{% call layout.grid('inner') %}
+
+{% call layout.block('column') %}
+
+### Expert Code Review
+
+Chat with top developers
+working at the cutting edge
+of front-end, design systems,
+and W3C standards.
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### Troubleshooting Help
+
+Get a new perspective
+on a thorny design or development issue,
+and find ways to make your app
+more performant and scalable.
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### More Intuitive Designs
+
+Talk through quick and easy options
+to make your website or app
+more accessible and intuitive
+for the people who visit.
+
+{% endcall %}
+
+{% endcall %}
+
+{% endcall %}
+
+{{ layout.title('Topics') }}
+
+{% call embed.media_block(
+  media=embed.screen(
+    fill='hsl(202.5, 7.5%, 42%)',
+    content=embed.img(
+      src='work/medcurbside/medcurbside-phone.jpg',
+      alt='medcurbside welcome screen',
+      sizes='media'
+    )
+  )
+) %}
+
+{% call layout.grid('narrow-columns') %}
+
+{% call layout.block('column') %}
+
+### Languages & Tools
+
+- CSS & Sass
+- Accessible HTML
+- JavaScript (Svelte, Vue, React, Node)
+- Python, FastAPI, & Django
+- OddTools (OddContrast, Polyfills)
+- WordPress
+- Figma
+
+{% endcall %}
+
+{% call layout.block('column') %}
+
+### Design & Structure
+
+- Brand & Logo Design
+- UX/UI Design
+- Design Systems & Component Libraries
+- Product Messaging
+
+{% endcall %}
+
+{% endcall %}
+
+{% endcall %}
+
+{% call layout.block('fancy-list') %}
+
+## How It Works ...
+
+- **Step 1** \
+  Send us a message
+  requesting office hours coaching
+  including the topic or issue
+  you'd like to talk about.
+- **Step 2** \
+  We'll reply with our recommendation
+  for the OddBird who can help out,
+  as well as links to schedule and pay.
+- **Step 3** \
+  Schedule a date/time
+  that works well for you.
+- **Step 4** \
+  Pay for ongoing coaching
+  or individual sessions.
+- **Step 5** \
+  Send any materials or code
+  you'd like us to review
+ before the video call.
+
+ [Get expert help](/contact/)
+
+{% endcall %}
+
+{{ quotes.find(
+  collections.all,
+  slugs=['pleasant', 'best-in-the-world']
+) }}
+
+{{ layout.title('Services') }}
path: content/services/consulting.md
user: login: mirisuzanne
body: Packages makes sense to me
created_at: 2025-03-06T22:19:32Z
author_association: MEMBER

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-05T21:33:47Z
body: View diff of compiled files (may take a few minutes): https://github.com/oddbird/oddleventy-built/compare/main..office-hours-service
author_association: NONE
user: login: SondraE
created_at: 2025-03-05T21:37:58Z
body: @mirisuzanne @jamesnw 
I've assigned you all to review the Office Hours service page while I'm still working on a few things like a new header image, removing the "Want to chat..." block at the bottom, and adding this to the Services list view.
author_association: CONTRIBUTOR
user: login: SondraE
created_at: 2025-03-05T21:55:00Z
body: @mirisuzanne @jamesnw 
Okay, I've added a new header image, and the new service is appearing in the Services list view, but I haven't found where to remove the "Want to chat..." block from this service detail page.
author_association: CONTRIBUTOR
user: login: jamesnw
created_at: 2025-03-06T01:29:02Z
body: > I haven't found where to remove the "Want to chat..." block from this service detail page.

I don't love how I did it, but I did remove the Want to chat block. Jonny may have a better solution.
author_association: CONTRIBUTOR
user: login: jgerigmeyer
created_at: 2025-03-06T17:06:44Z
body: @mirisuzanne We went ahead and merged this to get it live before James's podcast in 25min, but feel free to review and suggest changes when you have some time.
author_association: MEMBER