feat: hybrid follow engine — LinkedIn WebView interaction, session management & deep-link fallback#177
feat: hybrid follow engine — LinkedIn WebView interaction, session management & deep-link fallback#177Itzzavdheshh wants to merge 6 commits into
Conversation
|
Hi **@ShantKhatri ** 👋 This PR delivers the complete Layer 2 WebView Follow Engine from Product Doc Section 6.9 — every acceptance criterion met, every failure path covered, and full platform compliance maintained.
Happy to address any feedback! 🚀 |
Great work done @Itzzavdheshh , I really appreciate this. This PR will take some time to review, as I wanna look into this personally. This was the part which we need to really focus on. Can you please add just a small demo video, showing the feature, so that I can have idea how functionality working for this? |
|
@Itzzavdheshh Could please join our discord channel from README I would like to discuss something with you. |
- Backend: followRoutes returns webview strategy for LinkedIn/Twitter platforms - Backend: POST /api/follow/:platform/:targetUsername/log for telemetry - Backend: DELETE /api/follow/:platform/:targetUsername/log to reset Done state - Backend: public profile now returns followed:true for previously connected links - Backend: auth improvements — encode mobile redirect URI in OAuth state - Mobile: WebViewScreen — full LinkedIn JS injection engine with polling, MutationObserver, visibilitychange, popstate, and injectedJSBeforeContentLoaded - Mobile: DevCardViewScreen — premium UI, emoji icons, brand-colored buttons, Done tile with long-press reset, GitHub browser fallback - Mobile: HomeScreen — username search bar to view any DevCard profile - Mobile: App.tsx — hash fragment token extraction for OAuth deep links - Mobile: config.ts — auto-detects LAN IP via Expo Constants for Expo Go - Mobile: Expo migration — index.js, metro.config.js, babel.config.js, app.json - Tests: new follow.test.ts cases for webview strategy and log endpoint - Docs: README updated with telemetry and fallback overlay details - Config: docker-compose port 5433, .env.example LAN IP placeholders
- prisma.ts: replace authenticate:any with proper typed signature (request: FastifyRequest, reply: FastifyReply) => Promise<void> - auth.ts: replace err as any with instanceof Error check in both GitHub and Google OAuth catch blocks for type-safe error handling - Skeleton.tsx: replace width/height as any with DimensionValue type from react-native to preserve TypeScript safety
- connect.ts: replace err as any with instanceof Error check in GitHub connect catch block (same pattern as auth.ts fix) - MainTabs.tsx: extract WebViewConnect params into standalone exported type WebViewConnectParams for reusability and future maintainability - profiles.test.ts: replace mockPrisma as any with Pick<PrismaClient,'user'> and unknown cast to preserve TypeScript safety in tests
- prisma.ts: merged authenticate type declaration — kept upstream's method signature style with our FastifyRequest/FastifyReply imports - pnpm-lock.yaml: kept card branch version (includes Expo packages)
|
HI @ShantKhatri & @Harxhit ...please review , i did some changes ....Happy to address any feedback! 🚀 @ShantKhatri ---> i hope this work : https://drive.google.com/file/d/1J6VaEbFByZMBLIb7LSN-zOuOkNxGU9pQ/view?usp=drivesdk |
Summary
Implements the complete Layer 2 WebView Interaction Engine as specified in Product Doc Section 6.9. LinkedIn's API blocks programmatic connection requests — this PR routes LinkedIn connects through a secure in-app WebView with session cookie sharing, JS-injected Connect button highlighting, invite success detection, and a 10s deep-link fallback. Users tap "Connect on LinkedIn" in
DevCardViewScreen, see the real LinkedIn profile inside the app with their session active, tap the native button, and receive a success toast — all without leaving DevCard or violating LinkedIn's API terms.Closes #36
Type of Change
What Changed
apps/backend/src/routes/follow.tswebviewstrategy handler — whenfollowStrategy === 'webview', returns{ strategy: 'webview', url }instead of an error; strictly guarded toplatform === 'linkedin'onlyapps/mobile/src/navigation/MainTabs.tsxWebViewConnectroute params updated with strict TypeScript types —urlandplatformNamenow required;profileUrl,displayName,usernamekept optional for backward compatibilityapps/mobile/src/screens/DevCardViewScreen.tsxhandlePlatformActioncase 'webview'now POSTs to backend; onstrategy === 'webview'response navigates toWebViewScreenwith resolved URLhandleWebViewConnect(link)— zero broken flowsapps/mobile/src/screens/WebViewScreen.tsxsharedCookiesEnabled={true}+thirdPartyCookiesEnabled={true}— LinkedIn session carries over from system browserPending,Invitation sent) and URL transitions;send-invitestage explicitly excluded to prevent premature triggersisSuccessHandledref guard — success toast (1.2s) + modal dismiss fire exactly once; duplicate events impossibleonError+onHttpErrorhandlers all route togetDeepLinkUrl→ native LinkedIn app → system browser fallback chainapps/backend/README.mdHow to Test
WebViewScreenopens with correct LinkedIn profilenpx tsc --noEmit→ verify zero TypeScript errorsgit diff --check→ verify zero trailing whitespaceChecklist
pnpm -r run lintpasses)pnpm -r run typecheck)pnpm -r run test)apps/backend/README.mdFollow Engine section addedconsole.logor debug statements left in the codeplatform === 'linkedin'only; zero impact on GitHub, GitLab, Discord flowsisSuccessHandledref guard active — success toast + dismiss fire exactly onceonError,onHttpErrorall route to deep-link fallbackScreenshots / Recordings
1.

WebViewScreen— LinkedIn profile loaded with instruction banner2. JS injection — Connect button scrolled into view + dashed blue highlight

3. Success toast — invite detected, native banner shown 1.2s then dismissed

4. 10s timeout — native LinkedIn app launched via deep link
)
5. Backend offline — WebView still opens with local fallback URL

6.

npx tsc --noEmit— zero TypeScript errors7.

apps/backend/README.md— Follow Engine section with Mermaid diagramAdditional Context
isSuccessHandledguard and dual-detection (DOM + URL) could be extended to other platforms that move to awebviewstrategy in future. The 4-layer architecture infollow.tsis designed for this extensibility.🙌 Contribution Note
Hi **@ShantKhatri ** 👋
This PR delivers the complete Layer 2 WebView Follow Engine from Product Doc Section 6.9 — every acceptance criterion met, every failure path covered, and full platform compliance maintained.
tsc --noEmitpasses,WebViewConnectparams fully typedHappy to address any feedback! 🚀
🏷️ Labels
#GSSOC#feature#linkedin#webview#follow-engine#react-native#session-management#js-injection#deep-link#mobile#typescript#platform-compliance#advancedSubmitted as part of Open Source Contribution —GSSoC(GirlScript Summer of Code)