This is a submission for the GitHub Finish-Up-A-Thon Challenge
What I Built
I revived personal_blog, a server-rendered personal blogging platform built with Dart Shelf, PostgreSQL, Mustache templates, and Tailwind CSS.
Repository: https://github.com/AlainDevs/personal_blog
The project started as a bare-bones Dart web app and gradually became a small publishing system with:
- Public blog pages and individual post pages
- User registration and login
- Admin-only pages for posts, categories, users, and settings
- PostgreSQL persistence
- Seeded demo content and demo users
- Tailwind-powered styling
- Docker Compose setup for one-command local deployment
- Automated tests for authentication, settings, comments, middleware, and blog routing
- A separate Docker-based performance testing stack using
wrkand Lua
What makes this project meaningful to me is that it is intentionally simple. It is not trying to be another huge CMS. It is a calm, personal publishing space: fast to run, easy to understand, and small enough for one developer to confidently maintain.
Before the comeback, it still felt like a rough prototype. It had pieces of a blog, but it was not easy enough to run, test, benchmark, or explain to another person. The Finish-Up-A-Thon gave me a reason to turn it into something I could actually hand to someone and say: clone it, run one command, log in, and start exploring.
Demo
Project repository: https://github.com/AlainDevs/personal_blog
Run the demo locally with Docker Compose:
git clone https://github.com/AlainDevs/personal_blog.git
cd personal_blog
docker compose up --build
Then open:
http://localhost:8080
Admin area:
http://localhost:8080/admin
Performance report included in the repository:
The latest recorded smoke benchmark reported:
- 1,877 total requests in 2.01 seconds
- 935.31 requests per second
- 4.27ms average latency
- 7.45ms 99th percentile latency
- No reported socket errors
- No reported non-2xx/3xx responses
Validation checks recorded in the project:
-
docker compose -f docker-compose.performance.yml config --quietpassed -
dart analyzepassed -
dart test --timeout=30spassed
The Comeback Story
The project had eight commits in total. The first four commits created the original prototype: project structure, Tailwind setup, CRUD-oriented services, Docker scripts, and an early server implementation.
The Finish-Up-A-Thon comeback happened in the top four commits. These were the commits where I used GitHub Copilot, together with my AI coding context and rules including ByteRover, DCM Flutter Guidelines, and AI rules for Flutter/Dart-style development, to push the project from “works on my machine prototype” toward “finished, runnable, documented project.”
Commit 1: 8345dbd — Docker infrastructure and service layer enhancements
Commit message: Add Docker infrastructure and service layer enhancements
This was the biggest comeback commit. It changed 44 files with 4,183 insertions and 1,577 deletions.
Before this commit, the project had useful pieces, but the architecture was still too tangled. Server setup, routing, database access, auth behavior, and page rendering were not cleanly separated enough for confident testing or future changes.
What changed:
- Added a cleaner
createAppHandler()function so the Shelf app can be built both by the executable and by tests. - Improved the middleware flow so JWT auth context is attached to requests.
- Protected admin pages and admin APIs more consistently.
- Added
DatabaseConnectionas a shared PostgreSQL bootstrap layer. - Added schema creation and seed data for users, categories, posts, comments, post categories, and application settings.
- Added an
AppSettingmodel. - Added
SettingsServiceandSettingsHandler. - Added admin settings UI for toggling public registration.
- Improved service-layer boundaries for users, posts, categories, comments, and settings.
- Used safer named SQL patterns through
Sql.namedstyle interactions. - Updated Docker Compose to use PostgreSQL 18 and a persistent database volume.
- Added tests for auth, registration settings, comments, and admin middleware.
This commit was where the project stopped being a pile of working code and started feeling like an application with structure.
Copilot helped here by accelerating the repetitive but important parts: service methods, handler wiring, model mapping, test doubles, and route refactors. The AI rules helped keep the generated code closer to consistent Dart conventions instead of random snippets.
Commit 2: d8832a9 — Safer route parameter handling
Commit message: refactor: Replace direct access to request parameters with a utility function for safer path string retrieval
This was a smaller but important hardening commit.
Before this commit, route handlers accessed path parameters directly, for example by reading request.params['slug'] inline. That works, but it spreads low-level request handling across the codebase.
What changed:
- Added
readPathString(Request request, String key)inrequest_utils.dart. - Updated integer path parsing so
readPathInt()builds on top ofreadPathString(). - Updated the blog detail route to read the slug through the utility function.
- Added a test proving that
/blog/a-tiny-publishing-checklistrenders the correct blog detail page. - Added fake post/comment services so the page route can be tested without a real database.
This commit represents the “finish-up” mindset: not just adding features, but reducing fragile patterns and locking behavior with tests.
Copilot helped by suggesting the test structure and the fake service overrides. That let me quickly validate the route behavior rather than only eyeballing the refactor by using MCP.
Commit 3: f52a043 — Performance testing infrastructure
Commit message: feat: Add performance testing infrastructure with Docker and Lua scripts
This commit added 1,015 lines across seven files.
Before this commit, I could run the app, but I did not have a repeatable way to answer a basic question: “How does it behave under load?”
What changed:
- Added
docker-compose.performance.yml, a separate performance testing stack. - Added an Alpine-based performance Dockerfile that builds
wrk. - Added
request_mix.luafor weighted traffic across realistic routes:- homepage
- seeded blog detail pages
- generated CSS
- public JavaScript
- Added
generate_report.js, which runs Docker Compose, captures benchmark output, parses results, and writes a GitHub-ready Markdown report. - Added
PERFORMANCE_RESULTS.mdwith the latest benchmark output. - Added npm scripts:
npm run performance:reportnpm run performance:report:smoke
- Documented how to tune benchmark load with environment variables.
This was a big step toward making the project feel complete. A personal blog should not only have features; it should be easy to verify that pages respond quickly and that changes do not obviously break performance.
Copilot was especially useful here because the work crossed several small domains: Docker Compose, shell readiness checks, Lua route selection for wrk, Node.js process management, Markdown report generation, and benchmark parsing.
Commit 4: fdb4e92 — README polish and beginner-friendly setup
Commit message: docs: Update README to enhance Docker Compose instructions and clarify setup process
This final comeback commit focused on usability.
Before this commit, the README still described the project like a basic Dart web app and told users to install WebDev manually. That no longer matched the revived project by creating our own agent - doc-reviewer.
What changed:
- Rewrote the README around Docker Compose as the primary way to run the project.
- Explained that users do not need to install Dart, Node.js, PostgreSQL, or WebDev locally.
- Added step-by-step startup instructions.
- Added the local URL:
http://localhost:8080. - Added seeded admin and reader accounts.
- Added the admin URL:
http://localhost:8080/admin. - Added stop, restart, and database reset instructions.
- Kept the performance testing section so users can generate benchmark reports.
This was the last mile of finishing the project. The app may be technically complete, but if another developer cannot run it easily, it still feels unfinished. This README update made the project approachable.
Copilot helped turn rough notes into a clearer onboarding path and made the documentation more user-focused.
My Experience with GitHub Copilot
GitHub Copilot helped me finish the project in the way I actually needed: not by replacing my decisions, but by keeping momentum while I worked through lots of small, connected tasks.
I used Copilot with my AI development context, including ByteRover, DCM Flutter Guidelines, and AI rules for Flutter/Dart-style development. Even though this is a Dart Shelf web server rather than a Flutter UI app, those rules still helped encourage cleaner structure, explicit tests, safer utilities, and more maintainable code.
The most useful parts of Copilot were:
- Turning architectural intent into concrete Dart service and handler code.
- Helping refactor the Shelf server into a testable
createAppHandler()structure. - Suggesting test cases and fake services for auth, settings, comments, and blog routes.
- Speeding up repetitive model and mapping work.
- Helping write Docker Compose and benchmark infrastructure without constantly switching mental context.
- Helping polish the README so the final project is easier for another person to run.
The before-and-after arc is clear to me:
Before, personal_blog was a promising but unfinished side project. It had the shape of a blog, but it still required too much local setup knowledge, had less confidence around tests, and did not have a clear performance story.
After, it is a Dockerized Dart personal blog with seeded content, admin flows, persistent PostgreSQL storage, application settings, automated tests, performance benchmarking, and beginner-friendly documentation.
That is exactly what I wanted from this challenge: not to start something new, but to finally finish something I already cared about.










Top comments (0)