Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions .github/workflows/deploy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ on:
type: choice
options:
- vercel
- render
- firebase

jobs:
Expand All @@ -39,6 +40,19 @@ jobs:
VERCEL_TOKEN: ${{ secrets.VERCEL_TOKEN }}
VERCEL_ENV: ${{ github.event.inputs.environment || 'production' }}

deploy-render:
if: ${{ github.event_name == 'workflow_dispatch' && inputs.provider == 'render' }}
runs-on: ubuntu-latest
environment:
name: ${{ github.event.inputs.environment }}
steps:
- uses: actions/checkout@v7
- uses: jdx/mise-action@v4
- name: Deploy to Render
run: mise run deploy:render
env:
RENDER_DEPLOY_HOOK: ${{ secrets.RENDER_DEPLOY_HOOK }}

deploy-firebase:
if: ${{ github.event_name == 'workflow_dispatch' && inputs.provider == 'firebase' }}
runs-on: ubuntu-latest
Expand Down
10 changes: 10 additions & 0 deletions .mise.toml
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,16 @@ else
fi
"""

[tasks."deploy:render"]
description = "Deploy the site to Render"
run = """
if [ -z "$RENDER_DEPLOY_HOOK" ]; then
echo "Error: RENDER_DEPLOY_HOOK is not set." >&2
exit 1
fi
curl -f -X POST "$RENDER_DEPLOY_HOOK"
"""

[tasks."deploy:vercel"]
description = "Deploy the site to Vercel"
run = """
Expand Down
1 change: 1 addition & 0 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ Validated via Zod in `app/lib/env.ts`.

## 13. Deployment
- Vercel: Primary target for SSR site (`mise run deploy:vercel` / `deploy.yml`).
- Render: Web service target for SSR site (`mise run deploy:render` / `render.yaml` / `deploy.yml`).
- Firebase Hosting: Alternative target for site and docs (`mise run deploy:firebase`).
- GitHub Pages: Static documentation hosting (`docs.yml`).

Expand Down
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ cur8d is an opinionated, production-ready Next.js starter template optimized for
- **Comprehensive Testing Rigor**: Robust test coverage enforcement (80%+ target) with Vitest for unit/component tests and Playwright for E2E, visual, and accessibility (Axe) audits.
- **Static Documentation Project**: An integrated documentation workspace powered by Nextra, generating a static site ready for GitHub Pages or Firebase hosting.
- **Zero-Friction Dev Environment**: Fully managed local development tasks and toolchains via `mise`, including custom alias shortcuts for common git and npm tasks.
- **Flexible Deployment Targets**: Configured for Serverless deployments on Vercel (ideal for Next.js App Router and Server Components) and static site deployment on Firebase Hosting.
- **Flexible Deployment Targets**: Configured for Serverless deployments on Vercel, Node.js web service on Render, and static site deployment on Firebase Hosting.

## Project Structure

Expand All @@ -33,6 +33,7 @@ This project is organized as a monorepo workspace managed by `pnpm`:
│ ├── unit/ # Component and utility tests (Vitest)
│ └── e2e/ # E2E and accessibility audits (Playwright)
├── .mise.toml # Toolchain, task definitions, and run shortcuts
├── render.yaml # Render Blueprint specification
└── pnpm-workspace.yaml # Monorepo workspaces definition
```

Expand All @@ -49,7 +50,7 @@ The core framework and library stack includes (without version locks):
- **Unit Testing**: Vitest with React Testing Library & jsdom
- **E2E & A11y Testing**: Playwright & `@axe-core/playwright`
- **Documentation**: Nextra & Markdown (MDX)
- **Deployments**: Vercel CLI & Firebase CLI
- **Deployments**: Vercel CLI, Render Blueprint & Deploy Hook, and Firebase CLI

## Quick Start

Expand Down
6 changes: 3 additions & 3 deletions docs/content/adr/adr-008-vercel.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ Status: Accepted
We need a scalable, automated hosting architecture supporting both Server-Side Rendered (SSR) web applications and static documentation.

## Decision
We chose Vercel as the primary SSR deployment platform, Firebase Hosting as an alternative multi-target host, and GitHub Pages for static documentation.
We chose Vercel as the primary SSR deployment platform, Render as a managed Node.js web service platform, Firebase Hosting as an alternative multi-target host, and GitHub Pages for static documentation.

## Rationale
Vercel delivers native zero-configuration optimization for Next.js App Router, React Server Components, and Edge Middleware. GitHub Pages provides free, high-availability hosting for Nextra static docs, and Firebase Hosting serves as a battle-tested static and preview environment.
Vercel delivers native zero-configuration optimization for Next.js App Router, React Server Components, and Edge Middleware. Render provides fully managed Node.js runtime hosting with Blueprints and Deploy Hooks. GitHub Pages provides free, high-availability hosting for Nextra static docs, and Firebase Hosting serves as a battle-tested static and preview environment.

## Consequences
Workflows in `.github/workflows/` are partitioned into `deploy.yml` (application deployment to Vercel/Firebase) and `docs.yml` (documentation deployment to GitHub Pages).
Workflows in `.github/workflows/` are partitioned into `deploy.yml` (application deployment to Vercel/Render/Firebase) and `docs.yml` (documentation deployment to GitHub Pages).

1 change: 1 addition & 0 deletions docs/content/deployment/_meta.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export default {
"index": "Overview",
"vercel": "Vercel",
"render": "Render",
"firebase": "Firebase Hosting",
"github-pages": "GitHub Pages"
}
1 change: 1 addition & 0 deletions docs/content/deployment/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
Instructions for deploying your cur8d application and documentation.

- [Vercel](/deployment/vercel)
- [Render](/deployment/render)
- [Firebase Hosting](/deployment/firebase)
- [GitHub Pages](/deployment/github-pages)

36 changes: 36 additions & 0 deletions docs/content/deployment/render.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Render Deployment

Render provides cloud hosting for Next.js App Router applications as a managed Node.js web service, fully supporting Server Components, API routes, and SSR.

## Configuration

Render services can be defined as Infrastructure-as-Code using Render Blueprints:

- [`render.yaml`](file:///Users/amrabed/Library/CloudStorage/OneDrive-Personal/code/cur8d.tsx/render.yaml): Configures the web service name, Node.js runtime, build command (`pnpm install && pnpm run build`), start command (`pnpm run start`), and environment variables.

## Automated CI/CD Deployment

Render deployment can be automated via Render Deploy Hooks and GitHub Actions:

- **Deploy Hooks**: Trigger zero-downtime deployments instantly by sending a POST request to your Render Deploy Hook URL.
- **GitHub Actions Workflow**: Configured in `.github/workflows/deploy.yml`. Can be triggered on-demand via `workflow_dispatch` selecting the `render` provider.

### Setting up Secrets in GitHub

To enable automated deployments via GitHub Actions:
1. Navigate to your Web Service in the [Render Dashboard](https://dashboard.render.com).
2. Go to **Settings** > **Deploy Hook** and copy your hook URL.
3. Add `RENDER_DEPLOY_HOOK` to your repository secrets (`Settings > Secrets and variables > Actions`).

## Local Deployment via mise

You can trigger a deployment directly from your terminal using `mise` or `pnpm`:

```bash
# Trigger Render deployment via deploy hook
export RENDER_DEPLOY_HOOK="https://api.render.com/deploy/srv-xxxx?key=yyyy"
mise run deploy:render

# Or using package.json script directly
pnpm run deploy:render
```
1 change: 1 addition & 0 deletions docs/content/getting-started/environment-variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ Environment variables are validated against the `envSchema` defined in `app/lib/
These tokens are used by deployment workflows in `.github/workflows/deploy.yml` and local deployment tasks defined in `.mise.toml`:

- `VERCEL_TOKEN`: Authentication token for automated deployments using Vercel CLI.
- `RENDER_DEPLOY_HOOK`: Webhook URL for triggering automated deployments to Render.
- `FIREBASE_TOKEN`: Authentication token for deploying to Firebase Hosting via Firebase CLI.

## Schema Definition
Expand Down
1 change: 1 addition & 0 deletions docs/content/getting-started/project-structure.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ The project follows a modern Next.js App Router workspace structure optimized fo
- `.mise.toml`: Toolchain management and task definitions.
- `pnpm-workspace.yaml`: Monorepo workspaces definition.
- `firebase.json` & `.firebaserc`: Firebase Hosting configuration for app and docs.
- `render.yaml`: Render Blueprint deployment configuration.
- `vercel.json`: Vercel deployment configuration.

## Application Directory (`app/`)
Expand Down
3 changes: 2 additions & 1 deletion docs/content/reference/workflows.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ Cur8d includes pre-configured GitHub Actions workflows in `.github/workflows/` w
- **Triggers**: Push to `main` (excluding changes strictly in `docs/**`) and manual trigger (`workflow_dispatch`).
- **Inputs**:
- `environment`: `'production'` (default) or `'preview'`.
- `provider`: `'vercel'` (default) or `'firebase'`.
- `provider`: `'vercel'` (default), `'render'`, or `'firebase'`.
- **Jobs**:
- `deploy-vercel`: Runs `mise run deploy:vercel` using `VERCEL_TOKEN`.
- `deploy-render`: Runs `mise run deploy:render` using `RENDER_DEPLOY_HOOK`.
- `deploy-firebase`: Runs `mise run deploy:firebase` using `FIREBASE_TOKEN`.

### 3. Documentation Deployment (`docs.yml`)
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"test:e2e:report": "playwright show-report",
"analyze": "ANALYZE=true next build",
"deploy:firebase": "firebase deploy --only hosting:site",
"deploy:firebase:docs": "firebase deploy --only hosting:docs"
"deploy:firebase:docs": "firebase deploy --only hosting:docs",
"deploy:render": "curl -f -X POST $RENDER_DEPLOY_HOOK"
},
"dependencies": {
"@heroui/react": "3.2.4",
Expand Down
10 changes: 10 additions & 0 deletions render.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
services:
- type: web
name: cur8d
runtime: node
plan: starter
buildCommand: pnpm install && pnpm run build
startCommand: pnpm run start
envVars:
- key: NODE_ENV
value: production
6 changes: 5 additions & 1 deletion scripts/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ async function main() {
'app/components/Navbar/index.tsx',
'app/page.tsx',
'.firebaserc',
'render.yaml',
'docs/app/[[...mdxPath]]/layout.tsx',
'docs/theme.config.jsx',
'docs/next.config.mjs',
Expand Down Expand Up @@ -151,12 +152,15 @@ async function main() {
content = content.replace(/"name": "docs"/, `"name": "${slug}-docs"`);
}

// 4. Firebase project IDs
// 4. Firebase & Render project configs
if (file === '.firebaserc') {
content = content.replace(/cur8d-vibe/g, `${slug}`);
content = content.replace(/cur8d-site/g, `${slug}-site`);
content = content.replace(/cur8d-docs/g, `${slug}-docs`);
}
if (file === 'render.yaml') {
content = content.replace(/name: cur8d/g, `name: ${slug}`);
}

// 5. Descriptions (must happen before general cur8d replacement)
if (description) {
Expand Down