The Zotonic workspace
The checkout is an Erlang umbrella project: one build contains many applications.
apps/contains Zotonic's core applications and bundled modules.apps_user/contains your sites and additional modules.apps_user/<project>/apps/can contain applications in a nested project; this path is included in the current build configuration._build/contains build output and dependencies. Do not treat it as the authoritative source directory.doc/contains versioned documentation and reference sources.bin/zotonicis the command-line entry point.
A site or external module can be its own Git repository inside apps_user. Before changing files, check which repository owns them. Add dependencies in the appropriate rebar.config, then build from the umbrella root.
What belongs in src and priv
Use src for compiled Erlang code and priv for application resources.
Put request handling in controllers, model APIs in models, template transformations in filters, rendered components in scomps, and supporting business logic in support. Directory names help readers; the Erlang module name and exported callbacks still determine behavior.
Under priv, put routes in dispatch, templates in templates, browser-ready files in lib, and their editable build sources in lib-src. Translation catalogs belong in translations.
Do not put uploaded files, caches, or local secrets in a deployable assets directory. Use the site's configured storage and configuration mechanisms. Do not edit generated CSS when its source and build command are available.
Runtime data and uploaded files
Keep runtime data separate from the application's source and static assets.
Site media, generated previews, backups, logs, and caches can live outside the checkout. Their locations depend on the running installation's configuration. Use Zotonic's storage and path APIs rather than assuming a relative directory beside a template.
For media, work through model#media and related storage facilities so metadata, preview generation, access checks, and storage backends remain coordinated. Never replace a file behind the model's back as a normal upload workflow.
When deploying, preserve the site's durable files as well as its database. Rebuilding _build is not a backup or migration strategy for uploaded content.