Skip to main content

Overview

Arre uses Cloud Firestore as its primary database. Data is organized by user, with each user having their own sub-collections for tasks, projects, and integrations.

Data Structure

The database follows a hierarchical structure with user isolation:
/users/{userId}
  ├── /tasks/{taskId}
  ├── /projects/{projectId}
  └── /integrations/{integrationId}
All user data is isolated under /users/{userId} to ensure proper access control via security rules.

Collections

Tasks Collection

The tasks collection stores all user task data with status tracking, scheduling, and project associations.

TaskDocument Interface

Defined in src/lib/types/firestore.ts:
src/lib/types/firestore.ts
import { Timestamp } from 'firebase/firestore';
import { TaskStatus } from '../../shared/types/task';

export interface TaskDocument {
  id: string;              // Document ID
  title: string;           // Task title (required)
  notes?: string;          // Optional task notes/description
  status: TaskStatus;      // 'todo' | 'completed' | 'canceled' | 'someday'
  date?: string;           // YYYY-MM-DD string for scheduled date
  isEvening?: boolean;     // Flag for "This Evening" feature
  energy?: 'low' | 'neutral' | 'high';  // Energy level estimate
  tags?: string[];         // Array of tag strings
  projectId?: string;      // Reference to associated project
  createdAt: Timestamp;    // Firestore server timestamp
  completedAt?: Timestamp; // Timestamp when task was completed
  updatedAt: Timestamp;    // Last modification timestamp
}

Field Details

id
string
required
Unique document identifier. Matches the Firestore document ID.
title
string
required
Task title. Must be non-empty string (validated by security rules).
notes
string
Additional task description or notes. Supports markdown formatting in the UI.
status
TaskStatus
required
Current task status. Must be one of: 'todo', 'completed', 'canceled', 'someday'
date
string
Scheduled date in YYYY-MM-DD format. Used for daily planning and filtering.
isEvening
boolean
Marks task for “This Evening” planning feature. Used in conjunction with date.
energy
'low' | 'neutral' | 'high'
Estimated energy level required for the task. Used for smart scheduling.
tags
string[]
Array of tag strings for categorization. Frontend suggests common tags.
projectId
string
Foreign key reference to a project document ID. Must exist in user’s projects collection.
createdAt
Timestamp
required
Firestore server timestamp set on document creation.
completedAt
Timestamp
Timestamp when task status changed to 'completed'. Used for analytics.
updatedAt
Timestamp
required
Firestore server timestamp updated on every document modification.

TaskStatus Type

src/shared/types/task.ts
export type TaskStatus = 'todo' | 'completed' | 'canceled' | 'someday';

Projects Collection

Projects organize tasks into categories with visual color coding.

ProjectDocument Interface

src/lib/types/firestore.ts
export interface ProjectDocument {
  id: string;      // Document ID
  title: string;   // Project name (required)
  color: string;   // Hex color code or color name
  order: number;   // Display order in UI
}

Field Details

id
string
required
Unique project identifier matching the Firestore document ID.
title
string
required
Project name. Must be non-empty (validated by security rules).
color
string
required
Color identifier. Can be a hex code (#10b981) or color name from the predefined palette.
order
number
required
Numeric ordering for display. Lower numbers appear first in the UI.

Available Project Colors

src/shared/types/task.ts
export const PROJECT_COLORS = [
  { name: 'emerald', hex: '#10b981', label: 'Emerald' },
  { name: 'sapphire', hex: '#2563eb', label: 'Sapphire' },
  { name: 'ruby', hex: '#dc2626', label: 'Ruby' },
  { name: 'lavender', hex: '#7c3aed', label: 'Lavender' },
  { name: 'gold', hex: '#f59e0b', label: 'Gold' },
  { name: 'cyan', hex: '#06b6d4', label: 'Cyan' },
  { name: 'rose', hex: '#f43f5e', label: 'Rose' },
  { name: 'amber', hex: '#d97706', label: 'Amber' },
  { name: 'teal', hex: '#14b8a6', label: 'Teal' },
  { name: 'indigo', hex: '#6366f1', label: 'Indigo' },
] as const;

Integrations Collection

Stores OAuth tokens and configuration for third-party integrations (e.g., Google Tasks).
This collection contains sensitive data. Access is strictly limited to the authenticated user via security rules.

Timestamp Handling

Firestore Timestamps vs. ISO Strings

Arre uses different timestamp formats depending on the context:
Uses Firestore Timestamp objects for precise datetime storage:
import { Timestamp, serverTimestamp } from 'firebase/firestore';

const taskData = {
  title: 'New Task',
  createdAt: serverTimestamp(),
  updatedAt: serverTimestamp()
};

Converting Between Formats

// Firestore Timestamp → ISO String
const isoString = timestamp.toDate().toISOString();

// ISO String → Firestore Timestamp
const timestamp = Timestamp.fromDate(new Date(isoString));

// Current server timestamp (preferred for writes)
import { serverTimestamp } from 'firebase/firestore';
const now = serverTimestamp();
Always use serverTimestamp() when writing timestamps to Firestore to ensure consistency across different client time zones.

Query Examples

Fetch User’s Tasks

import { collection, query, where, getDocs } from 'firebase/firestore';
import { db } from './firebase';

const userId = auth.currentUser?.uid;
const tasksRef = collection(db, 'users', userId, 'tasks');

// Get all active tasks
const q = query(tasksRef, where('status', '==', 'todo'));
const snapshot = await getDocs(q);
const tasks = snapshot.docs.map(doc => ({ ...doc.data(), id: doc.id }));

Create a New Task

import { collection, addDoc, serverTimestamp } from 'firebase/firestore';

const tasksRef = collection(db, 'users', userId, 'tasks');

const newTask = await addDoc(tasksRef, {
  title: 'Complete documentation',
  status: 'todo',
  date: '2026-03-05',
  energy: 'neutral',
  createdAt: serverTimestamp(),
  updatedAt: serverTimestamp()
});

console.log('Task created:', newTask.id);

Update Task Status

import { doc, updateDoc, serverTimestamp } from 'firebase/firestore';

const taskRef = doc(db, 'users', userId, 'tasks', taskId);

await updateDoc(taskRef, {
  status: 'completed',
  completedAt: serverTimestamp(),
  updatedAt: serverTimestamp()
});

Best Practices

1

Use Server Timestamps

Always use serverTimestamp() for createdAt and updatedAt fields to avoid client clock skew.
2

Validate Before Writing

Ensure all required fields are present before writing to Firestore. Security rules will reject invalid documents.
3

Handle Subcollection References

When referencing projects via projectId, verify the project exists in the user’s projects collection.
4

Clean Up Orphaned Data

When deleting a project, either update or delete associated tasks to maintain referential integrity.

Next Steps

Cloud Functions

Learn how functions interact with Firestore

Security Rules

Understand how schema is enforced

Build docs developers (and LLMs) love