expo-screenshotter v0.5.1
📱 Expo Screenshotter
✨ Features
Note: Device framing is fully implemented for both iPhone and Android frames. The tool will take your screenshot and overlay the device frame on top of it, maintaining the screenshot's dimensions.
🆕 What's New in v0.4.0
- Screenshot Report Generation: Automatically generate a beautiful HTML report of all screenshots taken
🚀 Installation
npm install -g expo-screenshotter
🖼️ Device Frame Assets
To use the device frame feature, you need to have the frame images in the correct location.
Pill=true, Color=Space Black.png
Pill=true, Color=Gold.png
Pill=true, Color=Silver.png
Pill=true, Color=Deep Purple.png
Pill=False, Color=Starlight.png
Pill=False, Color=Midnight.png
Pill=False, Color=Red.png
Pill=False, Color=Blue.png
Android Compact Black.png
Android Compact Silver.png
Android Medium Black.png
Android Medium Silver.png
If you're using this tool as a dependency in your project, you may need to create the appropriate asset directories and add the frame images manually.
📋 Usage
There are three main commands:
Initialize Configuration
expo-screenshotter init
This creates a default expo-screenshotter.json
configuration file in your project. You can then customize this file for your needs.
If you're using Expo Router, the tool will detect it and offer to automatically scan your project for routes:
Do you want us to automatically detect all routes for you? (Y/n):
If you select yes, the tool will:
1. Scan your app
or src/app
directory for route files
2. Detect routes based on Expo Router conventions (including route groups with parentheses)
3. Show you the detected routes and present an interactive menu with three options:
- Select specific routes interactively: Opens a checkbox interface where you can use arrow keys to navigate, space to select routes, and enter to confirm
- Use all detected routes: Includes all detected routes in your configuration
- Use default routes: Uses the default example routes instead
This makes it much easier to get started with complex Expo Router projects!
Take Screenshots
expo-screenshotter capture
This will use your expo-screenshotter.json
configuration to take screenshots. Make sure your Expo web app is running first with expo start --web
.
Generate Report
expo-screenshotter report
This will generate an HTML report from existing screenshots in your output directory. You can specify a custom directory with the --dir
option:
expo-screenshotter report --dir ./my-screenshots
⚙️ Configuration File (expo-screenshotter.json)
The configuration file controls which routes to screenshot, at what sizes, and with what options. You can create this file manually or use the init
command, which can automatically detect routes in Expo Router projects.
{
"views": [
{
"name": "Home",
"path": "/"
},
{
"name": "Form with Input",
"path": "/form",
"interactions": [
{
"type": "type",
"selector": "input[placeholder=\"First Name\"]",
"text": "John"
},
{
"type": "wait",
"waitTime": 500
},
{
"type": "type",
"selector": "input[placeholder=\"Last Name\"]",
"text": "Doe"
},
{
"type": "wait",
"waitTime": 1000
}
],
"waitAfterInteractions": 1000
},
{
"name": "Button Click",
"path": "/buttons",
"interactions": [
{
"type": "click",
"selector": "button.primary-button"
},
{
"type": "wait",
"waitTime": 2000
}
],
"waitAfterInteractions": 1000
}
],
"sizes": [
{
"width": 375,
"height": 812,
"name": "iPhone X"
},
{
"width": 1280,
"height": 800,
"name": "Tablet"
},
{
"width": 2560,
"height": 1440,
"name": "Desktop"
},
{
"width": 1280,
"height": 800,
"name": "Tablet Full Page",
"fullPage": true
},
{
"width": 375,
"height": 812,
"name": "iPhone X with Frame",
"useDeviceFrame": true,
"deviceType": "iphone",
"iphoneOptions": {
"pill": true,
"color": "Space Black"
}
},
{
"width": 375,
"height": 812,
"name": "iPhone X with Gold Frame",
"useDeviceFrame": true,
"deviceType": "iphone",
"iphoneOptions": {
"pill": true,
"color": "Gold"
}
},
{
"width": 375,
"height": 812,
"name": "iPhone X with Custom Size",
"useDeviceFrame": true,
"deviceType": "iphone",
"iphoneOptions": {
"pill": true,
"color": "Gold",
"width": 1242,
"height": 2688
}
},
{
"width": 360,
"height": 740,
"name": "Android Medium Black",
"useDeviceFrame": true,
"deviceType": "android",
"androidOptions": {
"size": "medium",
"color": "black"
}
},
{
"width": 360,
"height": 740,
"name": "Android Compact Silver",
"useDeviceFrame": true,
"deviceType": "android",
"androidOptions": {
"size": "compact",
"color": "silver"
}
},
{
"width": 360,
"height": 740,
"name": "Android with Custom Size",
"useDeviceFrame": true,
"deviceType": "android",
"androidOptions": {
"size": "medium",
"color": "black",
"width": 1080,
"height": 2340
}
}
],
"outputDir": "./screenshots",
"expoUrl": "http://localhost:8081",
"waitTime": 2000,
"waitForSelector": "#my-element",
"fullPage": false,
"useDeviceFrame": false,
"generateReport": true,
"iphoneOptions": {
"pill": true,
"color": "Space Black"
},
"androidOptions": {
"size": "medium",
"color": "black"
}
}
🔧 Advanced Configuration Options
waitTime
: Delay in milliseconds before taking screenshots (default: 1000)waitForSelector
: CSS selector to wait for before taking screenshots (e.g., "#my-element")fullPage
: Set totrue
to capture the entire scrollable content for all sizes (default: false)useDeviceFrame
: Set totrue
to place all screenshots inside device frames (default: false)deviceType
: Default device frame type to use ('iphone' or 'android')generateReport
: Set totrue
to automatically generate an HTML report of all screenshots (default: true)iphoneOptions
: Options for iPhone frames:pill
: Set totrue
for pill-style (iPhone 14 Pro+) orfalse
for notch-style (iPhone 13, 14)color
: iPhone color ('Gold', 'Space Black', 'Silver', 'Deep Purple', 'Starlight', 'Midnight', 'Red', 'Blue')width
: Optional target width for the final image (for custom resizing)height
: Optional target height for the final image (for custom resizing)
androidOptions
: Options for Android frames:size
: Android device size ('compact' or 'medium')color
: Android device color ('black' or 'silver')width
: Optional target width for the final image (for custom resizing)height
: Optional target height for the final image (for custom resizing)
Each size in the sizes
array can have these additional options:
fullPage
: Override the global fullPage setting for this specific sizescrollY
: Scroll vertically by specified pixels before capturingscrollX
: Scroll horizontally by specified pixels before capturinguseDeviceFrame
: Override the global useDeviceFrame setting for this specific sizedeviceType
: Override the global deviceType setting for this specific sizeiphoneOptions
: Override the global iPhone frame options for this specific size- Including
width
andheight
properties to resize the final framed image to specific dimensions
- Including
androidOptions
: Override the global Android frame options for this specific size- Including
width
andheight
properties to resize the final framed image to specific dimensions
- Including
For example, to wait for a specific element and capture a full-page screenshot with device frames:
{
"waitForSelector": "#content-loaded",
"waitTime": 3000,
"useDeviceFrame": true,
"deviceType": "iphone",
"iphoneOptions": {
"pill": true,
"color": "Gold"
},
"sizes": [
{
"name": "Full Page Mobile",
"width": 375,
"height": 812,
"fullPage": true
},
{
"name": "Scrolled Desktop",
"width": 1280,
"height": 800,
"scrollY": 500
},
{
"name": "iPhone with Notch",
"width": 375,
"height": 812,
"iphoneOptions": {
"pill": false,
"color": "Midnight"
}
},
{
"name": "iPhone with Custom Size",
"width": 375,
"height": 812,
"useDeviceFrame": true,
"deviceType": "iphone",
"iphoneOptions": {
"pill": true,
"color": "Gold",
"width": 1242,
"height": 2688
}
},
{
"name": "Android Medium Black",
"width": 360,
"height": 740,
"deviceType": "android",
"androidOptions": {
"size": "medium",
"color": "black"
}
},
{
"name": "Android Compact Silver",
"width": 360,
"height": 740,
"deviceType": "android",
"androidOptions": {
"size": "compact",
"color": "silver"
}
},
{
"name": "Android with Custom Size",
"width": 360,
"height": 740,
"useDeviceFrame": true,
"deviceType": "android",
"androidOptions": {
"size": "medium",
"color": "black",
"width": 1080,
"height": 2340
}
}
]
}
Each view in the views
array can have these additional options:
interactions
: An array of interactions to perform before taking screenshots:- Type interactions:
{ "type": "type", "selector": "CSS_SELECTOR", "text": "TEXT_TO_TYPE" }
- Click interactions:
{ "type": "click", "selector": "CSS_SELECTOR" }
- Wait interactions:
{ "type": "wait", "waitTime": MILLISECONDS }
- Type interactions:
waitAfterInteractions
: Time in milliseconds to wait after all interactions are complete before taking screenshots
For example, to fill out a form and click a button before taking screenshots:
{
"name": "Form Submission",
"path": "/contact",
"interactions": [
{
"type": "type",
"selector": "input[name='name']",
"text": "John Doe"
},
{
"type": "type",
"selector": "input[name='email']",
"text": "john@example.com"
},
{
"type": "type",
"selector": "textarea[name='message']",
"text": "This is a test message"
},
{
"type": "click",
"selector": "button[type='submit']"
},
{
"type": "wait",
"waitTime": 2000
}
],
"waitAfterInteractions": 1000
}
📊 Screenshot Report
The tool can automatically generate a beautiful HTML report of all screenshots taken. This makes it easy to view and share your screenshots with team members or clients.
- Visual Grid Layout: All screenshots are displayed in a responsive grid layout
- Screenshot Information: Each screenshot card shows the view name, size, and file path
- Interactive UI: Hover effects and clean design for easy browsing
- Automatic Generation: Reports can be generated automatically during capture or separately with the
report
command
Enabling Report Generation
You can enable automatic report generation in your configuration file:
{
"generateReport": true,
// ... other configuration options
}
This option is enabled by default in new configurations created with the init
command.
Generating Reports Separately
You can also generate a report from existing screenshots without recapturing them:
expo-screenshotter report
This command will scan your output directory for screenshots and generate an HTML report. You can specify a custom directory with the --dir
option:
expo-screenshotter report --dir ./my-screenshots
The report will be saved as screenshot-report.html
in your output directory.
📱 Available Device Frame Options
🛠️ Development
# Clone the repository
git clone https://github.com/TheRealPerson98/expo-screenshotter.git
cd expo-screenshotter
# Install dependencies
npm install
# Build the project
npm run build
The project uses ESLint for code quality:
# Run linting
npm run lint
# Fix linting issues automatically
npm run lint:fix
📝 License
This software is dual-licensed:
For Individual/Open Source Use
MIT © Person98 LLC - Jace Sleeman (@TheRealPerson98)
This software can be used freely in personal and open-source projects. For commercial use, please refer to the license terms or contact for licensing options.
📸 Examples
Testing
To run the tests:
npm test
Test Setup
The tests use a mock server to simulate an Expo app and mock the screenshot capture process. The tests are designed to run in isolation and not interfere with each other.
Test Files
basic.test.ts
: Tests basic functionality like initializing a configuration file and taking screenshots.advanced.test.ts
: Tests advanced features like device frames, interactions, and full-page screenshots.programmatic.test.ts
: Tests the programmatic API.
Mock Server
The tests use a mock server (MockExpoServer
) to simulate an Expo app. The server serves static HTML pages that can be used for testing.
Test Configuration
The test configuration is defined in setup.ts
and includes:
- Output directory for screenshots
- Mock server port
- Expo URL
Troubleshooting
TypeScript Errors
If you encounter TypeScript errors when running the tests, make sure you have the correct TypeScript configuration. The tests use a separate tsconfig.json
file in the __tests__
directory.
Port Conflicts
If you encounter port conflicts when running the tests, you can modify the port numbers in the test files. Each test file uses a different port to avoid conflicts.
PowerShell Execution Policy
If you're using PowerShell and encounter execution policy errors, you can run the tests with:
powershell -ExecutionPolicy Bypass -Command "npm test"