AI-powered interview question generator that creates thoughtful, role-specific questions for any job title. Built with vanilla HTML, CSS, and JavaScript β no frameworks, no build tools, instant deploy.
IQ Gen is designed with a highly secure, serverless proxy architecture that separates client presentation from the AI ingestion backend. This ensures the application is both responsive and completely secure against credential theft.
This flowchart illustrates how client requests are routed depending on the presence of a custom key, and how the dynamic fallback system recovers from transient API errors.
flowchart TD
%% Class Definitions for Premium Theme (Mocha / Material Dark)
classDef startEnd fill:#1e1e2e,stroke:#cba6f7,stroke-width:2px,color:#cdd6f4,font-weight:bold
classDef ui fill:#181825,stroke:#89b4fa,stroke-width:2px,color:#cdd6f4
classDef decision fill:#313244,stroke:#f9e2af,stroke-width:2px,color:#cdd6f4,font-weight:bold
classDef secure fill:#112a21,stroke:#a6e3a1,stroke-width:2px,color:#a6e3a1
classDef bypass fill:#2c1921,stroke:#f38ba8,stroke-width:2px,color:#f38ba8
classDef model fill:#1e1e2e,stroke:#cba6f7,stroke-width:2px,color:#cdd6f4
classDef output fill:#181825,stroke:#89dceb,stroke-width:2px,color:#89dceb,font-weight:bold
User([Recruiter User]) -->|Input job title| Frontend[Vanilla HTML/JS/CSS App]
Frontend --> KeyDecision{Custom API Key?}
%% Proxy Route
KeyDecision -->|No - Default Proxy| ProxyRoute["POST /.netlify/functions/generate"]
ProxyRoute --> ServerlessFn["Netlify Serverless Function"]
ServerlessFn -->|Injects secret API key| EnvVars[(Netlify Environment Variables)]
EnvVars --> PrimaryModel["Primary: gemini-2.5-flash"]
%% Direct Route
KeyDecision -->|Yes - Reviewer Bypass| DirectRoute["Direct Client-Side Fetch"]
DirectRoute --> DirectPrimary["Primary: gemini-2.5-flash"]
%% Fallbacks
PrimaryModel -->|503 or 429 Error| Fallback1["Fallback A: gemini-3.1-flash-lite"]
DirectPrimary -->|503 or 429 Error| DirectFallback["Fallback A: gemini-3.1-flash-lite"]
Fallback1 -->|503 or 429 Error| Fallback2["Fallback B: gemini-2.5-flash-lite"]
%% Success Outputs
PrimaryModel -->|200 OK| Output["Render & Display Animated Cards"]
DirectPrimary --> Output
Fallback1 --> Output
DirectFallback --> Output
Fallback2 --> Output
%% Assign Styles
class User startEnd
class Frontend ui
class KeyDecision decision
class ProxyRoute,ServerlessFn,EnvVars secure
class DirectRoute bypass
class PrimaryModel,DirectPrimary,Fallback1,DirectFallback,Fallback2 model
class Output output
This sequence diagram details the timelines and lifecycles of both request models. By separating the workflows, legibility is dramatically enhanced.
sequenceDiagram
autonumber
actor User as "Recruiter"
participant FE as "Frontend (app.js)"
participant Proxy as "Serverless Proxy"
participant Gemini as "Gemini API"
Note over User,Gemini: Default Secure Flow (Zero-Friction)
User->>FE: Click "Generate Questions"
FE->>Proxy: POST /generate { jobTitle }
Note over Proxy: Server injects hidden GEMINI_API_KEY
Proxy->>Gemini: POST gemini-2.5-flash
alt Success (200 OK)
Gemini-->>Proxy: JSON Questions
else 503 / 429 Triggered
Note over Proxy: Dynamic Fallback
Proxy->>Gemini: POST gemini-3.1-flash-lite
Gemini-->>Proxy: JSON Questions
end
Proxy-->>FE: JSON Array Response
FE->>User: Render Question Cards
Note over User,Gemini: Optional Reviewer Flow (Custom API Key)
User->>FE: Click "Generate Questions"
FE->>Gemini: POST gemini-2.5-flash (Direct with Key)
alt Success (200 OK)
Gemini-->>FE: JSON Questions
else 503 / 429 Triggered
Note over FE: Dynamic Fallback
FE->>Gemini: POST gemini-3.1-flash-lite
Gemini-->>FE: JSON Questions
end
FE->>User: Render Question Cards
- Frontend: Pure HTML5, CSS3 (Vanilla design token system, responsive grids, glassmorphic UI), and ES Modules. No build tool, bundler, or heavy framework required.
- Serverless Backend: Hosted on Netlify Functions (
netlify/functions/generate.js) to completely hide the API key from the browser. - LLM Engine: Google Gemini API (
gemini-2.5-flashwith dynamic fallbacks togemini-3.1-flash-liteandgemini-2.5-flash-lite). - Persistence & State:
sessionStoragefor temporary, tab-isolated key overrides, andlocalStoragefor theme preference caching.
- Serverless Proxy: By default, client-side requests are securely proxied through Netlify's CDN edge to a Serverless Function. The
GEMINI_API_KEYis securely injected from Netlify's encrypted vault on the server side, meaning it never traverses the network to the user's browser. - Protected Repositories: The
.gitignorefile is strictly configured to ensure local.envconfiguration files and large packages (node_modules/) are never pushed or leaked to public version control repositories.
To guarantee high availability and eliminate 503 (Service Unavailable) or 429 (Resource Exhausted) errors during times of intense Google backend demand, the application implements an automatic model fallback chain:
gemini-2.5-flash(Primary high-performance model)gemini-3.1-flash-lite(Ultra-fast, high-availability frontier fallback)gemini-2.5-flash-lite(Fast, highly stable backup fallback)
If a model degrades or rate-limits, the request automatically slides to the next available model in the sequence inside the same network call.
Serverless functions (like Netlify Functions) have strict execution limits (10 seconds on the free tier). Standard network retries with delays can easily trigger Netlify server termination, returning a hard 502 Bad Gateway to users. To solve this, the serverless handler assigns a 6-second watchdog timeout to each model request. If a model hangs or is congested, the request aborts instantly and switches to the next model in the fallback chain, ensuring successful responses well under the serverless execution limit.
To prevent LLM formatting anomalies (like conversational prefixes, unescaped markdown blocks, or corrupted arrays), the backend forces 100% deterministic outputs using Gemini's native Structured Outputs framework:
responseMimeType: "application/json",
responseSchema: {
type: "ARRAY",
items: { type: "STRING" }
}This forces the model to strictly return a valid JSON array of strings, reducing token overhead, increasing generation speed, and eliminating parsing failures.
- Local Storage Caching: Every successful generation is cached in
localStorageunderiq-gen-questions-cacheindexed by job title. - Instant loads (<10ms): Searching for a previously generated role bypasses the network entirely, loading the questions in under 10ms with a custom caching badge and a "Force Refresh" action button.
- Graceful Degradation: If your connection degrades or goes completely offline, clicking regenerate will cleanly load the last successful cached version of the questions alongside a prominent status banner: "Offline or poor network. Loaded last successful generation."
- Connection Speed Awareness: If the network request takes longer than 3.5 seconds, a beautiful speed-alert banner automatically appears: "Your connection seems a bit slow, but we are still trying to generate..." so the user is kept informed throughout.
- Deep-Linking: Pass a job role via the URL parameters (e.g.,
?role=Customer+Success+Manager) to instantly trigger zero-click, beautifully animated question generations on load. - One-Click Copy: Custom cards equipped with visual haptic feedback (copy buttons dynamically morph to checkmarks upon successful Clipboard API interaction).
- Export to Plaintext: Automatically packages the role, timestamp, and generated questions into a cleanly structured
.txtfile for download. - Dynamic Theme Engine: Seamless Light/Dark mode transitions respecting system preferences automatically, while keeping overrides saved locally.
- Strict Accessibility (a11y): Built with native semantic tags, custom focus outlines, keyboard navigational compliance, and dynamic
aria-liveregions to announce skeleton loads to screen readers.
- Node.js (v18 or higher recommended)
- NPM (packaged automatically with Node)
-
Clone the repository
git clone https://github.com/YOUR_USERNAME/iq-gen.git cd iq-gen -
Install local development dependencies
npm install
-
Configure your API Key Create a file named
.envin the root of the project:GEMINI_API_KEY=YOUR_GEMINI_API_KEY
(Get your free key at Google AI Studio).
-
Launch the local development environment
npm run dev
This command starts the local Netlify Dev environment. It will read your local
.envfile, spin up your serverless function proxy, and serve the static files.- π₯οΈ Access the local application at: http://localhost:8888
To securely host this app live in production:
- Create a free account on Netlify.
- Connect your GitHub repository to a new site.
- In your Netlify dashboard, navigate to Site Settings β Environment Variables and add:
- Key:
GEMINI_API_KEY - Value: Your actual Gemini API key.
- Key:
- Deploy the site! Netlify will automatically build the static assets and set up the edge routes to securely map your backend proxy.
This project is licensed under the MIT License. See LICENSE for details.