Skip to content

About

Final version of the news app for learning concepts.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

19 Commits

Folders and files

Repository files navigation

DEV@Deakin — NewsAppFinal

A news and Q&A site for developers: read and post articles, ask and answer questions, subscribe to a newsletter, and unlock a premium analytics dashboard.

It runs for anyone, with no accounts and no API keys. Clone it, run one command, and the app comes up on http://localhost:3000 with seeded content — no cloud project, no configuration.

The home page: featured articles with images and featured questions

Quick start

Requires Node 22 or newer (the server uses the built-in node:sqlite module) and make.

make demo

That builds the client, seeds a fresh database, and serves the whole app on http://localhost:3000. Sign in with any seeded account — password password123:

Email Role
ada@example.com administrator + premium
ravi@example.com premium
mei@example.com regular

There is no .env to create and nothing to sign up for. All accounts and content are fictional.

What this is

NewsAppFinal began as a Deakin coursework app built on Firebase Auth, Firestore, Netlify Functions and Stripe. It worked — but only for its author: Firebase needs a live Google project whose keys are (correctly) never committed, so a reviewer who cloned it got a blank screen.

This version replaces that cloud dependency with a local backend, so the app is judged on what it does rather than on whether you hold the author's keys. The original is preserved at the v0-firebase tag.

Architecture

flowchart LR
    subgraph Browser
        UI["React 19 + Vite<br/>Tailwind"]
        api["src/api.js<br/>src/auth.js"]
        UI --> api
    end

    subgraph "Node process"
        EX["Express"]
        MW["JWT middleware<br/>requireAuth / requireAdmin"]
        RT["routes:<br/>auth · posts · users<br/>checkout · stats · subscribe"]
        DB[("node:sqlite<br/>news.db")]
        EX --> MW --> RT --> DB
    end

    api -->|"/api/* (relative)"| EX
    EX -->|"serves built client in demo"| UI

    RT -. "only if a key is set" .-> STRIPE["Stripe"]
    RT -. "only if a key is set" .-> MAIL["Mailchimp / SendGrid"]
Loading

The client only ever calls relative paths. In development Vite proxies them to the server; in the demo one Node process serves both the built client and the API, so the same paths work with no configuration. The external services are dashed because they are reached only when their key is present — otherwise the request runs a labelled demo path (see below).

client/                React 19 + Vite + Tailwind
  src/api.js           all data access — one place that talks to the server
  src/auth.js          session state (token + useCurrentUser hook)
  src/components/       NavBar, cards, forms, route guards, error boundary
  src/pages/            home, article, questions, plans, dashboard, admin, …

server/                Express + node:sqlite
  server.js            wiring; also serves the built client in the demo
  db.js                schema created on boot; ./data/news.db
  seed.js              demo users, articles and questions (with images)
  passwords.js         scrypt hashing (node:crypto)
  middleware/auth.js   token issuing, requireAuth, requireAdmin
  routes/              auth, posts, users, checkout, stats, subscribe
  tests/               API tests that drive the real server over HTTP
  • Data & auth are an Express API over SQLite — the built-in node:sqlite module, so there is nothing to install and nothing to compile.
  • Passwords are hashed with scrypt from Node's own crypto. Sessions are a signed JWT. With no JWT_SECRET set, the server generates a random one per process — so no signing secret sits in the repository, and sessions simply do not survive a restart (fine for a demo; log in again).
  • Authorization is enforced on the server. The user list needs a valid token and an admin flag held in the database; the premium dashboard needs the premium flag. Nothing security-relevant is decided in the browser.

An article renders its banner image and Markdown body:

An article with its banner image and Markdown body

Signed-in users post articles and questions; the author and timestamp are set by the server from the token, never trusted from the browser:

The New Post form — question or article, with tags

Premium users get an analytics dashboard drawn from real database counts (not the placeholder figures the coursework version showed):

The premium analytics dashboard with real post counts

Running without keys

The paid integrations degrade to a clearly-labelled demo path when their key is absent — nothing throws, and the UI shows exactly what a keyed server would have sent, so you can see the integration is wired rather than stubbed.

Integration With no key (default) With a key set
Stripe Panel shows the real POST /v1/checkout/sessions; premium unlocks locally Real Stripe Checkout
Mailchimp Subscriber recorded in SQLite; panel shows the real /members call Real list subscribe
SendGrid Panel shows the real /v3/mail/send call; nothing sent Real welcome email

Email addresses are masked (d***@example.com) before they reach a log or a panel — personal data never appears in full.

The newsletter in demo mode, showing the real Mailchimp and SendGrid calls it would make, with the email masked

Tests

make test

79 tests. The 51 API tests start the real server as a process and drive it over HTTP — no production file was reshaped to be reachable. The 28 client tests run under Vitest. Each suite was validated by reintroducing every fixed defect in a throwaway copy and confirming the matching test turns red; a suite that has only ever passed proves nothing.

Security

make check

scripts/check-secrets.sh fails the build if anything resembling a real credential (Stripe, SendGrid, Mailchimp, a JWT secret, a Firebase key, private keys) or real personal data (any email outside the reserved demo domains) is in the tree. It is proven by planting a fake for each rule in a throwaway repo and confirming each is caught — never by mutating this one. It runs in CI on every push, alongside the test suite.

No secret has ever been committed; the working tree and full history were scanned before this was made public.

Administrators get a user-management page, gated on a server-checked admin flag:

The admin user-management page with role badges

No live deployment — on purpose

There is none, and that is deliberate. A long-running Express process cannot run on Netlify, and SQLite does not persist on serverless functions, so keeping a live deployment would require hosted Postgres and a keyed platform account — exactly the "you need the author's keys" problem this rewrite removes. The one-command local demo is the deliverable.

AI assistance

Parts of this rewrite were developed with the assistance of Claude (Anthropic). All design decisions, review and testing were my own.

License

MIT

Author

Daniel Allen — Bachelor of Information Technology (Application Development), Deakin University.

About

Final version of the news app for learning concepts.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages