Create your first site

Create the garden blog, open it in your browser, and sign in to its admin.

Start with a running Zotonic node from your installation route. Run the commands below from the repository root, inside the container or Nix shell if you chose one.

1. Create the example site

bin/zotonic addsite -s blog -H garden.test garden
bin/zotonic status

The command creates apps_user/garden, prepares the database schema, compiles the application, and starts it on the running node. Expect garden to reach the running state. Keep the generated admin password shown in the output; you need it for the next step.

2. Give your browser the local hostname

On the computer running your browser, add this line to its hosts file using an administrator-enabled text editor:

127.0.0.1 garden.test

The file is /etc/hosts on macOS/Linux and C:\Windows\System32\drivers\etc\hosts on Windows. For containers, edit the computer's hosts file, not just the container's. Keep any existing entries. You can skip this step if your local DNS already resolves garden.test to this machine.

3. Open the site and admin

Open your garden site in the browser. These examples use the default development HTTPS port 8443; use your configured port if different. Expect the blog home page. The generated development certificate may need a local browser exception.

Open the garden admin and log in as admin, using the password printed by addsite. These are your site's credentials, separate from the status site's wwwadmin account.

4. Make your first change

Open apps_user/garden in your editor, then follow Change a template and see the result. There is no need to create a custom module first.

If the wrong site opens, check the hosts entry and priv/zotonic_site.config hostname. If creation fails, read the error and inspect the partially created directory before retrying. Native database problems can be checked with Prepare local PostgreSQL; containers use database host postgres. See addsite options for a non-default configuration.

Install initial content with a datamodel

Use a datamodel for resources that a module needs on installation. Add this declaration and callback to the mod_garden.erl from the module-creation task:

-include_lib("zotonic_core/include/zotonic.hrl").
-mod_schema(1).
-export([manage_schema/2]).

-spec manage_schema(Version, Context) -> Datamodel
    when Version :: install | {upgrade, pos_integer()},
         Context :: z:context(),
         Datamodel :: #datamodel{}.
manage_schema(install, _Context) ->
    #datamodel{
        resources = [
            {garden_welcome, text, #{
                <<"title">> => <<"Welcome to the garden">>,
                <<"is_published">> => false
            }}
        ]
    }.

Put declarations before functions and include the header only once. Compile and activate the module on a fresh local database-backed site. The module manager applies the returned datamodel; do not call the callback manually expecting it to create data. Confirm m_rsc:rid(garden_welcome, C) returns an ID and find the unpublished page in the admin.

A module already installed with a schema version needs an explicit upgrade step for later changes. Give managed resources stable names, and decide which properties editors own. Test with an edited title before applying an upgrade: returning defaults must not be treated as permission to replace editorial work.