PackShip v2 is now available! 🚀 Learn more

Package Structure

Understanding the structure of your package is essential for effective development and maintenance. PackShip creates a well-organized project structure based on your choices during initialization.

Project Types

PackShip supports multiple project types, each with its own recommended structure. The structure varies based on your language choice (TypeScript or JavaScript) and project type.

TypeScript React Package

A TypeScript React package is structured to support component development with type safety:

my-package/
├── src/
│   ├── index.tsx           # Main entry point
│   ├── declaration.d.ts    # TypeScript declarations
│   └── internal/           # (Optional) Internal components
│       └── index.tsx
├── types/
│   └── index.ts            # Type definitions
├── styles/                 # (Optional) CSS styles
│   └── style.css
├── dist/                   # Compiled output (created after build)
├── package.json            # Package configuration
├── tsconfig.json           # TypeScript configuration
├── webpack.config.js       # (Optional) Webpack configuration
├── babel.config.json       # Babel configuration
├── postcss.config.js       # (Optional) PostCSS configuration
├── .eslintrc.json          # (Optional) ESLint configuration
├── .gitignore              # Git ignore file
├── .npmignore              # (Optional) npm ignore file
├── README.md               # (Optional) Documentation
├── LICENSE.md              # (Optional) License information
└── CODE_OF_CONDUCT.md      # (Optional) Code of conduct

TypeScript Node.js Package

A TypeScript Node.js package is structured for server-side development:

my-package/
├── src/
│   ├── index.ts            # Main entry point
│   ├── declaration.d.ts    # TypeScript declarations
│   └── internal/           # (Optional) Internal modules
│       └── index.ts
├── types/
│   └── index.ts            # Type definitions
├── dist/                   # Compiled output (created after build)
├── package.json            # Package configuration
├── tsconfig.json           # TypeScript configuration
├── webpack.config.js       # (Optional) Webpack configuration
├── .eslintrc.json          # (Optional) ESLint configuration
├── .gitignore              # Git ignore file
├── .npmignore              # (Optional) npm ignore file
├── README.md               # (Optional) Documentation
├── LICENSE.md              # (Optional) License information
└── CODE_OF_CONDUCT.md      # (Optional) Code of conduct

JavaScript React Package

A JavaScript React package is structured for component development without TypeScript:

my-package/
├── src/
│   ├── index.jsx           # Main entry point
│   └── internal/           # (Optional) Internal components
│       └── index.jsx
├── styles/                 # (Optional) CSS styles
│   └── style.css
├── dist/                   # Compiled output (created after build)
├── package.json            # Package configuration
├── webpack.config.js       # (Optional) Webpack configuration
├── babel.config.json       # Babel configuration
├── postcss.config.js       # (Optional) PostCSS configuration
├── .eslintrc.json          # (Optional) ESLint configuration
├── .gitignore              # Git ignore file
├── .npmignore              # (Optional) npm ignore file
├── README.md               # (Optional) Documentation
├── LICENSE.md              # (Optional) License information
└── CODE_OF_CONDUCT.md      # (Optional) Code of conduct

JavaScript Node.js Package

A JavaScript Node.js package is structured for server-side development without TypeScript:

my-package/
├── src/
│   ├── index.js            # Main entry point
│   └── internal/           # (Optional) Internal modules
│       └── index.js
├── dist/                   # Compiled output (created after build)
├── package.json            # Package configuration
├── webpack.config.js       # (Optional) Webpack configuration
├── .eslintrc.json          # (Optional) ESLint configuration
├── .gitignore              # Git ignore file
├── .npmignore              # (Optional) npm ignore file
├── README.md               # (Optional) Documentation
├── LICENSE.md              # (Optional) License information
└── CODE_OF_CONDUCT.md      # (Optional) Code of conduct

Vanilla JavaScript Package

A Vanilla JavaScript package is structured for browser-based utilities without framework dependencies:

my-package/
├── src/
│   ├── index.js            # Main entry point
│   └── internal/           # (Optional) Internal utilities
│       └── index.js
├── styles/                 # (Optional) CSS styles
│   └── style.css
├── dist/                   # Compiled output (created after build)
├── package.json            # Package configuration
├── webpack.config.js       # (Optional) Webpack configuration
├── postcss.config.js       # (Optional) PostCSS configuration
├── .eslintrc.json          # (Optional) ESLint configuration
├── .gitignore              # Git ignore file
├── .npmignore              # (Optional) npm ignore file
├── README.md               # (Optional) Documentation
├── LICENSE.md              # (Optional) License information
└── CODE_OF_CONDUCT.md      # (Optional) Code of conduct

Key Files and Directories

Entry Points

The entry point is the main file that exports your package's functionality:

  • src/index.tsx or src/index.jsx: Main entry point for React packages
  • src/index.ts or src/index.js: Main entry point for Node.js and Vanilla JS packages

Example of a TypeScript React entry point:

// src/index.tsx
import MyComponent from './components/MyComponent';
import MyOtherComponent from './components/MyOtherComponent';

// Export components
export { MyComponent, MyOtherComponent };

// Default export
export default { MyComponent, MyOtherComponent };

Type Definitions

TypeScript packages include type definitions to provide type information:

  • types/index.ts: Contains shared type definitions
  • src/declaration.d.ts: Contains module declarations for non-TypeScript files

Example of type definitions:

// types/index.ts
export interface ComponentProps {
  className?: string;
  children?: React.ReactNode;
  onClick?: () => void;
}

export type Theme = 'light' | 'dark' | 'system';

Configuration Files

PackShip generates several configuration files based on your choices:

  • package.json: Defines package metadata, dependencies, and scripts
  • tsconfig.json: Configures TypeScript compiler options
  • webpack.config.js: Configures bundling options (if Webpack is selected)
  • babel.config.json: Configures Babel for transpilation (for React projects)
  • postcss.config.js: Configures PostCSS for CSS processing (if selected)
  • .eslintrc.json: Configures ESLint for code linting (if selected)

package.json

The package.json file contains important metadata and configuration:

{
  "name": "my-package",
  "version": "0.1.0",
  "description": "My awesome package",
  "main": "dist/index.js",
  "module": "dist/index.mjs",
  "type": "module",
  "scripts": {
    "test": "echo 'Error: no test specified' && exit 1",
    "build": "tsc && npm run build-babel && npm run build-webpack",
    "build-babel": "babel src --out-dir dist --presets=@babel/preset-react,@babel/preset-env",
    "build-webpack": "webpack --config webpack.config.js",
    "lint": "eslint .",
    "packship:publish": "packship publish"
  },
  "keywords": [],
  "author": {
    "name": "Your Name",
    "email": "your.email@example.com"
  },
  "license": "MIT",
  "_packshipInitialized": true,
  "peerDependencies": {
    "react": "^18.2.0",
    "react-dom": "^18.2.0"
  },
  "devDependencies": {
    "@babel/cli": "^7.10.5",
    "@babel/core": "^7.23.9",
    "@babel/preset-env": "^7.23.9",
    "@babel/preset-react": "^7.23.3",
    "@babel/preset-typescript": "^7.24.7",
    "@types/react": "^18.3.3",
    "@types/react-dom": "^18.3.0",
    "ts-loader": "^9.5.1",
    "typescript": "^4.9.5",
    "webpack": "^5.0.0",
    "webpack-cli": "^5.1.4",
    "eslint": "^7.32.0",
    "eslint-plugin-react": "^7.24.0",
    "@typescript-eslint/eslint-plugin": "^5.0.0",
    "@typescript-eslint/parser": "^5.0.0",
    "autoprefixer": "^10.3.1",
    "postcss": "^8.4.5"
  }
}

The _packshipInitialized property is added to your package.json to indicate that the package was initialized with PackShip.

Customizing Your Project Structure

While PackShip provides a solid foundation, you can customize your project structure to fit your specific needs:

Adding Directories

  • src/components/: For React components
  • src/hooks/: For React hooks
  • src/utils/: For utility functions
  • src/services/: For service modules
  • src/constants/: For constant values
  • tests/: For test files
  • Keep related files together in feature-based directories
  • Use clear, consistent naming conventions
  • Export public APIs only from the main entry point
  • Use the internal directory for components not meant for public consumption
  • Keep configuration files at the root level

While you can customize your project structure, following the PackShip conventions makes it easier to use the built-in tools and workflows.