• Step-by-step: MAMP web server Configuration for Python CGI Scripts Explained on MacOS

    Step-by-step: MAMP web server Configuration for Python CGI Scripts Explained on MacOS

    Recently I was helping out a family member who is doing a degree in software engineering to get a working web server that could run Python CGI scripts. I’ve never really done this myself so I needed to work it out. What I quickly discovered is that there is a lot of ways to do this as usual, but none that were particularly simple for a beginner. What I did realise was that I would likely be best with a basic Apache server with a few modifications. In the end, for the simplicity I opted for MAMP since it’s an easy web server to set up with some basic UI.

    Note, there are ways to just install Apache locally, but I like the simplicity of MAMP for beginners.

    MAMP and Python

    To configure MAMP to run .py files (Python scripts), you’ll need to follow a few steps to set up the necessary environment for CGI (Common Gateway Interface) scripts. MAMP, by default, is configured for PHP, but you can modify it to handle Python CGI scripts as well.

    This tutorial is specifically aimed at setting up sub-project folders in MAMP’s web content root folder with Python scripts residing in a /cgi-bin subfolder.

    For anyone coming to this later, this was setup on MacOS Sequioa 15.1, with python3 and MAMP v7.1 (not Pro). The steps are slightly different for MAMP Pro since it includes features for enabling Python support directly.

    Here’s how to set it up:

    1. Create a /cgi-bin Directory

    Inside your MAMP document root (default should be Applications/MAMP/htdocs), create a new directory for your project and a subfolder called cgi-bin. This is where your Python scripts will reside. So you should have htdocs/my-project and htdocs/my-project/cgi-bin

    2. Configure Apache to Allow CGI Scripts

    • Open the MAMP application.
    • Edit the Apache configuration file:
      • You will find the Apache configuration file at MAMP/conf/apache/httpd.conf.
      • Search for <Directory "/Applications/MAMP/cgi-bin"> and make sure that the Options attribute is set to +ExecCGI and not None.
      • Add the following lines (change the project folder name to yours) below that <Directory block to enable CGI for the cgi-bin folder:
    <Directory "/Applications/MAMP/htdocs/your_project_folder/cgi-bin">
        Options +ExecCGI
        AddHandler cgi-script .py
        DirectoryIndex index.py
    </Directory>
    
    • Enable CGI Module:
      • In the httpd.conf file, make sure the CGI module is loaded. Look for the following line and ensure it’s uncommented (remove the # if present):
    LoadModule cgid_module modules/mod_cgid.so
    

    3. Configure Python

    • MAMP doesn’t include Python by default, so you’ll need to ensure Python is installed on your computer and accessible. MAMP typically uses PHP and MySQL, but Python can be used with a custom setup.
    • Ensure Python is Installed: Open a terminal and type:
    python3 --version
    

    If it’s not installed, you can install Python through python.org or use a package manager like Homebrew on macOS.

    4. Set File Permissions

    • Make sure your .py files are executable. In your terminal, navigate to the cgi-bin folder in your project and set the correct permissions:
    chmod +x your_script.py
    

    5. Write Your Python Script

    • In your cgi-bin folder, create a Python script, for example, hello.py:
    #!/usr/bin/env python3
    
    print("Content-type: text/html\n")
    print("<html><body><h1>Hello, World!</h1></body></html>")
    

    Ensure that the script has the correct shebang (#!/usr/bin/env python3) at the top, which tells the system to use Python to execute the script. To do this, in your terminal, type the following:

    which python3
    

    If this returns /usr/bin/python3 you should be fine with the line suggested earlier #!/usr/bin/env python3

    6. Restart MAMP

    • After modifying the Apache configuration, restart the MAMP server to apply the changes.

    7. Access the Script in Your Browser

    • Now you can access your Python script in a browser by visiting http://localhost:8888/your_project/cgi-bin/hello.py (again, ensuring you update the path to your actual project folder name)
    • If everything is set up correctly, you should see the output of your Python script.

    Conclusion

    Congratulations! You should now have a working MAMP web server that can run Python scripts. If you’d like to add more projects, create a new folder in the MAMP web root and update the Apache config to allow Python in that folder too.

    There are many other ways you could do this, but sometimes you just need something functional to get started. One thing I’ve learned over the years is that the hardest thing about any project is getting started. Don’t obsess over the perfect environment while you’re learning, sometimes you just need a quick solution so you can try things out.

    As you learn more, and progress in your experience, you’ll find plenty of other ways to set things up! For now, I wish you luck in your coding adventures.

  • WordPress Post Formats and Gutenberg. Is it worth it?

    Let me save you time. The answer is, it depends, but I think it’s worth it.

    I love Post Formats, even though I haven’t always used them. With the WordPress Block Editor, they initially seem totally redundant. Let me make a case for why they still work really well together.

    A primer on Post Formats

    Post Formats is a feature that was initially introduced in 2011. The general idea was to break the sea of blog posts that looked the same no matter what content they contained. At the time a post containing only a gallery, or a video, or even a quote would look the same as a post with long-form content. Or rather, they were treated the same.

    Post Formats came along as a way to mark each post with a specific type of content. From here, your theme could utilise custom features in the code, or custom styling on the front to make each type look different. An image could be styled to make that image pop. The gallery could be made to be full width of the page and really shine. The video could have a special design with a frame of some sort.

    It can be hard to tell apart content on a blog feed that is just all one post type. It can be also hard to imagine what a site with post formats can look like. Let me share an example (that also utilises the Block Editor!). A site that has always utilised them really well is Matt Mullenweg’s blog at https://ma.tt.

    Scroll down and notice that the site has posts containing long-form content, short quotes, links to other sites and videos. Each type of post is styled slightly differently and the effect is wonderful.

    Why not just Gutenberg?

    Post Formats aren’t as popular these days for a couple of reasons. Themes have been steadily dropping support for them and with the introduction of the Block Editor, you can now craft each post to look different. Create some Block Patterns and you can just drop one of those in to include the styling for each type of post content automatically.

    I think this is fantastic, but it still feels a little manual. I have to remember the Pattern each time and so on. Also, what if I change my mind and would like to change something in all posts that aren’t covered by the pattern?

    For example, I’d like to hide post titles for status updates, or quotes. This isn’t easily done with the Block Editor.

    What if I could use the Block Editor to craft my content when I want it to, but use Post Formats to style things automatically too?

    Here in lies the power of combining both Post Formats with the Block Editor.

    Why should I care?

    It’s important to understand why I’d want my blog to have all this content and not just use Instagram for images or Twitter (X?) or Mastodon for short-form updates.

    I don’t really enjoy using Social Media. I don’t like using a dedicated app, or having to log in to view content, unless it’s behind a pay wall specifically to support an author. I’ve worked really hard to be present with people where I’m at, not constantly doom-scrolling through endless app feeds.

    Still, I’d like a place I can share thoughts, share links, let me family across the world know how I’m doing and so on. My blog is that place.

    Why should I put my content anywhere else? My blog is mine. Yes, I use WordPress.com hosting, but I could move this to any other WordPress host and things would continue to work. I own this data. My Tweets (or “X” now) are really in the control of Twitter. Instagram is in control of your photos.

    I dream of an alternate reality where social media was actually just a collection of blogs where everyone had the ability to communicate between all of them. Not the current walled garden isolating people in really unclear ways. It’s a little like what is happening with the mass Twitter exodus and Mastodon. The fediverse gives you a place to put your content, but others using different fediverse platforms can still see those in their feed and leave comments etc. It’s wonderful that you don’t need a million different apps to access your different accounts.

    Using a blog is the next step. A blog has the power to take any form of content. Again, many of these fediverse services are trying to clone another service, focussed on a specific form of content. Why use Mastodon for my Twitter fix, or PixelFed for my Instagram snaps when I can post all of those on my single blog feed, marked up using Post Formats and still use tools in WordPress to share my content automatically to those social networks for greater reach?

    Because they’re marked with a format, I can then even use that to create a separate page with a feed dedicated to a specific type of content or a filter to only show my images.

    I have that choice. It just takes a little work.

    Hopefully in the near future you’ll see a little more diverse content on my site, displayed using Blocks and Post Formats to really make them shine.

    What do you think? Are Post Formats worth it? Have you seen other blogs displaying content in clever ways? I’d love to hear your thoughts.

  • Experiments in Block Art

    Experiments in Block Art

    Playing around with methods for creating art using WordPress blocks only. These experiments all work best on desktop, although seeing how they respond on mobile is quite interesting.

    Browse More
  • Implementing SASS with Webpack – Part 1

    My CSV converter project that I’ve been working on is a test-bed for learning some key development workflows such as using Pull Requests, implementing JavaScript modules and one of the most useful of those – using Webpack to bundle project files.

    When I first started the project it consisted of the following files:

    • index.html
    • style.css
    • app.js

    That was it! It was nice and simple but didn’t really do much so this was perfect. The question is, what if I was working on a far more complicated app that would benefit from splitting the files into modules, the styles into multiple files for each module and so on? I could just import every module and style file into my project – this is okay but isn’t really good in the real world aka “production”.

    You will eventually want to take all those files and optimise them into a much more compact codebase with fewer files. Why? So that your 50 individual files don’t all use 50 HTTP requests when loading the page from the server. The idea of bundling is to take every one of those files that you work on while developing and with a simple set of tools and a command to then bundle all of that for you into fewer files and therefore fewer HTTP requests.

    This just touches the tip of the iceberg since the bundling tools will also allow you to compress, minify and make various other changes such as implementing SASS or SCSS to your code and then making it production ready all in a single command.

    Maybe I’ll come back and write more about webpack another time but for now, I’m learning how to implement SASS, so in the next part of this series we will start discussing how that works.

    Interested in finding out when the next part get’s published? Why not subscribe to this blog?

  • TIL: Passing parameters to callback functions

    Today I tried to move an Event Listener callback function to it’s own module. It seemed simple enough. Take the following code example:

    app.js

    element.addEventlistener("submit", (event) => {
      event.preventDefault();
    });
    

    Now, my callback was a little more complex so it made sense to move to a module. The question then became why it didn’t work when I tried the following:

    app.js

    element.addEventListener("submit", eventHandler(event));
    

    eventHandler.js

    function eventHandler(event) {
      event.preventDefault();
    }
    

    I would get an error from app.js saying that event is not defined. After a little research I discovered on the MDN guide for addEventListener that you need to pass parameters using an anonymous function. My eventHandler() was fine – the issue was in the way I passed the parameter to the function in the callback. To fix it this was the solution:

    app.js

    // Arrow function syntax
    element.addEventListener("submit", (event) => {
      eventHandler(event);
    });
    
    // Full function syntax
    element.addEventListener("submit", function(event) {
      eventHandler(event);
    });
    

    Edit: turns out there is an even simpler approach when you’re only sending a single parameter – just don’t add the parameter to the callback function at all. This is also valid and you will still be able to access the parameter in the callback:

    element.addEventListener("submit", eventHandler);
    
  • The second is even harder

    So, I started this blog with the intention of putting thoughts and experiences of learning somewhere. The thing that I quickly realise in my learning journey is the challenge of figuring out what I don’t know.

    I have “dabbled” in development (PHP, JavaScript and a few others) over many years and learned a lot along the but much of it was never coherent knowledge. So then if I can’t figure out what I don’t know, how can I know if I’m good enough yet?

    There are only so many times you can take a beginners course or even struggle through an intermediate course while thinking “I know this stuff, but I’m not confident so I’m clearly not ready” before I lost my way a little. I’ve started and restarted courses many times but each time I come back to it I feel lost again. Then the imposter syndrome sets in and I mentally put myself in the “still learning, not ready” category.

    I have learned task runners, local development environments, loops, site migrations, database manipulations and so much else over the years that I often question if I really know as little as I think but then actually try to develop something, get overwhelmed and give up to pursue the next project that hasn’t lost me yet!

    What is different this time? I’m not alone and I have a plan. I have a mentor, friends reviewing my code, I’m planning my project out before I even begin to write any code and so I have a framework to follow. The best part? It’s working!

    I haven’t felt this confident in my learning journey in a long time. So I encourage you, if you’re struggling to progress in your learning – get a plan, collaborate on your code, find a mentor, find a friend. Get your code on Github or some other version control system and get them to comment on your code as issues or pull requests. You will feel far better and have somewhere to get your internal criticism out into the open to allow others to encourage you instead.

    Feel free to check out the current learning project I’m working on!

  • The first post is the hardest

    Why do this blog? To make myself write thoughts and process what I learn as I grow my ability as a developer. I plan to write, even if it’s small and even if someone else wrote a better post about what I learned.

    Why public? I work for Automattic – a fundamentally distributed organisation who also make incredible Open Source software. We code in the open – you can find much of our code, issues and discussions publically so, why not learn to embrace that? Maybe someone will also learn something valuable along the way. Even if they don’t, I’ll still become a better blogger!

    Edit: how could I forget – we’re pretty heavily about WordPress so why wouldn’t I blog with it?

    I have no idea what I’ll post just yet so let’s enjoy the ride together. What I do know is that I plan to write a post at least once every month to start.

    Also…this post was written using the “Introduce yourself (Example post)” posts that are on WordPress sites by default. Whoever came up with that – you are amazing.