Thanks for your interest in contributing to Tools Collection.
git clone https://github.com/amargiovanni/tools-collection.git
cd tools-collection
npm install
npm run devEach tool is three files + registry entries:
import { ok, err } from '../lib/result'
import type { Result } from '../lib/result'
export function myToolFunction(input: string): Result<string> {
if (!input.trim()) return err('EMPTY_INPUT', 'Please enter some input')
// transform input
return ok(result)
}- Returns
Result<T>, never throws - Zero DOM, zero side effects
- Independently testable
import { describe, it, expect } from 'vitest'
import { myToolFunction } from '../../src/tools/my-tool'
describe('myToolFunction', () => {
it('returns error for empty input', () => {
const r = myToolFunction('')
expect(r.ok).toBe(false)
})
it('transforms input correctly', () => {
const r = myToolFunction('test')
expect(r.ok).toBe(true)
if (r.ok) expect(r.value).toBe('expected')
})
})import { createSignal } from 'solid-js'
import { TextArea } from '../ui/TextArea'
import { Button } from '../ui/Button'
import { OutputPanel } from '../ui/OutputPanel'
import { StatusMessage } from '../ui/StatusMessage'
import { myToolFunction } from '../../tools/my-tool'
import { t, translateError } from '../../i18n'
import type { Language } from '../../i18n'
interface Props { lang: Language }
export default function MyTool(props: Props) {
const [input, setInput] = createSignal('')
const [output, setOutput] = createSignal('')
const [error, setError] = createSignal<string | null>(null)
const handle = () => {
const result = myToolFunction(input())
if (result.ok) { setOutput(result.value); setError(null) }
else { setError(translateError(props.lang, result.error)) }
}
return (
<div class="flex flex-col gap-4">
<TextArea onInput={(e) => setInput(e.currentTarget.value)} />
<Button onClick={handle}>Go</Button>
{error() && <StatusMessage type="error" message={error()!} />}
<OutputPanel value={output()} />
</div>
)
}- Registry — add entry to
src/config/tools.ts(id, category, icon, keywords, path) - Component map — add import to
src/config/tool-components.ts - i18n — add
tools_myTool_nameandtools_myTool_descriptionkeys to bothsrc/i18n/messages/en.jsonandsrc/i18n/messages/it.json - Error keys — add
errors_MY_ERROR_CODEto both locale files if your tool has custom error codes
The tool automatically gets pages at /en/tools/my-tool and /it/tools/my-tool, appears in the sidebar, homepage, and command palette.
feature/short-description
fix/short-description
type(scope): short description
Types: feat, fix, refactor, test, docs, chore, ci
npm test # all tests pass
npm run build # 57+ pages build
npm run check # no type errorsVerify there are no console.log in src/:
grep -rn 'console.log' src/ --include='*.ts' --include='*.tsx'- TypeScript strict — no
any, no@ts-ignore, no unsafe casts - Pure logic in
src/tools/— no DOM, no imports from UI layer - Shared components in
src/components/ui/— tool UIs compose these, never duplicate - i18n for all visible text — use
t(lang, key), never hardcode strings - Error handling via
Result<T>— useok()/err(), never throw in tool logic - Use
translateError()for error display — neveras any
Open an issue at https://github.com/amargiovanni/tools-collection/issues with:
- What you expected
- What happened
- Browser and OS
- Steps to reproduce