🔥Inspiration:

Gen Z is often called the “Sleeping Giant” of politics. Millions of young Americans are eligible to vote, but many choose not to. Why? Because elections can feel overwhelming. Our media diet is dominated by national headlines like presidential races, Supreme Court battles, endless drama in D.C. That constant noise makes it hard to see where our own vote matters most: in our local community. It leaves us wondering: Does my vote really make a difference? Can local leaders actually fix the issues affecting me? When even is the local election? That’s where Flint comes in. By connecting you to local candidates that are advocating for the issues you care about, civic engagement can be easy and approachable. With Flint, anyone can become politically involved and spark change in their community.

🪨What it does:

Our app awakes the Sleeping Giant!

Users pick three issues in their city that they care about the most. Flint connects those issues directly to the local candidates and ballot measures that address them. Users get digestible explanations about each ballot measure and easy-to-read profiles of local candidates (you can even ⭐star the ones you want to keep track of)! Once you feel ready to vote, Flint gives you your election date, nearest polling locations, and mail-in ballot instructions so you can cast your vote with confidence.

Flint isn’t the final word on who to vote for — it’s the spark! No more confusion about who’s on the ballot or how to vote. Flint gives you an easy starting point to learn about the candidates and issues that matter to you.

🔨How we built it:

We built Flint by starting frontend-first, using React 18 with TypeScript to rapidly prototype the user journey and define clear data contracts. Accessibility was central, so we chose shadcn/ui on Radix primitives with Tailwind CSS for fast styling, and Vite for a solo-developer workflow. A centralized useAppState hook became the backbone, persisting user choices across steps and managing complex relationships between issues, offices, candidates, and ballot measures. From these frontend needs, we worked backward to design our Flask backend with an application factory pattern and a dual-layer data system that could run on mock data or scale to Supabase PostgreSQL.

⛰️Challenges we ran into:

We faced several challenges, starting with having a solo developer who had never built a full-stack project before. Another major hurdle was transitioning from our mocked local database, implemented with a Python class, to the Supabase setup we ultimately used. Processing the raw civic data was also difficult. Ballot measures and candidate information came in inconsistent formats, which required extensive manual cleaning. To streamline this, we built Python migration scripts that handled data validation, normalized candidate position arrays, standardized office-to-issue mappings, and created relational links between candidates and their target offices. These tools made the process easier, but we still had to carefully determine which parts of the raw data were actually useful.

🌞Accomplishments that we’re proud of:

We’re proud to have created a neutral civic tech platform that helps young voters become politically involved without getting lost in partisan divides or political noise. Flint prides itself on its focus on community issues and encourages users to make their civic engagement journey personal to them. Technically, we're most proud of being able to send emails with real voting guides & candidate info to users who can use them in preparation for the Nov 4 election.

🌱What we learned:

We learned the importance of implementing proper separation of concerns with API client abstractions, consistent error handling across frontend and backend, and environment-specific configuration management. The experience taught us how to structure React hooks for complex state management and implement robust failsafes for external service dependencies and APIs. Working with an unfamiliar stack reinforced the critical importance of frequent commits with descriptive messages when experimenting with new integrations. This proved essential when debugging Supabase connection issues and handling breaking changes. Finally, we learned how to design PostgreSQL schemas for many-to-many relationships using array columns and create RLS policies. The experience showed us how to balance normalized design with query performance for civic data relationships.

🌎What’s next for Flint:

We are excited to empower young Houstonians to vote and spark change in their community through Flint. But as the Sleeping Giant stretches across the United States, we hope to expand Flint to other cities, helping more young people become politically active and make their voices heard.

Built With

Share this project:

Updates