Real-World Example: Building JSLipi Blog App with GitHub Copilot This is the post I wanted to write from the beginning of this series — a real project, built with Copilot, showing exactly what it helped with, and being honest about what it could not do. JSLipi is a full-stack blog platform that I built as a learning project and content home for this series. It has user authentication, blog and post management, categories, comments, and a full React frontend. Everything in this series is drawn directly from building it. What JSLipi Is The app is a full-stack TypeScript application: Layer Technology ------- ----------- Frontend React + TypeScript, TailwindCSS Backend Node.js, Express, TypeScript Database MongoDB with Mongoose Auth JWT (access + refresh tokens) Images Cloudinary Hosting Vercel (API) + static build It is not a tutorial app with three routes. It has real authentication, image uploads, nested content (blogs → posts), a comment system, admin routes, and a mobile-responsive frontend. This is the kind of app where Copilot's help is meaningful — not because it replaces thinking, but because it drastically reduces the time spent on structural and boilerplate code. Phase 1: Project Structure and Setup At the start, the question is not "how do I write this code" — it is "how should I organise this project so it scales cleanly." I opened Copilot Chat and described what I was building: Copilot produced a clean, layered structure — very close to what the project looks like today: This took five minutes instead of thirty minutes of reading tutorials, looking at GitHub repos, and second-guessing myself. Phase 2: Authentication Authentication is the part of every app that developers either copy from a tutorial (and then do not fully understand) or spend hours getting right. The requirement: JWT-based auth with separate access and refresh tokens. Access tokens expire in 15 minutes. Refresh tokens are stored in an HTTP-only cookie and expire in 7 days. I described the token strategy to Copilot: Copilot produced . I reviewed it, adjusted the error handling to match my project's error format, and it was in production that day. The refresh token middleware — the part that checks for the cookie, verifies the refresh token, issues a new access token — I prompted similarly and got a working draft in minutes. What I still had to think through: the edge cases. What happens when both tokens are expired? When should the refresh endpoint set a new cookie vs return 401? These are design decisions that Copilot cannot make for you. Phase 3: Blog and Post CRUD A blog has many posts. Each post has ordered content, a markdown body, a title, and metadata. The CRUD operations needed to be consistent across both resources. The approach: I built the blog model and its service first, tested it, then used it as a template for the post model. When I needed the post service, I opened the blog service in one tab and asked: Copilot had context from the open file. Its output matched the style of the existing code, which meant less editing to make it fit the project. The result: The post service worked on first try for basic CRUD. The reordering logic needed one manual fix because Copilot sorted in the wrong direction. One review pass, one fix. Phase 4: Frontend Features The frontend is a React + TypeScript app. This is where Copilot's inline suggestions shine — it is particularly good at: Component boilerplate: Give it a description in a comment and it writes the component skeleton: Copilot writes the JSX structure. I adjust the styles and types. Custom hooks: I described what data the blog listing page needed (paginated blogs with category filter) and asked Copilot to write a hook using React Query. The output was close to correct and needed only minor adjustments. TypeScript types: The frontend and backend share a type contract. When I had the API response shape in mind, I described it and asked Copilot to write the TypeScript interface. This is tedious work and Copilot is fast at it. What Copilot Could Not Do In the interest of an honest post: Architecture decisions: When I was deciding whether to store refresh tokens in the database (revocable) or rely purely on token expiry (stateless), Copilot gave me an answer but it was generic. I had to research the tradeoffs myself. Complex query logic: The MongoDB aggregation for nested blog/post queries with category filtering and pagination needed careful manual work. Copilot helped with syntax but I had to think through the logic. Debugging production issues: When the Cloudinary image upload was failing only on Vercel and not locally, no AI tool could debug that in one go. It took log reading, environment variable checking, and careful reasoning. The Honest Verdict Note on timing: The experience below is from building JSLipi between November 2025 and January 2026. Copilot and other AI coding tools are evolving quickly — the percentages here may understate what is possible today. Treat them a…