Tag Archives: codelabs

Migrating from App Engine Blobstore to Cloud Storage (Module 16)

Posted by Wesley Chun (@wescpy), Developer Advocate, Google Cloud

Introduction and background

The most recent Serverless Migration Station video demonstrated how to add use of the App Engine's Blobstore service to a sample Python 2 App Engine app, kicking off the first of a 2-part series on migrating away from Blobstore. In today's Module 16 video, we complete this journey, arriving at Cloud Storage. Moving away from proprietary App Engine services like Blobstore makes apps more portable, giving them enough flexibility to:


Showing App Engine users how to migrate to Cloud Storage

As described previously, a Blobstore for Python 2 dependency on webapp made the Module 15 content more straightforward to implement if it was still using webapp2. To completely modernize this app here in Module 16, the following migrations should be carried out:

  • Migrate from webapp2 (and webapp) to Flask
  • Migrate from App Engine NDB to Cloud NDB
  • Migrate from App Engine Blobstore to Cloud Storage
  • Migrate from Python 2 to Python (2 and) 3

Performing the migrations

Prior to modifying the application code, a variety of configuration updates need to be made. Updates applying only to Python 2 feature a "Py2" designation while those migrating to Python 3 will see "Py3" annotations.

  1. Remove the built-in Jinja2 library from app.yaml—Jinja2 already comes with Flask, so remove use of the older built-in version which may possibly conflict with the contemporary Flask version you're using. (Py2)
  2. Use of Cloud client libraries (such as those for Cloud NDB and Cloud Storage) require a pair of built-in libraries, grpcio and setuptools, so add those to app.yaml (Py2)
  3. Remove everything in app.yaml except for a valid runtime (Py3)
  4. Add Cloud NDB and Cloud Storage client libraries to requirements.txt (Py2 & Py3)
  5. Create an appengine_config.py supporting both built-in (those in app.yaml) and non built-in (those in requirements.txt) libraries used (Py2)

The Module 15 app already migrated away from webapp2's (Django) templating system to Jinja2. This is useful when migrating to Flask because Jinja2 is Flask's default template system. Switching from App Engine NDB to Cloud NDB is fairly straightforward as the latter was designed to be mostly compatible with the original. The only change visible in this sample app is to move Datastore calls into Python with blocks.

The most significant changes occur when moving the upload and download handlers from webapp to Cloud Storage. The video and corresponding codelab go more in-depth into the necessary changes, but in summary, these are the updates required in the main application:

  1. webapp2 is replaced by Flask. Instead of using the older built-in version of Jinja2, use the version that comes with Flask.
  2. App Engine Blobstore and NDB are replaced by Cloud NDB and Cloud Storage, respectively.
  3. The webapp Blobstore handler functionality is replaced by a combination of the io standard library module plus components from Flask and Werkzeug. Furthermore, the handler classes and methods are replaced by Flask functions.
  4. The main handler class and corresponding GET and POST methods are all replaced by a single Flask function.

The results

With all the changes implemented, the original Module 15 app still operates identically in Module 16, starting with a form requesting a visit artifact followed by the most recents visits page:
The sample app's artifact prompt page

The sample app's most recent visits page.

The only difference is that four migrations have been completed where all of the "infrastructure" is now taken care of by non-App Engine legacy services. Furthermore, the Module 16 app could be either a Python 2 or 3 app. As far as the end-user is concerned, "nothing happened."

Migrating sample app from App Engine Blobstore to Cloud Storage

Wrap-up

Module 16 featured four different migrations, modernizing the Module 15 app from using App Engine legacy services like NDB and Blobstore to Cloud NDB and Cloud Storage, respectively. While we recommend users move to the latest offerings from Google Cloud, migrating from Blobstore to Cloud Storage isn't required, and should you opt to do so, can do it on your own timeline. In addition to today's video, be sure to check out the Module 16 codelab which leads you step-by-step through the migrations discussed.

In Fall 2021, the App Engine team extended support of many of the bundled services to 2nd generation runtimes (that have a 1st generation runtime), meaning you are no longer required to migrate to Cloud Storage when porting your app to Python 3. You can continue using Blobstore in your Python 3 app so long as you retrofit the code to access bundled services from next-generation runtimes.

If you're using other App Engine legacy services be sure to check out the other Migration Modules in this series. All Serverless Migration Station content (codelabs, videos, source code [when available]) can be accessed at its open source repo. While our content initially focuses on Python users, the Cloud team is working on covering other language runtimes, so stay tuned. For additional video content, check out our broader Serverless Expeditions series.

How can App Engine users take advantage of Cloud Functions?

Posted by Wesley Chun (@wescpy), Developer Advocate, Google Cloud

Introduction

Recently, we discussed containerizing App Engine apps for Cloud Run, with or without Docker. But what about Cloud Functions… can App Engine users take advantage of that platform somehow? Back in the day, App Engine was always the right decision, because it was the only option. With Cloud Functions and Cloud Run joining in the serverless product suite, that's no longer the case.

Back when App Engine was the only choice, it was selected to host small, single-function apps. Yes, when it was the only option. Other developers have created huge monolithic apps for App Engine as well… because it was also the only option. Fast forward to today where code follows more service-oriented or event-driven architectures. Small apps can be moved to Cloud Functions to simplify the code and deployments while large apps could be split into smaller components, each running on Cloud Functions.

Refactoring App Engine apps for Cloud Functions

Small, single-function apps can be seen as a microservice, an API endpoint "that does something," or serve some utility likely called as a result of some event in a larger multi-tiered application, say to update a database row or send a customer email message. App Engine apps require some kind web framework and routing mechanism while Cloud Function equivalents can be freed from much of those requirements. Refactoring these types of App Engine apps for Cloud Functions will like require less overhead, helps ease maintenance, and allow for common components to be shared across applications.

Large, monolithic applications are often made up of multiple pieces of functionality bundled together in one big package, such as requisitioning a new piece of equipment, opening a customer order, authenticating users, processing payments, performing administrative tasks, and so on. By breaking this monolith up into multiple microservices into individual functions, each component can then be reused in other apps, maintenance is eased because software bugs will identify code closer to their root origins, and developers won't step on each others' toes.

Migration to Cloud Functions

In this latest episode of Serverless Migration Station, a Serverless Expeditions mini-series focused on modernizing serverless apps, we take a closer look at this product crossover, covering how to migrate App Engine code to Cloud Functions. There are several steps you need to take to prepare your code for Cloud Functions:

  • Divest from legacy App Engine "bundled services," e.g., Datastore, Taskqueue, Memcache, Blobstore, etc.
  • Cloud Functions supports modern runtimes; upgrade to Python 3, Java 11, or PHP 7
  • If your app is a monolith, break it up into multiple independent functions. (You can also keep a monolith together and containerize it for Cloud Run as an alternative.)
  • Make appropriate application updates to support Cloud Functions

    The first three bullets are outside the scope of this video and its codelab, so we'll focus on the last one. The changes needed for your app include the following:

    1. Remove unneeded and/or unsupported configuration
    2. Remove use of the web framework and supporting routing code
    3. For each of your functions, assign an appropriate name and install the request object it will receive when it is called.

    Regarding the last point, note that you can have multiple "endpoints" coming into a single function which processes the request path, calling other functions to handle those routes. If you have many functions in your app, separate functions for every endpoint becomes unwieldy; if large enough, your app may be more suited for Cloud Run. The sample app in this video and corresponding code sample only has one function, so having a single endpoint for that function works perfectly fine here.

    This migration series focuses on our earliest users, starting with Python 2. Regarding the first point, the app.yaml file is deleted. Next, almost all Flask resources are removed except for the template renderer (the app still needs to output the same HTML as the original App Engine app). All app routes are removed, and there's no instantiation of the Flask app object. Finally for the last step, the main function is renamed more appropriately to visitme() along with a request object parameter.

    This "migration module" starts with the (Python 3 version of the) Module 2 sample app, applies the steps above, and arrives at the migrated Module 11 app. Implementing those required changes is illustrated by this code "diff:"

    Migration of sample app to Cloud Functions

    Next steps

    If you're interested in trying this migration on your own, feel free to try the corresponding codelab which leads you step-by-step through this exercise and use the video for additional guidance.

    All migration modules, their videos (when published), codelab tutorials, START and FINISH code, etc., can be found in the migration repo. We hope to also one day cover other legacy runtimes like Java 8 as well as content for the next-generation Cloud Functions service, so stay tuned. If you're curious whether it's possible to write apps that can run on App Engine, Cloud Functions, or Cloud Run with no code changes at all, the answer is yes. Hope this content is useful for your consideration when modernizing your own serverless applications!

An easier way to move your App Engine apps to Cloud Run

Posted by Wesley Chun (@wescpy), Developer Advocate, Google Cloud

Blue header

An easier yet still optional migration

In the previous episode of the Serverless Migration Station video series, developers learned how to containerize their App Engine code for Cloud Run using Docker. While Docker has gained popularity over the past decade, not everyone has containers integrated into their daily development workflow, and some prefer "containerless" solutions but know that containers can be beneficial. Well today's video is just for you, showing how you can still get your apps onto Cloud Run, even If you don't have much experience with Docker, containers, nor Dockerfiles.

App Engine isn't going away as Google has expressed long-term support for legacy runtimes on the platform, so those who prefer source-based deployments can stay where they are so this is an optional migration. Moving to Cloud Run is for those who want to explicitly move to containerization.

Migrating to Cloud Run with Cloud Buildpacks video

So how can apps be containerized without Docker? The answer is buildpacks, an open-source technology that makes it fast and easy for you to create secure, production-ready container images from source code, without a Dockerfile. Google Cloud Buildpacks adheres to the buildpacks open specification and allows users to create images that run on all GCP container platforms: Cloud Run (fully-managed), Anthos, and Google Kubernetes Engine (GKE). If you want to containerize your apps while staying focused on building your solutions and not how to create or maintain Dockerfiles, Cloud Buildpacks is for you.

In the last video, we showed developers how to containerize a Python 2 Cloud NDB app as well as a Python 3 Cloud Datastore app. We targeted those specific implementations because Python 2 users are more likely to be using App Engine's ndb or Cloud NDB to connect with their app's Datastore while Python 3 developers are most likely using Cloud Datastore. Cloud Buildpacks do not support Python 2, so today we're targeting a slightly different audience: Python 2 developers who have migrated from App Engine ndb to Cloud NDB and who have ported their apps to modern Python 3 but now want to containerize them for Cloud Run.

Developers familiar with App Engine know that a default HTTP server is provided by default and started automatically, however if special launch instructions are needed, users can add an entrypoint directive in their app.yaml files, as illustrated below. When those App Engine apps are containerized for Cloud Run, developers must bundle their own server and provide startup instructions, the purpose of the ENTRYPOINT directive in the Dockerfile, also shown below.

Starting your web server with App Engine (app.yaml) and Cloud Run with Docker (Dockerfile) or Buildpacks (Procfile)

Starting your web server with App Engine (app.yaml) and Cloud Run with Docker (Dockerfile) or Buildpacks (Procfile)

In this migration, there is no Dockerfile. While Cloud Buildpacks does the heavy-lifting, determining how to package your app into a container, it still needs to be told how to start your service. This is exactly what a Procfile is for, represented by the last file in the image above. As specified, your web server will be launched in the same way as in app.yaml and the Dockerfile above; these config files are deliberately juxtaposed to expose their similarities.

Other than this swapping of configuration files and the expected lack of a .dockerignore file, the Python 3 Cloud NDB app containerized for Cloud Run is nearly identical to the Python 3 Cloud NDB App Engine app we started with. Cloud Run's build-and-deploy command (gcloud run deploy) will use a Dockerfile if present but otherwise selects Cloud Buildpacks to build and deploy the container image. The user experience is the same, only without the time and challenges required to maintain and debug a Dockerfile.

Get started now

If you're considering containerizing your App Engine apps without having to know much about containers or Docker, we recommend you try this migration on a sample app like ours before considering it for yours. A corresponding codelab leading you step-by-step through this exercise is provided in addition to the video which you can use for guidance.

All migration modules, their videos (when available), codelab tutorials, and source code, can be found in the migration repo. While our content initially focuses on Python users, we hope to one day also cover other legacy runtimes so stay tuned. Containerization may seem foreboding, but the goal is for Cloud Buildpacks and migration resources like this to aid you in your quest to modernize your serverless apps!

Containerizing Google App Engine apps for Cloud Run

Posted by Wesley Chun (@wescpy), Developer Advocate, Google Cloud

Google App Engine header

An optional migration

Serverless Migration Station is a video mini-series from Serverless Expeditions focused on helping developers modernize their applications running on a serverless compute platform from Google Cloud. Previous episodes demonstrated how to migrate away from the older, legacy App Engine (standard environment) services to newer Google Cloud standalone equivalents like Cloud Datastore. Today's product crossover episode differs slightly from that by migrating away from App Engine altogether, containerizing those apps for Cloud Run.

There's little question the industry has been moving towards containerization as an application deployment mechanism over the past decade. However, Docker and use of containers weren't available to early App Engine developers until its flexible environment became available years later. Fast forward to today where developers have many more options to choose from, from an increasingly open Google Cloud. Google has expressed long-term support for App Engine, and users do not need to containerize their apps, so this is an optional migration. It is primarily for those who have decided to add containerization to their application deployment strategy and want to explicitly migrate to Cloud Run.

If you're thinking about app containerization, the video covers some of the key reasons why you would consider it: you're not subject to traditional serverless restrictions like development language or use of binaries (flexibility); if your code, dependencies, and container build & deploy steps haven't changed, you can recreate the same image with confidence (reproducibility); your application can be deployed elsewhere or be rolled back to a previous working image if necessary (reusable); and you have plenty more options on where to host your app (portability).

Migration and containerization

Legacy App Engine services are available through a set of proprietary, bundled APIs. As you can surmise, those services are not available on Cloud Run. So if you want to containerize your app for Cloud Run, it must be "ready to go," meaning it has migrated to either Google Cloud standalone equivalents or other third-party alternatives. For example, in a recent episode, we demonstrated how to migrate from App Engine ndb to Cloud NDB for Datastore access.

While we've recently begun to produce videos for such migrations, developers can already access code samples and codelab tutorials leading them through a variety of migrations. In today's video, we have both Python 2 and 3 sample apps that have divested from legacy services, thus ready to containerize for Cloud Run. Python 2 App Engine apps accessing Datastore are most likely to be using Cloud NDB whereas it would be Cloud Datastore for Python 3 users, so this is the starting point for this migration.

Because we're "only" switching execution platforms, there are no changes at all to the application code itself. This entire migration is completely based on changing the apps' configurations from App Engine to Cloud Run. In particular, App Engine artifacts such as app.yaml, appengine_config.py, and the lib folder are not used in Cloud Run and will be removed. A Dockerfile will be implemented to build your container. Apps with more complex configurations in their app.yaml files will likely need an equivalent service.yaml file for Cloud Run — if so, you'll find this app.yaml to service.yaml conversion tool handy. Following best practices means there'll also be a .dockerignore file.

App Engine and Cloud Functions are sourced-based where Google Cloud automatically provides a default HTTP server like gunicorn. Cloud Run is a bit more "DIY" because users have to provide a container image, meaning bundling our own server. In this case, we'll pick gunicorn explicitly, adding it to the top of the existing requirements.txt required packages file(s), as you can see in the screenshot below. Also illustrated is the Dockerfile where gunicorn is started to serve your app as the final step. The only differences for the Python 2 equivalent Dockerfile are: a) require the Cloud NDB package (google-cloud-ndb) instead of Cloud Datastore, and b) start with a Python 2 base image.

Image of The Python 3 requirements.txt and Dockerfile

The Python 3 requirements.txt and Dockerfile

Next steps

To walk developers through migrations, we always "START" with a working app then make the necessary updates that culminate in a working "FINISH" app. For this migration, the Python 2 sample app STARTs with the Module 2a code and FINISHes with the Module 4a code. Similarly, the Python 3 app STARTs with the Module 3b code and FINISHes with the Module 4b code. This way, if something goes wrong during your migration, you can always rollback to START, or compare your solution with our FINISH. If you are considering this migration for your own applications, we recommend you try it on a sample app like ours before considering it for yours. A corresponding codelab leading you step-by-step through this exercise is provided in addition to the video which you can use for guidance.

All migration modules, their videos (when published), codelab tutorials, START and FINISH code, etc., can be found in the migration repo. We hope to also one day cover other legacy runtimes like Java 8 so stay tuned. We'll continue with our journey from App Engine to Cloud Run ahead in Module 5 but will do so without explicit knowledge of containers, Docker, or Dockerfiles. Modernizing your development workflow to using containers and best practices like crafting a CI/CD pipeline isn't always straightforward; we hope content like this helps you progress in that direction!

New! Learn advanced skills for developing Android apps in Kotlin

Posted by Aleks Haecky

Advanced Android in Kotlin, developed by Google together with Udacity, is our newly-released, free, self-paced online course. In this course expert instructors from the Android team at Google will introduce you to some of the advanced features you can build into your Android apps.

This course is intended for developers who have mastered the basics of building an Android app in Kotlin, and want to dive deeper into advanced functionality. To benefit most from this course, you need skills equivalent to what's taught in our Android Fundamentals Udacity or codelab courses.

Advanced Android in Kotlin teaches you about notifications, graphics and animations on Android, using third-party authentication for login, and how to add maps to your apps. Learn how to create custom views that can look like anything you want, draw to a canvas, and have eye-catching animations. And, most importantly, you will learn how to properly test your apps!

Here is a sample of apps you will build:

  • An egg timer that implements various types of notifications.
  • A painting app that converts what the user traces on the screen into a colorful drawing.
  • Animations of the moon and a rain of falling stars.

Check out the YouTube course trailer below for additional information about the course and apps:

Different people like to learn in different ways, so we are offering this course as both a Udacity video-based course and as a series of codelabs with topics that you can explore in any order. Whether you prefer to work on your own with just the text and code, or to have an instructor help walk through the code with you on video, we’ve got you covered; just choose your path and get learning!

New! Learn advanced skills for developing Android apps in Kotlin

Posted by Aleks Haecky

Advanced Android in Kotlin, developed by Google together with Udacity, is our newly-released, free, self-paced online course. In this course expert instructors from the Android team at Google will introduce you to some of the advanced features you can build into your Android apps.

This course is intended for developers who have mastered the basics of building an Android app in Kotlin, and want to dive deeper into advanced functionality. To benefit most from this course, you need skills equivalent to what's taught in our Android Fundamentals Udacity or codelab courses.

Advanced Android in Kotlin teaches you about notifications, graphics and animations on Android, using third-party authentication for login, and how to add maps to your apps. Learn how to create custom views that can look like anything you want, draw to a canvas, and have eye-catching animations. And, most importantly, you will learn how to properly test your apps!

Here is a sample of apps you will build:

  • An egg timer that implements various types of notifications.
  • A painting app that converts what the user traces on the screen into a colorful drawing.
  • Animations of the moon and a rain of falling stars.

Check out the YouTube course trailer below for additional information about the course and apps:

Different people like to learn in different ways, so we are offering this course as both a Udacity video-based course and as a series of codelabs with topics that you can explore in any order. Whether you prefer to work on your own with just the text and code, or to have an instructor help walk through the code with you on video, we’ve got you covered; just choose your path and get learning!

International Women’s Day’19 featuring Actions on Google

Posted by Marisa Pareti, Rubi Martinez & Jessica Earley-Cha

In celebration of International Women’s Day, Women Techmakers hosted its sixth annual summit series to acknowledge and celebrate women in the tech industry, and to create a space for attendees to build community, hear from industry leaders, and learn new skills. The series featured 19 summits and 305 meetups across 87 countries.

This year, Women Techmakers partnered with the Actions on Google team to host technical workshops at these events so attendees could learn the fundamental concepts to develop Actions for the Google Assistant.Together, we created hundreds of new Actions for the Assistant. Check out some of the highlights of this year’s summit in the video below:

Technical Workshop Details

If you couldn’t attend any of our meetups this past year, we’ll cover our technical workshops now so you can start building for the Assistant from home. The technical workshop kicked off by introducing Actions on Google — the platform that enables developers to build Actions for the Google Assistant. Participants got hands-on experience building their first Action with the following features:

  • Users can start a conversation by explicitly calling the Action by name, which then responds with a greeting message.
  • Once in conversation, users are prompted to provide their favorite color. The Action parses the user’s input to extract the information it needs (namely, the color parameter).
  • If a color is provided, the Action processes the color parameter to auto-generate a “lucky number” to send back to the user and the conversation ends.
  • If no color is provided, the Action sends the user additional prompts until the parameter is extracted.
  • Users can explicitly leave the conversation at any time.

During Codelab level 1, participants learned how to parse the user’s input by using Dialogflow, a tool that uses Machine Learning and acted as their Natural Language Processor (NLP). Dialogflow processes what the user says and extracts important information from that input to identify how to fulfill the user’s request. Participants configured Dialogflow and connected it to their code’s back-end using Dialogflow’s inline editor. In the editor, participants added their code and tested their Action in the Action Simulator.

In Codelab level 2, participants continued building on their Action, adding features such as:

  • Supports deep links to directly launch the user into certain points of dialog
  • Uses utilities provided by the Actions on Google platform to fetch the user’s name and address them personally
  • Responds with follow-up questions to further the conversation
  • Presents users with a rich visual response complete with sound effects

Instead of using Dialogflow’s inline editor, participants set up a Cloud Functions for Firebase as their server.

You can learn more about developing your own Actions here. To support developers’ efforts in building great Actions for the Google Assistant, the team also has a developer community program.

Alex Eremia, a workshop attendee, reflected, “I think voice applications will have a huge impact on society both today and in the future. It will become a natural way we interact with the items around us.”

From keynotes, fireside chats, and interactive workshops, the Women Techmakers summit attendees enjoyed a mixture of technical and inspirational content. If you’re interested in learning more and getting involved, follow us WTM on twitter, check out our website and sign up to become a member.

To learn more Actions on Google and how to build for the Google Assistant, be sure to follow us on Twitter, and join our Reddit community!

Android codelab courses are here!

Posted by Jocelyn Becker, Senior Program Manager, Google Developer Training

The Google Developers Training team recently published an updated version of our Android Developer Fundamentals course as a series of Google codelabs.

Android Developer Fundamentals course landing page

Codelabs made their debut as onsite tutorials at Google I/O in 2015, and have skyrocketed in popularity as a way for developers to learn how to use Google technologies, APIs, and SDKs. A codelab is a short, self-contained tutorial that walks you through how to do a specific task. More than 2 million users have worked through Google codelabs this year.

Our Android courses were originally intended as classroom-based courses. However, we found that many people work through the courses on their own, outside of formal teaching programs. So, when we updated the Android Developer Fundamentals course, in addition to supporting classroom-based learning, we made the material available as a sequential series of codelabs.

Android Developer Fundamentals course

The updated Android Developer Fundamentals (V2) course includes lessons on using the Room database and other Architecture Components. All the apps have been updated to reflect that the Empty Activity template in Android Studio uses ConstraintLayout, and we've updated all apps to a later version of Android Studio. For more details on the differences, see the release notes.

Advanced Android course

We've also re-published the Advanced Android Developer course as a series of codelabs. This course provides step-by-step instructions for learning about more advanced topics, and adding features to your app to improve user engagement and delight. Learn how to add maps to your apps, create custom views, use SurfaceView to draw directly to the screen, and much more.

Screenshots for apps that display a customized map marker, a customized fan controller view, and an Android hiding in the dark

Teaching materials for both courses

Android logo wearing graduation cap

If you want to teach either course in the classroom, or use it as the basis of a study jam, the complete package is still available, including slide decks, source code in GitHub, and concept guides, in addition to the step-by-step codelabs.

Gmail Add-ons framework now available to all developers

Originally posted by Wesley Chun, G Suite Developer Advocate on the G Suite Blog

Email remains at the heart of how companies operate. That's why earlier this year, we previewed Gmail Add-ons—a way to help businesses speed up workflows. Since then, we've seen partners build awesome applications, and beginning today, we're extending the Gmail add-on preview to include all developers. Now anyone can start building a Gmail add-on.

Gmail Add-ons let you integrate your app into Gmail and extend Gmail to handle quick actions.

They are built using native UI context cards that can include simple text dialogs, images, links, buttons and forms. The add-on appears when relevant, and the user is just a click away from your app's rich and integrated functionality.

Gmail Add-ons are easy to create. You only have to write code once for your add-on to work on both web and mobile, and you can choose from a rich palette of widgets to craft a custom UI. Create an add-on that contextually surfaces cards based on the content of a message. Check out this video to see how we created an add-on to collate email receipts and expedite expense reporting.

Per the video, you can see that there are three components to the app's core functionality. The first component is getContextualAddOn()—this is the entry point for all Gmail Add-ons where data is compiled to build the card and render it within the Gmail UI. Since the add-on is processing expense reports from email receipts in your inbox, the createExpensesCard()parses the relevant data from the message and presents them in a form so your users can confirm or update values before submitting. Finally, submitForm()takes the data and writes a new row in an "expenses" spreadsheet in Google Sheets, which you can edit and tweak, and submit for approval to your boss.

Check out the documentation to get started with Gmail Add-ons, or if you want to see what it's like to build an add-on, go to the codelab to build ExpenseItstep-by-step. While you can't publish your add-on just yet, you can fill out this form to get notified when publishing is opened. We can't wait to see what Gmail Add-ons you build!

Start planning your Google I/O 2017 schedule!

Posted by Christopher Katsaros, Product Marketing Manager

Whether you're joining us in person or remotely, we're looking forward to connecting with you at Google I/O, on May 17-19. It's the best way to learn about building apps for the Google Assistant, how to go from Zero to App with Firebase, all of the goodies inside Android O, and much more!

Over 150 Technical Sessions, Livestreamed

The show kicks off at 10AM PDT on Wednesday, May 17 with the Google Keynote, an opportunity to hear about the latest product and platform innovations from Google, helping connect you to billions of users around the world. After that, we'll be diving into all of the ways developers can take advantage of this newness in a Developer Keynote at 1PM PDT. From there, the 14 tracks at Google I/O kickoff, with over 150 technical sessions livestreamed (i.e. all of them!) at google.com/io.

We've just published more talks on the I/O website, so you can start planning your custom schedule ahead of the conference (shhh! we've got a few more sessions up our sleeve, so don't forget to check back directly after the Developer Keynote).

You can also take advantage of Codelabs - self-paced tutorials on a number of technical topics to get you up and running with a Google product or feature. These Codelabs will be available both to those who are joining us in person at Shoreline, and online for those of you tuning in from around the world. More details will be available on the schedule soon.

Joining in person?

We received a lot of great feedback from attendees last year, and have been working hard since then to make sure this is the best Google I/O, yet. To help make it easier to attend your favorite talks and minimize lines, you'll be able to reserve seats across sessions before I/O starts. But don't worry, we're saving a few seats in each session that will be available on a first-come, first-served basis onsite. We've also increased the size of each of the tents this year, giving you more opportunities to see all of your favorite talks in-person.

Finally, we've doubled the number of Office Hours available, since you told us that being able to connect directly with Googlers to get your questions answered was extremely valuable. On top of that, all of the sandbox demo areas will be inside climate-controlled structures, making it easier to avoid the elements (but don't forget to bring your layers – Shoreline Amphitheatre is still an outdoor venue, after all).

See you in 3 weeks!

We're looking forward to seeing you in just a few weeks. We've got a few more updates to share before then; be sure to check out the Google I/O website for more details, or follow the conversation using the #io17 hashtag.