This is a boilerplate site to help you get started building a simple semi-static site.
- Static pages built with jekyll and hosted on S3
- Backend functionality with flask, powered by lambda and API Gateway, with deployment help from zappa.io
- Simple backend functionality that processes a form, stores the data in a DynamoDB database and sends an email to the administrator with SES
You can read about the motivation behind it here.
Here is the result of this repo, running on S3, and Lambda, sending an email to the Administrator (me) and inserting a record into a DynamoDB.
If you know a bit about AWS, you should be up and running in an hour. If you've never used AWS, budget a day.
- Clone this repo
- Read the Zappa.io documentation
- Set up python
cd hellolambda_api python3 --version # ==> confirm >= 3.6.0 python3 -m venv pyvenv source pyvenv/bin/activate pip install flask flask_cors awscli boto3 zappa pip install -e .. python devserver.py
- In browser:
http://127.0.0.1:5285/api/ping?does_it_work=yes
==> {"does_it_work": "yes"} - Python debugger - set up your python debugger or IDE (I use pycharm) so you can debug your flask API
- In browser:
- Install Jekyll
- Confirm Jekyll works
cd ../site
jekyll serve
- In browser:
http://127.0.0.1:4000/
==> Hello, Lambda! page should show (in yellow) - In browser:
http://127.0.0.1:4000/test
==> Test page should show (in yellow)
- Create an S3 bucket for your static website
- Read the docummentation
- Note the bucket name should match the URL you will be using. EG hellolambda.yourdomain.com
- Set your DNS to point to your new bucket
- Update config.py
CORS_ACCEPTABLE_ORIGINS
with your domain - Push the static part of your site to your new S3 bucket
- A convenience function:
bin/update -s
- What this does:
aws s3 sync <a lot of parameters>
- A convenience function:
- Use zappa.io
zappa deploy
- copy the API Gateway url it prints at the end. EG:
Deployment complete!: https://xxx.execute-api.us-west-2.amazonaws.com/dev
- Test it in the browser (append '/api/ping'):
https://xxx.execute-api.us-west-2.amazonaws.com/dev/api/ping
- If it gives you an internal error, check your CloudWatch logs
- Test ping in your static test page
http://hellolambda.xxx.com/test/
- Open the browser debug console to make sure there are no errors
(Note - there will be a 404 error for private_config.js. Ignore it.) - Click the 'Test Ping' button
- If error
- Check cloudwatch logs
- Trace execution of the JS. Is it sending the URLs you expect?
- Switch the "API Endpoint Selector" to 'use localhost', run the devserver in your debugger, and trace the python side
- Pay particular attention to CORS
- As you do your debugging, use
bin/update
to update the S3 static site and lambda code - Good luck!
- If success - Hooray!
You now have a working static site with a flask-powered, runs-on-lambda backend.
Now lets get your services running: A DynamoDB table to store the form content, and SES to send emails to the administrator. ###DynamoDB
- Create table: hellolambda (or new name and update config.py)
- Primary Key: "pk" (string)
Note: I do not know what the best primary key format is. After some trial and error I've settled on 'tag-'. I'm pretty sure this would be frowned on, but its easy, flexible, and probably doesn't matter for the table size I'll be using. - Default Setting: No
- Set capacity to 1/1 unless you have a reason not to
- Primary Key: "pk" (string)
- Test
- Spin up your local python debugger and run the dev server
- Open the test page (either on S3, or locally with jekyll serve - it doesn't matter which).
- Make sure your test page endpoint selector is selecting localhost
- Test ping, to confirm everything is running properly
- Test DynamoDB and debug
zappa update
- Test on S3
Setting up SES is a bit more involved. Follow the documentation. When complete, do the same process as you did with DynamoDB - test locally with your python debugger, zappa update, test on AWS.
Once you've got all your individual services tested, its time to test your production form.
Once that's complete, you should probably either remove your test page or hide it, because it's probably not good to have your test functions out there. To hide it, create a long random number (eg: a SHA-256). Rename site/test to site/<LONG_RANDOM>. In config.py, set 'TEST_PATH_PREFIX' to <LONG_RANDOM>. Redploy (bin/update
). Then to try your test page, you'll have to copy / paste it the first time, but after that when you start typing, the browser will autocomplete it.
You might also want to implement
- An AWS Budget with an SNS alert to notify you if costs exceed your expectations
- AWS Config to track changes over time
- @daily_limit decorator - Decide if you want to use this and what limits to use.
If you find any errors, please submit a PR. If you don't know how, just submit an issue.