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 expiredrate_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.
Links
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:
- Copy the example code
- Paste into a test file
- Run it with proper dependencies installed
- 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.