Welcome, and thank you for your interest in contributing to WordyMe!
We're thrilled to have you here. Whether you're a first-time contributor or an experienced developer, your contributions make a real difference. This project exists because of people like you who take the time to improve it.
Every contribution matters — from fixing a typo to implementing a major feature. We value all forms of contribution and treat every contributor with respect and appreciation.
- Learn and grow — Work with modern technologies like React 19, TypeScript, and Turborepo
- Build your portfolio — Meaningful open source contributions that showcase your skills
- Join a community — Connect with developers who share your passion
- Make an impact — Help people own their notes and documentation instead of renting them
Before you start: Please search existing issues and pull requests to see if someone else is working on something similar.
- Contributor Licence Agreement (CLA)
- Legal Headers (SPDX)
- Commercial Features
- Code of Conduct
- Questions
- How to Contribute
- Development Setup
- Project Structure
- Testing
- Pull Request Process
- Commit Convention
- Getting Help
To protect the project's future and allow us to offer an Enterprise version to sustain development, we require all contributors to agree to our Contributor License Agreement (CLA).
By submitting a Pull Request to this repository, you agree to the following:
- You grant TeamCoderz Ltd a perpetual, worldwide, irrevocable license to use, modify, and distribute your contribution.
- You represent that you own the rights to the code you are submitting.
- You understand that your contribution will be licensed under AGPL-3.0 in this repository, but TeamCoderz Ltd may also use it in commercial or proprietary versions of the software.
Note: For large contributions, our automated assistant will prompt you to digitally sign the full CLA before your code can be merged.
To ensure the license stays with the code, applicable files are now handled automatically.
The canonical SPDX header is:
/**
* SPDX-FileCopyrightText: 2026 TeamCoderz Ltd <legal@teamcoderz.org>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/- Pre-commit runs SPDX automation on staged files and re-stages changes automatically.
- CI runs a repository-wide SPDX check, so bypassed hooks are still caught.
- Existing compliant files are left unchanged.
SPDX automation currently targets:
- Source files under
apps/**/srcandpackages/**/srcwith extensionsts,tsx,js,jsx
SPDX automation skips generated and non-meaningful targets, including:
*.gen.ts,node_modules,dist,.turbo,coverage- Type declaration files (
*.d.ts) *.mjs,*.cjs, and tooling/config filename patterns:*.config.{ts,js,tsx,jsx},*.rc.{ts,js,tsx,jsx},.*.rc.{ts,js,tsx,jsx}, plusdrizzle.config.*(examples:vite.config.ts,tailwind.config.js,foo.rc.ts,.eslintrc.ts; these mirrorTOOLING_CONFIG_PATTERNSused by the automation)- Binary/media/archive assets
- JSON files and lockfiles
pnpm license:fix # add missing headers across tracked and untracked applicable files (full-repo mode uses git ls-files --cached --others --exclude-standard)
pnpm license:check # check tracked and untracked applicable files (full-repo mode uses git ls-files --cached --others --exclude-standard) and fail on missing headersWordyMe™ follows an Open Core model. If you are interested in developing features intended for large organizations (e.g., SAML/SSO, advanced audit logging), please contact us first. These features often belong in our Enterprise version, and we can discuss how to best collaborate.
Be welcoming, inclusive, and respectful. We don't tolerate harassment or exclusionary behavior. Report violations to maintainers.
If you have questions about implementation details or need help:
- Search existing issues before creating a new one
- Open an issue with the
questionlabel for implementation questions
| Type | Description |
|---|---|
| Bug Reports | Report a bug with reproduction steps and environment details |
| Feature Requests | Request a feature describing the problem it solves |
| Documentation | Fix typos, add examples, improve clarity, translate content |
| Code Review | Review open PRs — fresh eyes catch bugs |
| Design | UI/UX feedback, accessibility improvements |
Before you begin, ensure you have the following installed:
# 1. Fork and clone the repository
git clone https://github.com/<your-username>/WordyMe.git
cd WordyMe
# 2. Add upstream remote (this points to the original repo, so you can sync updates)
git remote add upstream https://github.com/TeamCoderz/WordyMe.git
# 3. Install dependencies
pnpm install
# 4. Set up the backend environment, then generate a session secret.
# apps/web needs no .env — see LOCAL_SETUP.md for why copying it is harmful.
cp apps/backend/.env.example apps/backend/.env
echo "BETTER_AUTH_SECRET=$(openssl rand -base64 32)" >> apps/backend/.env
# 5. Apply migrations — required on a fresh clone, or sign-up fails
cd apps/backend && pnpm drizzle-kit migrate && cd ../..
# 6. Start development servers
pnpm dev
# 7. Create a feature branch
git checkout -b feature/your-feature-nameSee LOCAL_SETUP.md for detailed instructions, or DOCKER.md for Docker setup.
This is a Turborepo monorepo with the following packages:
| Package | Description |
|---|---|
apps/web |
React 19 frontend (Vite, TanStack Router) |
apps/backend |
Express.js API (Drizzle ORM, libSQL) |
packages/editor |
Lexical rich text editor |
packages/ui |
Shared UI components |
packages/sdk |
API client SDK |
packages/types |
TypeScript type definitions |
packages/lib |
Shared utilities |
packages/shared |
Shared business logic |
pnpm dev # Start all services
pnpm dev --filter=web # Frontend only
pnpm dev --filter=@repo/backend # Backend only
pnpm build # Production build
pnpm lint # Run linter
pnpm lint:md # Lint Markdown docs
pnpm check-types # Type check
pnpm format # Format with Prettiercd apps/backend
pnpm drizzle-kit generate # Generate migration
pnpm drizzle-kit migrate # Apply migrationEvery pull request runs .github/workflows/ci.yml, which must pass before merge:
| Job | What it proves |
|---|---|
| Lint, type-check, build | pnpm lint, pnpm check-types, pnpm build all succeed |
| Docker stack health | The image builds and answers /api/health — not merely that it boots |
Run the first job locally before pushing:
pnpm lint && pnpm check-types && pnpm buildpnpm install --frozen-lockfile is used in CI, so a manifest change without its
matching pnpm-lock.yaml fails here rather than during a release.
Four packages carry a --max-warnings N ceiling instead of 0:
| Package | Ceiling |
|---|---|
packages/editor |
103 |
apps/web |
30 |
packages/embed-pdf |
27 |
packages/ui |
22 |
These are ratchets, not targets. The warnings predate the gate — they were
invisible because eslint-plugin-react's version detection crashed the whole
run on ESLint 10, so nobody had seen a complete lint result in months. Most of
what surfaced is behavioural (React Compiler correctness, hook dependencies,
conditionally-called hooks) and wants reviewing one case at a time, not a sweep.
The rule: the number may go down, never up. If a fix lowers the count, lower
the ceiling in the same pull request. The goal for all four is 0; every other
package is already there and is pinned at --max-warnings 0.
Be aware of what --max-warnings does and does not catch. It compares the
total count against the ceiling, so it fails a pull request that pushes the
total over — but a new warning introduced alongside a fix elsewhere nets to zero
and passes. It is a ceiling, not a per-warning diff. Closing that gap properly
needs a baseline file committed to the repository and compared per run, which is
worth doing once the counts are small enough that the baseline is not itself
noise.
Test thoroughly before opening a PR. Untested code wastes everyone's time and may be closed without review.
- Manually verify your changes work as expected
- Test edge cases and error scenarios
- Run
pnpm lint— must pass with no errors - Run
pnpm check-types— must pass with no errors - Run
pnpm build— must complete successfully - Verify you haven't broken existing functionality
- Test in multiple browsers (for UI changes)
-
Sync with upstream:
git fetch upstream git rebase upstream/main
-
Run all checks:
pnpm lint && pnpm check-types && pnpm build
-
Push your branch:
git push origin feature/your-feature-name
A template will auto-load when you open a PR on GitHub.
Just fill it out — don't leave sections empty. Use this title format (follow Commit Convention):
<type>(<scope>): <clear description>
Examples: feat(editor): add keyboard shortcuts, fix(auth): resolve session on custom domain
- Fill out every section of the auto-loaded template
- Link related issues (e.g.,
Fixes #123) - Include screenshots for UI changes
- Keep PRs focused — one feature or fix per PR
- Respond to review feedback promptly
- Don't force-push after review has started (unless asked)
| Requirement | Verification |
|---|---|
| Passes lint | pnpm lint |
| Passes type check | pnpm check-types |
| Builds successfully | pnpm build |
| Tested manually | Your verification |
| Clear commit messages | See Commit Convention |
We follow Conventional Commits. Please use the format:
<type>(<scope>): <description>
[optional body]
[optional footer]
| Type | Description |
|---|---|
feat |
New feature |
fix |
Bug fix |
docs |
Documentation changes |
style |
Formatting, no code change |
refactor |
Code restructuring |
test |
Adding or updating tests |
build |
Build system or dependencies |
ci |
CI configuration |
chore |
Other changes |
feat(editor): add keyboard shortcuts for toolbar
fix(auth): resolve session expiration issue
docs(api): update authentication examples
refactor(sdk): simplify error handling
Use descriptive prefixes: feature/, fix/, docs/, refactor/
| Label | Description |
|---|---|
good first issue |
Great for newcomers |
help wanted |
Extra help needed |
bug |
Something's broken |
enhancement |
Feature request |
documentation |
Docs improvement |
- GitHub Issues — Questions, ideas, and bug reports
- Security issues — Report privately to maintainers
By contributing, you agree that your contributions will be licensed under the AGPL-3.0.
Thank you for contributing to WordyMe!