2026-csforca-virtual
About these apps
These apps are starter MIT App Inventor apps as presented at the 2026 Texas CSTA Regional Conference. The slides accompanying this presentation are available at https://aif.to/2026-csforca-virtual.
Apps
Projects
The What we learned sections (starter project and completed project) and the MIT App Inventor block code for the completed apps is below.
TellMeAJoke
What we learned
From the starter project in the Designer
There are typical ways to set up user-interface components in a project.
- Screen1 is set to
Title: TellMeAJoke — as are all project titles.
- Screen1 is set to
Scrollable: ☒ — so text going off the end of the screen can be scrolled.
|
From the completed project in the Designer
Visible and non-visible components can be added to Screen1.
- Added Button1 set to
Text: Tell me a joke!.
- Added Label1 set to
Width: Fill Parent... and Text: Joke....
- Added ChatBot1 (non-visible component) set with (the default)
Provider: chatgpt.
From the completed project in the Blocks
Many MIT App Inventor components use the protocol where a component procedure generates an asynchronous event — a two-step process used by ChatBot1. In this case submitting a question to ChatBot1 for a joke → whose result is displayed in Label1.
Because Chatbot1 takes some time to respond when 'thinking,' part of this protocol is to limit submissions to Chatbot1.Converse until a response is received with either Chatbot1.GotResponse or Chatbot1.ErrorOccured events.
- Add Button1.Click event to call Chatbot1.Converse with the
question parameter set to "Tell me a PG joke that I haven't heard before", to set Label1.Text to "Thinking..." (to clear any previous response and indicate that the chatbot is 'thinking'), and to set Button1.Enabled to false (to disable the button and prevent multiple queries).
- Add ChatBot1.GotResponse event to set Label1.Text to the
responseText parameter (to display the response) and set Button1.Enabled to true (to enable the button for the next query). It is vital that ButtonSubmit.Enabled is set to true in both chatbot events or the app could cease working.
- Add ChatBot1.ErrorOccured event to set Label1.Text to the
responseText parameter (to display the error) and set Button1.Enabled to true (to enable the button for the next query). It is vital that ButtonSubmit.Enabled is set to true in both chatbot events or the app could cease working.
|
Design

Code

Doodle
What we learned
From the starter project in the Designer
There are typical ways to set up user-interface components in a project.
- Screen1 is set to
Title: Doodle — as are all project titles.
- Canvas1 is set to
Width: Fill Parent... and Height: Fill Parent... to fill out the Screen1 extent.
- HorizontalArrangement1 is set to
Width: Fill Parent... for when it is made visible.
Visible components have a visible property that can be used to hide / show parts of the user interface.
- HorizontalArrangement1 is set to
Visible: ☐ rendering it invisible.
|
From the completed project in the Designer
By default, user-interface components stack vertically, so use a HorizontalArrangement to arrange added components side-by-side and Width: Fill Parent... to space evenly.
- Set HorizontalArrangement1 to
Visible: ☒ rendering it visible.
- Added ButtonClear to HorizontalArrangement1 (and named it) set to
Text: Clear.
- Added SliderWidth to HorizontalArrangement1 (and renamed it) set to
Width: Fill Parent..., MaxValue: 20, MinValue: 2, NumberOfSteps: 18, and ThumbPosition: 2.
From the completed project in the Blocks
The Canvas component has many procedures for drawing and managing the image. The thumb-position value of a Slider can change the behavior of an app.
- The Canvas1.Dragged event calls Canvas1.DrawLine with the proper parameters.
- The ButtonClear.Clicked event calls Canvas1.Clear.
- The SliderWidth.PositionChanged sets Canvas1.LineWidth to the
thumbPosition parameter value.
|
Design

Code

Map
What we learned
From the starter project in the Designer
There are typical ways to set up user-interface components in a project.
- Screen1 is set to
Title: Map — as are all project titles.
- Map1 is set to
Width: Fill Parent... and Height: Fill Parent... (to fill out the Screen1 extent), CenterFromString: 37.166,-119.449 (the geographical center of California), and ZoomLevel: 8 (to feature more of the state).
Markers (pins) can be added to Maps in Designer.
|
From the completed project in the Blocks
Markers (pins) can be added to Maps under programmatic control, but must be kept track of.
- The Map1.LongPressAtPoint event initializes the local variable pin with the result of the call to Map1.CreateMarker using the
latitude and longitude parameters.
Any Component Blocks can manage properties, handle events, and call procedures of any component with a reference — in this case to manage the infobox window display property.
- With Any Marker from the Any component drawer, use setMarker.Draggable with the value of the pin local variable as the
of component parameter and false as the to parameter — thereby fixing its position.
- With Any Marker from the Any component drawer, use setMarker.EnableInfoBox with the value of the pin local variable as the
of component parameter and true as the to parameter — thereby enabling the infobox window display (including the Title) when the user taps the Marker.
- With Any Marker from the Any component drawer within the local variable block, use setMarker.Title with the value of the pin local variable as the
of component parameter and a Text join of two values as the to parameter: - the rounded result of a call to Marker.DistanceToPoint from Any Marker in the Any component drawer with the value of the pin local variable as the
of component parameter, the value of the MarkerMcMillen.Latitude property as the latitude parameter, and the value of the MarkerMcMillen.Longitude property as the longitude parameter and; - the text
" meters to McMillen".
|
Design

Code

GoodReader
What we learned
From the starter project in the Designer
There are typical ways to set up user-interface components in a project, including using HorizontalArrangements to arrange components side-by-side and Width: Fill Parent... to space evenly. The three HorizontalArrangements each contain a label and a user-interface component to create the prompt for ChatBot1.
- Screen1 is set to
Title: GoodReader — as are all project titles.
- HorizontalArrangement1 is set to
Width: Fill Parent... and has two components within it.
- Label1 is set to
Text: Book / Part: .
- TextBoxBook is set to
Width: Fill Parent....
- HorizontalArrangement2 is set to
Width: Fill Parent... and has three components within it.
- Label2 is set to
Text: Age: .
- SliderAge is set to
Width: Fill Parent..., MaxValue: 18, MinValue: 6, NumberOfSteps: 12, and ThumbPosition: 10.
- Label2 is set to
Text: Age.
- HorizontalArrangement3 is set to
Width: Fill Parent... and has two components within it.
- Label3 is set to
Text: Type: .
- SpinnerQuestionType is set to
Width: Fill Parent... and ElementsFromString: Reading and comprehension questions,Writing prompts,Analysis questions.
To interact with a ChatBot requires configuration (ApiKey, Model, Provider) and a Label to display the response.
- LabelResponse is set to
Width: Fill Parent..., Text:.
- ChatBot1 (non-visible component) is set with an
ApiKey and Provider: gemini.
From the starter project in the Blocks
- The blocks in the Screen1.Initialize event illustrate several MIT App Inventor coding idioms, including iteration and the Any component drawer:
- Use of for each item in list from the Control drawer to iterate over each item of a list.
- Using Screen1.Initialize to initialize user-interface component properties — rather than setting them in the designer. In this case using Any Label from the Any component drawer to set the WidthPercent of Label1, Label2, and Label3 and to set the FontSize of every Label (available in Any Label from the Any component drawer).
- Set LabelAge.Text to the initial SliderAge.ThumbPosition value.

- An unconnected Chatbot1.Converse call illustrates the GoodReader prompt strategy using SpinnerQuestionType.Selection, SliderAge.ThumbPosition, and TextBoxBook.Text.

|
From the completed project in the Designer
The starter code includes components for creating a prompt for ChatBot1 — add HorizontalArrangement4 and components for interacting with ChatBot1.
- Added HorizontalArrangement4 set to
Width: Fill Parent... and has two components within it:
- Added ButtonSubmit and set to
Width: Fill Parent... and Text: Submit.
- Added ButtonNew and set to
Width: Fill Parent... and Text: New Reading.
From the completed project in the Blocks
Property modifications for every Button can also be added to Screen1.Initialize.
- Add to the Screen1.Initialize event a for each item in list block from the Control drawer to iterate over each item of the every Button list (available in Any Button from the Any component drawer) to set the FontSize and FontBold of every button.
The value of a Slider's thumb position is only visible if displayed.
- Add a SliderAge.PositionChanged event that sets LabelAge.Text to SliderAge.ThumbPosition.
The project illustrates several code techniques for smooth interactions with a generative AI ChatBot.
- Add ButtonSubmit.Click event to call Chatbot1.Converse with the prompt, to set LabelResponse.Text to
"" (to clear any previous response and indicate that the chatbot is 'thinking'), to set ButtonSubmit.Enabled to false (to disable the button and prevent multiple queries), and to set ButtonSubmit.TextColor to gray (to 'gray it out').
- Add ChatBot1.GotResponse event to set LabelResponse.Text to the
responseText parameter (to display the response), set ButtonSubmit.Enabled to true (to enable the button for the next query), and set ButtonSubmit.TextColor to black. It is vital that ButtonSubmit.Enabled is set to true in both chatbot events or the app could cease working.
- Add ChatBot1.ErrorOccured event to set LabelResponse.Text to the
responseText parameter (to display the error), set ButtonSubmit.Enabled to true (to enable the button for the next query), and set ButtonSubmit.TextColor to black. It is vital that ButtonSubmit.Enabled is set to true in both chatbot events or the app could cease working.
- Add ButtonNew.Click event to call Chatbot1.ResetConversation and to set LabelResponse.Text to
"" (to clear any previous response).
|
Design

Code

Journal
What we learned
From the starter project in the Designer
There are typical ways to set up user-interface components in a project, including using HorizontalArrangements to arrange components side-by-side and Width: Fill Parent... to space evenly.
- Screen1 is set to
Title: Journal — as are all project titles.
- HorizontalArrangement1 is set to
Width: Fill Parent... and has two components within it.
- ButtonSave is set to
Text: Save.
- TextBoxItem is set to
Width: Fill Parent....
- Label1 is set to
Width: Fill Parent... and Text: Journal....
This app include a variety of non-visible components for special functions.
- Spreadsheet1 (non-visible component) holds the journal entries and is set with ApplicationName: Journal and SpreadsheetID matching the id of the shared spreadsheet. The CredentialsJson parameter holds a Google Sheets API private-key .JSON file generated by following this step-by-step process — which includes giving
Edit access to the shared spreadsheet for the e-mail address associated with the .JSON credentials. To receive a sample private-key .JSON file, participants could fill out [this form](https://forms.gle/6chRaVweL56sYLYXA).
- Clock1 (non-visible component) has no special settings and is used only for procedures Clock1.FormatDateTime and Clock1.Now.
- ChatBot1 (non-visible component) is set with an
ApiKey and Provider: gemini.
From the starter project in the Blocks
The blocks in the JournalStarter project illustrate several MIT App Inventor coding idioms, including global variables, procedures, and selection.
:
- Initialize the global variable sheet (from the Variables from the Built-in drawer) to
"CHANGE". This is the shared worksheet within the shared Google Sheet and should be changed to suit the user.
- The Screen1.Initialize event calls Spreadsheet1.AddSheet with the value of the global variable sheet as the
sheetName parameter.
- The Spreadsheet1.ErrorOccured event uses an if-then block to filter the
errorMessage parameter on the text phrase "already exists" to trap duplicate Spreadsheet1.AddSheet attempts.
- The makeRow procedure returns a three-item list corresponding to three columns in the shared worksheet:
- A formatted date and time (
"yyyy-MM-dd HH:mm:ss")
- The text
"YOUR NAME".
- The value for the TextBoxItem.Text property.
This is the row that will be added to the shared worksheet with Spreadsheet1.AddRow.
|
From the completed project in the Blocks
Many MIT App Inventor components use the protocol where a component procedure generates an asynchronous event — a two-step process used by Spreadsheet1 and ChatBot1. In this case submitting a journal entry adds a row to Spreadsheet1 → which in turn is queried for all journal entries → then submitted to ChatBot1 for a summary → whose result is displayed in Label1.
- ButtonSave.Click event calls Spreadsheet1.AddRow with the value of
global sheet and the result of a call to makeRow as parameters.
- The Spreadsheet1.FinishedAddRow event (the result of Spreadsheet1.AddRow) calls Spreadsheet1.ReadSheet with the value of
global sheet as its sheetName parameter to read the entire worksheet.
- The Spreadsheet1.GotSheetData event (the result of Spreadsheet1.ReadSheet) calls ChatBot1.Converse with a prompt consisting of the entire worksheet, prefaced with the text
"Summarize this list of items: " as its question parameter. In addition, ButtonSaved.Enabled is set to false to disable it.
- The ChatBot1.GotResponse and ChatBot1.ErrorOccured events (the possible results of ChatBot1.Converse) both display the
responseText in Label1.Text and set ButtonSaved.Enabled to true to reenable it.
|
Design

Code
