Skip to content

Commit

Permalink
blog: Building Productivity Tools with marimo (#69)
Browse files Browse the repository at this point in the history
  • Loading branch information
Oreoxmt authored Jul 10, 2024
1 parent ec7a35c commit 6756e24
Show file tree
Hide file tree
Showing 8 changed files with 98 additions and 5 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
slug: "2024-07-10-building-productivity-tools-with-marimo"
title: "Building Productivity Tools with marimo"
summary: "Discover how marimo, an open-source Python reactive notebook, can revolutionize your workflow. This post describes the journey in creating three powerful productivity tools: a Working Day Calculator, a Holiday Announcement Parser, and an Automatic Release Scheduler."
authors: [Oreo]
tags: [Python]
---

```mdx-code-block
import ReactPlayer from 'react-player';
```

Have you ever dreamed of creating custom tools to simplify your work life? In recent weeks, I've been exploring the capabilities of [marimo](https://marimo.io), an innovative open-source Python reactive notebook. This powerful tool has enabled me to create three applications that have significantly streamlined my work planning process. In this post, I'm excited to share my journey with marimo and showcase the tools I've developed.

:::info quote

marimo is an open-source reactive notebook for Python — reproducible, git-friendly, executable as a script, and shareable as an app.

—— [marimo](https://marimo.io)

:::

<!--truncate-->

## Showcasing the tools

Let's dive into the tools I built using marimo:

- [**Working Day Calculator**](https://tool.oreo.life/workcalc/): parses official holiday announcements from the General Office of the State Council and generates data for annual public holidays and compensatory working days in China.

<ReactPlayer playing controls url='/img/workcalc-demo.mp4' />

- [**Holiday Announcement Parser**](https://tool.oreo.life/holiparse/): calculates dates before or after a specified number of working days, taking into account official public holidays and compensatory working days in China.

<ReactPlayer playing controls url='/img/holiparse-demo.mp4' />

- **Automatic Release Scheduler**: streamlines the product release process by automatically scheduling tasks based on a given release date.

<ReactPlayer playing controls url='/img/autosched-demo.mp4' />

## From idea to implementation

The journey of creating these tools was an organic process, driven by real-world needs and continuous improvement:

1. It all began with the **Automatic Release Scheduler**. Manually calculating working days in China, especially around public holidays, was a significant pain point. I wanted a tool that could take a product release date and automatically schedule tasks, accounting for these complexities.
2. During this process, I realized that calculating a date a certain number of working days before or after a given date was a fundamental need applicable to various scenarios. This led to the creation of the **Working Day Calculator** as a standalone tool.
3. Initially, I planned to manually configure annual holidays and compensatory workdays through the UI. However, I soon realized that keeping this information up-to-date would be tedious. This realization sparked the development of the **Holiday Announcement Parser**, which automatically extracts this data from official government notifications.
4. For the parser, I initially considered using an AI model but found it occasionally omitted holidays. I then explored regex but encountered limitations with capturing multiple repeated groups.
5. Finally, I refactored the **Automatic Release Scheduler** to leverage the code from the **Working Day Calculator**, showcasing the power of code reusability in marimo.

## My Experience with marimo

Here are some key takeaways from my time with marimo:

- **Version control friendly**: marimo stores notebooks as `.py` files, making them git-friendly and easy to version control.
- **Visualized dependencies**: marimo provides helpful visualizations of variables and dependencies, making code optimization and understanding a smoother process.
- **Code reusability**: marimo enables you to reuse code defined in one notebook across other notebooks or Python files. This came in handy when I refactored the Automatic Release Scheduler using the Working Day Calculator's code.
- **Data analysis capabilities**: marimo offers `marimo.ui.table` for data analysis. You can filter. But it's not a UI for display. To display a list of lists as a table, it would need to be converted to a list of dict.
- **WebAssembly support**: marimo notebooks can be run in the browser using WebAssembly. For deployment, however, Docker is currently required, which might present a hurdle for beginners. Thankfully, [Marimo Cloud](https://docs.marimo.io/guides/deploying/deploying_marimo_cloud.html) is in beta and might provide a simplified deployment process.

## Beyond the code: the importance of user experience

While the development process itself took around 15 hours, a significant amount of time was dedicated to crafting a user-friendly interface. Finding the right combination and arrangement of UI elements was crucial for a positive user experience. Inspiration for the UI layout came from the designs generated by [Claude 3.5](https://www.anthropic.com/news/claude-3-5-sonnet).

## Conclusion

I hope this blog post has given you a taste of the possibilities marimo offers for building innovative tools. If you're a Python developer looking to streamline your workflow or create custom applications, marimo is definitely worth exploring!

By leveraging marimo, I was able to create three interconnected tools that have significantly improved my work planning process. The journey from identifying a need to developing a solution was not only rewarding but also a great learning experience in terms of tool development and user interface design.

Whether you're looking to solve a specific problem in your workflow or just want to explore new ways of working with Python, I encourage you to give marimo a try.
2 changes: 1 addition & 1 deletion website/blog/tags.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Technical Writing:
TiDB Cloud:
label: 'TiDB Cloud'
description: 'Blog posts related to TiDB Cloud'
permalink: /tiDB-cloud
permalink: /tidb-cloud

Tips & Tricks:
label: 'Tips & Tricks'
Expand Down
2 changes: 1 addition & 1 deletion website/i18n/en/docusaurus-plugin-content-blog/tags.yml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Technical Writing:
TiDB Cloud:
label: 'TiDB Cloud'
description: 'Blog posts related to TiDB Cloud'
permalink: /tiDB-cloud
permalink: /tidb-cloud

Tips & Tricks:
label: 'Tips & Tricks'
Expand Down
3 changes: 2 additions & 1 deletion website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@
"clsx": "^1.2.1",
"prism-react-renderer": "^2.1.0",
"react": "^18.2.0",
"react-dom": "^18.2.0"
"react-dom": "^18.2.0",
"react-player": "^2.16.0"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^3.4.0",
Expand Down
Binary file added website/static/img/autosched-demo.mp4
Binary file not shown.
Binary file added website/static/img/holiparse-demo.mp4
Binary file not shown.
Binary file added website/static/img/workcalc-demo.mp4
Binary file not shown.
25 changes: 23 additions & 2 deletions website/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -4440,7 +4440,7 @@ deep-extend@^0.6.0:
resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac"
integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==

deepmerge@^4.2.2, deepmerge@^4.3.1:
deepmerge@^4.0.0, deepmerge@^4.2.2, deepmerge@^4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/deepmerge/-/deepmerge-4.3.1.tgz#44b5f2147cd3b00d4b56137685966f26fd25dd4a"
integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==
Expand Down Expand Up @@ -6116,6 +6116,11 @@ lines-and-columns@^1.1.6:
resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632"
integrity sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==

load-script@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/load-script/-/load-script-1.0.0.tgz#0491939e0bee5643ee494a7e3da3d2bac70c6ca4"
integrity sha512-kPEjMFtZvwL9TaZo0uZ2ml+Ye9HUMmPwbYRJ324qF9tqMejwykJ5ggTyvzmrbBeapCAbk98BSbTeovHEEP1uCA==

loader-runner@^4.2.0:
version "4.3.0"
resolved "https://registry.yarnpkg.com/loader-runner/-/loader-runner-4.3.0.tgz#c1b4a163b99f614830353b16755e7149ac2314e1"
Expand Down Expand Up @@ -6488,6 +6493,11 @@ memfs@^3.1.2, memfs@^3.4.3:
dependencies:
fs-monkey "^1.0.4"

memoize-one@^5.1.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.2.1.tgz#8337aa3c4335581839ec01c3d594090cebe8f00e"
integrity sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==

[email protected]:
version "1.0.1"
resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61"
Expand Down Expand Up @@ -7920,7 +7930,7 @@ react-error-overlay@^6.0.11:
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.11.tgz#92835de5841c5cf08ba00ddd2d677b6d17ff9adb"
integrity sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==

react-fast-compare@^3.2.0:
react-fast-compare@^3.0.1, react-fast-compare@^3.2.0:
version "3.2.2"
resolved "https://registry.yarnpkg.com/react-fast-compare/-/react-fast-compare-3.2.2.tgz#929a97a532304ce9fee4bcae44234f1ce2c21d49"
integrity sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==
Expand Down Expand Up @@ -7960,6 +7970,17 @@ react-loadable-ssr-addon-v5-slorber@^1.0.1:
dependencies:
"@types/react" "*"

react-player@^2.16.0:
version "2.16.0"
resolved "https://registry.yarnpkg.com/react-player/-/react-player-2.16.0.tgz#89070700b03f5a5ded9f0b3165d4717390796481"
integrity sha512-mAIPHfioD7yxO0GNYVFD1303QFtI3lyyQZLY229UEAp/a10cSW+hPcakg0Keq8uWJxT2OiT/4Gt+Lc9bD6bJmQ==
dependencies:
deepmerge "^4.0.0"
load-script "^1.0.0"
memoize-one "^5.1.1"
prop-types "^15.7.2"
react-fast-compare "^3.0.1"

react-router-config@^5.1.1:
version "5.1.1"
resolved "https://registry.yarnpkg.com/react-router-config/-/react-router-config-5.1.1.tgz#0f4263d1a80c6b2dc7b9c1902c9526478194a988"
Expand Down

0 comments on commit 6756e24

Please sign in to comment.