Skip to content

What the portal is

The brand portal is a GitHub-backed, WYSIWYG single-page site builder for client brand guides and asset libraries. Each client gets its own GitHub repository deployed on Netlify. The framework ships as five @drawnagency/* npm packages — client repos contain only content and configuration.

LayerChoiceVersion
SSR frameworkAstro (output: 'server') + Netlify adapter^6.1.4
Component / editor runtimeReact^19
StylingTailwind CSS via @tailwindcss/vite~4.1.18
Schema + validationZod^4
LanguageTypeScript^5

Astro output: 'server' means every route is server-rendered on each request — no static export. The Netlify adapter handles the Node.js function runtime and CDN caching rules.

React 19 is used for two distinct purposes: section components (rendered server-side to plain HTML for viewers) and the interactive editor shell (hydrated in the browser for editors). See Architecture for how the two paths stay separate.

Tailwind 4 via the Vite plugin (@tailwindcss/vite) replaces the PostCSS pipeline. Client repos must add @source directives in their src/styles/base.css to make Tailwind scan node_modules/@drawnagency/*/src/** — Tailwind 4 ignores node_modules by default.

Zod schemas are the single source of truth for every content type. A section’s Zod schema drives JSON validation at load time, TypeScript types (inferred via z.infer<>), and editor form generation. Adding a new section type means adding a Zod schema — there is no separate type file.

The framework is distributed as five npm packages under the @drawnagency scope. Client repos declare them as dependencies and add only their own src/content/ files and portal.config.mjs. There is no framework source in a client repo.

Package versions follow 0.1.x. Client repos pin to ^0.1.0 ranges (>=0.1.0 <0.2.0 under semver 0.x rules), so 0.2.0+ versions require an explicit range bump. Client repos use Renovate with rangeStrategy: "bump" to keep lockfiles fresh.