Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/PULL_REQUEST_TEMPLATE.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

## Validation

- [ ] `pnpm check`
- [ ] `pnpm verify`
- [ ] `pnpm docs:index` was run if docs changed
- [ ] Relevant tests or manual verification

## Release notes
Expand Down
207 changes: 36 additions & 171 deletions AGENTS.md
Original file line number Diff line number Diff line change
@@ -1,171 +1,36 @@
# Ultracite Code Standards

This project uses **Ultracite**, a zero-config preset that enforces strict code quality standards through automated formatting and linting.

## Quick Reference

- **Format code**: `pnpm dlx ultracite fix`
- **Check for issues**: `pnpm dlx ultracite check`
- **Diagnose setup**: `pnpm dlx ultracite doctor`

Biome (the underlying engine) provides robust linting and formatting. Most issues are automatically fixable.

---

## Core Principles

Write code that is **accessible, performant, type-safe, and maintainable**. Focus on clarity and explicit intent over brevity.

### Type Safety & Explicitness

- Use explicit types for function parameters and return values when they enhance clarity
- Prefer `unknown` over `any` when the type is genuinely unknown
- Use const assertions (`as const`) for immutable values and literal types
- Leverage TypeScript's type narrowing instead of type assertions
- Use meaningful variable names instead of magic numbers - extract constants with descriptive names

### Modern JavaScript/TypeScript

- Use arrow functions for callbacks and short functions
- Prefer `for...of` loops over `.forEach()` and indexed `for` loops
- Use optional chaining (`?.`) and nullish coalescing (`??`) for safer property access
- Prefer template literals over string concatenation
- Use destructuring for object and array assignments
- Use `const` by default, `let` only when reassignment is needed, never `var`

### Async & Promises

- Always `await` promises in async functions - don't forget to use the return value
- Use `async/await` syntax instead of promise chains for better readability
- Handle errors appropriately in async code with try-catch blocks
- Don't use async functions as Promise executors

### React & JSX

- Use function components over class components
- Call hooks at the top level only, never conditionally
- Specify all dependencies in hook dependency arrays correctly
- Use the `key` prop for elements in iterables (prefer unique IDs over array indices)
- Nest children between opening and closing tags instead of passing as props
- Don't define components inside other components
- Use semantic HTML and ARIA attributes for accessibility:
- Provide meaningful alt text for images
- Use proper heading hierarchy
- Add labels for form inputs
- Include keyboard event handlers alongside mouse events
- Use semantic elements (`<button>`, `<nav>`, etc.) instead of divs with roles

### Error Handling & Debugging

- Remove `console.log`, `debugger`, and `alert` statements from production code
- Throw `Error` objects with descriptive messages, not strings or other values
- Use `try-catch` blocks meaningfully - don't catch errors just to rethrow them
- Prefer early returns over nested conditionals for error cases

### Code Organization

- Keep functions focused and under reasonable cognitive complexity limits
- Extract complex conditions into well-named boolean variables
- Use early returns to reduce nesting
- Prefer simple conditionals over nested ternary operators
- Group related code together and separate concerns

### Security

- Add `rel="noopener"` when using `target="_blank"` on links
- Avoid `dangerouslySetInnerHTML` unless absolutely necessary
- Don't use `eval()` or assign directly to `document.cookie`
- Validate and sanitize user input

### Performance

- Avoid spread syntax in accumulators within loops
- Use top-level regex literals instead of creating them in loops
- Prefer specific imports over namespace imports
- Avoid barrel files (index files that re-export everything)
- Use proper image components (e.g., Next.js `<Image>`) over `<img>` tags

### Framework-Specific Guidance

**Next.js:**
- Use Next.js `<Image>` component for images
- Use `next/head` or App Router metadata API for head elements
- Use Server Components for async data fetching instead of async Client Components

**React 19+:**
- Use ref as a prop instead of `React.forwardRef`

**Solid/Svelte/Vue/Qwik:**
- Use `class` and `for` attributes (not `className` or `htmlFor`)

---

## Testing

- Write assertions inside `it()` or `test()` blocks
- Avoid done callbacks in async tests - use async/await instead
- Don't use `.only` or `.skip` in committed code
- Keep test suites reasonably flat - avoid excessive `describe` nesting

## When Biome Can't Help

Biome's linter will catch most issues automatically. Focus your attention on:

1. **Business logic correctness** - Biome can't validate your algorithms
2. **Meaningful naming** - Use descriptive names for functions, variables, and types
3. **Architecture decisions** - Component structure, data flow, and API design
4. **Edge cases** - Handle boundary conditions and error states
5. **User experience** - Accessibility, performance, and usability considerations
6. **Documentation** - Add comments for complex logic, but prefer self-documenting code

---

Most formatting and common issues are automatically fixed by Biome. Run `pnpm dlx ultracite fix` before committing to ensure compliance.

---

## Cursor Cloud specific instructions

### Services overview

This is a Turborepo monorepo with deployable Next.js apps and local-only email/video workspaces.

- **Dev servers**: `pnpm dev:app` → http://localhost:3000, `pnpm dev:api` → http://localhost:3001, `pnpm dev:web` → http://localhost:3002, `pnpm dev:email` → http://localhost:3004, `pnpm dev:video` → http://localhost:3005
- **Database**: Remote Neon Postgres via `DATABASE_URL` (no local DB required). Use `@outname/db` (`pg` + `attachDatabasePool` per [Neon + Vercel connection methods](https://neon.com/docs/guides/vercel-connection-methods)). Use Neon's pooled connection string (hostname includes `-pooler`). In the session workflow codepath, prefer normal static imports even for step-oriented modules that touch `@outname/db` or server helpers. Keep `await import(...)` only when you truly want optional-path lazy loading or package/runtime-local loading (for example the optional child-trace path or `bash-tool` package loading).
- **Lint**: `pnpm lint` (Ultracite/Biome)
- **Format**: `pnpm fix` (auto-fix lint/format issues)

### Environment variables

Required secrets are injected automatically. A `.env.local` must exist for Next.js to read them at runtime. Create it with:

```
DATABASE_URL=<from env>
BETTER_AUTH_SECRET=<from env>
BETTER_AUTH_URL=http://localhost:3001
BETTER_AUTH_TRUSTED_ORIGINS=http://localhost:3000,http://localhost:3001,http://localhost:3002
AUTH_COOKIE_DOMAIN=
CONNECTION_ENCRYPTION_KEY=<from env>
APP_REVALIDATION_SECRET=<from env>
VERCEL_API_PROJECT_ID=
VERCEL_APP_PROJECT_ID=
VERCEL_WEB_PROJECT_ID=
SANDBOX_TEAM_ID=<from env>
SANDBOX_PROJECT_ID=<from env>
SANDBOX_ACCESS_TOKEN=<from env>
RESEND_API_KEY=<from env>
AUTH_FROM_EMAIL=<verified sender>
AUTH_REPLY_TO=<verified reply-to sender>
WAITLIST_FROM_EMAIL=<verified sender for waitlist emails>
WAITLIST_REPLY_TO=<reply-to sender for waitlist emails>
WAITLIST_ADMIN_EMAIL=<admin inbox for new waitlist signup notifications>
```

### Known caveats

- **Sign-up is disabled** at the Better Auth level (`packages/auth/server/auth.ts`); new users are provisioned from the waitlist and sign in with email OTP codes. The data model is multi-user — every user-owned table is scoped by `user_id` and routes verify ownership. Use a provisioned address such as `TEST_USER_EMAIL` to request a login code in dev.
- **Dev sign-in flow**: Request an OTP via `POST /api/auth/request-otp` with `{"email":"<existing-user>"}`, then read the code from the `verification` table (`SELECT value FROM verification ORDER BY "createdAt" DESC LIMIT 1` — the OTP is the part before the `:`). Submit it to `POST /api/auth/sign-in/email-otp` with `{"email":"...","otp":"..."}` to get a `better-auth.session_token` cookie. Existing test users can be found with `SELECT email FROM "user" LIMIT 5`.
- **`drizzle-kit push`** requires a TTY for confirmation prompts. Use `drizzle-kit push --force` or run interactively if schema changes are needed.
- **Do not commit `pnpm-workspace.yaml` allow-build overrides.** They make the production build fail in this app.
- **UI/auth changes should be tested manually** via the browser. There is no comprehensive automated product test suite for waitlist and authentication flows.
- **Running `pnpm test`** requires `DATABASE_URL` to be set in the environment. Export it before running tests or source it from `.env.local`. Some test files import `@outname/db` which throws at module load time if the variable is missing.
# Agent Rules

Keep this file minimal. Put feature knowledge in `docs/<feature>/` and keep
tool-specific preferences out unless they are hard project constraints.

## Documentation

- Every feature document lives under a feature folder in `docs/`.
- Non-index markdown files under `docs/` must stay at 30 lines or fewer.
- Generated `index.md` files may exceed 30 lines when needed for navigation.
- If a docs folder has more than one markdown file, it must have `index.md`.
- `docs/index.md` and folder indexes are generated; update source docs, then run
`pnpm docs:index` instead of hand-editing generated indexes.

## Runtime Caveats

- The database is remote Neon Postgres through `DATABASE_URL`; no local Postgres
is expected. Use the pooled Neon hostname containing `-pooler`.
- Next.js needs `.env.local` at runtime even when secrets are injected by the
environment.
- In session workflow codepaths, prefer static imports for modules touching
`@outname/db` or server helpers. Use dynamic imports only for truly optional
runtime-local paths.
- Public sign-up is disabled in Better Auth. Dev users are provisioned from the
waitlist and sign in with email OTP codes.
- For dev OTP login, request `/api/auth/request-otp`, read the newest
`verification.value`, then submit the code before `:` to
`/api/auth/sign-in/email-otp`.
- `drizzle-kit push` prompts for confirmation unless run with `--force` or an
interactive TTY.
- Do not commit `pnpm-workspace.yaml` allow-build overrides; they break
production builds.
- UI and auth changes need manual browser verification because there is no full
product test suite for those flows.
- `pnpm test` imports database-backed modules; set `DATABASE_URL` first or source
`.env.local`.
8 changes: 4 additions & 4 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ Thanks for your interest in improving `outname`.

1. Read `README.md` for the product overview and setup steps.
2. Read `.env.example` and create `.env.local` for local development.
3. Read `docs/ARCHITECTURE.md` if your change touches runtime behavior,
integrations, or data flow.
3. Read `docs/index.md`; for runtime changes, start with the agent events,
realtime turns, scheduler, tools, and channel feature docs.

## Local setup

Expand Down Expand Up @@ -47,8 +47,8 @@ request:
pnpm verify
```

`pnpm verify` runs the workflow boundary check plus `build`, `typecheck`,
`lint`, and `react-doctor` across the monorepo.
`pnpm verify` runs the docs check plus `build`, `typecheck`, `lint`, and
`react-doctor` across the monorepo.

If you changed TypeScript runtime code, also run:

Expand Down
31 changes: 17 additions & 14 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
[![Turborepo](https://img.shields.io/badge/Turborepo-000000?style=flat-square&logo=turborepo&logoColor=EF4444)](https://turbo.build)
[![PRs welcome](https://img.shields.io/badge/PRs-welcome-ff3000?style=flat-square&labelColor=000000)](CONTRIBUTING.md)

**[Website](https://outna.me)** · **[Quick start](#-quick-start)** · **[How it works](#-how-it-works)** · **[Architecture](docs/ARCHITECTURE.md)** · **[Contributing](CONTRIBUTING.md)** · **[X / Twitter](https://x.com/OutnameBot)**
**[Website](https://outna.me)** · **[Quick start](#-quick-start)** · **[How it works](#-how-it-works)** · **[Docs](docs/index.md)** · **[Contributing](CONTRIBUTING.md)** · **[X / Twitter](https://x.com/OutnameBot)**

</div>

Expand Down Expand Up @@ -145,8 +145,8 @@ flowchart LR
WF --> Tools[Tools and Skills]
```

See **[docs/ARCHITECTURE.md](docs/ARCHITECTURE.md)** for runtime boundaries, the
event model, and the full request/event flow.
See **[docs/index.md](docs/index.md)** for generated, feature-focused docs,
including runtime boundaries, event flow, tools, channels, and data ownership.

## 🧱 Tech stack

Expand Down Expand Up @@ -184,7 +184,7 @@ outname/
│ ├─ shared/ # Shared domain, marketing, and server utilities
│ ├─ ui/ # Design system (Radix + shadcn)
│ └─ workflow/ # Workflow helpers
└─ docs/ # Architecture + ADRs
└─ docs/ # Generated feature index, feature notes, and ADRs
```

## 🚀 Quick start
Expand Down Expand Up @@ -273,8 +273,10 @@ pnpm dev:video # Remotion Studio (:3005)
pnpm build # Build all workspaces
pnpm lint # Lint (Ultracite / Biome)
pnpm typecheck # Type-check
pnpm verify # Lint + typecheck + tests
pnpm verify # Docs check + build + typecheck + lint + react-doctor
pnpm fix # Auto-fix lint/format issues
pnpm docs:index # Regenerate docs indexes
pnpm docs:check # Validate docs indexes and non-index markdown line limit

pnpm db:generate # Generate Drizzle migrations
pnpm db:migrate # Apply migrations
Expand All @@ -283,15 +285,16 @@ pnpm db:studio # Open Drizzle Studio

## 📚 Documentation

| Document | What's inside |
| ------------------------------------------------------------- | ------------------------------------------ |
| [docs/ARCHITECTURE.md](docs/ARCHITECTURE.md) | System architecture and runtime boundaries |
| [docs/adr/](docs/adr) | Architecture Decision Records |
| [docs/SLACK_INTEGRATION.md](docs/SLACK_INTEGRATION.md) | Slack setup and integration |
| [AGENTS.md](AGENTS.md) | Code standards and local dev notes |
| [CONTRIBUTING.md](CONTRIBUTING.md) | Contributor workflow and quality checks |
| [SECURITY.md](SECURITY.md) | Vulnerability disclosure process |
| [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md) | Community expectations |
Start at **[docs/index.md](docs/index.md)**. Feature docs live in
`docs/<feature>/`, stay under 30 lines per non-index markdown file, and are
linked through generated indexes.

Other project guidance:

- **[AGENTS.md](AGENTS.md)**: non-inferable rules for coding agents.
- **[CONTRIBUTING.md](CONTRIBUTING.md)**: contributor workflow.
- **[SECURITY.md](SECURITY.md)**: vulnerability disclosure.
- **[CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)**: community expectations.

## 🤝 Contributing

Expand Down
Loading