Skip to content

Linklater is a tiny Instapaper-style “read it later” app built as a take-home assignment for a job interview.

License

Notifications You must be signed in to change notification settings

nschneble/linklater

Repository files navigation

Linklater

Linklater is a tiny Instapaper-style “read it later” app built as a take-home assignment for a job interview.

It’s both an homage to Richard Linklater and a ridiculously apt portmanteau.

What Problem Does This Solve?

Most curious adults come across dozens of interesting articles on any given day. Do they have time to read them all? Nope. Do they often forget about them? Totally.

Linklater allows these articles to quickly and easily be saved for later reading.

As an added bonus, you don’t have to use (or pay!) for a service that’s gone decidedly downhill since Marco Arment left.

Features

  • Sign up for an account with an email and password
  • Save links to read later
  • Search through your links to find something to read
  • Archive links you’ve managed to read
  • Delete links you can no longer stand the sight of
  • StumbleUpon a random saved link
  • Toggle between light and dark mode
  • Use a bookmarklet to save links
  • Delete your account and burn it to the ground

Screenshots

Click on a thumbnail to see the full-size screenshot:

Your Links Archived Links Account Settings Log In Light Mode

Tech Stack

Monorepo Structure

It’s a majestic modular monorepo!

.
├── apps
│   ├── api       # NestJS back-end
│   └── web       # React + Vite front-end
├── package.json  # root workspace + scripts
└── README.md

Bookmarklet

Linklater supports a simple “send this page to Linklater” bookmarklet by pre-filling the url + title via query params.

Example bookmarklet:

javascript:(function(){
  const base = 'https://linklater.example.com';
  const url = encodeURIComponent(location.href);
  const title = encodeURIComponent(document.title);
  window.open(`${base}/?url=${url}&title=${title}`, '_blank','noopener,noreferrer');
})();

For local development:

javascript:(function(){
  const base = 'http://localhost:5173';
  const url = encodeURIComponent(location.href);
  const title = encodeURIComponent(document.title);
  window.open(`${base}/?url=${url}&title=${title}`, '_blank','noopener,noreferrer');
})();

Running The Project Locally

Prerequisites

  • Node.js (22.x recommended)
  • PostgreSQL running locally with a “linklater” database

Install Dependencies

# from the repo root
npm install

Configure Environment Variables

Create apps/api/.env:

DATABASE_URL="postgresql://YOUR_PG_USER:YOUR_PG_PASSWORD@localhost:5432/linklater?schema=public"
JWT_SECRET="dev-secret-change-me"

Create apps/web/.env:

VITE_API_BASE_URL="http://localhost:3000"

Run Database Migrations

cd apps/api
npx prisma migrate dev --name init

Start It Up

# from the repo root
npm run dev

This uses concurrently to run:

Open http://localhost:5173 in your web browser.

Linting, Tests, and CI

Both the front and back-end use ESLint and Prettier:

# lint everything
npm run lint

# lint front-end only
npm run lint --workspace @linklater/web

# lint back-end only
npm run lint --workspace @linklater/api

Vitest is used to test the front-end:

cd apps/web
npm run test

Jest is used to test the back-end:

cd apps/api
npm run test

GitHub Actions lint and test on pushes and PRs to main.

Design Notes & Tradeoffs

  • Created a monorepo to keep local dev simple and straightforward
  • Used email/pass authentication for speed and simplicity
    • No email verification or 2FA
  • Vite makes it real easy to spin up a UI and wire up Tailwind for styles
  • Kept the UX focused on clarity
    • One main “Links” view with all actions
    • Separate “Settings” view for user account changes
    • Light/dark theme persistence via localStorage
    • Basic responsive layout
  • Back-end tests mock Prisma to avoid DB dependencies
  • Front-end tests cover core UI behaviors

Future Ideas To Grow This Into Something Extra

  • Add OAuth2 support to login with Google, GitHub, etc.
  • Fetch and store link metadata via a background job
  • Link tags and collections
  • Improve the full-text search
  • Create browser extensions for one-click saving
  • Higher contrast light and dark mode color palettes
    • Use Tailwind's dark variant w/ overrides
  • THEMES

AI Assistance

ChatGPT was instrumental in rapidly prototyping this project.

An initial prompt of 600 words (!?) was used to create a plan of attack for the features and design considerations.

Additionally, ChatGPT was used to analyze several authentication frameworks and provide rationale for their use in the project.

A 300 word (!) prompt was written to address a handful of fast-follows to improve and refine the user experience.

About

Linklater is a tiny Instapaper-style “read it later” app built as a take-home assignment for a job interview.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published