At its core this is a fairly simple static webpage that uses some background services to
expand its capabilities.
When users go to the custom domain google domains redirects them to the URL for my
CloudFront distribution. CloudFront was used for multiple reasons, the most obvious is that
as a contend delivery network it will make sure that users get a fast consistent experience.
The second reason is that it integrates with S3 to take your static pages prevent every
visit from calling your S3 bucket. This will help lower any data egress costs. The final
reason is that it allows you to add a certificate to your page to make it secure. This
becomes useful when implanting a new feature where people can use their current location to
check eligibility. Modern browsers require a secure connection to call location information.
When users enter an address or pass their GPS coordinates the webpage sends a request to an
API endpoint that passes the request to separate lambda functions. Those lambda functions
use the United States Census bureau geolocation API to look up the Federal Information
Processing number (FIPS) associated with an area. That FIPS number is then used to query my
DynamoDB that has entries for every block group in the nation. The query returns all of the
information about eligibility which is passed back to the webpage and more JavaScript is
used to display it as tables.
This was my first time using the API gateway, Lambda functions, or cloudfront. In a twist that may
not be a surprise to anyone. It turns out that doing the actual work is hard then learning about how
to do the work.
CORS
API gateway requires paying attention to your cross-origin resource settings in a way I never
had to before. A lot of time was spent pulling my hair trying to figure out what I was
missing. When in the end it was simply needing to set ALL of the CORS options.
CloudFront Origins and Root Objects
Here again I made the mistake of setting an origin path without understanding what that fully
meant. It lead to a series of frustrating google searches as to why I was getting access
denied errors. Also it is helpful to set a default object to display when people visit the
CloudFront URL in my case that was index.html
Lambda functions and CloudWatch
You will spend a lot of time debugging your lambda functions but you wont get all of the
output you do when coding locally. Print statements and cloudwatch execution logs will be
your friend when trying to pinpoint failures.
Certs and user data
I had built code to request user locations from the browser and it worked when I tested it
locally. I pushed my version up to the bucket and found the button did nothing. It took a
little reading to figure out that browsers will ignore location request from webpages that
are not secure. This meant I would need to get a certificate or give up on the feature.
Fortunately implementing CloudFront allows us to add certificates in front of static pages.
CNAME and ownership verification
Most of the documentation for how to get a public certificate from AWS assumes you are using
Route 53 the AWS native DNS service. It took a little more digging and was a little more
ambiguous to set up DNS verification for the cert when your domain is with Google Domains.
In the end it just requires one CNAME record to be added to verify ownership of the domain
itself, but it was not readily apparent at first how they wanted verification done.
Fetch
JavaScript has never been a language I am fluent in or even proficient. A lot of time was
spent learning how to execute API calls with fetch and then how to take the returned
information and display it on the page. I am sure the code could be optimized and cleaned up
by people who are more familiar with front end development.
Layers
Python libraries you want to use need to be packed up in a ZIP files called python and uploaded as layers that you then attach to the lambda function. Its a little count intuitive but you can reuse packed layers across multiple functions. Though there is a limit to the number you can attach and a 50mb limit. So you may run into issue with more complex load outs.
Retrospective
My first job out of college introduced me to the problem of kids who rely on school breakfast and
lunches as their only meals for the day. Which works during the school year another program is
needed to help them get meals during the summer. The United Stated Department of Agriculture (USDA)
which oversees all school nutrition programs has the Summer Food Service Program (SFSP) which is
meant to allow organizations to set up summer feeding sites to help feed these children during the
summer.
The problem is that there are only certain areas where these sites are allowed to operate. Each year
they publish a list of eligible areas (census block groups) and publish a national map you can
scroll through to see if an area is eligible.
They also publish a list of business rules that you can use to attempt to convert non-eligible areas
into eligible areas. You do this by taking adjacent block groups and averaging the number of
identified kids if each block group meets a specific threshold.
So, if an organization wants to operate in an area that is not eligible, they need to submit a
request to their states nutrition office and program specialist are meant to go to this map, look up
the address, gather the information for that area and all of the adjacent areas. Then perform the
series of calculations for every possible combination to see if a site can be operated there. This
leaves a significant amount of room for human error. A program can be written to perform the
hundreds of thousands of calculations required and return a list of eligible areas.
I had written code to do these calculations and even to made some interactive maps but never had a
way to search for address inside of them or a way to distribute them so that people who want to
operate sites or state agencies could use them to verify eligibility.
After studying for my developer certification from AWS I was introduced to DynamoDB tables, Lambda
functions, and the API gateway. And leveraging these tools along with some JavaScript I was finally
able to build a simple interface that allows anyone to check if an address is eligible by looking up
the location and checking it against a database of my calculations.
In future versions of this page I would like to incorporate some kind of “near me” system to find
the closest eligible area or use the list of approved feeding sites for a year to let people search
for the one closest to them. I know that dynamo has some geohashing features that can be used to
develop things like this but currently I am unfamiliar with implantation of them.