DevFrame is a free and open-source portfolio builder for developers. Users sign in, choose a ready-made template, fill in a guided form, and publish a portfolio at a route like /p/regie.
This repo is set up as an open-source app starter with:
- Next.js 16 App Router
- Tailwind CSS 4
- shadcn-style UI primitives
- Clerk authentication
- Supabase PostgreSQL
- Supabase Storage-ready architecture
- React Hook Form + Zod
- Vercel-friendly deployment setup
- Optional community support through GitHub, GoTyme InstaPay, and GCash
- Marketing homepage for DevFrame
- Clerk sign-in and sign-up routes
- Protected dashboard, templates, and builder pages
- Template catalog with three starter portfolio styles
- Public portfolio route at
/p/[slug] - API routes for templates and public portfolio fetches
- Server action for saving portfolio data
- Cookie-backed preview mode when Supabase is not configured yet
- Supabase schema file for real persistence
- Install dependencies.
npm install- Copy the example environment file.
cp .env.example .env.local- Create a Clerk app and add:
NEXT_PUBLIC_CLERK_PUBLISHABLE_KEYCLERK_SECRET_KEYCLERK_AUTHORIZED_PARTIESif you want to override the default origin allowlist
DevFrame keeps Clerk as auth/session infrastructure only and uses custom auth screens. For Clerk CLI checks, OAuth redirects, and email template setup, see docs/clerk-auth-setup.md.
- Create a Supabase project and add:
NEXT_PUBLIC_SUPABASE_URLNEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEYSUPABASE_SERVICE_ROLE_KEY
-
Run the SQL in supabase/schema.sql inside the Supabase SQL editor.
-
Start the app.
npm run devOpen http://localhost:3000.
- Set
NEXT_PUBLIC_APP_URLto your production origin, for examplehttps://your-domain.com. - Clerk
authorizedPartiesis now enforced insrc/proxy.ts. - By default it allows
NEXT_PUBLIC_APP_URLplus the current Vercel deployment URL(s). - If you want an explicit fixed allowlist, set
CLERK_AUTHORIZED_PARTIESas a comma-separated list such ashttps://your-domain.com,https://your-project.vercel.app. - For durable production rate limiting, set either
UPSTASH_REDIS_REST_URL+UPSTASH_REDIS_REST_TOKENor Vercel KV'sKV_REST_API_URL+KV_REST_API_TOKEN. If these are missing, DevFrame uses a per-instance in-memory fallback that is for local/dev only and is not durable security protection on Vercel serverless. - Leave Vercel's
Automatically expose System Environment Variablessetting enabled so preview deployments can useVERCEL_BRANCH_URL,VERCEL_URL, andVERCEL_PROJECT_PRODUCTION_URL.
| Branch | Purpose | Vercel deployment |
|---|---|---|
main |
Production | Live site |
staging |
Testing | Preview |
feature/* |
Dev | Preview |
- This requires a Vercel
ProorEnterpriseplan. - In Vercel, go to
Project Settings -> Environments -> Create Environment. - Create a custom environment named
staging. - Enable
Branch Trackingand point it at the Git branch namedstaging. - Add your
stagingenvironment variables there. - Optionally attach a staging domain like
staging.your-domain.com. - After that, every push to the Git branch
stagingwill automatically deploy to the Vercel environmentstaging, sovercel deploy --target=stagingbecomes optional.
- Import the repo into Vercel and keep
mainas the Production Branch. - Add your shared secrets to the correct Vercel environments:
- Production: real production values, including
NEXT_PUBLIC_APP_URL=https://your-domain.com - Preview: shared preview values for non-production branches
- Development: local
vercel dev/vercel env pullusage
- Production: real production values, including
- For
staging, add branch-specific Preview overrides only for values that should differ from other preview branches.- Example: set
NEXT_PUBLIC_APP_URL=https://staging.your-domain.comonly for thestagingpreview branch if you want a stable staging URL
- Example: set
- If you want a stable
stagingdomain, assign that domain to thestagingGit branch in Vercel. - Let
feature/*branches use the default generated Preview URLs unless you have a specific reason to override them.
- Production deploys use
NEXT_PUBLIC_APP_URLwhen you set it. - Preview deploys now automatically fall back to the active Vercel branch/deployment URL when
NEXT_PUBLIC_APP_URLis not set for Preview. - That means
stagingandfeature/*previews no longer fall back tohttp://localhost:3000for metadata and generated portfolio links.
DevFrame is free and open-source. The easiest ways to support the project are:
- Star the repository: https://github.com/RegieSanJuan/DevFrame
- Report bugs with clear reproduction steps.
- Suggest features through GitHub Issues or Discussions.
- Contribute code, docs, and templates. Start with CONTRIBUTING.md.
- Support development through the GoTyme InstaPay or GCash QR codes on
/support.
Donations are optional and help cover hosting, tools, and continued development. There is no Ko-fi, PayPal, Patreon, or payment API integration in this repo.
- If Clerk and Supabase are configured, portfolio submissions are saved to Supabase.
- If Supabase is missing, the builder still works in preview mode using a secure cookie so you can keep designing the experience locally.
- Public portfolio pages always try Supabase first, then fall back to local seeded examples and preview mode.
- Add image upload flows with Supabase Storage
- Add more template variants
- Add a custom domain workflow
- Add an editor for multiple projects, testimonials, and blog posts
- Improve contribution guides and community templates
DevFrame uses a modular template system. Each template is a standalone React component registered in a central registry.
- Specific Template: Edit the file in
src/templates/. For example, to change the "Nova" template, editsrc/templates/nova/index.tsx. - Shared Components: Common elements like
LinkPillorSkillBadgeare located insrc/templates/base-components.tsx. Changing these will update all templates simultaneously. - Global Styles: Core design tokens (colors, fonts) are defined as CSS variables in
src/app/globals.css.
- Create the component: Create a new file (e.g.,
src/templates/my-new-template.tsx). - Register it: Call
registerTemplate("my-slug", MyComponent)at the bottom of your file. - Import it: Add an import for your new template in
src/templates/index.ts. - Update Catalog: Add your template metadata (slug, name, tagline, etc.) to
src/lib/template-catalog.tsso it appearing in the builder. - (Optional) Add Seed Data: Add a sample portfolio for your template in
src/lib/portfolio-storage.tsto enable instant previews.
src/templates/registry.ts: The central registry mapping slugs to components.src/components/portfolio-renderer.tsx: The main renderer that dynamically loads the correct template.