-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
blog: Building Productivity Tools with marimo (#69)
- Loading branch information
Showing
8 changed files
with
98 additions
and
5 deletions.
There are no files selected for viewing
71 changes: 71 additions & 0 deletions
71
...ctivity-tools-with-marimo/2024-07-10-building-productivity-tools-with-marimo.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Binary file not shown.
Binary file not shown.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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== | ||
|
@@ -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" | ||
|
@@ -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" | ||
|
@@ -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== | ||
|
@@ -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" | ||
|