diff --git a/AGENTS.md b/AGENTS.md index acfb0889..c016d44f 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,24 +1,13 @@ # AGENTS.md — Bedrock Bedrock is an open-source, full-stack boilerplate for standing up an admin dashboard / SaaS backend: -a Node/Mongo API paired with a React admin UI, plus a schema-driven code generator. New CRUD screens -generated from a schema must look and behave identically to hand-built ones. +a Node/Mongo API paired with a React admin UI. ## Monorepo layout - **`services/api`** — Node + MongoDB API. -- **`services/web`** — React 19 admin UI (Vite, Tailwind v4, shadcn/ui). **See - [services/web/AGENTS.md](services/web/AGENTS.md) before doing any UI work** — it carries the design - system contract (PRODUCT.md + DESIGN.md + tokens) that all screens must follow. -- **`generator`** — scaffolds CRUD screens + models from a schema; its output must stay visually and - structurally consistent with hand-built `services/web` screens. - -## Conventions - -- Package manager **pnpm**; Node **>= 26**. Full stack locally via `docker compose up`. -- **Design/UI**: the visual standard lives in `services/web` — `PRODUCT.md` (who/why), `DESIGN.md` - (visual system), `THEME.md` (branding + theming), and `src/styles/globals.css` (tokens). Brand is - a single white-label knob (`--primary`, Indigo by default). Never hard-code brand colours. +- **`services/web`** — React 19 admin UI. **See [services/web/AGENTS.md](services/web/AGENTS.md) + before any UI work** — it routes to the design contract all screens must follow. ## Skills diff --git a/README.md b/README.md index 1a350c32..3c3372fe 100644 --- a/README.md +++ b/README.md @@ -53,16 +53,6 @@ share the `.pnpm` symlink farm across worktrees. It is **not enabled** here; the store above already makes worktree installs fast and cheap. It can be turned on per machine via global pnpm config if wanted, since these packages use pnpm's default `node_modules` layout. -### API Documentation +## API Documentation -Full portal with examples: - -http://localhost:2200/docs/getting-started - -Code documentation: - -[services/api](services/api) - -### Web Documentation - -[services/web](services/web) +Full portal with examples: http://localhost:2200/docs/getting-started diff --git a/services/api/README.md b/services/api/README.md index 9c667dbd..b40b1d55 100644 --- a/services/api/README.md +++ b/services/api/README.md @@ -44,13 +44,7 @@ See http://localhost:2200/docs for full documentation on this API (requires runn ## Dependencies -Ensure Node.js version uniformity using Volta: - -``` -curl -sSLf https://get.volta.sh | bash -``` - -Install dependencies: (will install correct Node.js version) +Toolchain setup (Volta, pnpm): [root README](../../README.md#package-management). Then: ``` pnpm install @@ -303,78 +297,15 @@ with `LOG_LEVEL`. In Google Cloud environments all levels are output. ## Documentation -Good API documentation needs love, so make sure to take the time to describe parameters, create examples, etc. The -[Bedrock CLI](https://github.com/bedrockio/bedrock-cli) can generate documentation using the command: - -``` -bedrock generate docs -``` - -After generation, documentation can be found and augmented in the files: +The OpenAPI definition lives in `openapi.json`, generated from the routes and their validation: ``` -services/api/src/routes/__openapi__/resource.json -services/web/src/docs/RESOURCE.md -``` - -The format in `src/routes/__openapi__` is using a slimmed down version of the OpenAPI spec to make editing easier. API -calls can be defined in the `paths` array and Object definitions can be defined in the `objects` array. - -Here's an example of an API call definition: - -```json -{ - "method": "POST", - "path": "/login", - "requestBody": [ - { - "name": "email", - "description": "E-mail address of the user trying to log in", - "required": true, - "schema": { - "type": "string", - "format": "email" - } - }, - { - "name": "password", - "description": "Password associated with the e-mail address", - "required": true, - "schema": { - "type": "string" - } - } - ], - "responseBody": [ - { - "name": "data.token", - "description": "JWT token that can be used to authenticate user", - "schema": { - "type": "string" - } - } - ], - "examples": [ - { - "name": "A new login from John Doe", - "requestBody": { - "email": "john.doe@gmail.com", - "password": "AN$.37127" - }, - "responseBody": { - "data": { - "token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1ZTZhOWMwMDBmYzY3NjQ0N2RjOTkzNmEiLCJ0eXBlIjoidXNlciIsImtpZCI6InVzZXIiLCJpYXQiOjE1ODk1NjgyODQsImV4cCI6MTU5MjE2MDI4NH0.I0DhLK9mBHCy8sJglzyLHYQHFfr34UYyCFyTaEgFFG" - } - } - } - ] -} +pnpm docs:generate ``` -All information in `src/routes/__openapi__` is exposed through the API and used by the Markdown-powered documentation -portal in `/services/web/src/docs`. - -See [../../services/web](../../services/web) for more info on customizing documentation. +Titles, summaries and descriptions can be edited in place in the docs portal, which saves them back to +`openapi.json`. Portal pages are MDX in `services/web/src/docs/pages` — see +[services/web](../web/README.md#api-documentation-portal). ## Authentication diff --git a/services/web/AGENTS.md b/services/web/AGENTS.md index 3962a4ac..822f6c98 100644 --- a/services/web/AGENTS.md +++ b/services/web/AGENTS.md @@ -18,44 +18,20 @@ it once fixes it everywhere. **[DESIGN.md](DESIGN.md) is the design contract.** Do not invent a look, and do not copy its rules into other files — apply them from there. -## What this app is - -A React admin UI for the Bedrock boilerplate: the operator-facing dashboard. Optimised first -for **end operators** doing fast, accurate CRUD, and second for **adopting developers** forking -Bedrock. Shops and Products are replaceable CRUD demos, not fixed features. - ## Stack -React 19 + Vite 6, **JavaScript/JSX — not TypeScript** (`components.json` has `tsx: false`), -Tailwind CSS v4 (CSS-first, no `tailwind.config`), shadcn/ui on Radix primitives with the source -vendored into `src/components/ui`. Package manager pnpm; Node >= 26. Full list: [README.md](README.md). +**JavaScript/JSX — not TypeScript** (`components.json` has `tsx: false`). Tailwind v4 is +CSS-first: there is no `tailwind.config`. Full list: [README.md](README.md#frameworks-used). ## Working rules - **Reuse `src/components/ui/*` first.** Don't hand-roll a button, dialog, input or table that - already exists. Adding or updating one: see [THEME.md](THEME.md#adding-components). + already exists, and don't add another component library. Adding or updating one: see + [THEME.md](THEME.md#adding-components). - **Style through tokens, never literals.** New meaning → add a token in `globals.css` first. The rest of the visual doctrine is in [DESIGN.md](DESIGN.md). - **Where code goes:** composed components in `src/components/*`, screens in `src/screens/*`, shells in `src/layouts/*`. -- **Icons:** lucide-react. Never Unicode or emoji as icons. - **Imports:** `@/*` → `src/*` (shadcn convention). Bare aliases also exist — `components/`, `screens/`, `layouts/`, `stores/`, `hooks/`, `utils/`, `helpers/`, `styles/`, `docs/`. Match the file you're editing. - -## Commands - -```bash -pnpm start # dev server → http://localhost:2200 -pnpm build # vite production build -pnpm test # vitest -pnpm lint # eslint -``` - -(Or `docker compose up` from the repo root for the full stack.) - -## Don'ts - -- Don't add raw colours, fluid `clamp()` type sizing, display fonts in UI chrome, or reach for a - modal as the first solution. -- Don't introduce a component library other than the vendored shadcn/ui + Radix. diff --git a/services/web/DESIGN.md b/services/web/DESIGN.md index ede3bed0..1ba8aa86 100644 --- a/services/web/DESIGN.md +++ b/services/web/DESIGN.md @@ -369,9 +369,7 @@ so generated and hand-built screens match. **The One Primary Rule.** Exactly one primary button per view. **The Seven States Rule.** Every interactive component defines default, hover, focus-visible, active, disabled, loading, and error; tables add skeleton-loading -and teaching empty states. **The Parity Rule.** A generator-scaffolded screen -must be visually and structurally indistinguishable from a hand-built one — same -components, same tokens. Bedrock's defining constraint. +and teaching empty states. ## Do's and Don'ts @@ -387,8 +385,6 @@ components, same tokens. Bedrock's defining constraint. mono. - **Do** give tables an uppercase header row, a clear sort affordance, density, skeletons, and teaching empty states. -- **Do** keep generated and hand-built screens on the exact same components and - tokens (Parity Rule). ### Don't: diff --git a/services/web/PRODUCT.md b/services/web/PRODUCT.md index a77902f5..d2f30c54 100644 --- a/services/web/PRODUCT.md +++ b/services/web/PRODUCT.md @@ -9,19 +9,18 @@ web Two audiences, in order of who this design work optimizes for right now: 1. **End operators (primary focus for current work)** — internal staff/admins using an app built on Bedrock day to day: working record lists, drilling into details, editing through forms and reviewing history. Their job is fast, accurate CRUD and oversight, not exploration. -2. **Adopting developers** — engineers evaluating or scaffolding a new admin dashboard/SaaS backend from this boilerplate (`services/api` + `services/web`, plus the `generator` for schema-driven CRUD scaffolding). Their first impression of the default UI shapes whether they trust and keep it. +2. **Adopting developers** — engineers evaluating or scaffolding a new admin dashboard/SaaS backend from this boilerplate (`services/api` + `services/web`). Their first impression of the default UI shapes whether they trust and keep it. ## Product Purpose -Bedrock is an open-source, full-stack boilerplate for quickly standing up an admin dashboard / SaaS backend: a Node/Mongo API (`services/api`) paired with a React admin UI (`services/web`), plus a code generator that scaffolds new CRUD screens and models from a schema. Success is twofold: developers can fork it and have a working, production-credible admin app fast, and the operators who end up using that app can do their daily admin work efficiently. +Bedrock is an open-source, full-stack boilerplate for quickly standing up an admin dashboard / SaaS backend: a Node/Mongo API (`services/api`) paired with a React admin UI (`services/web`). Success is twofold: developers can fork it and have a working, production-credible admin app fast, and the operators who end up using that app can do their daily admin work efficiently. ## Positioning -A batteries-included, code-generator-backed starter that pairs a real API with a real admin UI — not a low-code platform, not a single-purpose SaaS. The differentiator is that new CRUD screens generated from a schema are expected to look and behave identically to hand-built ones, because they share the same component/token system. +A batteries-included starter that pairs a real API with a real admin UI — not a low-code platform, not a single-purpose SaaS. ## Operating Context -- Local dev via `docker compose up` or `pnpm start`; admin dashboard served at `http://localhost:2200`. - Auth flows: login, signup, invite acceptance, forgot/reset password, lockout. - Core screens: Organizations, Users, Invites, Templates, Audit Log, Settings, Onboard, plus Shops and Products as replaceable CRUD demos. - API documentation portal generated from Markdown + OpenAPI helpers (`src/docs`). @@ -31,11 +30,10 @@ A batteries-included, code-generator-backed starter that pairs a real API with a - Stack and theming are documented where they're maintained, not restated here: [README.md](README.md) for the stack and setup, [THEME.md](THEME.md) for branding and dark mode, [DESIGN.md](DESIGN.md) for the visual system. - Brand is a single white-label knob, so visual identity stays swappable per adopter rather than baked into components. - Screens like Shops and Products are reference/example CRUD implementations meant to be adapted or replaced by adopters, not fixed product features. -- Generated screens (via the schema-driven generator) must stay visually and structurally consistent with hand-built screens. ## Brand Commitments -None fixed. "Bedrock," the neutral shadcn palette, and Geist are defaults meant to be rebranded per adopter, not a binding identity — treat brand/visual choices here as swappable, not as constraints to preserve. +None fixed. "Bedrock," the Indigo primary, and the Geist + Bricolage Grotesque fonts are defaults meant to be rebranded per adopter, not a binding identity — treat brand/visual choices here as swappable, not as constraints to preserve. ## Evidence on Hand @@ -46,5 +44,4 @@ None. No real customer content, testimonials, or case studies exist in this repo - Operator efficiency first: scanability, consistency, and native web-admin expectations outrank decorative expression (Operate mode) for the current work. - Production-credible defaults: the out-of-the-box look should read as a real, finished admin product, not a scaffold demo — it's also the first impression for adopting developers. - Rebrandable by design: visual identity stays a thin, swappable layer (one primary-color token, one swappable font stack), never hard-baked into components. -- Consistency across generated and hand-built screens: the generator's schema-driven CRUD output must match hand-built UI patterns exactly. - Accessible by default: built on Radix primitives, with no product-specific requirement established beyond that baseline. diff --git a/services/web/README.md b/services/web/README.md index 5c9fae3f..3d7dd7eb 100644 --- a/services/web/README.md +++ b/services/web/README.md @@ -10,24 +10,17 @@ - `package.json` - Configure dependencies - `vite.config.js` - Bundling and build configuration -- `.env` - Enviroment variables +- `.env` - Environment variables - `src/components` - Home of reuseable components - `src/utils` - Home of specific JS helper utilities -- `src/index.html` - Main entrypoint into App UI +- `index.html` - Main entrypoint into App UI - `serve/static.js` - Static server -- `serve/dev.js` - Static server for development -- `dist/*` - Files generated by vite, incuding index.html. These are the assets +- `dist/*` - Files generated by vite, including index.html. These are the assets that should be HTTP served ## Install Dependencies -Ensure Node.js version uniformity using Volta: - -``` -curl -sSLf https://get.volta.sh | bash -``` - -Install dependencies: (will install correct Node.js version) +Toolchain setup (Volta, pnpm): [root README](../../README.md#package-management). Then: ``` pnpm install @@ -35,15 +28,12 @@ pnpm install ## Run -The following command serves all HTML/JS/CSS and watches all changes to -`src/*.js` - ```bash -pnpm start +pnpm start # dev server with watch → http://localhost:2200 +pnpm build # vite production build +pnpm lint # eslint ``` -UI is running at [http://localhost:2200/](http://localhost:2200/) - ## Testing Tests are written using Vitest. Tests MUST follow these guidelines: @@ -65,7 +55,7 @@ All configuration is done using environment variables. The default values in `.env` can be overwritten using environment variables. - `SERVER_HOST` - Host to bind to, defaults to `"0.0.0.0"` -- `SERVER_PORT` - Port to bind to, defaults to `2300` +- `SERVER_PORT` - Port to bind to, defaults to `2200` - `SERVER_AUTH_PATH` - Basic Auth: Path to protect - `SERVER_AUTH_USER` - Basic Auth: Username - `SERVER_AUTH_PASS` - Basic Auth: Password @@ -74,9 +64,8 @@ All configuration is done using environment variables. The default values in - `API_URL` - URL for API defaults to `http://localhost:2300` - `SENTRY_DSN` - Sentry error monitoring credentials -All config vars are available in the `serve/dev.js` and `serve/static.js` -server-side code. In the browser-side all variables are available as a global -object `window.__env_conf`. +Config vars are injected into the page as `window.__ENV__` — by `vite.config.js` +in dev and `serve/middleware/env.js` in production — and read via `src/utils/env.js`. ## Frameworks Used @@ -94,7 +83,6 @@ object `window.__env_conf`. ## Other Features - Full login/signup flow with separate dashboard and homepage router -- Uses shadcn/ui (Radix UI + Tailwind CSS v4) as the UI component base - Uses ES6 style React components - Code hotswapping - Static server @@ -110,30 +98,10 @@ import { omit } from 'lodash'; ## API Documentation Portal -All API documentation is powered by Markdown. The API documentation can be -curated in `src/docs`. The menu and order of the guides can be configured in -`src/screens/Docs/index.js`. - -Markdown has some extentions that allow you to pull in information via OpenAPI: - -- `callHeading` - A method for showing a `method` + `path` summary of the API - call -- `callParams` - A summary of the request body/query parameters -- `callResponse` - A summary of the response body -- `callExamples` - A list of examples on how to use the API call -- `callSummary` - All of the above -- `objectSummary` - Show attributes for a given rich object of `name` - -For example, to generate a summary of API parameters for login, add this to the -Markdown: - -```javascript -callParams({ method: 'POST', path: '/1/auth/login' }); -``` +Guides are MDX pages in `src/docs/pages`, registered (menu and order) in +`src/docs/pages/index.js`. `` and `` from `src/docs/components` +render endpoint details from the API's OpenAPI data. ## Theming -The UI is built on [shadcn/ui](https://ui.shadcn.com/) + Tailwind CSS v4, with -all design tokens in `src/styles/globals.css`. See **[THEME.md](THEME.md)** for -how to change the brand colour, swap the font, work with dark mode and add -shadcn components — and [DESIGN.md](DESIGN.md) for the visual system itself. +See [THEME.md](THEME.md) for branding and [DESIGN.md](DESIGN.md) for the visual system. diff --git a/services/web/THEME.md b/services/web/THEME.md index 3d8446b9..5ef3e6ed 100644 --- a/services/web/THEME.md +++ b/services/web/THEME.md @@ -22,12 +22,12 @@ indicator and (optionally) the focus ring — nothing else needs to change. ## Font -The app ships [Geist](https://vercel.com/font) (bundled via -`@fontsource-variable/geist`, so it's stable across platforms). It's wired in -two places — swap both to use a different font: +The app ships [Geist](https://vercel.com/font) for UI and data, and Bricolage +Grotesque for headings, bundled via `@fontsource-variable/*` so they are stable +across platforms. Each is wired in two places — swap both to change a font: -- the imports in `src/Wrapper.js` (`@fontsource-variable/geist*`) -- the `--font-sans` / `--font-mono` tokens in `src/styles/globals.css` +- the imports in `src/Wrapper.js` (`@fontsource-variable/*`) +- the `--font-sans` / `--font-mono` / `--font-heading` tokens in `src/styles/globals.css` ## Dark mode diff --git a/services/web/package.json b/services/web/package.json index ddd92be4..15f02149 100644 --- a/services/web/package.json +++ b/services/web/package.json @@ -13,7 +13,6 @@ "static": "node ./serve/static", "lint": "eslint", "test": "vitest", - "generate": "cd ../../generator && pnpm install && pnpm generate", "postinstall": "cd serve && pnpm install" }, "dependencies": {