{"pageProps":{"posts":[{"slug":"deploy-a-python-serverless-function-on-zeit-now","published":true,"title":"Deploy a Python serverless function on ZEIT Now","excerpt":"Let's write an API endpoint using a Python serverless function that will give us DNS records in JSON format from a given domain.","date":"2020-03-16T05:35:07.322Z","status":"In Progress","author":{"name":"Juan Olvera","picture":"/assets/blog/authors/tim.jpeg"},"ogImage":{"url":"/static/deploy-python-on-now.jpeg"},"changeLog":{"Thu Sep 19 2019 00:00:00 GMT+0000 (Coordinated Universal Time)":"First draft"},"content":"\nLet's write an API endpoint using a Python serverless function that will give us DNS records in JSON format from a given domain. We will send a GET request with a query parameter named \"domain\", i.e.,\n\n```\nGET https://localhost:3000/api?domain=\"jolvera.dev\"\n```\n\nThe tools we are going to use are a ZEIT account, npm, now-cli and a browser. I will assume that you already have npm and a browser installed.\n\nThe API that we are going to write is actually how I started the prototype of [DNS check](https://dnscheck.app). DNS check was born out of the necessity to explain clients and co-workers what's happening with a domain when we make a DNS change. Tools already exist that provide DNS lookup information, but most of them aren't simple enough, in my opinion.\n\nWe only need two dependencies for this project, [Bottle](https://bottlepy.org/docs/dev/) and [dnspython](http://www.dnspython.org/).\n\n## Create the Python function\n\nThe first step is to create a function that returns the DNS records (A, CNAME, MX, for example.) of a given domain name using dnspython.\n\n```python\nimport dns.resolver\n\nids = [\n \"A\",\n \"NS\",\n \"CNAME\",\n \"SOA\",\n \"MX\",\n \"TXT\",\n \"AAAA\",\n]\n\ndef resolve(domain: str):\n result = []\n for record in ids:\n try:\n answers = dns.resolver.query(domain, record)\n data = [{\"record\": record, \"value\": rdata.to_text()} \n for rdata in answers]\n for item in data:\n result.append(item)\n except Exception as e:\n print(e)\n return result\n\nprint(resolve('jolvera.dev'))\n```\n\nBefore creating any files in our computer, [let's try this function in Repl.it](https://repl.it/@jolvera/DNS-records). If everything is okay you will get something like:\n\n```js\n[\n {\n 'record': 'A',\n 'value': '3.19.25.128'\n },\n {\n 'record': 'A',\n 'value': '3.19.23.166'\n },\n {\n 'record': 'NS',\n 'value': 'b.zeit-world.org.'\n },\n {\n 'record': 'NS',\n 'value': 'e.zeit-world.net.'\n },\n {\n 'record': 'NS',\n 'value': 'f.zeit-world.com.'\n },\n {\n 'record': 'NS',\n 'value': 'a.zeit-world.co.uk.'\n },\n {\n 'record': 'MX',\n 'value': '10aspmx1.migadu.com.'\n },\n {\n 'record': 'TXT',\n 'value': '\"v=spf1 a mx include:spf.migadu.com ~all\"'\n }\n]\n```\n\nTry with different domains, make sure it works, then proceed to create the API endpoint.\n\n## Convert the function to a Serverless function\n\nThe serverless platform we are going to use is ZEIT Now. They make serverless development extremely easy and projects deployments a joy. \n\nTo follow this example, create an account at [zeit.co](http://zeit.co/) and install Now globally in your system by running `npm i -g now`, and with that you are ready to go.\n\n### Folder structure\n\nCreate a folder and call it `dnscheck` then create another folder inside called `api`.\n\n```bash\n$ mkdir dnscheck\n$ mkdir dnscheck/api\n```\n\nThis folder structure is all you need. \n\n### Virtual environment\n\nPython best practices say we need a virtual environment, so we don't install our dependencies globally in the system (Like what we did with `npm i -g now` but in the Python world).\nIn this example, I'm going to use `virtualenv`, but you can use [Poetry](https://poetry.eustace.io/) or [Pipenv](https://docs.pipenv.org/en/latest/) as well. I chose `virtualenv` here to keep things simple.\nInside the `dnscheck/api` folder, create a new virtual environment.\n\n```bash\n$ cd dnscheck/api\n(dnscheck/api) $ virtualenv venv\n```\n\nThen, activate the virtual environment.\n\n```bash\n(dnscheck/api) $ ./venv/bin/activate\n```\n\nWith this, we have our virtual environment ready to go, and we can start installing dependencies that are only available in our project. We start by installing `dnspython` and `bottle`.\n\n```bash\n(dnscheck/api) $ pip install bottle dnspython\n```\n\nThen we create a `requirements.txt` file that lists all the dependencies we are using. Now uses this to install the dependencies while it's deploying.\n\n```bash\n(dnscheck/api) $ pip freeze > requirements.txt\n```\n\n### API endpoint with Bottle\n\nInside the `api/` folder, create a file named [`index.py`](http://index.py/). Inside write the following code.\n\n```python\nfrom bottle import Bottle, request\nimport dns.resolver\n\napp = Bottle()\n\nids = [\n \"A\",\n \"NS\",\n \"CNAME\",\n \"SOA\",\n \"MX\",\n \"TXT\",\n \"AAAA\",\n]\n\n\n@app.get('/api')\ndef api():\n domain = request.query.get('domain')\n result = resolve(domain)\n return dict(data=result)\n \n\ndef resolve(domain: str):\n result = []\n for record in ids:\n try:\n answers = dns.resolver.query(domain, record)\n data = [{\"record\": record, \"value\": rdata.to_text()} \n for rdata in answers]\n for item in data:\n result.append(item)\n except Exception as e:\n print(e)\n return result\n```\n\nThis code listens for GET requests in `http://localhost:3000/api` and tries to grab a query parameter named `domain`, so to be able to get the data we have to send a get request to [http://localhost:3000/api?domain=jolvera.dev](http://localhost:3000/api?domain=jolvera.dev) or simply open the URL in the browser.\n\nTo test it locally, inside the `dnscheck/` folder run `now dev`,\n\n```bash\n(dnscheck/api) $ cd ..\n(dnscheck) $ now dev\n```\n\nif everything is okay, you should get the development URL.\n\n```bash\n> Ready! Available at http://localhost:3000\n```\n\nIf so, go to your browser and visit [http://localhost:3000/api?domain=jolvera.dev](http://localhost:3000/api?domain=jolvera.dev) and you should see a response in JSON like shown in the following screenshot.\n\n\n\n### Deploy to Now\n\nEverything is ready to deploy our serverless function to Now and share it to the world!\n\nInside the `dnscheck/` folder run `now` \n\n```bash\n(dnscheck) $ now\n```\n\nand If everything goes okay, we will get a URL like [https://dnscheck-example-2k7pyj3cr.now.sh/](https://dnscheck-example-2k7pyj3cr.now.sh/), in my case I got [https://dnscheck-post-example.jolvera.now.sh/](https://dnscheck-post-example.jolvera.now.sh/), and you can test my domain going to [https://dnscheck-post-example.jolvera.now.sh/api?domain=jolvera.dev](https://dnscheck-post-example.jolvera.now.sh/api?domain=jolvera.dev).\n\n[See the project in action.](https://i.imgur.com/t7l26yB.gifv)\n\n## Conclusion\n\nWe were able to prototype a small idea into a workable API and share it on the web with ease. What we did in this post was the premise of my project and the train of thought I had to get something working. After I got the example working, I kept trying new ideas on it and added domain validation, a Next.js frontend and more.\n\nBeing able to prototype an idea into an API with these few tools encourage me to try new things more often. Once you get a first working example you will get motivate to keep going and build lots of things.\nYou can check my finished project dnscheck.app in these two repositories:\n\n- [DNS Check frontend](https://github.com/j0lv3r4/dnscheck-frontend)\n- [DNS Check Serverless function](https://github.com/j0lv3r4/dnscheck)\n\nAlso published in:\n\n- DEV.to\n\n"},{"slug":"good-second-drafts","published":true,"title":"Publishing good second drafts","excerpt":"I’ve been trying to improve the amount of writing I publish. I write a lot, but mostly rough ideas in a notebook. I followed every tip online to write more, and they worked, but now I don’t have content I’d like to publish in my blog, yet. So, the problem wasn’t quantity but quality. Or so I thought.","date":"2019-07-25","status":"Draft","author":{"name":"Juan Olvera"},"ogImage":{"url":"/static/publishing-good-second-drafts.jpeg"},"changeLog":{"Thu Jul 25 2019 00:00:00 GMT+0000 (Coordinated Universal Time)":"First draft"},"content":"\nI’ve been trying to improve the amount of writing I publish. I write a lot, but mostly rough ideas in a notebook. I followed every tip online to write more, and they worked, but now I don’t have content I’d like to publish in my blog, yet. So, the problem wasn’t quantity but quality. Or so I thought.\n\nI don’t write for SEO purposes. I don’t care if my website gets tons of visits, because my website is a form of self-documentation. I want to write about what and how I learned it and put it out there in case someone finds it useful.\n\nPublishing revised, edited, quality content is okay for a magazine site, or a serious publication, but for a personal website, I decided that publishing drafts is okay too. The web facilitates that. Put out there a work-in-progress post, get feedback, and update as needed.\n\nThis is not a revolutionary idea. Anne Lammot in her book “Bird by Bird” writes about shitty first drafts, which are what you do when you want to throw whatever you have in your head about a particular topic in paper or your text editor. Random thoughts, senseless paragraphs, stuff you can put together in better shape later, these are part of your shitty first draft.\n\n
\n\n\nI read her book last year, and I’ve kept this idea of publishing drafts in my blog in my head for a while. This year I came upon [gwern’s website](https://www.gwern.net/) where he uses tags to describe the state of his writings.\n\nAll good writers write them. This is how they end up with good second drafts and terrific third drafts.
\n \n
\n\n\nWith these two ideas together, I finally had a concept (shitty first drafts) and an implementation (status tags) to publish drafts in my blog. Even though I still don’t want to put shitty first drafts out there, I’m okay with putting good second ones. This concept gives me more freedom on making progress in my content and less pressure to put it out there. Also, it’s open to feedback in an early state.\n\nI’ll try to limit myself from keeping the blog full of drafts. Maybe I’ll keep it at three-four drafts maximum. Also, I want to keep track of the changes, so I’ll somehow keep a changelog per post to document the progress.\n\nThis is my latest attempt to publish more content mostly for self-documentation and journal my experiences. Instead of doing short rants on social media, I expect to put my thoughts in a place I own."},{"slug":"accessible-read-more-links","published":true,"title":"Accessible \"Read More\" links","excerpt":"A pattern you probably have seen in various blogs is the “Read more” link. The design usually has the title first, then a small excerpt of the content and a “Read more” text link to the full post. ","date":"2019-06-18","status":"Draft","author":{"name":"Juan Olvera"},"ogImage":{"url":"/static/site-feature.png"},"changeLog":{"Thu Jun 13 2019 00:00:00 GMT+0000 (Coordinated Universal Time)":"First draft"},"content":"\n\"Learn More\" Links are part of a pattern we see in Blogs. The design has the title first, then a content excerpt and a text link that takes us to the post page with the full content.\n\n\n\nBlogs have an index page with a list of posts that makes it easier for the general public to choose what to read. This is simple enough the general public, but it gets complicated with people with disabilities. In this specific case, people that use screen readers.\n\nThe fix for this issue is so simple, yet I see it everywhere, on big company websites or simple personal blogs.\n\nBefore I started writing this post, I checked ten blogs—some of them with an excellent reputation—and eight had an inaccessible “Read more” link.\n\nHow can we know if a “Read more” link is inaccessible?\n\n## Screen reader usage\n\nScreen readers generate a list of links without context to help the user map the content of the page. Also, screen reader users usually navigate a page by using the tab key to jump from link to link without reading the content. So you can expect that having a list of “Read more” links is useless and adds redundancy in this context, e.g.,\n\n```markdown\n|- Title for a blog post\n|- Read more\n|- Title for a second blog post\n|- Read more\n|- Third blog post\n|- Read more\n|- Another blog post\n|- Read more\n```\n\n[Also watch “Screen reader demo: don't use 'click here' for links” in YouTube](https://www.youtube.com/watch?v=zGa_rIK1itA)\n\n### Real world examples\n\nLet’s see some examples and inspect the code they use.\n\n#### Example 1\n\n\n\nIn this example, the link is a big button acting as a call to action, but the button by itself is lacking context. Continue reading… what?\n\n```html\nThe \"status\" tag describes the state of completion: whether it’s a pile of links & snippets & \"notes\", or whether it is a \"draft\" which at least has some structure and conveys a coherent thesis, or it’s a well-developed draft which could be described as \"in progress\", and finally when a page is done—in lieu of additional material turning up—it is simply \"finished\".
\n \n