Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 3 additions & 14 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -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

Expand Down
14 changes: 2 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
81 changes: 6 additions & 75 deletions services/api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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

Expand Down
32 changes: 4 additions & 28 deletions services/web/AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
6 changes: 1 addition & 5 deletions services/web/DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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:

Expand Down
11 changes: 4 additions & 7 deletions services/web/PRODUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`).
Expand All @@ -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

Expand All @@ -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.
60 changes: 14 additions & 46 deletions services/web/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,40 +10,30 @@

- `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
```

## 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:
Expand All @@ -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
Expand All @@ -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

Expand All @@ -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
Expand All @@ -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`. `<Route>` and `<Resource>` 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.
10 changes: 5 additions & 5 deletions services/web/THEME.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
1 change: 0 additions & 1 deletion services/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": {
Expand Down
Loading