Andino is an open-source community engagement platform built for community builders, by community builders. Our vision is to be the only tool that community leaders need to manage and engage with their communities effectively.
Current features include:
- Event management (similar to Luma)
- CRM functionality (comparable to Salesforce)
- Mass messaging via WhatsApp and email
- Customer CSV imports
Upcoming features:
- AI-driven automations for community management
- Forms and surveys
- Hackathon management
- Expense tracking
- Fundraising automation
- Social media management (like Buffer)
- Networking booking app (similar to Upstream)
- AI agent for user data scraping
- AI-driven content generation
- Blockchain NFTs for ticketing and marketplace
- Networking proximity maps for spontaneous meetings
- Node.js (version specified in
package.json
) - Docker and Docker Compose
- Git
-
Clone the repository:
-
Install dependencies:
npm install
-
Set up the database:
docker-compose up -d
-
Set up environment variables:
- Copy
.env.example
to.env
- Fill in the required values (see below for details)
- Copy
-
Run database migrations:
npm run migrate
-
Start the development server:
npm run dev
Copy the contents of .env.example
to a new file named .env
and fill in the values:
CALLBACK
: OAuth callback URLGOOGLE_CLIENT_ID
andGOOGLE_CLIENT_SECRET
: Google OAuth credentialsDIRECT_URL
andDATABASE_URL
: PostgreSQL database URLsAWS_ACCESS_KEY_ID
,AWS_SECRET_ACCESS_KEY
,AWS_REGION
,AWS_S3_BUCKET_NAME
: AWS S3 credentials for file uploads- Add any other required environment variables
- Frontend: Next.js with React
- Backend: Next.js API routes and server actions
- Database: PostgreSQL with Prisma ORM
- Authentication: NextAuth.js
- API: tRPC for type-safe API calls from native apps
- Validation: Zod for schema validation
- File Storage: AWS S3
- Email: AWS SES
- Payments: Mercado Pago
- We use server actions instead of REST or GraphQL for most operations
- tRPC is used for connecting native apps
- Prisma is used for database migrations and ORM
- Zod is used for data validation
For more details on available scripts and dependencies, refer to package.json
.
We welcome contributions to Andino! If you'd like to contribute:
- Fork the repository
- Create a new branch for your feature or bug fix
- Make your changes and commit them with clear, descriptive messages
- Push your changes to your fork
- Submit a pull request to the main repository
Please ensure your code follows the existing style and includes appropriate tests.
WIP
- WhatsApp Community: Join our WhatsApp group
- Twitter: @andino_labs
- Email: paul@andinolabs.io
For more information or to get involved, feel free to reach out through any of these channels!
Thank you for your interest in Andino! Together, we can build the ultimate tool for community engagement.
To simulate cron jobs locally, you can use the provided shell script. This script will call the cron routes every 2 minutes.
-
Make sure your local development server is running:
npm run dev
-
Open a new terminal window and navigate to the project root.
-
Run the script:
npm run run-crons
The script will continue running and calling the cron routes every 2 minutes until you stop it (use Ctrl+C to stop the script).
Note: Ensure that your local development server is running on http://localhost:3000
. If you're using a different port or URL, update the BASE_URL
in the run-crons.sh
script accordingly.
Andino uses a queue-based notification system to handle various types of communications with users. The system is built around the Notification
model in the database which acts as a queue for pending notifications.
-
Notifications are queued by creating entries in the
Notification
table with:- Target user(s)
- Organization context
- Notification type (email, WhatsApp, etc)
- Scheduled time to send
- Additional data needed for the notification
-
A cron job regularly checks for pending notifications and processes them through the appropriate channels (email/WhatsApp)
src/lib/
contains the core notification logic and handlerssrc/services/actions/
provides server actions that the frontend can use to queue notifications- All incoming/outgoing data is validated using Zod schemas defined in
src/schemas/
The email systems for notifications and inbound emails are based on an event driven system by using cron jobs to poll for stuff and execute. For outbound we use resend (https://resend.com/emails) api that is triggered by creating SEND_USER_MESSAGE queue job. You can queue up as many as these as you need without worrying about the order of handling them. They should be handled by src/lib/cron/queueCron.ts.
The inbound system is another cron job that polls the SQS queue for emails. This SQS will only return emails based on the AWS setup for the domain of the email. Once received we simply store the email in the database so that the app can display and it to the correct organization.
-
verify a domain in SES to use. Our platform will use an entire domain to send emails from based on the name of the organization.
-
setup the MX records for inbound (something like Host:@ value: inbound-smtp.us-east-1.amazonaws.com priority: 10) - use the region that the account is in.
-
in the SES console, create a receiving rule set with a catch all rule that allows all email to be received and "deliver to s3 bucket". Make a new IAM policy that has the write permissions to the bucket you are using to store. DONOT ASUME THAT THE BUCKET IS CREATED WITH THE CORRECT PERMISSIONS. SO long as u make a IAM policy with the correct permissions, u can use any bucket. In that same rule the second action must be to publish to an SNS topic - AGAIN DO NOT ASSUME THAT THE SNS TOPIC IS CREATED WITH THE CORRECT PERMISSIONS. you need to modify the permissons of the SNS topic to publish from the rule.
-
create a SQS queue and connect it to the SNS topic. Make sure that the SQS has the right permissions to connect to that topic.
-
generate and API key and secrete so that u can locally test this. You will be using the aws SQS client to receive the emails.
The permissions part is the trickiest part of all. Just use chatgpt to generate it or ask the chat. Or maybe use the cloudformation template to create the resources.(i havent tested it but it should work if u replace the placeholders with your own values.)