DEVSA is the central platform connecting San Antonio's tech community. We bridge the gap between passionate builders, local partners, and the growing tech ecosystem.
🌐 Live Site: www.devsa.community
DEVSA started with a simple question: "Where is the tech community in San Antonio?"
We found 20+ tech-focused organizations scattered across the city, not collaborating and living in their own bubbles. So we built DEVSA to bring them together—a platform where you can discover tech communities that match your interests and where these groups can collaborate, share resources, and grow stronger together.
- Framework: Next.js 16 with App Router (Turbopack)
- Language: TypeScript
- Styling: Tailwind CSS v4
- Animation: Motion, Three.js, Paper shaders
- Database: Google Firestore
- Auth: Firebase Authentication — Google OAuth + email/password
- Email: Resend
- Bot protection: Vercel BotID
- Payments: Stripe (+ Stripe Connect for bounty payouts)
- Merch fulfillment: Printify
- Storage: Vercel Blob
- Deployment: Vercel
git clone https://github.com/devsanantonio/next-devsa.git
cd next-devsa
pnpm install
cp .env.example .env.local # then fill in your keys
pnpm devThe app runs at http://localhost:3000. See .env.example for which variables are required versus optional — most features fail soft when their keys are absent, so you can run the site with just the Firebase and Resend blocks filled in.
After deploying, bootstrap the first admin account. This only works once, while no admins exist:
curl -X POST https://your-domain.com/api/admin/setup \
-H "Content-Type: application/json" \
-d '{"email": "[email protected]", "secret": "your_admin_setup_secret"}'Standard Next.js App Router layout — routes in app/, UI in components/, server helpers and third-party clients in lib/, and static seed data in data/.
Two things worth knowing before you start:
Firestore is the source of truth; data/ is a fallback. Communities, partners, and events are read from Firestore and fall back to the checked-in TypeScript files when Firestore is unavailable or a document is missing. If you add a community or partner, it needs to exist in both places to render reliably.
Components under components/jobs/ belong to the bounty marketplace. The job board was renamed to "bounties" — routes live at /bounties, and /jobs permanently redirects. The directory name is leftover.
Event listings aggregated across member communities, with RSVP capture, calendar feeds (/api/events/feed), and per-event Open Graph images. The primary front door for the community.
The Geekdom coworking partnership page, including a "ping an admin" inquiry form that reaches a real person.
Discover 20+ local tech communities and partner organizations.
Marketplace for paid community work. Firebase Auth for posting and claiming, Stripe Connect for payouts.
DEVSA merch, checked out through Stripe and fulfilled by Printify.
Protected dashboard for community organizers — manage events, communities, and admin users. Requires approved admin access recorded in Firestore.
pnpm dev # Dev server (Turbopack)
pnpm build # Production build — the main correctness gate, since there is no broad test suite
pnpm lint # ESLint
pnpm lint:fix # ESLint with autofix
pnpm test:feed # Vitest: events feed contract testWe welcome contributions from the San Antonio tech community.
- Fork the repository on GitHub and clone your fork
- Branch:
git checkout -b feature/your-feature-name - Install:
pnpm install - Develop:
pnpm dev - Check your work:
pnpm lint && pnpm build - Commit with a clear message and push to your fork
- Open a Pull Request against the main repository
Both are managed through the Admin Dashboard, but the static fallback lives in data/communities.ts and data/partners.ts. Add your entry there too, matching the shape of the existing records — the fallback is what renders if Firestore is unreachable.