A full-stack blog sharing application, refactored into a single repo with:
- Backend in the project root (
Node.js+Express+MongoDB) - Frontend in the
client/folder (React+Vite) - Production build served statically from the backend (
dist/)
The repository also demonstrates a simple CI/CD pipeline using GitHub Actions and Fly.io.
This project is part of the Full Stack Open curriculum. The application allows users to:
- Create new blog posts
- Like existing blogs
- View all blogs in a list
- Authenticate with a username and password
On top of the basic bloglist functionality, this repo focuses on:
- Automated testing (backend & frontend)
- Linting & style checks
- Continuous deployment to Fly.io
At a high level:
-
Backend API & server
- Location: project root
- Entry point:
index.js→ usesapp.js - Static files served from:
dist/(built frontend)
-
Frontend (React + Vite)
- Location:
client/ - Entry point:
client/src/main.jsx - API calls:
- Blogs:
client/src/services/blogs.js→/api/blogs - Login:
client/src/services/login.js→/api/login
- Blogs:
- Location:
-
Tests
- Backend tests:
tests/(Node test runner + Supertest) - Frontend tests: under
client/src(Vitest + Testing Library)
- Backend tests:
-
Frontend
- React, Vite, Axios, Testing Library, Vitest
-
Backend
- Node.js, Express, Mongoose (MongoDB), JSON Web Tokens, bcrypt
-
DevOps
- GitHub Actions
- Fly.io for deployment
- Dockerfile for container-based deployment
The CI/CD setup is defined in GitHub Actions workflows under .github/workflows/:
- Deploy & test workflow:
.github/workflows/pipeline.yml
Triggers
- On push to the
mainbranch. - On pull requests targeting
main(runs checks only, no deployment).
Jobs
-
deploy_pipeline– Build, lint, test, and (on push) deploy- Environment
- Uses Node.js 20 on
ubuntu-latest.
- Uses Node.js 20 on
- Backend steps
npm installnpm run lintnpm run test(usesTEST_MONGODB_URIandSECRETfrom GitHub secrets).
- Frontend steps
npm run install:clientnpm run lint:clientnpm run test:clientnpm run build:client
- Deploy (push events only)
flyctl deploy --remote-onlyusing theFLY_API_TOKENGitHub secret.
- Environment
-
tag_release– Automatically bump version and create a Git tag- Runs after
deploy_pipelinecompletes successfully (needs: [deploy_pipeline]). - Uses
anothrNick/github-tag-actionto:- Bump the version (default: patch).
- Push a corresponding Git tag back to GitHub.
- Runs only on push events (
GITHUB_TOKENis provided automatically by GitHub).
- Runs after
Required GitHub secrets
FLY_API_TOKEN– Fly.io API token used for deployment.TEST_MONGODB_URI– MongoDB connection string used by the backend test suite in CI.SECRET– JWT signing secret used during backend tests in CI.GITHUB_TOKEN– Automatically provided by GitHub; used by the tagging action.
git clone https://github.com/[YOUR_USERNAME]/[YOUR_REPO_NAME].git
npm install
npm run install:client
fly launch
Change the port on the default fly.toml from 3000 > 3003 or the port in the .env file!
Adapt the .env.example to your own .env file in the project root:
`
MONGODB_URI– production/development MongoDB connection stringTEST_MONGODB_URI– database used whenNODE_ENV=testPORT– port for the Express server (exposed to Fly; defaults to3003)SECRET– secret key used to sign JWTs incontrollers/login.js
npm run dev - This starts the Express server (by default on port 3003, controlled by PORT in .env).
- Connects to MongoDB using
MONGODB_URI/TEST_MONGODB_URI(utils/config.js) - Exposes REST endpoints under
/api/* - Serves the production frontend build from
dist/when present
From the client directory:
npm run dev Vite will start a dev server (usually on port 5173).
In development:
- The frontend uses relative URLs (
/api/blogs,/api/login) so you typically run both:- Backend on
http://localhost:3003 - Frontend on
http://localhost:5173
- Backend on
npm start: Run the server in production modenpm run dev: Run the server in development mode with file watchingnpm test: Run all backend tests with Node’s test runnernpm run start:test: Start the server in test modenpm run lint: Run ESLint on the backend codebase.npm run install:client: Install frontend dependencies from the rootnpm run build:client: Build the frontend from the rootnpm run test:client: Run frontend tests from the rootnpm run clean:client: Removeclient/node_modules.npm run build: Install deps, build the frontend intodist/, and clean upclient/node_modulesfor a lean production image.
npm run dev: Start the Vite development server.npm run build: Create a production build of the frontend intodist/(copied to the project root by your Docker/CI setup).npm run preview: Preview the production build locally.npm test: Run frontend tests with Vitest.npm run lint: Run ESLint on the frontend codebase.
npm test
This runs the backend test suite (including tests in tests/), using the TEST_MONGODB_URI database.
npm run test:client This runs the React component tests using Vitest and Testing Library.
This project is open source and available under the MIT License.
Created as part of the Full Stack Open curriculum (University of Helsinki).