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
8 changes: 5 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,14 @@ node_modules
.turbo

# Locally Built Stuff
.astro/
coverage
reports
dist
super-linter-output
storybook-static
dist-app
docs/dist/
reports
storybook-static
super-linter-output

# managed by holocron setup — skills
/.agents/skills/
Expand Down
5 changes: 2 additions & 3 deletions .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,11 @@ const config: StorybookConfig = {
framework: "@storybook/react-vite",
staticDirs: ["../public"],
stories: ["../src/**/*.mdx", "../src/**/*.story.@(js|jsx|mjs|ts|tsx)"],
async viteFinal(config) {
// Merge custom configuration into the default config
async viteFinal(config, { configType }) {
const { mergeConfig } = await import("vite");

return mergeConfig(config, {
// Add dependencies to pre-optimization
base: configType === "PRODUCTION" ? "/sandbox/" : "/",
optimizeDeps: {
include: ["react/jsx-dev-runtime", "react-dom/client"],
},
Expand Down
27 changes: 27 additions & 0 deletions astro.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import starlight from "@astrojs/starlight";
import { defineConfig } from "@theholocron/astro-config";
import { docsTheme } from "@theholocron/docs-theme";

export default defineConfig({
docs: {
name: "React Template",
github: "react-template",
sidebar: [
{ label: "Overview", slug: "" },
{
label: "Guide",
items: [
{ label: "Getting Started", slug: "getting-started" },
{ label: "Project Structure", slug: "structure" },
{ label: "Components", slug: "components" },
{ label: "Testing", slug: "testing" },
],
},
],
},
starlight,
docsTheme,
srcDir: "./docs/src",
outDir: "./docs/dist",
publicDir: "./docs/public",
});
3 changes: 3 additions & 0 deletions docs/src/content.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { createDocsCollections } from "@theholocron/docs-theme/content";

export const collections = createDocsCollections();
43 changes: 43 additions & 0 deletions docs/src/content/docs/components.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
---
title: Components
description: How to build and document components with this template.
---

## File conventions

Each component lives in a feature directory under `src/` with its source, story, and tests co-located:

```
src/tasks/
├── TaskList.tsx
├── TaskList.story.tsx
└── TaskList.test.tsx
```

## Writing stories

Stories use the `.story.tsx` extension and follow the [Component Story Format](https://storybook.js.org/docs/writing-stories):

```tsx
import type { Meta, StoryObj } from "@storybook/react";
import { TaskList } from "./TaskList";

const meta: Meta<typeof TaskList> = {
component: TaskList,
};

export default meta;
type Story = StoryObj<typeof TaskList>;

export const Default: Story = {
args: { tasks: [] },
};
```

## Exporting

Export components from `src/index.ts` to include them in the published library:

```ts
export { TaskList } from "./tasks/TaskList";
```
41 changes: 41 additions & 0 deletions docs/src/content/docs/getting-started.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
---
title: Getting Started
description: How to use the React template to start a new project.
---

## Use this template

Click **Use this template** on GitHub, or clone it directly:

```bash
git clone https://github.com/theholocron/react-template.git my-project
cd my-project
pnpm install
```

## Development

Start Storybook for interactive component development:

```bash
pnpm start
```

Run the smoke-test app:

```bash
pnpm dev
```

## Scripts

| Script | Description |
| --------------------- | --------------------------------------- |
| `pnpm start` | Start Storybook dev server on port 6006 |
| `pnpm dev` | Start the Vite app dev server |
| `pnpm build` | Build the component library |
| `pnpm test` | Run all tests |
| `pnpm test:storybook` | Run Storybook interaction tests |
| `pnpm test:cypress` | Open Cypress for user flow tests |
| `pnpm typecheck` | Run TypeScript type-checking |
| `pnpm lint` | Run ESLint |
29 changes: 29 additions & 0 deletions docs/src/content/docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
title: React Template
description: A modern React template with pre-configured tools, best practices, and CI/CD setup.
sidebar:
hidden: true
---

`@theholocron/react-template` is an opinionated starter for React component libraries and apps. It ships with a full development, testing, and release pipeline ready to go.

## What's included

| Tool | Purpose |
| ------------------------------------------------------- | --------------------------------------- |
| [Vite](https://vitejs.dev) | Build and dev server |
| [Storybook](https://storybook.js.org) | Component development and documentation |
| [Vitest](https://vitest.dev) | Unit and interaction tests |
| [Cypress](https://cypress.io) | End-to-end user flow tests |
| [Chromatic](https://www.chromatic.com) | Visual regression testing |
| [TypeScript](https://www.typescriptlang.org) | Type safety |
| [ESLint](https://eslint.org) | Linting |
| [Prettier](https://prettier.io) | Formatting |
| [semantic-release](https://semantic-release.gitbook.io) | Automated releases |

## Quick links

- [Getting started](./getting-started) — use this template in a new project
- [Project structure](./structure) — understand what's where
- [Components](./components) — building and documenting components
- [Testing](./testing) — the testing strategy
35 changes: 35 additions & 0 deletions docs/src/content/docs/structure.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
---
title: Project Structure
description: An overview of the files and directories in the React template.
---

```
.
├── app/ # Smoke-test app harness (main.tsx, mocks)
├── docs/ # Documentation site source
│ └── src/
│ └── content/docs/
├── public/ # Static assets served by Vite
├── src/ # Component library source
│ ├── tasks/
│ ├── login/
│ ├── inbox/
│ └── index.ts # Library entry point
├── .storybook/ # Storybook configuration
├── astro.config.ts # Docs site configuration
├── tsconfig.json # TypeScript configuration
├── vite.config.ts # Library build configuration
└── vite.app.config.ts # App harness build configuration
```

## `src/`

The component library source. Files here are bundled by `vite build` and published as the package. Each feature is a subdirectory containing components, stories, and tests co-located together.

## `app/`

A minimal React app used for smoke-testing the built library and for Cypress user flow tests. It is built separately by `vite.app.config.ts` and never published.

## `.storybook/`

Storybook configuration. Stories are discovered from `src/**/*.story.tsx`. The Storybook is deployed to `/sandbox/` on GitHub Pages.
38 changes: 38 additions & 0 deletions docs/src/content/docs/testing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
title: Testing
description: The testing strategy used in the React template.
---

The template uses three complementary testing layers.

## Unit and interaction tests (Vitest + Storybook)

Interaction tests run inside Storybook via `@storybook/addon-vitest`. They test component behaviour using Testing Library:

```bash
pnpm test:storybook
```

Unit tests run with Vitest directly:

```bash
pnpm test
```

## User flow tests (Cypress)

End-to-end tests run against the smoke-test app using Cypress:

```bash
pnpm test:cypress
```

The app is served from `app/main.tsx` and exercises the full component integration.

## Visual regression (Chromatic)

Chromatic captures and compares component screenshots on every PR. It is triggered automatically in CI via the `test` workflow.

## Coverage

Coverage is collected from Storybook interaction tests using `@storybook/addon-coverage`. The threshold is enforced in CI via Codecov.
5 changes: 5 additions & 0 deletions docs/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"extends": "@theholocron/tsconfig/astro",
"include": [".astro/types.d.ts", "../astro.config.ts", "src/**/*"],
"exclude": ["dist"]
}
2 changes: 1 addition & 1 deletion holocron.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ export default defineConfig({
},
},
{ name: "release", with: { "run-build": true } },
{ name: "deploy", with: { storybook: [{ name: "app" }] } },
{ name: "deploy", with: { docs: true, storybook: [{ name: "app" }] } },
],
providers: {
...providers,
Expand Down
35 changes: 21 additions & 14 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
"build": "vite build",
"build:storybook": "storybook build",
"dev": "vite",
"docs:build": "astro build",
"docs:dev": "astro dev",
"docs:preview": "astro preview",
"lint": "docker run -e LOG_LEVEL=DEBUG -e RUN_LOCAL=true -v .:/tmp/lint --rm ghcr.io/super-linter/super-linter:latest",
"prepare": "husky && playwright install chromium",
"prepreview": "pnpm build --config vite.app.config.ts",
Expand All @@ -42,6 +45,7 @@
"typecheck": "tsc --noEmit"
},
"devDependencies": {
"@astrojs/starlight": "^0.41.7",
"@chromatic-com/storybook": "^5.2.1",
"@commitlint/cli": "^21.2.1",
"@commitlint/config-conventional": "^21.2.0",
Expand All @@ -62,28 +66,31 @@
"@storybook/react-vite": "^10.5.6",
"@testing-library/jest-dom": "^7.0.0",
"@testing-library/react": "^16.3.0",
"@theholocron/cli": "^3.13.0",
"@theholocron/commitlint-config": "^7.14.3",
"@theholocron/eslint-config": "^7.14.3",
"@theholocron/holocron-config": "^7.14.3",
"@theholocron/holocron-plugin-github": "^3.13.0",
"@theholocron/lighthouse-config": "^7.14.3",
"@theholocron/lint-staged-config": "^7.14.3",
"@theholocron/prettier-config": "^7.14.3",
"@theholocron/semantic-release-config": "^7.14.3",
"@theholocron/astro-config": "^7.19.1",
"@theholocron/cli": "^3.24.3",
"@theholocron/commitlint-config": "^7.19.1",
"@theholocron/docs-theme": "^1.3.5",
"@theholocron/eslint-config": "^7.19.1",
"@theholocron/holocron-config": "^7.19.1",
"@theholocron/holocron-plugin-github": "^3.24.3",
"@theholocron/lighthouse-config": "^7.19.1",
"@theholocron/lint-staged-config": "^7.19.1",
"@theholocron/prettier-config": "^7.19.1",
"@theholocron/semantic-release-config": "^7.19.1",
"@theholocron/skills": "^1.3.2",
"@theholocron/storybook-config": "^7.14.3",
"@theholocron/stylelint-config": "^7.14.3",
"@theholocron/tsconfig": "^7.14.3",
"@theholocron/vite-config": "^7.14.3",
"@theholocron/vitest-config": "^7.14.4",
"@theholocron/storybook-config": "^7.19.1",
"@theholocron/stylelint-config": "^7.19.1",
"@theholocron/tsconfig": "^7.19.1",
"@theholocron/vite-config": "^7.19.1",
"@theholocron/vitest-config": "^7.19.1",
"@types/react": "^19.2.18",
"@types/react-dom": "^19.2.4",
"@vitejs/plugin-react": "^6.0.5",
"@vitest/browser": "^4.1.10",
"@vitest/coverage-v8": "^4.1.10",
"@vitest/eslint-plugin": "^1.6.26",
"alex": "^11.0.1",
"astro": "^7.2.0",
"axe-playwright": "^2.1.0",
"conventional-changelog-conventionalcommits": "^10.2.1",
"cypress": "^15.19.0",
Expand Down
Loading
Loading