Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pull content for moratorium banner from Contentful. #2125

Merged
merged 7 commits into from
Jul 13, 2021

Conversation

toolness
Copy link
Collaborator

@toolness toolness commented Jun 16, 2021

This is an attempt to try pulling content for the Covid moratorium banner text directly from Contentful, so that we don't need to push a change to this repository whenever we want to change the text of the banner.

It currently uses the new @justfixnyc/contentful-common-strings package to help accomplish this.

How it works

The tenant platform now optionally supports retrieving "common strings" from Contentful. By "common strings" we really mean "common rich text strings".

Each common string has an alphanumeric id and a value. The value is a localizable rich text value. For example, in this PR, the common string with id covidMoratoriumBanner is expected to have a value containing the rich text to show users about the current state of the COVID Moratorium, localized in both English and Spanish.

The platform retrieves all entries from its configured Contentful space tagged common. Each of these entries is expected to have a short text field called id and a localized rich text field called value. For reference, here's what such a model looks like in the Contentful content model UI:

image

The common strings are made available to front-end code,. A helper function on the front-end makes it convenient to retrieve a common string's rich text document representation by its id. The front-end can then render them using the @contentful/rich-text-react-renderer package.

Note that at present, all locales of the common strings are passed to the front-end, which means that there's a slight amount of bloat--but it shouldn't be too bad since we have very few common strings.

The back-end caches the common strings from Contentful for a short period of time--at the time of this writing, it's 5 seconds--to ensure minimal latency during periods of high load. (Note that the back-end is responsible for retrieving the Contentful strings to ensure that they are properly rendered during server-side rendering.)

To do

  • Figure out if this is a good idea
  • Add documentation
  • Add tests
  • It would be nice if the links opened in new windows, like our other external links do
  • I'm not sure what will happen if the developer has no internet connection. I'm hoping that it wouldn't cause every single request to take a ridiculously long time as the Contentful server was trying to be reached, but I'm not sure. If so, this would be very annoying.
  • Consider spinning out some of the front-end code into a separate module under the @justfixnyc namespace so our static sites can use it too (see Pull content for moratorium banner from Contentful. who-owns-what#482 for more details) See Add contentful-common-strings package. justfix-ts#32.

Comment on lines +399 to +401
CONTENTFUL_SPACE_ID: str = ""

CONTENTFUL_ACCESS_TOKEN: str = ""
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should consider just using our actual space ID and access token as defaults here; because the access token is read-only and these credentials are intended for use in browser-side JS, they're effectively public (not secrets), and as such, just hard-coding them as defaults won't be a security hazard, and will also make it easier for developers to get up and running quickly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm into that

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So this is kind of frustrating, I ended up adding the defaults to the WoW version of this PR, in JustFixNYC/who-owns-what#482, and immediately got this email:

image

ARGH. While I am pretty sure this isn't actually a security hole, I really, really wish it were possible to just tell Contentful to make a space publicly readable so we didn't have to go through this false alarm stuff.

@@ -65,6 +66,7 @@ def create_initial_props_for_lambda(
"debug": settings.DEBUG,
"facebookAppId": settings.FACEBOOK_APP_ID,
"nycGeoSearchOrigin": settings.NYC_GEOSEARCH_ORIGIN,
"contentfulCommonStrings": contentful.get_common_strings(),
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be bad, if contentful ever goes down. We don't cache anything when there's a network error, so if cdn.contentful.com happens to timeout, all requests to our server could take an unusually long time, effectively resulting in a denial of service.

That said, contentful does use a CDN so this request should be pretty darn fast and timeouts should be extremely rare. Lots of businesses depend on Contentful's CDN to be responsive so we could always just give this a shot and revisit if anything ever goes wrong.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems reasonable

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! My understanding is that the org site already has infrastructure to pull from contentful, so that one would be easier to change over. So that would just leave us with WOW still pulling from react-common, and presumably we could do something similar with WOW.

Right, though there are a few wrinkles--more details at JustFixNYC/who-owns-what#482!

Copy link
Contributor

@samaratrilling samaratrilling left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool! My understanding is that the org site already has infrastructure to pull from contentful, so that one would be easier to change over. So that would just leave us with WOW still pulling from react-common, and presumably we could do something similar with WOW.

@@ -65,6 +66,7 @@ def create_initial_props_for_lambda(
"debug": settings.DEBUG,
"facebookAppId": settings.FACEBOOK_APP_ID,
"nycGeoSearchOrigin": settings.NYC_GEOSEARCH_ORIGIN,
"contentfulCommonStrings": contentful.get_common_strings(),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

seems reasonable

toolness added a commit to JustFixNYC/justfix-ts that referenced this pull request Jun 24, 2021
This factors out the common logic in JustFixNYC/tenants2#2125 and JustFixNYC/who-owns-what#482 into its own reusable package, `@justfixnyc/contentful-common-strings`.
@toolness toolness marked this pull request as ready for review July 13, 2021 15:19
toolness added a commit to JustFixNYC/who-owns-what that referenced this pull request Jul 13, 2021
This is analogous to JustFixNYC/tenants2#2125, but for our static sites (WoW's front-end is a static site).

Note that pulling from Contentful for common strings for our static sites is a bit unusual because:

* Not all our static sites use the same framework. For example, WoW uses Create React App, while our other sites use Gatsby. Each of these has their own particular way of accessing data from Contentful (WoW uses Contentful's API directly, while our other sites use a Gatsby plugin).
* While all our static sites currently use Contentful in some capacity, they don't use the same Contentful _space_.  The common strings are all stored in a separate Contentful space to keep things DRY.  But our static sites are generally built assuming that there is only _one_ Contentful space to pull strings from (and even if they supported multiple spaces, which the Gatsby plugin does, we'd still have to write custom code for each framework).

I've added a [`@justfixnyc/contentful-common-strings`](https://www.npmjs.com/package/@justfixnyc/contentful-common-strings) package which deals with these issues, and this PR now uses it.

## How it works

1. A command-line script is run to retrieve the Contentful common strings (see JustFixNYC/tenants2#2125 for more details) and write them out to a JSON file. This script is run whenever the site is built.

2. The front-end code loads the common strings JSON and renders it in a similar way to the tenant platform.

Step 1 is the main place where the behavior of the tenant platform differs from that of our static sites: while the TP retrieves the strings dynamically and passes them on to the front-end during server-side rendering, our static sites will instead retrieve the content at build time.

## Why not do this in-browser?

I decided to retrieve the strings at build time, rather than dynamically from the browser at page load time, for a few reasons:

* If we fetched the strings dynamically using Contentful's CORS API, browsers that lack JS (or whose JS was broken for some reason) wouldn't be able to see the content.  Since the common content we have right now is actually pretty important, it seemed more prudent to render it at build time.

* Our static sites are already re-rendered whenever content changes, so this just follows the same pattern (well, we might need to manually re-run WoW's pulling of contentful data, but that one's not so bad because we don't change its contentful content very often).  However, it should be noted that **we need to set up Webhooks on the Contentful common space** that trigger rebuilds of all our static sites whenever common strings are changed (we could alternatively manually trigger rebuilds, but it's likely that we'd forget to do this).
@toolness toolness merged commit bc47ac8 into master Jul 13, 2021
@toolness toolness deleted the contentful-common-strings branch July 13, 2021 15:38
toolness added a commit that referenced this pull request Jul 13, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants