Skip to content
Open
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
139 changes: 139 additions & 0 deletions .claude/skills/pr-screenshot/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
---
name: pr-screenshot
description: "Capture and attach frontend screenshots and videos to pull requests for django-react-intro. Auto-triggers when a PR changes the React frontend or its styles."
user_invocable: true
codepress_generated: true
---

# PR Screenshot — django-react-intro

Capture useful visual evidence for pull requests that change the React frontend. The repository has one frontend at `web/`, built with Create React App 1.0.10 and Yarn 1, and one public route: `/`.

## When to Trigger

Run this skill when a PR changes files under:

- `web/src/**/*.{js,jsx,css}`
- `web/public/**/*`
- `web/package.json` or `web/yarn.lock` when the dependency change affects visible UI

Do not run it for backend-only changes under `server/`, documentation-only changes, or test-only changes with no visual impact.

## What to Capture

| Changed files | What to screenshot | URL |
| --- | --- | --- |
| `web/src/containers/home/**` | Home screen and welcome content | `/` |
| `web/src/containers/App/**` or `web/src/containers/router/**` | Routed application shell | `/` |
| `web/src/index.css` or `web/src/**/*.css` | The affected page with its surrounding layout | `/` |
| `web/public/**` | Home screen using the changed public asset | `/` |

The page is public and has no authentication or API data dependency. The key ready-state selector is the heading `Welcome to React`; the page root uses `.Home` and the logo uses `.Home-logo`.

## Dev Server

### Docker capture (preferred in CodePress sessions)

The repository root `Dockerfile` is a self-contained validation image for the `web` app. It installs the pinned Yarn dependencies inside the image and starts CRA on port 3000.

```text
build_and_start_app_server(
workspaceDir=<absolute repo root>,
dockerfilePath="Dockerfile",
port=3000,
envVars={
"HOST":"0.0.0.0",
"PORT":"3000",
"BROWSER":"none",
"DANGEROUSLY_DISABLE_HOST_CHECK":"true",
"CHOKIDAR_USEPOLLING":"true"
}
)

take_app_server_screenshot(
containerId=<container id>,
path="/",
viewport={"width":1440,"height":1100},
wait_ms=1000,
full_page=false
)

stop_app_server(containerId=<container id>)
```

Assert that the screenshot contains the changed feature, not just a non-blank shell. For this app, wait for the `Welcome to React` heading or another stable selector introduced by the PR.

### Local Playwright fallback

From `web/`, install dependencies with the existing Yarn lockfile. If Playwright is not already a dev dependency, add it once and install Chromium:

```bash
cd web
yarn install --frozen-lockfile
yarn add --dev @playwright/test
yarn exec playwright install chromium
```

Create `web/e2e/playwright.config.js` temporarily when no config exists:

```js
const { defineConfig } = require('@playwright/test');

module.exports = defineConfig({
testDir: './tests',
use: { baseURL: 'http://127.0.0.1:3000' },
webServer: {
command: 'HOST=0.0.0.0 BROWSER=none DANGEROUSLY_DISABLE_HOST_CHECK=true yarn start',
port: 3000,
reuseExistingServer: true,
timeout: 60000,
},
});
```

## Capture Spec Template

Create `web/e2e/tests/_pr-screenshot.spec.js` temporarily and remove it after the run:

```js
const { test } = require('@playwright/test');

test('capture the changed home screen', async ({ page }) => {
await page.goto('/');
await page.getByRole('heading', { name: 'Welcome to React' }).waitFor({ state: 'visible' });
await page.locator('.Home').scrollIntoViewIfNeeded();
await page.screenshot({
path: '/tmp/pr-screenshots/pr-screenshot-home.png',
fullPage: false,
});
});
```

For a PR that changes an interaction, record a short video with Playwright's `video: 'on'` setting and perform the real interaction before waiting for its final-state selector. Keep captures under ten seconds and include the final state.

## Running the Spec

```bash
cd web
mkdir -p /tmp/pr-screenshots
yarn exec playwright test --config e2e/playwright.config.js e2e/tests/_pr-screenshot.spec.js --workers=1
```

Check that each screenshot is larger than 10 KB and that the changed content is visible. Capture a 390x844 viewport as well when the PR changes responsive behavior. Capture the same route against the merge-base in a detached worktree for a before/after pair when practical; if the base cannot render, keep the valid after capture and note why.

## Upload and Embed

In CodePress cloud sessions, call `upload_pr_asset` for each PNG, GIF, or WebM and embed the returned permanent URL in the PR's `## Demo` section. Use a before/after table when both captures exist, and stamp the section with the captured commit SHA.

For local fallback, upload assets to the repository's `pr-assets` GitHub release with `gh release upload`, using PR-number-prefixed filenames. Prefer a GIF plus a link to the original WebM for video evidence.

## Cleanup

Remove the temporary spec and config, delete `/tmp/pr-screenshots`, and stop any server started for the capture. Do not commit temporary Playwright specs, configs, screenshots, or videos.

## Tips

- Use viewport captures for bounded UI changes and include enough height to show the feature below the header.
- Capture `/` for any shared component, router, or global-style change because the app currently has only that route.
- No auth bypass or API mocking is needed for this repository.
- Skip screenshots for changes that cannot affect rendered output.
103 changes: 103 additions & 0 deletions .claude/skills/start-app-server/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
---
name: start-app-server
description: "Start the django-react-intro web app in a Docker container and validate it responds. Uses a pre-validated recipe with no discovery or guessing."
user_invocable: true
codepress_generated: true
---

# Start App Server — django-react-intro

Fast-path startup for the repository's Create React App frontend. Discovery was completed on 2026-08-06T21:12:43Z. The recipe is at `.codepress/start-app-server/recipe.json`.

This recipe targets the independently runnable `web/` frontend on port 3000. The repository also contains a separate legacy Django backend under `server/`, but no combined full-stack start command was present during bootstrap.

## Tools

Use these tools directly:

- `build_and_start_app_server` to build the image and start the container
- `forward_app_request` to send HTTP requests into the container
- `get_app_server_logs` to inspect startup failures
- `stop_app_server` to clean up a container

## Static Context

- **Stack**: Create React App 1.0.10, React 15.6.1, Yarn 1.22.22, Node 18
- **Dockerfile**: `Dockerfile.codepress`
- **Port**: 3000
- **Validation**: `GET /` with status in `[200, 301, 302, 404]`
- **Services**: none
- **Required secrets**: none

## Step 1: Drift Check

Compare the current inputs with the recipe checksums:

```bash
git hash-object Dockerfile.codepress
git hash-object web/package.json
```

The expected first 16 characters are `34367fcd930b90e4` and `e334e8cea064856b`. A mismatch is a warning that the recipe may need updating; continue to build and report the drift.

## Step 2: Environment

No vault secrets or companion services are required. Use these safe runtime values:

```json
{
"HOST": "0.0.0.0",
"PORT": "3000",
"BROWSER": "none",
"DANGEROUSLY_DISABLE_HOST_CHECK": "true",
"CHOKIDAR_USEPOLLING": "true"
}
```

## Step 3: Build and Start

```text
build_and_start_app_server(
workspaceDir=<absolute path to the repository root>,
port=3000,
dockerfilePath="Dockerfile.codepress",
name="web",
envVars={
"HOST":"0.0.0.0",
"PORT":"3000",
"BROWSER":"none",
"DANGEROUSLY_DISABLE_HOST_CHECK":"true",
"CHOKIDAR_USEPOLLING":"true"
}
)
```

If retrying after a fix, pass `existingContainerId` with the previous container ID so it is replaced cleanly.

## Step 4: Validate

When the tool reports `health_check: "ready"`, call:

```text
forward_app_request(containerId=<container id>, path="/", method="GET")
```

Accept status 200, 301, 302, or 404. If health times out, poll `/` for up to 12 rounds at 5-second intervals and inspect `get_app_server_logs` before diagnosing a failure. A response outside the allowed statuses, a crash, or exhausted polling is a failed start.

## Step 5: Report

Report the container ID, port 3000, the request form above, and `stop_app_server(containerId=<id>)` for cleanup. Leave a successfully started container running unless the caller is performing verification or explicitly asks for teardown.

## Known Fixes

- The tracked `.codepress/dev-server/Dockerfile.web` is a Live Dev Server image and does not contain application source or dependencies; use `Dockerfile.codepress` for standalone validation.
- The old CRA toolchain needs Node 18 and Yarn 1.22.22. Dependencies are installed during the image build.
- The server binds to `0.0.0.0`, with the browser disabled and polling enabled for containerized development.

## Repair on Failure

Read the full tool error and `get_app_server_logs` output before changing anything. Fix all identified issues together, rebuild with the previous container ID, and update the recipe checksums if the Dockerfile or `web/package.json` changes. Do not put secrets in the recipe or Dockerfile. If three prior repairs are recorded in `recipe.json`, stop and request a fresh bootstrap instead of looping.

## Cleanup

Do not stop a successful container when the user only asked to start the app. Stop failed containers and containers used solely for verification with `stop_app_server`.
Loading