Writing Your First Flutter Application With Deno and Postgres

A brief demonstration on how to build your Flutter App with Deno and Backend on Postgres.

Author

Devanand Padmanaban
Devanand PadmanabanSoftware Engineer

Date

Jun 22, 2020

We are back with Deno - the Server-side Runtime which was launched recently and is promisingly getting a lot of lauds from the Developer community. Obviously, it's time for us to get our hands dirty by doing the practical implementation of building a running application!

Read my previous article here to know everything about Deno and what it promises to give to the Developer community.

So, without any further delay, let's get into the practical implementation of Deno with a Flutter Application.

Why Flutter with Deno?

Flutter has been proven as the most propitious Mobile App Development framework. Hence, it would be great to have Flutter as a companion while experimenting with Deno. 

Additives

  • Flutter - The Frontend Mobile User Interface Development framework by Google.
  • Deno - The server-side runtime.
  • Postgres - The Relational Database
  • Android Studio and VS Code - The IDE for Coding (Your preference!)

Concept of the Application

Let's build a sample application that posts poems written by you. Also, let the home screen be similar to the feed page of any social media application you have used. I'd like to name this application Scribblings.

Scribblings - Steps to make the server-side and Database

Every action becomes a process with data - Me!

To start with, we need some data to support the app. Hence, we shall set up a Postgres server on the local machine by downloading the Postgres Installer from the official website here.

I personally prefer Postico - The UI interface for Postgres DB, which helps me to dump the data and create tables easily. It's completely your choice to stick with pgadmin or to go for Postico which can be downloaded here.

A deep analysis on data modeling helps fix the data structure. So, after analysis, the fields required for our application along with their types are listed as follows :

  • id - integer
  • name - text
  • poem - text
  • description - text
  • createdAt - timestamp with time zone
  • updatedAt - timestamp with time zone

The table with fields is created under a specific database.

Hence, after creating the table under the database poems, your table will look similar to this :

Now, since the data part is ready, let's look into the Server and Routes setup.

Before choosing, you must know about the following modules that help:

Oak - A middleware framework for Deno's http server, including a router middleware.

deno-postgres - PostgreSQL driver for Deno

Denon - A TS based script used for running a server similar to nodemon. You can use the denon start command to keep running the server.

Now we'll go step by step in building the Serverside application!

Config File:

To Connect with any Database, we need a Client to contact which takes the credentials as a token. Here we create a new file called config.ts and an object with all the database credentials and export it so that it can be used commonly along the files.

Controller File:

We need to create controller file to control the routes. This is where the Oak framework and Deno-postgres modules are used. We name this file as user_controller.ts

The first step is to import the required modules. As Deno supports URL imports for modules, I'm directly importing the Oak framework from the Deno Third Party Module Library. Also, I'm importing the dbCredentials object we created from config.ts file:

import {dbCredentials} from '../models/config.ts';
import { Client } from "https://deno.land/x/postgres/mod.ts";

Now I am creating a method getPosts to perform the GET request. Since it takes the context for the arrow function, I am naming the object as response. As an additional advantage of TypeScript, I am specifying the type of response as any.

async ({ response }: { response: any }) => {}

Now, create a client object using the Client() class by passing the dbCredentials as follows:

const client = await new Client(dbCredentials);

You may wonder why I am using the async/await keywords method. It is fortunate that Deno supports asynchronous actions that the likes of async/await promise.

Now it's time for the core logic. For better structural advantage, we prefer to write the logic inside try-catch blocks.

await client.connect()
const result = await client.query("SELECT * FROM posts")

Getting into some TypeScript magic, to process the data which comes as a raw query result, we create an object, get the field and values from each row, bind them into a JSON kind of format and push into an array of posts.

const posts = new Array()    
result.rows.map(p => {
  let obj: any = new Object()
  result.rowDescription.columns.map((element, index) => {
    obj[element.name] = p[index]
  })
  posts.push(obj)
})

To match the response, we bind and send the data as follows:

response.body = {
  success: true,
  data: posts
}

To manipulate the error and close the connection, we use the catch and finally blocks.

catch (err) {
  response.status = 500
  response.body = {
    success: false,
    msg: err.toString()
  }
} 
finally {
  await client.end()
}

Finally, the user_controller.ts file will be conceived like this :

Routes File:

We need to design the routes for using the Controller methods we created. Hence, we call the Router method from the Oak Standard Library. Also, we need to import the getPosts method from the controller file.

import { Router } from 'https://deno.land/x/oak/mod.ts'
import { getPosts } from '../controller/user_controller.ts'

const router = new Router()
router.get('/api/posts', getPosts)
export default router

Server File:

We are at the end of the server-side application. Now we can set up a new application by creating an instance to the Application() class called app.

const app = new Application()
app.use(router.routes())
app.use(router.allowedMethods())
await app.listen({ port: +port })

In your terminal, go for denon start command after setting up the configuration and flag values to run the server.ts file.

Scribblings - Steps to make the Flutter UI and Integrations

Good Start is half the way done - Anonymous

Now that we have successfully integrated the API, let's move on to the UI creation and Integration in Flutter.

API Handler File:

We create a service named APIHandler.dart. To perform the actions, import the http module inside the pubspec.yaml file.

import 'dart:convert';
import 'package:http/http.dart' as http;
import 'package:scribblings/services/config.dart';

class APIHandler {
  static Future<dynamic> get(url) async {
    print("hitting it inside the get request");
    print(config["baseUrl"] + url);
    return http
        .get(config["baseUrl"] + url)
        .then((http.Response response) {
      final int statusCode = response.statusCode;
      if (statusCode < 200 || statusCode > 400 || json == null) {
        throw new Exception("${response.body.toString()}");
      }
      return utf8.decode(response.bodyBytes);
    });
  }
}

Model File:

Use a JSON to Dart Converter online to convert the JSON response into a FeedCardModel.

class FeedCardModel {
  int id;
  String name;
  String poem;
  String createdAt;
  String description;
  String updatedAt;

  FeedCardModel({this.id, this.name, this.poem, this.createdAt, this.description, this.updatedAt});

  FeedCardModel.fromJson(Map<String, dynamic> json) {
    id = json['id'];
    name = json['name'];
    poem = json['poem'];
    createdAt = json['createdAt'];
    description = json['description'];
    updatedAt = json['updatedAt'];
  }

  Map<String, dynamic> toJson() {
    final Map<String, dynamic> data = new Map<String, dynamic>();
    data['id'] = this.id;
    data['name'] = this.name;
    data['poem'] = this.poem;
    data['createdAt'] = this.createdAt;
    data['description'] = this.description;
    data['updatedAt'] = this.updatedAt;
    return data;
  }
}

Controller File:

data = await APIHandler.get('api/posts');
data = json.decode(data);
data["data"].forEach((post) {
  Map postJsonData = post;
  FeedCardModel obj = FeedCardModel.fromJson(postJsonData);
  feedList.add(obj);
});

Posts Page:

PostController postController = PostController()
Container(
  height: 300,
  width: MediaQuery.of(context).size.width,
  color: Colors.white,
  child: Center(
    child: Text(
      widget.feedList.poem,
      style: TextStyle(fontFamily: 'Sacramento', fontSize: 28),
    ),
  ),
),
Container(
  color: Colors.white,
  child: Column(
    children: <Widget>[
      SizedBox(height: 20),
      Container(
        child: Center(
          child: Text(
            widget.feedList.description,
            style: TextStyle(
              color: Colors.blue,
              fontSize: 18,
              fontStyle: FontStyle.italic,
            ),
          ),
        ),
      )

It is important to note that I have used additional support in our Flutter Application :

  • State Management Technique - Provider
  • Font Style - Sacramento - To use custom font

Resources:


Upshot - The End:

I strongly believe that this article will give you an insight into how to integrate the output of Deno along with the Flutter Application. Follow me on Twitter to get interesting updates about Deno!

Make a 🔔 sound if you built your first Flutter Application with Deno with this article!

Book a Discovery Call

Recaptcha Failed.

Related Articles.

More from the engineering frontline.

Dive deep into our research and insights on design, development, and the impact of various trends to businesses.

From RFPs to Revenue: How We Built an AI Agent Team That Writes Technical Proposals in 60 Seconds
Article

Apr 9, 2026

From RFPs to Revenue: How We Built an AI Agent Team That Writes Technical Proposals in 60 Seconds

GeekyAnts built DealRoom.ai — four AI agents that turn RFPs into accurate technical proposals in 60 seconds, with real-time cost breakdowns and scope maps.

How We Built an AI System That Automates Senior Solution Architect Workflows
Article

Apr 6, 2026

How We Built an AI System That Automates Senior Solution Architect Workflows

Discover how we built a 4-agent AI co-pilot that converts complex RFPs into draft technical proposals in 15 minutes — with built-in conflict detection, assumption surfacing, and confidence scoring.

AI Code Healer for Fixing Broken CI/CD Builds Fast
Article

Apr 6, 2026

AI Code Healer for Fixing Broken CI/CD Builds Fast

A deep dive into how GeekyAnts built an AI-powered Code Healer that analyzes CI/CD failures, summarizes logs, and generates code-level fixes to keep development moving.

A Real-Time AI Fraud Decision Engine Under 50ms
Article

Apr 2, 2026

A Real-Time AI Fraud Decision Engine Under 50ms

A deep dive into how GeekyAnts built a real-time AI fraud detection system that evaluates transactions in milliseconds using a hybrid multi-agent approach.

Building an Autonomous Multi-Agent Fraud Detection System in Under 200ms
Article

Apr 1, 2026

Building an Autonomous Multi-Agent Fraud Detection System in Under 200ms

GeekyAnts built a 5-agent fraud detection pipeline that makes decisions in under 200ms — 15x cheaper than single-model systems, with full explainability built in.

Building a Self-Healing CI/CD System with an AI Agent
Article

Mar 31, 2026

Building a Self-Healing CI/CD System with an AI Agent

When code breaks a pipeline, developers have to stop working and figure out why. This blog shows how an AI agent reads the error, finds the fix, and submits it for review all on its own.

Scroll for more
View all articles