Repository navigation
[GSoC 2026] Building a Decentralized Analytics dApp for Bio-Block - Final Report #254
santhil-cyber
started this conversation in
Show and tell
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Building a Decentralized Analytics dApp for Bio-Block — GSoC 2026 Final Report
Introduction
Hi! I'm Santhil, and over the summer of 2026, I had the privilege of working as a Google Summer of Code contributor with Alaska (University of Alaska / Healthy Inc) on Bio-Block.
Bio-Block is an open-source decentralized healthcare data marketplace built on Ethereum and IPFS. Prior to this summer, Bio-Block successfully handled the core data exchange lifecycle: patient data upload, automated de-identification, client-side encryption, marketplace listing, and secure acquisition. However, the data custody chain abruptly broke at download.
Once researchers purchased and decrypted a dataset, they had to export raw clinical data into external tools (like R, Python notebooks, or Excel). This introduced three critical limitations:
My project bridged this gap by designing and implementing a complete, decentralized analytics and attestation layer — establishing an unbroken lifecycle:
$$\text{Upload} \longrightarrow \text{Anonymize} \longrightarrow \text{Encrypt} \longrightarrow \text{Sell} \longrightarrow \text{Download} \longrightarrow \textbf{Analyze} \longrightarrow \textbf{Attest}$$
Project Overview
Core Objectives & Design Goals
Instead of treating data download as the final step, this project transforms Bio-Block into an end-to-end research workbench where findings are computed in a privacy-preserving environment, stored on IPFS, and permanently attested on Ethereum Sepolia via our custom
AnalyticsRegistrysmart contract.Architecture and Components
graph TB subgraph Frontend["Next.js Frontend (Port 3000)"] SD[SearchData.tsx<br/>Purchase & Decrypt Flow] AD[Analytics Dashboard<br/>Descriptive · Graphical · Inferential] AS[analyticsService.ts<br/>EIP-712 Signing & API Client] CS[contractService.ts<br/>AnalyticsRegistry Interface] end subgraph HypLab["Hypothesis Lab — Vite + React (Port 5174)"] TP[TreePane<br/>Interactive Decision Tree] DP[DatasetPane<br/>Dataset Profile & Columns] RP[ResearchPane<br/>Hypotheses & Results] RC[ResultCard + GraphicalView<br/>Statistical Output & Charts] AB[AttestButton<br/>EIP-712 Wallet Signing] PL[ProvenanceLedger<br/>On-chain Attestation History] HAPI[api/client.js<br/>Session & Analysis API Client] HATT[api/attestation.js<br/>Attestation API Client] end subgraph AnalyticsAPI["Analytics API — FastAPI (Port 3003)"] MAIN[main.py<br/>Core API Application] DEMO[demo_router.py<br/>Hypothesis Lab Endpoints] AUTH[EIP-712 Auth Module<br/>eip712.py · dependencies.py] RL[Rate Limiter<br/>Per-wallet sliding window] DESC[Descriptive Engine<br/>pandas · numpy] VIZ[Visualization Engine<br/>matplotlib · plotly] INFER[Inferential Engine<br/>scipy.stats · statsmodels] HYP[Hypothesis Tree<br/>Decision Engine] PROF[Dataset Profiler<br/>Automated Analysis] SESS[Session Manager<br/>demo_sessions.py] CSV[CSV Parser<br/>Robust parsing + validation] SER[Result Serializer] IPFS_UP[IPFS Uploader<br/>Pinata Integration] CHAIN[Chain Registry<br/>On-chain Registration] end subgraph JSBackend["JS Backend (Port 3001)"] IPFS_CTRL[ipfsController.js<br/>Pinata Uploads] ANON_CTRL[anonymizeController.js] AUDIT[AuditLogger<br/>HIPAA §164.312] end subgraph PyBackend["Python Backend (Port 3002)"] CHROMA[ChromaDB Search] IMG_ANON[Image Anonymization] end subgraph Blockchain["Ethereum (Sepolia Testnet)"] DOC_SOL[DocumentStorage.sol<br/>Data Marketplace Contract] ANA_SOL[AnalyticsRegistry.sol<br/>Result Attestation Contract] end subgraph Storage["IPFS (Pinata)"] DATASETS[(Encrypted Datasets)] RESULTS[(Analytics Results)] end SD -->|"Decrypted CSV"| AD SD -->|"Launch Hypothesis Lab"| HypLab AD -->|"EIP-712 Signed Request"| AS AS -->|"API Calls"| MAIN CS -->|"On-chain Queries"| ANA_SOL HAPI -->|"/demo/hypothesis-tree/*"| DEMO HATT -->|"Attestation Request"| DEMO AB -->|"EIP-712 Sign"| HATT PL -->|"Query Attestations"| HATT MAIN --> AUTH MAIN --> RL MAIN --> DESC MAIN --> VIZ MAIN --> INFER MAIN --> HYP MAIN --> CSV DEMO --> SESS DEMO --> HYP DEMO --> INFER DEMO --> IPFS_UP AUTH -->|"Verify Purchase"| DOC_SOL DESC --> SER VIZ --> SER INFER --> SER SER --> IPFS_UP IPFS_UP -->|"Upload Result"| RESULTS IPFS_UP --> CHAIN CHAIN -->|"Register CID"| ANA_SOL IPFS_CTRL -->|"Fetch/Upload"| DATASETS IPFS_CTRL -->|"Fetch/Upload"| RESULTS style Frontend fill:#1a1a2e,stroke:#e94560,color:#fff style HypLab fill:#1a1a2e,stroke:#e94560,color:#fff style AnalyticsAPI fill:#16213e,stroke:#0f3460,color:#fff style JSBackend fill:#1a1a2e,stroke:#533483,color:#fff style PyBackend fill:#1a1a2e,stroke:#533483,color:#fff style Blockchain fill:#0f3460,stroke:#e94560,color:#fff style Storage fill:#16213e,stroke:#0f3460,color:#fffThe analytics layer is built as a new microservice that integrates with Bio-Block's existing infrastructure through precisely defined touchpoints:
Analytics API (FastAPI on port 3003)
A dedicated Python microservice architecturally parallel to the existing Python backend (port 3002). It handles CSV uploads, descriptive/graphical/inferential analysis, result serialization, IPFS storage, and on-chain attestation. Keeping analytics separate from the core platform prevents heavy libraries (pandas, scipy, statsmodels, matplotlib) from affecting existing service stability.
AnalyticsRegistry.sol(Ethereum Sepolia)A lightweight on-chain registry contract that links analytics result CIDs to source dataset CIDs. Uses a relayer pattern — the server wallet submits transactions on behalf of EIP-712-authenticated users, so researchers don't pay gas. Designed for future L2 migration (Polygon/Arbitrum).
EIP-712 Authentication Module
Zero-trust authentication using typed structured data signatures. Every analytics request carries a signed payload containing
timestamp,nonce,datasetCID, andrequestHash. The backend enforces a 5-minute expiration window and per-wallet nonce tracking to prevent replay and parameter-tampering attacks.Next.js Frontend Integration
Extended
SearchData.tsxwith an "Analyze This Dataset" button that appears post-purchase. TheanalyticsService.tsclient handles EIP-712 signing and API calls, whilecontractService.tswas extended withregisterAnalytics()andgetAnalyticsForDataset()functions.Statistical Decision Engine & Hypothesis Tree
Choosing the correct statistical test in biomedical research is critical: violating assumptions like normality, homoscedasticity (equal variances), or independence leads to invalid p-values and unreplicable findings. To solve this, I designed and implemented the Interactive Hypothesis Tree Decision Engine (
hypothesis_tree.py).The engine dynamically inspects dataset column types, sample distributions (Shapiro-Wilk, skewness, kurtosis), variance equality (Levene's test), and experimental designs to guide researchers toward statistically sound conclusions:
graph TD Start([Research Question / Goal]) --> GoalType{What is the Research Goal?} %% Goal: Compare Groups GoalType -->|Compare Groups| SampleType{Sample Design?} SampleType -->|Independent Groups| NumGroups{How many groups?} NumGroups -->|2 Groups| NormCheck2{Normality & Variance?} NormCheck2 -->|Normal & Equal Var| TTest["Student's t-test<br/>(Max power, equal variances)"] NormCheck2 -->|Normal & Unequal Var| WelchT["Welch's t-test<br/>(Robust to heteroscedasticity)"] NormCheck2 -->|Skewed / Non-normal / n<30| MWU["Mann-Whitney U test<br/>(Rank-based non-parametric)"] NumGroups -->|3+ Groups| NormCheckMulti{Normality & Variance?} NormCheckMulti -->|Normal & Equal Var| ANOVA["One-way ANOVA + Tukey HSD<br/>(F-test with post-hoc pairs)"] NormCheckMulti -->|Normal & Unequal Var| WelchANOVA["Welch's ANOVA + Games-Howell<br/>(Robust to unequal variances)"] NormCheckMulti -->|Skewed / Non-normal| Kruskal["Kruskal-Wallis H test<br/>(Non-parametric rank sum)"] SampleType -->|Paired / Before-After| PairedNorm{Distribution of Differences?} PairedNorm -->|Normal Differences| PairedT["Paired samples t-test<br/>(Matched pairs comparison)"] PairedNorm -->|Skewed Differences| Wilcoxon["Wilcoxon Signed-Rank test<br/>(Non-parametric paired ranks)"] SampleType -->|3+ Repeated Measures| SpherCheck{Sphericity Met?} SpherCheck -->|Normal & Sphericity| RMANOVA["Repeated-Measures ANOVA<br/>(Within-subject longitudinal)"] SpherCheck -->|Violation / Skewed| Friedman["Friedman test<br/>(Non-parametric repeated ranks)"] %% Goal: Relationships GoalType -->|Study Relationships| VarTypes{Variable Types?} VarTypes -->|Numeric vs Numeric| BivariateDist{Linearity & Outliers?} BivariateDist -->|Linear & Bivariate Normal| Pearson["Pearson Correlation (r)<br/>(Linear association + 95% CI)"] BivariateDist -->|Monotonic / Outliers / Skewed| Spearman["Spearman Rank Correlation (ρ)<br/>(Monotonic rank association)"] VarTypes -->|Categorical vs Categorical| CellCounts{Expected Frequencies?} CellCounts -->|Expected counts ≥ 5| ChiSquare["Chi-square Independence (χ²)<br/>(+ Cramér's V effect size)"] CellCounts -->|Sparse cells < 5| SDCWarn["SDC Warning & Suppression<br/>(n<5 cell suppression)"] %% Goal: Reference Value GoalType -->|Compare to Reference| RefNorm{Sample Normality?} RefNorm -->|Normal Distribution| OneSampleT["One-sample t-test<br/>(Sample mean vs benchmark μ₀)"] RefNorm -->|Skewed Distribution| OneSampleWilcoxon["One-sample Wilcoxon test<br/>(Median vs benchmark)"] style Start fill:#4a5568,stroke:#cbd5e0,color:#fff style GoalType fill:#2b6cb0,stroke:#63b3ed,color:#fff style SampleType fill:#2c5282,stroke:#90cdf4,color:#fff style NumGroups fill:#2c5282,stroke:#90cdf4,color:#fff style VarTypes fill:#2c5282,stroke:#90cdf4,color:#fff style TTest fill:#22543d,stroke:#68d391,color:#fff style WelchT fill:#22543d,stroke:#68d391,color:#fff style MWU fill:#234e52,stroke:#4fd1c5,color:#fff style ANOVA fill:#22543d,stroke:#68d391,color:#fff style WelchANOVA fill:#22543d,stroke:#68d391,color:#fff style Kruskal fill:#234e52,stroke:#4fd1c5,color:#fff style PairedT fill:#22543d,stroke:#68d391,color:#fff style Wilcoxon fill:#234e52,stroke:#4fd1c5,color:#fff style RMANOVA fill:#22543d,stroke:#68d391,color:#fff style Friedman fill:#234e52,stroke:#4fd1c5,color:#fff style Pearson fill:#22543d,stroke:#68d391,color:#fff style Spearman fill:#234e52,stroke:#4fd1c5,color:#fff style ChiSquare fill:#22543d,stroke:#68d391,color:#fff style SDCWarn fill:#744210,stroke:#f6e05e,color:#fff style OneSampleT fill:#22543d,stroke:#68d391,color:#fff style OneSampleWilcoxon fill:#234e52,stroke:#4fd1c5,color:#fffStatistical Decision Matrix & Tradeoffs
Interactive Hypothesis Analytics Lab Interface
End-to-End Data Flow
sequenceDiagram participant R as Researcher participant FE as Frontend participant MM as MetaMask participant DS as DocumentStorage participant IPFS as IPFS/Pinata participant API as Analytics API participant AR as AnalyticsRegistry Note over R,AR: Phase 1 — Purchase & Decrypt (Existing Flow) R->>FE: Browse & select dataset FE->>MM: purchaseDocument(ipfsHash, price) MM->>DS: Transaction (ETH payment) DS-->>FE: DocumentPurchased event FE->>IPFS: Fetch encrypted dataset IPFS-->>FE: Encrypted blob FE->>FE: smartDecrypt() → CSV data Note over R,AR: Phase 2 — Analytics Trigger & Decision Tree (NEW) R->>FE: Click "Analyze This Dataset" FE->>API: GET /dataset/profile (Dataset Profiler) API-->>FE: Column types, distributions, test recommendations R->>FE: Select hypothesis & statistical test Note over R,AR: Phase 3 — EIP-712 Authentication (NEW) FE->>MM: Sign EIP-712 typed data MM-->>FE: Signature + params Note over R,AR: Phase 4 — Analysis Execution (NEW) FE->>API: POST /analytics/infer (CSV + signature + test params) API->>API: Verify EIP-712 signature API->>DS: Verify hasPurchased(CID, wallet) API->>API: Run analysis (scipy/statsmodels) + SDC checks API-->>FE: Results JSON + Effect sizes + Confidence intervals Note over R,AR: Phase 5 — Attestation (NEW) API->>IPFS: Upload result JSON → resultCID API->>AR: registerAnalytics(sourceCID, resultCID, type, analyst) AR-->>API: AnalyticsRegistered event API-->>FE: resultCID + txHash FE-->>R: Results + Etherscan linkWhat I Implemented During GSoC
During GSoC 2026, I delivered a complete, production-ready analytics layer spanning every level of the stack — from Solidity smart contracts to Python microservices to React frontend components. Concretely:
Analytics API Microservice
Descriptive Statistics Engine (
POST /analytics/describe)Full descriptive profiling using pandas: per-column summary statistics (count, mean, std, min, max, median, missing%), IQR, quartiles, data type detection, distribution analysis, Pearson and Spearman correlation matrices.
Visualization Engine (
POST /analytics/visualize)Chart generation supporting 7 chart types — histogram, scatter plot, box plot, correlation heatmap, bar chart, line chart, and pie chart. Handles both numeric and categorical data with automatic aggregation, grouping, and color encoding. Outputs base64-encoded images + JSON chart configs for frontend re-rendering.
Inferential Statistics Engine (
POST /analytics/infer)Comprehensive hypothesis testing using scipy.stats and statsmodels:
Hypothesis Tree Decision Engine
An interactive decision tree system that guides researchers through statistical test selection. Analyzes data characteristics (continuous vs. categorical, normal vs. non-normal, paired vs. independent) and recommends the most appropriate statistical test with plain-language explanations.
Dataset Profiler
Automated dataset profiling that detects column types, identifies potential health data columns (demographics, lab values, conditions), and generates analysis recommendations.
EIP-712 Authentication & Rate Limiting
Zero-trust auth module with signed typed data verification, 5-minute expiration windows, per-wallet nonce tracking, and sliding-window rate limiting.
IPFS & On-Chain Pipeline
Result serialization → Pinata IPFS upload →
AnalyticsRegistry.solon-chain registration via relayer pattern.Robust CSV Parsing
Handles UTF-8/ISO-8859-1 encodings, dialect sniffing, malformed row recovery, with enforced 10MB / 10,000 row caps.
AnalyticsRegistry Smart Contract (Solidity)
classDiagram class AnalyticsRegistry { +address relayer -mapping userAnalytics -mapping datasetResults -mapping registeredResults +registerAnalytics(sourceCID, resultCID, analysisType, analyst) +getAnalyticsForDataset(sourceCID) string[] +getAnalyticsForAddress(analyst, offset, limit) AnalyticsRecord[] +getAnalyticsCount(analyst) uint256 } class AnalyticsRecord { +string sourceCID +string resultCID +string analysisType +uint256 timestamp } class DocumentStorage { +storeDocumentHash(ipfsHash, price, previewHash) +purchaseDocument(ipfsHash) +hasPurchased(ipfsHash, buyer) bool } AnalyticsRegistry --> AnalyticsRecord : stores AnalyticsRegistry ..> DocumentStorage : verifies purchase viaregisteredResultsmappinggetAnalyticsForAddress(analyst, offset, limit)DocumentStorage.test.jspatterns)Frontend Integration (TypeScript/TSX)
analyticsService.ts: Complete API client with EIP-712 signature generation, all analytics API calls (describe, visualize, infer), and client-side statistical fallback for offline/development resilience.contractService.tsextensions: AddedregisterAnalytics()andgetAnalyticsForDataset()functions following existinggetProviderAndSigner()→new Contract()patterns.SearchData.tsxmodifications: Integrated "Analyze This Dataset" button in the post-purchase flow.Comprehensive Test Suite (21 test files)
test_anova.pytest_hypothesis_tree.pytest_infer_endpoint.pytest_inferential.pytest_visualization.pytest_visualization_categorical.pytest_demo_router.pytest_dataset_profiler.pytest_auth.py+test_auth_dependency.pytest_chain_registry.pytest_chi_square.pytest_correlation.pytest_descriptive.pytest_csv_parser.pytest_rate_limiter.pytest_ipfs_uploader.pytest_result_serializer.pytest_demo_sessions.pyAnalyticsRegistry.test.jsDocumentStorage.test.jsGSoC Coding Period — Detailed Timeline
gantt title GSoC 2026 — Bio-Block Analytics dApp Implementation Timeline dateFormat YYYY-MM-DD axisFormat %b %d section Phase 1: Core API & Contracts API Foundation & CSV Parser :done, 2026-05-26, 2026-06-06 EIP-712 Auth & Descriptive Stats :done, 2026-06-02, 2026-06-17 Visualization Engine (7 Chart Types) :done, 2026-06-10, 2026-06-25 AnalyticsRegistry.sol & Hardhat Tests :done, 2026-06-18, 2026-07-04 IPFS Pipeline & Relayer Integration :done, 2026-06-26, 2026-07-12 section Phase 2: Inferential Engine T-Tests, ANOVA & Effect Sizes :done, 2026-07-01, 2026-07-18 Chi-Square, Correlation & SDC Checks :done, 2026-07-08, 2026-07-24 Rate Limiting & Security Hardening :done, 2026-07-14, 2026-07-28 section Phase 3: Hypothesis Engine & Lab Hypothesis Tree Decision Engine :done, 2026-07-20, 2026-08-10 Demo Router & Session Management :done, 2026-07-27, 2026-08-12 Hypothesis Lab UI & Interactive Graphs :done, 2026-07-25, 2026-08-16 section Phase 4: Frontend & Integration Next.js Analytics Dashboard & Search :done, 2026-07-22, 2026-08-16 EIP-712 Signing & Attestation Client :done, 2026-08-01, 2026-08-16 section Phase 5: Profiling & Polish Dataset Profiler & Health Templates :done, 2026-08-03, 2026-08-14 Property-Based Testing (21 Test Files) :done, 2026-08-06, 2026-08-16 Documentation & Final Report :done, 2026-08-09, 2026-08-16Phase 1: Analytics API Foundation + Smart Contract (Weeks 1–5)
Weeks 1–2:
analytics-service/project structure with FastAPI on port 3003eth_accountwith replay protection (nonce + 5-minute timestamp expiration + requestHash binding)Weeks 3–4:
AnalyticsRegistry.solwith Hardhat — relayer pattern, duplicate prevention, paginated queriesWeek 5:
PRs: #230, #231, #232, #235, #237
Phase 2: Inferential Analytics + Rate Limiting (Weeks 6–9)
Weeks 6–7:
Weeks 8–9:
Phase 3: Frontend Dashboard + Hypothesis Tree (Weeks 10–11)
Week 10:
SearchData.tsxpost-purchase flowanalyticsService.tswith EIP-712 signing, all API calls, and offline fallbackcontractService.tswithregisterAnalytics()andgetAnalyticsForDataset()Week 11:
Phase 4: Validation + Documentation (Week 12)
Code and Merge History
Codebase Statistics
analytics-service/app/)analytics-service/tests/)analyticsService.ts+contractService.ts+SearchData.tsx)AnalyticsRegistry.sol+ tests)Core Components
Analytics API
analytics-service/app/main.py— FastAPI application with all endpointsservices/descriptive.py— Descriptive statistics engineservices/visualization.py— 7-chart visualization engineservices/inferential.py— Full inferential statistics engineservices/hypothesis_tree.py— Interactive decision engineservices/dataset_profiler.py— Automated dataset profilingauth/eip712.py— EIP-712 signature verificationservices/chain_registry.py— On-chain registration via relayerSmart Contract
prototype/src/AnalyticsRegistry.solprototype/test/AnalyticsRegistry.test.jsFrontend
nextjs-frontend/lib/analyticsService.ts— Analytics API client + EIP-712 signingnextjs-frontend/lib/contractService.ts— Extended with AnalyticsRegistry functionsnextjs-frontend/components/SearchData.tsx— Post-purchase analytics integrationSelected Pull Requests
Analytics API Foundation
Visualization & Charting
Smart Contract & On-Chain Integration
Inferential Statistics & Decision Engine
For a complete list of changes, see:
is:pr author:santhil-cybercommits?author=santhil-cyberDeliverables Completion Status
AnalyticsRegistrycontractSearchData.tsxpost-purchaseWhat's Left and Future Work
Further enhancements to make the platform more enterprise-ready:
L2 Deployment: Migrate
AnalyticsRegistry.solto Polygon or Arbitrum for sub-cent attestation costs at scale.Async Processing (Celery/Redis): Implement a task queue for long-running analyses once real usage data justifies the infrastructure cost. The current synchronous API with Uvicorn multi-worker mode handles the GSoC scope.
The Graph Integration: Build a subgraph for
AnalyticsRegistryevents to enable efficient off-chain querying and analytics history indexing.Predictive Analytics: Add scikit-learn-based predictive models (regression, classification) as a fourth analysis level.
Audit Logging Phase 2: Extend the HIPAA audit logger to cover analytics operations with integrity verification endpoints.
OpenDP Integration (Stretch Goal): Integrate the OpenDP library to add formal differential privacy guarantees to analytics outputs. This would allow researchers to query aggregate statistics over sensitive health datasets with mathematically provable privacy bounds, complementing the current SDC warning/suppression approach with rigorous ε-differential privacy mechanisms.
Hypothesis Tree Improvements: Expand the decision engine with additional statistical tests (e.g., mixed-effects models, survival analysis, logistic regression), richer assumption diagnostics (e.g., multicollinearity detection via VIF, autocorrelation checks), and a visual tree replay feature that lets researchers compare branching paths side-by-side across sessions.
Lessons Learned
This project was as much about designing a robust hybrid on-chain/off-chain system as it was about writing code. Key takeaways:
Hybrid architecture is the right pattern for blockchain + analytics.
Running compute-intensive analysis off-chain while recording results on-chain preserves the benefits of decentralization (verifiability, transparency) without the costs (gas, latency). The relayer pattern made this seamless for users.
Statistical correctness requires rigorous decision pathways.
Building an automated hypothesis decision tree was essential to prevent misuse of parametric tests on skewed clinical data, heteroscedastic samples, or small cohorts. Chalinda's guidance on when parametric assumptions break down in real-world biomedical data was invaluable in shaping the decision engine's fallback logic — for example, defaulting to Welch's t-test over Student's t-test and routing to Mann-Whitney U when normality checks fail.
EIP-712 signatures are powerful but tricky.
Typed structured data signing provides strong authentication without requiring on-chain transactions from users. However, the implementation required careful attention to nonce tracking, timestamp validation, and request hash binding to prevent subtle replay and tampering attacks.
Statistical correctness requires rigorous testing.
Every statistical function was validated against known reference outputs with fixed-seed datasets. Property-based testing caught edge cases (zero-variance columns, single-row groups, non-normal distributions) that manual testing would have missed.
Separation of concerns pays off.
Running analytics as a separate microservice on port 3003 — rather than adding to the existing Python backend on port 3002 — prevented dependency conflicts and kept each service independently deployable and testable.
Healthcare data has special challenges.
Small cohort protection (SDC warnings at n<30, suppression at n<5) isn't just a nice-to-have — it's essential when working with rare disease datasets where aggregate statistics can expose individual records.
Acknowledgments
I want to say a big, big thank you to my mentors. @Chali-healthy, you are one of the smartest people I know. You have a special superpower for design and startups! You understood well how to make the customer's journey easier, and that taught me so much. You even made me love statistics, which I never thought I would love. I feel really lucky to have learned from you, and I will always remember your help. At last, will be missing your Sri-Lankan and your journey to India stories.
@karthiksathishjeemain , thank you for being like a big brother to me. You checked my code, gave me tips, and helped me the whole time I worked on this project. Because of you and Chali, my project became much better and much stronger. I learned so much from both of you, and I am very thankful.
I also want to say thank you to @pradeeban. You made a place felt open, supportive and collaborative environment, and free to share ideas. You made sure we never felt worried or stressed while working.
If you want to know more about my project, or just want to talk, you can email me here: santhil.kherwal05@gmail.com
All reactions