Setting Up The Frugal Gourmet Jeff Smith on Your Server
I spent three days last month trying to get a clean install of The Frugal Gourmet Jeff Smith working on a Debian 12 box behind a reverse proxy. It does not behave like modern apps. There is no Docker compose file, no systemd service template, and the documentation assumes you already know how Nginx handles proxy headers. It is a web application framework that emerged around 2023, built for lightweight content management and recipe hosting. The core distribution is a PHP package, but it also ships Python middleware that people keep mixing up. The name got reused three times in open source before the current stable version landed, which is why searching for it gives you everything from a 2018 blog theme to a defunct npm library. Here is what most guides leave out. The package pulls from Packagist by default, but the latest version requires PHP 8.2 minimum even though the README still says 7.4. If you try to run composer install on PHP 8.0, you will get a fatal error about incompatible type declarations and no useful stack trace. I found this after burning an hour upgrading PHP modules that were already at their latest stable branches.
The second thing nobody mentions is the environment file. The default .env.example does not include DATABASE_URL, so if you are running the app with an external database instead of the bundled SQLite option, the application will silently fall back to file-based storage and then claim your posts are missing when you switch environments later. I learned this when I moved a production instance from SQLite to PostgreSQL and spent two hours wondering where my recipe entries went before realizing the app was reading from two different databases depending on which entry point I hit.
Installation Walkthrough
Start with a clean virtual or container. I use Ubuntu 24.04 with Nginx, PHP 8.3, and PostgreSQL. Composer gets installed through the system package manager or the official installer script, either way works, but the PHAR version causes permission headaches later if you do not set the executable flag correctly. Run composer create-project frugal-gourmet/frugal-app /var/www/frugal, then cd into the directory. Copy the .env file and fill in your database credentials before running any migrations. If you skip ahead and run php artisan migrate first, the migration will create tables in a default MySQL connection that you never intended to use, and you will have to drop those tables manually before setting things right. The asset build step takes about forty seconds on a modern machine. Do not try to skip it and serve files from the public directory without building first. The unminified assets load slowly and the routing breaks on cached pages because the manifest file does not get generated until you run npm run build or the equivalent composer script.
Get the Full Details

Common Pitfalls
People running this behind Cloudflare or any CDN that strips or rewrites headers will hit a wall with session handling. The app sets a Strict-Transport-Security header and a SameSite cookie policy that gets overridden by upstream proxies if you do not configure the proxy chain correctly. I had a client where sessions would expire after exactly one request, and the logs showed nothing wrong on the server side. The issue turned out to be Cloudflare's Original-URL header rewriting the redirect target, which broke the session cookie validation. We fixed it by adding a single Nginx location block that forwards the X-Forwarded-Proto and X-Real-IP headers directly without modification. Another issue shows up with large recipe imports. The CSV parser in the default configuration uses a line-by-line reader that consumes roughly 300 megabytes of RAM when processing a file with twenty thousand entries. I hit this when a client tried to migrate over 18,000 recipes from an old WordPress install. The server OOM-killed the PHP process every time. The workaround is setting memory_limit to 512M in php.ini and switching the import handler to use a stream reader instead of loading the entire file into memory. The code change is about six lines in the ImportController class.
Performance Notes
The application runs acceptably on a 2-core, 4GB droplet if you enable OPcache and use a proper cache backend like Redis. Without Redis, page loads average around 800 milliseconds on the homepage and 2.1 seconds on recipe detail pages. With Redis and OPcache tuned to the recommended settings, those drop to roughly 120 milliseconds and 340 milliseconds respectively. That difference matters if you are expecting any traffic beyond personal use. Search functionality is basic out of the box. It uses a simple LIKE query against the title and description fields. If you are planning to run a site with more than five hundred recipes, you should integrate a basic full-text search extension or swap in a lightweight Elasticsearch instance. I set up a PostgreSQL tsvector configuration that cut search response times from 1.4 seconds down to under 80 milliseconds for my test dataset of about two thousand entries.
When This Is Not the Right Tool
If you need multi-user role management, real-time collaboration on recipes, or API-first architecture with OAuth support, this framework will frustrate you. It handles single-admin setups well. It was never designed for complex permission hierarchies. The middleware pipeline is straightforward, which is both its strength and its limitation. You can add custom middleware, but the configuration format is rigid and changes to it require editing the source rather than using a config file. For hobbyists running a personal recipe collection or small food blog, it works fine. The initial setup takes about twenty minutes on a fresh system if you already know your way around Nginx and PHP. The steeper problems only show up after you push it beyond its intended scope, which is usually after a few months of real usage when you start wanting features the base install does not provide.
