Full Width [alt+shift+f] Shortcuts [alt+shift+k]
Sign Up [alt+shift+s] Log In [alt+shift+l]
17
The 987.2 Porsche Boxster is one of the best values in the used sports car market today. There is so much to love about the vehicle, but the OEM headunit is not one of them. It's very dated, clunky, and doesn't support CarPlay (!), so one of the first things I did after picking up my car was purchase and install a new headunit. I selected the Sony XAV-AX1000 headunit because: It's one of the only aftermarket headunits with a physical volume knob The matte black plastic finish very closely matches my Porsche's interior I didn't need wireless CarPlay It's relatively cheap I also picked up this dash kit from Crutchfield as well to have the install look as factory as possible. I will say that the fit is very tight (it's a friction fit) so triple check wiring before sliding this into the dash. If you do happen to get the kit stuck with the headunit in it, I've had luck freeing it with the help of a metal putty knife. My 987.2 has the Sound Package Plus (SPP), which is the middle tier...
over a year ago

Improve your reading experience

Logged in users get linked directly to articles resulting in a better reading experience. Please login for free, it takes less than 1 minute.

More from noahbuscher.com

Zed Public Beta

I have been a dedicated Nova user for over three years. I switched over from VSCode after tiring of the slow performance and "uncanny valley" interface. I'm a sucker for a well-done native app, and Panic really hit the sweet spot with Nova: a beautiful, minimal editor that felt right at home on macOS. It was also extremely fast to boot, indexing files and rendering 50,000 LOC+ without even breaking a sweat on the M1 Pro. Unfortunately, I've been looking for an alternative as of late due to the high frequency of Nova crashes and lack of updates from Panic. Still, the editor scene hasn't changed much from what it looked like half a decade ago, with a smattering of Electron apps, Coda/Nova, some stalwarts such as Sublime Text and TextMate, and, of course, the venerated Vim/Emacs/Neovim trio. I'm not one to spend a lot of time messing around with my tooling; I just want whatever editor I use to have a shallow learning curve and be performant. Somehow, looking for a new editor last week, I came across Zed's tweet: Zed is officially in public beta for macOS! We've been building Zed in Zed for a year now, and here's what we're loving most about it... 🧵 Since then, I've been playing around with and customizing the editor to see what living with a Rust-powered, minimal editor could look like. Install & Setup Zed was very simple to set up; after downloading the '.dmg,' I had an instance ready to code in a matter of seconds. That's instant points over terminal-based editors. I will note here that Zed is currently only available on macOS. Support for Linux and Windows, according to the team, is: [...] planned, but it is not being prioritized in the short term. Customizing the editor was also very straightforward. They have a default editor configuration that you can use, but I found it easier to open a custom settings file and see what was available via their beautiful autocomplete. There are a few things that I was surprised I wasn't able to customize yet, such as: Setting the interface's font Setting the interface's font size, independently of the editor Enabling (or disabling) icons or colors for the file tree view Allow hiding hidden files Performance This is where Zed really shines. Loading a package-lock.json with over 7500 lines is instantaneous—quite literally. Even Nova would take at least a few hundred ms to parse and color a blob of that size, however, Zed doesn't even flinch. There is also zero scroll lagging, autocomplete delays, etc. that I could notice in any of my testing. I'm not sure of the actual numbers, but in my initial testing, Zed felt like the fastest editor I've ever used. That is to be expected, of course: the editor was written in Rust and, as stated in their docs, performance was a top concern while developing the app over the course of this past year. Put another way, VSCode is a 2000's Land Rover Discovery with tons of buttons and features, whereas Zed is a sleek McLaren F1 - minimal, extremely fast, and with three front seats. Why three front seats? Multiplayer Zed's big bet is on multiplayer. The editor comes with first-class support for real-time pairing, bundled right into the editor. By no means do you need to use the feature in order to derive a lot out of Zed, however, as more people hop on the Zed bullet train, I can see it becoming an integral part of many people's (and companies') workflows. As stated by the team: [Multiplayer] makes it easy to have nuanced, real-time conversations about any part of your codebase, whether the code in question was committed last year or hasn't yet been saved to disk. VSCode does have Live Share, but it feels tacked on to the interface, whereas in Zed, pairing feels just like any other feature within the editor: seamless. It almost invites you to collaborate with your team. Ecosystem As Zed is still in public beta, there is surely a lot coming down the pipeline. For the time being, however, there were a few features I definitely missed from Nova: No extension market (1st or 3rd party) No way to add/edit themes (it comes pre-bundled with a number, however) No dark/light mode based on system Limited git integration No markdown preview Limited language support No spellcheck I could not find anything regarding Zed Industries' plan for supporting extensions (if there even is one), however, I hope they do allow for writing extensions with a scripting language such as JavaScript. Forcing developers to build in Rust may be good for performance, but in a world where everyone is building VSCode extensions, it will cripple the marketplace's offerings from the start. Besides the aforementioned list, Zed really has most of the niceties I'm used to built right in. I have come across a few small bugs, which is to be expected at this stage of development, but none of which have detracted me from getting my work done. Recap Zed is a fantastic editor - it's eye-wateringly fast, extremely minimal (and beautiful), has a talented team behind it, and is a natural transition for anyone who has familiarity with both terminal and GUI-based editors. However, in a world that is dominated by the free, open-source VSCode, I am curious to see how Zed's extension ecosystem grows and what Zed Industries' plan is for monetizing their product. For the time being, I have found the editor a pleasure to work with, and I will be using Zed as my daily driver moving forward. If you're tired of VSCode's large size, cluttered interface, and slow performance, I urge you to download Zed's beta and give it a try. I think you'll be pleasantly surprised.

over a year ago 18 votes
Create a Markdown Portfolio with Next.js

So you've set out to create a new portfolio for yourself. You start gathering inspiration from platforms like Godly and Minimal Gallery, draw some rectangles in Figma, and open your text editor. You pause. There's thousands of ways to build your website, how do you decide which to go with? You want your website to be beautiful for the users, but you also want to be able to quickly add new posts and case studies. You decide you want to have a dynamic website (good choice!), but the dozens of CMS options weigh on you. Do you pick headless or full-stack? What if you just make a theme? So many choices. I was faced with the same dilemma a few months ago. I finally had the motivation to create a new personal website, but wasn't sure where to start. I decided to keep things simple, I'd write it with a library I knew very well: React. That only solved half of the equation, however. When it came time to decide how to power the dynamic content on the site, I knew I wanted it to be free, easy to use, and open source. A static site powered by Next.js and markdown was the obvious choice. View the source on GitHub. To get started on creating your portfolio, run the following commands. I'm using pnpm, but feel free to use yarn or npm! pnpm dlx create-next-app@latest --typescript cd into your new project and run the following commands to install the necessary packages and bootstrap Tailwind: pnpm install dayjs pnpm install gray-matter react-markdown tailwindcss postcss autoprefixer -D pnpm dlx tailwindcss init -p That's a lot of packages. Let's break them down... gray-matter will be used to parse "front-matter" from our markdown files (we'll read more about this later!) react-markdown is a React component to render markdown content tailwindcss postcss autoprefixer are requirements for installing Tailwind for Next.js Phew! Let's continue our setup by finishing the Tailwind install... Add the following to the module.exports in the generated tailwind.config.js file: content: [ "./pages/**/*.{js,ts,jsx,tsx}", "./components/**/*.{js,ts,jsx,tsx}", "./layouts/**/*.{js,ts,jsx,tsx}", "./utils/**/*.{js,ts,jsx,tsx}" ], To bring the styles into your project, add the following to the styles/globals.css file: @tailwind base; @tailwind components; @tailwind utilities; Great! Finally, let's create our new directories by running the following in the root: mkdir _projects mkdir public/projects mkdir layouts mkdir components mkdir utils We're finally ready to start coding! To get started, create a new layout file, ProjectCard.tsx in the components directory. This component will be displayed for each project on the home page's grid. In components/ProjectCard.tsx add: import React from "react"; import Image from "next/image"; import Link from "next/link"; const ProjectCard = ({ title, description, slug, photo, }: { title: string; description: string; slug: string; photo: string; }) => ( <Link href={`/project/${slug}`}> <div className="flex-1 flex flex-col gap-2"> <Image src={photo} alt={title} width="0" height="0" sizes="100vw" className="w-full h-full aspect-square object-cover" priority /> <h3 className="text-black font-bold text-xs">{title}</h3> <p className="text-gray-500 text-xs">{description}</p> </div> </Link> ); export default ProjectCard; Now we need a place to display all of our project cards. Create a new layout called Grid.tsx in the layouts directory. In layouts/Grid.tsx, add the following: import React from "react"; import ProjectCard from "../components/ProjectCard"; import type { Project } from "../layouts/Project"; const Grid = ({ projects }: { projects: Project[] }) => ( <div className="flex flex-col gap-12 max-w-screen-md mx-auto"> <h2 className="text-black font-bold text-lg">Projects</h2> <div className="grid grid-cols-2 md:grid-cols-4 gap-8"> {projects.map(({ meta }) => ( <ProjectCard key={meta.slug} title={meta.title} description={meta.description} slug={meta.slug} photo={meta.photo} /> ))} </div> </div> ); export default Grid; Let's add a demo project now! In the _projects at your root, create a new file. The name doesn't matter, but I find it helpful to make it the same as the URL slug. In that file, add soemthing similar to the following: --- title: Example Project slug: example-project date: February 1, 2023 description: Just an example project! photo: /projects/example-project.jpg --- Something about Example Project... The area between the ---'s is called "front-matter", and it's what we brought gray-matter in to parse for us. Everything under the second seperator is the content of the case study. It can be any valid markdown. Save the file and let's move on to tying things together! In your pages/index.tsx file that Next.js generated, replace the content with the following. Feel free to ignore the missing Project type for now. We'll add that soon! import React from "react"; import path from "path"; import { promises as fs } from "fs"; import matter from "gray-matter"; import dayjs from "dayjs"; import Grid from "../layouts/Grid"; import type { Project } from "../layouts/Project"; const PROJECTS_DIR = "_projects"; export async function getStaticProps() { const projectsDir = path.join(process.cwd(), PROJECTS_DIR); const files = await fs.readdir(projectsDir); const postPaths = files.filter((file) => { const ext = path.extname(file); return ext === ".md"; }); const projects = await Promise.all( postPaths.map(async (file: string) => { const contents = await fs.readFile(path.join(projectsDir, file), "utf8"); const parsed = matter(contents); const project = { content: parsed.content, meta: parsed.data, }; return project; }) ); const sortedProjects = projects.sort((a, b) => dayjs(a.meta.date).isAfter(dayjs(b.meta.date)) ? -1 : 1 ); return { props: { projects: sortedProjects, }, }; } export default function Home({ projects }: { projects: Project[] }) { return ( <main className="mx-10 sm:mx-0 my-10"> <Grid projects={projects} /> </main> ); } This may look a little confusing if you've never seen getStaticProps before, but you can read more about it in the Next.js docs. All it's doing here is getting an array of Projects that we then use dayjs to sort from a human-readable date in the metadata and pass that array as a prop to our Grid. Now just run pnpm dev and you should see your project on the home page! Feel free to add more projects and see how it sorts by date and adds them to the grid. Now, if you try and click on a project, you'll notice it takes you to a 404 page. Let's go ahead and add a single project layout by creating a file called Project.tsx in layouts. In Project.tsx, add the following: import React from "react"; import Image from "next/image"; export type ProjectMeta = { title: string; description: string; slug: string; date: string; photo: string; }; export type Project = { meta: ProjectMeta; content: string; }; const Project = ({ project, renderedProjectContent, }: { project: Project; renderedProjectContent: string; }) => ( <div className="flex flex-col gap-8 max-w-screen-md mx-auto"> <h2 className="text-black font-bold text-lg">{project.meta.title}</h2> <h3 className="text-gray-500 text-base">{project.meta.description}</h3> <Image src={project.meta.photo} alt={project.meta.title} width="0" height="0" sizes="100vw" className="w-full h-full" priority /> <div className="flex flex-col gap-8" dangerouslySetInnerHTML={{ __html: renderedProjectContent }} /> </div> ); export default Project; ⚠️ Note the dangerouslySetInnerHTML. It's ok to use here as the only user's content that will be rendered there is your's. This is not a great practice, however, and you should not do this on a platform that other's are able to post content to. In the next step, we are going to be writing a utility to generate that HTML. To do so, create a new file called markdown.tsx in the utils directory and add the following: import React from "react"; import Link from "next/link"; import * as ReactDOMServer from "react-dom/server"; import ReactMarkdown from "react-markdown"; const Img = ({ ...props }: any) => ( <img className="rounded-[8px] max-w-screen-lg mx-auto w-full" {...props} /> ); const Text = ({ children, node }: { children: React.ReactNode; node: any }) => { if (node.children[0].tagName === "img") { const image: any = node.children[0]; return <Img src={image.properties.src} />; } return ( <p className="flex-1 flex-grow w-full text-xs leading-6 max-w-screen-md mx-auto"> {children} </p> ); }; const Anchor = ({ children, href }: any) => ( <Link href={href} className="inline underline"> {children} </Link> ); export const renderMarkdownToHTML = (markup: string) => { return ReactDOMServer.renderToStaticMarkup( <ReactMarkdown components={{ p: Text, img: Img, a: Anchor, }} > {markup.trim()!} </ReactMarkdown> ); }; This component uses react-markdown to enable us to define JSX component mappings for markdown elements! Feel free to get creative here and expand upon what's already in there. So far so good! We're getting close. Now we just need to create a new file called [slug].tsx in pages/project that will pull that new component in. In [slug.tsx], add the following: import React from "react"; import { promises as fs } from "fs"; import path from "path"; import matter from "gray-matter"; import ProjectLayout from "../../layouts/Project"; import { renderMarkdownToHTML } from "../../utils/markdown"; import type { Project } from "../../layouts/Project"; const PROJECTS_DIR = "_projects"; export async function getStaticProps({ params }: { params: { slug: string } }) { const projectsDir = path.join(process.cwd(), PROJECTS_DIR); const files = await fs.readdir(projectsDir); const projectPaths = files.filter((file) => { const ext = path.extname(file); return ext === ".md"; }); const projects = await Promise.all( projectPaths.map(async (file: string) => { const contents = await fs.readFile(path.join(projectsDir, file), "utf8"); const parsed = matter(contents); return { content: parsed.content, meta: parsed.data, }; }) ); const project = projects.find((p) => p?.meta?.slug === params.slug); const renderedProjectContent = renderMarkdownToHTML(project?.content!); return { props: { project, renderedProjectContent, }, }; } export async function getStaticPaths() { const projectsDir = path.join(process.cwd(), PROJECTS_DIR); const files = await fs.readdir(projectsDir); const projectPaths = files.filter((file) => { const ext = path.extname(file); return ext === ".md"; }); const projects = await Promise.all( projectPaths.map(async (file: string) => { const contents = await fs.readFile(path.join(projectsDir, file), "utf8"); const parsed = matter(contents); return { content: parsed.content, meta: parsed.data, }; }) ); const paths = projects.map((project) => ({ params: { slug: project?.meta?.slug }, })); return { paths, fallback: false, }; } const Project = ({ project, renderedProjectContent, }: { project: Project; renderedProjectContent: string; }) => ( <main className="mx-10 sm:mx-0 my-10"> <ProjectLayout project={project} renderedProjectContent={renderedProjectContent} /> </main> ); export default Project; Similar to the index.tsx page, we are grabbing the list of projects again, however this time we are filtering to find the single project whose slug matches that in the dynamic page's URL. Then, we are defining a function called getStaticPaths that is another special Next.js feature to dynamically create the static paths for generated content (in this case, our Projects!). You can read more about that in the Next.js docs. Great! If you go back to the home page and click a project, you should now see it takes you to a single project page! That's really all you need to get started! You now have a simple markdown-powered portfolio. You can use this as a jumping-off point to continue building out the (easy-to-update) portfolio of your dreams! Here's some ideas to get you started: Use next-sitemap to generate a sitemap to all of your dynamic routes to make it easier for search engines to index your site As you probably noted, some of the code we wrote isn't very DRY; maybe extract some of the repeated code into more utils Add a navbar and footer Add more pages to tell visitors about yourself or how to get in touch with you Looking foward to see what y'all create! View the source on GitHub.

over a year ago 18 votes

More in technology

This automatic emergency braking system protects RC cars

It is a story as old as time (or at least the 1960s): kid gets an RC car for Christmas and excitedly takes it for spin, but crashes it into a wall within five minutes and tears ensue. The automotive industry has cut down on accidents by implementing automatic emergency braking safety features, so why […] The post This automatic emergency braking system protects RC cars appeared first on Arduino Blog.

21 hours ago 2 votes
Comics from Winter 1980 Issue of Electronics Today International

AI and everything in between.

5 hours ago 2 votes
This unique electronic toy helps children learn their shapes

It isn’t a secret that many kids find math to be boring and it is easy for them to develop an attitude of “when am I ever going to use this?” But math is incredibly useful in the real world, from blue-collar machinists using trigonometry to quantum physicists unveiling the secrets of our universe through […] The post This unique electronic toy helps children learn their shapes appeared first on Arduino Blog.

3 days ago 5 votes
From building ships to shipping builds: how to succeed in making a career switch to software development

I have worked with a few software developers who made the switch to this industry in the middle of their careers. A major change like that can be scary and raise a lot of fears and doubts, but I can attest that this can work out well with the right personality traits and a supporting environment. Here’s what I’ve observed. To keep the writing concise, I’ll be using the phrase “senior junior”1 to describe those that have made such a career switch. Overcoming the fear Fear is a natural reaction to any major change in life, especially when there’s risk of taking a financial hit while you have a family to support and a home loan to pay. The best mitigation that I’ve heard is believing that you can make the change, successfully. It sounds like an oversimplification, sure, as all it does is that it removes a mental blocker and throws out the self-doubt. And yet it works unreasonably well. It also helps if you have at least some savings to help mitigate the financial risk. A years’ worth of expenses saved up can go a long way in providing a solid safety net. What makes them succeed A great software developer is not someone that simply slings some code over the wall and spends all of their day working only on the technical stuff, there are quite a few critical skills that one needs to succeed. This is not an exhaustive list, but I’ve personally observed that the following ones are the most critical: ability to work in a team great communication skills conflict resolution ability to make decisions in the context of product development and business goals maintaining an environment of psychological safety Those with more than a decade of experience in another role or industry will most likely have a lot of these skills covered already, and they can bring that skill set into a software development team while working with the team to build their technical skill set. Software development is not special, at the end of they day, you’re still interacting with humans and everything that comes with that, good or bad. After working with juniors that are fresh out of school and “senior juniors” who have more career experience than I do, I have concluded that the ones that end up being great software developers have one thing in common: the passion and drive to learn everything about the role and the work we do. One highlight that I often like to share in discussions is one software developer who used to work in manufacturing. At some point they got interested in learning how they can use software to make work more efficient. They started with an MVP solution involving a big TV and Google Sheets, then they started learning about web development for a solution in a different area of the business, and ended up building a basic inventory system for the warehouse. After 2-3 years of self-learning outside of work hours and deploying to production in the most literal sense, they ended up joining my team. They got up to speed very quickly and ended up being a very valuable contributor in the team. In another example, I have worked with someone who previously held a position as a technical draftsman and 3D designer in a ship building factory (professionals call it a shipyard), but after some twists and turns ended up at a course for those interested in making a career switch, which led to them eventually working in the same company I do. Now they ship builds with confidence while making sure that the critical system we are working on stays stable. That developer also kicks my ass in foosball about 99% of the time. The domain knowledge advantage The combination of industry experience and software development skills is an incredibly powerful one. When a software developer starts work in a project, they learn the business domain piece by piece, eventually reaching a state where they have a slight idea about how the business operates, but never the full picture. Speaking with their end users will help come a long way, but there are always some details that get lost in that process. Someone coming from the industry will have in-depth knowledge about the business, how it operates, where the money comes from, what are the main pain points and where are the opportunities for automation. They will know what problems need solving, and the basic technical know-how on how to try solving them. Like a product owner, but on steroids. Software developers often fall into the trap of creating a startup to scratch that itch they have for building new things, or trying out technologies that have for a very long time been on their to-do list. The technical problems are fun to solve, sure, but the focus should be on the actual problem that needs fixing. If I wanted to start a new startup with someone, I’d look for someone working in an industry that I’m interested in and who understands the software development basics. Or maybe I’m just looking for an excellent product owner. How to help them succeed If you have a “senior junior” software developer on your team, then there really isn’t anything special you’d need to do compared to any other new joiner. Do your best to foster a culture of psychological safety, have regular 1-1s with them, and make sure to pair them up with more experienced team members as often as possible. A little bit of encouragement in challenging environments or periods of self-doubt can also go a long way. Temporary setbacks are temporary, after all. What about “AI”? Don’t worry about all that “AI”2 hype, if it was as successful in replacing all software development jobs as a lof of people like to shout from the rooftops, then it would have already done so. At best, it’s a slight productivity boost3 at the cost of a huge negative impact on the environment. Closing thoughts If you’re someone that has thought about working as a software developer or who is simply excited about all the ways that software can be used to solve actual business problems and build something from nothing, then I definitely recommend giving it a go, assuming that you have the safety net and risk appetite to do so. For reference, my journey towards software development looked like this, plus a few stints of working as a newspaper seller or a grocery store worker. who do you call a “senior senior” developer, a senile developer? ↩︎ spicy autocomplete engines (also known as LLM-s) do not count as actual artificial intelligence. ↩︎ what fascinates me about all the arguments around “AI” (LLM-s) is the feeling of being more productive. But how do you actually measure developer productivity, and do you account for possible reduced velocity later on when you’ve mistaken code generation speed as velocity and introduced hard to catch bugs into the code base that need to be resolved when they inevitably become an issue? ↩︎

3 days ago 9 votes
A slept on upscaling tool for macOS

I uploaded YouTube videos from time to time, and a fun comment I often get is “Whoa, this is in 8K!”. Even better, I’ve had comments from the like, seven people with 8K TVs that the video looks awesome on their TV. And you guessed it, I don’t record my videos in 8K! I record them in 4K and upscale them to 8K after the fact. There’s no shortage of AI video upscaling tools today, but they’re of varying quality, and some are great but quite expensive. The legendary Finn Voorhees created a really cool too though, called fx-upscale, that smartly leverages Apple’s built-in MetalFX framework. For the unfamiliar, this library is an extensive of Apple’s Metal graphics library, and adds functionality similar to NVIDIA’s DLSS where it intelligently upscales video using machine learning (AI), so rather than just stretching an image, it uses a model to try to infer what the frame would look like at a higher resolution. It’s primarily geared toward video game use, but Finn’s library shows it does an excellent job for video too. I think this is a really killer utility, and use it for all my videos. I even have a license for Topaz Video AI, which arguably works better, but takes an order of magnitude longer. For instance my recent 38 minute, 4K video took about an hour to render to 8K via fx-upscale on my M1 Pro MacBook Pro, but would take over 24 hours with Topaz Video AI. # Install with homebrew brew install finnvoor/tools/fx-upscale # Outputs a file named my-video Upscaled.mov fx-upscale my-video.mov --width 7680 --codec h265 Anyway, just wanted to give a tip toward a really cool tool! Finn’s even got a [version in the Mac App Store called Unsqueeze](https://apps.apple.com/ca/app/unsqueeze/id6475134617 Unsqueeze) with an actual GUI that’s even easier to use, but I really like the command line version because you get a bit more control over the output. 8K is kinda overkill for most use cases, so to be clear you can go from like, 1080p to 4K as well if you’re so inclined. I just really like 8K for the future proofing of it all, in however many years when 8K TVs are more common I’ll be able to have some of my videos already able to take advantage of that. And it takes long enough to upscale that I’d be surprised to see TVs or YouTube offering that upscaling natively in a way that looks as good given the amount of compute required currently. Obviously very zoomed in to show the difference easier If you ask me, for indie creators, even when 8K displays are more common, the future of recording still probably won’t be in native 8K. 4K recording gives so much detail still that have more than enough details to allow AI to do a compelling upscale to 8K. I think for my next camera I’m going to aim for recording in 6K (so I can still reframe in post), and then continue to output the final result in 4K to be AI upscaled. I’m coming for you, Lumix S1ii.

4 days ago 9 votes