<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Pearl Latteier</title>
    <description>The latest articles on DEV Community by Pearl Latteier (@pblatteier).</description>
    <link>https://dev.to/pblatteier</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F81428%2F4f3fdbf7-628f-4031-9c94-50df39cb3c15.jpg</url>
      <title>DEV Community: Pearl Latteier</title>
      <link>https://dev.to/pblatteier</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/pblatteier"/>
    <language>en</language>
    <item>
      <title>A Quick CORS Primer for Frontend Folks</title>
      <dc:creator>Pearl Latteier</dc:creator>
      <pubDate>Sun, 08 Nov 2020 19:56:11 +0000</pubDate>
      <link>https://dev.to/pblatteier/a-quick-cors-primer-for-frontend-folks-2lgd</link>
      <guid>https://dev.to/pblatteier/a-quick-cors-primer-for-frontend-folks-2lgd</guid>
      <description>&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--n-EyrFIP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kq68c326k7bsuzp0okj5.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--n-EyrFIP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/kq68c326k7bsuzp0okj5.jpg" alt="A skull and crossbones on a computer screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h6&gt;
  
  
  Photo by Michael Geiger on &lt;a href="https://unsplash.com/s/photos/computer-error"&gt;Unsplash&lt;/a&gt;
&lt;/h6&gt;

&lt;p&gt;You've made some requests on &lt;a href="https://www.postman.com/"&gt;Postman&lt;/a&gt;. You understand which endpoints will deliver what payloads. Contented, you start developing on localhost. Enter the villain — CORS Error!&lt;/p&gt;

&lt;h2&gt;
  
  
  What is CORS?
&lt;/h2&gt;

&lt;p&gt;Cross-Origin Resource Sharing (&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"&gt;CORS&lt;/a&gt;) is a &lt;a href="https://www.w3.org/wiki/CORS"&gt;web standard&lt;/a&gt; designed to let servers on different domains share resources (HTML or JSON documents, images, fonts, etc.) in a safe way. &lt;/p&gt;

&lt;p&gt;CORS comes into play when a web application on one origin (&lt;a href="https://some-domain.com"&gt;https://some-domain.com&lt;/a&gt;) requests a resource from another origin (&lt;a href="https://some-other-domain.com"&gt;https://some-other-domain.com&lt;/a&gt;). To protect both the server receiving and the browser sending the request, CORS manages these cross-origin interactions. &lt;/p&gt;

&lt;h2&gt;
  
  
  How does CORS work?
&lt;/h2&gt;

&lt;p&gt;The CORS standard manages cross-origin interactions via HTTP headers. The server hosting the desired resource can use &lt;code&gt;Access-Control-Allow-Origin&lt;/code&gt; and &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers#CORS"&gt;other headers&lt;/a&gt; to specify how it will respond to cross-origin requests. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Simple requests&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For example, when I send a GET request to &lt;a href="http://dog.ceo"&gt;Dog.ceo&lt;/a&gt; for a &lt;a href="https://dog.ceo/api/breeds/image/random"&gt;random dog pic&lt;/a&gt;, the response includes this header: &lt;code&gt;Access-Control-Allow-Origin: *&lt;/code&gt;  The &lt;code&gt;*&lt;/code&gt; means that the sever will deliver the the resource in response to any request, whatever domain it comes from.&lt;/p&gt;

&lt;p&gt;If, for some reason, &lt;a href="http://dog.ceo"&gt;Dog.ceo&lt;/a&gt; decided to make its resources available only to requests from &lt;a href="https://example.com"&gt;https://example.com&lt;/a&gt;, it could change the header to &lt;code&gt;Access-Control-Allow-Origin: https://example.com&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Or &lt;a href="http://dog.ceo"&gt;Dog.ceo&lt;/a&gt; might want to limit its resources to a handful of origins. In that case, it could set the allow-origin header to whatever the request origin is, but then inspect the request to make sure it's on the list of allowed origins before responding.&lt;/p&gt;

&lt;p&gt;If the allow-origin header is anything more specific than  &lt;code&gt;*&lt;/code&gt; , the server should also send a &lt;code&gt;[Vary: Origin&lt;/code&gt; header](&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Vary&lt;/a&gt;), telling caches that the content of the response will vary depending where the request is coming from.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Preflight requests&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;My GET request to &lt;a href="http://dog.ceo"&gt;Dog.ceo&lt;/a&gt; is very simple. Many requests are more complicated, and the CORS standard requires additional work from browsers whenever a request isn't a GET, HEAD, or POST, when it's content type isn't a form or plain text, or when it meets several other conditions.&lt;/p&gt;

&lt;p&gt;In these cases, before it sends the cross-origin request, the browser sends a "preflight request" using the OPTIONS method. The purpose of the pre-flight request is to figure out if the real request is actually allowed by the responding domain. The response from the server to the OPTIONS request will indicate which origins are allowed, which request methods are allowed, if cookies Authorization headers are allowed, or required, or forbidden, and other things along those lines.&lt;/p&gt;

&lt;p&gt;(Note: the reason your cross-origin Postman request worked fine is because Postman is not a browser. It does not send a preflight request.)&lt;/p&gt;

&lt;p&gt;If you're not sure if your request is simple enough to avoid preflight, a nice tool called &lt;a href="https://httptoolkit.tech/will-it-cors/"&gt;Will it CORS?&lt;/a&gt; can help you figure it out.&lt;/p&gt;

&lt;p&gt;Once the browser had received the response to the preflight request and determined that your request is OK, it will send the request. If your request is not OK, you'll get the infuriating CORS error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting CORS errors
&lt;/h2&gt;

&lt;p&gt;What about that error? When you run into a CORS error, what can you do? &lt;/p&gt;

&lt;p&gt;If you're a frontend person, you can start by inspecting your request. Are you using the right method, sending the right credentials (or not sending credentials if they are not accepted by the responding domain), and sending the appropriate content type? The &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"&gt;MDN article&lt;/a&gt; about what triggers a preflight request could be helpful here, along with the &lt;a href="https://httptoolkit.tech/will-it-cors/"&gt;Will it CORS?&lt;/a&gt; tool.&lt;/p&gt;

&lt;p&gt;If you have access to the responding server, you're in luck. You can examine the server's CORS configuration and make sure that it is correct. MDN has an &lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"&gt;article&lt;/a&gt; about specifically for server developers that may assist you in this. Alternatively, if you have access to a person who has access to the server, supplicate yourself and humbly, kindly, gratefully ask for help.&lt;/p&gt;

&lt;p&gt;Whatever the case, I hope this quick primer helps keep you brave in the face of your next CORS error.&lt;/p&gt;




&lt;p&gt;Special thanks to Abraham Williams (&lt;a href="https://twitter.com/abraham"&gt;@abraham&lt;/a&gt;) for talking me through more than one CORS crisis and introducing me to Will it CORS?.&lt;/p&gt;

&lt;p&gt;Originally published in the &lt;a href="https://medium.com/propeller-health-tech-blog/a-quick-cors-primer-for-frontend-folks-83c53b9cb28f"&gt;Propeller Health Tech Blog&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;References&lt;/p&gt;

&lt;p&gt;&lt;a href="https://httptoolkit.tech/will-it-cors/"&gt;https://httptoolkit.tech/will-it-cors/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS"&gt;https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://fetch.spec.whatwg.org/#cors-protocol"&gt;https://fetch.spec.whatwg.org/#cors-protocol&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.w3.org/wiki/CORS"&gt;https://www.w3.org/wiki/CORS&lt;/a&gt;&lt;/p&gt;

</description>
      <category>cors</category>
      <category>frontend</category>
      <category>postman</category>
      <category>http</category>
    </item>
    <item>
      <title>Lost in SPA(ce): Helping screen readers navigate React applications</title>
      <dc:creator>Pearl Latteier</dc:creator>
      <pubDate>Wed, 25 Mar 2020 18:39:58 +0000</pubDate>
      <link>https://dev.to/pblatteier/lost-in-spa-ce-helping-screen-readers-navigate-react-applications-55h8</link>
      <guid>https://dev.to/pblatteier/lost-in-spa-ce-helping-screen-readers-navigate-react-applications-55h8</guid>
      <description>&lt;p&gt;&lt;em&gt;Originally published in the &lt;a href="https://medium.com/propeller-health-tech-blog"&gt;Propeller Health Tech Blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;When the front-end team at Propeller Health recently set out to make our websites accessible, I thought I was in familiar territory. I’m a fan of &lt;a href="https://css-tricks.com/why-how-and-when-to-use-semantic-html-and-aria/"&gt;semantic html&lt;/a&gt;, &lt;a href="https://www.w3.org/WAI/tutorials/images/decision-tree/"&gt;alt tags&lt;/a&gt; and &lt;a href="https://dequeuniversity.com/rules/axe/3.2/label"&gt;input labels&lt;/a&gt;, I’m proud of my perfect scores on &lt;a href="https://developers.google.com/web/tools/lighthouse"&gt;Lighthouse&lt;/a&gt; accessibility audits and I’m fluent in &lt;a href="https://www.w3.org/TR/wai-aria-practices-1.1/"&gt;aria attributes&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;But I learned pretty quickly that web accessibility is more complicated than I’d thought. To make our site friendly to all users, the team had to start asking new questions. Does it work without a mouse or when the screen is zoomed to 300%? Is the structure of information clear to assistive technologies? Can all users navigate, find content and determine where they are?&lt;/p&gt;

&lt;p&gt;The last question raised a particularly tricky problem for us. We work on a single-page React application that involves a “multi-page” form. A user fills out some form fields, clicks “next”, sees a new view with new form fields, fills them out, and clicks “next” again. How would we keep users of screen readers oriented when the page content changed without a browser refresh?&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem
&lt;/h2&gt;

&lt;p&gt;In a server-rendered website, each time the page changes, the browser refreshes. The old page is gone, and screen readers start reading the new page from the top. The first thing the screen reader articulates is the page title in the HTML header. This lets the user know immediately where they are. If they are in the right place, they can start tabbing forward to explore the page.&lt;/p&gt;

&lt;p&gt;Single page applications don’t work the same way. When the page changes, the browser does not refresh and the screen reader doesn’t know that anything has happened. The focus doesn’t automatically move to the top of the screen. There is nothing to orient the reader.&lt;/p&gt;

&lt;h2&gt;
  
  
  Our Solution
&lt;/h2&gt;

&lt;p&gt;At the time of this writing, there was no standard, codified way to make single page applications navigable by screen readers. Nor could we find any well-tested NPM package that would solve the problem for us. So we rolled our own solution. It’s not perfect, but it works.&lt;/p&gt;

&lt;p&gt;Our solution was inspired by a pattern employed in server-rendered websites called a “&lt;a href="https://webaim.org/techniques/skipnav/"&gt;skip link&lt;/a&gt;” (and by Mary Sutton’s discussion of skip links in her Frontend Masters &lt;a href="https://frontendmasters.com/courses/javascript-accessibility/"&gt;course&lt;/a&gt; ). The goal of the skip link is to give users of screen readers a way to skip past the top navigation that is usually found at the beginning of every web page. Without a skip link, these users have to wade through many links, icons, and search boxes on every page before they can get to the page’s main content.&lt;/p&gt;

&lt;p&gt;The skip link is generally the first item on a page. When the user clicks the skip link they are brought to the main section of the page.&lt;/p&gt;

&lt;p&gt;In HTML, it would look something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--wh7iwElo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5po16ofiup0ek3v88pb1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--wh7iwElo--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/5po16ofiup0ek3v88pb1.png" alt="Html code depicting a skip link anchor tag"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We repurposed the skip-link pattern as a way to let users know when the content of our single page application had changed. It’s implemented as a lightweight component that wraps each of our page-level components. The component moves the focus to the top of the page and prompts the screen reader to say the page title, imitating what would happen when the browser refreshes. Here’s more or less the whole thing:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--EyS4MiLi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ndt3kksu70kesaqo5215.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--EyS4MiLi--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ndt3kksu70kesaqo5215.png" alt="Code snippet of a React component"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We create a ref to the skip link and move focus to the link as soon as the component has loaded. The screen reader reads the link, which includes the title of the page and a message about skipping to the main content. This way, the user knows what page they are on and what to do to move forward.&lt;br&gt;
There are likely better implementations out there (share yours in the comments!). We hoped that by following the skip-link pattern ours would at least be familiar and easy to understand.&lt;/p&gt;

&lt;p&gt;We at Propeller and the frontend community at large have more work to do to make our single page applications accessible to everyone. Our recent accessibility initiative has increased our empathy for users who use the web differently than we do. We embrace the challenge.&lt;/p&gt;

</description>
      <category>a11y</category>
      <category>react</category>
      <category>screenreaders</category>
      <category>javascript</category>
    </item>
  </channel>
</rss>
