Overview

I prototyped an app using Zotero’s API and Streamlit.

https://nakamura196-zotero.streamlit.app/

This article is a memo on developing this app.

Streamlit

The following article was very helpful.

https://qiita.com/sypn/items/80962d84126be4092d3c

Zotero’s API

Zotero’s API is described at the following page.

https://www.zotero.org/support/dev/web_api/v3/start

This time, I used the following library introduced on the above page.

https://github.com/urschrei/pyzotero

To use the API, you need to obtain a personal library ID and an API key, which could be obtained by following the Quickstart steps in the README.

Below is the screen when issuing an API key.

Development with Streamlit

The source code is available at the following repository.

https://github.com/nakamura196/zotero_streamlit

Sensitive Information

It appears that sensitive information should be stored in a file called /.streamlit/secrets.toml. Don’t forget to add it to .gitignore.

[zotero]
library_id="xxx"
library_type="user"
api_key="xxx"

It could then be called as follows.

def init_zotero():
    library_id = st.secrets["zotero"]["library_id"]
    library_type = st.secrets["zotero"]["library_type"]
    api_key = st.secrets["zotero"]["api_key"]
    return zotero.Zotero(library_id, library_type, api_key)

Retrieving the Collection List from the Zotero Library

The following code was used to retrieve the collection list from the Zotero library.

def fetch_collections(zot):
    """ Retrieve collection list from Zotero library """
    collections = zot.collections()
    # Get title and key (ID) from each collection
    collection_list = [{"name": collection['data']['name'], "key": collection['data']['key']} for collection in collections]
    return collection_list

Retrieving Items Within a Collection

Items within a collection could be retrieved with the following. Processing to skip items where itemType is attachment has been added.

# Convert bibliography data to DataFrame
def create_df(zot, collection_id):
    if not collection_id:
        return pd.DataFrame()

    try:
        items = zot.collection_items(collection_id)
        rows = [{
            'title': item['data']['title'],
            "itemType": item['data']['itemType'],
            "creators": ", ".join(f"{creator['firstName']} {creator['lastName']}" for creator in item['data'].get('creators', [])),
            "date": item['data'].get('date', "")
        } for item in items if item['data']['itemType'] != "attachment"]

        return pd.DataFrame(rows)
    except Exception as e:
        st.error(f"Failed to load items from collection: {e}")
        return pd.DataFrame()

Meta Tag Configuration

Page settings such as the title could be configured as follows.

# Page configuration
st.set_page_config(
    page_title="Zotero x Streamlit",  # Title displayed in the browser title bar
    page_icon="🧊",               # Icon displayed in the browser tab
    # layout="wide",                # Set layout to wide
    # initial_sidebar_state="expanded",  # Set sidebar initial state to expanded
    menu_items={                  # Meta tag settings with additional menu options
        'Get Help': "https://github.com/nakamura196/zotero_streamlit/",
        'Report a bug': 'https://github.com/nakamura196/zotero_streamlit/issues',
        'About': "App development using [Zotero](https://www.zotero.org/)'s API and Streamlit"
    }
)

Deployment

It was easy to deploy to Streamlit Community Cloud from the “Deploy” button in the upper right of the development screen.

At that time, by adding the information written in /.streamlit/secrets.toml in the Advanced settings, sensitive information could also be used on the server.

Summary

Using Streamlit, I was able to easily create a web app.

I hope this serves as a helpful reference for using the Zotero API and more.