Latest Items
- Creating a serverless web app with Airtable, Glitch, Node.js, Surge.sh & Ember.js
Continue reading...TL;DR;In this post I show how I built a serverless CMS/Blog system based entirely on free and modern PaaS services such as Airtable, Glitch (formerly Gomix, Hyperdev) & Surge.sh.The end result is:https://medium.com/media/c04f0af49229ba610972f9f1c18d4b35/hrefYou can visit it at: http://caring-eggs.surge.sh/And check out the source code:Frontend: https://github.com/benoror/experiment_blog_xt014_dProxy: https://github.com/benoror/proxy_blog_xt014_d & https://glitch.com/#!/project/keen-gorillaOk, tell me more…Lately I’ve been thinking how server code is becoming less and less relevant each day, and how everything you needed to code back in the day is now offered as a cloud service at your disposal, such as:Authentication/authorization (Auth0, Twilio), asset hosting (AWS S3), database (Firebase, Airtable), AI (google prediction API), payment processing (Stripe), etc…The remaining parts of your app, the ones that make you “unique”, can be written in isolated & scalable modules in any language and/or framework of choice, which nowadays can be also easily deployed. Such easy-to-deploy, lego-like blocks of functionality can be achieved with modern services such as AWS Lambda, Zeit Now or, what concerns us today, Glitch.Since I’ve been messing around with these ideas for a while, I decided to see how doable it really was by making a PoC:A Markdown Blog system, à la Canvas or Medium, with Airtable as Database/CMSPaaS ArchitectureDisclaimer: I chose services I’m interested in and/or using at the moment, altough the stack can be flexible at every level:Database/CMShttps://airtable.comAlternatives: Fieldbook (see my related post) , Firebase Realtime, etc…Node.js Proxy/Auth Backendhttps://glitch.comAlternatives: Heroku, Zeit Now, Parse, Aerobatic, AWS Lambda, etc…Ember.js SPA Frontendhttps://surge.shAlternatives: Zeit Now, Aerobatic, Firebase Hosting, Pagefront, AWS S3, Github Pages, etc…Designing the Database StructurePosts tablehttps://airtable.com/shrwpGUmpyeRtvpfTAuthors tablehttps://airtable.com/shradskAUbxUeUPhfComments tablehttps://airtable.com/shriWy0K1HdG8qTs9Crafting a nice client with Ember.jsI won’t enter into much details here, but I prototyped a blog app with Ember.js, using my own ember-airtable data adapter addon. If you like to learn more make sure to check out my post about it.I chose Ember.js since it’s the framework we’re currently using at work (Nimbo X), but you can use whatever framework/library you like, say React, Angular, Vue, etc…The Ember app’s source code is available at: https://github.com/benoror/experiment_blog_xt014_dAt this point Ember Data’s Adapter is pointing directly to the Airtable API URL while exposing the secret API token to the browser, which is clearly not an ideal situation.To overcome this issue I decided to pull a trick up the sleeve…Setting up an HTTP ProxyStoring credentials in a server is a good idea to keep them private. Also interesting are the possibilities of this architecture, as we can provide other kind of functionalities at this layer, such as Auth (albeit our experiment might become less serverless), but that’s material for a future post.First I decided to avoid reinventing the wheel and use http-proxy-middleware to redirect request to my Airtable API. The code snippet to accomplish it is:https://medium.com/media/31890724b2289367316618c0452d2325/hrefDeploying the thingy…Deploying an app into Glitch is a breeze, as you can import the code from a Git repository, or edit it directly in the browser:Storing secretsWith Glitch you can set .env file with the API secrets, visible only to you:Tip: If you decide to use Zeit Now they recently announced support for environment variables and secrets!Now we can change our Ember adapter accordingly:Surge.shAs usual business, deploying to Surge.sh is a piece of cake. We can see the application running immediately afterwards:... - Node.js Airtable API Proxy
Continue reading...var express = require('express');var proxy = require('http-proxy-middleware');var options = {logLevel: 'debug',target: 'https://api.airtable.com/v0/' + process.env.APP_ID,changeOrigin: true,headers: {'Accept': 'application/json','Authorization': 'Bearer ' + process.env.API_KEY},pathRewrite: {'^/api' : ''},secure: false,ssl: {rejectUnauthorized: false}};var apiProxy = proxy(options);var app = express();... - Ember & Electron for Desktop Apps
Recently at Nimbo X we realised our end users would greatly benefit from having a “Desktop-like experience” when using our app, so we set ourselves to produce a first version of it. In this post we’ll explain our experience from a technical point of view. Download it now for OS X & Windows Publishing it to the “App Stores” distribution channels is still a work in progress, which deserves a post for itself, where we’ll narrate the bureaucratic experience while submitting the app.Meet Electron ⚛electron.atom.ioElectron is a runtime environment based on Node.js & Chromium. It allows creating desktop applications using regular web technologies, giving them access to the filesystem, hardware, OS notifications, etc. Ember + ElectronThe awesome ember-electron addon by Felix Rieseberg allowed us to quickly build app executables for major platforms by simply running: ember electron:packageIt wraps other amazing tools, like ember-packager and electron-osx-sign, into a single easy-to-use package. Other tools we relied on were: <a...
Continue reading... - 2do Meetup Ember Monterrey — Overview: EmberCLI, Ember Data, JSON API & Mirage
https://medium.com/media/66b11acda714ae47a108697fcf538112/hrefUna de las primeras preguntas que nos hacemos como developers después de aprender lo básico de un framework front-end como Ember es: Cómo creamos aplicaciones para problemas reales, con un backend y una base de datos como cimientos que nos permitirán escalarla?Ember Data es una capa de abstracción que nos permitirá conectar nuestra aplicación SPA (client-side) con nuestro backend API de manera transparente, asegurando la mayor compatibilidad y la menor fricción posible. Sin embargo es común que durante la etapa de prototipeo alguna de las siguientes situaciones se presenten: No somos/tenemos desarrolladores backendAun no se ha decidido el stack (proveedores, arquitectura, base de datos, framework)Tiempo y recursos limitadosPor estas y otras razones es conveniente usar una herramienta como ember-cli-mirage para contar desde un inicio con un API que asemeje al real, lo que nos permitira: Ser agiles al crear, adaptar y descartar ideas rapidamenteBest practices desde el inicio: TDD (Test-driven development)Productividad y escalabilidad de equipos de desarrolloSlidesOVERVIEW: EMBER-CLI, EMBER DATA, JSON API & MIRAGE by Benjamin Orozco...
Continue reading... - Ember PostgREST Dynamic UI — An approach to flexible & easy-to-maintain interfaces
This is a pet-project I worked on during the Hack Week (July 13–15th) at eCareSoft. It emerged from a casual chat between Jorge Camargo and I discussing ways to achieve dynamic forms for different medical specialties at Nimbo X, while keeping it simple and easy to maintain.
Ember PostgREST Dynamic UI — An approach to flexible & easy-to-maintain interfaces was originally published in The Backlog by Ecaresoft on Medium, where people are continuing the conversation by highlighting and responding to this story.
- Dev Notes: Fuzzy Search on PostgreSQL
My previous experience with search in Rails was 5+ years ago, then I used Sphinx as a Full-Text external search engine, which seems to have gone out of fashion. At Nimbo X we use pg_search rails gem for searching purposes, with Full-Text already enabled in PostgreSQL itself, which has worked for us so far. Nevertheless, with the increase of usage among practicians, along with our recent introduction of Medispan, support tickets related to mismatched search queries have become a cause of pain for the team. We knew our users deserve better. #MayThe4thBeWithYouFirst we needed to understand the current landscape on psql search. Luckily PgSearch documentation pointed us in the right direction: along with full-text search, other algorithms are supported through PostgreSQL contrib packages: fuzzystrmatch (Levenshtein, Double Metaphone) & pg_trgm (Trigrams). AlgorithmsLevenshtein (a.k.a. match difference)Levenshtein distance is a string metric for measuring the difference between two sequences. Informally, the Levenshtein distance between two words is the minimum number of single-character edits (i.e....
Continue reading... - AirtableSerializer
Continue reading...import Ember from 'ember';import DS from 'ember-data';/** Override RESTSerializer since it's the closest to Airtable's afaik*/export default DS.RESTSerializer.extend({/** Normalize each response from Airtable* to meet expected RESTSerializer criteria*/normalizeResponse(store, type, payload) {/** Get model name pluralized* ToDo: pluralization with Ember.Inflector*/const modelNamePlural = type.modelName + 's';/*... - adapters/application.jsimport DS from 'ember-data';export default DS.JSONAPIAdapter.extend({host: 'https://api.airtable.com',namespace: 'v0/appL0nGiD3nT1f1c4t0r',headers: {'Accept': 'application/json','Authorization': 'Bearer ' + 'keyS3CR3T'},});
- keybase.mdContinue reading...
Keybase proof
I hereby claim:
- I am benoror on github.
- I am benoror (https://keybase.io/benoror) on keybase.
- I have a public key whose fingerprint is 099E C5B1 CC72 1D45 89BF AB46 CCF1 0E48 07D4 6DA6
To claim this, I am signing this object:
{"body": {"key": {"eldest_kid": "0101db568c3dc9975669cf56ee915baae1d54ba6c6a24150cf5b142fe87382cea64e0a","fingerprint": "099ec5b1cc721d4589bfab46ccf10e4807d46da6","host": "keybase.io","key_id": "ccf10e4807d46da6","kid": "0101db568c3dc9975669cf56ee915baae1d54ba6c6a24150cf5b142fe87382cea64e0a","uid": "a1acc8f956a802d78c685b099e4eba19","username": "benoror"},"service": {"name": "github","username": "benoror"},"type": "web_service_binding","version": 1},"ctime": 1461218032,"expire_in": 157680000,"prev": "a6d0c39e65a9764ca47b281e3fd1a266a8fe5f227baf4e5c04145f4da299e5a5","seqno": 2,"tag": "signature"}with the key 099E C5B1 CC72 1D45 89BF AB46 CCF1 0E48 07D4 6DA6, yielding the signature:
-----BEGIN PGP MESSAGE----- Version: GnuPG v1 owGtUm1MHFUU3d0iBKhICCDaGugUEctCZ4aZ2ZlNWgQx0VglNJBGwMJ7M2+WgWVn mV0+NrhtUYIihG5qBAwI1NIWghapLZGUUm1t+rG10qZKW6io2dpQJRUEqpUFZ0j9 p/98f17eueecd8/N9Ty6RmfQX5oNezHoWtkhvXca6nbElDyowaAsuDBzDVaKVi9k FZDDWVgqCZgZwwmcECDNsHyqwHOciWYYjhdpBiGOoCEAiBBoCgKGZwBJETSu1iBB kSJiTaksySPAUAgHmBETJZsFKXZFsjk1W45DvMrkeRNJCBTNclAEkGJ4XiRwRLG4 SaAYATCqsFh2aAq1OQgcKEWSVUx9FK629y/8/7nvilU7QACeZ0WOZgCLk4KJ5RmW hloKCkFAcBrRgRQbKEMqGyKbrMgK5jZiKlgp8Uib68OiRXIWV8D/FDhddg2pQrDw obYQSjZBnZ4qqUSKQ5JtmJlQmbxT0sQExRAkweKppBFD1XZJQYWSxqBNDIurx4jZ FVSpZWAEnE/lEEMDzsRQPHiVMkGSJVCqKBCAZNRoIqJFkjRBIFKI5nGKoGiREgCp 5qQBjWlxym0yZla/cgKL6umQLDbgrFAQ5g5pMKwP0OkNusBHDNpe6UKCw/9Ztsvu cF0bf0efcNs/uNwwcf6GLzrzXs94qzd4IqP9ftGfs53fdy9d/6ElTwhZU3E8oAWv...
Generated at May 31, 2026, 2:35 PM