Skip to content

Architecture & Motivation

Tabulate edited this page Aug 1, 2026 · 2 revisions

Why does this exist?

As a pretty strong Linux advocate, I sometimes have people who are interested in trying it out come to me for advice on the age-old question of which distro they should use. Personally, I always end up recommending Fedora to new users. It sits in this nice sweet spot between being stable like Ubuntu but not being fully bleeding-edge like Arch, and the software is pretty up-to-date which I value a lot. However, there are a few default configuration things that I disagree with, and while I have my own static setup script, I've always wanted an extensible Fedora setup script generator to make it easier for new users to choose exactly what they want in a graphical setting. This is when I discovered fedora-things-to-do. This was a really cool project, and to be clear, I'm not trying to hate on it at all; I have a lot of respect for all the work that went into putting it all together. But after contributing to the project, I noticed that the underlying architecture creates some friction for contributors and I found myself disagreeing with a few technical design choices. Here's how my take on this project is different:

  1. Frontend Only: the original project is a streamlit app, which means every single configuration change typically sends a few network requests to the Python backend. This feels really unnecessary to me, and I felt as if the whole thing could be purely frontend, leading to a more robust and snappier experience.

  2. No Server Dependency: Leading off of point number 1, the original project relies on streamlit which is a 3rd party service. While it's not terrible since you can self-host streamlit, it feels weird to me to rely on streamlit being maintained to be able to use this app. Since my app is fully frontend, there is no server to rely on.

  3. Maintainability: Speaking on the contribution pain points of the other project, the whole thing is kind of difficult to modify and verify. It's written in fully untyped Python, and running an LSP like basedpyright gives you hundreds of errors/warnings in the main Python script, which makes it very difficult to see if you've introduced something that might cause an issue. Also, all configuration options are defined in a huge 1000+ line JSON file with no standard spec, so the Python is just blindly indexing into it and relying on a bunch of edge case checks to not crash during runtime. This isn't maintainable at all and was a primary issue that I wanted to fix with my take on the project. My implementation uses strictly-typed TypeScript, which means that creating plugins is super easy and the compiler feedback really aids with development.

  4. Continuous Deployment: I also noticed that this project had no automatic CD pipeline set up, so even when my contribution got merged in, it wasn't reflected in production. This app has a full CI/CD suite that automatically deploys whenever a new change hits master, and it's also much easier to self-host if my deployment were to ever go down.

  5. Input Validation: The last problem I had with the original project was the lack of bash/input validation. For example, the set-hostname option did not restrict the user's input to a valid hostname. If you type in a #, it will end up in the bash script as a comment and something will end up unexpected when trying to run it. While this example alone probably wouldn't cause much harm, I'm sure there are other things that lack validation that definitely could.

Architecture

Tech Stack

  • Framework: Vue.js
  • Language: TypeScript
  • Styling: TailwindCSS + DaisyUI
  • Syntax Highlighting: Shiki

Project Overview

Following is a list of important files and directories within the project. Note that it's not everything and is just a brief overview of things you may need to know when getting started with contributing.

  • src/App.vue - entrypoint
  • src/assets/*.css - DaisyUI setup + global styling overrides
  • src/components/ - main application components
  • src/components/options/ - plugin option type card components (checkbox, dropdown, etc)
  • src/composables/
    • useShiki.ts - state management for shiki syntax highlighting
    • usePlugins.ts - state management for interacting with plugin selections during runtime
      • Validation errors
      • Script downloading
      • Script uploading/URL fragment importing
      • Permalink generation
  • src/core/
    • configSerde.ts - serialization and deserialization of user configuration
    • loader.ts - defines everything related to plugin loading
    • scriptGenerator.ts - transforms plugin configs into a bash script and templates it onto script_template.sh
    • script_template.sh - script preamble/footer
  • src/plugins/ - contains all of the plugins in the application
  • public/ - static site files such as favicons

Clone this wiki locally