| name | squared-package |
| description | Critical architecture knowledge for the squared component library package. Use this skill when working on squared package components, troubleshooting build/transpilation issues, or setting up apps to consume squared. Covers the NO BUILD STEP architecture, CSS Modules-only styling requirement, Next.js transpilation configuration, direct TypeScript source exports, and testing infrastructure. |
Squared Package Architecture
The @lsst-sqre/squared package is a React component library with a unique architecture designed for flexibility and type safety.
Critical Architecture Rules
NO BUILD STEP
⚠️ The squared package does NOT have a build step - it exports TypeScript source files directly.
This means:
- package.json
main,module, andtypesall point tosrc/index.ts(not adist/directory) - Consuming apps must transpile the package themselves
- No
tsup,tsc, or other build tools in the squared package - Changes are immediately available without rebuilding the package
Why This Architecture?
- Flexibility: Consuming apps control transpilation (target browsers, polyfills, etc.)
- Type Safety: Source TypeScript available for better IDE integration
- Development Speed: No build step means instant updates during development
- Simplicity: Fewer build tools to configure and maintain
Package.json Configuration
See the actual package configuration at packages/squared/package.json.
Key fields:
{
"main": "./src/index.ts",
"module": "./src/index.ts",
"types": "./src/index.ts",
"exports": {
".": {
"types": "./src/index.ts",
"default": "./src/index.ts"
},
"./components/*": "./src/components/*"
},
"sideEffects": false
}
Important:
- All entry points are TypeScript source files
sideEffects: falseenables tree-shaking- Component-level exports for granular imports
Styling Requirements
CSS Modules Only
⚠️ Squared package MUST use CSS Modules - NO styled-components allowed.
Why:
- Avoids runtime CSS-in-JS overhead
- Better SSR performance
- Consistent with design token system
- Clear separation of styles and logic
Pattern:
MyComponent/
├── MyComponent.tsx
├── MyComponent.module.css
├── MyComponent.stories.tsx
├── MyComponent.test.tsx
└── index.ts
Using Design Tokens
Styles use design tokens from @lsst-sqre/rubin-style-dictionary and @lsst-sqre/global-css.
See the design-system skill for complete CSS variable reference.
/* MyComponent.module.css */
.container {
padding: var(--sqo-space-md);
background-color: var(--rsd-color-primary-600);
border-radius: var(--sqo-border-radius-1);
box-shadow: var(--sqo-elevation-md);
}
.title {
font-size: 1.125rem;
font-weight: 600;
color: var(--rsd-component-text-color);
}
Available via:
packages/rubin-style-dictionary/dist/tokens.css- Foundation tokens (prefix:--rsd-*)packages/global-css/src/tokens.css- Application tokens (prefix:--sqo-*)- Import
@lsst-sqre/global-cssin your app to load all tokens
Consuming Squared in Apps
Apps that use squared must configure transpilation.
Next.js Configuration
Required in next.config.js:
module.exports = {
transpilePackages: ['@lsst-sqre/squared'],
// ... other config
};
This tells Next.js to transpile the squared package's TypeScript source.
See consuming-app-setup.md for complete setup guide.
Without Transpilation Configuration
If you forget to add transpilePackages, you'll see errors like:
Module parse failed: Unexpected token
You may need an appropriate loader to handle this file type
Testing Infrastructure
Vitest with Two Projects
Squared uses vitest with two separate test projects:
- Unit tests - Traditional vitest tests (
.test.tsfiles) - Storybook tests - Tests in Storybook stories via addon-vitest
See the actual test configuration at packages/squared/vitest.config.ts.
Running Tests
# Unit tests only
pnpm test --filter @lsst-sqre/squared
# Storybook tests only
pnpm test-storybook --filter @lsst-sqre/squared
# Storybook tests in watch mode
pnpm test-storybook:watch --filter @lsst-sqre/squared
# All tests (run from root)
pnpm test
pnpm test-storybook
Test Setup
Unit tests:
- Setup file:
src/test-setup.ts - Environment: jsdom
- Globals: enabled
- CSS Modules: non-scoped classNameStrategy
Storybook tests:
- Browser: Playwright (chromium)
- Environment: browser + jsdom
- Setup file:
.storybook/vitest.setup.ts
Component Development
TypeScript Patterns
Prefer type over interface:
// ✅ Good
type MyComponentProps = {
title: string;
onClick?: () => void;
};
// ❌ Avoid (unless extending/merging needed)
interface MyComponentProps {
title: string;
onClick?: () => void;
}
Avoid React.FC - type props directly:
// ✅ Good
export default function MyComponent({ title, onClick }: MyComponentProps) {
return <div onClick={onClick}>{title}</div>;
}
// ❌ Avoid
const MyComponent: React.FC<MyComponentProps> = ({ title, onClick }) => {
return <div onClick={onClick}>{title}</div>;
};
Component Structure
// MyComponent/MyComponent.tsx
import styles from './MyComponent.module.css';
type MyComponentProps = {
title: string;
variant?: 'primary' | 'secondary';
};
/**
* Component description for documentation
*/
export default function MyComponent({
title,
variant = 'primary'
}: MyComponentProps) {
return (
<div className={styles.container} data-variant={variant}>
<h2 className={styles.title}>{title}</h2>
</div>
);
}
Export Pattern
// MyComponent/index.ts
export { default } from './MyComponent';
export type { MyComponentProps } from './MyComponent';
// src/index.ts
export { default as MyComponent } from './components/MyComponent';
export type { MyComponentProps } from './components/MyComponent';
Dependencies
Workspace Dependencies
Squared depends on other monorepo packages:
@lsst-sqre/global-css- Global styles and design token application@lsst-sqre/rubin-style-dictionary- Design tokens@lsst-sqre/eslint-config- Linting configuration@lsst-sqre/tsconfig- TypeScript configuration
These use workspace protocol: "@lsst-sqre/global-css": "workspace:*"
Key External Dependencies
- React 19 - Component framework (peer dependency)
- Radix UI - Unstyled UI primitives
- react-feather - Icon library
- Font Awesome - Additional icons
- date-fns - Date manipulation
- react-day-picker - Date picker component
Dev Dependencies
- Next.js - Required for type checking (peer dep)
- Vitest - Test runner
- Storybook 9 - Component documentation
- Testing Library - React testing utilities
- Playwright - Browser testing (for Storybook tests)
Storybook Integration
Running Storybook
# Start Storybook dev server
pnpm storybook --filter @lsst-sqre/squared
# Build static Storybook
pnpm build-storybook --filter @lsst-sqre/squared
Story Pattern
// MyComponent.stories.tsx
import type { Meta, StoryObj } from '@storybook/react';
import MyComponent from './MyComponent';
const meta: Meta<typeof MyComponent> = {
title: 'Components/MyComponent',
component: MyComponent,
tags: ['autodocs'],
};
export default meta;
type Story = StoryObj<typeof MyComponent>;
export const Default: Story = {
args: {
title: 'Example Title',
variant: 'primary',
},
};
export const Secondary: Story = {
args: {
title: 'Example Title',
variant: 'secondary',
},
};
Testing Stories
With @storybook/addon-vitest, stories can include tests:
import { expect, within } from '@storybook/test';
export const WithTest: Story = {
args: {
title: 'Test Title',
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await expect(canvas.getByText('Test Title')).toBeInTheDocument();
},
};
Run with: pnpm test-storybook --filter @lsst-sqre/squared
Creating New Components
Manual Creation
- Create component directory in
src/components/ - Add
.tsx,.module.css,.stories.tsx,.test.tsxfiles - Create
index.tswith exports - Export from
src/index.ts - Import design tokens in CSS
- Write Storybook stories
- Write tests
Migration from Styled-Components
If you encounter styled-components in squared, they need to be migrated to CSS Modules.
See the migrate-styled-components-to-css-modules skill for complete step-by-step migration guidance, including:
- Component conversion patterns
- Design token usage
- Dynamic styles handling
- Test updates
- Before/after examples
Note: The squareone app still uses styled-components (legacy), but new squared components must use CSS Modules.
Troubleshooting
Build Errors: "Unexpected token"
Cause: App not configured to transpile squared package.
Solution: Add to next.config.js:
transpilePackages: ['@lsst-sqre/squared']
CSS Module Styles Not Applying
Cause: CSS Module not imported or class name mismatch.
Solution:
- Import:
import styles from './Component.module.css'; - Use:
className={styles.className} - Check CSS file has
.classNamedefined
Design Tokens Not Working
Cause: @lsst-sqre/global-css not imported in app.
Solution: Import in app's root layout/component:
import '@lsst-sqre/global-css';
TypeScript Errors in Consuming App
Cause: Type resolution issues with direct source imports.
Solution: Ensure consuming app's tsconfig.json includes squared source:
{
"include": ["src", "node_modules/@lsst-sqre/squared/src"]
}
Tests Failing
Unit tests:
# Run specific test
pnpm test --filter @lsst-sqre/squared -- MyComponent.test.tsx
# Run in watch mode
pnpm test --filter @lsst-sqre/squared -- --watch
Storybook tests:
# Run in watch mode for debugging
pnpm test-storybook:watch --filter @lsst-sqre/squared
# Run specific story test
pnpm test-storybook --filter @lsst-sqre/squared -- --grep "MyComponent"
Best Practices
- Always use CSS Modules for styling
- Always use design tokens (CSS variables) in styles
- Prefer
typeoverinterfacefor props - Avoid
React.FC- type props directly in function parameters - Write Storybook stories for all components
- Write tests for components (unit or story tests)
- Use Radix UI for accessible primitives when possible
- Document components with JSDoc comments
- Export components and types from
src/index.ts - Keep components focused - one responsibility per component
Related Files
packages/squared/package.json- Package configurationpackages/squared/vitest.config.ts- Test configuration- consuming-app-setup.md - App integration guide (in this skill)
Related Skills
- design-system - Complete CSS variable and design token reference
- component-creation - Creating new components with CSS Modules
- migrate-styled-components-to-css-modules - Converting legacy styled-components
- testing-infrastructure - Testing patterns and tools
Package Scripts
# Test commands
pnpm test # Unit tests
pnpm test-storybook # Storybook tests
pnpm test-storybook:watch # Watch mode
# Quality commands
pnpm lint # ESLint
pnpm type-check # TypeScript checking
# Storybook commands
pnpm storybook # Dev server
pnpm build-storybook # Build static site
# Utility commands
pnpm clean # Clean caches
Remember: Always run from repository root with --filter @lsst-sqre/squared for proper Turborepo caching!