A Simple Flutter Web App

This is the most simple, yet useful, web app I could come up with

What we'll build?

A simple web app called The Background App. It'll be just a canvas colored with a default color. We'll be able to manipulate the color by passing it as a parameter in the URL of the browser.

Why is this useful? Sometimes I want to grab screenshots of certain on-screen elements and have a specific color fill as background. So the use case will be that we'll go to that web app, set the desired color, and bring the elements we want to capture on top. Then, we do the capture with Cmd + Shift + 4 on Mac, or Windows key + Shift + S on Windows.

The environment

I'm developing a simple example web app using the latest master channel. The development machine that I'm using is a Mac and the IDE of choice for this exercise is IntelliJ IDEA Community Edition. Also, I have the Flutter SDK and the Flutter + Dart plugins installed. You can follow along using the Visual Studio Code IDE as well. Chrome browser should be installed too.

Building it up

We'll work with the Terminal, although you can create the project using IntelliJ's UI ( FileNewProject…, then select Flutter). First, we'll make sure that we are inside the folder we want to create the project. For me, that is the default folder that IntellliJ IDEA creates ~/IdeaProjects/. Then I run the following command:

flutter create background

This will start creating a new project called background. You can replace the name background with anything else.

Creating project background......Running "flutter pub get" in background...                       2,295ms
Wrote 129 files.
All done!
In order to run your application, type:
$ cd background
$ flutter run
Your application code is in background/lib/main.dart.

To make sure everything's fine we can run:

cd background
flutter run -d chrome

This will run our newly created app inside Chrome. You should see the following:

Image for post
Image for post

You can open the newly created project in your IDE of choice, so it's easier to work with the project's files.

First of all, we need to get rid of all these widgets that are filling up the screen.

In the main.dart file just select all code and replace it with the following:

import 'package:flutter/material.dart';

void main() {
runApp(Background());
}

class Background extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
);
}
}

The above code returns a StatelessWidget Container filled with white color.

After you hot-reload you should see:

Image for post
Image for post

For the next step, we could either use the dart:html package or use the universal_html package. The recommended way is to use the latter because we should "avoid using web-only libraries outside Flutter web plugin packages".

dependencies:
flutter:
sdk: flutter
universal_html: ^1.2.3

So, after adding our dependency into pubspec.yaml, we can import the package and use the window object to get the color value from the URL (if any).

When running the Flutter app, the default address looks something like this:

http://localhost:62480/#/

We'll pass the color value as a HEX color. A typical HEX color has a length of 7. It starts with the # then followed by 6 characters. For example, if we want to pass on the color red that would be:

http://localhost:62480/#/#FF0000

Now that the color we want to use is in the URL ( which can be accessed by window.location) we can use window.location.hash to get the part of the URL that is after the first # and that is /#FF0000

We make sure remove the / and # chars and we're left with #FF0000.

String color = window.location.hash.substring(2);

This is a String and we need a Color object. To transform the String into a Color we use a helper method:

Color hexToColor(String code) {
try {
return Color(int.tryParse(code.substring(1, 7), radix: 16) + 0xFF000000);
} catch(error) {
return Colors.white;
}
}

We try to parse the input. If anything fails we return the default white color.

Putting it all together we get:

import 'package:flutter/material.dart';
import 'package:universal_html/prefer_universal/html.dart';

void main() {
runApp(Background());
}

Color hexToColor(String code) {
try {
return Color(int.tryParse(code.substring(1, 7), radix: 16) + 0xFF000000);
} catch(error) {
return Colors.white;
}
}

class Background extends StatelessWidget {
@override
Widget build(BuildContext context) {

String color = '';
if(window.location.hash.length > 2) {
color = window.location.hash.substring(2);
}

return Container(
color: hexToColor(color),
);
}
}

The result can be seen below:

Image for post
Image for post
Image for post
Image for post

Technically we're almost done. There could be some more parsing done on the hexToColor method to support more HEX inputs (like 3 or 8 digits lengths), but for now, what we have done is sufficient.

We next move to the web folder from the root of the project. There we can find an icons folder and 3 other files: favicon.png, index.html and manifest.json . These are all a sort of template files and will be used when running the build command: flutter build web.

To go the extra mile in customizing our newly created web app, we'll do some editing in these files.

index.html

After editing this file we'll have:

<!DOCTYPE html>
<html>
<head>
<base href="/">

<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="This app will change your background.">

<!-- iOS meta tags & icons -->
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="background">
<link rel="apple-touch-icon" href="icons/Icon-192.png">

<!-- Favicon -->
<link rel="icon" type="image/png" href="favicon.png"/>

<title>The Background App</title>
<link rel="manifest" href="manifest.json">
</head>
<body>
<script>
if ('serviceWorker' in navigator) {
window.addEventListener('flutter-first-frame', function () {
navigator.serviceWorker.register('flutter_service_worker.js');
});
}
</script>
<script src="main.dart.js" type="application/javascript"></script>
</body>
</html>

Note that we removed some comments and changed the default title of the HTML auto-generated file from background to The Background App.

manifest.json

{
"name": "The Background App",
"short_name": "Background",
"start_url": ".",
"display": "standalone",
"background_color": "#FFFFFF",
"theme_color": "#FFFFFF",
"description": "This app will change your background.",
"orientation": "landscape-primary",
"prefer_related_applications": false,
"icons": [
{
"src": "icons/Icon-192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "icons/Icon-512.png",
"sizes": "512x512",
"type": "image/png"
}
]
}

Here we've changed the name, short_name, background_color, theme_color, description, and orientation. Just small changes.

The icons

We need to create 3 icons: a 16x16 px favicon.png, a 192x192 px Icon-192.png, and a 512x512 px Icon-512.png.

For this I created a simple logo, for a simple app using Adobe Illustrator:

Image for post
Image for post

The result

Image for post
Image for post

That's it. You can see the title changed, and also favicon.png shows in the browser tab.

Running the following command gets us a web release build:

flutter build web

If you want to test the result, I've placed the release build here:

To make it work on that path I had to edit the start_url in the manifest.json from . to ./flutter/background/ and the base tag in the index.html from <base href="/"> to base <base href="/flutter/background/">. You'll have to edit those if you deploy your web app to any other path than the root folder.

We've completed the simplest yet kind of useful app. Hope you enjoyed it!

Tha(nk|t’)s all!

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store