@devwithbobby/loops 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/.changeset/README.md +8 -0
  2. package/.changeset/config.json +14 -0
  3. package/.config/commitlint.config.ts +11 -0
  4. package/.config/lefthook.yml +11 -0
  5. package/.github/workflows/release.yml +52 -0
  6. package/.github/workflows/test-and-lint.yml +39 -0
  7. package/README.md +517 -0
  8. package/biome.json +45 -0
  9. package/bun.lock +1166 -0
  10. package/bunfig.toml +7 -0
  11. package/convex.json +3 -0
  12. package/example/CLAUDE.md +106 -0
  13. package/example/README.md +21 -0
  14. package/example/bun-env.d.ts +17 -0
  15. package/example/convex/_generated/api.d.ts +53 -0
  16. package/example/convex/_generated/api.js +23 -0
  17. package/example/convex/_generated/dataModel.d.ts +60 -0
  18. package/example/convex/_generated/server.d.ts +149 -0
  19. package/example/convex/_generated/server.js +90 -0
  20. package/example/convex/convex.config.ts +7 -0
  21. package/example/convex/example.ts +76 -0
  22. package/example/convex/schema.ts +3 -0
  23. package/example/convex/tsconfig.json +34 -0
  24. package/example/src/App.tsx +185 -0
  25. package/example/src/frontend.tsx +39 -0
  26. package/example/src/index.css +15 -0
  27. package/example/src/index.html +12 -0
  28. package/example/src/index.tsx +19 -0
  29. package/example/tsconfig.json +28 -0
  30. package/package.json +95 -0
  31. package/prds/CHANGELOG.md +38 -0
  32. package/prds/CLAUDE.md +408 -0
  33. package/prds/CONTRIBUTING.md +274 -0
  34. package/prds/ENV_SETUP.md +222 -0
  35. package/prds/MONITORING.md +301 -0
  36. package/prds/RATE_LIMITING.md +412 -0
  37. package/prds/SECURITY.md +246 -0
  38. package/renovate.json +32 -0
  39. package/src/client/index.ts +530 -0
  40. package/src/client/types.ts +64 -0
  41. package/src/component/_generated/api.d.ts +55 -0
  42. package/src/component/_generated/api.js +23 -0
  43. package/src/component/_generated/dataModel.d.ts +60 -0
  44. package/src/component/_generated/server.d.ts +149 -0
  45. package/src/component/_generated/server.js +90 -0
  46. package/src/component/convex.config.ts +27 -0
  47. package/src/component/lib.ts +1125 -0
  48. package/src/component/schema.ts +17 -0
  49. package/src/component/tables/contacts.ts +16 -0
  50. package/src/component/tables/emailOperations.ts +22 -0
  51. package/src/component/validators.ts +39 -0
  52. package/src/utils.ts +6 -0
  53. package/test/client/_generated/_ignore.ts +1 -0
  54. package/test/client/index.test.ts +65 -0
  55. package/test/client/setup.test.ts +54 -0
  56. package/test/component/lib.test.ts +225 -0
  57. package/test/component/setup.test.ts +21 -0
  58. package/tsconfig.build.json +20 -0
  59. package/tsconfig.json +22 -0
package/prds/CLAUDE.md ADDED
@@ -0,0 +1,408 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is a **Convex component template** for building reusable Convex components. It uses:
8
+ - **Bun** for package management, testing, and development
9
+ - **Biome** for linting and formatting
10
+ - **convex-test** for testing Convex functions
11
+ - TypeScript with strict mode enabled
12
+
13
+ ## Key Commands
14
+
15
+ ### Development
16
+ ```sh
17
+ bun run dev # Start both backend and frontend (with build watcher)
18
+ bun run dev:backend # Start Convex dev server with live component sources and typechecking
19
+ bun run dev:frontend # Start example frontend (Bun.serve with hot reload)
20
+ bun run build # Build TypeScript for distribution
21
+ bun run build:watch # Watch and rebuild on changes
22
+ ```
23
+
24
+ ### Testing
25
+ ```sh
26
+ bun test # Run all tests
27
+ bun test --watch # Watch mode for continuous testing
28
+ bun test --coverage # Generate code coverage reports
29
+ bun test --bail # Stop after first failure
30
+ bun test -t "pattern" # Filter tests by name pattern
31
+ CLAUDECODE=1 bun test # AI-friendly quiet output (only shows failures)
32
+ ```
33
+
34
+ ### Linting and Formatting
35
+ ```sh
36
+ bun run lint # Lint the codebase (Biome)
37
+ bun run lint:fix # Auto-fix linting issues
38
+ bun run format # Format code with Biome
39
+ bun run check # Run both lint and format checks
40
+ bun run check:fix # Auto-fix both lint and format issues
41
+ ```
42
+
43
+ ### Versioning and Releases
44
+ ```sh
45
+ bun run changeset # Add a new changeset (run when making user-facing changes)
46
+ bun run ci:version # Update versions and changelogs (usually automated by GitHub Actions)
47
+ bun run ci:publish # Publish to npm (usually automated by GitHub Actions)
48
+ ```
49
+
50
+ ## Project Structure
51
+
52
+ ```
53
+ src/
54
+ component/ # The Convex component source code
55
+ convex.config.ts # Component configuration (exported via package.json)
56
+ schema.ts # Convex schema definition
57
+ lib.ts # Component functions (queries, mutations)
58
+ _generated/ # Auto-generated Convex types (gitignored)
59
+
60
+ client/ # Client library (runs in app context, not component)
61
+ index.ts # Helper class for easier component interaction
62
+ types.ts # Type utilities for component API
63
+
64
+ react/ # React hooks and components (optional)
65
+ index.ts # React hooks for using the component
66
+
67
+ test/
68
+ component/ # Component tests (separate from source to avoid bundling)
69
+ setup.test.ts # Test setup with module auto-discovery
70
+ *.test.ts # Unit tests for the component
71
+
72
+ client/ # Client library tests
73
+ setup.test.ts # Test setup that registers the component
74
+ *.test.ts # Unit tests for the client library
75
+
76
+ example/
77
+ convex/ # Example app that uses the component
78
+ convex.config.ts # Example app configuration that imports the component
79
+ schema.ts # Example app schema
80
+ example.ts # Example usage of the client library
81
+ _generated/ # Auto-generated Convex types (gitignored)
82
+
83
+ src/ # Example frontend (Bun.serve + React)
84
+ index.tsx # Bun server with hot reload
85
+ frontend.tsx # React entry point
86
+ App.tsx # Main React component
87
+ ```
88
+
89
+ ## Architecture
90
+
91
+ ### Convex Component Pattern
92
+ This project follows the **Convex component architecture** with a three-layer structure:
93
+
94
+ 1. **Component Layer** (`src/component/`):
95
+ - Defines the component with `defineComponent("loopsComponent")`
96
+ - Contains the actual Convex functions (queries, mutations, actions)
97
+ - Has isolated tables, file storage, and scheduled functions
98
+ - Exported via package.json `"./convex.config"` with `@convex-dev/component-source` condition
99
+
100
+ 2. **Client Library Layer** (`src/client/`):
101
+ - Runs in the **app context** (not the component)
102
+ - Provides a helper class that wraps component API calls
103
+ - Can access `process.env` and `ctx.auth` from the app
104
+ - Exported via package.json `"."` (main entry point)
105
+ - Example: `LoopsComponent` class with `.add()` and `.count()` methods
106
+
107
+ 3. **React Layer** (`src/react/`):
108
+ - Optional React hooks and components
109
+ - Uses the client library internally
110
+ - Provides optimistic updates and loading states
111
+ - Exported via package.json `"./react"`
112
+ - Example: `useLoopsComponent()` hook
113
+
114
+ **Usage Flow**:
115
+ ```typescript
116
+ // 1. App mounts the component (example/convex/convex.config.ts)
117
+ import component from "robertalv/loops-component/convex.config"
118
+ app.use(component)
119
+
120
+ // 2. App creates client wrapper (example/convex/example.ts)
121
+ import { LoopsComponent } from "robertalv/loops-component"
122
+ const counter = new LoopsComponent(components.loopsComponent)
123
+ export const { add, count } = counter.api()
124
+
125
+ // 3. React component uses the hook (example/src/App.tsx)
126
+ import { useLoopsComponent } from "robertalv/loops-component/react"
127
+ const { count, add } = useLoopsComponent(api.example, "myCounter")
128
+ ```
129
+
130
+ ### Testing Pattern
131
+ This project uses `convex-test` with Bun's test runner. **Tests are kept separate from the component source** to prevent Convex from trying to bundle them during development.
132
+
133
+ #### Component Tests (`test/component/`)
134
+ Tests the component functions in isolation.
135
+
136
+ **Setup** (`test/component/setup.test.ts`):
137
+ - Auto-discovers all `.ts` files from `src/component/` using `Bun.Glob`
138
+ - Creates a `modules` map for convex-test
139
+ - Exports a `convexTest()` helper function
140
+ - Preloaded by Bun (configured in `bunfig.toml`)
141
+
142
+ **Example**:
143
+ ```ts
144
+ import { test, expect } from "bun:test";
145
+ import { api } from "../../src/component/_generated/api";
146
+ import { convexTest } from "./setup.test";
147
+
148
+ test("component function works", async () => {
149
+ const t = convexTest();
150
+ const result = await t.query(api.lib.greet, { name: "Alice" });
151
+ expect(result).toBe("Hello, Alice!");
152
+ });
153
+ ```
154
+
155
+ #### Client Library Tests (`test/client/`)
156
+ Tests the client library that wraps the component. This is more complex because it requires **registering the component**.
157
+
158
+ **Setup** (`test/client/setup.test.ts`):
159
+ - Auto-discovers client test files from `test/client/`
160
+ - Auto-discovers component files from `src/component/`
161
+ - Exports `initConvexTest()` that creates a test instance and registers the component
162
+ - Exports a mock `components` object for type-safe testing
163
+
164
+ **Example**:
165
+ ```ts
166
+ import { test, expect } from "bun:test";
167
+ import { LoopsComponent } from "../../src/client/index.js";
168
+ import { components, initConvexTest } from "./setup.test.js";
169
+
170
+ test("client library works", async () => {
171
+ const t = initConvexTest();
172
+ const counter = new LoopsComponent(components.loopsComponent);
173
+
174
+ await t.run(async (ctx) => {
175
+ await counter.add(ctx, "test");
176
+ const count = await counter.count(ctx, "test");
177
+ expect(count).toBe(1);
178
+ });
179
+ });
180
+ ```
181
+
182
+ **Key difference**: Client tests use `t.registerComponent()` to mount the component within the test environment, simulating the real app usage pattern.
183
+
184
+ ### Example App Frontend
185
+ The example app uses **Bun.serve** with HTML imports for a lightweight development experience.
186
+
187
+ **Architecture**:
188
+ - `example/src/index.tsx` - Bun server that serves HTML with hot reload
189
+ - `example/src/frontend.tsx` - React entry point that bootstraps the app
190
+ - `example/src/App.tsx` - Main React component using the component hooks
191
+
192
+ **Key features**:
193
+ - HTML files can directly import `.tsx` files (no bundler config needed)
194
+ - Hot module reloading via `bun --hot`
195
+ - Tailwind CSS via `bun-plugin-tailwind`
196
+ - Convex environment variables automatically passed through
197
+
198
+ **Running the frontend**:
199
+ ```sh
200
+ bun run dev:frontend # or: cd example && bun --hot src/index.tsx
201
+ ```
202
+
203
+ ## Code Style
204
+
205
+ ### Biome Configuration
206
+ - **Indentation**: Tabs (not spaces)
207
+ - **Quotes**: Double quotes for JavaScript/TypeScript
208
+ - **Imports**: Auto-organized via Biome assist
209
+ - **Ignores**: `_generated` directories are excluded from linting/formatting
210
+
211
+ ### TypeScript Configuration
212
+ - Strict mode enabled with additional checks:
213
+ - `noUncheckedIndexedAccess: true`
214
+ - `noImplicitOverride: true`
215
+ - `noFallthroughCasesInSwitch: true`
216
+ - Module resolution: `bundler` mode
217
+ - JSX: `react-jsx` (automatic runtime)
218
+
219
+ ## Package Exports Configuration
220
+
221
+ The `package.json` defines three entry points using conditional exports:
222
+
223
+ ```json
224
+ {
225
+ "exports": {
226
+ ".": {
227
+ "@convex-dev/component-source": "./src/client/index.ts",
228
+ "types": "./dist/client/index.d.ts",
229
+ "default": "./dist/client/index.js"
230
+ },
231
+ "./convex.config": {
232
+ "@convex-dev/component-source": "./src/component/convex.config.ts",
233
+ "types": "./dist/component/convex.config.d.ts",
234
+ "default": "./dist/component/convex.config.js"
235
+ },
236
+ "./react": {
237
+ "@convex-dev/component-source": "./src/react/index.ts",
238
+ "types": "./dist/react/index.d.ts",
239
+ "default": "./dist/react/index.js"
240
+ }
241
+ }
242
+ }
243
+ ```
244
+
245
+ **`@convex-dev/component-source` condition**:
246
+ - Used during development with `--live-component-sources` flag
247
+ - Points directly to TypeScript source files for hot reloading
248
+ - Bypasses the built `dist/` directory for faster iteration
249
+
250
+ **Why this matters**:
251
+ - Production: Apps install the package and use built `.js` files from `dist/`
252
+ - Development: The `--live-component-sources` flag makes Convex use `.ts` files directly
253
+ - Type checking: TypeScript uses the `.d.ts` files from `dist/`
254
+
255
+ ## Important Notes
256
+
257
+ - **Generated files**: Never edit files in `_generated/` directories - they are auto-generated by Convex
258
+ - **Test files**: Place all test files in `test/component/` or `test/client/` directories (separate from `src/`) to prevent Convex from bundling them during development
259
+ - **Component name**: Currently set to `"loopsComponent"` in convex.config.ts - change this for your component
260
+ - **Live reloading**: The `--live-component-sources` flag enables hot-reloading during development
261
+ - **Build exclusion**: Test files are excluded from the TypeScript build via `tsconfig.build.json`
262
+ - **Client vs Component**: Remember that `src/client/` runs in the app context and can access env vars, while `src/component/` is isolated
263
+
264
+ ## Release Workflow (Changesets)
265
+
266
+ This project uses [Changesets](https://github.com/changesets/changesets) for versioning and publishing automation.
267
+
268
+ ### When to Add a Changeset
269
+
270
+ Add a changeset whenever you make user-facing changes:
271
+ - ✅ New features (minor bump)
272
+ - ✅ Bug fixes (patch bump)
273
+ - ✅ Breaking changes (major bump)
274
+ - ✅ API changes
275
+ - ✅ Dependency updates that affect consumers
276
+
277
+ Don't add a changeset for:
278
+ - ❌ Documentation-only changes
279
+ - ❌ Test-only changes
280
+ - ❌ Internal refactoring with no API changes
281
+ - ❌ CI/build configuration updates
282
+ - ❌ Dev dependency updates
283
+
284
+ ### Adding a Changeset (For Contributors)
285
+
286
+ 1. Make your code changes
287
+ 2. Run the changeset command:
288
+ ```sh
289
+ bun run changeset
290
+ ```
291
+ 3. Follow the prompts:
292
+ - Select version bump type (patch, minor, or major)
293
+ - Write a summary of your changes
294
+ 4. A markdown file will be created in `.changeset/` directory
295
+ 5. Commit both your code changes AND the changeset file:
296
+ ```sh
297
+ git add .
298
+ git commit -m "feat: your feature description"
299
+ ```
300
+
301
+ **Changeset Summary Guidelines:**
302
+ - Write clear, concise descriptions
303
+ - Focus on **what** changed and **why**
304
+ - Include migration instructions for breaking changes
305
+ - Use markdown formatting for readability
306
+
307
+ **Example changeset file** (`.changeset/brave-lions-dance.md`):
308
+ ```markdown
309
+ ---
310
+ "robertalv/loops-component": minor
311
+ ---
312
+
313
+ Added `useResetCounter` hook for resetting counter values.
314
+
315
+ You can now reset counters to zero:
316
+ \`\`\`tsx
317
+ const resetCounter = useResetCounter();
318
+ await resetCounter("myCounter");
319
+ \`\`\`
320
+ ```
321
+
322
+ ### Automated Release Process
323
+
324
+ The release workflow is fully automated via GitHub Actions:
325
+
326
+ 1. **Developer adds changeset** and pushes to a feature branch
327
+ 2. **PR is created** → `test-and-lint.yml` workflow runs
328
+ 3. **PR is merged to main** → `release.yml` workflow runs
329
+ 4. **Release workflow detects changesets** and creates a "Version Packages" PR
330
+ 5. **Version PR is reviewed** → Check version bumps and CHANGELOG updates
331
+ 6. **Version PR is merged** → Package is automatically published to npm
332
+ 7. **GitHub release is created** with release notes
333
+
334
+ ### Manual Release (If Needed)
335
+
336
+ If you need to publish manually (bypassing automation):
337
+
338
+ ```sh
339
+ # 1. Update versions and changelogs from all changesets
340
+ bun run ci:version
341
+
342
+ # 2. Review changes to package.json and CHANGELOG.md
343
+ git diff
344
+
345
+ # 3. Commit the version changes
346
+ git add .
347
+ git commit -m "chore: version packages"
348
+ git push
349
+
350
+ # 4. Publish to npm (runs tests, build, and validation)
351
+ bun run ci:publish
352
+ ```
353
+
354
+ ### Configuration Files
355
+
356
+ - **`.changeset/config.json`**: Changesets configuration
357
+ - `access: "public"` - Package is published publicly to npm
358
+ - `changelog: "@changesets/changelog-github"` - Generates changelogs with PR links and contributor attribution
359
+ - `baseBranch: "main"` - Git branch for comparisons
360
+
361
+ - **`.github/workflows/release.yml`**: GitHub Actions workflow for automated releases
362
+ - Triggers on push to `main` branch
363
+ - Creates version PRs when changesets exist
364
+ - Publishes to npm when version PR is merged
365
+ - Requires `NPM_TOKEN` secret in repository settings
366
+
367
+ ### Setting Up NPM Publishing (One-Time Setup)
368
+
369
+ For the automated release workflow to publish packages, you need to configure an npm token:
370
+
371
+ 1. Go to [npmjs.com](https://npmjs.com) → Account Settings → Access Tokens
372
+ 2. Generate a new **Automation** token (bypasses 2FA for CI/CD)
373
+ 3. Copy the token
374
+ 4. In GitHub repository: Settings → Secrets and variables → Actions
375
+ 5. Create new secret named `NPM_TOKEN` with the token value
376
+ 6. Ensure GitHub Actions has write permissions:
377
+ - Settings → Actions → General → Workflow permissions
378
+ - Select "Read and write permissions"
379
+ - Check "Allow GitHub Actions to create and approve pull requests"
380
+
381
+ ### Viewing Published Versions
382
+
383
+ After publishing:
384
+ - **npm**: `https://www.npmjs.com/package/robertalv/loops-component`
385
+ - **GitHub Releases**: `https://github.com/robertalv/loops-component/releases`
386
+ - **Changelog**: `CHANGELOG.md` in the repository root
387
+
388
+ ### Troubleshooting
389
+
390
+ **Changesets not detected?**
391
+ - Ensure `.changeset/` files are committed and pushed
392
+ - Check that changeset files have `.md` extension
393
+ - Verify YAML frontmatter is properly formatted
394
+
395
+ **Version PR not created?**
396
+ - Check GitHub Actions tab for workflow errors
397
+ - Ensure `GITHUB_TOKEN` has sufficient permissions
398
+ - Verify no merge conflicts in the version PR
399
+
400
+ **Publishing failed?**
401
+ - Verify `NPM_TOKEN` is correctly set in repository secrets
402
+ - Check npm token hasn't expired (max 90 days for granular tokens)
403
+ - Ensure package name isn't already taken on npm
404
+ - Run `bun run preversion` locally to catch test/lint failures
405
+
406
+ **Multiple changesets in one PR?**
407
+ - This is fine! All changesets will be consolidated in the version PR
408
+ - Each changeset contributes to the overall version bump (highest semver wins)
@@ -0,0 +1,274 @@
1
+ # Contributing to Convex Component Template
2
+
3
+ Thank you for your interest in contributing! This document provides guidelines and instructions for contributing to this project.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Code of Conduct](#code-of-conduct)
8
+ - [Getting Started](#getting-started)
9
+ - [Development Workflow](#development-workflow)
10
+ - [Coding Standards](#coding-standards)
11
+ - [Testing](#testing)
12
+ - [Submitting Changes](#submitting-changes)
13
+ - [Release Process](#release-process)
14
+
15
+ ## Code of Conduct
16
+
17
+ By participating in this project, you agree to maintain a respectful and inclusive environment for all contributors.
18
+
19
+ ## Getting Started
20
+
21
+ ### Prerequisites
22
+
23
+ - **Bun** (latest stable version)
24
+ - **Node.js** 18+ (for Convex CLI)
25
+ - **Git**
26
+
27
+ ### Setup
28
+
29
+ 1. Fork the repository on GitHub
30
+ 2. Clone your fork locally:
31
+ ```sh
32
+ git clone https://github.com/SamHoque/convex-component-template.git
33
+ cd convex-component-template
34
+ ```
35
+
36
+ 3. Install dependencies:
37
+ ```sh
38
+ bun install
39
+ ```
40
+
41
+ 4. Set up your Convex dev environment:
42
+ ```sh
43
+ bun run dev:backend
44
+ ```
45
+
46
+ 5. In another terminal, run the example app:
47
+ ```sh
48
+ bun run dev:frontend
49
+ ```
50
+
51
+ ## Development Workflow
52
+
53
+ ### Running the Dev Environment
54
+
55
+ The project uses a multi-process development setup:
56
+
57
+ ```sh
58
+ # Start all dev processes (backend, frontend, build watch)
59
+ bun run dev
60
+
61
+ # Or run individually:
62
+ bun run dev:backend # Convex dev server with live component sources
63
+ bun run dev:frontend # Example app with hot reload
64
+ bun run build:watch # TypeScript build in watch mode
65
+ ```
66
+
67
+ ### Making Changes
68
+
69
+ 1. Create a new branch for your feature or bugfix:
70
+ ```sh
71
+ git checkout -b feature/your-feature-name
72
+ ```
73
+
74
+ 2. Make your changes following the [coding standards](#coding-standards)
75
+
76
+ 3. Add tests for your changes in `test/component/`
77
+
78
+ 4. Run the test suite:
79
+ ```sh
80
+ bun test
81
+ ```
82
+
83
+ 5. Run linting and formatting:
84
+ ```sh
85
+ bun run check:fix
86
+ ```
87
+
88
+ 6. Commit your changes with a descriptive message following [Conventional Commits](https://www.conventionalcommits.org/):
89
+ ```sh
90
+ git commit -m "feat: add new counter increment limit"
91
+ ```
92
+
93
+ ### Commit Message Format
94
+
95
+ We use conventional commit messages with gitmoji:
96
+
97
+ - `✨ feat:` - New features
98
+ - `🐛 fix:` - Bug fixes
99
+ - `📝 docs:` - Documentation changes
100
+ - `🎨 style:` - Code style/formatting changes
101
+ - `♻️ refactor:` - Code refactoring
102
+ - `✅ test:` - Test additions or updates
103
+ - `🔧 chore:` - Build process or auxiliary tool changes
104
+ - `⚡️ perf:` - Performance improvements
105
+ - `👷 ci:` - CI/CD changes
106
+
107
+ ## Coding Standards
108
+
109
+ ### TypeScript
110
+
111
+ - Use **strict mode** TypeScript
112
+ - Enable all recommended checks
113
+ - Avoid `any` types - use proper typing
114
+ - Use `const` over `let` where possible
115
+
116
+ ### Code Style
117
+
118
+ We use **Biome** for linting and formatting:
119
+
120
+ - **Indentation**: Tabs (not spaces)
121
+ - **Quotes**: Double quotes for strings
122
+ - **Line length**: 100 characters (recommended)
123
+ - **Semicolons**: Required
124
+
125
+ Run the following before committing:
126
+
127
+ ```sh
128
+ # Check for issues
129
+ bun run check
130
+
131
+ # Auto-fix issues
132
+ bun run check:fix
133
+ ```
134
+
135
+ ### File Organization
136
+
137
+ - **Component source**: `src/component/`
138
+ - **Tests**: `test/component/` (separate from source to avoid bundling)
139
+ - **React hooks**: `src/react/`
140
+ - **Client utilities**: `src/client/`
141
+ - **Example app**: `example/`
142
+
143
+ ### Naming Conventions
144
+
145
+ - **Files**: camelCase for source files, kebab-case for config files
146
+ - **Functions**: camelCase
147
+ - **Components**: PascalCase (React)
148
+ - **Constants**: UPPER_SNAKE_CASE
149
+ - **Types/Interfaces**: PascalCase
150
+
151
+ ## Testing
152
+
153
+ ### Writing Tests
154
+
155
+ Place all test files in `test/component/` directory:
156
+
157
+ ```typescript
158
+ import { test, expect } from "bun:test";
159
+ import { api } from "../../src/component/_generated/api";
160
+ import { convexTest } from "./setup.test";
161
+
162
+ test("my query works", async () => {
163
+ const t = convexTest();
164
+ const result = await t.query(api.lib.myQuery, { arg: "value" });
165
+ expect(result).toBe("expected");
166
+ });
167
+ ```
168
+
169
+ ### Running Tests
170
+
171
+ ```sh
172
+ # Run all tests
173
+ bun test
174
+
175
+ # Watch mode
176
+ bun test --watch
177
+
178
+ # With coverage
179
+ bun test --coverage
180
+
181
+ # Filter by name
182
+ bun test -t "pattern"
183
+
184
+ # Stop on first failure
185
+ bun test --bail
186
+ ```
187
+
188
+ ### Testing Authenticated Scenarios
189
+
190
+ ```typescript
191
+ test("authenticated query", async () => {
192
+ const t = convexTest();
193
+ const asUser = t.withIdentity({ subject: "user123" });
194
+ const result = await asUser.query(api.lib.userQuery, {});
195
+ expect(result).toBeDefined();
196
+ });
197
+ ```
198
+
199
+ ## Submitting Changes
200
+
201
+ ### Pull Request Process
202
+
203
+ 1. Ensure all tests pass: `bun test`
204
+ 2. Ensure linting passes: `bun run check`
205
+ 3. Ensure TypeScript compiles: `bun run typecheck`
206
+ 4. Ensure package exports are correct: `bun run attw`
207
+ 5. Update documentation if needed
208
+ 6. Push your branch to your fork
209
+ 7. Open a Pull Request against the `main` branch
210
+ 8. Fill out the PR template with:
211
+ - Description of changes
212
+ - Related issue numbers
213
+ - Testing performed
214
+ - Breaking changes (if any)
215
+
216
+ ### PR Review Process
217
+
218
+ - At least one maintainer approval is required
219
+ - All CI checks must pass
220
+ - Code must follow the project's coding standards
221
+ - Tests must be included for new features
222
+
223
+ ### What Happens After Your PR is Merged
224
+
225
+ - Your changes will be included in the next release
226
+ - The CHANGELOG will be updated
227
+ - You'll be credited as a contributor
228
+
229
+ ## Release Process
230
+
231
+ This section is for maintainers.
232
+
233
+ ### Version Bumping
234
+
235
+ The project uses npm version scripts:
236
+
237
+ ```sh
238
+ # Alpha release (pre-release)
239
+ bun run alpha
240
+
241
+ # Patch release (0.1.0 -> 0.1.1)
242
+ bun run release
243
+
244
+ # Manual version bump
245
+ npm version [major|minor|patch]
246
+ ```
247
+
248
+ ### What Happens During Release
249
+
250
+ 1. `preversion`: Runs tests, linting, typecheck, and package validation
251
+ 2. `version`: Updates version, opens CHANGELOG.md for editing, formats it
252
+ 3. `postversion`: Pushes changes and tags to GitHub
253
+
254
+ ### Publishing
255
+
256
+ Publishing happens automatically after version bump:
257
+
258
+ ```sh
259
+ # For alpha releases
260
+ npm publish --tag alpha
261
+
262
+ # For stable releases
263
+ npm publish
264
+ ```
265
+
266
+ ## Questions?
267
+
268
+ If you have questions, please:
269
+
270
+ - Check existing issues and discussions
271
+ - Open a new issue for bugs
272
+ - Start a discussion for questions
273
+
274
+ Thank you for contributing!