Compare commits
17
Commits
a3dd4b9ffa
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fccc0115c4 | ||
|
|
189260bbb3 | ||
|
|
8e7070cbaf | ||
|
|
a8d7db562d | ||
|
|
e220f46d35 | ||
|
|
93460ece19 | ||
|
|
7b67897612 | ||
|
|
c5f79f1fd2 | ||
|
|
41abcaa7a4 | ||
|
|
966f3b23fa | ||
|
|
45b30918a0 | ||
|
|
7eeec7e781 | ||
|
|
527131a462 | ||
|
|
6b07b83583 | ||
|
|
c7e130ce4d | ||
|
|
5a2b68763f | ||
|
|
84624976a8 |
@@ -1,11 +1,11 @@
|
|||||||
# Graph Report - 2e709500-79ab-403f-9ca0-3f027ac9f36e (2026-06-19)
|
# Graph Report - 2e709500-79ab-403f-9ca0-3f027ac9f36e (2026-06-24)
|
||||||
|
|
||||||
## Corpus Check
|
## Corpus Check
|
||||||
- 61 files · ~611,807 words
|
- 64 files · ~615,668 words
|
||||||
- Verdict: corpus is large enough that graph structure adds value.
|
- Verdict: corpus is large enough that graph structure adds value.
|
||||||
|
|
||||||
## Summary
|
## Summary
|
||||||
- 596 nodes · 620 edges · 114 communities (87 shown, 27 thin omitted)
|
- 619 nodes · 640 edges · 117 communities (90 shown, 27 thin omitted)
|
||||||
- Extraction: 99% EXTRACTED · 1% INFERRED · 0% AMBIGUOUS · INFERRED: 4 edges (avg confidence: 0.8)
|
- Extraction: 99% EXTRACTED · 1% INFERRED · 0% AMBIGUOUS · INFERRED: 4 edges (avg confidence: 0.8)
|
||||||
- Token cost: 0 input · 0 output
|
- Token cost: 0 input · 0 output
|
||||||
|
|
||||||
@@ -50,9 +50,8 @@
|
|||||||
- [[_COMMUNITY_Community 34|Community 34]]
|
- [[_COMMUNITY_Community 34|Community 34]]
|
||||||
- [[_COMMUNITY_Community 35|Community 35]]
|
- [[_COMMUNITY_Community 35|Community 35]]
|
||||||
- [[_COMMUNITY_Community 36|Community 36]]
|
- [[_COMMUNITY_Community 36|Community 36]]
|
||||||
- [[_COMMUNITY_Community 41|Community 41]]
|
- [[_COMMUNITY_Community 37|Community 37]]
|
||||||
- [[_COMMUNITY_Community 42|Community 42]]
|
- [[_COMMUNITY_Community 38|Community 38]]
|
||||||
- [[_COMMUNITY_Community 43|Community 43]]
|
|
||||||
- [[_COMMUNITY_Community 44|Community 44]]
|
- [[_COMMUNITY_Community 44|Community 44]]
|
||||||
- [[_COMMUNITY_Community 45|Community 45]]
|
- [[_COMMUNITY_Community 45|Community 45]]
|
||||||
- [[_COMMUNITY_Community 46|Community 46]]
|
- [[_COMMUNITY_Community 46|Community 46]]
|
||||||
@@ -71,6 +70,9 @@
|
|||||||
- [[_COMMUNITY_Community 59|Community 59]]
|
- [[_COMMUNITY_Community 59|Community 59]]
|
||||||
- [[_COMMUNITY_Community 60|Community 60]]
|
- [[_COMMUNITY_Community 60|Community 60]]
|
||||||
- [[_COMMUNITY_Community 61|Community 61]]
|
- [[_COMMUNITY_Community 61|Community 61]]
|
||||||
|
- [[_COMMUNITY_Community 62|Community 62]]
|
||||||
|
- [[_COMMUNITY_Community 63|Community 63]]
|
||||||
|
- [[_COMMUNITY_Community 64|Community 64]]
|
||||||
|
|
||||||
## God Nodes (most connected - your core abstractions)
|
## God Nodes (most connected - your core abstractions)
|
||||||
1. `Performance Testing Scripts` - 12 edges
|
1. `Performance Testing Scripts` - 12 edges
|
||||||
@@ -94,7 +96,7 @@
|
|||||||
- `POST()` --calls--> `logApiRequest()` [INFERRED]
|
- `POST()` --calls--> `logApiRequest()` [INFERRED]
|
||||||
src/pages/api/newsletter.ts → src/utils/logger.ts
|
src/pages/api/newsletter.ts → src/utils/logger.ts
|
||||||
|
|
||||||
## Communities (114 total, 27 thin omitted)
|
## Communities (117 total, 27 thin omitted)
|
||||||
|
|
||||||
### Community 0 - "Community 0"
|
### Community 0 - "Community 0"
|
||||||
Cohesion: 0.05
|
Cohesion: 0.05
|
||||||
@@ -144,49 +146,49 @@ Nodes (11): Code Example, code:astro (---), code:javascript (// Traditional SPA:
|
|||||||
Cohesion: 0.18
|
Cohesion: 0.18
|
||||||
Nodes (10): code:hcl (# Define AWS EC2 instance), code:dockerfile (# Multi-stage build for a Go application), code:yaml (# AWS Cost allocation tags), Common Pitfalls, Conclusion, Containerization as a Migration Strategy, Cost Optimization Strategies, Infrastructure as Code (+2 more)
|
Nodes (10): code:hcl (# Define AWS EC2 instance), code:dockerfile (# Multi-stage build for a Go application), code:yaml (# AWS Cost allocation tags), Common Pitfalls, Conclusion, Containerization as a Migration Strategy, Cost Optimization Strategies, Infrastructure as Code (+2 more)
|
||||||
|
|
||||||
### Community 18 - "Community 18"
|
### Community 16 - "Community 16"
|
||||||
Cohesion: 0.43
|
Cohesion: 0.2
|
||||||
Nodes (6): trackCaseStudyView(), trackEvent(), trackExternalLink(), trackFormSubmit(), trackNewsletterSignup(), trackPortfolioFilter()
|
Nodes (9): Catalogue Listing vs Bidding: How You Actually Win, Common Reasons Software Vendors Get Rejected or Delayed, Document Checklist, Fees, Caution Money, and Timelines, Frequently Asked Questions, MSME and Startup Benefits Worth Claiming, Step-by-Step Registration Process, Turning GeM Access Into Government Contracts (+1 more)
|
||||||
|
|
||||||
### Community 19 - "Community 19"
|
### Community 18 - "Community 18"
|
||||||
Cohesion: 0.36
|
Cohesion: 0.22
|
||||||
Nodes (7): extract_scores(), get_issues(), main(), Run Lighthouse audit on a URL, Extract key scores from Lighthouse data, Extract issues from Lighthouse audit, run_lighthouse()
|
Nodes (8): 2026 Cost Ranges by Project Tier, A Simple Way to Estimate Your Own Cost, Build vs Buy: When Custom Actually Pays Off, Frequently Asked Questions, Getting an Accurate Number for Your Project, Hidden Costs Buyers Forget to Budget, The Biggest Cost Driver: The Team, What "Custom ERP" Actually Means for Pricing
|
||||||
|
|
||||||
### Community 20 - "Community 20"
|
### Community 20 - "Community 20"
|
||||||
Cohesion: 0.46
|
Cohesion: 0.43
|
||||||
Nodes (7): captureScreenshot(), ensureDir(), generateIndex(), main(), screenshotPath(), setTheme(), waitForPageReady()
|
Nodes (6): trackCaseStudyView(), trackEvent(), trackExternalLink(), trackFormSubmit(), trackNewsletterSignup(), trackPortfolioFilter()
|
||||||
|
|
||||||
### Community 21 - "Community 21"
|
### Community 21 - "Community 21"
|
||||||
Cohesion: 0.36
|
Cohesion: 0.36
|
||||||
Nodes (4): deleteFromDB(), getAllFromDB(), openDB(), processSyncQueue()
|
|
||||||
|
|
||||||
### Community 22 - "Community 22"
|
|
||||||
Cohesion: 0.43
|
|
||||||
Nodes (6): trackCaseStudyView(), trackEvent(), trackExternalLink(), trackFormSubmit(), trackNewsletterSignup(), trackPortfolioFilter()
|
|
||||||
|
|
||||||
### Community 23 - "Community 23"
|
|
||||||
Cohesion: 0.46
|
|
||||||
Nodes (7): checkRateLimit(), corsHeaders(), escapeHtml(), OPTIONS(), POST(), sendContactEmail(), validateContactForm()
|
|
||||||
|
|
||||||
### Community 24 - "Community 24"
|
|
||||||
Cohesion: 0.36
|
|
||||||
Nodes (7): extract_scores(), get_issues(), main(), Run Lighthouse audit on a URL, Extract key scores from Lighthouse data, Extract issues from Lighthouse audit, run_lighthouse()
|
Nodes (7): extract_scores(), get_issues(), main(), Run Lighthouse audit on a URL, Extract key scores from Lighthouse data, Extract issues from Lighthouse audit, run_lighthouse()
|
||||||
|
|
||||||
### Community 25 - "Community 25"
|
### Community 22 - "Community 22"
|
||||||
Cohesion: 0.46
|
Cohesion: 0.46
|
||||||
Nodes (7): captureScreenshot(), ensureDir(), generateIndex(), main(), screenshotPath(), setTheme(), waitForPageReady()
|
Nodes (7): captureScreenshot(), ensureDir(), generateIndex(), main(), screenshotPath(), setTheme(), waitForPageReady()
|
||||||
|
|
||||||
### Community 26 - "Community 26"
|
### Community 23 - "Community 23"
|
||||||
Cohesion: 0.36
|
Cohesion: 0.36
|
||||||
Nodes (4): deleteFromDB(), getAllFromDB(), openDB(), processSyncQueue()
|
Nodes (4): deleteFromDB(), getAllFromDB(), openDB(), processSyncQueue()
|
||||||
|
|
||||||
|
### Community 24 - "Community 24"
|
||||||
|
Cohesion: 0.46
|
||||||
|
Nodes (7): checkRateLimit(), corsHeaders(), escapeHtml(), OPTIONS(), POST(), sendContactEmail(), validateContactForm()
|
||||||
|
|
||||||
|
### Community 25 - "Community 25"
|
||||||
|
Cohesion: 0.43
|
||||||
|
Nodes (6): trackCaseStudyView(), trackEvent(), trackExternalLink(), trackFormSubmit(), trackNewsletterSignup(), trackPortfolioFilter()
|
||||||
|
|
||||||
|
### Community 26 - "Community 26"
|
||||||
|
Cohesion: 0.36
|
||||||
|
Nodes (7): extract_scores(), get_issues(), main(), Run Lighthouse audit on a URL, Extract key scores from Lighthouse data, Extract issues from Lighthouse audit, run_lighthouse()
|
||||||
|
|
||||||
### Community 27 - "Community 27"
|
### Community 27 - "Community 27"
|
||||||
Cohesion: 0.48
|
Cohesion: 0.46
|
||||||
Nodes (5): initAllAnimations(), initButtonRipple(), initCounters(), initProgressBars(), initScrollReveal()
|
Nodes (7): captureScreenshot(), ensureDir(), generateIndex(), main(), screenshotPath(), setTheme(), waitForPageReady()
|
||||||
|
|
||||||
### Community 28 - "Community 28"
|
### Community 28 - "Community 28"
|
||||||
Cohesion: 0.48
|
Cohesion: 0.36
|
||||||
Nodes (5): extractJsonLd(), main(), validateOpenGraph(), validatePage(), validateTwitterCard()
|
Nodes (4): deleteFromDB(), getAllFromDB(), openDB(), processSyncQueue()
|
||||||
|
|
||||||
### Community 29 - "Community 29"
|
### Community 29 - "Community 29"
|
||||||
Cohesion: 0.48
|
Cohesion: 0.48
|
||||||
@@ -197,23 +199,31 @@ Cohesion: 0.48
|
|||||||
Nodes (5): extractJsonLd(), main(), validateOpenGraph(), validatePage(), validateTwitterCard()
|
Nodes (5): extractJsonLd(), main(), validateOpenGraph(), validatePage(), validateTwitterCard()
|
||||||
|
|
||||||
### Community 31 - "Community 31"
|
### Community 31 - "Community 31"
|
||||||
Cohesion: 0.47
|
Cohesion: 0.48
|
||||||
Nodes (5): main(), measure_response_time(), print_stats(), Measure response time for a URL over multiple iterations, Print statistics for response times
|
Nodes (5): initAllAnimations(), initButtonRipple(), initCounters(), initProgressBars(), initScrollReveal()
|
||||||
|
|
||||||
|
### Community 32 - "Community 32"
|
||||||
|
Cohesion: 0.48
|
||||||
|
Nodes (5): extractJsonLd(), main(), validateOpenGraph(), validatePage(), validateTwitterCard()
|
||||||
|
|
||||||
### Community 33 - "Community 33"
|
### Community 33 - "Community 33"
|
||||||
Cohesion: 0.47
|
Cohesion: 0.47
|
||||||
Nodes (5): main(), measure_response_time(), print_stats(), Measure response time for a URL over multiple iterations, Print statistics for response times
|
Nodes (5): main(), measure_response_time(), print_stats(), Measure response time for a URL over multiple iterations, Print statistics for response times
|
||||||
|
|
||||||
### Community 35 - "Community 35"
|
### Community 35 - "Community 35"
|
||||||
|
Cohesion: 0.47
|
||||||
|
Nodes (5): main(), measure_response_time(), print_stats(), Measure response time for a URL over multiple iterations, Print statistics for response times
|
||||||
|
|
||||||
|
### Community 37 - "Community 37"
|
||||||
Cohesion: 0.6
|
Cohesion: 0.6
|
||||||
Nodes (3): formatUptime(), GET(), percentile()
|
Nodes (3): formatUptime(), GET(), percentile()
|
||||||
|
|
||||||
### Community 36 - "Community 36"
|
### Community 38 - "Community 38"
|
||||||
Cohesion: 0.6
|
Cohesion: 0.6
|
||||||
Nodes (3): formatUptime(), GET(), percentile()
|
Nodes (3): formatUptime(), GET(), percentile()
|
||||||
|
|
||||||
## Knowledge Gaps
|
## Knowledge Gaps
|
||||||
- **140 isolated node(s):** `Run Lighthouse audit on a URL`, `Extract key scores from Lighthouse data`, `Extract issues from Lighthouse audit`, `Measure response time for a URL over multiple iterations`, `Print statistics for response times` (+135 more)
|
- **156 isolated node(s):** `Run Lighthouse audit on a URL`, `Extract key scores from Lighthouse data`, `Extract issues from Lighthouse audit`, `Measure response time for a URL over multiple iterations`, `Print statistics for response times` (+151 more)
|
||||||
These have ≤1 connection - possible missing edges or undocumented components.
|
These have ≤1 connection - possible missing edges or undocumented components.
|
||||||
- **27 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
|
- **27 thin communities (<3 nodes) omitted from report** — run `graphify query` to explore isolated nodes.
|
||||||
|
|
||||||
@@ -223,7 +233,7 @@ _Questions this graph is uniquely positioned to answer:_
|
|||||||
- **Are the 2 inferred relationships involving `captureException()` (e.g. with `sendContactEmail()` and `subscribeToNewsletter()`) actually correct?**
|
- **Are the 2 inferred relationships involving `captureException()` (e.g. with `sendContactEmail()` and `subscribeToNewsletter()`) actually correct?**
|
||||||
_`captureException()` has 2 INFERRED edges - model-reasoned connections that need verification._
|
_`captureException()` has 2 INFERRED edges - model-reasoned connections that need verification._
|
||||||
- **What connects `Run Lighthouse audit on a URL`, `Extract key scores from Lighthouse data`, `Extract issues from Lighthouse audit` to the rest of the system?**
|
- **What connects `Run Lighthouse audit on a URL`, `Extract key scores from Lighthouse data`, `Extract issues from Lighthouse audit` to the rest of the system?**
|
||||||
_140 weakly-connected nodes found - possible documentation gaps or missing edges._
|
_156 weakly-connected nodes found - possible documentation gaps or missing edges._
|
||||||
- **Should `Community 0` be split into smaller, more focused modules?**
|
- **Should `Community 0` be split into smaller, more focused modules?**
|
||||||
_Cohesion score 0.05 - nodes in this community are weakly interconnected._
|
_Cohesion score 0.05 - nodes in this community are weakly interconnected._
|
||||||
- **Should `Community 1` be split into smaller, more focused modules?**
|
- **Should `Community 1` be split into smaller, more focused modules?**
|
||||||
|
|||||||
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
File diff suppressed because one or more lines are too long
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [{"id": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_middleware_ts", "label": "middleware.ts", "file_type": "code", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L1"}, {"id": "src_middleware_validatecsrforigin", "label": "validateCsrfOrigin()", "file_type": "code", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L19"}], "edges": [{"source": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_middleware_ts", "target": "astro_middleware", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L1", "weight": 1.0}, {"source": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_middleware_ts", "target": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_utils_logger_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L2", "weight": 1.0}, {"source": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_middleware_ts", "target": "utils_logger_logger", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L2", "weight": 1.0}, {"source": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_middleware_ts", "target": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_utils_sentry_ts", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L3", "weight": 1.0}, {"source": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_middleware_ts", "target": "utils_sentry_captureexception", "relation": "imports", "context": "import", "confidence": "EXTRACTED", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L3", "weight": 1.0}, {"source": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_middleware_ts", "target": "src_middleware_validatecsrforigin", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L19", "weight": 1.0}], "raw_calls": [{"caller_nid": "src_middleware_validatecsrforigin", "callee": "includes", "is_member_call": true, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L24"}, {"caller_nid": "src_middleware_validatecsrforigin", "callee": "startsWith", "is_member_call": true, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L25"}, {"caller_nid": "src_middleware_validatecsrforigin", "callee": "get", "is_member_call": true, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L36"}, {"caller_nid": "src_middleware_validatecsrforigin", "callee": "get", "is_member_call": true, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L37"}, {"caller_nid": "src_middleware_validatecsrforigin", "callee": "startsWith", "is_member_call": true, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L52"}, {"caller_nid": "src_middleware_validatecsrforigin", "callee": "startsWith", "is_member_call": true, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/middleware.ts", "source_location": "L52"}]}
|
||||||
Vendored
+1
@@ -0,0 +1 @@
|
|||||||
|
{"nodes": [{"id": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_pages_sitemap_xml_ts", "label": "sitemap.xml.ts", "file_type": "code", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/pages/sitemap.xml.ts", "source_location": "L1"}, {"id": "pages_sitemap_xml_get", "label": "GET()", "file_type": "code", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/pages/sitemap.xml.ts", "source_location": "L13"}], "edges": [{"source": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_pages_sitemap_xml_ts", "target": "astro", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/pages/sitemap.xml.ts", "source_location": "L1", "weight": 1.0}, {"source": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_pages_sitemap_xml_ts", "target": "astro_content", "relation": "imports_from", "context": "import", "confidence": "EXTRACTED", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/pages/sitemap.xml.ts", "source_location": "L2", "weight": 1.0}, {"source": "home_agent_ai_agent_backend_workspace_2e709500_79ab_403f_9ca0_3f027ac9f36e_src_pages_sitemap_xml_ts", "target": "pages_sitemap_xml_get", "relation": "contains", "confidence": "EXTRACTED", "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/pages/sitemap.xml.ts", "source_location": "L13", "weight": 1.0}], "raw_calls": [{"caller_nid": "pages_sitemap_xml_get", "callee": "getCollection", "is_member_call": false, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/pages/sitemap.xml.ts", "source_location": "L15"}, {"caller_nid": "pages_sitemap_xml_get", "callee": "getCollection", "is_member_call": false, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/pages/sitemap.xml.ts", "source_location": "L20"}, {"caller_nid": "pages_sitemap_xml_get", "callee": "map", "is_member_call": true, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/pages/sitemap.xml.ts", "source_location": "L43"}, {"caller_nid": "pages_sitemap_xml_get", "callee": "map", "is_member_call": true, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/pages/sitemap.xml.ts", "source_location": "L52"}, {"caller_nid": "pages_sitemap_xml_get", "callee": "join", "is_member_call": true, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/pages/sitemap.xml.ts", "source_location": "L69"}, {"caller_nid": "pages_sitemap_xml_get", "callee": "map", "is_member_call": true, "source_file": "/home/agent/ai-agent/backend/workspace/2e709500-79ab-403f-9ca0-3f027ac9f36e/src/pages/sitemap.xml.ts", "source_location": "L69"}]}
|
||||||
File diff suppressed because one or more lines are too long
+697
-290
File diff suppressed because it is too large
Load Diff
@@ -58,6 +58,9 @@ Allow: /
|
|||||||
User-agent: GPTBot
|
User-agent: GPTBot
|
||||||
Allow: /
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: OAI-SearchBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
# Anthropic/Claude
|
# Anthropic/Claude
|
||||||
User-agent: anthropic-ai
|
User-agent: anthropic-ai
|
||||||
Allow: /
|
Allow: /
|
||||||
@@ -65,10 +68,22 @@ Allow: /
|
|||||||
User-agent: Claude-Web
|
User-agent: Claude-Web
|
||||||
Allow: /
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: ClaudeBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Claude-SearchBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Claude-User
|
||||||
|
Allow: /
|
||||||
|
|
||||||
# Perplexity AI
|
# Perplexity AI
|
||||||
User-agent: PerplexityBot
|
User-agent: PerplexityBot
|
||||||
Allow: /
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Perplexity-User
|
||||||
|
Allow: /
|
||||||
|
|
||||||
# Google Gemini/Bard
|
# Google Gemini/Bard
|
||||||
User-agent: Google-Extended
|
User-agent: Google-Extended
|
||||||
Allow: /
|
Allow: /
|
||||||
@@ -80,3 +95,40 @@ Allow: /
|
|||||||
# Meta AI
|
# Meta AI
|
||||||
User-agent: FacebookBot
|
User-agent: FacebookBot
|
||||||
Allow: /
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Meta-ExternalAgent
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: meta-externalagent
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
# Apple Intelligence
|
||||||
|
User-agent: Applebot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
User-agent: Applebot-Extended
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
# Amazon AI
|
||||||
|
User-agent: Amazonbot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
# ByteDance / TikTok AI
|
||||||
|
User-agent: Bytespider
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
# Cohere AI
|
||||||
|
User-agent: cohere-ai
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
# DuckDuckGo AI (DuckAssist)
|
||||||
|
User-agent: DuckAssistBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
# You.com AI
|
||||||
|
User-agent: YouBot
|
||||||
|
Allow: /
|
||||||
|
|
||||||
|
# Diffbot (knowledge graph / AI training)
|
||||||
|
User-agent: Diffbot
|
||||||
|
Allow: /
|
||||||
|
|||||||
@@ -0,0 +1,166 @@
|
|||||||
|
/*!
|
||||||
|
* WRNexus Web Push — service worker.
|
||||||
|
*
|
||||||
|
* ┌─────────────────────────────────────────────────────────────────────────┐
|
||||||
|
* │ HOST THIS FILE ON YOUR OWN ORIGIN. │
|
||||||
|
* │ │
|
||||||
|
* │ A service worker can only control the origin it is served from, so the │
|
||||||
|
* │ browser will NOT let wrnexus.com register a worker for your site. Copy │
|
||||||
|
* │ this file to the ROOT of your site and serve it at: │
|
||||||
|
* │ │
|
||||||
|
* │ https://your-domain.example/wrnexus-push-sw.js │
|
||||||
|
* │ │
|
||||||
|
* │ It must be served same-origin, over HTTPS, with │
|
||||||
|
* │ `Content-Type: text/javascript`. To control the whole site from a │
|
||||||
|
* │ non-root path, also send `Service-Worker-Allowed: /`. │
|
||||||
|
* └─────────────────────────────────────────────────────────────────────────┘
|
||||||
|
*
|
||||||
|
* Core behaviour needs NO configuration — the click/delivery tracking URLs are
|
||||||
|
* carried inside each push payload built by the WRNexus API. The optional
|
||||||
|
* CONFIG block below is only used to silently re-subscribe after the browser
|
||||||
|
* rotates a subscription (`pushsubscriptionchange`); leave it blank to skip
|
||||||
|
* that.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* eslint-disable no-restricted-globals */
|
||||||
|
|
||||||
|
// ── OPTIONAL: only needed for automatic re-subscription on key rotation ──────
|
||||||
|
var WRNEXUS_PUSH_CONFIG = {
|
||||||
|
// Your site's publicKey (the same value as data-site-id in the snippet).
|
||||||
|
siteKey: '',
|
||||||
|
// The WRNexus API origin (e.g. 'https://api.wrnexus.com').
|
||||||
|
apiBase: '',
|
||||||
|
// Your site's VAPID public key (shown in Push → Settings).
|
||||||
|
vapidPublicKey: '',
|
||||||
|
};
|
||||||
|
|
||||||
|
self.addEventListener('install', function () {
|
||||||
|
self.skipWaiting();
|
||||||
|
});
|
||||||
|
|
||||||
|
self.addEventListener('activate', function (event) {
|
||||||
|
event.waitUntil(self.clients.claim());
|
||||||
|
});
|
||||||
|
|
||||||
|
// CORS-simple POST (text/plain, no custom headers, no credentials) so the
|
||||||
|
// receipt reaches the WRNexus API cross-origin without a preflight.
|
||||||
|
function postReceipt(url) {
|
||||||
|
if (!url) return Promise.resolve();
|
||||||
|
return fetch(url, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'text/plain;charset=UTF-8' },
|
||||||
|
credentials: 'omit',
|
||||||
|
keepalive: true,
|
||||||
|
mode: 'cors',
|
||||||
|
}).catch(function () {});
|
||||||
|
}
|
||||||
|
|
||||||
|
function urlBase64ToUint8Array(base64String) {
|
||||||
|
var padding = '='.repeat((4 - (base64String.length % 4)) % 4);
|
||||||
|
var base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
|
||||||
|
var raw = self.atob(base64);
|
||||||
|
var out = new Uint8Array(raw.length);
|
||||||
|
for (var i = 0; i < raw.length; ++i) out[i] = raw.charCodeAt(i);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
function keyToB64(buf) {
|
||||||
|
if (!buf) return '';
|
||||||
|
var bytes = new Uint8Array(buf);
|
||||||
|
var binary = '';
|
||||||
|
for (var i = 0; i < bytes.length; i++) binary += String.fromCharCode(bytes[i]);
|
||||||
|
return self
|
||||||
|
.btoa(binary)
|
||||||
|
.replace(/\+/g, '-')
|
||||||
|
.replace(/\//g, '_')
|
||||||
|
.replace(/=+$/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Incoming notification ─────────────────────────────────────────────────
|
||||||
|
self.addEventListener('push', function (event) {
|
||||||
|
var data = {};
|
||||||
|
try {
|
||||||
|
data = event.data ? event.data.json() : {};
|
||||||
|
} catch (_e) {
|
||||||
|
try {
|
||||||
|
data = { title: event.data && event.data.text() };
|
||||||
|
} catch (_e2) {
|
||||||
|
data = {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var title = data.title || 'Notification';
|
||||||
|
var options = {
|
||||||
|
body: data.body || '',
|
||||||
|
icon: data.icon || undefined,
|
||||||
|
image: data.image || undefined,
|
||||||
|
badge: data.badge || undefined,
|
||||||
|
tag: data.tag || data.campaignId || undefined,
|
||||||
|
requireInteraction: !!data.requireInteraction,
|
||||||
|
data: {
|
||||||
|
clickUrl: data.clickUrl || data.url || '/',
|
||||||
|
url: data.url || '/',
|
||||||
|
openUrl: data.openUrl || '',
|
||||||
|
campaignId: data.campaignId || '',
|
||||||
|
subscriptionId: data.subscriptionId || '',
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
event.waitUntil(
|
||||||
|
Promise.all([
|
||||||
|
self.registration.showNotification(title, options),
|
||||||
|
// Delivery receipt — records a `delivered` event for analytics.
|
||||||
|
postReceipt(data.deliveredUrl),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── Click → record + open the destination ─────────────────────────────────
|
||||||
|
self.addEventListener('notificationclick', function (event) {
|
||||||
|
var d = (event.notification && event.notification.data) || {};
|
||||||
|
event.notification.close();
|
||||||
|
|
||||||
|
// `clickUrl` is a signed WRNexus redirect: hitting it records the `clicked`
|
||||||
|
// event and 302s to the real destination, so tracking fires from the open.
|
||||||
|
var target = d.clickUrl || d.url || '/';
|
||||||
|
|
||||||
|
event.waitUntil(
|
||||||
|
self.clients.matchAll({ type: 'window', includeUncontrolled: true }).then(function (list) {
|
||||||
|
// Reuse an existing tab on the destination when possible.
|
||||||
|
for (var i = 0; i < list.length; i++) {
|
||||||
|
var client = list[i];
|
||||||
|
if (d.url && client.url === d.url && 'focus' in client) return client.focus();
|
||||||
|
}
|
||||||
|
if (self.clients.openWindow) return self.clients.openWindow(target);
|
||||||
|
return undefined;
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── Optional: re-subscribe after the browser rotates the subscription ──────
|
||||||
|
self.addEventListener('pushsubscriptionchange', function (event) {
|
||||||
|
var cfg = WRNEXUS_PUSH_CONFIG || {};
|
||||||
|
if (!cfg.siteKey || !cfg.apiBase || !cfg.vapidPublicKey) return;
|
||||||
|
event.waitUntil(
|
||||||
|
self.registration.pushManager
|
||||||
|
.subscribe({ userVisibleOnly: true, applicationServerKey: urlBase64ToUint8Array(cfg.vapidPublicKey) })
|
||||||
|
.then(function (sub) {
|
||||||
|
return fetch(cfg.apiBase.replace(/\/+$/, '') + '/api/push/subscriptions', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'text/plain;charset=UTF-8' },
|
||||||
|
credentials: 'omit',
|
||||||
|
mode: 'cors',
|
||||||
|
body: JSON.stringify({
|
||||||
|
key: cfg.siteKey,
|
||||||
|
endpoint: sub.endpoint,
|
||||||
|
keys: {
|
||||||
|
p256dh: keyToB64(sub.getKey('p256dh')),
|
||||||
|
auth: keyToB64(sub.getKey('auth')),
|
||||||
|
},
|
||||||
|
metadata: { source: 'pushsubscriptionchange' },
|
||||||
|
}),
|
||||||
|
}).catch(function () {});
|
||||||
|
})
|
||||||
|
.catch(function () {})
|
||||||
|
);
|
||||||
|
});
|
||||||
@@ -166,6 +166,23 @@ const currentYear = new Date().getFullYear();
|
|||||||
By subscribing, you agree to our
|
By subscribing, you agree to our
|
||||||
<a href="/privacy" class="text-primary hover:underline">Privacy Policy</a>.
|
<a href="/privacy" class="text-primary hover:underline">Privacy Policy</a>.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
<!-- Web push opt-in (WRNexus). User-gesture subscribe control.
|
||||||
|
Hidden by default; the client script below reveals it only when the
|
||||||
|
WRNexus SDK + browser push support are available, and sets the
|
||||||
|
correct label based on the visitor's current subscription state. -->
|
||||||
|
<button
|
||||||
|
id="wrnexus-subscribe"
|
||||||
|
type="button"
|
||||||
|
hidden
|
||||||
|
aria-label="Enable notifications"
|
||||||
|
class="mt-6 w-full px-4 py-3 bg-secondary-800 border border-secondary-700 text-white font-medium rounded-lg hover:bg-secondary-700 focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 focus:ring-offset-secondary-900 transition-all duration-200 text-sm flex items-center justify-center gap-2 disabled:opacity-60 disabled:cursor-not-allowed"
|
||||||
|
>
|
||||||
|
<svg class="w-4 h-4 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
|
||||||
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 17h5l-1.405-1.405A2.032 2.032 0 0118 14.158V11a6.002 6.002 0 00-4-5.659V5a2 2 0 10-4 0v.341C7.67 6.165 6 8.388 6 11v3.159c0 .538-.214 1.055-.595 1.436L4 17h5m6 0v1a3 3 0 11-6 0v-1m6 0H9" />
|
||||||
|
</svg>
|
||||||
|
<span id="wrnexus-subscribe-label">Enable notifications</span>
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -193,6 +210,106 @@ const currentYear = new Date().getFullYear();
|
|||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
|
<!-- WRNexus push subscribe: state-aware control wired via addEventListener
|
||||||
|
(Astro strips inline on* handlers). The button reflects whether the
|
||||||
|
visitor is already subscribed and lets them toggle the subscription. -->
|
||||||
|
<script is:inline>
|
||||||
|
(function () {
|
||||||
|
function init() {
|
||||||
|
var btn = document.getElementById('wrnexus-subscribe');
|
||||||
|
var label = document.getElementById('wrnexus-subscribe-label');
|
||||||
|
if (!btn || !label) return;
|
||||||
|
|
||||||
|
var push = window.WRNexusPush;
|
||||||
|
var supported =
|
||||||
|
push &&
|
||||||
|
'Notification' in window &&
|
||||||
|
'serviceWorker' in navigator &&
|
||||||
|
'PushManager' in window;
|
||||||
|
|
||||||
|
// No SDK or no browser push support: keep the button hidden entirely.
|
||||||
|
if (!supported) {
|
||||||
|
btn.hidden = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Permission permanently blocked by the user: the SDK can't re-prompt,
|
||||||
|
// so surface a clear, non-actionable disabled state instead of a button
|
||||||
|
// that silently does nothing.
|
||||||
|
if (window.Notification && Notification.permission === 'denied') {
|
||||||
|
label.textContent = 'Notifications blocked';
|
||||||
|
btn.setAttribute('aria-label', 'Notifications are blocked in your browser settings');
|
||||||
|
btn.disabled = true;
|
||||||
|
btn.hidden = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the button for a given subscription state.
|
||||||
|
// Default UX: subscribed users get an actionable "Unsubscribe" toggle
|
||||||
|
// rather than a dead "Already subscribed" label.
|
||||||
|
// (Alternative: render a disabled "Already subscribed" indicator instead
|
||||||
|
// of the Unsubscribe toggle if product prefers a non-actionable state.)
|
||||||
|
function render(subscribed) {
|
||||||
|
if (subscribed) {
|
||||||
|
label.textContent = 'Unsubscribe';
|
||||||
|
btn.setAttribute('aria-label', 'Unsubscribe from notifications');
|
||||||
|
} else {
|
||||||
|
label.textContent = 'Enable notifications';
|
||||||
|
btn.setAttribute('aria-label', 'Enable notifications');
|
||||||
|
}
|
||||||
|
btn.dataset.subscribed = subscribed ? 'true' : 'false';
|
||||||
|
btn.disabled = false;
|
||||||
|
btn.hidden = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
async function refresh() {
|
||||||
|
try {
|
||||||
|
var subscribed = await push.isSubscribed();
|
||||||
|
render(!!subscribed);
|
||||||
|
} catch (err) {
|
||||||
|
// On error, fall back to the unsubscribed label so the control stays usable.
|
||||||
|
console.error('[wrnexus-push] isSubscribed() failed:', err);
|
||||||
|
render(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
btn.addEventListener('click', async function () {
|
||||||
|
if (btn.disabled) return;
|
||||||
|
|
||||||
|
var wasSubscribed = btn.dataset.subscribed === 'true';
|
||||||
|
var busyLabel = wasSubscribed ? 'Unsubscribing…' : 'Enabling…';
|
||||||
|
|
||||||
|
// In-progress state to prevent double-clicks while the promise is pending.
|
||||||
|
btn.disabled = true;
|
||||||
|
label.textContent = busyLabel;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (wasSubscribed) {
|
||||||
|
await push.unsubscribe();
|
||||||
|
} else {
|
||||||
|
// prompt() must run from this real user gesture.
|
||||||
|
await push.prompt();
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
console.error('[wrnexus-push] toggle failed:', err);
|
||||||
|
} finally {
|
||||||
|
// Re-read the authoritative state and re-render the label.
|
||||||
|
await refresh();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Determine and render the initial state.
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (document.readyState === 'loading') {
|
||||||
|
document.addEventListener('DOMContentLoaded', init);
|
||||||
|
} else {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { trackNewsletterSignup } from '../utils/analytics';
|
import { trackNewsletterSignup } from '../utils/analytics';
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@
|
|||||||
// Each answer is written as a definitive, self-contained paragraph: it can be
|
// Each answer is written as a definitive, self-contained paragraph: it can be
|
||||||
// read (or quoted) in isolation without the question for context, and the
|
// read (or quoted) in isolation without the question for context, and the
|
||||||
// buyer-stage answers bundle the WorkRoot name with the canonical numbers
|
// buyer-stage answers bundle the WorkRoot name with the canonical numbers
|
||||||
// (founded 2022 · 20+ projects · 11 districts · 50,000+ records · 99.9%
|
// (founded 2022 · 20+ projects · 11+ districts · 50,000+ records · 99.9%
|
||||||
// uptime · GeM · IIT Patna). Keep every figure identical to <ProofNumbers />
|
// uptime · GeM · IIT Patna). Keep every figure identical to <ProofNumbers />
|
||||||
// and the homepage `companyFacts` set — the visible text below is also the
|
// and the homepage `companyFacts` set — the visible text below is also the
|
||||||
// source for the FAQPage JSON-LD emitted at the bottom of this component.
|
// source for the FAQPage JSON-LD emitted at the bottom of this component.
|
||||||
@@ -54,7 +54,7 @@ const moneyFaqs = [
|
|||||||
{
|
{
|
||||||
question: 'Do you work with government tenders / GeM?',
|
question: 'Do you work with government tenders / GeM?',
|
||||||
answer:
|
answer:
|
||||||
'Yes. WorkRoot IT Solutions is empanelled on the Government e-Marketplace (GeM) for relevant IT service categories and can respond to government tenders. We have delivered public-service platforms live across 11 districts of Bihar at 99.9% uptime, including a Police Management System and a Smart Crematorium Management System for the Bihar Government.',
|
'Yes. WorkRoot IT Solutions is empanelled on the Government e-Marketplace (GeM) for relevant IT service categories and can respond to government tenders. We have delivered public-service platforms live across 11+ districts of Bihar at 99.9% uptime, including a Police Management System and a Smart Crematorium Management System for the Bihar Government.',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
question: 'What technologies do you work with?',
|
question: 'What technologies do you work with?',
|
||||||
|
|||||||
@@ -40,12 +40,12 @@ interface Props {
|
|||||||
// credibility bug this set was created to fix.
|
// credibility bug this set was created to fix.
|
||||||
//
|
//
|
||||||
// - "20+ Projects" — total delivered engagements
|
// - "20+ Projects" — total delivered engagements
|
||||||
// - "11 Districts Deployed" — matches hero trust badge copy
|
// - "11+ Districts Deployed" — cumulative Bihar government district reach
|
||||||
// - "50,000+ Records Managed" — records under management across deployments
|
// - "50,000+ Records Managed" — records under management across deployments
|
||||||
// - "8+ Years Avg Experience" — average team experience
|
// - "8+ Years Avg Experience" — average team experience
|
||||||
const defaultItems: ProofItem[] = [
|
const defaultItems: ProofItem[] = [
|
||||||
{ value: '20+', label: 'Projects' },
|
{ value: '20+', label: 'Projects' },
|
||||||
{ value: '11', label: 'Districts Deployed' },
|
{ value: '11+', label: 'Districts Deployed' },
|
||||||
{ value: '50,000+', label: 'Records Managed' },
|
{ value: '50,000+', label: 'Records Managed' },
|
||||||
{ value: '8+', label: 'Years Avg Experience' },
|
{ value: '8+', label: 'Years Avg Experience' },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ const orgId = `${baseUrl}/#organization`;
|
|||||||
// src/pages/index.astro). All three are 5★, so the aggregate rating is 5.0
|
// src/pages/index.astro). All three are 5★, so the aggregate rating is 5.0
|
||||||
// over reviewCount = 3.
|
// over reviewCount = 3.
|
||||||
//
|
//
|
||||||
// Headline proof numbers in the description (20+ projects · 11 districts ·
|
// Headline proof numbers in the description (20+ projects · 11+ districts ·
|
||||||
// 50,000+ records · 99.9% uptime) mirror the canonical set in
|
// 50,000+ records · 99.9% uptime) mirror the canonical set in
|
||||||
// ProofNumbers.astro and the /services stats — keep them identical site-wide.
|
// ProofNumbers.astro and the /services stats — keep them identical site-wide.
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
@@ -102,7 +102,7 @@ const organizationSchema = {
|
|||||||
"height": "512"
|
"height": "512"
|
||||||
},
|
},
|
||||||
"image": `${baseUrl}/og-image.jpg`,
|
"image": `${baseUrl}/og-image.jpg`,
|
||||||
"description": "WorkRoot IT Solutions LLP builds production-grade web, mobile, ERP, and government IT systems — 20+ projects delivered across 11 districts, 50,000+ records managed, and 99.9% uptime on mission-critical government deployments.",
|
"description": "WorkRoot IT Solutions LLP builds production-grade web, mobile, ERP, and government IT systems — 20+ projects delivered across 11+ districts, 50,000+ records managed, and 99.9% uptime on mission-critical government deployments.",
|
||||||
"foundingDate": "2022",
|
"foundingDate": "2022",
|
||||||
"founder": {
|
"founder": {
|
||||||
"@type": "Person",
|
"@type": "Person",
|
||||||
@@ -238,7 +238,7 @@ const blogPostingSchema = article && type === 'BlogPosting' ? {
|
|||||||
"dateModified": article.dateModified || article.datePublished,
|
"dateModified": article.dateModified || article.datePublished,
|
||||||
"publisher": {
|
"publisher": {
|
||||||
"@type": "Organization",
|
"@type": "Organization",
|
||||||
"name": "WorkRoot IT Solutions",
|
"name": "WorkRoot IT Solutions LLP",
|
||||||
"url": baseUrl,
|
"url": baseUrl,
|
||||||
"logo": {
|
"logo": {
|
||||||
"@type": "ImageObject",
|
"@type": "ImageObject",
|
||||||
@@ -298,7 +298,7 @@ const webPageSchema = type === 'WebPage' && Astro.url.pathname !== '/' ? {
|
|||||||
},
|
},
|
||||||
"about": {
|
"about": {
|
||||||
"@type": "Organization",
|
"@type": "Organization",
|
||||||
"name": "WorkRoot IT Solutions"
|
"name": "WorkRoot IT Solutions LLP"
|
||||||
},
|
},
|
||||||
"primaryImageOfPage": {
|
"primaryImageOfPage": {
|
||||||
"@type": "ImageObject",
|
"@type": "ImageObject",
|
||||||
@@ -330,7 +330,7 @@ const aboutPageSchema = type === 'AboutPage' ? {
|
|||||||
"inLanguage": "en-US",
|
"inLanguage": "en-US",
|
||||||
"mainEntity": {
|
"mainEntity": {
|
||||||
"@type": "Organization",
|
"@type": "Organization",
|
||||||
"name": "WorkRoot IT Solutions",
|
"name": "WorkRoot IT Solutions LLP",
|
||||||
"url": baseUrl
|
"url": baseUrl
|
||||||
}
|
}
|
||||||
} : null;
|
} : null;
|
||||||
@@ -345,8 +345,8 @@ const contactPageSchema = type === 'ContactPage' ? {
|
|||||||
"inLanguage": "en-US",
|
"inLanguage": "en-US",
|
||||||
"mainEntity": {
|
"mainEntity": {
|
||||||
"@type": "LocalBusiness",
|
"@type": "LocalBusiness",
|
||||||
"name": "WorkRoot IT Solutions",
|
"name": "WorkRoot IT Solutions LLP",
|
||||||
"alternateName": "WorkRoot IT Solutions LLP",
|
"alternateName": "WorkRoot IT Solutions",
|
||||||
"url": baseUrl,
|
"url": baseUrl,
|
||||||
"telephone": "+91-9561417403",
|
"telephone": "+91-9561417403",
|
||||||
"email": "admin@workroot.in",
|
"email": "admin@workroot.in",
|
||||||
|
|||||||
@@ -181,6 +181,17 @@ const fullTitle = title === 'Home' ? homeTitle : `${title} | ${brand}`;
|
|||||||
<!-- Analytics (GA4 or Plausible) -->
|
<!-- Analytics (GA4 or Plausible) -->
|
||||||
<Analytics />
|
<Analytics />
|
||||||
|
|
||||||
|
<!-- WRNexus Web Push SDK — loaded once globally so it runs on every page
|
||||||
|
that should collect push subscribers. is:inline keeps Astro's bundler
|
||||||
|
from rewriting the external src and preserves data-site-id / defer. -->
|
||||||
|
<script is:inline src="https://api.wrnexus.com/push/sdk.js" data-site-id="pk_rP51XN8tZnud5HdX9UqidjHk" defer></script>
|
||||||
|
|
||||||
|
<!-- WRNexus Bot Widget — loaded once globally here so the chat widget
|
||||||
|
renders on every route (pages + blog posts) via this shared layout.
|
||||||
|
is:inline keeps Astro's bundler from rewriting the external src and
|
||||||
|
preserves data-bot-id / async. -->
|
||||||
|
<script is:inline src="https://api.wrnexus.com/bots/widget.js" data-bot-id="d3998f1b-51d7-4f7c-a57e-3fa1af4394a0" async></script>
|
||||||
|
|
||||||
<!-- Additional head content slot -->
|
<!-- Additional head content slot -->
|
||||||
<slot name="head" />
|
<slot name="head" />
|
||||||
</head>
|
</head>
|
||||||
|
|||||||
+6
-4
@@ -155,11 +155,13 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|||||||
// - inline scripts/styles: Required for Astro framework
|
// - inline scripts/styles: Required for Astro framework
|
||||||
// - https://www.googletagmanager.com & https://www.google-analytics.com: GA4
|
// - https://www.googletagmanager.com & https://www.google-analytics.com: GA4
|
||||||
// - https://plausible.io: Plausible Analytics
|
// - https://plausible.io: Plausible Analytics
|
||||||
|
// - https://api.wrnexus.com: WRNexus web-push SDK (sdk.js), bot widget
|
||||||
|
// (bots/widget.js) + runtime config/iframe served from the same origin
|
||||||
// Note: unsafe-eval is removed in production (only needed during Astro HMR dev mode)
|
// Note: unsafe-eval is removed in production (only needed during Astro HMR dev mode)
|
||||||
const isProduction = import.meta.env.PROD;
|
const isProduction = import.meta.env.PROD;
|
||||||
const scriptSrc = isProduction
|
const scriptSrc = isProduction
|
||||||
? "script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com https://plausible.io"
|
? "script-src 'self' 'unsafe-inline' https://www.googletagmanager.com https://www.google-analytics.com https://plausible.io https://api.wrnexus.com"
|
||||||
: "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com https://plausible.io";
|
: "script-src 'self' 'unsafe-inline' 'unsafe-eval' https://www.googletagmanager.com https://www.google-analytics.com https://plausible.io https://api.wrnexus.com";
|
||||||
|
|
||||||
const csp = [
|
const csp = [
|
||||||
"default-src 'self'",
|
"default-src 'self'",
|
||||||
@@ -167,11 +169,11 @@ export const onRequest = defineMiddleware(async (context, next) => {
|
|||||||
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
|
"style-src 'self' 'unsafe-inline' https://fonts.googleapis.com",
|
||||||
"img-src 'self' data: https://images.unsplash.com https://www.google-analytics.com https://www.googletagmanager.com https://maps.googleapis.com https://maps.gstatic.com",
|
"img-src 'self' data: https://images.unsplash.com https://www.google-analytics.com https://www.googletagmanager.com https://maps.googleapis.com https://maps.gstatic.com",
|
||||||
"font-src 'self' data: https://fonts.gstatic.com",
|
"font-src 'self' data: https://fonts.gstatic.com",
|
||||||
"connect-src 'self' https://www.google-analytics.com https://analytics.google.com https://stats.g.doubleclick.net https://plausible.io",
|
"connect-src 'self' https://www.google-analytics.com https://analytics.google.com https://stats.g.doubleclick.net https://plausible.io https://api.wrnexus.com",
|
||||||
"worker-src 'self'",
|
"worker-src 'self'",
|
||||||
"manifest-src 'self'",
|
"manifest-src 'self'",
|
||||||
"object-src 'none'", // Block Flash/plugins (defense-in-depth)
|
"object-src 'none'", // Block Flash/plugins (defense-in-depth)
|
||||||
"frame-src https://www.google.com", // Allow Google Maps iframe embed
|
"frame-src https://www.google.com https://api.wrnexus.com", // Google Maps iframe + WRNexus bot widget iframe
|
||||||
"frame-ancestors 'none'",
|
"frame-ancestors 'none'",
|
||||||
"base-uri 'self'",
|
"base-uri 'self'",
|
||||||
"form-action 'self'",
|
"form-action 'self'",
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ const teamMembers = [
|
|||||||
// stats counters) so the numbers never contradict across pages.
|
// stats counters) so the numbers never contradict across pages.
|
||||||
const stats = [
|
const stats = [
|
||||||
{ value: '20+', label: 'Projects' },
|
{ value: '20+', label: 'Projects' },
|
||||||
{ value: '11', label: 'Districts Deployed' },
|
{ value: '11+', label: 'Districts Deployed' },
|
||||||
{ value: '50,000+', label: 'Records Managed' },
|
{ value: '50,000+', label: 'Records Managed' },
|
||||||
{ value: '8+', label: 'Years Avg Experience' },
|
{ value: '8+', label: 'Years Avg Experience' },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -44,8 +44,8 @@ const services = [
|
|||||||
slug: 'government-systems',
|
slug: 'government-systems',
|
||||||
title: 'Government IT Solutions',
|
title: 'Government IT Solutions',
|
||||||
outcome: 'Roll out secure, compliant platforms across districts without rewriting them for each one.',
|
outcome: 'Roll out secure, compliant platforms across districts without rewriting them for each one.',
|
||||||
description: 'GeM-empanelled and already live across 11 districts at 99.9% uptime — role-based access, audit trails, and the security public services demand.',
|
description: 'GeM-empanelled and already live across 11+ districts at 99.9% uptime — role-based access, audit trails, and the security public services demand.',
|
||||||
features: ['Live in 11 Districts', 'GeM-Empanelled & Compliant', '99.9% Uptime'],
|
features: ['Live in 11+ Districts', 'GeM-Empanelled & Compliant', '99.9% Uptime'],
|
||||||
cta: 'Discuss your government project',
|
cta: 'Discuss your government project',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
@@ -124,7 +124,7 @@ const testimonials = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
// NOTE: The homepage stat band is rendered once by <ProofNumbers />, which
|
// NOTE: The homepage stat band is rendered once by <ProofNumbers />, which
|
||||||
// holds the canonical site-wide proof set (20+ Projects · 11 Districts ·
|
// holds the canonical site-wide proof set (20+ Projects · 11+ Districts ·
|
||||||
// 50,000+ Records · 8+ Years). The previously-duplicated "Numbers That
|
// 50,000+ Records · 8+ Years). The previously-duplicated "Numbers That
|
||||||
// Matter" stats section (and its local `stats` array + count-up script) was
|
// Matter" stats section (and its local `stats` array + count-up script) was
|
||||||
// removed so a visitor never sees the same four numbers twice on one page.
|
// removed so a visitor never sees the same four numbers twice on one page.
|
||||||
@@ -182,7 +182,7 @@ const techStack = [
|
|||||||
// this canonical set was created to fix.
|
// this canonical set was created to fix.
|
||||||
const companyFacts = [
|
const companyFacts = [
|
||||||
'WorkRoot IT Solutions was founded in 2022 and has delivered 20+ production software systems for startups, enterprises, and government bodies.',
|
'WorkRoot IT Solutions was founded in 2022 and has delivered 20+ production software systems for startups, enterprises, and government bodies.',
|
||||||
'WorkRoot IT Solutions runs government platforms across 11 districts of Bihar, India, sustaining 99.9% uptime on mission-critical public services.',
|
'WorkRoot IT Solutions runs government platforms across 11+ districts of Bihar, India, sustaining 99.9% uptime on mission-critical public services.',
|
||||||
'WorkRoot IT Solutions manages 50,000+ live records across its government and enterprise deployments.',
|
'WorkRoot IT Solutions manages 50,000+ live records across its government and enterprise deployments.',
|
||||||
'WorkRoot IT Solutions built the University Management System for IIT Patna on a Next.js and Spring Boot stack.',
|
'WorkRoot IT Solutions built the University Management System for IIT Patna on a Next.js and Spring Boot stack.',
|
||||||
'WorkRoot IT Solutions is empanelled on the Government e-Marketplace (GeM), making it eligible to bid on Indian government IT tenders.',
|
'WorkRoot IT Solutions is empanelled on the Government e-Marketplace (GeM), making it eligible to bid on Indian government IT tenders.',
|
||||||
@@ -194,19 +194,19 @@ const companyFacts = [
|
|||||||
// Mirrors the deeper table on /services/custom-erp-development, surfaced on the
|
// Mirrors the deeper table on /services/custom-erp-development, surfaced on the
|
||||||
// homepage so the core buying trade-off is framed before a late-stage visitor
|
// homepage so the core buying trade-off is framed before a late-stage visitor
|
||||||
// reaches the inline lead form. The final row carries the canonical
|
// reaches the inline lead form. The final row carries the canonical
|
||||||
// "11 districts · 99.9% uptime" proof point.
|
// "11+ districts · 99.9% uptime" proof point.
|
||||||
const comparison = [
|
const comparison = [
|
||||||
{ dimension: 'Fit to your workflow', offShelf: 'You reshape your process to fit the software', custom: 'The software is built around your exact process' },
|
{ dimension: 'Fit to your workflow', offShelf: 'You reshape your process to fit the software', custom: 'The software is built around your exact process' },
|
||||||
{ dimension: 'Source-code ownership', offShelf: 'Vendor-locked, closed source', custom: 'Full IP transfer on delivery — you own the code' },
|
{ dimension: 'Source-code ownership', offShelf: 'Vendor-locked, closed source', custom: 'Full IP transfer on delivery — you own the code' },
|
||||||
{ dimension: 'Licensing cost', offShelf: 'Recurring per-seat fees that grow with headcount', custom: 'One-time build — no per-seat licence tax' },
|
{ dimension: 'Licensing cost', offShelf: 'Recurring per-seat fees that grow with headcount', custom: 'One-time build — no per-seat licence tax' },
|
||||||
{ dimension: 'Data residency', offShelf: 'The vendor’s cloud and region', custom: 'Your servers, your region, your control' },
|
{ dimension: 'Data residency', offShelf: 'The vendor’s cloud and region', custom: 'Your servers, your region, your control' },
|
||||||
{ dimension: 'Proven at scale', offShelf: 'Generic, one-size-fits-all', custom: 'Live across 11 districts at 99.9% uptime' },
|
{ dimension: 'Proven at scale', offShelf: 'Generic, one-size-fits-all', custom: 'Live across 11+ districts at 99.9% uptime' },
|
||||||
];
|
];
|
||||||
---
|
---
|
||||||
|
|
||||||
<BaseLayout
|
<BaseLayout
|
||||||
title="Home"
|
title="Home"
|
||||||
description="WorkRoot IT Solutions builds production-grade web, mobile, ERP, and government IT systems. 20+ projects delivered across 11 districts with 99.9% uptime."
|
description="WorkRoot IT Solutions builds production-grade web, mobile, ERP, and government IT systems. 20+ projects delivered across 11+ districts with 99.9% uptime."
|
||||||
>
|
>
|
||||||
<SEO
|
<SEO
|
||||||
slot="head"
|
slot="head"
|
||||||
@@ -239,7 +239,7 @@ const comparison = [
|
|||||||
<svg class="w-5 h-5 text-accent-400" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
<svg class="w-5 h-5 text-accent-400" fill="currentColor" viewBox="0 0 20 20" aria-hidden="true">
|
||||||
<path fill-rule="evenodd" d="M6.267 3.455a3.066 3.066 0 001.745-.723 3.066 3.066 0 013.976 0 3.066 3.066 0 001.745.723 3.066 3.066 0 012.812 2.812c.051.643.304 1.254.723 1.745a3.066 3.066 0 010 3.976 3.066 3.066 0 00-.723 1.745 3.066 3.066 0 01-2.812 2.812 3.066 3.066 0 00-1.745.723 3.066 3.066 0 01-3.976 0 3.066 3.066 0 00-1.745-.723 3.066 3.066 0 01-2.812-2.812 3.066 3.066 0 00-.723-1.745 3.066 3.066 0 010-3.976 3.066 3.066 0 00.723-1.745 3.066 3.066 0 012.812-2.812zm7.44 5.252a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
<path fill-rule="evenodd" d="M6.267 3.455a3.066 3.066 0 001.745-.723 3.066 3.066 0 013.976 0 3.066 3.066 0 001.745.723 3.066 3.066 0 012.812 2.812c.051.643.304 1.254.723 1.745a3.066 3.066 0 010 3.976 3.066 3.066 0 00-.723 1.745 3.066 3.066 0 01-2.812 2.812 3.066 3.066 0 00-1.745.723 3.066 3.066 0 01-3.976 0 3.066 3.066 0 00-1.745-.723 3.066 3.066 0 01-2.812-2.812 3.066 3.066 0 00-.723-1.745 3.066 3.066 0 010-3.976 3.066 3.066 0 00.723-1.745 3.066 3.066 0 012.812-2.812zm7.44 5.252a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
|
||||||
</svg>
|
</svg>
|
||||||
<span class="text-sm font-medium text-white">Trusted by 20+ teams · Deployed across 11 districts</span>
|
<span class="text-sm font-medium text-white">Trusted by 20+ teams · Deployed across 11+ districts</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Main heading — benefit-led: outcome + audience -->
|
<!-- Main heading — benefit-led: outcome + audience -->
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ const featuredProjects = projects.filter(p => p.featured);
|
|||||||
<div class="mt-14 grid grid-cols-2 sm:grid-cols-4 gap-4 lg:gap-6 reveal-on-scroll reveal-delay-2">
|
<div class="mt-14 grid grid-cols-2 sm:grid-cols-4 gap-4 lg:gap-6 reveal-on-scroll reveal-delay-2">
|
||||||
{[
|
{[
|
||||||
{ value: '20+', label: 'Projects' },
|
{ value: '20+', label: 'Projects' },
|
||||||
{ value: '11', label: 'Districts Deployed' },
|
{ value: '11+', label: 'Districts Deployed' },
|
||||||
{ value: '50,000+', label: 'Records Managed' },
|
{ value: '50,000+', label: 'Records Managed' },
|
||||||
{ value: '8+', label: 'Years Avg Experience' },
|
{ value: '8+', label: 'Years Avg Experience' },
|
||||||
].map((stat) => (
|
].map((stat) => (
|
||||||
|
|||||||
@@ -294,7 +294,7 @@ const processSteps = [
|
|||||||
|
|
||||||
<BaseLayout
|
<BaseLayout
|
||||||
title="ERP, Web & Mobile App Development Services"
|
title="ERP, Web & Mobile App Development Services"
|
||||||
description="Custom web development, mobile apps, ERP platforms, and government IT solutions from WorkRoot. 20+ projects delivered across 11 districts — get a free quote."
|
description="Custom web development, mobile apps, ERP platforms, and government IT solutions from WorkRoot. 20+ projects delivered across 11+ districts — get a free quote."
|
||||||
>
|
>
|
||||||
<SEO
|
<SEO
|
||||||
slot="head"
|
slot="head"
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
// ServiceFaq) and feeds Service + FAQ schema into SEO.astro.
|
// ServiceFaq) and feeds Service + FAQ schema into SEO.astro.
|
||||||
//
|
//
|
||||||
// All company stats mirror the canonical site-wide set used in
|
// All company stats mirror the canonical site-wide set used in
|
||||||
// ProofNumbers.astro, /portfolio, and SEO.astro — 20+ projects · 11 districts ·
|
// ProofNumbers.astro, /portfolio, and SEO.astro — 20+ projects · 11+ districts ·
|
||||||
// 50,000+ records · 99.9% uptime · 8+ years. Case-study numbers are taken
|
// 50,000+ records · 99.9% uptime · 8+ years. Case-study numbers are taken
|
||||||
// verbatim from the IIT Patna and Bihar government case studies on /portfolio.
|
// verbatim from the IIT Patna and Bihar government case studies on /portfolio.
|
||||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||||
@@ -44,7 +44,7 @@ const comparison = [
|
|||||||
const stats = [
|
const stats = [
|
||||||
{ value: '5+', label: 'ERP & enterprise deployments' },
|
{ value: '5+', label: 'ERP & enterprise deployments' },
|
||||||
{ value: '20,000+', label: 'Users across systems' },
|
{ value: '20,000+', label: 'Users across systems' },
|
||||||
{ value: '11', label: 'Districts running our platforms' },
|
{ value: '11+', label: 'Districts running our platforms' },
|
||||||
{ value: '99.9%', label: 'Uptime on critical systems' },
|
{ value: '99.9%', label: 'Uptime on critical systems' },
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
// schema into SEO.astro.
|
// schema into SEO.astro.
|
||||||
//
|
//
|
||||||
// Canonical stats mirror ProofNumbers.astro / /portfolio / SEO.astro:
|
// Canonical stats mirror ProofNumbers.astro / /portfolio / SEO.astro:
|
||||||
// 20+ projects · 11 districts · 50,000+ records · 99.9% uptime · 8+ years.
|
// 20+ projects · 11+ districts · 50,000+ records · 99.9% uptime · 8+ years.
|
||||||
|
// (This page's own hero stat shows "11" — the specific Bihar deployment
|
||||||
|
// underpinning the company-wide "11+" figure; do not inflate it.)
|
||||||
import BaseLayout from '../../layouts/BaseLayout.astro';
|
import BaseLayout from '../../layouts/BaseLayout.astro';
|
||||||
import SEO from '../../components/SEO.astro';
|
import SEO from '../../components/SEO.astro';
|
||||||
import GuaranteeBand from '../../components/GuaranteeBand.astro';
|
import GuaranteeBand from '../../components/GuaranteeBand.astro';
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ const sitemapSections = [
|
|||||||
links: [
|
links: [
|
||||||
{ name: 'Custom ERP Development', url: '/services/custom-erp-development', description: 'Bespoke enterprise systems on Spring Boot & Angular' },
|
{ name: 'Custom ERP Development', url: '/services/custom-erp-development', description: 'Bespoke enterprise systems on Spring Boot & Angular' },
|
||||||
{ name: 'University ERP', url: '/services/university-erp', description: 'Admissions, exams, grading — built for IIT Patna' },
|
{ name: 'University ERP', url: '/services/university-erp', description: 'Admissions, exams, grading — built for IIT Patna' },
|
||||||
{ name: 'Government IT & GeM Vendor', url: '/services/government-it-solutions-gem-vendor', description: 'GeM-empanelled, live across 11 districts' },
|
{ name: 'Government IT & GeM Vendor', url: '/services/government-it-solutions-gem-vendor', description: 'GeM-empanelled, live across 11+ districts' },
|
||||||
{ name: 'Police Management System', url: '/services/police-management-system', description: 'FIR, case tracking & personnel for 15,000+ officers' },
|
{ name: 'Police Management System', url: '/services/police-management-system', description: 'FIR, case tracking & personnel for 15,000+ officers' },
|
||||||
{ name: 'React Native App Development', url: '/services/react-native-app-development', description: 'One codebase for iOS and Android' },
|
{ name: 'React Native App Development', url: '/services/react-native-app-development', description: 'One codebase for iOS and Android' },
|
||||||
],
|
],
|
||||||
|
|||||||
+2
-2
@@ -84,7 +84,7 @@ export function generateArticleSchema(
|
|||||||
},
|
},
|
||||||
publisher: {
|
publisher: {
|
||||||
'@type': 'Organization',
|
'@type': 'Organization',
|
||||||
name: 'WorkRoot IT Solutions',
|
name: 'WorkRoot IT Solutions LLP',
|
||||||
logo: {
|
logo: {
|
||||||
'@type': 'ImageObject',
|
'@type': 'ImageObject',
|
||||||
url: 'https://workroot.in/logo.png',
|
url: 'https://workroot.in/logo.png',
|
||||||
@@ -132,7 +132,7 @@ export function generateServiceSchema(
|
|||||||
description: description,
|
description: description,
|
||||||
provider: {
|
provider: {
|
||||||
'@type': 'Organization',
|
'@type': 'Organization',
|
||||||
name: 'WorkRoot IT Solutions',
|
name: 'WorkRoot IT Solutions LLP',
|
||||||
url: siteUrl,
|
url: siteUrl,
|
||||||
},
|
},
|
||||||
areaServed: {
|
areaServed: {
|
||||||
|
|||||||
Reference in New Issue
Block a user