In this tutorial, you’ll use the Writer Framework to build an application that generates social media posts and tags based on user input.

Finished social post generator application

Setting up your project

Creating a Writer app and getting your API key

From the Home screen, click on Build an app.

Writer home screen

Select Framework as the type of application you want to create so that you can generate keys and build your application using the Writer Framework

App type selection

On the next screen, you can edit your Writer application name at the top left. Under “Authenticate with an API key”, click Reveal to view and copy your API key.

Creating the application

Next, open your terminal and navigate to the directory where you want to create your application directory.


Set API key

To pass your API key to the Writer Framework, you need to set an environment variable called WRITER_API_KEY. An easy way to do this is to export the variable for your terminal session.

export WRITER_API_KEY=[key]

Create application

To create the application, run the following command:

writer create social-generator --template=ai-starter

This command will set up a new project called social-generator in the specified directory using an ai-starter template.


Edit project

To edit your project, run the below commands. This will bring up the console, where Framework-wide messages and errors will appear, including logs from the API. By default, the Writer Framework Builder is accessible at localhost:3006. If that port is in use, you can specify a different port. Open this address in your browser to view your default application setup.

writer edit social-generator

Building the UI

The Writer Framework lets you set up any layout according to your preferences with a fast drag-and-drop UI.

Input layout

To rename this application and update the Header component, open the code editor and update my_app.title in wf.init_state:

    "my_app": {
        "title": "SOCIAL POST GENERATOR"

Click the provided Section component to open its Component settings and clear out the default title.

If you’d like, you can also change the Section’s colors. Choose “Pick” under Accent color to bring up a color picker and input RGB(114,28,201). You can also input HSL or hex values by clicking on the switch currently labeled “RGB.” For the Container background, click “Pick” and input RGB(237,226,255).

Next, drag a Text Input component into the Section and label it with something like, “Topic for social posts.” Then, drag a Button component below the Text Input. You can replace the button text in the Component settings panel with “Generate posts.” In the Icon field, add “arrow_forward.”

To display loading messages, drag a Messages component below the Button. Click the component to bring up the component settings and update the Loading color to RGB(212,255,242).

Generated text layout

Next, build the layout for where the generated text will appear. Drag a new Section component inside of the current Section component below the Messages component. Delete the Title text and update the Container background color to RGB(246,239,253).

Next, drag a Tags component from the Content section of the Toolkit into the new Section.

Then, drag a Separator component below the Tags component.

Finally, drag a Text component below the button. This is where the text generated by the LLM will appear.

Initial UI layout

Updating the code

With the UI set up, you’ll next add some code to manage user input, communicate with an LLM when the user interacts with the UI, and update the application state based on the results.


Set up imports

Open your code editor. The ai-starter template already includes necessary imports from the Writer Framework and Writer AI packages:

import writer as wf

You’ll also need a regular expression library to create hashtags. Import that library at the top of your file:

import re

Initialize application state

Initialize your application state by defining key state elements. Here’s how to set up your initial state:

    "my_app": {
        "title": "SOCIAL POST GENERATOR"
    "posts": "",
    "topic": "writing",
    "message": ""

You can replace “writing” with any default topic you prefer.


Handle button click

Add a method called handle_button_click to handle interactions. This method will pass user input to the Writer AI module complete method and update the state with the results. Here’s the method implementation:

def handle_button_click(state):
    state["message"] = "% Loading up expert social media posts..."
    prompt = f"You are a social media expert. Generate 5 engaging social media posts about {state['topic']}. Include emojis."
    state["posts"] =

    prompt = f"You are a social media expert. Generate 5 hashtags about {state['topic']}, delimited by spaces. For example, #dogs #cats #ducks #elephants #badgers"
    pattern = r'#\w+'
    hashtags = re.findall(pattern,
    state["tags"] = {item: item for item in hashtags}
    state["message"] = ""

This function sets a loading message, generates social posts and hashtags using AI, and clears the message once processing is complete.

Binding to the UI components

The last task is to bind all of the state elements and the click handler to the UI.


Bind topic to text input

Click on the Text Input component to bring up the Component settings panel. In the Bindings section, type topic.

Text input settings


Set up button click event

Click on the Button component to bring up the Component settings panel. In the Events section, use the dropdown for wf-click to choose the handle_button_click handler.

Text input settings


Configure message component

Click on the Message component and set the Text to @{message}. Under Visibility, choose “Custom” and set it to message.


Bind tags to tags component

Click on the Tags component. Under General, click “JSON” for Tags and set the object to @{tags}.

Text input settings


Bind posts to text component

Click on the Text component to bring up the Component settings panel. In General Properties, bind this text box to a variable called posts by entering @{posts} in the text property field. You can also set this text box to accept Markdown input if needed by toggling the “Use Markdown” property.

Text input settings


Set visibility for section containing tags and posts

Finally, click on the Section that contains the Tags and Text components. Under Visibility, choose Custom and set it to posts.

When you save and run this code, your social media posts will generate in the text section you created earlier.

Finished social post generator application

Deploying the application

To deploy the application to the Writer cloud from your terminal, either terminate your current Writer Framework process or open a new terminal session and run the following command:

writer deploy social-generator

Once the application is deployed, the CLI will return with the URL of your live application.


That’s all it takes to set up a basic application with the Writer Framework. This setup not only demonstrates the platform’s capabilities but also provides a foundation on which you can build more complex applications. To learn more, explore the rest of the Writer Framework documentation and the API documentation.