Back to Blog

Resurrecting a Dead App: Neurelo to the Rescue

...Because I want to ship an app, not build another custom backend

Every developer has their "I'll build this someday" list. This is a constant, and the only difference is how long or ambitious each person's list might be. My personal list is around a dozen or so half-started ideas, with an ongoing list of "wouldn't this be neat?" items.

One of them that kept making its way to the top of the list was an app I call "BoomKarks."

At the most basic level, BoomKarks is a standard CRUD with a database of links related to web development topics. I've been a web development instructor off and on the better part of five years. Over that time I've curated a list of hundreds of helpful links. The topics range from the history of JavaScript, helpful SQL commands, up to general "Day in the life of a developer" articles.

As an aside, I tell all my students that a majority of their coding errors will actually be spelling errors, and the code will likely be fine. As a matter of coincidence, I had a typo when trying to spell "bookmarks" in which I transposed the "m" and the "k." In the spirit of the "spelling nemesis," I decided to keep the typo. Ergo, BoomKarks.

For years I've just been writing directly to the database with every intention of writing a full blown app that I could share with students. I have been teaching full-stack web development for most of the time I've been an instructor, and I've been a professional web developer for almost 15 years. I can build APIs in Symfony PHP, Express, and Django.

Help Photo by Anncapictures via Pixabay

However, I don't necessarily want to build APIs. If I boil down Django or Express into their simplest steps, at a minimum, here's what I'm avoiding:

Setting Up an Express API

  1. Initialize a new Node.js project: npm init -y
  2. Scaffold out a basic Express app (i.e. via the express-generator).
  3. Define your data Models to match your database.
  4. If you're using an ORM, run any necessary migrations.
  5. Define API routes using Express's HTTP methods like GET, POST, PUT, or DELETE.
  6. Deploy your API to a hosting service like Heroku, AWS, or Azure.

Setting Up a Django Rest API

  1. Scaffold a New Django Project django-admin startproject api
  2. Open the models.py file inside your app directory (app) and define your data model using Django's Model classes.
  3. Run migrations to create the database tables based on your models.
  4. If you're building a RESTful API, install Django REST framework and configure it in your project's settings.
  5. Define your API views to handle GET, POST, PUT, or DELETE routes.
  6. Create your url patterns in your urls.py, i.e. path('api/', views.api_view, name='api_view'),
  7. Deploy your Django API to a hosting service like Heroku, AWS, or Azure.

Anyone who has completed those steps before knows that I'm leaving out a lot of small, incremental steps. Those outlines also assume that everything goes well and you can quickly deploy. In reality, those six or seven steps are actually off by at least half. If I enjoyed working on server frameworks and managing cloud servers (and/or AWS clusters), then none of those steps would necessarily be daunting. However, since I do not enjoy working on backend services, those seven steps might as well be 7000 steps.

My preference is focus on the frontend. Outside of teaching I'm usually working on UI development. My "happy place" is the frontend, React, Remix, Next, Vue, etc... Building an API was like that one chore you keep pushing to the bottom of your to-do list. So, there it was, continuously backlogged.

My app languished, dreaming of a time when it could see the light of day.

This is what my app was doing, staring menancingly at me. Wikimedia Commons

The best way to build a zombie app is to start on an idea that involves something you can do but don't want to do. The number of repos I've half started that are gathering dust with undead code is staggering. I don't think anyone starts with the idea of building an undead pile of code. We're all mad scientists to a degree, and we often start with the best of intentions. Then life finds a way to derail us, and instead of creating life you just have a bunch of decaying parts lying about. I knew BoomKarks solved real problems, after all I would SELECT * FROM links on a regular basis to pass resources on to my students. I couldn't let the idea go, but I also couldn't muster up the energy to put the beast on an operating table, raise it outside my castle, and expose it to enough lightning to animate its dead corpose.

Enter Neurelo and my "It's ALIVE!!" moment...

Neurelo Gives Me the Power to Wake the Dead

There are many upsides to Neurelo, but let's start with the biggest: I added my database as a data source and BOOM 💥, I had an API!

Seriously, that's all there was to get up and running with the BoomKarks API. Neurelo read my schema and conjured up GET, POST, PUT, and DELETE routes for all my primary tables. Within minutes I could throw out some fetch() queries and was able to do all the basic CRUD. No Node, no Python, no PHP, just point the data source as my PostgreSQL server*, flip with switch and BOOMKARKS LIVES!

NOTE*: It could really be any database, i.e. MySQL, MongoDB. I prefer Postgres but Neurelo is totally agnostic in this regard.

Things didn't stop there!

Neurelo basically (or, metaphorically, it's not a sentient app) said, "Why stop at the basics when we can give you the whole shebang?"

I am like most developers, most of my time is spent writing code and almost none of it is dedicated to documenting that code. Almost preternaturally, Neurelo generated all the API docs for me based on my schema. I'll let Neurelo speak for itself here (again, metaphorically, I swear it's not sentient!):

The BoomKarks project has two APIs available for use automatically generated by Neurelo. The REST API has predictable resource-oriented URLs, accepts JSON-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs. The GraphQL API exposes a single endpoint where clients can send GraphQL queries or mutations and a strictly-typed schema that be be shared across consumers.
Neurelo documents so I don't have to!

In addition to the documentation, they also provide sample code for various operations. For example:


# This operation creates a new record in the database for the links model.

curl -X POST https://[MY NEURELO API URL]/rest/links/__one?<query-string>
 -H 'Content-Type: application/json'
 -d <request-body>
  
# This operation returns a single record from the database for the links model.

curl -X GET https://[MY NEURELO API URL]/rest/links/{id}?<query-string>
 -H 'Content-Type: application/json'
  

I could opt to copy/paste that into my terminal, or fire up something like Postman or Insomnia. The docs gave me the routes, the syntax, and what my expected response will look like. If I make a change to the database, Neurelo automatically picks it up! The routes return the changes automatically.

Along with this, I was able to add any number of custom endpoints simply adding SQL queries. For clarification, these weren't Neurelo specific queries, I didn't have to tune anything in my database to work with Neurelo. These were all queries I would have written for any API.

It was as easy as:

  1. Write a SQL query with the necessary JOIN statements.
  2. Test and confirm the query against my database (Neurelo let's you do this on the dashboard interface).
  3. Give the route a name and commit the new route + query in Neurelo.
  4. A new endpoint is born, complete with GET, POST, PUT, PATCH methods.
Custom endpoints are a SQL query away.
Custom Query Endpoints in Neurelo
Yes, it does  raw `PATCH` endraw  requests too!

Time out to mention an added bonus...

I can write backends, and I can write SQL. But, it's not my strong suit. Neurelo helped me out there too!

The beta version of their AI Assistant has been a lifesaver. More accurately, it's a timesaver. The time I'm not spending looking up SQL statements is time I can work on the parts of the app I enjoy.

(Again, I promise, the app is not sentient...but I wouldn't blame you if you were starting to think it was!)

We now return you to the rest of the post, already in progress...

Those four steps above turn hours of work into minutes. When you consider that you don't need to manage anything but your data source, and all those unknown, incremental, steps are removed, you've got an API up and running in a fraction of the time. As a frontend-focused developer, the ability to jump directly into frontend code without fine-tuning an API was a game changer.

If you noticed that step 3 involved a commit, I don't mean in that in any colloquial sense. Neurelo tracks changes to your API via commits. At any point you can stop its runners and change the commit that's being loaded by the environment. You don't lose work, giving you the ability to try out features in a non-destructive way. If something doesn't work, simply rollback to an earlier commit and you're back up and running. It's all the benefits of git and continuous integration rolled into a few clicks on the dashboard.

The commit flow means I can make changes relatively worry free.

A Resurrected App and a Developer Begins Plotting the Next Step

Thanks to Neurelo, I was back in my comfort zone, focusing on UI development. It was like relaxing on my couch in comfy pajamas. I was working with my framework of choice without the dread of having an undead app lurking in the background. I wasn't hampered by the daunting task of building an API from scratch. I didn't feel trapped by half an idea that would shackle me to servers that needed managing, incurring additional hosting costs and maintenance time. Like the final seconds before the credits of the movie roll, I felt like I had escaped an ordeal and the future was bright!

	
// Hey, you want some topic data? Here, have some topic data!
export async function loader() {
    const res = await fetch(
        '[MY NEURELO API URL]/topics',
        {
            method: 'GET',
            headers: {
                'X-API-KEY': `[MY API KEY]`,
            },
        }
    );
    return json(await res.json());
}

export default function App() {
    const apiRequest = useLoaderData<typeof loader>();
    const { data } = apiRequest;
...
	

The real beauty here was the speed at which I could release my app and gather feedback. With the API hurdle behind me, I could focus on the usability of the app, and quickly push out updates and improvements! This turbo-charged development cycle let me spot bugs and brainstorm new features in record time. Remember when I mentioned that Neurelo picks up the changes to the database? I decided to add the ability to upvote/downvote a link. A simply migration later and the endpoints were ready for POST requests to update this entirely new field in an existing table.

At the risk of being cliche, I could "fail fast" and keep evolving my app. I can fix issues, add improvements, and introduce features the never occurred to me during the initial development phase.

	
<ul>
    {links.map((link: any, id: number) => {
        const { link_id, link_url, link_title, link_score } = link;
        return (
            <li key={id} className='flex py-2'>
                <a href={link_url} className='flex-1 pr-4' target="_blank" rel="noreferrer">
                    {link_title}
                </a>
                <div className='flex'>
                    <HandThumbUpIcon
                        className='mx-2 w-4 cursor-pointer'
                        onClick={() => UpVote(link_id, link_score)}
                    />
                    <div className='px-3'>{link_score}</div>
                    <HandThumbDownIcon
                        className='mx-2 w-4 cursor-pointer'
                        onClick={() => DownVote(link_id, link_score)}
                    />
                </div>
            </li>
        );
    })}
</ul>
	

Neurelo didn't just resurrect my app; they turned it into a beast of unlimited power! I've since released it to my current group of students and asked them to provide feedback that will inform the direction of BoomKarks moving forward.

The BEAST LIVES! - Image by Christine Engelhardt from Pixabay

Conclusion: Neurelo - Because Even Dead Apps Deserve a Second Chance

If you've ever encountered a zombie, then you know it's better off dead than chasing you. Standard zombie lore says to chop off the head and leave it to rot. BUT, in the world of software, nothing every truly dies. If you just can't pull the trigger on an rm -rf my_dead_app, or you're put off by the thought of creating another DIY API, then Neurelo has all the magic you could want. It lets you focus on your strengths and preferences as a developer.

Sometimes, it's not about doing everything yourself but finding the Michone to your Rick, the Renfield to your Dracula, the Gandalf to your Frodo. In my case, Neurelo was the partner I didn't know I needed. It came along to save BoomKarks from the abyss, and allowed me to focus on what I do best.

So, if you're stuck with a dead app, don't despair! Neurelo can help you navigate your escape from the graveyard of ideas. Because in the world of software development, even dead apps deserve a second shot at greatness.

Whether you're starting from scratch or need to bring a project back from the dead, building with Neurelo can supercharge your process!



Credits: This post was authored by
Sean Reid and originally published here. Republished here with permission. Some content has been modified for brevity.