Software Requirements Specification #
SRS v1.0 · ronilprasad8.tech · Full-Stack Portfolio & AI Assistant Platform
1. Introduction #
1.1 Purpose #
This Software Requirements Specification (SRS) documents the functional and non-functional requirements for
ronilprasad8.tech, a full-stack personal portfolio and AI-powered assistant platform.
The document serves as the definitive reference for what the system does, which external services it depends on,
and what quality attributes it must exhibit.
1.2 Scope #
The system encompasses a public-facing portfolio website with the following major capability areas:
- Static content pages (Home, About, Projects, Contact).
- An AI conversational assistant ("The GOAT") with a multi-layered LLM failover engine.
- User authentication (Email/Password signup & login, Google OAuth, password reset) via Firebase.
- Persistent user data and chatbot knowledge storage via Cloud Firestore.
- SEO optimizations including JSON-LD structured data, Open Graph tags, and a sitemap.
- Serverless deployment on Vercel with a Python (Flask) backend.
The scope excludes payment processing, admin dashboards, CMS-managed content, and any native mobile
applications.
1.3 Intended Audience #
| Audience |
Interest |
| Project Owner (Ronil Prasad) |
Authoritative feature catalogue and design rationale. |
| Developers / Maintainers |
Exact behavioral requirements for every route, module, and integration. |
| Academic Reviewers |
SRS artefact for coursework / portfolio assessment. |
1.4 Definitions & Acronyms #
| Term |
Definition |
| GOAT |
The AI assistant persona β "Greatest Of All Time". Implemented as a Python chatbot module. |
| Failover |
Automatic switching from one LLM provider to the next upon failure (e.g. quota exhaustion). |
| Knowledge |
A per-user array of facts persisted in Firestore that are injected into the LLM system prompt to provide
memory across sessions. |
| L1 / L2 / L3 |
Layers of the chatbot failover hierarchy: L1 = Gemini Key 1, L2 = Gemini Key 2, L3 = Groq (Llama 3.3).
|
2. Overall Description #
2.1 Product Perspective #
The system is a standalone, self-contained web application. It is not a module within a larger
enterprise system. It communicates with external services (Firebase, Gemini, Groq, ESPN) via their REST or SDK
APIs but does not expose its own public API for third-party consumption.
Architecturally, the application follows a server-rendered template pattern: Flask serves
Jinja2-rendered HTML pages, with client-side JavaScript modules handling Firebase Authentication, Firestore
data access, and chatbot widget interactions directly from the browser.
2.2 User Classes #
| User Class |
Access Level |
Description |
| Anonymous Visitor |
Read-only (public pages) |
Can browse Home, About, Projects, Contact, and download the CV. Cannot use the chatbot.
|
| Authenticated User |
Full interactive access |
All visitor access plus the GOAT chatbot (widget + dedicated page). The chatbot learns and remembers
user-specific facts. |
| Owner (Master) |
Elevated chatbot persona |
Identified by verified owner administrative credentials. The chatbot addresses them as "Master",
stores learned facts under a global ronil_global Firestore document, and shows a unique input
placeholder.
|
2.3 Operating Environment #
| Aspect |
Detail |
Source |
| Runtime |
Python 3.x (Flask 3.1.3) via Vercel Serverless Functions |
vercel.json, requirements.txt |
| Client |
Modern browsers (ES Module support required for Firebase SDK v10/v11) |
base.html script imports |
| Hosting |
Vercel (production), Flask dev server on port 5000 (local) |
app:main, vercel.json |
| Domain |
ronilprasad8.tech (canonical) |
base.html:canonical_meta |
3. Functional Requirements #
3.1 Portfolio & Static Content #
| ID |
Requirement |
Priority |
| FR-001 |
Landing Page (Hero). The / route shall render a hero section displaying the
owner's name,
a typewriter animation cycling through traits ("Reliable", "Observant", "Nimble", "Insightful",
"Logical"), a subtitle, and two CTA buttons ("View my work" linking to /project,
"Get in touch" linking to /contact).
|
High |
| FR-002 |
About Page. The /about route shall render the owner's biography, education
info card
(BSE at USP, Year 3), philosophy card, a "View Resume" button linking to /cv, a categorized
Technical Arsenal section (Languages, Web & Frontend, Backend, AI & APIs, Cloud & Deployment,
Virtualization, Networking & Systems, Tools & IDEs, Version Control β each with badge images), and
an Academic Roadmap section listing specific USP course units.
|
High |
| FR-003 |
Projects Page. The /project route shall display project cards for:
Website Documentation, Intelligent Document Assistant (external link to assistant.ronilprasad8.tech),
Socket Programming project (GitHub repo link), Multi-Site Campus Network Simulation (GitHub repo link),
and a general GitHub Repositories card (link to the user's GitHub repos tab).
|
High |
| FR-004 |
Contact Page. The /contact route shall render a social grid with clickable
tiles for
GitHub, Instagram, Facebook, X (Twitter), Email (mailto:), and Phone (tel:).
|
High |
| FR-005 |
Architecture Showcase & Documentation. The /architecture route shall render a dedicated System Architecture showcase page (architecture.html) displaying multi-layered failover hierarchies (L1 Gemini Primary, L2 Gemini Key Rotation, L3 Groq Failover), interactive logic pipelines, and deep links into comprehensive technical specifications under /documentation/trd.html#architecture.
|
Medium |
| FR-006 |
CV Download. The /cv route shall serve the file CV/CV.pdf via
Flask's send_from_directory.
|
Medium |
| FR-007 |
Sitemap. The /sitemap.xml route shall serve a static XML sitemap from the
project root.
|
Low |
3.2 Global Navigation & Layout #
| ID |
Requirement |
Priority |
| FR-008 |
Persistent Navigation Bar. A top navigation bar shall appear on every page (via
base.html),
containing links to Home, About, Projects, and Contact, plus an auth icon button on the right.
|
High |
| FR-009 |
Auth Icon State Toggle. The auth icon shall reactively change based on Firebase
onAuthStateChanged: show a user-circle icon (link to /login) when logged out,
and a sign-out icon (red, triggers signOut() then redirects to /login) when
logged in.
|
High |
| FR-010 |
Footer. A global footer shall display a comprehensive navigation bar (Home, About, Projects, Contact, Architecture, Docs, Privacy Policy & Terms), a copyright line with the dynamic current year, and social links (GitHub, LinkedIn, Instagram, Facebook, X).
|
Medium |
3.3 Authentication #
| ID |
Requirement |
Priority |
| FR-011 |
Login/Signup Tabs. The /login page shall present two tabs: "Login" and "Sign
Up",
switchable client-side via switchTab(). The Login tab is shown by default.
|
High |
| FR-012 |
Email/Password Login. Users shall authenticate via
signInWithEmailAndPassword().
On success, a banner displays and the user is redirected to / after 1 second. On failure,
an error banner is shown.
|
High |
| FR-013 |
Google OAuth Login. Users shall authenticate via signInWithPopup() using
GoogleAuthProvider with prompt: 'select_account'. First-time Google users
are auto-registered in Firestore with derived first/last names from displayName.
|
High |
| FR-014 |
Email/Password Registration. The Sign Up form collects: First Name, Last Name, Nickname,
Organization, Email, Password, and Retype Password. Validation includes password match check and
complexity
regex (β₯8 chars, β₯1 uppercase, β₯1 digit, β₯1 special character). On success, a Firestore user document is
created under users/{uid}.
|
High |
| FR-015 |
Forgot Password. A "Forgot Password?" link is shown on the login form. Clicking it
reveals
a separate view with an email input and "Send Reset Link" button. The system calls Firebase's
sendPasswordResetEmail(). A success banner (mentioning the spam folder) is displayed,
and the view auto-returns to Login after 3 seconds. Error handling covers invalid email and
user-not-found.
|
High |
| FR-016 |
Duplicate Email Guard. If registration is attempted with an already-used email, the
system
catches auth/email-already-in-use and displays: "This email address is already linked to an
active account."
|
Medium |
3.4 GOAT Chatbot #
| ID |
Requirement |
Priority |
| FR-017 |
Global Chat Widget. A floating chat launcher icon (bottom-right) shall be visible on all
pages
except /chat. Clicking it toggles a chat container. Clicking outside the container closes it.
|
High |
| FR-018 |
Dedicated Chat Page. The /chat (GET) route shall render a full-page chat
interface.
The global widget is hidden on this page via CSS override. The chat page also requires authentication
(gating
check via onAuthStateChanged).
|
High |
| FR-019 |
Authentication Gating. Both the widget and dedicated chat page shall disable input and
display
a "You must log in" message with a link to /login when no user is authenticated. Input is
re-enabled upon successful authentication.
|
High |
| FR-020 |
Intent-Based Routing. The backend shall classify user messages as "personal" (about
Ronil)
or "general" based on a hardcoded keyword list (50+ keywords including "ronil", "usp", "football",
"anime",
etc.) and intro patterns ("I'm", "my name is", etc.). Personal queries are routed to Gemini; general
queries
(or Gemini failures) are routed to Groq.
|
High |
| FR-021 |
Multi-Key Gemini Rotation. The system shall support comma-separated Gemini API keys in
the
GEMINI_API_KEY environment variable. On a key failure (e.g. 429), the system cycles to the
next key. The model used is gemini-2.0-flash.
|
High |
| FR-022 |
Groq Failover Layer. If all Gemini keys fail, or if the query is classified as "general",
the system shall fall back to Groq's API using the llama-3.3-70b-versatile model.
|
High |
| FR-023 |
Conversation History. The client shall maintain a local array of chat messages (capped at
10)
and send the last 10 entries to the backend with each request. The backend passes these to both Gemini and
Groq for contextual continuity.
|
Medium |
| FR-024 |
Live Context Injection. Before each response, the backend fetches live context including:
current Fiji time (UTC+12), activity/location inference (at university, sleeping, semester break, etc.),
and Bayern Munich match results from the ESPN API (site.api.espn.com). This context is
injected
into the system prompt.
|
Medium |
| FR-025 |
Knowledge Learning & Persistence. If the LLM response contains a
[LEARN_RONIL: <fact>] or [LEARN_USER: <fact>] tag, the client-side
JS extracts the fact, persists it to Firestore under knowledge/{userId} (or
knowledge/ronil_global for the owner), strips the tag from the displayed text, and updates
the local knowledge array. These facts are sent with subsequent requests.
|
Medium |
| FR-026 |
Typewriter Response Animation. Bot responses shall be rendered character-by-character at
~15β20ms per character to simulate typing.
|
Low |
| FR-027 |
Typing Indicator. While waiting for a backend response, an animated three-dot typing
indicator shall be displayed in the chat window.
|
Low |
| FR-028 |
Dynamic Persona (Owner vs. User). When the authenticated user's email matches the
owner's,
the system prompt addresses them as "Master" / "The Sage" and enables the LEARN_RONIL
trigger.
For all other users, it addresses them by their first name (fetched from Firestore) and enables the
LEARN_USER trigger. The widget placeholder text also changes for the owner.
|
Medium |
| FR-029 |
Chat Message Logging (SAVE_TRIGGER). If the LLM response contains a
[SAVE_TRIGGER: {...}] JSON tag, the client shall parse it and write a document to the
Firestore messages collection with username, text, and a
server-generated timestamp.
|
Low |
3.5 SEO & Analytics #
| ID |
Requirement |
Priority |
| FR-030 |
JSON-LD Structured Data. Every page shall include a schema.org/Person
JSON-LD
block in <head> with name, URL, job titles, address, education, and social
sameAs links.
|
Medium |
| FR-031 |
Open Graph & Twitter Cards. Each page shall have OG and Twitter meta tags with
dynamic
title and description derived from Jinja2 blocks.
|
Medium |
| FR-032 |
Vercel Speed Insights. The Vercel Speed Insights script shall be loaded on every page for
web performance analytics.
|
Low |
| FR-033 |
Google Search Console Verification. The /googlec53d9b38dc3c26f5.html route
shall return the Google verification string.
|
Low |
4. Non-Functional Requirements #
| ID |
Requirement |
Priority |
| NFR-001 |
Page Load Time. Static pages (Home, About, Projects, Contact) shall load within 3 seconds
on a standard broadband connection. Vercel's global CDN edge network provides the delivery layer.
|
High |
| NFR-002 |
Chatbot Response Latency. The ESPN API call in get_live_context() uses a
3-second
timeout (timeout=3); on failure, the live context is silently omitted. LLM provider response
time is dependent on Gemini/Groq service performance.
|
Medium |
| NFR-003 |
History Window Cap. Client-side chat history is pruned to the last 10 messages to bound
token consumption and payload size.
|
Medium |
4.2 Security #
| ID |
Requirement |
Priority |
| NFR-004 |
Credential Storage. All API keys (Gemini, Groq, Firebase) are stored in environment
variables
(loaded via python-dotenv in development, Vercel environment variables in production). The
Firebase API key is injected into page templates server-side via Flask's context_processor.
|
High |
| NFR-005 |
Authentication Provider. Authentication is fully delegated to Firebase Authentication.
Passwords are never stored or handled by the Flask backend. The client SDK communicates directly with
Firebase servers over HTTPS.
|
High |
| NFR-006 |
Password Complexity. Registration enforces: minimum 8 characters, at least one uppercase
letter, at least one digit, and at least one special character.
|
High |
| NFR-007 |
Server-Side Auth Verification & Rate Limiting. The Flask backend verifies Firebase Auth ID tokens on the
/chat POST endpoint using google.oauth2.id_token against Google's public certificates (returning 401 Unauthorized on failure). In addition, an in-memory sliding window rate limiter throttles traffic to a maximum of 15 requests per 60 seconds per UID/IP, returning 429 Too Many Requests if exceeded.
|
High |
4.3 Usability #
| ID |
Requirement |
Priority |
| NFR-008 |
Responsive Layout. All pages shall be usable on desktop and mobile viewports. The base
stylesheet (style.css, 30KB) contains responsive rules.
|
High |
| NFR-009 |
Error Feedback. The login/signup forms use a dual banner system (success = green, error =
red)
with auto-scroll-into-view for error banners. The chatbot displays "Logic uplink failed. Try again." on
network errors.
|
Medium |
| NFR-010 |
Accessibility. The chat send button and social links include aria-label
attributes. Font Awesome icons are decorative only. The emoji favicon uses an SVG text fallback.
|
Medium |
4.4 Reliability & Availability #
| ID |
Requirement |
Priority |
| NFR-011 |
LLM Failover. The chatbot shall remain functional even if the primary AI provider
(Gemini)
is unavailable. The three-tier failover (Gemini Key 1 β Key 2 β Groq) provides redundancy. A hard
fallback message ("The GOAT is currently in a logical deadlockβ¦") is displayed only if all providers fail.
|
High |
| NFR-012 |
Live Context Fault Tolerance. If the ESPN API call fails, get_live_context()
catches the exception and returns an empty string, ensuring the chatbot still responds.
|
Medium |
4.5 Scalability #
| ID |
Requirement |
Priority |
| NFR-013 |
Serverless Scaling. The application is deployed as Vercel Serverless Functions. Scaling
is
handled automatically by the platform (cold starts apply).
|
Medium |
| NFR-014 |
Rate Limiting & Abuse Prevention. The Flask /chat endpoint implements an in-memory sliding window rate limiter allowing a maximum of 15 requests per 60 seconds per authenticated UID (or client IP), returning 429 Too Many Requests if exceeded to protect LLM API quotas.
|
High |
5. External Interface Requirements #
5.1 Third-Party APIs #
| Service |
Purpose |
Protocol |
Auth Method |
Source Reference |
| Google Gemini |
Primary LLM for personal queries (model: gemini-2.0-flash) |
REST via google-genai SDK |
API Key (env: GEMINI_API_KEY, comma-separated for rotation) |
chatbot:call_gemini_with_retry |
| Groq |
Failover LLM (model: llama-3.3-70b-versatile) |
REST via groq SDK |
API Key (env: GROQ_API_KEY) |
chatbot:call_groq |
| ESPN API |
Fetch Bayern Munich (team ID 132) match results for live context |
HTTPS GET (public, no auth) |
None (User-Agent header configured) |
chatbot:fetch_bayern_results |
| Firebase Authentication |
Email/Password, Google OAuth, Password Reset |
Firebase Client JS SDK v10/v11 |
Firebase API Key (injected via template) |
login.html, base.html, chatbot.js |
| Cloud Firestore |
User profiles, knowledge persistence, chat message logging |
Firebase Client JS SDK v10/v11 |
Firebase API Key + Auth context |
chatbot.js, login.html, chat.html |
| Vercel Speed Insights |
Web performance analytics |
Client-side JS (CDN script) |
Automatic (Vercel project-bound) |
base.html L170β176 |
5.2 Database (Firestore Collections) #
| Collection |
Document ID Pattern |
Fields |
Written By |
users |
{firebase_uid} |
firstName, lastName, nickname, organization (email
signups only), email, createdAt |
Signup flow (login.html) |
knowledge |
{firebase_uid} or ronil_global |
facts (array of strings) |
Chatbot widget (chatbot.js) |
messages |
Auto-generated |
username, text, timestamp (server) |
SAVE_TRIGGER in chatbot (chatbot.js) |
5.3 External CDN Resources #
| Resource |
URL |
Purpose |
| Font Awesome 6.5.1 |
cdnjs.cloudflare.com |
Icon library for navigation, social links, and chat UI |
| Firebase JS SDK |
gstatic.com/firebasejs/11.0.1/ |
Auth, Firestore (unified to v11.0.1 across all templates and JS modules) |
| shields.io |
img.shields.io |
Tech stack badge images on the About page |
Note: The codebase has unified the Firebase JS SDK to v11.0.1 across
all HTML templates (login.html, base.html, chat.html) and JavaScript modules (chatbot.js).
This eliminates version disparity and ensures a single client-side singleton instance across the application lifecycle.
6. Constraints & Assumptions #
6.1 Constraints #
| ID |
Constraint |
Impact |
| C-001 |
Vercel Serverless Execution Limit. Vercel's free/hobby tier imposes a 10-second function
execution timeout. LLM calls that exceed this will fail.
|
High β chatbot responses may timeout on complex queries. |
| C-002 |
LLM API Quotas. Both Gemini and Groq enforce rate limits and daily quotas. The key
rotation pattern mitigates this for Gemini but does not eliminate it.
|
Medium β under heavy traffic, all keys may be exhausted. |
| C-003 |
Server-Side Auth, Identity Verification & Rate Limiting. Firebase ID token verification is enforced on the server-side
for the Flask /chat POST endpoint, extracting cryptographically verified user identity and throttling requests to 15 per minute per user/IP.
|
Mitigated β unauthorized direct API calls are blocked with 401 at the server layer and quota abuse is prevented with 429 rate limiting. |
| C-004 |
ES Module Requirement. Firebase SDK imports use ES module syntax
(import ... from). Browsers without ES module support (e.g., IE 11) will not function.
|
Low β IE 11 usage is negligible. |
| C-005 |
Single-Region Deployment. Vercel deploys serverless functions to a single region by
default. Users far from that region may experience higher latency on chatbot responses.
|
Low β static assets are served from CDN edge. |
| C-006 |
Firestore Quotas. The Firebase project (ronilprasad8-5ba1e) is on the free
Spark plan or Blaze plan with appropriate Firestore read/write limits.
|
Medium β database writes (learned facts, message logs) will fail if quota is exceeded. |
6.2 Assumptions #
| ID |
Assumption |
| A-001 |
The Gemini and Groq API keys provided in environment variables are valid and have sufficient quota for
normal traffic levels. |
| A-003 |
The ESPN public API endpoint for Bayern Munich scheduling remains available and structurally stable.
|
| A-004 |
End users will access the site from modern browsers (Chrome, Firefox, Safari, Edge) with JavaScript
enabled. |
| A-005 |
A sliding-window rate limit of 15 requests per minute per user/IP is sufficient for genuine interactive conversations while effectively preventing automated quota exhaustion. |