Skip to main content
Photo of DeepakNess DeepakNess

Raw notes

Raw notes include useful resources, incomplete thoughts, ideas, micro thoughts, and learnings as I go about my day. Below, you can also subscribe to the RSS feed to stay updated:

https://deepakness.com/feed/raw.xml

Total Notes: 322


Tracking Antigravity usage

Ever since Antigravity announced revised limits, it's now important than ever to track your usage when coding. And since there is no inbuilt way to track this, I researched about it a bit and finally an IDE extension that does that.

The extension is called Antigravity Cockpit and you just have to install this in the Antigravity IDE, and it starts showing you the usage below the chat area. And you might also need to change your marketplace info for the IDE, I have written another post about that.

I also learned that in Antigravity there are different bucket groups for limits, as one person pointed out in this post:

  1. GROUP 1: Gemini 3 Pro (High), Gemini 3 Pro (Low)
  2. GROUP 2: Claude Sonnet 4.5, Claude Sonnet 4.5 (Thinking), Claude Opus 4.5 (Thinking), GPT-OSS 120B
  3. GROUP 3: Gemini 3 Flash

And it does make sense, because the Antigravity Cockpit also shows the usage as per different groups. For example, here is what it looked like for me at the time of writing this post:

Feature Group 1 Group 2 Group 3
Percentage 100.00% 78.67% 88.87.%
Reset In 5h 0m 2h 21m 3h 45m
Reset Time 01/10/2026 21:22 01/10/2026 18:43 01/10/2026 19:23
Included Models (Count) 3 4 1

Cool, right?

I tried a bunch of other IDE extensions as well, but this one seemed more polished.


Antigravity limits

I am subscribed to the Google's AI Pro plan that also gives me an enhanced limit in Antigravity IDE, but today is the first time I have hit the limit when using the Claude Opus 4.5 model extensively for ~2 hours. And after hitting the limits, the below message is shown above the chat interface:

You have reached the quota limit for Claude Opus 4.5 (Thinking). You can resume using this model at 1/9/2026, 8:34:23 PM. You can upgrade to the Google AI Ultra plan to receive the highest rate limits.

I have also read at multiple places that there's a 5-hour limit in Antigravity (at least for AI Pro subscribers) - means, even if you hit the limits, it will be restored within 5 hours, at max.

Update:

As we balance giving the best possible quotas and maintaining fairness between users, especially under incredible demand, we will be establishing generous weekly limits for all models. This will only affect a minority of Google AI Pro users. These limits do not apply to Google AI Ultra, which continues to be the best plan for power developers!

Google Antigravity account tweeted this info just today.


Adding Laravel Boost MCP to Antigravity

Laravel Boost is awesome as it makes your new projects AI-ready from the start, but the laravel-boost MCP wasn't working in Antigravity from the start. It worked in Cursor, but not in Antigravity initially... but I have finally found the fix for it.

First, here's what worked for me (I'm on macOS):

{
    "mcpServers": {
        "laravel-boost": {
            "command": "/Users/deepak/.config/herd-lite/bin/php",
            "args": [
                "/Users/deepak/Documents/laravel-test/artisan",
                "boost:mcp"
            ]
        }
    }
}

For your information, deepak is my laptop's username, and I was working in the /Documents/laravel-test folder at the time.

Please note that I installed Laravel on my device using CLI by following the steps explained on the official installation documentation page. First, installed PDF using /bin/bash -c "$(curl -fsSL https://php.new/install/mac/8.4)" command and then Laravel using composer global require laravel/installer command.

But if you have installed PHP using Homebrew, then the command inside the above MCP JSON would be probably something like /opt/homebrew/opt/php@8.4/bin/php and then it should work.

I got some ideas for getting the MCP working from this discussion, but it didn't work directly and I still had to try a bunch of different things.


Fix slow loading of Antigravity extensions

If you're trying to install any extensions on your Antigravity IDE and nothing loads for minutes when you search for the extension, here's a simple fix for that.

Navigate to Settings > Antigravity Settings > Editor and then copy-paste URLs for the followings:

Marketplace Item URL:

https://marketplace.visualstudio.com/items

Marketplace Gallery URL:

https://marketplace.visualstudio.com/_apis/public/gallery

Basically, Antigravity is a VS Code fork, but it uses OpenVSX/OpenVSCode for extensions, which is very slow and sometimes doesn't even work. However, it directly gives you the option to change marketplace item and gallery URL to the VS Code official marketplace and that fixes everything.

I didn't know this, so I had to wait for like 5 minutes to install a simple extension in the IDE, but now it's fast. And I got to know this from this article by Jimmy Song.


Organic social media marketing trick

Utilizing social media correctly for your marketing can give some serious boost to your business from the start, and I see more and more people benefit from this a lot. And it's a great thing, and probably a marketing masterclass as well.

For example, recently I saw this post from Connor, it went viral, and then one person quoted the tweet and replied exactly with an app just like that. Here I am not interested in whether they both collaborated and planned this, but interested in the concept here.

For example, you can ask someone from your circle to post something generic that has the possibility to go viral and then reply with the product you're working on. And that's it. Of course, it won't work all the time, but who says you can only try once?

Love this trick, even as a consumer.


The best advice on writing

I don't remember how I came across this article titled The Day You Became A Better Writer, but I did, and I'm glad that I did. It gives you the best advice on writing better in the simplest way possible.

The article is now deleted so I have linked to the Archive version, and I learned that it was written by Scott Adams, an American author and cartoonist. I have copied the entire piece below (I just don't want to lose it):

I went from being a bad writer to a good writer after taking a one-day course in “business writing.” I couldn’t believe how simple it was. I’ll tell you the main tricks here so you don’t have to waste a day in class.

Business writing is about clarity and persuasion. The main technique is keeping things simple. Simple writing is persuasive. A good argument in five sentences will sway more people than a brilliant argument in a hundred sentences. Don’t fight it.

Simple means getting rid of extra words. Don’t write, “He was very happy” when you can write “He was happy.” You think the word “very” adds something. It doesn’t. Prune your sentences.

Humor writing is a lot like business writing. It needs to be simple. The main difference is in the choice of words. For humor, don’t say “drink” when you can say “swill.”

Your first sentence needs to grab the reader. Go back and read my first sentence to this post. I rewrote it a dozen times. It makes you curious. That’s the key.

Write short sentences. Avoid putting multiple thoughts in one sentence. Readers aren’t as smart as you’d think.

Learn how brains organize ideas. Readers comprehend “the boy hit the ball” quicker than “the ball was hit by the boy.” Both sentences mean the same, but it’s easier to imagine the object (the boy) before the action (the hitting). All brains work that way. (Notice I didn’t say, “That is the way all brains work”?)

That’s it. You just learned 80% of the rules of good writing. You’re welcome.

I researched a bit about Scott, and discovered that nowadays he's mostly active on X (Twitter) and doesn't write much. He also does podcasts and YouTube.


How browsers work

Came across this post from Dmytro Krasun where mentioned publishing a new interactive blog post he wrote about how browsers work. By the way, it's an open-source project and here's the GitHub repo for that. The topics that explained in an interactive way are:

  • How browsers work with URLs
  • URLs turning into HTTP requests
  • Resolving server addresses
  • Establishing TCP connections
  • HTTP requests and responses
  • Parsing HTML and building the DOM tree, etc.

The website built with Next.js and Tailwind CSS and is hosted at Cloudflare Pages.

I liked the site and how it explains the concept. Also, I noticed that there's no favicon on the site, so I added one and opened a PR on GitHub for adding the site icon 😅. Now, let's see if it gets accepted.


Creating decent-looking PDFs using TailwindCSS

Came across this interesting post titled How to vibe code a PDF that talks about creating decent-looking PDFs by vibe coding, or AI-assisted coding (as I like to say). Although the post is long, here are the direct steps mentioned in the post:

1. Scaffold a basic setup with Tailwind CSS. I used Next.JS but you could also just use basic HTML.
2. Prompt the agent to use the print modifier within Tailwind CSS to build the core PDF, keeping in mind the standard 8.5 by 11 inch page size.
3. Run your dev server and load your page on localhost.
4. Use your print shortcut to preview the page.
5. Iterate as needed.
6. Download the PDF (tip: turn off the "Headers and footers" option on Chrome for a clean export).

I think, I have already done something like this one time, but it's good to keep the best practices documented for the future.


Claude Code Chrome extension does wonders

A while ago, Anthropic launched a Chrome extension for Claude Code and a lot of people are sharing how great it is. Basically, think of this as the Perplexity's Comet browser or OpenAI's Atlas browser. The extension can read webpages, click links and buttons, fill up forms, and other tasks that you ask.

For example, a user asked to make X (Twitter) into dark mode and the extension clicked through different options in settings and finally applied the dark theme.

And not just this, you can write social media posts, plan events, create Chrome extensions, chat with customer support, play chess with you, and whatnot.

I like how differently people are using the Claude Code for Chrome extension.


Guide to LLM Agent

This new post titled The Hitchhikers Guide to LLM Agent is a recent article from Saurabh who has explained different aspects of an LLM Agent in an easy-to-understand way. There is some more discussion on X about the same that can also be useful.

The article covers topics like:

  • LLM and inference
  • Context engineering
  • Memory
  • Agent evaluation
  • Subagents, etc.

The article is a good read, understandable even for a beginner like me.


Using Perplexity inside Google Sheets

I have a list of 100s of URLs that I wanted to visit and then grab specific information from those pages, but obviously it's not possible to do that manually. So I used this script that lets me use multiple AI models inside Google Sheets via OpenRouter.

Perplexity is not good at providing output in the specified format, so I just used Perplexity Sonar Pro model to grab all info I wanted in whatever format it provides, fed that info to OpenAI GPT 5.2, and then asked it generate the final output in the format I wanted, for all rows.

This setup works great, as all the info is 100% correct this way.


Localflare: Local Cloudflare development dashboard

Discovered this cool tool called Localflare, created by Rohan Prasad, that works as a dashboard for local development with Cloudflare Workers, as mentioned on the website. Basically, it gives you a dashboard that keeps showing info about:

  • D1 Databases
  • KV Namespaces
  • R2 Buckets
  • Durable Objects
  • Queues
  • Tail Logs, etc.

Not to mention, it's an open-source project and here's the GitHub repo for this. I am yet to use this, but seems like a cool idea.


How to self-host videos with HLS

My YouTube channel got deleted over a month ago, and these days I am seeing more and more channels getting deleted. Recently, I learned that Ilias Ism's channel also got deleted and the appeal got rejected as well, so he decided to self-host all videos. And the similar thing happened with Pat from StarterStory as well, and now he's also self-hosting videos.

Ilias also wrote a detailed post about his setup of self-hosting videos, and I am going to copy all the text below, in case the X post is no longer live. And it seems like too valuable information to let go.

Yeah, very similar approach! Here's what I did:
- Setup: Hetzner dedicated server (EX63, Intel Core Ultra 7, 64GB RAM, 1TB NVMe)
- Coolify, on Docker -> Nginx -> Filesystem mount to SSD
- Nginx is serving HLS streams directly from disk
- FFmpeg is transcoding to 3 quality levels (360p, 720p, 1080p)
- Also making thumbnails
- On hover there is a preview sprite looping (example: https://video.seoroast.com/i-roasted-this-slack-app-s-seo-guinea-pig/preview-sprite.jpg)
- Cloudflare in front for caching/CDN

💰 Cost: ~€80/month for the dedicated server (which also runs the main app, database, etc)

🧠 The process:
- Upload raw MP4s to server
- Batch convert to HLS with FFmpeg (adaptive bitrate)
- Nginx serves the .m3u8 playlists and .ts segments
- hls.js on the frontend for playback

It's all on the same server - no separate storage service.  The 1TB NVMe handles ~100 videos fine.

For thumbnails/sprites I generate those during conversion too.

Main win vs YouTube: No ads, full control over the player, videos load faster, and Google can't delete my channel again 😅

Ilias is encoding videos on the Hetzner server itself, so he doesn't need to keep encoding GBs of video files locally, which seems like a good idea. He converted all his 110 GB of videos to HLS.js, transcoded via FFmpeg, and then transcribed all 2,000 mins of footage with Whisper, as he mentions in this post.

But if you have a machine fast enough and don't have to transcode a lot of videos, you can also transcode your videos locally and then host them on Cloudflare R2. This method is explained in detail in this blog post.

I also found some cool blog posts on self-hosting videos that are worth-reading:

Also, I think the easiest option to self-host videos will be Cloudflare Stream service, a paid service where you can directly upload videos or via an API and then it automatically transcodes in the background. And from here you can embed the video anywhere or share as a URL.

Apart from this, Videopress by WordPress.com can be another good option, but I guess it works only with WordPress. Has a generous pricing tier though.

I also did a post about the same that might be a bit helpful.


Dual-boot Linux on Windows from an .exe file

Came across this weird project that lets you dual-boot Linux on a Windows machines, but via a .exe file. The project is called LinuxGate and here's the GitHub repo with more info on how it works. But before you try, just know that:

WARNING: This project is functional but NOT RECOMMENDED for production use.

It seems like an interesting idea, but I wouldn't try it because I'm perfectly versed with creating a bootable USB drive and then install whatever distro I want. But I guess, it should be very helpful for people who are not as tech-savvy.


Archive X (Twitter) bookmarks to Markdown

Came across this post on X and then learned about this tool called smaug that helps you archive your X (Twitter) bookmarks into Markdown files. The tool is described as:

Archive your Twitter/X bookmarks to markdown. Automatically. Like a dragon hoarding treasure, Smaug collects the valuable things you bookmark.

You need to either automatically give access to your X account, or manually copy-paste auth_token and ct0 that you get from visiting the Developer Tools → Application → Cookies in the web browser, as explained in the README.md file.

Only a few days ago, I posted about creating a tool for archiving tweets so that even if the original tweets get deleted, I still have the permanent links to use anywhere. I haven't started working on it yet, but this smaug tool will definitely give me ideas about how to approach this.


Use Antigravity via OpenCode

Found this plugin called opencode-antigravity-auth that you can use to authenticate OpenCode against Antigravity and the use models like gemini-3-pro-high and claude-opus-4-5-thinking models inside OpenCode. The plugin is described as:

Enable Opencode to authenticate against Antigravity (Google's IDE) via OAuth so you can use Antigravity rate limits and access models like gemini-3-pro-high and claude-opus-4-5-thinking with your Google credentials.

I have yet to try this, but it's great if it works. You can use the current top coding models for coding inside OpenCode.

Got to know about this from this discussion on GitHub.


MonoURL – stores text in the URL

I was going through Simon Willison's blog and came across a post that featured this GitHub repo, and I was intrigued with the simple yet brilliant idea. I used textarea.my for a bit and then decided to build a better version for personal use.

And I did create one and hosted it on a subdomain text.deepakness.com where you can try it, and you can also see the GitHub repo since it's open-source. Basically, it's a simple index.html file that contains HTML, CSS, and JavaScript and that makes everything possible.

Some of the features I created in my version are:

  1. Has light and dark mode theme options that can be switched between by using the keyboard shortcut ctrl/cmd + shift + L
  2. Spellcheck can also be toggled off or on by pressing ctrl/cmd + shift + K
  3. The note can be downloaded by pressing ctrl/cmd + S or by clicking on the download icon at the top
  4. The share URL can be copied by clicking on the copy icon at the top
  5. Saves the note locally, so just visiting the main URL loads the text that you last wrote
  6. Also shows the number of words and characters at the left-bottom side

To give you a better example, here is the note containing the entire 750+ lines of index.html file saved in the URL itself. Try opening it, the URL is too long, but it works.


DIY bird feeder camera using ESP32

Came across this cool post on X where Clayton created a DIY bird feeder by using the ESP32 camera, only for $30. It does motion detection as well as automatically classifies the birds that come in front of the camera. He must have used an ESP32 cam like this one (it contains both the camera and programming module), and then used Claude Code for writing the code, including writing the firmware as well other deployment related code.

For the case, he mentions using a scrap Airpods paper box and I think that's how these simpler DIY projects should be done. Honestly, I wouldn't be so interested in this, if he were 3D printing the case.

Clayton hasn't shared any more info about this specific project, but I am keeping an eye and will update this post if I find more info about this.

Also, I found this cool video which creates a DIY security camera using the ESP32-CAM.


Generating missing meta descriptions using AI

On deepakness.com, I had 100+ blog posts that didn't have meta descriptions because for some reason descriptions didn't come back when I migrated my site from WordPress to 11ty. It wasn't possible to manually add "description" properties in the frontmatter to all those .md files for blog posts, so I created this Python script that automatically does that.

The script checks each markdown file in the /blog folder one-by-one, if the "description" property exists, it skips them and if there's no "description" then reads the entire blog post, sends a prompt to OpenAI's GPT-5 and then creates the "description".

Here's the entire script:

#!/usr/bin/env python3
"""
Script to add descriptions to blog posts that don't have them.
Uses OpenAI GPT-5 API to generate descriptions under 140 characters.
"""

import os
import re
import requests
from pathlib import Path

# Hardcode your OpenAI API key here
OPENAI_API_KEY = "YOUR_OPENAI_API_KEY"

BLOG_DIR = Path("content/blog")
API_URL = "https://api.openai.com/v1/responses"


def get_frontmatter_and_content(file_path: Path) -> tuple[str, str, str]:
    """
    Parse a markdown file and return (frontmatter, content, full_text).
    """
    with open(file_path, "r", encoding="utf-8") as f:
        text = f.read()

    # Match frontmatter between --- delimiters
    match = re.match(r'^---\n(.*?)\n---\n(.*)$', text, re.DOTALL)
    if match:
        return match.group(1), match.group(2), text
    return "", text, text


def has_description(frontmatter: str) -> bool:
    """
    Check if frontmatter contains a description field.
    """
    # Look for description: at the start of a line
    return bool(re.search(r'^description:', frontmatter, re.MULTILINE))


def generate_description(content: str, title: str) -> str:
    """
    Use OpenAI GPT-5 to generate a description under 140 characters.
    """
    # Truncate content to avoid token limits (first 2000 chars should be enough)
    truncated_content = content[:2000]

    prompt = f"""Read the following blog post and create a brief description for it.
The description MUST be under 140 characters.
Do not use quotes around the description.
Just return the description text, nothing else.

Title: {title}

Content:
{truncated_content}"""

    headers = {
        "Content-Type": "application/json",
        "Authorization": f"Bearer {OPENAI_API_KEY}"
    }

    payload = {
        "model": "gpt-5",
        "input": prompt
    }

    try:
        response = requests.post(API_URL, headers=headers, json=payload)
        response.raise_for_status()
        data = response.json()

        # Extract the output text from response
        # The output is a list of output objects
        output = data.get("output", [])
        description = ""

        for item in output:
            if item.get("type") == "message":
                content = item.get("content", [])
                for content_item in content:
                    if content_item.get("type") == "output_text":
                        description = content_item.get("text", "").strip()
                        break
                if description:
                    break

        # Ensure it's under 140 characters
        if len(description) > 140:
            description = description[:137] + "..."

        return description
    except requests.exceptions.RequestException as e:
        print(f"  API Error: {e}")
        return ""
    except (KeyError, IndexError, TypeError) as e:
        print(f"  Parse Error: {e}")
        return ""


def get_title_from_frontmatter(frontmatter: str) -> str:
    """
    Extract title from frontmatter.
    """
    match = re.search(r'^title:\s*["\']?(.+?)["\']?\s*$', frontmatter, re.MULTILINE)
    if match:
        return match.group(1).strip('"\'')
    return "Untitled"


def add_description_to_frontmatter(frontmatter: str, description: str) -> str:
    """
    Add description field to frontmatter after the title field.
    """
    lines = frontmatter.split('\n')
    new_lines = []
    description_added = False

    for line in lines:
        new_lines.append(line)
        # Add description after title line
        if line.startswith('title:') and not description_added:
            # Escape any quotes in description
            escaped_desc = description.replace('"', '\\"')
            new_lines.append(f'description: "{escaped_desc}"')
            description_added = True

    return '\n'.join(new_lines)


def update_file(file_path: Path, frontmatter: str, content: str, new_frontmatter: str):
    """
    Write updated content back to file.
    """
    new_text = f"---\n{new_frontmatter}\n---\n{content}"
    with open(file_path, "w", encoding="utf-8") as f:
        f.write(new_text)


def main():
    if OPENAI_API_KEY == "your-openai-api-key-here":
        print("⚠️  Please set your OpenAI API key in the script!")
        print("   Edit add_descriptions.py and replace 'your-openai-api-key-here'")
        return

    # Find all blog post index.md files
    blog_posts = list(BLOG_DIR.glob("*/index.md"))

    print(f"Found {len(blog_posts)} blog posts")
    print("-" * 50)

    posts_updated = 0
    posts_skipped = 0
    posts_failed = 0

    for post_path in sorted(blog_posts):
        slug = post_path.parent.name
        print(f"\nProcessing: {slug}")

        frontmatter, content, _ = get_frontmatter_and_content(post_path)

        if has_description(frontmatter):
            print(f"  ✓ Already has description, skipping")
            posts_skipped += 1
            continue

        title = get_title_from_frontmatter(frontmatter)
        print(f"  → No description found, generating...")

        description = generate_description(content, title)

        if not description:
            print(f"  ✗ Failed to generate description")
            posts_failed += 1
            continue

        print(f"  → Generated: {description}")

        new_frontmatter = add_description_to_frontmatter(frontmatter, description)
        update_file(post_path, frontmatter, content, new_frontmatter)

        print(f"  ✓ Updated successfully")
        posts_updated += 1

    print("\n" + "=" * 50)
    print(f"Summary:")
    print(f"  Updated: {posts_updated}")
    print(f"  Skipped (already had description): {posts_skipped}")
    print(f"  Failed: {posts_failed}")


if __name__ == "__main__":
    main()

You might need to tweak the script a bit to make it work for you, and also replace YOUR_OPENAI_API_KEY with your OpenAI API key.


Cloudflare Workers free vs paid

Came across this post from Naoki Otsu that shares his story of moving only the serverless functions from from Vercel to Cloudflare and how this is super economical for him.

  • Cloudflare free plan: 100,000 requests per day
  • Cloudflare paid plan ($5/mo): 10,000,000 requests per day

And this is crazy.

I haven't ever used Cloudflare Workers, but will definitely give it a try for my next project.


macOS apps I use as an internet generalist

As an internet generalist, I use very limited apps on my Macbook Air M2, and here's the entire list of apps that are installed. I will list everything, but add links only to the uncommon ones.

Not to mention, most of these apps are completely free to use.

  1. VS Code: Mostly for taking plaintext notes, and writing posts for deepakness.com
  2. Cursor: IDE for coding, use less these days
  3. Antigravity: Google's IDE for coding, use a lot these days
  4. Google Chrome: The browser
  5. Helium browser: Mostly use this browser, best alternative for the Brave browser
  6. Brave browser: Used this as the main browser for years, feels very cluttered now, but still have this installed
  7. Handy.computer: The best offline speech-to-text app, uses local LLMs
  8. Caffeine: Menubar app to prevent your computer from sleeping
  9. AlDente: Prevent your device from charging over certain percentage
  10. Shottr: The best screenshotting tool, have also bought the license for this (unlocks some extra features)
  11. Cryptomator: For encrypting some folders with password
  12. DB Browser for SQLite: Sometimes use SQLite for simple local projects, so the app helps a lot
  13. Docker: Rarely use it, but using it for locally running a Screaming Frog alternative tool called SEOnaut
  14. Ice: For hiding too many menu bar items under a small dot
  15. Localsend: For sending files from my Macbook to Google Pixel 7, and vice versa
  16. LM Studio: For running some local LLMs, sometimes
  17. Ollama: Again for running local LLMs, but occasionally
  18. Maccy: The ultimate clipboard manager, haven't used any other, but love it
  19. NetNewsWire: The best RSS feed reader for my device
  20. OnlyOffice: The best office suite, free, and compatible with MS Office
  21. Obsidian: Used to use it a lot, now not a lot (mostly use VS Code itslef for taking notes)
  22. Screen Studio: For recording myself and my computer screen when explaining something, all my YouTube videos are recorded using this app
  23. Signal: For communicating with just one friend who uses Signal
  24. Telegram: For communicating with my colleagues, especially with Bikash
  25. Transmission: The simplest torrent client, that I only need sometimes
  26. VLC: The best video or rather the best media player
  27. Dropbox: Sometimes use it for saving things that I don't ever want deleted
  28. WhatsApp: Rarely use it, for communicating with a few people

That's it.

And hopefully I will keep updating this list in the future.


An app to clean your macOS

Came across this post on X and then discovered this cool terminal-style macOS app called Mole that deep cleans your computer. It contains all the features of CleanMyMac, AppCleaner, DaisyDisk, and iStat apps, all combined in a single binary.

JUST WOW!

It can either be installed via a curl command or via Homebrew by running the following command:

brew install tw93/tap/mole

I absolutely love it, I mean just look at the terminal text when trying to uninstall apps via this app:

$ mo uninstall

Select Apps to Remove
═══════════════════════════
▶ ☑ Adobe Creative Cloud      (9.4G) | Old
  ☐ WeChat                    (2.1G) | Recent
  ☐ Final Cut Pro             (3.8G) | Recent

Uninstalling: Adobe Creative Cloud

  ✓ Removed application
  ✓ Cleaned 52 related files across 12 locations
    - Application Support, Caches, Preferences
    - Logs, WebKit storage, Cookies
    - Extensions, Plugins, Launch daemons

====================================================================
Space freed: 12.8GB
====================================================================

By the way, the app is built using 77% shell scripts and 23% Go language. And the app is created by @HiTw93, who is from HangZhou, China.

I will definitely be using this.


Should you create a website for your mobile app?

I came across a post on X that showed Google Search Console graphs for a website that the person created for their mobile app, and now it's getting significant amount of views.

As far as I understood from reading the post and the replies, the person has a mobile app, and he created a website and a bunch of pages targeting important keywords by using the techniques of programmatic SEO. And now he's getting the benefits.