System Architecture¶
Complete technical documentation of Skigk Søkeapp's system design.
High-Level Architecture¶
┌─────────────────────────────────────────────────────────────┐
│ Browser / Client │
│ (Angular 20 SPA) │
│ │
│ ┌──────────────────┐ ┌──────────────────────┐ │
│ │ UI Components │ │ Service Layer │ │
│ │ - Search Input │ │ - AuthService │ │
│ │ - File List │ │ - DriveService │ │
│ │ - Summary Panel │ │ - GeminiService │ │
│ └──────────────────┘ └──────────────────────┘ │
└─────────────────────────────────────────────────────────────┘
↓ ↓ ↓
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ Google OAuth │ │ Google Drive API │ │ Google Gemini API│
│ Authorization │ │ File Search │ │ AI Summaries │
│ │ │ File Content │ │ │
└──────────────────┘ └──────────────────┘ └──────────────────┘
↓ ↓ ↓
Google Cloud Platform (APIs)
Component Overview¶
Frontend (Angular 20)¶
app.component.ts - Main application component - Handles search input and state management - Manages search debouncing with RxJS - Displays search results - Triggers AI summarization
Services:
- AuthService (
src/services/auth.service.ts) - Manages Google OAuth 2.0 authentication
- Handles token lifecycle
- Manages user profile
-
Provides logout functionality
-
DriveService (
src/services/drive.service.ts) - Searches files across all Drives
- Retrieves file content
- Exports Google Docs/Sheets to text
-
Handles Drive API errors
-
GeminiService (
src/services/gemini.service.ts) - Calls Google Gemini API
- Generates file summaries
- Handles summarization errors
- Returns formatted summaries
Models:
- DriveFile - Represents a searchable file
- User - Represents authenticated user
Data Flow¶
Search Flow¶
User Types → Input (debounced) → Search Subject
↓
DriveService.searchFiles()
↓
Google Drive API
↓
Files array returned
↓
Display in UI
Summarization Flow¶
User clicks "Get Summary" → GeminiService.summarizeContent()
↓
DriveService.getFileContent()
↓
Google Gemini API
↓
Summary text returned
↓
Display below file
API Specifications¶
Google Drive API¶
Endpoint: https://www.googleapis.com/drive/v3/files
Search Query Parameters:
q=fullText contains '{query}'&
corpora=allDrives&
includeItemsFromAllDrives=true&
supportsAllDrives=true&
pageSize=20
Response:
{
"files": [
{
"id": "file-id",
"name": "Document Name",
"mimeType": "application/vnd.google-apps.document",
"owners": [{"displayName": "John Doe"}],
"modifiedTime": "2026-01-17T10:00:00Z",
"webViewLink": "https://drive.google.com/file/d/{id}/view"
}
]
}
Google Gemini API¶
Endpoint: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
Request:
{
"contents": [{
"parts": [{
"text": "Summarize the following file content:\n\n{content}"
}]
}]
}
Response:
{
"candidates": [{
"content": {
"parts": [{
"text": "Summary of the file..."
}]
}
}]
}
Authentication Flow¶
OAuth 2.0 Authorization Code Flow¶
1. User clicks "Logg inn"
↓
2. Redirect to Google OAuth Consent Screen
↓
3. User authorizes permissions
↓
4. Google redirects with authorization code
↓
5. Client exchanges code for access token
↓
6. Token stored in localStorage
↓
7. Token used for all Drive API requests
Required Scopes:
- https://www.googleapis.com/auth/drive.readonly - Read Drive files
- https://www.googleapis.com/auth/userinfo.profile - Read user profile
- https://www.googleapis.com/auth/spreadsheets.readonly - Read Sheets
State Management¶
Signal-Based (Angular 20):
// Reactive signals in app.component.ts
searchQuery = signal('');
isLoading = signal(false);
isSummarizing = signal(false);
summaries = signal<Map<string, string>>(new Map());
No Redux/NgRx: - Uses Angular's built-in Signals for reactivity - Computed signals for derived state - Effects for side effects (logging, analytics)
Deployment Architecture¶
Firebase Hosting¶
Configuration: firebase.json
{
"hosting": {
"public": "dist",
"rewrites": [
{
"source": "**",
"destination": "/index.html"
}
]
}
}
Benefits: - ✅ Global CDN distribution - ✅ Automatic SSL/HTTPS - ✅ Serverless (no backend needed) - ✅ Built-in analytics - ✅ 99.95% uptime SLA
Build Pipeline¶
Source Code (TypeScript)
↓
Angular Compiler
↓
Optimized JavaScript (minified)
↓
dist/ folder
↓
Firebase Hosting
↓
Global CDN
Security Considerations¶
OAuth Scopes¶
- ✅ Uses drive.readonly - Cannot modify files
- ✅ No delete permissions
- ✅ No write permissions
- ✅ Respects Google Drive permissions
API Keys¶
- ✅ OAuth tokens stored in localStorage
- ✅ Tokens have expiration (1 hour typically)
- ✅ Automatic token refresh
- ✅ No credentials in code
CORS & Origins¶
- ✅ Authorized origins configured in Google Cloud
- ✅ Only allows requests from whitelisted domains
- ✅ Prevents cross-origin attacks
Performance Optimizations¶
Frontend¶
- Search Debouncing - 300ms debounce on input
- Lazy Loading - Results loaded as user scrolls
- Code Splitting - Angular auto-splits bundles
- Caching - Browser caches Drive API responses
Backend (Google APIs)¶
- Page Size - Limited to 20 results per request
- Pagination - User can load more results
- Indexing - Google Drive has built-in indexing
Scalability¶
Current Limits¶
- Users: 100+ concurrent users
- Files Searchable: 1,000,000+ (Google Drive limit)
- Search Speed: <2 seconds typically
- Concurrent Requests: Limited by Google API quotas
Future Scaling¶
For 1,000+ users or enterprise deployments:
- Add Backend Cache:
- Redis for search results
-
Reduces Google API calls
-
Multi-Region Deployment:
- Replicate to multiple Firebase regions
-
Reduce latency globally
-
Database Integration:
- Store search history
- Persist user preferences
-
Analytics and metrics
-
Rate Limiting:
- Per-user quotas
- Prevent API abuse
Technology Stack¶
| Component | Technology | Version |
|---|---|---|
| Frontend Framework | Angular | 20 |
| Language | TypeScript | 5.0+ |
| Styling | Tailwind CSS | 3.0+ |
| State Management | Angular Signals | 20 |
| Async | RxJS | 7.0+ |
| Build Tool | Vite/Angular CLI | Latest |
| Deployment | Firebase Hosting | Latest |
| APIs | Google Cloud APIs | v3 |
Code Organization¶
src/
├── app.component.ts # Main component
├── config.ts # Configuration
├── env.ts # Environment variables
├── components/ # Reusable components
│ └── file-icon.component.ts
├── models/ # Data models
│ ├── drive-file.model.ts
│ └── user.model.ts
└── services/ # Business logic
├── auth.service.ts
├── drive.service.ts
└── gemini.service.ts