Where government policy meets citizen voice โ AI bridges the gap, understands both sides, and delivers an informed decision.
๐ Live Demo ยท
See the complete flow โ from posting a government survey and uploading a policy PDF, to citizens submitting opinions and the AI generating a full decision report in real time.
๐ก To display images: Add your screenshots to a
screenshots/folder in the repo and uncomment the<img>tags below.
๐ 1. Landing PageThe entry point of CivicPulse โ choose between the Government Portal (dark) or Citizen Portal (light) to get started |
๐ 2. Government Portal LoginSecure, pre-authorised officer authentication โ no public registration allowed; credentials are configured by the system administrator |
๐ 3. Government Portal โ Post SurveyOfficers write a policy question, optionally upload a supporting PDF/DOCX, and set the minimum citizen response target before publishing |
๐ 4. Government Portal โ My SurveysDashboard showing all published surveys with live response counts and completion status โ empty state before any surveys are posted |
๐ 5. Government Portal โ Service ConnectionsReal-time health status of all integrated services โ Claude AI, InsForge Database, TinyFish Research, and the CivicPulse server, all confirmed online |
๐ณ๏ธ 6. Citizen Portal โ Sign InCitizens sign in with their registered username and password to access and respond to open government surveys |
โ๏ธ 7. Citizen Portal โ Create AccountNew citizens register with a unique username and password (min. 6 characters) โ passwords are bcrypt-hashed before storage |
๐ 8. Citizen Portal โ Awaiting Government PostsThe citizen dashboard before any surveys are published โ surveys appear here automatically once a government officer posts one |
๐ 9. Government Portal โ Survey with PDF AttachedA policy question filled in and a PDF uploaded (7k characters extracted) โ AI will read the document to deeply understand government intent before analysis |
๐ก 10. Government Portal โ Survey Published & Collecting OpinionsThe survey is now live with 1 post recorded; the system waits for the target number of citizen responses before auto-triggering AI analysis |
๐ฌ 11. Citizen Portal โ Active Survey Ready for ResponseThe government's published survey appears in the citizen dashboard; citizens write their opinion in free text โ AI understands the full reasoning, not just keywords |
โก 12. Government Portal โ Target Reached, Run AnalysisOnce the minimum response target is met (2/2 here), the "Run Analysis with N Responses Now" button appears โ government can trigger the AI pipeline on demand |
๐๏ธ 13. InsForge DB โ cp_surveys TableThe government-posted survey persisted in InsForge cloud database, showing the survey ID, question text, author (Amrish), response target, and attached policy document JSON |
๐ค 14. InsForge DB โ cp_users Table (Citizen Accounts)Registered citizen accounts stored in InsForge โ passwords are securely bcrypt-hashed ($2a$10$...) and never stored in plain text |
๐ 15. InsForge DB โ cp_responses Table (Citizen Answers)Each citizen's free-text response stored with their username, linked survey ID, and submission timestamp โ this raw data feeds directly into the AI analysis pipeline |
๐พ 16. InsForge DB โ cp_analysis Table (AI Output Persisted)The full AI decision report saved as 20 chunked string columns in InsForge โ ensuring the analysis survives server restarts and remains accessible at any time |
๐ 17. Government Portal โ Live AI Decision ReportThe complete AI-generated decision report displayed in the Government Portal: citizen sentiment bar (50% support / 50% neutral), win-win solution, recommended course of action, key statistics, urgency level, confidence score, and a "View Full Report" button โ all deployed live at civicpulse-production.up.railway.app |
|
CivicPulse is a full-stack civic engagement platform that connects government officers with citizens in real time. Governments post policy surveys, citizens respond in free text, and an AI pipeline analyses the data โ understanding government intent, citizen emotions, conflicts, and proposing win-win solutions.
| Feature | Description |
|---|---|
| ๐๏ธ Dual Portal System | Government Portal (dark theme) + Citizen Portal (light theme) |
| ๐ค AI Decision Report | Sentiment breakdown, conflict analysis, win-win solution, course of action |
| ๐๏ธ Persistent Cloud DB | InsForge PostgreSQL โ all data survives restarts |
| ๐ฌ Real-World Research | TinyFish web research pulls policy precedents from Wikipedia |
| ๐ JWT Auth | bcrypt-hashed passwords, 7-day tokens |
| ๐ PDF/DOCX Upload | Government attaches policy docs; AI reads up to 15,000 chars |
| โ๏ธ Follow-up Questions | Government can send targeted follow-up questions to citizens |
CivicPulse/
โโโ server.js โ Single-file Express backend (889 lines)
โ โโโ Config & env setup
โ โโโ In-memory fallback store (no DB mode)
โ โโโ InsForge REST helpers (ifGet/ifPost/ifPatch/ifDel)
โ โโโ DB auto-init (creates 4 tables on startup)
โ โโโ Auth middleware (JWT verify)
โ โโโ REST API routes (10 endpoints)
โ โโโ TinyFish SSE streaming client
โ โโโ triggerAnalysis() pipeline (6 steps)
โโโ public/
โ โโโ index.html โ Full frontend SPA (1428 lines, vanilla JS)
โ โโโ Landing page (dual portal selector)
โ โโโ Government portal (login, post survey, my surveys, connections)
โ โโโ Citizen portal (login, register, browse & respond to surveys)
โโโ .env.example โ Environment variable template
โโโ package.json โ npm dependencies
โโโ skills-lock.json โ Dependency lock
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ CLIENT BROWSER โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Government Portal โ โ Citizen Portal โ โ
โ โ (dark theme) โ โ (light theme) โ โ
โ โ - Post surveys โ โ - Register / Login โ โ
โ โ - Upload PDF/DOCX โ โ - Browse open surveys โ โ
โ โ - View AI reports โ โ - Submit free-text opinion โ โ
โ โ - Send follow-ups โ โ - See AI decision result โ โ
โ โโโโโโโโโโโโโฌโโโโโโโโโโโโ โโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโ โ
โ โ REST + JWT Bearer Token โ โ
โโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโผโโโโโโโโโโโโโโโโโโโ
โ โ
โผ โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ NODE.JS / EXPRESS SERVER โ
โ โ
โ โโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโ โ
โ โ Auth Layer โ โ API Routes โ โ AI Pipeline โ โ
โ โ โ โ โ โ triggerAnalysis()โ โ
โ โ โข JWT verify โ โ POST /login โ โ โ โ
โ โ โข Gov creds โ โ POST /survey โ โ Step 1: Re-fetch โ โ
โ โ from .env โ โ POST /resp. โ โ Step 2: Extract โ โ
โ โ โข bcrypt hash โ โ POST /upload โ โ gov doc โ โ
โ โ โข 7-day tokens โ โ GET /surveysโ โ Step 3: TinyFish โ โ
โ โโโโโโโโโโโโโโโโโโ โ GET /resp. โ โ research โ โ
โ โ POST /ai โ โ Step 4: Build โ โ
โ โโโโโโโโโโโโโโโโโโ โ POST /resrch โ โ prompt โ โ
โ โ In-Memory โ โ PATCH/survey โ โ Step 5: TinyFish โ โ
โ โ Fallback Store โ โ POST /shoot โ โ AI call โ โ
โ โ (no InsForge) โ โ GET /status โ โ Step 6: Save & โ โ
โ โ mem.users[] โ โโโโโโโโโโโโโโโโ โ cache โ โ
โ โ mem.surveys[] โ โโโโโโโโโโโโโโโโโโโโโ โ
โ โ mem.responses[]โ โ
โ โ analysisCache{}โ โ
โ โโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
โ InsForge DB โ โ Anthropic Claude โ โ TinyFish AI โ
โ (Cloud Postgres) โ โ (AI Proxy /api/ai) โ โ (SSE stream) โ
โ โ โ โ โ โ
โ cp_users โ โ claude-sonnet-4 โ โ Wikipedia โ
โ cp_surveys โ โ max_tokens: 1000 โ โ scraping for โ
โ cp_responses โ โ JWT-gated proxy โ โ real-world โ
โ cp_analysis โ โ โ โ precedents โ
โ (20 chunks) โ โโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโ
CivicPulse auto-creates all tables on startup and drops+recreates them to ensure correct column types.
cp_users
โโโ id uuid PK (auto)
โโโ username string NOT NULL, UNIQUE
โโโ password_hash string NOT NULL โ bcrypt $2a$10$...
โโโ created_at datetime
โโโ updated_at datetime
cp_surveys
โโโ id uuid PK (auto)
โโโ question string NOT NULL
โโโ author string NOT NULL โ gov officer username
โโโ target_responses integer โ min responses before AI fires
โโโ context_json string โ JSON array with [GOV_DOC]: prefix
โโโ status string โ 'active' | 'complete'
โโโ analysis_json string โ legacy (unused, see cp_analysis)
โโโ published_at datetime
cp_responses
โโโ id uuid PK (auto)
โโโ survey_id string FK โ cp_surveys.id
โโโ username string FK โ cp_users.username
โโโ answer string NOT NULL โ free-text citizen opinion
โโโ submitted_at datetime
cp_analysis โ AI report stored in 20 chunks
โโโ id uuid PK (auto)
โโโ survey_id string UNIQUE FK โ cp_surveys.id
โโโ chunk_0 string โ 250 chars of JSON
โโโ chunk_1 string
โโโ ...
โโโ chunk_19 string โ up to 5000 chars total JSON
โโโ created_at datetime
Why chunking? InsForge string columns max out at ~255 chars. The AI report JSON can be 2000โ5000 chars, so it's split into 20 ร 250-char chunks on write and reassembled on read via
toChunks()/fromChunks().
Dual-mode storage: If
INSFORGE_URLis not set, the server falls back to a plain in-memory JS object (mem.users,mem.surveys,mem.responses) so the app works without any database configured.
Government Login Citizen Login / Register
โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโ
POST /api/auth/gov-login POST /api/auth/register
username + password username + password
โ โ
โผ โผ
Check GOV_CREDS{} bcrypt.hash(password, 10)
(hardcoded in .env) โ store in cp_users (InsForge)
โ โ
โผ โผ
jwt.sign({ role:'government' }) jwt.sign({ role:'citizen' })
โ โ
โโโโโโโโโโโโ 7-day JWT โโโโโโโโโโโโโโโโ
โ
โผ
Bearer token in Authorization header
โ auth() middleware verifies on every
protected route (surveys, responses,
uploads, AI proxy, analysis trigger)
Triggered automatically when responses.length >= target_responses, or manually via the government portal button.
triggerAnalysis(survey, responses)
โ
โโโ STEP 1 โ Re-fetch fresh data
โ โโโ GET /cp_surveys/:id + GET /cp_responses?survey_id=eq.:id
โ (ensures latest data even if called with stale input)
โ
โโโ STEP 2 โ Extract government policy document
โ โโโ Parse survey.context_json (JSON array)
โ Find message with role:'system' and content starting '[GOV_DOC]:'
โ Extract up to 3000 chars as govDocSnippet
โ
โโโ STEP 3 โ TinyFish Wikipedia research (two parallel lookups)
โ โโโ Search Wikipedia for policy precedents
โ โ โ "real countries that implemented similar policies,
โ โ statistics, measurable outcomes, lessons learned"
โ โโโ Search Wikipedia for environmental/social impact data
โ โ SSE stream from https://agent.tinyfish.ai/v1/automation/run-sse
โ 20s hard timeout, processes data: events line-by-line
โ
โโโ STEP 4 โ Build comprehensive analysis prompt
โ โโโ Combines: survey question + gov doc snippet (3000 chars)
โ + citizen opinions (numbered list)
โ + Wikipedia precedent data (1000 chars)
โ + impact data (1000 chars)
โ Requests strict JSON output (no markdown, 23-field schema)
โ
โโโ STEP 5 โ TinyFish AI call
โ โโโ Sends full prompt to TinyFish as 'goal'
โ Parses JSON from SSE COMPLETE event
โ Falls back to regex JSON extraction if parsing fails
โ Falls back to rule-based sentiment analysis if TinyFish fails
โ (counts support/oppose keywords in citizen answers)
โ
โโโ STEP 6 โ Save & cache
โโโ analysisCache[survey.id] = analysisJson โ in-memory (instant access)
โโโ saveAnalysisToIF() โ toChunks() โ INSERT/UPDATE cp_analysis
โโโ PATCH cp_surveys/:id { status: 'complete' }
Analysis JSON schema (23 fields):
{
"final_decision": "2-3 sentence AI recommendation",
"government_intent": "what the government wants to achieve",
"government_concern": "core problem being solved",
"citizen_emotions": "emotional tone of responses",
"citizen_concerns": "main citizen issues raised",
"sentiment_breakdown": {
"support_percent": 60,
"oppose_percent": 30,
"neutral_percent": 10,
"support_reasons": ["..."],
"oppose_reasons": ["..."]
},
"conflict_analysis": "where gov intent and citizen needs clash",
"win_win_solution": "creative solution satisfying both sides",
"alternative_approaches": [{ "name": "", "description": "", "benefits": "", "tradeoffs": "" }],
"recommended_course_of_action": ["Step 1", "Step 2", "..."],
"statistics": {
"key_stats": ["stat with number"],
"comparable_cases": ["real city + outcome"],
"projected_impact": "expected outcome"
},
"pros": ["..."],
"cons": ["..."],
"environmental_social_factors": "context",
"urgency": "LOW | MEDIUM | HIGH",
"confidence": 85
}| Layer | Technology | Details |
|---|---|---|
| Backend | Node.js 18+ + Express | Single server.js, 889 lines |
| Frontend | Vanilla HTML/CSS/JS | Single index.html SPA, 1428 lines, no framework |
| Database | InsForge (Cloud PostgreSQL) | REST API, auto-provisioned tables, chunked JSON storage |
| AI Analysis | TinyFish AI | SSE streaming, Wikipedia scraping, 20s timeout |
| AI Proxy | Anthropic Claude (Sonnet 4) | JWT-gated /api/ai proxy endpoint |
| Auth | JWT + bcryptjs | 7-day tokens, cost-10 bcrypt, role-based (gov/citizen) |
| File Upload | multer + pdf-parse + mammoth | PDF & DOCX โ up to 15,000 chars extracted |
| Deployment | Railway | Auto-deploy from GitHub, env vars via Railway dashboard |
| In-memory fallback | Plain JS objects | Works without any database if InsForge not configured |
git clone https://github.com/AmrishS2004/CivicPulse.git
cd CivicPulse
npm installcp .env.example .envOpen .env and fill in your keys:
| Variable | Where to Get |
|---|---|
ANTHROPIC_API_KEY |
console.anthropic.com |
INSFORGE_URL |
insforge.app โ Create Project โ copy URL |
INSFORGE_ADMIN_KEY |
InsForge โ Settings โ API Keys |
TINYFISH_API_KEY |
tinyfish.ai โ 500 free steps |
JWT_SECRET |
Any long random string |
GOV_CREDENTIALS |
username:password pairs, comma-separated |
npm start # production
npm run dev # development (auto-reload with nodemon)Visit http://localhost:3000
You should see:
โ
InsForge ready
๐๏ธ CivicPulse โ http://localhost:3000
AI: โ
Claude
Backend: โ
InsForge
Research: โ
TinyFish
Government credentials are pre-configured in .env via GOV_CREDENTIALS. No self-registration is allowed for the government portal.
Default credentials (change in .env):
gov_admin / Admin@2024
gov_officer / Officer@2024
ministry_lead / Ministry@2024
CivicPulse auto-creates four tables in InsForge on startup:
| Table | Purpose |
|---|---|
cp_users |
Citizen accounts (bcrypt hashed passwords) |
cp_surveys |
Government surveys + uploaded document text |
cp_responses |
Citizen free-text responses |
cp_analysis |
AI analysis stored as 20 chunked string columns |
When the target response count is reached (or manually triggered):
1. Fetch โ pulls fresh survey + responses from InsForge
2. Extract โ parses uploaded policy document from context_json
3. Research โ TinyFish browses Wikipedia for real-world policy precedents
4. Analyse โ sentiment engine classifies each response (support / neutral / oppose)
5. Report โ builds 14-section decision report with win-win solution
6. Save โ chunks JSON into InsForge cp_analysis table (persists across restarts)
- โ๏ธ Final Decision โ AI-informed recommendation
- ๐ Citizen Sentiment Breakdown โ visual bar with percentages
- โก Conflict Analysis โ identifies tensions between government intent and citizen concern
- ๐ Win-Win Solution โ bridges both sides
- ๐บ๏ธ Recommended Course of Action โ step-by-step implementation plan
- ๐ Statistics & Comparable Cases โ real-world data via TinyFish
- ๐ก Alternative Approaches โ what else could be done
- โ Pros & โ Cons โ balanced view
| Method | Endpoint | Auth | Description |
|---|---|---|---|
| POST | /api/auth/register |
None | Register citizen |
| POST | /api/auth/login |
None | Citizen login |
| POST | /api/auth/gov-login |
None | Government login |
| GET | /api/surveys |
None | List all surveys |
| POST | /api/surveys |
Gov | Create survey |
| GET | /api/responses/:id |
None | Get responses |
| POST | /api/responses |
Citizen | Submit response |
| POST | /api/upload-doc |
Gov | Upload PDF/DOCX |
| POST | /api/admin/trigger-analysis/:id |
Gov | Manually trigger analysis |
| GET | /api/config/status |
None | Service health check |
npm install # installs everything from package.jsonCore: express ยท cors ยท dotenv ยท node-fetch ยท bcryptjs ยท jsonwebtoken ยท multer ยท pdf-parse ยท mammoth
- Email notifications when AI report is ready
- Multi-language citizen portal support
- Analytics dashboard for government officers
- Mobile app (React Native)
- Role-based access control within government portal
---
This project is licensed under the MIT License โ see the LICENSE file for details.
Made with โค๏ธ by Amrish Sasikumar, Aravind ยท Powered by Claude AI ยท InsForge ยท TinyFish
โญ Star this repo if you found it useful!



















