-
Notifications
You must be signed in to change notification settings - Fork 979
Create main.yml #472
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
eevanlai-stack
wants to merge
114
commits into
vercel:app-auth
Choose a base branch
from
eevanlai-stack:main
base: app-auth
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Create main.yml #472
Changes from all commits
Commits
Show all changes
114 commits
Select commit
Hold shift + click to select a range
4aecadb
App Router Migration (#221)
steven-tey 5d83d9e
workaround
steven-tey 7e230a2
remove dark mode from Tremor
steven-tey b2b6c9f
added prettier
steven-tey d75e0f2
return null for generateMetadata
steven-tey 41b6445
fixed revalidateTag bug
steven-tey e850abf
fixed revalidateTag (was revalidating the wrong ones)
steven-tey 01acf25
small fix
steven-tey 2cf60e1
Added custom 404 pages
steven-tey 1cb1ace
add router.refresh() when creating site
steven-tey 2c96d28
added va track
steven-tey 4a429cc
move not-found to page level, added metadatabase
steven-tey 5425bea
updated login page
steven-tey f0a45ab
temp fix for server action error obfuscated in prod
steven-tey 5f28d5d
remove color selector, updated github auth env var names
steven-tey 5ceb766
Update README.md
steven-tey 17f46dc
edit ctas
steven-tey 40a52ed
refresh router when delete site, upgrade next to latest
steven-tey 5cffd0b
router.refresh when delete post
steven-tey d2fbdb4
fix how we handle errors with Server Actions
steven-tey 42e64cd
updated deploy button
steven-tey 30563bc
Update login-button.tsx
steven-tey d42d3b4
patch fix revalidateTag
steven-tey 1a7e4db
update next to canary
steven-tey 107af11
fix revalidate tags syntax
steven-tey 1d074c2
fix cache keys
steven-tey 8d9d664
test tarball fix
steven-tey 137e33e
added report abuse button, upgraded next to canary
steven-tey 5fa14e3
removed file based metadata
steven-tey 1970167
added dynamic sitemap
steven-tey 90b134c
bug fixes and improve UX
steven-tey 06fb6ec
hide sidebar on path change
steven-tey e5cd134
redirect vercel.pub to blog post
steven-tey 6453d5e
fixed infinite loop in editor
steven-tey a01298e
revalidate metadata on site create and delete too
steven-tey 8ac049f
override default CMD+S behavior
steven-tey 5b8cc4d
change editor autoFocus to title
steven-tey e4f18e5
fixed image uploader
steven-tey 63006ba
Added dark mode 🥳 (#228)
steven-tey b63e3d6
Added dark mode for client pages too
steven-tey 935d227
small fixes
steven-tey 7794f0e
upgrade react-tweet
steven-tey 20643af
fix styles
steven-tey 640ff7b
updated CTAs
steven-tey 99756cb
await revalidateTag
steven-tey 70d0ad8
fix login page dark mode styles
steven-tey af3b8ac
fix prisma
steven-tey b97a867
Create opengraph-image.png
steven-tey 8eca7d5
Update README.md
steven-tey ae23480
added rate-limiting with Vercel KV
steven-tey e9e5719
Merge branch 'main' of https://github.com/vercel/platforms
steven-tey 8f81acd
fix incorrect CNAME
steven-tey 82463bf
fix dark mode author name styles
steven-tey 3e21a46
Add tremor link to README.md (#235)
christopherkindl 9c329e4
fix instances of vercel.pub
steven-tey 6a00df4
Fix markdown links (#239)
lfades 8cf1ad9
Fix tweet styles (#241)
lfades 2a894e5
Update .env.example
steven-tey c42e919
fix thumbnail image
steven-tey d0bc8c2
Update .env.example (#237)
arig4m3r bec449b
upgrade next to canary
steven-tey 505a8cf
Update next version to fix dependency resolution (#247)
olistic 9120f47
added POSTGRES_URL_NON_POOLING
steven-tey b538188
Include title and desc in autocomplete context (#251)
DevMaxC d2ed0af
refactor import statement (#249)
zafarruzmatov 5b9847b
chore: removing the fs dependency (#240)
nicholasgriffintn d91dfc6
Update all deps (#255)
steven-tey 4691a62
Update fetchers.ts
steven-tey 94a2eea
Updated root page, added tailwind-merge
steven-tey e2aa869
added tally form for blob beta
steven-tey befb025
Update README.md
steven-tey 5dfa338
Update middleware.ts
steven-tey 5a2a284
Update middleware.ts
steven-tey 1c761dd
upgrade next to canary
steven-tey 7ded19d
Merge branch 'main' of https://github.com/vercel/platforms
steven-tey b99d24a
Added `novel` SDK (#309)
steven-tey b6f2a5e
make TEAM_ID_VERCEL optional
steven-tey fe1e2c7
bump next to canary
steven-tey ffd9a8f
optional: add canonical URLs
steven-tey 4cfd59c
fix: issue that causes root home page to 404 on vercel (#323)
chroxify ebb8954
domain from page params converted to decodeURIComponent (#313)
Adnan0061 76734c1
fix(prisma): Remove shadowDatabaseUrl and upgrade to newest Prisma (t…
janpio 36a5a67
generateStaticParams
steven-tey 2fa51dc
fix ts issue
steven-tey e9e5367
account for www.
steven-tey eeabcf1
import prisma
steven-tey ef6fc76
fix ts error
steven-tey 5084746
Fox #288
steven-tey ca3bc27
fix ts error
steven-tey 2435c66
fix generateStaticParams
steven-tey 1ed55b1
fix
steven-tey a281c65
bump next-auth
steven-tey 4708aea
fix: placeholder typo (#301)
0o001 a645f23
bump version
steven-tey c83b6ff
bump next.js version
steven-tey 5947c92
revert to 13.5.4
steven-tey 379b8da
revert
steven-tey 2ba463a
change version
steven-tey 3f4cbf3
fixed issue
steven-tey dbbc887
Replace deprecated props (#348)
ItzCrazyKns 841619c
Subdomain Previews Implementation (#347)
steven-tey a634401
fix: (minor) double class (#284)
jpvalery ff88e60
Chore: collpase imports from the same library into a single statement…
TatisLois fdca323
Fix analytics Top Pages rendering bug (#331)
versecafe 29e20e7
Update dependencies. (#353)
leerob 7e33556
Migrate to Drizzle ORM (#404)
realmikesolo 834ca43
update deploy button env link and text (#440)
ismaelrumzan 299867c
Migrate to new, simplified example. (#451)
leerob 0658ac1
Update README.md (#454)
yamz8 a2845dd
Small update to Middleware
leerob 5bab8fb
Fix client error
leerob 29cfcbe
Add Vercel Analytics and Speed Insights integration (#468)
dieDeMiguel d8d803f
Create main.yml
eevanlai-stack 3a765ec
Create npm
eevanlai-stack File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
name: NodeJS with Gulp | ||
|
||
on: | ||
push: | ||
branches: [ "main" ] | ||
pull_request: | ||
branches: [ "main" ] | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
|
||
strategy: | ||
matrix: | ||
node-version: [18.x, 20.x, 22.x] | ||
|
||
steps: | ||
- uses: actions/checkout@v4 | ||
|
||
- name: Use Node.js ${{ matrix.node-version }} | ||
uses: actions/setup-node@v4 | ||
with: | ||
node-version: ${{ matrix.node-version }} | ||
|
||
- name: Build | ||
run: | | ||
npm install | ||
gulp |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,41 @@ | ||
**/node_modules | ||
**.next | ||
**.env | ||
**.DS_Store | ||
**.vercel | ||
**.git | ||
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files. | ||
|
||
# dependencies | ||
/node_modules | ||
/.pnp | ||
.pnp.* | ||
.yarn/* | ||
!.yarn/patches | ||
!.yarn/plugins | ||
!.yarn/releases | ||
!.yarn/versions | ||
|
||
# testing | ||
/coverage | ||
|
||
# next.js | ||
/.next/ | ||
/out/ | ||
|
||
# production | ||
/build | ||
|
||
# misc | ||
.DS_Store | ||
*.pem | ||
|
||
# debug | ||
npm-debug.log* | ||
yarn-debug.log* | ||
yarn-error.log* | ||
.pnpm-debug.log* | ||
|
||
# env files (can opt-in for committing if needed) | ||
.env* | ||
|
||
# vercel | ||
.vercel | ||
|
||
# typescript | ||
*.tsbuildinfo | ||
next-env.d.ts |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,137 +1,90 @@ | ||
<p align="center"> | ||
<a href="https://demo.vercel.pub"> | ||
<img src="https://assets.vercel.com/image/upload/v1588805858/repositories/vercel/logo.png" height="96"> | ||
<h3 align="center">Platforms Starter Kit</h3> | ||
</a> | ||
</p> | ||
# Next.js Multi-Tenant Example | ||
|
||
<p align="center"> | ||
The <em>all-in-one</em> starter kit <br/> | ||
for building platforms on Vercel. | ||
</p> | ||
A production-ready example of a multi-tenant application built with Next.js 15, featuring custom subdomains for each tenant. | ||
|
||
<p align="center"> | ||
<a href="#introduction"><strong>Introduction</strong></a> · | ||
<a href="https://vercel.com/guides/nextjs-multi-tenant-application"><strong>Guide</strong></a> · | ||
<a href="https://demo.vercel.pub/"><strong>Demo</strong></a> · | ||
<a href="https://steven.vercel.pub/kitchen-sink"><strong>Kitchen Sink</strong></a> · | ||
<a href="#contributing"><strong>Contributing</strong></a> | ||
</p> | ||
<br/> | ||
## Features | ||
|
||
## Deploy Your Own | ||
- ✅ Custom subdomain routing with Next.js middleware | ||
- ✅ Tenant-specific content and pages | ||
- ✅ Shared components and layouts across tenants | ||
- ✅ Redis for tenant data storage | ||
- ✅ Admin interface for managing tenants | ||
- ✅ Emoji support for tenant branding | ||
- ✅ Support for local development with subdomains | ||
- ✅ Compatible with Vercel preview deployments | ||
|
||
[Read the guide](https://vercel.com/guides/nextjs-multi-tenant-application) to learn how to deploy your own version of this template. | ||
## Tech Stack | ||
|
||
## Introduction | ||
- [Next.js 15](https://nextjs.org/) with App Router | ||
- [React 19](https://react.dev/) | ||
- [Upstash Redis](https://upstash.com/) for data storage | ||
- [Tailwind 4](https://tailwindcss.com/) for styling | ||
- [shadcn/ui](https://ui.shadcn.com/) for the design system | ||
|
||
Multi-tenant applications serve multiple customers across different subdomains/custom domains with a single unified codebase. | ||
## Getting Started | ||
|
||
For example, our demo is a multi-tenant application: | ||
### Prerequisites | ||
|
||
- Subdomain: [demo.vercel.pub](http://demo.vercel.pub) | ||
- Custom domain: [platformize.co](http://platformize.co) (maps to [demo.vercel.pub](http://demo.vercel.pub)) | ||
- Build your own: [app.vercel.pub](http://app.vercel.pub) | ||
- Node.js 18.17.0 or later | ||
- pnpm (recommended) or npm/yarn | ||
- Upstash Redis account (for production) | ||
|
||
Another example is [Hashnode](https://vercel.com/customers/hashnode), a popular blogging platform. Each writer has their own unique `.hashnode.dev` subdomain for their blog: | ||
### Installation | ||
|
||
- [eda.hashnode.dev](https://eda.hashnode.dev/) | ||
- [katycodesstuff.hashnode.dev](https://katycodesstuff.hashnode.dev/) | ||
- [akoskm.hashnode.dev](https://akoskm.hashnode.dev/) | ||
1. Clone the repository: | ||
|
||
Users can also map custom domains to their `.hashnode.dev` subdomain: | ||
```bash | ||
git clone https://github.com/vercel/platforms.git | ||
cd platforms | ||
``` | ||
|
||
- [akoskm.com](https://akoskm.com/) → [akoskm.hashnode.dev](https://akoskm.hashnode.dev/) | ||
2. Install dependencies: | ||
|
||
This repository makes it easier than ever for creators to build their own platform. | ||
```bash | ||
pnpm install | ||
``` | ||
|
||
## Template features | ||
3. Set up environment variables: | ||
Create a `.env.local` file in the root directory with: | ||
|
||
Forget manually setting up CNAME records, wrestling with DNS, or making custom server rewrite rules with NGINX. With Vercel and the Platforms Starter Kit, you can focus on building the next big thing. | ||
``` | ||
KV_REST_API_URL=your_redis_url | ||
KV_REST_API_TOKEN=your_redis_token | ||
``` | ||
|
||
- **Custom domains**: Subdomain and custom domains support with [Edge Functions](https://vercel.com/features/edge-functions) and the [Vercel Domains API](https://domains-api.vercel.app/). | ||
- **Static generation with ISR**: Performance without sacrificing personalization, by combining [Incremental Static Regeneration](https://vercel.com/docs/concepts/next.js/incremental-static-regeneration) (ISR) and [Middleware](https://vercel.com/docs/concepts/functions/edge-functions#middleware). ISR allows you to create new content (with custom domains) on demand without needing to redeploy your application. | ||
- **Uploading custom images**: Allow your customers to upload custom thumbnail images with our Cloudinary integration. | ||
- **Static tweets**: Avoid [Cumulative Layout Shift](https://vercel.com/blog/core-web-vitals) (CLS) from the native Twitter embed by using our [static tweets implementation](https://static-tweets-tailwind.vercel.app/) (supports image, video, gif, poll, retweets, quote retweets, and more). | ||
4. Start the development server: | ||
|
||
## Examples of platforms | ||
```bash | ||
pnpm dev | ||
``` | ||
|
||
Vercel customers like [Hashnode](https://vercel.com/customers/hashnode), [Super](https://super.so), and [Cal.com](https://cal.com) are building scalable platforms on top of Vercel and Next.js. There are multiple types of platforms you can build with this starter kit: | ||
5. Access the application: | ||
- Main site: http://localhost:3000 | ||
- Admin panel: http://localhost:3000/admin | ||
- Tenants: http://[tenant-name].localhost:3000 | ||
|
||
### 1. Content creation platforms | ||
## Multi-Tenant Architecture | ||
|
||
These are content-heavy platforms (blogs) with simple, standardized page layouts and route structure. | ||
This application demonstrates a subdomain-based multi-tenant architecture where: | ||
|
||
> “With Vercel, we spend less time managing our infrastructure and more time delivering value to our users.” — Sandeep Panda, Co-founder, Hashnode | ||
- Each tenant gets their own subdomain (`tenant.yourdomain.com`) | ||
- The middleware handles routing requests to the correct tenant | ||
- Tenant data is stored in Redis using a `subdomain:{name}` key pattern | ||
- The main domain hosts the landing page and admin interface | ||
- Subdomains are dynamically mapped to tenant-specific content | ||
|
||
1. [Hashnode](https://hashnode.com) | ||
2. [Mirror.xyz](https://mirror.xyz/) | ||
3. [Read.cv](https://read.cv/) | ||
The middleware (`middleware.ts`) intelligently detects subdomains across various environments (local development, production, and Vercel preview deployments). | ||
|
||
### 2. Website & e-commerce store builders | ||
## Deployment | ||
|
||
No-code site builders with customizable pages. | ||
This application is designed to be deployed on Vercel. To deploy: | ||
|
||
By using Next.js and Vercel, [Super](https://super.so/) has fast, globally distributed websites with a no-code editor (Notion). Their customers get all the benefits of Next.js (like [Image Optimization](https://nextjs.org/docs/basic-features/image-optimization)) without touching any code. | ||
1. Push your repository to GitHub | ||
2. Connect your repository to Vercel | ||
3. Configure environment variables | ||
4. Deploy | ||
|
||
1. [Super.so](https://super.so) | ||
2. [Typedream](https://typedream.com) | ||
3. [Makeswift](https://www.makeswift.com/) | ||
For custom domains, make sure to: | ||
|
||
### 3. B2B2C platforms | ||
|
||
Multi-tenant authentication, login, and access controls. | ||
|
||
With Vercel and Next.js, platforms like [Instatus](https://instatus.com) are able to create status pages that are *10x faster* than competitors. | ||
|
||
1. [Instatus](https://instatus.com/) | ||
2. [Cal.com](https://cal.com/) | ||
3. [Dub](https://dub.sh/) | ||
|
||
## Built on open source | ||
|
||
This working demo site was built using the Platforms Starter Kit and: | ||
|
||
- [Next.js](https://nextjs.org/) as the React framework | ||
- [Tailwind](https://tailwindcss.com/) for CSS styling | ||
- [Prisma](https://prisma.io/) as the ORM for database access | ||
- [PlanetScale](https://planetscale.com/) as the database (MySQL) | ||
- [NextAuth.js](https://next-auth.js.org/) for authentication | ||
- [Vercel](http://vercel.com/) for deployment | ||
|
||
We also have another [example](https://github.com/vercel/examples/tree/main/solutions/platforms-slate-supabase) of the Platforms Starter Kit that uses Supabase for the database and Slate.js for the text editor. | ||
|
||
## Frequently Asked Questions | ||
|
||
- **Should we be generating static webpages with `getStaticProps` and `getStaticPaths` at build time? It doesn't seem to be very scalable.** | ||
|
||
For scale, we recommend using [Incremental Static Regeneration](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration) instead. This basically means that instead of generating all pages at build time, you only specify a subset of pages and then generate the rest on the fly. Then when someone requests that page, all subsequent requests will be cached on the Vercel edge. You can also use [on-demand ISR](https://nextjs.org/docs/basic-features/data-fetching/incremental-static-regeneration#on-demand-revalidation) to programmatically invalidate caches per page every time someone makes a change to it, which is what we do [here](https://github.com/vercel/platforms/blob/1b2bd00055bbbdde8f2dcc89e0bdb2c3f8488f97/lib/api/post.ts#L243-L257). | ||
|
||
- **Is it wise to be using the `/_sites/[site]` path to serve all static pages/website? Wouldn't that lead to a significant amount of load on a single Next.js server?** | ||
|
||
The beauty about a serverless setup is you won’t have to worry about load since each request invokes a separate serverless function, and once it’s cached, you don’t invoke the server anymore (the page is served directly from the Vercel edge). Read more about the [Vercel Edge Network](https://vercel.com/docs/concepts/edge-network/overview) and [how caching works](https://vercel.com/docs/concepts/edge-network/caching). | ||
|
||
|
||
## Caveats | ||
|
||
- This template does not work with i18n, which is an [advanced feature in Next.js](https://nextjs.org/docs/advanced-features/i18n-routing). | ||
|
||
|
||
## Contributing | ||
|
||
- [Start a discussion](https://github.com/vercel/platforms/discussions) with a question, piece of feedback, or idea you want to share with the team. | ||
- [Open an issue](https://github.com/vercel/platforms/issues) if you believe you've encountered a bug with the starter kit. | ||
|
||
## Author | ||
|
||
- Steven Tey ([@steventey](https://twitter.com/steventey)) | ||
|
||
## License | ||
|
||
The MIT License. | ||
|
||
--- | ||
|
||
<a aria-label="Vercel logo" href="https://vercel.com"> | ||
<img src="https://badgen.net/badge/icon/Made%20by%20Vercel?icon=zeit&label&color=black&labelColor=black"> | ||
</a> | ||
1. Add your root domain to Vercel | ||
2. Set up a wildcard DNS record (`*.yourdomain.com`) on Vercel |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
'use server'; | ||
|
||
import { redis } from '@/lib/redis'; | ||
import { isValidIcon } from '@/lib/subdomains'; | ||
import { revalidatePath } from 'next/cache'; | ||
import { redirect } from 'next/navigation'; | ||
import { rootDomain, protocol } from '@/lib/utils'; | ||
|
||
export async function createSubdomainAction( | ||
prevState: any, | ||
formData: FormData | ||
) { | ||
const subdomain = formData.get('subdomain') as string; | ||
const icon = formData.get('icon') as string; | ||
|
||
if (!subdomain || !icon) { | ||
return { success: false, error: 'Subdomain and icon are required' }; | ||
} | ||
|
||
if (!isValidIcon(icon)) { | ||
return { | ||
subdomain, | ||
icon, | ||
success: false, | ||
error: 'Please enter a valid emoji (maximum 10 characters)' | ||
}; | ||
} | ||
|
||
const sanitizedSubdomain = subdomain.toLowerCase().replace(/[^a-z0-9-]/g, ''); | ||
|
||
if (sanitizedSubdomain !== subdomain) { | ||
return { | ||
subdomain, | ||
icon, | ||
success: false, | ||
error: | ||
'Subdomain can only have lowercase letters, numbers, and hyphens. Please try again.' | ||
}; | ||
} | ||
|
||
const subdomainAlreadyExists = await redis.get( | ||
`subdomain:${sanitizedSubdomain}` | ||
); | ||
if (subdomainAlreadyExists) { | ||
return { | ||
subdomain, | ||
icon, | ||
success: false, | ||
error: 'This subdomain is already taken' | ||
}; | ||
} | ||
|
||
await redis.set(`subdomain:${sanitizedSubdomain}`, { | ||
emoji: icon, | ||
createdAt: Date.now() | ||
}); | ||
|
||
redirect(`${protocol}://${sanitizedSubdomain}.${rootDomain}`); | ||
} | ||
|
||
export async function deleteSubdomainAction( | ||
prevState: any, | ||
formData: FormData | ||
) { | ||
const subdomain = formData.get('subdomain'); | ||
await redis.del(`subdomain:${subdomain}`); | ||
revalidatePath('/admin'); | ||
return { success: 'Domain deleted successfully' }; | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.