A Folder Becomes a Site
One command and every project in a folder has a URL. This chapter is about what just happened — because “it works with no configuration” is a claim worth taking apart before you rely on it.
The problem
Between a folder of code and a working local URL there are three questions, and the traditional answer to each is a file you must remember to edit.
-
What is this project called? A line
in
/etc/hosts. - Where does the server send its requests? A virtual host block.
-
What kind of project is it? Whether
the document root is the folder or
public/, whether URLs rewrite toindex.php— more config.
Three answers per project, none of them interesting, all of them yours to maintain forever.
Park: a folder of projects
grove park ~/Code
Every sub-folder is now a site.
~/Code/freddy is
http://freddy.test. Create
~/Code/invoices tomorrow and
http://invoices.test works immediately, with
nothing run and nothing edited.
That last sentence is the one to notice. The site exists because the directory exists — there is no registry to fall out of sync, no step to forget at eleven at night. Park the folder you keep your work in, once, and the question “how do I set up a local URL” stops being a question you have.
Link: one project, from inside it
cd ~/work/client-site
grove link # → client-site.test
grove link acme # → acme.test
For projects that live outside your parked folder.
grove list shows everything Grove serves,
linked and parked together.
Why DNS, and not /etc/hosts
Grove answers DNS for your whole TLD. macOS is told once,
in /etc/resolver/test, to ask Grove about
anything ending in .test, and Grove answers
127.0.0.1 for all of it.
Compared with a hosts file, that buys four things:
-
New names cost nothing. No file, no
sudo, no restart. -
Subdomains work.
api.freddy.test,tenant-one.freddy.test— multi-tenant apps and subdomain routing work locally without a hosts entry per tenant, which is impossible with the other approach. -
It is visible.
grove listandgrove doctorcan tell you what is being served and whether the resolver is in place. A hosts file is a system file that nothing in your project can see. -
It is reversible. Stop Grove and your
machine stops resolving
.test— there is no residue to clean up in six months.
Use .test and nothing else, by the way. It is
reserved by the IETF for exactly this and will never be
bought by anyone. .dev was a popular choice
until Google bought it and turned on enforced HTTPS,
which broke a great many machines in an afternoon.
How it knows what your project is
The third question — what kind of project is this — Grove answers by looking. It detects Laravel, WordPress, plain PHP, static sites and proxies, and serves each the way that kind of project expects: the right document root, the right rewrite rules.
Detection is a default, not a decree. When you are running something Grove has never seen — a Node app on a port, a container — say so:
grove proxy dashboard http://127.0.0.1:3000
Now dashboard.test is your Node app, with the
same DNS and, from the next chapter, the same trusted
certificate as everything else. This is also how a Docker
or OrbStack container becomes a proper local site.
grove list. Everything you have been
meaning to set up a local URL for has one, including the
projects you had forgotten were there.
What you learned
- Park a folder and every sub-folder is a site — the URL exists because the directory does.
- Link is for projects that live elsewhere, and both show up in
grove list. - A real resolver gives you wildcards, subdomains and reversibility that a hosts file cannot.
- Use .test. It is reserved for this; .dev was bought and broke everyone using it.
- Project type is detected, not configured — and
grove proxyis the override for anything it has not seen.