
Prerequisites
Before starting, ensure you have:- A Writer account: You don’t need an account to use Writer Framework, but you’ll need one to use the AI module. Sign up for a free account here.
- Python 3.9.2 or later: Use the installer from python.org.
- pip: This command-line application comes with Python and is used for installing Python packages, including those from Writer.
- A basic understanding of Python: You should be familiar with the basics of the language.
- Your favorite code editor (optional): There’s a code editor built into Writer for writing back-end code, but you can also use Visual Studio Code, Notepad++, Vim, Emacs, or any text editor made for programming if you prefer.
Setting up your project
Create a Writer app and get its API key
First, you’ll need to create a new app within Writer.Create the app in Writer


Copy your app's API key

Set up your computer and create the app’s project
The next step is to set up the Writer Framework environment on your computer. You’ll do this by creating a directory for the project, installing dependencies, and creating the project for the application using a template.Open your terminal application
Install the dependencies
writer
and python-dotenv
packages installed on your computer, you can skip this step.writer
and python-dotenv
packages by entering the following commands in your terminal application:pip
, the Python package installer, to install two packages:writer
, which provides some command-line commands and enables Python code to interact with Writer and the Writer Framework.python-dotenv
, which makes it easy to manage environment variables by loading them from a.env
file. This one is optional for this exercise, but you might find it useful when working on larger projects.
Set the API key environment variable
WRITER_API_KEY
.Select your operating system and terminal application below, then copy and paste the command into your terminal application, replacing [your_api_key]
with the API key you copied earlier:WRITER_API_KEY
environment variable will remain defined as long your terminal session is open (that is, until you close your terminal application’s window).Create the project
social-post-generator
using a starter template called ai-starter
so that you’re not starting “from scratch.”Build the UI
Now that you’ve created the project, it’s time to define the UI. The Writer Framework’s drag-and-drop capabilities make it easy — even if you haven’t done much UI work before! The project editor is a web application that runs on your computer and enables you to define and edit your app’s user interface. Launch it by typing the following into your terminal application:
- The canvas is in the center. It displays the app’s user interface.
- The column on the left contains:
- The Core toolkit, which contains all the UI components. You define the user interface by dragging components from the Toolkit and placing them on the canvas.
- The Component tree, which shows the arrangement of the UI components on the canvas. It’s also useful for selecting items on the canvas, especially when it has a lot of UI components.
Examine the header

@{my_app.title}
. The @{
and }
indicate that my_app.title
is a variable and that its contents should be the text displayed instead of the literal text “my_app.title”. You’ll set the value of this variable soon.Clear the Section's default title

Add a Text Input component
-
Find the Label property and set its value to
Topic for social posts and tags
. -
(Optional) Feel free to add some placeholder to the Text Input component by setting the value of the Placeholder property with something like
Enter words or phrases describing your topic
.
Add a Button component
-
Set the Text property’s value to
Generate posts
. -
Find the Icon property, and set its value to
arrow_forward
.
Add a Message component
- Scroll down to the Style section and look for the Loading property, which sets the color of the Message component when it’s loading.
- Click its CSS button, which will cause a text field to appear below it.
-
Enter this color value into the text field:
#D4FFF2
.
Add a new Section

- Find the Title property and clear it its value to remove the Section’s title.
- Scroll down to the Style section and look for the Container background property, which sets the Section’s background color.
- Click its CSS button, which will cause a text field to appear below it.
-
Enter this color value into the text field:
#F6EFFD
.
Add a Tags component

Add a Separator

Add a Text component

Add the back-end code
With the UI laid out, it’s time to work on the logic behind it. The logic behind the user interface is defined in a file namedmain.py
, which is in your project’s directory. This file was automatically generated; you’ll update the code in it to define the behavior of your app.
The simplest way to edit main.py
is within the project editor. Click on the “toggle code” button (beside the word Code) near the lower left corner of the project editor page.

main.py
.

main.py
file in your project’s directory.Import libraries and load the Writer Framework API key
WRITER_API_KEY
environment variable.Create a handler to respond to the user's input
%
at the start of the string being assigned to state["message"]
will be replaced by a “spinning circle” progress indicator graphic in the Message component.The pattern
variable in the # Generate and display hashtags
section defines a regular expression pattern to search for words that begin with the #
character. The r
in front of the opening quote specifies that the string is a raw string, which means that the \
character should be treated as a literal backslash and not as the start of an escape character sequence.Note that generate_and_display_posts_and_tags()
uses print()
functions for debugging purposes, and you can use them to get a better idea of what’s happening in the function. You’ll see their output in both your terminal application and in the project editor’s ‘log’ pane (which will be covered shortly) as you use the social post generator. This output will include:- The topic the user entered
- The posts generated by the LLM
- The hashtags generated by the LLM
print()
functions don’t affect the operation of the social post generator in any way, and you can remove them if you wish.Initialize the application
generate_and_display_posts_and_tags()
function…init_state()
method sets the initial value of state
, a dictionary containing values that define the state of the application. The key-value pairs in state
are how you store values used by your app and how you pass data between the back-end code and the UI.The code above sets the initial value of state
so that it has these key-value pairs:topic
: A string containing the topic that the application should generate social media posts and tags for. You’ll bind its value to the Text Input component where the user will enter the topic.message
: A string containing text of the message that will be displayed to the user while the application is generating posts and tags. You’ll bind its value to the Message component.tags
: A list containing the hashtags generated by the LLM. You’ll bind its value to the Tags component.posts
: A string containing the social media posts generated by the LLM. You’ll bind its value to the Text component.my_app
: A dictionary containing values that define the application’s appearance. This dictionary has a single key-value pair,title
, which defines the text that appears as the application’s title.
state
variable, see our Application state page.Save the updated code and hide the code editor

Bind the UI to the back-end code
You’ve built the UI and written the code behind it. Let’s connect the two! Go back to the browser window with the project editor and do the following:Observe that the heading at the top of the app is now 'SOCIAL POST GENERATOR'
@{my_app.title}
, a value in the app’s state
variable. You changed this value when you update the call to the Writer Framework’s init_state()
method.Bind the Text Input component to the 'state' variable's 'topic' key
state
variable key whose value will be connected to the Text Input component. Set its value to topic
.
Connect the Button component to the 'generate_and_display_posts_and_tags()' function
wf-click
property. This is where you specify the function to call when the user clicks the button — set its value to generate_and_display_posts_and_tags
.
Bind the Message component to the 'state' variable's 'message' key
@{message}
.
Bind the Tags component to the 'state' variable's 'tags' key.
- Find the Tags property, which specifies the source of the tags that the component will display.
- Click its JSON button.
-
In the text field below the JSON button, set the Tags property’s value to
@{tags}
.
Bind the Text component to the 'state' variable's 'posts' key
-
Find the Text property, which specifies the content of the Text component. Set its value to
@{posts}
. -
Set the Use Markdown property to yes.
Set the visiblity of the Section component containing the Tags and Text components based on the 'state' variable's 'posts' key
- Scroll to the Visibility property at the bottom.
- Click on the Custom button.
-
In the Visibility value field, set the value to
posts
. This will cause the Section to be visible only when thestate
variable’sposts
key has a non-empty value.
Test the application
You’ve completed all the steps to make a working social post generator, and you can try using it right now, even while editing the user interface! Enter a topic into the Topic for social posts and tags text field, then click the Generate Posts button* twice — the first time will cause the properties panel to appear, and the second click will register as a click. You’ll know that you’ve clicked the button when you see the Message component display the text “Generating social media posts and tags for you…”



print()
functions and error messages by clicking on the Log button located near the upper right corner of the page:


Run the application locally
Once you’ve tested the application, it’s time to run it locally. Switch back to your terminal application. Stop the editor with ctrl-c, then run the application by entering the following command:writer run
as opposed to writer edit
. This launches the application as your users will see it, without any of the editing tools. Even though you can preview your applications in the project editor, it’s still a good idea to test it by running it on your computer, outside the project editor, before deploying it.
You’ll be able to access the application with your browser at the URL that appears on the command line. It should look like this:

writer edit social-post-generator
, and your application, which you launched with writer run social-post-generator
, run on the same URL, but on different ports (specified by the number after the :
character at the end of the URL).