### Install Dependencies and Serve
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/05-configuration.md
Install project dependencies and start the development server. Navigate to http://localhost:4200 to view the application.
```bash
npm install
ng serve
# Navigate to http://localhost:4200
```
--------------------------------
### Install Dependencies and Start Development Server
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
Use these npm commands to install project dependencies and start the development server. Navigate to http://localhost:4200 in your browser to view the application.
```bash
npm install
npm start
```
--------------------------------
### Install Dependencies
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/00-api-index.md
Use this command to install all necessary project dependencies.
```bash
npm install
```
--------------------------------
### Start Development Server
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/00-api-index.md
Starts the development server on port 4200 for local development and testing.
```bash
npm start
```
--------------------------------
### Install Project Dependencies
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/README.md
This command installs the necessary Node.js dependencies for the project. It should be run after cloning the repository.
```bash
$ npm install
```
--------------------------------
### Example Usage of Entry Interface
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/03-types.md
Demonstrates how to create an instance of the Entry interface. Ensure the date is in ISO 8601 format.
```typescript
const entry: Entry = {
date: "2024-04-01",
entry: "This AI project is way over my head..."
}
```
--------------------------------
### EntryComponent Usage Example
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/08-module-exports.md
Shows how to import and use the EntryComponent in other Angular modules. It includes the necessary imports and a template example.
```typescript
import { EntryComponent } from './entry.component'
import { Entry } from './entry.component'
// Rendered in JournalComponent:
//
```
--------------------------------
### Example Deployment Commands
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
These commands demonstrate how to deploy the production build (`dist/` folder) to various static hosting platforms. No backend is required, but users must enter their API key at runtime.
```bash
# Firebase
firebase deploy --only hosting
```
```bash
# Vercel
vercel deploy dist/
```
```bash
# Netlify
netlify deploy --prod --dir=dist/
```
--------------------------------
### Bootstrap Angular Application
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/08-module-exports.md
Initializes and starts the Angular application using the bootstrapApplication function. It catches and logs any errors during the startup process.
```typescript
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err))
```
--------------------------------
### Re-Export Hierarchy Example
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/08-module-exports.md
Illustrates the import and re-export flow in an Angular application using standalone components, starting from the main entry point to nested components and interfaces.
```plaintext
main.ts
├─ imports AppComponent
│ └─ imports JournalComponent
│ └─ imports EntryComponent
│ └─ references Entry interface
└─ imports appConfig
Journal Data Flow:
JournalComponent
├─ injects JournalEntries service
└─ passes entries to EntryComponent via [entry] binding
```
--------------------------------
### Example Output of Journal Entry
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
Illustrates the expected output format for a single journal entry, showing the date followed by the entry text.
```text
2024-04-01
This AI project is way over my head. I barely understand the terms they're...
```
--------------------------------
### Run Tests with Karma and Jasmine
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/09-implementation-notes.md
This command executes the test suite using Karma as the test runner and Jasmine as the testing framework. Ensure you have npm installed.
```bash
npm test # Runs via Karma + Jasmine
```
--------------------------------
### JournalEntries Service Usage Example
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/08-module-exports.md
Demonstrates how to import and use the JournalEntries service within an Angular component via dependency injection.
```typescript
import { JournalEntries } from './journal-entries'
// In component (via dependency injection):
journalEntries = inject(JournalEntries)
const entries = journalEntries.getEntries("short")
```
--------------------------------
### JournalComponent Usage Example
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/08-module-exports.md
Illustrates how to import and use the JournalComponent in another Angular component. Ensure the necessary inputs like api_key and selected_journal are provided.
```typescript
import { JournalComponent } from './journal.component'
// Imported by AppComponent
// Rendered via:
```
--------------------------------
### Angular Application Bootstrap Configuration
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/05-configuration.md
Defines the root-level providers for the Angular application. This example shows an empty provider array, indicating no custom services are injected at the application bootstrap level. The configuration is passed to `bootstrapApplication` in `src/main.ts`.
```typescript
import { ApplicationConfig } from '@angular/core'
export const appConfig: ApplicationConfig = {
providers: []
}
```
```typescript
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err))
```
--------------------------------
### Package.json Scripts for Angular CLI
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/05-configuration.md
Defines common scripts for managing the Angular project, including starting the development server, building the application, watching for changes during development, and running tests. These scripts leverage the Angular CLI.
```json
{
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
}
```
--------------------------------
### Basic Gemini API Request
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/README.md
This snippet demonstrates how to send a basic API request to the Gemini API using the JavaScript SDK. Ensure you have installed the necessary dependencies and replaced 'GEMINI_API_KEY' with your actual API key.
```javascript
const { GoogleGenerativeAI } = require("@google/generative-ai");
const genAI = new GoogleGenerativeAI("GEMINI_API_KEY");
const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" });
const prompt = "Explain how AI works";
const result = await model.generateContent(prompt);
console.log(result.response.text());
```
--------------------------------
### Setting Valid Answer State
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/04-errors.md
TypeScript examples demonstrating how to set the `valid_answer` boolean property to indicate whether the Gemini response is valid or an error.
```typescript
// Success: set to true
this.valid_answer = true
```
```typescript
// Error: set to false
this.valid_answer = false
```
--------------------------------
### Generate Content with Error Handling
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/03-types.md
Use the generateContent method of a GenerativeModel to get a text response. Includes basic error handling for API key issues and other potential errors.
```typescript
try {
const result = await model.generateContent(prompt)
const text = await result.response.text()
return text
} catch(e: any) {
if(e.message.toLowerCase().includes("api key")) {
return "-2" // API key error
}
return "-1" // Other error
}
```
--------------------------------
### Build for Production
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/05-configuration.md
Generate optimized bundles for production deployment. The output is placed in the dist/ directory.
```bash
npm run build
```
--------------------------------
### Run Tests
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/00-api-index.md
Executes the project's test suite.
```bash
npm test
```
--------------------------------
### Build System Prompt with Date and Entries
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/07-data-flow.md
Constructs a system prompt for the Gemini API by including the current date and appending a list of journal entries. This is useful for providing context to the AI model.
```typescript
// Step 1: Get current date
const today = new Date()
const formattedDate = today.toLocaleDateString('en-US')
// Example: "6/23/2024"
// Step 2: Initialize system message
let prompt = `This is today's date: ${formattedDate}.
I'm passing you a list of journal entries at the end of this prompt.
Here is a question the author just asked about all of the entries: ${question_to_ask}.
Please pay attention to dates...
Here are the entries:
`
// Step 3: Append all journal entries
for(let entry of this.journalEntries.getEntries(this.selected_journal)) {
prompt += `${entry.date}\n${entry.entry}\n\n`
}
// Final prompt example:
/*
This is today's date: 6/23/2024. I'm passing you a list of journal entries
at the end of this prompt. Here is a question the author just asked about
all of the entries: What was the highlight of my last week?.
Please pay attention to dates...
Here are the entries:
2024-04-14
Demo went...amazing!...
2024-04-13
Demo day's looming...
... (more entries)
*/
```
--------------------------------
### Initialize GoogleGenerativeAI Client and Model
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/03-types.md
Instantiate the GoogleGenerativeAI client with an API key and retrieve a generative model instance. Ensure you have your API key available.
```typescript
const genAI = new GoogleGenerativeAI(this.api_key)
const model = genAI.getGenerativeModel({ model: 'gemini-pro' })
const result = await model.generateContent(prompt)
const text = await result.response.text()
```
--------------------------------
### Initialize GoogleGenerativeAI with API Key
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/09-implementation-notes.md
This snippet shows the current implementation of initializing the GoogleGenerativeAI client using a user-provided API key. Be aware of the risk of API key exposure in client-side code.
```typescript
const genAI = new GoogleGenerativeAI(this.api_key) // User-provided key
```
--------------------------------
### AppComponent
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/MANIFEST.md
Documentation for the root AppComponent, including its properties and methods for navigation and journal selection.
```APIDOC
## AppComponent
### Description
Root component of the application. Manages API key, selected journal, and navigation.
### Properties
- **api_key** (string): Stores the API key for accessing services.
- **selected_journal** (string): Indicates the currently selected journal type (short or long).
### Methods
- **goBack()**: Navigates the user back to the previous view.
- **select_short_journal()**: Selects the short journal for display.
- **select_long_journal()**: Selects the long journal for display.
```
--------------------------------
### Service Injection using inject()
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/09-implementation-notes.md
Demonstrates injecting services using the inject() function, typically for services marked with providedIn: "root" to ensure application-level singletons.
```typescript
// In JournalComponent
journalEntries = inject(JournalEntries)
// Service marked with providedIn: "root"
@Injectable({providedIn: "root"})
export class JournalEntries { }
```
--------------------------------
### GoogleGenerativeAI Constructor
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/03-types.md
Initializes the GoogleGenerativeAI client with your API key.
```APIDOC
## GoogleGenerativeAI Constructor
### Description
Initializes the client for interacting with the Google Generative AI API.
### Parameters
#### Path Parameters
- `apiKey` (string) - Required - Gemini API key for authentication
```
--------------------------------
### Read Angular Input Signal
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/03-types.md
Access the value of an input signal by calling it like a function `()`. This is necessary even when accessing properties of the input signal's value, as shown in the template example.
```typescript
entry = input.required()
// In template:
{{entry().date}} // Call signal to access properties
```
--------------------------------
### Application State Machine Diagram
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/07-data-flow.md
Visual representation of the application's states and transitions, from initial login to viewing journal entries.
```text
┌─────────────────────┐
│ INITIAL STATE │
│ (No API Key) │
└──────────┬──────────┘
│
│ api_key entered
↓
┌─────────────────────┐
│ LOGGED IN STATE │
│ (Ready for journal │
│ selection) │
└──────────┬──────────┘
│
┌────┴────┐
│ │
↓ ↓
SHORT LONG
JOURNAL JOURNAL
│ │
└────┬─────┘
│
↓
┌──────────────────────┐
│ JOURNAL VIEW STATE │
│ (Showing entries & │
│ question interface) │
└──────────┬───────────┘
│
│ goBack() clicked
│
↓
┌──────────────────────┐
│ BACK TO LOGIN │
│ (selected_journal │
│ reset to "") │
└──────────────────────┘
```
--------------------------------
### ask_question
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Main entry point for submitting a user question. It validates that the question is not empty before calling the core `ask()` method.
```APIDOC
## ask_question(): void
### Description
Main entry point for submitting a user question. It validates that the question is not empty before calling the core `ask()` method.
### Validation
- Returns with error message `"Please enter a question to ask Gemini about your journal"` if `question` is empty
```
--------------------------------
### Watch Mode Builds
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/00-api-index.md
Enables incremental builds, useful for continuous development and monitoring changes.
```bash
npm run watch
```
--------------------------------
### Bootstrap Angular Application
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
Initializes the Angular application using `bootstrapApplication`. Errors during startup are logged to the console. Uses `AppComponent` as the root component and default `appConfig`.
```typescript
import { bootstrapApplication } from '@angular/platform-browser'
import { appConfig } from './app/app.config'
import { AppComponent } from './app/app.component'
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err))
```
--------------------------------
### Component State Management for AI Query
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/07-data-flow.md
Illustrates the evolution of component state during an AI query process, from before submission to after receiving a response or an error.
```typescript
// Before submission
{
api_key: "AIzaSy...",
selected_journal: "short",
question: "What was the highlight?",
answer: "",
valid_answer: false,
error_message: "",
loading: false
}
// During API call
{
loading: true, // Everything else unchanged
// ... waiting for response
}
// After successful response
{
loading: false,
answer: "The highlight of your last week was the successful demo on 2024-04-14...",
valid_answer: true,
error_message: ""
}
// After error response
{
loading: false,
answer: "I cannot answer that question, please ask it in a different way.",
valid_answer: false,
error_message: ""
}
```
--------------------------------
### Angular Project File Structure
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/01-overview.md
Overview of the directory structure for the Angular application, highlighting key files and their roles.
```tree
src/app/
├── main.ts # Application bootstrap
├── app.config.ts # Angular config
├── app.component.ts # Root component (login & journal selection)
├── journal.component.ts # Journal UI with query interface
├── entry.component.ts # Individual entry display
└── journal-entries.ts # Data service with journal content
```
--------------------------------
### EntryComponent
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/MANIFEST.md
Documentation for the EntryComponent, focusing on its input signal and interface definition for displaying individual entries.
```APIDOC
## EntryComponent
### Description
Component for displaying a single journal entry.
### Input Signal
- **Entry InputSignal**: Receives an Entry object to display.
### Interface Definition
- **Entry**: Defines the structure of a journal entry, including date and text.
```
--------------------------------
### Project Dependency Structure
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/00-api-index.md
Illustrates the hierarchical dependency of the main application components. This is useful for understanding the flow of data and control within the application.
```text
main.ts
→ AppComponent
→ JournalComponent
→ EntryComponent
→ JournalEntries (service)
```
--------------------------------
### goBack Method Implementation
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Implements the goBack method which returns a function to reset the selected journal signal. This is used to return the user to the journal selection screen.
```typescript
goBack() {
return () => {
this.selected_journal.set("")
}
}
```
--------------------------------
### appConfig
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/08-module-exports.md
Angular application configuration object passed to bootstrapApplication(). It currently has an empty provider array.
```APIDOC
## appConfig: ApplicationConfig
### Description
Angular application configuration object passed to `bootstrapApplication()`.
### Type
`ApplicationConfig`
### Properties
- `providers`: `[]` - Empty provider array (no custom service providers)
### Usage
```typescript
import { appConfig } from './app/app.config'
bootstrapApplication(AppComponent, appConfig)
```
```
--------------------------------
### Helper Questions in HTML
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
These HTML list items represent pre-populated questions that users can click to quickly explore the application's capabilities. Clicking an item calls the `ask` function with the question text.
```html
What was the highlight of my last week?
What were my goals for this month, and have I made progress?
Can you summarize the overall mood of my journal this month?
```
--------------------------------
### generateContent
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/03-types.md
Sends a prompt to the model to generate content.
```APIDOC
## generateContent
### Description
Sends a prompt to the model and returns the completion result.
### Parameters
#### Path Parameters
- `prompt` (string) - Required - The text prompt to generate content from
### Returns
- `Promise` with structure:
```typescript
{
response: {
text(): string // Returns the generated text response
}
}
```
### Throws
- Error with message containing `"api key"` (case-insensitive) for invalid/missing API keys
- Other errors for rate limits, malformed requests, content filtering, etc.
```
--------------------------------
### User Input to Output Flow Diagram
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/07-data-flow.md
Detailed flow of user input processing, from keyboard events to Gemini API calls and response rendering.
```text
User Input (Question Text)
│
↓
inputChanged(KeyboardEvent)
├─ if key == "Enter" → ask_question()
├─ if question != "" → clear error_message
│
↓
ask_question()
├─ Validate: question != ""
├─ if empty → set error_message
└─ if OK → ask(question)
│
↓
ask(question_to_ask)
├─ Validate: api_key.length > 0
├─ if empty → set error_message, return
├─ Set loading = true
├─ Get current date
├─ Build prompt with:
│ • Current date
│ • Full question text
│ • All journal entries (date + text)
├─ Call callGemini(prompt)
│ │
│ ↓
│ Model.generateContent(prompt)
│ │
│ ├─ Try block:
│ │ └─ Return response.text()
│ └─ Catch block:
│ ├─ if "api key" in error → return "-2"
│ └─ else → return "-1"
│
├─ Set loading = false
├─ Check return value:
│ ├─ "-1" → answer = error message, valid_answer = false
│ ├─ "-2" → answer = invalid key message, valid_answer = false
│ └─ else → answer = response text, valid_answer = true
│
↓
Render output in template:
├─ if error_message.length > 0 → show red error box
├─ if loading == true → show "Asking your question..."
└─ if answer.length > 0 → show answer box
│
↓
User sees Gemini's response or error message
```
--------------------------------
### ask
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Core method for processing questions. It constructs a system prompt with the current date and journal entries, calls the Gemini API, and updates the component's state with the answer or error messages.
```APIDOC
## ask(question_to_ask: string): Promise
### Description
Core method for processing questions. It constructs a system prompt with the current date and journal entries, calls the Gemini API, and updates the component's state with the answer or error messages.
### Parameters
- `question_to_ask: string` - The question to ask about the journal
### System Prompt Construction
- Includes today's date in `en-US` locale format
- Includes all entries for the selected journal
- Instructs Gemini to be mindful of dates and provide brief, contextual responses
- Format: `"This is today's date: [DATE]. I'm passing you a list of journal entries... [ENTRIES]"`
### Error Handling
- Returns error `"Please enter an API KEY for Gemini first."` if `api_key.length == 0`
- Sets `answer` to `"I cannot answer that question, please ask it in a different way."` if `callGemini()` returns `"-1"` (non-API-key error)
- Sets `answer` to `"API key is invalid. Please go back and enter a valid API key."` if `callGemini()` returns `"-2"` (API key error)
- Sets `valid_answer = true` on successful response
### Side Effects
- Sets `loading = true` before API call, `loading = false` after completion
- Updates `question`, `answer`, `valid_answer`, and `error_message` properties
```
--------------------------------
### EntryComponent Template Rendering
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Illustrates how the journal entry's date and text are rendered within the EntryComponent's template. Access to signal values is done via function calls.
```html
{{entry().date}}
{{entry().entry}}
```
--------------------------------
### Construct Gemini API Prompt
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/09-implementation-notes.md
Formats the current date, appends journal entries, and builds the system message for the Gemini API. Ensure 'today' and 'entries' are properly defined before use.
```typescript
// Input: question_to_ask (string)
// selected_journal ("short" or "long")
// Step 1: Format date
const formattedDate = today.toLocaleDateString('en-US')
// Step 2: Build system message with instructions
let prompt = `This is today's date: ${formattedDate}...
// Step 3: Append all entries
for(let entry of entries) {
prompt += `${entry.date}\n${entry.entry}\n\n`
}
// Output: Full prompt string sent to Gemini API
```
--------------------------------
### Submit User Question in Journal Component
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Main entry point for submitting a user question. It validates that the question is not empty before calling the core 'ask' method.
```typescript
async ask_question() {
if(this.question == "") {
this.error_message = "Please enter a question to ask Gemini about your journal"
return
}
await this.ask(this.question)
}
```
--------------------------------
### AppComponent Methods
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/00-api-index.md
Methods available on the root AppComponent for controlling journal selection and navigation.
```APIDOC
## AppComponent Methods
### `goBack`
- **Description**: Returns a callback function that resets the journal selection.
- **Signature**: `(): () => void`
### `select_short_journal`
- **Description**: Sets the selected journal to "short".
- **Signature**: `(): void`
### `select_long_journal`
- **Description**: Sets the selected journal to "long".
- **Signature**: `(): void`
```
--------------------------------
### Loop (For Block)
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/00-api-index.md
Use to iterate over a collection and render a template for each item. The `track` expression is important for performance.
```html
@for(item of items; track item) {
}
```
--------------------------------
### Bind Entry to Component in Parent
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
Shows how to bind a journal entry object to the `entry` input of the `app-entry` component from a parent component.
```html
```
--------------------------------
### Handle User Input for Question
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
Manages user input for questions, triggering the `ask_question` method on Enter key press or button click. It also clears error messages as the user types.
```typescript
// Listen for Enter key or button click
inputChanged(e: KeyboardEvent) {
if(e.key == "Enter") {
this.ask_question() // Submit on Enter
}
if(this.question != "") {
this.error_message = "" // Clear error when typing
}
}
// Button click handler
async ask_question() {
if(this.question == "") {
this.error_message = "Please enter a question to ask Gemini about your journal"
return
}
await this.ask(this.question)
}
```
--------------------------------
### callGemini
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Calls the Gemini API with the provided prompt. It handles API key validation and general errors, returning specific codes for different failure scenarios.
```APIDOC
## callGemini(prompt: string): Promise
### Description
Calls the Gemini API with the provided prompt. It handles API key validation and general errors, returning specific codes for different failure scenarios.
### Parameters
- `prompt: string` - Full prompt including context and journal entries
### Returns
`Promise`
- Success: Raw text from `response.text()`
- API Key Error: `"-2"` (error message includes "api key" in lowercase)
- Other Errors: `"-1"` (any other error)
### Model
Uses `gemini-pro` model via `GoogleGenerativeAI` SDK
### Try-Catch Behavior
- Catches all exceptions and categorizes by error message
- Distinguishes API key errors from other failures
```
--------------------------------
### API Error Handling in callGemini
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/09-implementation-notes.md
Demonstrates how the callGemini function categorizes API errors, distinguishing between API key issues and other errors by returning specific codes.
```plaintext
API Error (throw)
↓
catch in callGemini()
├─ Check: e.message.toLowerCase().includes("api key")
├─ return "-2" or "-1"
↓
Back in ask()
├─ Check: geminiOutput == "-2" or "-1"
├─ Set: answer = user_message, valid_answer = false
↓
Template
├─ Conditional: [hidden]="!valid_answer"
├─ Render answer with or without "Gemini's answer:" heading
```
--------------------------------
### Signal Flow for Journal Component Rendering
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/09-implementation-notes.md
Illustrates the flow of signals and data that triggers the rendering of the JournalComponent based on changes in the selected journal.
```plaintext
AppComponent.selected_journal
↓ (signal change triggers re-render)
↓ Conditional rendering: @if(selected_journal() != "")
↓ Shows JournalComponent
↓ Passes: [selected_journal]="selected_journal()"
↓
JournalComponent
↓ Uses input property to call: journalEntries.getEntries(selected_journal)
↓ Returns entries for display
```
--------------------------------
### Gemini API Key Input in AppComponent
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/05-configuration.md
Handles user input for the Gemini API key in the AppComponent template. The entered key is bound to the `api_key` property and passed to the GoogleGenerativeAI constructor. Ensure the key is non-empty to enable journal selection. For production, consider backend proxies or OAuth for security.
```html
```
--------------------------------
### AppComponent Properties
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Exposes properties for API key management and selected journal state.
```APIDOC
## AppComponent Properties
### `api_key`
- **Type**: `string`
- **Default**: `""`
- **Description**: User-provided Gemini API key; triggers conditional rendering of journal interface.
### `selected_journal`
- **Type**: `Signal`
- **Default**: `""`
- **Description**: Angular signal tracking the currently selected journal (`"short"`, `"long"`, or empty).
```
--------------------------------
### User Interaction Flow Diagram
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/07-data-flow.md
Visualizes the complete user interaction flow, including API key input, journal selection, question input, asking questions, and answer display. It shows data binding with `ngModel` and event handling for clicks and keyups.
```text
┌─────────────────────────────────────────────────────────┐
│ USER INTERFACE │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. [API Key Input] ──[(ngModel)]──> api_key property │
│ │
│ 2. [Select Journal Button] │
│ └─ (click) ──> select_short_journal() / select... │
│ └─ selected_journal.set("short") │
│ └─ Template re-renders (signal change) │
│ │
│ 3. [Question Input] ──[(ngModel)]──> question prop │
│ (keyup) ──> inputChanged(event) │
│ ├─ if key=="Enter" ──> ask_question() │
│ └─ clear error if typing │
│ │
│ 4. [Ask Button] │
│ └─ (click) ──> ask_question() │
│ └─ Validate & call ask(question) │
│ │
│ 5. [Helper Question] │
│ └─ (click) ──> ask(preset_question) │
│ │
│ 6. Loading indicator updates │
│ └─ [hidden]="!loading" │
│ │
│ 7. Answer box updates │
│ └─ @for(line of answer.split("\n")) │
│ │
│ 8. [Switch Journals Button] │
│ └─ (click) ──> goBack() │
│ └─ selected_journal.set("") │
│ └─ Return to login screen │
│ │
└─────────────────────────────────────────────────────────┘
```
--------------------------------
### select_short_journal Method Implementation
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Sets the selected_journal signal to 'short' if an API key is present. This method is called when the user selects the 'Short Journal' option.
```typescript
select_short_journal() {
if(this.api_key != "") {
this.selected_journal.set("short")
}
}
```
--------------------------------
### Import Angular Bootstrap Dependencies
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/08-module-exports.md
Imports necessary Angular modules for bootstrapping the application. These are typically found in the main entry point of an Angular application.
```typescript
import { bootstrapApplication } from '@angular/platform-browser'
import { appConfig } from './app/app.config'
import { AppComponent } from './app/app.component'
```
--------------------------------
### JournalComponent
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/MANIFEST.md
Detailed API for the JournalComponent, covering input properties, state, and public methods for interacting with the Gemini API.
```APIDOC
## JournalComponent
### Description
Component responsible for displaying journal entries and interacting with the Gemini API to generate content.
### Input Properties
- **InputSignal** (Entry): An input signal that receives entry data.
### State Properties
- **(5 state properties)**: Internal state variables managed by the component.
### Methods
- **inputChanged()**: Handles changes in input fields.
- **ask_question()**: Initiates a question to the Gemini API.
- **ask()**: General method to ask a question.
- **callGemini()**: Core method to interact with the Gemini API.
### Code Examples
(Code examples for each method are provided in the source documentation.)
```
--------------------------------
### Implement Navigation Back Functionality
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
Allows a parent component to provide a callback function (`goBack`) to navigate back. The `JournalComponent` calls this callback to reset the `selected_journal` signal, which in turn triggers a UI update to return to the journal selection screen.
```typescript
// Parent passes callback
@Input() goBack = () => {}
// Component calls it to return to journal selection
(click)="goBack()"
// Implementation in AppComponent
goBack() {
return () => {
this.selected_journal.set("") // Reset to empty
}
}
```
--------------------------------
### Call Gemini API with Prompt
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Calls the Gemini API using the provided prompt. It handles potential errors, distinguishing between API key issues (returning '-2') and other general errors (returning '-1').
```typescript
async callGemini(prompt: string) {
const genAI = new GoogleGenerativeAI(this.api_key);
const model = genAI.getGenerativeModel({
model: 'gemini-pro'
});
try {
const result = await model.generateContent(prompt);
const response = await result.response;
const text = response.text();
return text
} catch(e: any) {
if(e.message.toLowerCase().includes("api key")) {
return "-2"
} else {
return "-1"
}
}
}
```
--------------------------------
### Define Angular Application Configuration
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/08-module-exports.md
Exports the application configuration object, which is used to configure Angular services and providers. This is passed to `bootstrapApplication`.
```typescript
export const appConfig: ApplicationConfig = {
providers: []
}
```
--------------------------------
### JournalComponent Methods
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/00-api-index.md
Methods available on the JournalComponent for handling user input and interacting with the Gemini API.
```APIDOC
## JournalComponent Methods
### `inputChanged`
- **Description**: Handles keyboard events on the question input field.
- **Signature**: `(e: KeyboardEvent): void`
- **Async**: No
### `ask_question`
- **Description**: Entry point for submitting a question.
- **Signature**: `(): void`
- **Async**: No
### `ask`
- **Description**: Core processing method that constructs a prompt and calls the Gemini API.
- **Signature**: `(question_to_ask: string): Promise`
- **Async**: Yes
### `callGemini`
- **Description**: Calls the Gemini API and returns the text response or an error code.
- **Signature**: `(prompt: string): Promise`
- **Async**: Yes
```
--------------------------------
### Access Journal Entries via Dependency Injection
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
Demonstrates how to inject `JournalEntries` to access journal data within a component. The `getEntries` method can be called with a parameter to specify which entries to retrieve.
```typescript
journalEntries = inject(JournalEntries)
// In component method:
const entries = this.journalEntries.getEntries("short")
// Returns: Array<{ date: string, entry: string }>
```
--------------------------------
### Gemini API Call Flow
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/07-data-flow.md
Illustrates the sequence of operations for calling the Gemini API, including client creation, model instantiation, content generation, response handling, and error management. This flow is essential for integrating AI capabilities.
```javascript
User submits question
│
↓
JournalComponent.ask(question)
│
├─ Construct full prompt with context
│
↓
JournalComponent.callGemini(prompt)
│
├─ Create GoogleGenerativeAI client
│ const genAI = new GoogleGenerativeAI(this.api_key)
│
├─ Get model instance
│ const model = genAI.getGenerativeModel({ model: 'gemini-pro' })
│
├─ Send request (async)
│ const result = await model.generateContent(prompt)
│
├─ Extract response
│ const response = await result.response
│ const text = response.text()
│
├─ Return text to caller
│ return text
│
└─ Error handling (catch)
if(e.message.toLowerCase().includes("api key")) {
return "-2" // API key error code
} else {
return "-1" // Generic error code
}
Back in ask():
│
├─ Check return value
│ ├─ "-1": error_message="I cannot answer..."
│ ├─ "-2": error_message="API key is invalid..."
│ └─ text: answer=text, valid_answer=true
│
↓
Template re-renders with new answer
```
--------------------------------
### Process Questions with Gemini API
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Core method for processing user questions. It constructs a system prompt with the current date and journal entries, calls the Gemini API, and updates the component's state, including loading status and error handling.
```typescript
async ask(question_to_ask: string) {
this.question = question_to_ask
if(this.api_key.length == 0) {
this.error_message = "Please enter an API KEY for Gemini first."
return
}
this.loading = true
const today = new Date();
const formattedDate = today.toLocaleDateString('en-US');
let prompt = `This is today's date: ${formattedDate}. I'm passing you a list of journal entries...`
for(let entry of this.journalEntries.getEntries(this.selected_journal)) {
prompt += `${entry.date}\n${entry.entry}\n\n`
}
const geminiOutput = await this.callGemini(prompt)
this.loading = false
if(geminiOutput == "-1") {
this.answer = "I cannot answer that question, please ask it in a different way."
this.valid_answer = false
} else if(geminiOutput == "-2") {
this.answer = "API key is invalid. Please go back and enter a valid API key."
this.valid_answer = false
} else {
this.answer = geminiOutput
this.valid_answer = true
}
}
```
--------------------------------
### Configure Gemini Model
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/05-configuration.md
Select the Gemini model to use. This is hard-coded and requires source code modification to change.
```typescript
const model = genAI.getGenerativeModel({
model: 'gemini-pro'
});
```
--------------------------------
### AppComponent Template Rendering with Conditional Logic
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/07-data-flow.md
Demonstrates how to conditionally render the JournalComponent based on the presence of an API key and selected journal. Shows property binding, signal unwrapping, method binding, and two-way binding with ngModel.
```typescript
@if(api_key != "" && selected_journal() != "") {
// Show JournalComponent
} @else {
// Show login/selection screen
// ← two-way binding
// ← event binding
// ← event binding
}
```
--------------------------------
### Render Response Lines in HTML
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/09-implementation-notes.md
Iterates over a string split by newline characters and renders each line within a separate HTML div element. This is a common pattern for displaying multi-line text responses.
```html
@for(answerLine of answer.split("\n"); track answerLine) {
{{answerLine}}
}
```
--------------------------------
### Template Usage for Valid Answer
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/04-errors.md
HTML template usage for conditionally displaying the 'Gemini's answer:' heading based on the `valid_answer` property.
```html
Gemini's answer:
```
--------------------------------
### Call Gemini API with Journal Entries
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
This function orchestrates calling the Gemini API. It validates the API key, sets a loading state, formats the current date, builds a prompt including journal entries, calls the Gemini API, and processes the response.
```typescript
async ask(question_to_ask: string) {
// 1. Validate API key
if(this.api_key.length == 0) {
this.error_message = "Please enter an API KEY for Gemini first."
return
}
// 2. Set loading state
this.loading = true
// 3. Get today's date
const today = new Date()
const formattedDate = today.toLocaleDateString('en-US')
// 4. Build system prompt with date context
let prompt = `This is today's date: ${formattedDate}. I'm passing you a list of journal entries at the end of this prompt. Here is a question the author just asked about all of the entries: ${question_to_ask}. ...`
// 5. Append all journal entries to prompt
for(let entry of this.journalEntries.getEntries(this.selected_journal)) {
prompt += `${entry.date}\n${entry.entry}\n\n`
}
// 6. Call Gemini API
const geminiOutput = await this.callGemini(prompt)
// 7. Clear loading state
this.loading = false
// 8. Process response or error code
if(geminiOutput == "-1") {
this.answer = "I cannot answer that question, please ask it in a different way."
this.valid_answer = false
} else if(geminiOutput == "-2") {
this.answer = "API key is invalid. Please go back and enter a valid API key."
this.valid_answer = false
} else {
this.answer = geminiOutput
this.valid_answer = true
}
}
async callGemini(prompt: string) {
const genAI = new GoogleGenerativeAI(this.api_key)
const model = genAI.getGenerativeModel({ model: 'gemini-pro' })
try {
const result = await model.generateContent(prompt)
const response = await result.response
const text = response.text()
return text
} catch(e: any) {
if(e.message.toLowerCase().includes("api key")) {
return "-2" // API key error
} else {
return "-1" // Other error
}
}
}
```
--------------------------------
### Select Short Journal
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
This TypeScript code snippet demonstrates how to select the 'Short Journal'. It internally calls the `select_short_journal` method, sets the `selected_journal` to 'short', and triggers a render of the JournalComponent.
```typescript
// Internally calls:
this.select_short_journal()
// Which sets:
this.selected_journal.set("short")
// And triggers render of JournalComponent with:
[selected_journal]="selected_journal()" // Value: "short"
```
--------------------------------
### Bind User Input to Template
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/06-usage-examples.md
Binds a text input field to the `question` property using `ngModel` and listens for keyboard events using `(keyup)`. A button is provided to trigger the `ask_question` method.
```html
```
--------------------------------
### Format Date using en-US Locale
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/05-configuration.md
This snippet demonstrates how to format the current date using the 'en-US' locale. This is used to provide context to the Gemini API.
```typescript
const formattedDate = today.toLocaleDateString('en-US')
```
--------------------------------
### Entry Interface Definition
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/00-api-index.md
Defines the structure for a journal entry, including the date and the entry content. The date should be in ISO 8601 format.
```typescript
interface Entry {
date: string // ISO 8601 format (YYYY-MM-DD)
entry: string // Journal text content
}
```
--------------------------------
### getEntries Method Implementation
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Implements the logic to retrieve journal entries based on the provided journal type. Returns specific entry arrays for 'short' and 'long' selections, and a default blank entry for any other input.
```typescript
getEntries(selected_journal: string) {
if(selected_journal == "short") {
return this.short_entries
}
if(selected_journal == "long") {
return this.long_entries
}
return this.blank_entries
}
```
--------------------------------
### Entry Interface
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/08-module-exports.md
The Entry interface defines the structure for a journal entry, containing a date and the entry text.
```APIDOC
## Entry Interface
### Description
Defines the structure of a journal entry.
### Fields
- **date** (string) - The date of the journal entry in ISO 8601 format.
- **entry** (string) - The text content of the journal entry.
```
--------------------------------
### AppComponent Class Definition
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/02-api-reference-components.md
Defines the root component 'AppComponent', its selector, standalone status, imported modules, and template/style placeholders. It also declares properties and methods.
```typescript
@Component({
selector: 'app-root',
standalone: true,
imports: [JournalComponent, FormsModule],
template: `...`,
styles: `...`
})
export class AppComponent {
api_key: string
selected_journal: Signal
goBack(): () => void
select_short_journal(): void
select_long_journal(): void
}
```
--------------------------------
### Direct User Input Interpolation in Prompt
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/09-implementation-notes.md
This code directly interpolates user input into a prompt string. This approach carries a risk of prompt injection, as no escaping or sanitization is applied.
```typescript
let prompt = `Question: ${question_to_ask}...` // User input directly interpolated
```
--------------------------------
### Signal-Based Reactivity for State Management
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/09-implementation-notes.md
Utilizes signals for state management, such as tracking selected journal entries. Signals can be set using .set() and read in templates by invoking them.
```typescript
selected_journal = signal("")
// Setting: this.selected_journal.set("short")
// Reading in template: selected_journal()
```
--------------------------------
### JournalEntries Service Methods
Source: https://github.com/google-gemini/journal-with-gemini/blob/main/_autodocs/00-api-index.md
Methods provided by the JournalEntries service for retrieving journal data.
```APIDOC
## JournalEntries Service Methods
### `getEntries`
- **Description**: Returns journal entries for a specified journal type.
- **Signature**: `(selected_journal: string): JournalEntry[]`
- **Returns**: An array of `JournalEntry` objects.
```