Thank you for your interest in contributing! OGCOPS is open source and welcomes contributions of all kinds.
- New templates — add OG image templates to existing or new categories
- Bug fixes — fix rendering issues, API bugs, or editor glitches
- New features — platform previews, editor improvements, API enhancements
- Documentation — improve README, API docs, or inline comments
- Performance — optimize rendering, bundle size, or load times
- Tests — increase coverage for templates, API, and utilities
- Node.js 20+ (22 recommended, see
.nvmrc) - npm 9+
- Git
git clone https://github.com/codercops/ogcops.git
cd ogcops
npm install
npm run devVisit http://localhost:4321 to see the app.
src/
templates/ # 109 OG image templates by category
types.ts # TemplateDefinition interface
registry.ts # Central template registry
utils.ts # Shared helpers (truncate, autoFontSize, etc.)
blog/ # Blog templates
product/ # Product templates
... # 10 more category folders
lib/ # Core engine
og-engine.ts # Satori + resvg-wasm PNG generation
font-loader.ts # Font loading for satori
meta-fetcher.ts # URL meta tag fetching
meta-analyzer.ts # Meta tag analysis and scoring
api-validation.ts # Zod schemas for API validation
platform-specs.ts # Platform viewport dimensions
components/
editor/ # React islands for OG image editor
preview/ # React islands for preview checker
shared/ # Platform mockups, viewport switcher
pages/ # Astro pages + API routes
api/ # /api/og, /api/preview, /api/templates
styles/ # CSS custom properties (no Tailwind)
tests/ # Vitest test suites
public/fonts/ # Bundled .woff fonts (Inter, Playfair Display, JetBrains Mono)
- Create a new file in
src/templates/{category}/following kebab-case naming:my-template-name.ts - Export a
TemplateDefinitionobject as the default export - Register it in
src/templates/{category}/index.ts - Add the import and registration in
src/templates/registry.ts - Run
npm run testto verify it renders without errors
Use src/templates/blog/minimal-dark.ts as a reference implementation.
- Canvas is always 1200x630px
- Use only inline styles (no CSS classes in satori elements)
- Every container
divmust havedisplay: 'flex'in its style - Available fonts: Inter, Playfair Display, JetBrains Mono
- Use
truncate()andautoFontSize()helpers from../utils - Use
commonFieldswhere applicable for consistent field definitions - Make the template visually distinct and professional
We use Conventional Commits:
feat(templates): add neon-gradient blog template
fix(api): handle missing title parameter gracefully
docs: update API examples in README
refactor(editor): extract color picker into shared component
test(templates): add snapshot tests for podcast category
chore: update dependencies
- CSS: Custom properties only, no Tailwind
- TypeScript: Strict mode enabled
- Templates: Inline styles only in satori elements (no CSS classes)
- Satori: Every
divneeds explicitdisplay: 'flex' - Utilities: Use shared helpers from
src/templates/utils.ts - Path alias:
@/*maps tosrc/*
npm run test # Run all tests
npm run test:watch # Watch mode
npm run check # Type-check (astro check + tsc)
npm run build # Full production build- Fork the repo and create a branch:
git checkout -b feat/my-feature - Make your changes
- Ensure
npm run checkandnpm run testpass - Push and open a PR against
dev - Fill out the PR template — screenshots are required for visual changes
- Wait for review
- Keep PRs focused on a single change
- Link related issues with "Closes #123"
- For new templates, include a screenshot of the rendered output
- Check existing issues before opening a new one
- Use the appropriate template: Bug Report, Feature Request, or Template Request
Just submit your PR. By contributing, you agree that your contribution is licensed under the MIT License.