DICOM Anonymizer & Sender Development
Expert guidance for the dicorre project - a browser-based DICOM anonymization and sending tool for radiology workflows.
What This Skill Does
Provides Claude Code with comprehensive context for working on the dicorre repository, including:
DICOM file processing and anonymization best practicesVue.js UI development with shadcn component systemTesting strategies with Playwright (avoiding common pitfalls)Tech stack conventions and architecture patternsDevelopment workflow and toolingTech Stack
**Frontend**: Vue.js + TypeScript + Vite**DICOM Processing**: dcmjs, @umessen/dicom-deidentifier**DICOM Sending**: dicomweb-client**File Handling**: JSZip (browser-based unzipping)**UI Components**: Vue shadcn (auto-imported with `Ui` prefix, prefer explicit imports)**Styling**: Tailwind CSS 3**Testing**: Playwright (e2e)**Package Manager**: pnpmKey Instructions
1. Development Commands
```bash
pnpm install # Install dependencies
pnpm dev # Run dev server (already running on :5173)
pnpm build # Production build
pnpm test # Run tests
pnpm lint # Lint code
pnpm type-check # TypeScript checking
docker-compose up -d # Start dcm4chee test server
```
**Important**: Never try to run the dev server yourself unless explicitly asked - it's already running on port 5173.
2. UI Component Guidelines
Components located in `/aca_nuxt/layers/base/components/ui`Auto-imported with `Ui` prefix (e.g., `UiButton`)Prefer explicit imports except for small common components like buttonsComponent installation via shadcn CLI is currently broken - ask before attempting new component installs3. Styling with Tailwind
**Always use Tailwind** for stylingVariables tracked in both `tailwind.css` and `tailwind.config.js`Prefer variables in `aca_nuxt/layers/base/assets/css/tailwind.css` (especially colors)Common colors: `primary-light-gray`, `secondary-gray`, `primary-dark-gray` (with `/50` for 50% opacity)**Scoped CSS**: Only use in Vue components when Tailwind isn't sufficient (e.g., grids with named slots, tables where `@apply` saves duplicates)4. DICOM Anonymization
**Critical**: The `@umessen/dicom-deidentifier` library expects raw `Uint8Array` data, NOT parsed dcmjs datasets.
```typescript
// ✅ CORRECT
const anonymized = await deidentifier.deidentify(new Uint8Array(arrayBuffer))
// ❌ WRONG
const dataset = dcmjs.data.DicomMessage.readFile(arrayBuffer)
const anonymized = await deidentifier.deidentify(dataset) // Will fail
```
**Test files**: Use `/test-data/CASES/Caso1.zip` (contains valid DICOM files with proper headers)
5. Playwright Testing Best Practices
#### NEVER USE TIMEOUTS
Avoid `waitForTimeout()` or hardcoded delaysUse Playwright tools: `{ waitUntil: 'networkIdle' }` or wait for expected UI stateMonitor console with `browser_console_messages()` for debugging#### File Upload Testing Pattern
File uploads require clicking the label element (not the input) to trigger the browser's file chooser:
```typescript
// 1. Click "Browse Files" label to open file chooser
await page.getByText('Browse Files').click()
// 2. Wait for file chooser modal state: "[File chooser]"
// 3. Upload file
await fileChooser.setFiles(['/path/to/test/file.zip'])
```
6. Scripts for Data Examination
Write scripts in Python or TypeScript when examining data (e.g., DICOM files)Examples in `/scripts` folder**Python**: Use `uv` to run with requirements in header**Cleanup**: Delete temporary scripts, keep useful ones for reference7. Documentation References
Always refer to official documentation:
**Vue.js**: https://vuejs.org/llms.txt**Effect**: https://effect.website/llms.txt**Shadcn-vue**: https://www.shadcn-vue.com/llms.txt8. Package Management
Always use `pnpm` instead of `npm`Project Architecture
Plugin Architecture
Format converters use plugin systemProject-based configurations for sharing with contributorsClient-Side Processing
All DICOM processing happens in the browserNo server-side file handling for privacy/securityDICOMweb-based sending to radiology destinationsCommon Workflows
Adding a New Anonymization Profile
1. Use `@umessen/dicom-deidentifier` standard profiles (TypeScript-friendly)
2. Pass raw `Uint8Array` data, not parsed datasets
3. Test with files from `/test-data/CASES/Caso1.zip`
Testing File Upload Flows
1. Write Playwright test
2. Click label element (not input) to trigger file chooser
3. Wait for `[File chooser]` modal state
4. Use `setFiles()` to upload test data
5. Monitor console messages for errors
Styling New Components
1. Check if shadcn-vue component exists in `/aca_nuxt/layers/base/components/ui`
2. Use Tailwind utility classes with project color variables
3. Only add scoped CSS when Tailwind isn't sufficient
4. Test responsive behavior
Constraints
Never attempt component installation via shadcn CLI (currently broken)Never run dev server unless explicitly requested (already running)Always use pnpm, never npmAlways pass raw `Uint8Array` to deidentifier (not parsed datasets)Never use hardcoded timeouts in Playwright testsExample Usage
**Scenario 1**: "Add a new anonymization profile for pediatric cases"
Read `@umessen/dicom-deidentifier` docsCreate profile configurationUpdate UI to select profileWrite Playwright test with `/test-data/CASES/Caso1.zip`Verify anonymized output with console monitoring**Scenario 2**: "Fix file upload UI not triggering"
Check label element is clickableVerify click targets label, not hidden inputAdd Playwright test following file upload patternTest with `.zip` files from test-data**Scenario 3**: "Add new color theme variable"
Add CSS variable to `aca_nuxt/layers/base/assets/css/tailwind.css`Update `tailwind.config.js` if neededUse new variable in components with Tailwind classesAvoid adding scoped CSS unless absolutely necessary