103
Bootstrapping an App for Launch A rapid, low-cost, server-less approach to app development @craigphares sixoverground.com

Bootstrapping an App for Launch

Embed Size (px)

Citation preview

Page 1: Bootstrapping an App for Launch

Bootstrapping an App for LaunchA rapid, low-cost, server-less approach to app development

@craigpharessixoverground.com

Page 2: Bootstrapping an App for Launch
Page 3: Bootstrapping an App for Launch

dropdrop.it/

Page 4: Bootstrapping an App for Launch

Developer

Page 5: Bootstrapping an App for Launch

There’s never been a better time to be a developer

Page 6: Bootstrapping an App for Launch
Page 7: Bootstrapping an App for Launch

Series1

Number of apps Barrier to entry

Page 8: Bootstrapping an App for Launch

App store markets are over-saturated

Page 9: Bootstrapping an App for Launch

There are over 2.2 million apps available for download on the Google Play Store

Statistahttp://www.statista.com/statistics/276623/number-of-apps-available-in-leading-app-stores/

Page 10: Bootstrapping an App for Launch

Just building a great product isn’t enough

Page 11: Bootstrapping an App for Launch

Less than 0.01 percent of consumer mobile apps are considered a financial success

Gartnerhttp://www.gartner.com/newsroom/id/2648515

Page 12: Bootstrapping an App for Launch
Page 13: Bootstrapping an App for Launch

Doing what someone else already knows how to do takes the world from 1 to n, adding more of something familiar. But when you do something new, you go from 0 to 1.”- Peter Thiel

Page 14: Bootstrapping an App for Launch

Apps need to stand out

Page 15: Bootstrapping an App for Launch

65.5% of smartphone users download zero apps per month

Quartzhttp://qz.com/253618/most-smartphone-users-download-zero-apps-per-month/

Page 16: Bootstrapping an App for Launch

After launch,It can take years to reach product/market fit

Page 17: Bootstrapping an App for Launch

Product/market fit means being in a good market with a product that can satisfy that market.”- Marc Andreessen

Page 18: Bootstrapping an App for Launch

Prepare to pivot

Page 19: Bootstrapping an App for Launch

Successful Tech Pivots• Pinterest was a mobile shopping app called Tote for 1 year• Twitter was a side-project of the podcast directory Odeo• Instagram began as Burbn, a check-in app with gaming

elements from Mafia Wars - and a photo feature• Android was an operating system for cameras in the 2

years before it was acquired by Google

Page 20: Bootstrapping an App for Launch

Monthly overhead

Page 21: Bootstrapping an App for Launch

55% of companies will increase their content marketing budget this year

Content Marketing Institutehttp://contentmarketinginstitute.com/wp-content/uploads/2014/10/2015_B2B_Research.pdf

Page 22: Bootstrapping an App for Launch

Apps are expensiveto make

Page 23: Bootstrapping an App for Launch

How much does it cost to build an app?• Big shops: $500,000 to $1,000,000• Average shops: $150,000 to $450,000

• Small shops: $50,000 to $100,000

Savvy Appshttp://savvyapps.com/blog/how-much-does-app-cost-massive-review-pricing-budget-considerations

Page 24: Bootstrapping an App for Launch

How much does it cost to build an app (cont.)?• Zero-frills: $9,900• Full-featured: $50,100

Crewhttp://howmuchtomakeanapp.com

Page 25: Bootstrapping an App for Launch

How much does it cost to build an app (cont.)?

$10,000 to $1,000,000

Page 26: Bootstrapping an App for Launch

Talent

Page 27: Bootstrapping an App for Launch

DesignerGraphic Designer

$51,360/year = $25/hour

Glassdoorhttps://www.glassdoor.com/Salaries/graphic-designer-salary-SRCH_KO0,16.htm

Page 28: Bootstrapping an App for Launch

Back-end engineerRuby on Rails Developer

$93,906/year = $50/hour

Glassdoorhttps://www.glassdoor.com/Salaries/ruby-on-rails-developer-salary-SRCH_KO0,23.htm

Page 29: Bootstrapping an App for Launch

Front-end developerAndroid Developer

$84,562/year = $50/hour

Glassdoorhttps://www.glassdoor.com/Salaries/android-developer-salary-SRCH_KO0,17.htm

Page 30: Bootstrapping an App for Launch

Project managerSoftware Project Manager

$108,659/year = $50/hour

Glassdoorhttps://www.glassdoor.com/Salaries/software-project-manager-salary-SRCH_KO0,24.htm

Page 31: Bootstrapping an App for Launch

Server costs

Page 32: Bootstrapping an App for Launch

Infrastructure as a Service• Approximately $60/month for:• Small EC2 instance• S3 bucket• CloudFront CDN

• $50/hour for maintenance

AWS

Amazon Web Serviceshttps://calculator.s3.amazonaws.com/index.html

Page 33: Bootstrapping an App for Launch

Platform as a Service• Approximately $125/month for:• Standard Plan with 3-1x dynos• Production database• SSL Endpoint• Web sockets push add-on

Heroku

Heroku Pricinghttps://www.heroku.com/pricing

Page 34: Bootstrapping an App for Launch

So… how much?

Page 35: Bootstrapping an App for Launch

Example app• Social login• User profiles• Friendships• User-generated

content

• Push notifications• Geolocation• Analytics

Page 36: Bootstrapping an App for Launch

Estimate• Design: $25/h x 100 h = $2,500• Back-end: $50/h x 200 h = $10,000• Front-end: $50/h x 200 h = $10,000• Project management: $50/h x 50 h = $2,500• Total: $25,000

Page 37: Bootstrapping an App for Launch

Design

Front-endBack-end

PM

ServerBreakdown

Page 38: Bootstrapping an App for Launch

Design

Front-endBack-end

PM

ServerPotential Savings

Page 39: Bootstrapping an App for Launch

Imagine if we could cut out the back-end

Page 40: Bootstrapping an App for Launch

Imagine if we could focus on making the app awesome

Page 41: Bootstrapping an App for Launch

Imagine if our overhead was zero,and we could scale as needed

Page 42: Bootstrapping an App for Launch

Here’s how we get there

Page 43: Bootstrapping an App for Launch

What we often do

Untitled 1

Untitled 2

Untitled 3

Budget spent MAU / Revenue

Launch

Page 44: Bootstrapping an App for Launch

What we should do

Untitled 1

Budget spent MAU / Revenue

Launch

Page 45: Bootstrapping an App for Launch

MVP(Minimum Viable Product)

Page 46: Bootstrapping an App for Launch

Ideas

CodeData

Learn Build

Measure

theleanstartup.com

Page 47: Bootstrapping an App for Launch

Back-end as a Service

Page 48: Bootstrapping an App for Launch

Server-less is at its most simple an outsourcing solution

Page 49: Bootstrapping an App for Launch
Page 50: Bootstrapping an App for Launch

Authentication Service

Traditional client/server architecture

Client(s) (app)

Authentication Service

API Gateway

Database

Server Application

Push Notification Service

File StorageSolution

Analytics

Page 51: Bootstrapping an App for Launch

Authentication Service

Server-less architecture

Client(s) (app)

Authentication Service

API Gateway

Database

Server Application

Push Notification Service

File StorageSolution

Analytics

Authentication ServiceAnalytics Database

Page 52: Bootstrapping an App for Launch

But… why?

Page 53: Bootstrapping an App for Launch

Benefits• Reduced operational cost• Reduced development cost• Reduced scaling costs• Reduced operational management• Reduced time to market

Page 54: Bootstrapping an App for Launch

Drawbacks• Vendor control• Vendor commitment• Security concerns• Repetition of logic across clients• Loss of server optimizations

Page 55: Bootstrapping an App for Launch

Okay, great.

Page 56: Bootstrapping an App for Launch

Back-end servicesWith free tiers

Page 57: Bootstrapping an App for Launch

File storage

Cloudinary Filestack

Page 58: Bootstrapping an App for Launch

Analytics

Flurry

Localytics

Segment

Fabric

Page 59: Bootstrapping an App for Launch

Real-time Push /Push notifications

Urban Airship

OneSignal

PubNub

Page 60: Bootstrapping an App for Launch

Mobile BaaS (MBaaS)Back-end as a service, built specifically for mobile apps

Page 61: Bootstrapping an App for Launch

ParseSunset by Facebook

Host your own from the GitHub repo:https://github.com/ParsePlatform/parse-server

Page 62: Bootstrapping an App for Launch

KinveyAuthorizationData storageFile storage with CDNPush/SMSAnalytics

Page 63: Bootstrapping an App for Launch

AWS Mobile ServicesAuthenticationData storageCloud logicNoSQL databaseAnalyticsPush notifications

Page 64: Bootstrapping an App for Launch

FirebaseRecently overhauled by Google

Realtime databaseAuthenticationPush notificationsFile storageRemote configAnalytics

Page 65: Bootstrapping an App for Launch

Live codingLet’s build Instagram (Lite)

Page 66: Bootstrapping an App for Launch

• Facebook loginPost photosNews feedCommentsLikesActivity feedFollow friendsPush notifications

Page 67: Bootstrapping an App for Launch

Firebase

Page 68: Bootstrapping an App for Launch

Bittypicgithub.com/sixoverground/bittypic-androidAn itty bitty photo sharing app

Page 69: Bootstrapping an App for Launch

Create a project

Page 70: Bootstrapping an App for Launch

The Firebase console

Page 71: Bootstrapping an App for Launch

Add the SDKbuildscript { // ... dependencies { // ... classpath 'com.google.gms:google-services:3.0.0' }}

build.gradle

Page 72: Bootstrapping an App for Launch

Add the SDK (cont.)apply plugin: 'com.android.application'android { // ...}dependencies { // ... compile 'com.google.firebase:firebase-core:9.2.1'}// ADD THIS AT THE BOTTOMapply plugin: 'com.google.gms.google-services'

Available libraries

AnalyticsRealtime DatabaseStorageCrash ReportingAuthenticationCloud Messaging / NotificationsRemote ConfigInvites / Dynamic LinksAdMobApp Indexing

app/build.gradle

Page 73: Bootstrapping an App for Launch

The data model

User Photo Activity• facebookId• email• displayName• profilePictureUrl• pushToken

• photoUrl• user

• owner• recipient• key• text• photo

Page 74: Bootstrapping an App for Launch

Enable Facebook login

Page 75: Bootstrapping an App for Launch

Authenticate with Facebook// Initialize Facebook Login buttonmCallbackManager = CallbackManager.Factory.create();LoginButton loginButton = (LoginButton) findViewById(R.id.button_facebook_login);loginButton.setReadPermissions("email", "public_profile");loginButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() { @Override public void onSuccess(LoginResult loginResult) { Log.d(TAG, "facebook:onSuccess:" + loginResult); handleFacebookAccessToken(loginResult.getAccessToken()); }

@Override public void onCancel() { Log.d(TAG, "facebook:onCancel"); // ... }

@Override public void onError(FacebookException error) { Log.d(TAG, "facebook:onError", error); // ... }});

FacebookLoginActivity.java

Page 76: Bootstrapping an App for Launch

Authenticate with Facebook (cont.)private void handleFacebookAccessToken(AccessToken token) { Log.d(TAG, "handleFacebookAccessToken:" + token);

AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken()); mAuth.signInWithCredential(credential) .addOnCompleteListener(this, new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());

// If sign in fails, display a message to the user. If sign in succeeds // the auth state listener will be notified and logic to handle the // signed in user can be handled in the listener. if (!task.isSuccessful()) { Log.w(TAG, "signInWithCredential", task.getException()); Toast.makeText(FacebookLoginActivity.this, "Authentication failed.", Toast.LENGTH_SHORT).show(); } // ... } });}

FacebookLoginActivity.java

Page 77: Bootstrapping an App for Launch

Authenticate with Firebaseprivate FirebaseAuth.AuthStateListener mAuthListener;

@Overrideprotected void onCreate(Bundle savedInstanceState) { mAuthListener = new FirebaseAuth.AuthStateListener() { @Override public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) { FirebaseUser user = firebaseAuth.getCurrentUser(); if (user != null) { // User is signed in Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid()); } else { // User is signed out Log.d(TAG, "onAuthStateChanged:signed_out"); } } };}

FacebookLoginActivity.java

Page 78: Bootstrapping an App for Launch

Write to your database// Write a user to the databaseFirebaseDatabase database = FirebaseDatabase.getInstance();DatabaseReference myRef = database.getReference("user");

myRef.setValue("Norm");

EditPhotoActivity.java

Page 79: Bootstrapping an App for Launch

File Storage// Points to the root referencestorageRef = storage.getReferenceFromUrl("gs://<your-bucket-name>");

// Points to "images"imagesRef = storageRef.child("images");

// Points to "images/cat.jpg"// Note that you can use variables to create child valuesString fileName = "cat.jpg";catRef = imagesRef.child(fileName);

// File path is "images/cat.jpg"String path = catRef.getPath();

// File name is "cat.jpg"String name = catRef.getName();

// Points to "images"imagesRef = catRef.getParent();

EditPhotoActivity.java

Page 80: Bootstrapping an App for Launch

Upload Files// Get the data from an ImageView as bytesimageView.setDrawingCacheEnabled(true);imageView.buildDrawingCache();Bitmap bitmap = imageView.getDrawingCache();ByteArrayOutputStream baos = new ByteArrayOutputStream();bitmap.compress(Bitmap.CompressFormat.JPEG, 100, baos);byte[] data = baos.toByteArray();

UploadTask uploadTask = photoRef.putBytes(data);uploadTask.addOnFailureListener(new OnFailureListener() { @Override public void onFailure(@NonNull Exception exception) { // Handle unsuccessful uploads }}).addOnSuccessListener(new OnSuccessListener<UploadTask.TaskSnapshot>() { @Override public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { // taskSnapshot.getMetadata() contains file metadata such as size, content-type, and download URL. Uri downloadUrl = taskSnapshot.getDownloadUrl(); }});

EditPhotoActivity.java

Page 81: Bootstrapping an App for Launch

Read from your database// Read from the databasemyRef.addValueEventListener(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { // This method is called once with the initial value and again // whenever data at this location is updated. String value = dataSnapshot.getValue(String.class); Log.d(TAG, "Value is: " + value); }

@Override public void onCancelled(DatabaseError error) { // Failed to read value Log.w(TAG, "Failed to read value.", error.toException()); }});

PhotoTimelineActivity.java

Page 82: Bootstrapping an App for Launch

Monitor token generation@Overridepublic void onTokenRefresh() { // Get updated InstanceID token. String refreshedToken = FirebaseInstanceId.getInstance().getToken(); Log.d(TAG, "Refreshed token: " + refreshedToken);

// TODO: Implement this method to send any registration to your app's servers. sendRegistrationToServer(refreshedToken);}

AnDevConFirebaseInstanceIdService.java

Page 83: Bootstrapping an App for Launch

Receive notifications@Overridepublic void onMessageReceived(RemoteMessage remoteMessage) { // TODO(developer): Handle FCM messages here. // If the application is in the foreground handle both data and notification messages here. // Also if you intend on generating your own notifications as a result of a received FCM // message, here is where that should be initiated. See sendNotification method below. Log.d(TAG, "From: " + remoteMessage.getFrom()); Log.d(TAG, "Notification Message Body: " + remoteMessage.getNotification().getBody());}

AnDevConFirebaseMessagingService.java

Page 84: Bootstrapping an App for Launch

Send an upstream notificationFirebaseMessaging fm = FirebaseMessaging.getInstance();fm.send(new RemoteMessage.Builder(SENDER_ID + "@gcm.googleapis.com") .setMessageId(Integer.toString(msgId.incrementAndGet())) .addData("my_message", "Hello World") .addData("my_action","SAY_HELLO") .build());

AnDevConService.java

If using Firebase, sending notifications needs to be done from the server.

Page 85: Bootstrapping an App for Launch

Launch party!

Page 86: Bootstrapping an App for Launch

What we should do

Untitled 1

Budget spent MAU / Revenue

Launch

Page 87: Bootstrapping an App for Launch

Create a Landing Page

Page 88: Bootstrapping an App for Launch
Page 89: Bootstrapping an App for Launch

Social Presence

Page 90: Bootstrapping an App for Launch

Choose a launch date

Page 91: Bootstrapping an App for Launch

thunderclap.it/

Page 92: Bootstrapping an App for Launch

Test test test

Page 93: Bootstrapping an App for Launch
Page 94: Bootstrapping an App for Launch

Communities

Page 95: Bootstrapping an App for Launch

slacklist.info/

Page 96: Bootstrapping an App for Launch

/r/startups/r/sideproject/r/apps

Page 97: Bootstrapping an App for Launch

news.ycombinator.com/

Page 98: Bootstrapping an App for Launch

helpareporter.com/

Page 99: Bootstrapping an App for Launch

SocialRank.com

Page 100: Bootstrapping an App for Launch

uberhunters.com/

Page 101: Bootstrapping an App for Launch

Let’s review• Cut-out over half the development budget with no back-end• Outsource any server effort with MBaaS• Spend less time programming the plumbing• Spend more time making the app stand out• On-board tons of beta testers prior to launch to receive critical feedback• Generate buzz leading up to launch through influencers and free services• Bring the app to market quickly• Keep overhead to zero until reaching product/market fit• Iterate - learn, tweak, build, test

Page 102: Bootstrapping an App for Launch

Launch party!

Page 103: Bootstrapping an App for Launch

@craigpharessixoverground.com

github.com/sixoverground/bittypic-android/

Thank you!

Bootstrapping an App for Launch