Grantify is a Nigeria-focused matching and discovery platform that helps users find relevant grants and reputable loan providers, read community content, and make more informed decisions.
Important:
- Grantify does not issue loans or grants directly.
- Any final decision and terms are determined by third-party providers.
If enabled, a daily blog post can be auto-published via the cron defined in vercel.json at the path /api/cron/daily-blog.
The endpoint is protected. In Vercel, the recommended way to secure cron jobs is to set CRON_SECRET in your Vercel Environment Variables. When CRON_SECRET is set, Vercel Cron Jobs will call your cron URL with:
Authorization: Bearer <CRON_SECRET>
This repo also supports BLOG_CRON_SECRET for manual/local triggering (/api/cron/daily-blog?key=...).
If your logs show 401 Unauthorized from vercel-cron/1.0, it usually means:
- You set
BLOG_CRON_SECRET, but did not setCRON_SECRETin Vercel (so Vercel didn’t attach the Authorization header).
Fix:
- In Vercel → Project → Settings → Environment Variables: set
CRON_SECRETto the same value asBLOG_CRON_SECRET.
To reduce Vercel bandwidth/storage usage (and avoid storing images in Postgres), the Admin blog editor can upload images directly to offsite storage using signed upload URLs.
Supported providers:
s3(S3/R2-compatible object storage)onedrive(uses your OneDrive quota; requires OAuth)gdrive(uses your Google Drive quota; requires OAuth)
OFFSITE_UPLOADS_ENABLED=true
Pick a provider:
OFFSITE_UPLOADS_PROVIDER=s3(default)OFFSITE_UPLOADS_PROVIDER=onedriveOFFSITE_UPLOADS_PROVIDER=gdrive
Required:
GDRIVE_CLIENT_IDGDRIVE_CLIENT_SECRET
Optional (defaults shown):
GDRIVE_REDIRECT_URI(default:https://<your-domain>/api/uploads/gdrive/callback)
How to generate GDRIVE_CLIENT_ID / GDRIVE_CLIENT_SECRET:
- Go to Google Cloud Console → create/select a project.
- APIs & Services → Library → enable Google Drive API.
- APIs & Services → OAuth consent screen:
- Choose External (typical) or Internal (Workspace only).
- Add your app name and support email.
- Add test users (your Google account) if the app is in testing.
- APIs & Services → Credentials → Create Credentials → OAuth client ID.
- Application type: Web application.
- Authorized redirect URIs: add the exact callback URL(s) you will use:
- Production:
https://<your-domain>/api/uploads/gdrive/callback- For this repo’s production domain:
https://grantify.help/api/uploads/gdrive/callback
- For this repo’s production domain:
- Local dev (optional):
http://localhost:3001/api/uploads/gdrive/callback
- Production:
- Copy the generated values into environment variables:
GDRIVE_CLIENT_ID(Client ID)GDRIVE_CLIENT_SECRET(Client secret)
Notes:
- The redirect URI must match exactly (including
httpvshttpsand port). If you use local dev, setGDRIVE_REDIRECT_URI=http://localhost:3001/api/uploads/gdrive/callback. - Google only returns a refresh token the first time you consent for a given client + user. If you don’t get a refresh token, remove the app from your Google Account → Security → Third-party access, then reconnect.
Connect once (as an Admin):
- When prompted in the Admin UI during an image upload, complete the Google consent flow in the newly opened tab/window, then retry the upload.
Notes:
- Uploaded images are stored under
Grantify/blog-imagesin your Drive. - Public visitors can view images via
/api/uploads/gdrive/image?id=<fileId>(the server streams the bytes from Drive).
Required:
ONEDRIVE_CLIENT_IDONEDRIVE_CLIENT_SECRET
Optional (defaults shown):
ONEDRIVE_TENANT(defaultconsumersfor personal OneDrive)ONEDRIVE_REDIRECT_URI(default:https://<your-domain>/api/uploads/onedrive/callback)
Connect once (as an Admin):
- When prompted in the Admin UI during an image upload, complete the OneDrive consent flow in the newly opened tab/window, then retry the upload.
Notes:
- After upload, the server creates an anonymous share link so images are viewable by anyone.
Required:
S3_BUCKET(bucket name)S3_ACCESS_KEY_IDS3_SECRET_ACCESS_KEYS3_PUBLIC_BASE_URL(public base URL where objects are served, e.g.https://pub-<id>.r2.devor your custom domain)
Optional (needed for Cloudflare R2 and some S3-compatible providers):
S3_ENDPOINT(e.g.https://<accountid>.r2.cloudflarestorage.com)S3_REGION(defaults toauto)
- The upload endpoint is
POST /api/uploads/imageand requires an Admin session. - The browser uploads the file directly to storage with
PUT(the server only generates the signed URL). - Your bucket must allow CORS for
PUTfrom your site origin.