PersonQL Documentation Style Guide


This guide establishes the writing standards and formatting conventions for PersonQL documentation. Consistent documentation helps developers integrate PersonQL quickly and confidently.

Writing Principles

1. Be Clear and Concise

Write in simple, direct language. Avoid jargon unless necessary.

Good:

PersonQL provides passwordless authentication through email OTP, phone OTP, and OAuth providers.

Bad:

PersonQL leverages cutting-edge paradigms to facilitate frictionless authentication experiences through multi-channel verification methodologies.

2. Start with Why, Then How

Explain the purpose before diving into implementation:

## Why Use Anonymous Authentication?

Anonymous authentication lets users try your app without signing up. This reduces friction and increases conversion rates for apps with free features.

## How to Implement Anonymous Auth

```typescript
await personql.auth.signInAnonymously();

### 3. Use Active Voice

Active voice is clearer and more direct than passive voice.

**Good:**
```markdown
PersonQL validates JWT tokens at the edge.

Bad:

JWT tokens are validated at the edge by PersonQL.

4. Show Working Code Examples

Every feature should include a complete, working code example:

// ✅ Complete example - can be copy-pasted
import { PersonQL } from '@personql/react';

const personql = new PersonQL({
  apiKey: 'pk_test_abc123'
});

const user = await personql.auth.signInWithEmail({
  email: 'user@example.com'
});
// ❌ Incomplete example - missing imports and initialization
const user = await signInWithEmail({ email: 'user@example.com' });

Formatting Conventions

Headings

Use hierarchical headings to organize content:

# H1: Document Title (once per page)

## H2: Major Sections

### H3: Subsections

#### H4: Specific Topics

Example:

# Authentication Guide

## Email OTP Authentication

### How Email OTP Works

#### Security Considerations

Code Blocks

Always specify the language for syntax highlighting:

```typescript
// TypeScript code
const user = await personql.auth.signIn();
```

```javascript
// JavaScript code
const user = await personql.auth.signIn();
```

```bash
# Shell commands
npm install @personql/react
```

```json
{
  "config": "value"
}
```

Inline Code

Use backticks for inline code, function names, and variable names:

Call the `signIn()` method with your `apiKey` to authenticate users.

API References

Document APIs consistently:

## `personql.auth.signIn(options)`

Authenticates a user with email and OTP.

**Parameters:**
- `options.email` (string, required): User's email address
- `options.code` (string, required): 6-digit OTP code

**Returns:**
- `Promise<User>`: Authenticated user object

**Example:**
```typescript
const user = await personql.auth.signIn({
  email: 'user@example.com',
  code: '123456'
});

Error Codes:

  • invalid_code: OTP code is incorrect or expired
  • rate_limited: Too many attempts, try again later

### Tables

Use tables for structured comparisons:

```markdown
| Feature | Starter | Professional | Enterprise |
|---------|---------|--------------|------------|
| Monthly Active Users | 1,000 | 10,000 | Unlimited |
| Anonymous Auth | ✅ | ✅ | ✅ |
| Email OTP | ✅ | ✅ | ✅ |
| Phone OTP | ❌ | ✅ | ✅ |
| Custom Domains | ❌ | ❌ | ✅ |

Lists

Use ordered lists for sequential steps:

## Getting Started

1. Sign up for a free account at app.personql.com
2. Get your API key from the dashboard
3. Install the SDK: `npm install @personql/react`
4. Initialize PersonQL with your API key
5. Add authentication to your routes

Use unordered lists for features or options:

PersonQL supports:
- Anonymous authentication
- Email OTP verification
- Phone OTP verification
- Google One Tap
- Multi-tenant organizations
- Role-based access control

Callouts and Alerts

Use blockquotes for important notes:

> **Note:** API keys starting with `pk_test_` are for testing only. Use `pk_live_` keys in production.

> **Warning:** Never expose your API key in client-side code. Use environment variables.

> **Tip:** Enable MFA for sensitive operations to increase security.

Use descriptive link text:

Good:

See the [authentication guide](/docs/authentication) for more details.

Bad:

Click [here](/docs/authentication) for more information.

Code Example Standards

1. Show Imports

Always show necessary imports:

import { PersonQL } from '@personql/react';
import { useAuth, useOrganization } from '@personql/react';

2. Include Error Handling

Demonstrate proper error handling:

try {
  const user = await personql.auth.signIn({
    email: 'user@example.com',
    code: '123456'
  });
  console.log('Signed in:', user.email);
} catch (error) {
  if (error.code === 'invalid_code') {
    console.error('Invalid OTP code');
  } else if (error.code === 'rate_limited') {
    console.error('Too many attempts, try again later');
  } else {
    console.error('Unexpected error:', error);
  }
}

3. Show Real-World Usage

Context matters. Show how code fits into a component:

import React, { useState } from 'react';
import { useAuth } from '@personql/react';

function SignInForm() {
  const { signIn } = useAuth();
  const [email, setEmail] = useState('');
  const [code, setCode] = useState('');
  const [error, setError] = useState('');

  const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();
    try {
      await signIn({ email, code });
    } catch (err) {
      setError(err.message);
    }
  };

  return (
    <form onSubmit={handleSubmit}>
      <input
        type="email"
        value={email}
        onChange={(e) => setEmail(e.target.value)}
        placeholder="Email"
        required
      />
      <input
        type="text"
        value={code}
        onChange={(e) => setCode(e.target.value)}
        placeholder="6-digit code"
        required
      />
      {error && <p className="error">{error}</p>}
      <button type="submit">Sign In</button>
    </form>
  );
}

4. Comment Explanations

Add comments to explain non-obvious code:

// Initialize PersonQL with your API key
const personql = new PersonQL({
  apiKey: process.env.PERSONQL_API_KEY,
  // Optional: Set custom base URL for self-hosted instances
  baseUrl: 'https://auth.yourdomain.com'
});

// Sign in with email OTP (sends verification email)
await personql.auth.sendEmailOTP({
  email: 'user@example.com'
});

// Verify the OTP code (expires after 10 minutes)
const user = await personql.auth.verifyEmailOTP({
  email: 'user@example.com',
  code: '123456'
});

SDK-Specific Conventions

React

Show hooks and components:

import { useAuth, PersonQLProvider } from '@personql/react';

function App() {
  return (
    <PersonQLProvider apiKey="your-api-key">
      <Dashboard />
    </PersonQLProvider>
  );
}

function Dashboard() {
  const { user, signOut } = useAuth();

  if (!user) return <SignIn />;

  return (
    <div>
      <p>Welcome, {user.email}</p>
      <button onClick={signOut}>Sign Out</button>
    </div>
  );
}

Next.js

Show both server and client patterns:

// app/api/auth/route.ts (Server-side)
import { getServerOrganizationContext } from '@personql/nextjs';

export async function GET(req: Request) {
  const context = await getServerOrganizationContext(req);

  if (!context.user) {
    return Response.json({ error: 'Unauthorized' }, { status: 401 });
  }

  return Response.json({ user: context.user });
}
// app/dashboard/page.tsx (Client-side)
'use client';

import { useAuth } from '@personql/nextjs';

export default function Dashboard() {
  const { user } = useAuth();
  return <div>Welcome, {user?.email}</div>;
}

React Native

Show platform-specific features:

import { useAuth } from '@personql/react-native';
import * as LocalAuthentication from 'expo-local-authentication';

function SignInScreen() {
  const { signIn } = useAuth();

  const handleBiometricAuth = async () => {
    const result = await LocalAuthentication.authenticateAsync({
      promptMessage: 'Authenticate to sign in',
      fallbackLabel: 'Use passcode'
    });

    if (result.success) {
      await signIn({ method: 'biometric' });
    }
  };

  return (
    <TouchableOpacity onPress={handleBiometricAuth}>
      <Text>Sign in with Face ID</Text>
    </TouchableOpacity>
  );
}

Documentation Structure

Every guide should follow this structure:

# [Feature Name]

[Brief introduction - what is this feature and why use it?]

## Prerequisites

[What users need before starting]

## Quick Start

[Minimal working example - get users up and running fast]

## How It Works

[Explain the underlying concepts and architecture]

## Integration Guide

[Step-by-step integration instructions]

## Configuration

[Available options and settings]

## API Reference

[Detailed API documentation]

## Examples

[Real-world use cases and code examples]

## Best Practices

[Recommendations for production use]

## Troubleshooting

[Common issues and solutions]

## Related Resources

[Links to related documentation]

Versioning

Indicate SDK version compatibility:

> **SDK Version:** This feature requires `@personql/react` v1.0.2 or higher.

Testing Documentation

All code examples should be tested to ensure they work:

  1. Copy the example code
  2. Paste into a test file
  3. Run it with proper dependencies installed
  4. Verify it produces expected results

Updates and Maintenance

  • Review documentation quarterly for accuracy
  • Update examples when APIs change
  • Add deprecation warnings for old features
  • Keep screenshots and videos current

Contributing to Documentation

See our contribution guide for how to submit documentation improvements.


Following this style guide ensures PersonQL documentation remains clear, consistent, and helpful for developers at all skill levels.

View complete documentation →