A TypeScript and Playwright-based browser automation project for generating AI-powered LinkedIn content, creating matching visuals, storing generated content locally, and scheduling posts through a browser workflow.
This project is designed for personal content automation, and building a reusable LinkedIn content workflow.
- AI-powered LinkedIn post generation
- AI image generation using a style reference
- Local storage for generated posts and images
- Weekly post scheduling support
- Multi-account ChatGPT profile support(Support 5 different account at the same time)
- Persistent browser profiles for saved login sessions
- Resume support after failed runs
- LinkedIn scheduling support
- Email alerts on automation failure
- Dry-run mode for safe testing
- TypeScript
- Node.js
- Playwright
- ChatGPT browser automation
- LinkedIn browser automation
- Local JSON storage
- Gmail SMTP email alerts
Before running this project, make sure the following are installed:
- Node.js
- npm
- Git
- Playwright browsers
Check Node.js and npm:
node -v
npm -vClone the repository:
Open the project folder:
```bash
cd linkedin-browser-automation
Install dependencies:
npm installInstall Playwright browsers:
npx playwright installThe project requires a few local files before running.
Create a .env file in the root folder:
.env
Example:
EMAIL_USER=your_email@gmail.com
EMAIL_PASS=your_gmail_app_password
EMAIL_TO=receiver_email@gmail.comThese values are used for email failure alerts.
For Gmail, use a Gmail App Password instead of your normal Gmail password.
Create a .env.example file in the root folder:
.env.example
Example:
EMAIL_USER=your_email@gmail.com
EMAIL_PASS=your_gmail_app_password
EMAIL_TO=receiver_email@gmail.comThis file is safe to keep in the repository because it does not contain real credentials.
Create a .gitignore file in the root folder:
.gitignore
Recommended content:
node_modules
.env
profiles/
storage/
dist/
build/
*.log
npm-debug.log*
.DS_StoreCreate an assets folder:
assets/
Add your style reference image:
assets/style.jfif
This image is used as the visual style reference for generated LinkedIn images.
linkedin-browser-automation/
│
├── assets/
│ └── style.jfif
│
├── src/
│ ├── browser/
│ ├── chatgpt/
│ ├── config/
│ ├── image-generator/
│ ├── linkedin/
│ ├── notifications/
│ ├── post-generator/
│ ├── prompts/
│ ├── scheduler/
│ ├── services/
│ ├── setup/
│ ├── storage/
│ ├── types/
│ └── main.ts
│
├── .env.example
├── .gitignore
├── package.json
├── tsconfig.json
└── README.md
The following folders are created locally during usage:
profiles/
storage/
Stores local browser sessions for ChatGPT and LinkedIn.
Example:
profiles/chatgpt-1
profiles/chatgpt-2
profiles/linkedin
Stores generated posts and images.
Example:
storage/posts/posts.json
storage/images/
These folders should not be committed to GitHub.
Main configuration is available in:
src/config/constants.ts
Example:
export const POSTS_PER_WEEK =
7;
export const ACCOUNT_LIMITS =
[
5,
2
];
export const ACCOUNT_LOGIN_READY =
[
true,
true,
false,
false,
false
];
export const LINKEDIN_PROFILE =
"./profiles/linkedin";
export const LINKEDIN_AUTO_SCHEDULE =
true;
export const LINKEDIN_DRY_RUN =
false;Number of posts to generate for one week.
export const POSTS_PER_WEEK =
7;Defines how many posts each ChatGPT account should generate.
export const ACCOUNT_LIMITS =
[
5,
2
];Example:
Account 1 = 5 posts
Account 2 = 2 posts
Total = 7 posts
Defines which ChatGPT accounts are ready to use.
export const ACCOUNT_LOGIN_READY =
[
true,
true,
false,
false,
false
];Only accounts marked as true are used.
Enables or disables LinkedIn scheduling.
export const LINKEDIN_AUTO_SCHEDULE =
true;Set to false if you only want to generate content without scheduling.
Runs LinkedIn scheduling in test mode.
export const LINKEDIN_DRY_RUN =
true;Use true for testing.
Use false for real scheduling.
The project uses these npm scripts:
{
"scripts": {
"dev": "ts-node src/main.ts",
"login-accounts": "ts-node src/setup/login-accounts.ts",
"login-linkedin": "ts-node src/setup/login-linkedin.ts",
"reset-linkedin-status": "ts-node src/setup/reset-linkedin-status.ts"
}
}Before running the main automation, login sessions need to be created.
npm run login-accountsThis opens browser profiles for ChatGPT accounts.
Log in manually when required.
npm run login-linkedinThis opens the LinkedIn browser profile.
Log in manually when required.
After setup is complete, run:
npm run devThis starts the main automation workflow.
Generated data will be saved locally inside:
storage/
To reset local LinkedIn scheduling status, run:
npm run reset-linkedin-statusThis is useful during testing when generated posts already exist but scheduling status needs to be cleared.
Generated posts are stored in:
storage/posts/posts.json
Generated images are stored in:
storage/images/
Example post object:
{
"topic": "AI Productivity",
"content": "AI is changing how developers build software...\n\n#ArtificialIntelligence #SoftwareEngineering #Programming",
"status": "linkedin-scheduled",
"imagePath": "storage/images/post-1.png",
"scheduledAt": 1783560600000,
"scheduledDate": "Wednesday, July 8, 2026 at 7:30 PM",
"linkedinStatus": "scheduled",
"linkedinError": ""
}Post prompt configuration is located in:
src/prompts/post.prompt.ts
Use this file to customize:
Post topic
Writing style
CTA
Hashtags
Output format
Image prompt configuration is usually created in:
src/services/weekly-generation.service.ts
Search for:
const imagePrompt =Use this section to customize image generation requirements.
The project can send email alerts when automation fails.
Required .env values:
EMAIL_USER=your_email@gmail.com
EMAIL_PASS=your_gmail_app_password
EMAIL_TO=receiver_email@gmail.comFor Gmail, enable 2-Step Verification and create an App Password.
For safe testing, enable dry-run mode:
export const LINKEDIN_DRY_RUN =
true;Then run:
npm run devAfter testing, disable dry run:
export const LINKEDIN_DRY_RUN =
false;Then run again:
npm run devRun login setup again:
npm run login-accounts
npm run login-linkedinCheck:
.env file exists
EMAIL_USER is correct
EMAIL_PASS is a Gmail App Password
EMAIL_TO is correct
Check these values in src/config/constants.ts:
export const LINKEDIN_AUTO_SCHEDULE =
true;
export const LINKEDIN_DRY_RUN =
false;Install Playwright browsers again:
npx playwright installDelete node_modules and reinstall:
npm installDo not commit private or generated files:
.env
profiles/
storage/
node_modules/
These files may contain credentials, browser sessions, generated content, or large dependencies.
MIT License