The site plugin convention
shipped 1.0.0cwp init scaffolds a plugin and points tracked at it.
The plugin is <project>-site by default; --plugin-slug names it otherwise.
That plugin is where your project’s own code goes.
No project code in
wp-content/themes/. Ever.
Why, precisely
WordPress has no grandchild themes. A child theme’s own updates overwrite anything written into it. A builder child theme that auto-updates from GitHub will do exactly that on a schedule you do not control.
On a Bricks site with an auto-updating child theme, custom code accumulates in two places it should never be: the child theme directory and the theme’s own code-snippet manager. Both fail the same way. Your work is one update away from being gone, and the update will not ask.
The site plugin has none of that problem. It is yours, nothing updates it, and it
is the one path cwp init puts in tracked. So it is the part of your code
that cwp deploy carries upward, alongside the tree.
What goes in it
Custom Bricks elements, registered on the init hook. Custom post types, and
those deserve a sentence of their own. Registering one in the theme means it
disappears from production the moment the theme updates. A builder page stored
against a post type that no longer registers is a page that no longer opens.
What cwp does about it
Nothing automatic, on purpose. cwp does not audit your theme directory and does not migrate anything out of it. It has no way to tell your snippet from the theme author’s. A migration that guessed wrong would move somebody else’s code into your plugin and call it done.
Read the theme directory and the snippet manager yourself, plan the move, and take a snapshot before you make it.
The one setting that makes registering a post type not enough
A post type registered in the site plugin and deployed to both sides still will
not open in the Bricks builder until it is in Bricks’ own list, and nothing
anywhere says why.
cwp bricks post-types puts it there,
and cwp doctor reports the gap per environment and points there.