Last day I shipped Duelr v0.1.1, a one-click LLM comparison tool that lets you see which LLM, such as GPT-4o, Claude 4 Sonnet, Groq etc., performs best for your own prompt, not a generic benchmark.
I wanted to document what worked (and what very much didn’t) during my first open-source journey. If you’re about to launch your own OSS project, I hope these notes save you a few headaches.
Repo: Duelr (Apache-2.0 license, contributions welcome!)
1. Project Snapshot
Area | Details |
---|---|
Frontend / Runtime | Next.js, shadcn/ui, TypeScript |
Backend | None—Next.js server routes call third-party LLM APIs directly |
CI / CD | GitHub Actions |
Linting | ESLint, Prettier |
2. Docs Before Dopamine
I forced myself to finish the boring artifacts before polishing UI:
- README – Short “Why / Try / How” structure; everything still fits on one screen.
- GitHub Issue Forms – YAML-based forms, not Markdown templates, so every bug report arrives pre-structured.
- CONTRIBUTING – Quick-start, branch flow, Conventional Commits cheat-sheet.
- LICENSE (Apache-2.0) & CODE_OF_CONDUCT
Tip: If you use Issue Forms, remember to set default labels in the YAML; otherwise issues arrive unlabeled.
Tip: Don't forget to create some issue labels since GitHub defaults are terrible. They say "enhancement" for new feature requests. New feature is new feature. Enhancement/improvement/refactoring is to develop something further to make it better.
3. The Boss Fight: Automated Releases
I wanted semantic versioning plus autogenerated changelogs and releases, so I picked Google’s release-please
Action. The promise:
- Parse Conventional Commits (
feat:
,fix:
,BREAKING:
…). - Open a “chore: release vX.Y.Z” PR.
- On merge, tag and publish the release + changelog.
The Gotcha
release-please
reads either the Action inputs or a repo-level config file, not both. Once you add release-please-config.json
, any parameters in your workflow YAML are ignored. I spent a night wondering why my configs were not applied.
Working Minimal Setup
{
"packages": {
".": {
"release-type": "node",
"changelog-sections": [
{ "type": "feat", "section": "✨ Features" },
{ "type": "fix", "section": "🐛 Bug Fixes" },
{ "type": "perf", "section": "⚡ Performance Improvements" },
{ "type": "docs", "section": "📚 Documentation" },
{ "type": "style", "section": "💄 Styles" },
{ "type": "refactor", "section": "♻️ Code Refactoring" },
{ "type": "test", "section": "✅ Tests" },
{ "type": "build", "section": "🔧 Build System" },
{ "type": "ci", "section": "👷 CI/CD" },
{ "type": "revert", "section": "⏪ Reverts" }
],
"bump-minor-pre-major": true,
"bump-patch-for-minor-pre-major": false,
"draft": false,
"prerelease": false,
"skip-github-release": false,
"include-component-in-tag": false
}
}
}
name: Release
on:
push:
branches: [main]
workflow_dispatch:
permissions:
contents: write
pull-requests: write
jobs:
release:
runs-on: ubuntu-latest
steps:
...
- name: Release
uses: google-github-actions/release-please-action@v4
id: release
with:
token: ${{ secrets.RELEASE_TOKEN }}
config-file: release-please-config.json
manifest-file: .release-please-manifest.json
Now every merge to main bumps SemVer, updates CHANGELOG.md
, and cuts a GitHub release in seconds.
4. Did I Miss Any Best Practices?
This is my first OSS journey, so I’m sure I broke a convention or two.
How would you improve the workflow or project layout? I’d love your feedback and, of course, PRs are very welcome!
👉 Repo: Duelr
Thanks for reading, and good luck on your own open-source adventures!
Top comments (2)
Hey Ayberk, huge congrats on shipping Duelr! 🚀
I just gave the repo a star, love how lightweight the stack is and how you shipped with real docs instead of “README coming soon.” The release-please tip about config vs. workflow inputs is a lifesaver; I definitely would have lost a night on that one.
Really cool stuff. I’m already poking around for a “good first issue.” Keep the updates coming! 🙌
Don't wait for a "good first issue". Open a new one about what you would want to see in the tool and start working on yours. 😅