249: LiveDebugger: Peering Inside a LiveView

249: LiveDebugger: Peering Inside a LiveView

Released Tuesday, 15th April 2025
Good episode? Give it some love!
249: LiveDebugger: Peering Inside a LiveView

249: LiveDebugger: Peering Inside a LiveView

249: LiveDebugger: Peering Inside a LiveView

249: LiveDebugger: Peering Inside a LiveView

Tuesday, 15th April 2025
Good episode? Give it some love!
Rate Episode

Episode Transcript

Transcripts are displayed as originally observed. Some content, including advertisements may have changed.

Use Ctrl + F to search

0:00

Hello and welcome to the

0:02

Thinking Lickser podcast, where we

0:04

cover the news of the

0:06

community and learn from each

0:09

other. My name is Mark

0:11

Erickson. And I'm David Bernheisle.

0:13

Let's jump into the news.

0:16

First up, the big news is

0:18

Phoenix 1.8.0. RC was released. So

0:20

we've talked about several of the

0:22

PRs that were merged along the

0:24

way, but now it's all together

0:26

into something you can download and

0:28

try out for yourself. This is

0:30

a lot of really cool stuff.

0:32

Some of it, like the Daisy

0:34

UI-styled Tailwind components, we've already talked

0:36

about that, that's in this release,

0:39

it's part of the generators, and

0:41

it includes the Plug Dark Mode

0:43

feature. Along with this, there's an

0:45

announcement blog post. We've got a link

0:47

to that. And in that blog post,

0:49

there are some little videos embedded that

0:52

show off some of these different features.

0:54

So if you're like wondering, what does

0:56

some of this mean? Go check out

0:58

the blog post, has a lot more

1:01

detail, has code, and it has some

1:03

of those videos that you can see.

1:05

So then the other one is the

1:08

magic link slash passwordless

1:10

authentication. Previously, that's something I had

1:12

to put in after the fact

1:14

and, you know, be very careful

1:16

and very concerned. Am I getting

1:18

this right? Am I messing up

1:20

anything? Because it's just a different flow.

1:22

So it's super great that this is

1:25

included, but I also saw a new

1:27

require pseudo mode plug. And we talked

1:29

about that idea of pseudo mode in

1:31

the web browser, and that's this

1:33

whole idea of when you're needing

1:35

to... perform some sensitive operation and

1:38

there's been a passage of time

1:40

since they've authenticated. It enforces recent

1:42

authentication to be able to access

1:44

something. So that was a surprise

1:46

to me. That was like a

1:48

just a nice little benefit. I think

1:50

the biggest thing in this release is

1:52

this new idea of scopes. And this

1:55

is scopes for data access and

1:57

authorization. And it's like build as a

1:59

new first class. in Phoenix, and

2:01

it's designed to make secure data access

2:03

the default, not something that you have

2:06

to remember or frequently forget, because the

2:08

point they're making is the most common

2:10

OASP vulnerability is broken access control, which

2:12

means the website's working, but you're able

2:15

to access data you're not supposed to

2:17

be able to reach. Yeah, basically the

2:19

code that you wrote is the most

2:21

broken. Yes. Just to set back for

2:24

a second, you know, like, Daisy UI

2:26

is probably going to be the biggest,

2:28

like, visual impact, you know, because core

2:31

components is, like, so used. And I'm

2:33

going to guess that if you're trying

2:35

to keep up with, like, with all

2:37

the conventions that the generators, and by

2:40

the generators, I should clarify. There is

2:42

the installer where it'll, like, like, start.

2:44

a new Phoenix project, that's where a

2:46

lot of this will come in. But

2:49

then there's the ongoing generators, like you've

2:51

got an existing app and you're adding

2:53

something to it. There is a difference

2:56

here. The installer, I guess, is really

2:58

is going to have the most changes

3:00

here. But for the pseudo mode and

3:02

things like that's Phoenix Gen Off, and

3:05

that is technically a generator, you know,

3:07

as well. Pseudo mode, authentication, authorization, right,

3:09

so Gen Off. Oth could mean two

3:11

things. Generally, you kind of have to

3:14

like differentiate that. There's authentication, which is

3:16

what Jen Oth has typically taken care

3:18

of for you. Email and password to

3:21

begin with, but now defaulting to password

3:23

lists via magic links. And by magic

3:25

links, we mean emails that are sent

3:27

to you like one-time codes. And now

3:30

also pseudo mode, which is that, like

3:32

you said, more recent sensitive, you know,

3:34

re-up on your authentication kind of thing.

3:37

I've had to do all of these

3:39

on my own on my own. pseudo

3:41

mode is also called like step up

3:43

authorization or yeah pseudo mode is like

3:46

a very computer term. GitHub uses that

3:48

one I think. It's just like a

3:50

super super user kind of mode right

3:52

like just to make sure like are

3:55

you really sure you want to do

3:57

this? The idea here is that your

3:59

cookie mine have gotten hijacked somehow, which

4:02

would be difficult to do anyway. But

4:04

if it did get hijacked, then at

4:06

least they wouldn't be able to perform

4:08

the sensitive actions because they would

4:11

have to have the password, you know,

4:13

or the author authentication method to like

4:15

do the pseudo things, the pseudo mode

4:17

things, which is things like taking over

4:19

your account, changing the email or changing

4:21

the password. Back to scopes here, scopes.

4:24

Okay, where do I begin? You know,

4:26

and I talk about like this is

4:28

the biggest change. This is like for

4:30

me on the level of introducing the

4:32

idea of context. Like there's this new

4:34

level of the way we think

4:36

about how we access data and

4:38

what goes in these modules. That's

4:40

what scopes feels like to me.

4:42

I don't know. What about you

4:45

David? Yes. It's going to definitely

4:47

change the way things feel in

4:49

all request cycles, I think. Right.

4:51

You've already probably have like a

4:53

pattern for this somewhere. This is

4:55

conventionalizing it. This is saying, give me

4:57

all of the required context that

4:59

travels along with this resource, and

5:01

we're going to, and the most common

5:03

resource out there is going to be

5:05

the user, the currently logged in user.

5:07

But there's lots of situations out

5:09

there. It's like, well, they're currently

5:11

looking at this account, though. So

5:13

we need that accounts context in

5:16

there as well. Or they don't

5:18

have pseudo mode turned on. So,

5:20

like, you need that kind of

5:22

flag carried in, you know, along

5:24

with it. Like, that's part of

5:26

the scope. Or you could even

5:28

say, like, for this API interaction,

5:30

they are trying to submit, you

5:32

know, change this ID of this

5:34

other resource. And so... That resource scope

5:36

needs to be kind of put in

5:38

there as well, like the currently viewed

5:40

resources in there. Like it all kind

5:42

of depends on what you're doing, how

5:45

you've styled these things. All right, this

5:47

is the biggest code architectural

5:49

impact part here is like what that

5:51

usually results in, this was a

5:53

huge problem in react, is property

5:56

drilling, right? So something way up at the

5:58

top, which in our case would be like... the

6:00

request is being made, the controller action

6:02

for example, or these plugs way up

6:04

there, that needs to carry that user

6:07

and all that scope along with it

6:09

all the way down to the deepest,

6:11

darkest depths of your code, right? And

6:13

probably the worst place that it ends

6:16

up that I've seen is in change

6:18

sets, right? All the way down to

6:20

like just doing any change and one

6:22

of the common patterns you might see

6:25

is like an audit log of like

6:27

who's performing the action, right? And so

6:29

you have that current scope of the

6:31

current user, right? And generally that's as

6:34

far as we think is the current

6:36

user, so we don't remember to put

6:38

all of the other things or leave

6:40

room for the other things on there.

6:43

So we might end up putting a

6:45

bunch of virtual fields on this user

6:47

and then attaching all this other junk

6:49

to this user that may or may

6:52

not be there, depending on the call

6:54

path for this thing. And then it

6:56

ends up being in the chainset, which

6:58

will admit other side effects to like

7:01

create... audit log records or something along

7:03

with the actual update record of the

7:05

resource you're trying to change. So, Scopes,

7:07

what can they do for you? Like,

7:10

they can do a lot for you

7:12

and it's going to be a very

7:14

important pattern, I think, going forward. And

7:16

I'm glad that they're setting up precedence

7:19

here because it is a difficult thing

7:21

to get right. And I think they're

7:23

not reaching too far into like your

7:25

app. This is just a recap like

7:28

a little bit of what they're actually

7:30

doing here. Like any config about scopes

7:32

with Phoenix is mostly about the generators.

7:34

It's not actually like it's not the

7:37

framework calling your code. Be clear about

7:39

that. It's setting up a pattern. for

7:41

you to be able to extend from

7:43

at that point, but it's still your

7:45

code that deals with the scope that

7:48

you're setting in there. Which for me

7:50

comes right back to how context was

7:52

introduced, right? It's a generator and it's

7:54

like here's a new pattern and we're

7:57

going to set you up for it.

7:59

You can customize it and own it

8:01

from there. Right. be very important for

8:03

things like like multi-tenancy kind of apps

8:06

this would be important for and I'm

8:08

kind of curious how they would recommend

8:10

it I should go chat with some

8:12

folks but like a lot of times

8:15

an app will have like the front

8:17

ends that users would face but then

8:19

you have the back office and so

8:21

the scope of that back office would

8:23

be different right right so you need

8:26

to kind of do something different when

8:28

you're in the back office and maybe

8:30

you do the pseudo mode to get

8:32

into the back office or How do

8:35

you handle impersonation? Oh, well now your

8:37

scope actually includes two users at this

8:39

point, right? The user that the app,

8:41

the front, the real app, you know,

8:44

kind of thinks it's acting under, you

8:46

know, and doing all the typical authorization

8:48

for that, but then there's going to

8:50

be some cases where, like, well, I

8:53

am impersonating and I need some extra,

8:55

like, links to the back office or

8:57

something, or extra debug information or something

8:59

like that I might be rendering in

9:01

the app. only when I'm in person

9:04

because I'm a staff user, right? Or

9:06

an admin user. Anyway, I'm very, as

9:08

you can tell, I'm very excited. I'm

9:10

very excited about this default scope. I've

9:13

been like, I've been like combing the

9:15

guide. By the way, there's a new

9:17

guide for scopes to kind of walk

9:19

you through it. So I've been combing

9:22

the guide and like comparing notes. I

9:24

mean like, this is what I did.

9:26

So I'm sure a lot of like

9:28

veteran Phoenix users are probably going to

9:31

be looking at this with great interest

9:33

and I'm very happy that new projects

9:35

going forward with Phoenix is going to

9:37

have what I'm judging to be a

9:39

very healthy pattern to start with, which

9:42

is very helpful. I'm pretty excited about

9:44

this. And it can extend to even

9:46

more, you know, it's not all about

9:48

the glorious con, you know, as con

9:51

as in the connection, the plug connection.

9:53

It could be about your absence context.

9:55

It could be about setting up fixtures

9:57

for, you know, set, you know, like

10:00

in factories or... something like that, or

10:02

other like helper functions, just and tests.

10:04

Like, there really is a lot that

10:06

you can kind of do here. Anyway,

10:08

very interesting, definitely worth diving into and

10:11

spending more than just a couple minutes

10:13

looking at the guides here. Like, you

10:15

should really, like, really assess how this

10:17

could be adopted in your code base.

10:20

Yeah, because I think of some of

10:22

the other libraries I've seen that handle

10:24

that help handle multi-tenancy. one of the

10:26

approaches that I've seen used is that

10:29

when you establish which tenant this is

10:31

that data gets put into the

10:33

process dictionary so that ends up

10:35

traveling down into those deeper levels so

10:37

you're not having to like push it

10:39

all the way down through every call

10:41

then it's like well when you spawn

10:43

a task you have to copy over

10:45

this context and and it's it's just

10:48

like this I want to see because

10:50

they even specifically mentioned that this could

10:52

be used for multi-tenancy. That's what I

10:54

want to see. I want to see

10:56

how this can be a more elegant

10:58

solution where everything's a little bit more

11:00

in your face in terms of the

11:02

code. You're not having to debug and

11:04

say, oh, what might be in the

11:06

process dictionary at this point? I

11:08

love that idea. So I am

11:11

really looking forward to playing with

11:13

this. Yeah. Oh, very exciting. Today's

11:15

episode is sponsored by paraxial.io. Every

11:17

day hackers search the internet for

11:20

vulnerable applications aiming to steal sensitive

11:22

data, commit fraud, and spitefully ruin

11:24

the weekend of a hardworking developer.

11:26

paraxial.io is the first and only

11:29

security platform with full elixir support

11:31

that stops these attacks. Developers love

11:33

the elixir native protection. Management

11:36

loves paraxial.io's metrics that detail the

11:38

security accomplishments of engineering, which are

11:40

required for SOC 2, ISO, and

11:42

HIPAA compliance. Sign in for a

11:44

free trial of paraxial.io today and

11:46

mention thinking elixir when you schedule

11:49

a demo for a limited time

11:51

offer. Check it out at paraxial.io.

11:53

All right, next up, there was

11:55

an interesting kind of privacy or

11:57

security focused PR that was merged

11:59

into... Hat Tip to Noah Benson, by

12:01

the way. Thanks for listening and giving

12:04

those tips. So we got a link

12:06

to the PRs and some posts on

12:08

Blue Sky about it, but here's the

12:10

thing. It's Ecto, right? There is a

12:13

way in Ecto by default to redact

12:15

a bunch of fields, right? It's on

12:17

the field macro. So you define your

12:19

field and you can say, redact true.

12:22

And what that tells all of the

12:24

implementations of like the logger and or

12:26

Jason or all these kinds of things

12:28

is to basically say don't log this

12:30

field it's got sensitive info. But what

12:33

if the whole struck to sensitive or

12:35

or what if what if you just

12:37

don't want any of that kind of

12:39

stuff logged and you're afraid of your

12:42

team like adding fields virtual or not

12:44

you know like like just adding to

12:46

it and then forgetting to add redact

12:48

true on there you know. You could

12:51

write your own little, use my app

12:53

dot schema that like does some of

12:55

the macro listing and give me all

12:57

the things, right? You could do that.

13:00

Or now, in Ecto Main, at least,

13:02

we'll wait for the release, but in

13:04

Ecto Main, now you can also set

13:06

a model attribute of schema redact, all

13:08

except primary keys, I guess, aren't sensitive,

13:11

right? Yeah, I was looking at the

13:13

PR, and it looks like from my

13:15

reading of it. where you might have

13:17

a schema that has foreign keys, that

13:20

those primary keys might be one of

13:22

those things that's not redacted. So how

13:24

this particular scheme is connected to other

13:26

related schemas is still there, which is

13:29

helpful, but like the actual data on

13:31

all of these is totally redacted for

13:33

logs. And I think of this approach,

13:35

like, you know, if I had an

13:37

integrations table where my service might integrate

13:40

into other services and the user is

13:42

able to put in... You know, we

13:44

have system generated API keys that they

13:46

have to have. It's a shared secret.

13:49

The user might be putting in other

13:51

data that might be part of that

13:53

integration for them, but it's user controlled

13:55

data. Like, I just wanted to redact

13:58

all. that just to be safe and

14:00

then because yeah if I do add

14:02

any more fields in the future just

14:04

block it all right that's one of

14:07

those situations where you know everything in

14:09

this schema we're just gonna treat a

14:11

sensitive just to be safe that's a

14:13

great addition yeah and and easy to you

14:15

know like just an easy setting easy in

14:18

the implementation as well so I was glad

14:20

to see it upstream up up up there

14:22

Yeah, so we got a link to the

14:25

posts on Blue Sky, so you can kind

14:27

of see the history of this too. It's

14:29

just kind of thrown out as a question.

14:31

I ended up as a PR and merged

14:34

into Ecto. It's one of those typical, you

14:36

know, like, hey man, if we just talk,

14:38

things can happen. So feel free to have

14:41

those conversations out in the while. Don't keep

14:43

them up in your head or privately, you

14:45

know, like it's okay to talk out loud about

14:47

those things about those things. You know, you know,

14:50

you know, you know, you know, or ESCT,

14:52

the Esk, the Esk, Esk,

14:54

Yes. Well, that project is

14:56

really, we had to bring

14:58

it up again because it's

15:00

a great community resource and

15:02

it is recently found a

15:04

new home for maintainorship. The

15:06

project, it's elixir secure coding

15:09

training, it's a GitHub repo,

15:11

an interactive cyber security curriculum

15:13

designed for enterprise use at

15:15

software companies using elixir. It

15:17

was actually developed at podium.

15:19

You know, I've been at companies where you

15:22

have to regularly take security

15:24

training, right? That's just part

15:26

of like socketoo compliance, just that

15:28

our developers are getting security

15:30

training. But our small elixir team

15:33

was part of a larger company

15:35

and a lot of the other, most of

15:37

the company was doing Java. And so

15:40

our security training was Java based, which,

15:42

you know, was dumb because... you know one

15:44

we don't know they're like saying which of

15:47

these functions should you be using in this

15:49

context for this particular business that but like

15:51

you tell me the answer because I don't

15:54

even know the string the string formatter one

15:56

obviously I don't know the the void voided

15:58

class one I think yeah And so

16:00

really was silly about that is it

16:02

would check the box that yes they've

16:04

received training but it didn't actually do

16:06

any good right it wasn't in any

16:09

way raising security awareness for the electorate

16:11

developers. What this project does is it

16:13

is something that you fork and you

16:15

can customize for your particular company and

16:17

so I just want to make sure

16:19

people were aware of this. So what

16:21

it is TV Labs has taken over

16:23

the maintainership of the project. And the

16:26

long-term plan is to move this to

16:28

the E EF, where they will hold

16:30

the repo because it's such a fantastic

16:32

community resource. If you haven't seen that

16:34

before and at your company you have

16:36

elixir being used, this is a security

16:38

resource you should be checking out. All

16:40

right, next up, we saw a cool

16:42

tip shared online, we just wanted to

16:45

pass it along. If you, in your

16:47

environment, export the environment variable visual equals

16:49

and then, you know, a pointer to

16:51

the binary of your editor of choice,

16:53

like if you have code, for example,

16:55

or NeoVim, then you can do a

16:57

cool trick in an IEX shell. On

16:59

the Mac at least, you can hit

17:02

escape O. And it's going to escape

17:04

out into your visual editor, I guess,

17:06

right? So that way, if you're doing

17:08

a lot of like multi-line commands in

17:10

the IEX terminal, like you can do

17:12

that in your terminal of choice. I

17:14

often, like, oh, I don't know, probably

17:16

seven times out of ten. I will

17:19

screw up the command and then like

17:21

have to IEX break lines or something.

17:23

to get out of it or just

17:25

forget where my end the ending brackets

17:27

are. I just get it wrong. So

17:29

I just have to start like spamming

17:31

in right brackets or right parentheses to

17:33

make a screw up. So in other

17:35

words, you know, yeah, escape, oh is

17:38

a nifty little trick to get out

17:40

of the IEX shell just temporarily and

17:42

into your editor of choice. Write the

17:44

IEX, you know, you know, commands, the

17:46

electric code of choice. And then when

17:48

you save and quit out of that,

17:50

the IEX will have that command in

17:52

its line then. So that's pretty cool.

17:55

Another way that you can kind of

17:57

take that tip is if like I'm

17:59

not... really sure what I need to

18:01

type. Well we've got and by we I

18:03

mean generally the developer in you know

18:05

a community at large has LLM support

18:07

out there now right so you can

18:09

kind of set that visual editor to

18:11

be like cursor for example and then

18:13

ask cursor questions on how do I

18:15

get this to be Jason decoded or

18:17

you know whatever and and and it's

18:19

gonna it's gonna help you out with

18:21

a little bit of that. So it's

18:24

just a way to get out of

18:26

the the the IEX terminal and anywhere

18:28

to where you need to be. And

18:30

then when you're done with that, all

18:32

of that code gets put back into

18:34

the IEX buffer, which is pretty great.

18:36

Nice cool tip. Loved it. We got

18:38

a link to the original post of

18:41

that tip. So you go give a

18:43

hat tip to them. Generally, for these

18:45

kinds of hot tips, maybe go subscribe

18:47

or listen to the hashtag elixir laying

18:50

tag there on Blue Sky. There's a

18:52

lot of that kind of stuff online.

18:54

And next up, speaking of cursor,

18:57

if you are using cursor or

18:59

another code editor that supports MCP

19:01

servers, so MCP is like all

19:03

the new hotness, it was protocol

19:05

that was defined by Enthropic, it's

19:08

all around large language models, actually

19:10

open AI of officially adopted support

19:12

for it too. What this is, is

19:14

some of these code editors support

19:16

MCP servers, and that stands for

19:18

model context protocol. Well Daniel Holzgan.

19:21

created a new MCP server that

19:23

you can add that brings package

19:25

repository awareness for hex p.m. N

19:27

p.m. Ruby gems and more. So

19:29

I got a link to it

19:31

in the show notes. But what

19:33

this means is that you can

19:35

be working with cursor. and say

19:38

install the latest XYZ package and

19:40

it will be able to find

19:42

out by querying the package repository

19:44

what is the latest version and then

19:46

be able to update your mix.exs file

19:48

dropping in the package with the right

19:51

version in the show notes I have

19:53

included a link and a little blurb

19:55

of what does this config look like

19:58

because when you go into cursor and

20:00

you say look at my settings for

20:02

MCP servers, it's just a Jason blob

20:04

and there's nothing in it. And so

20:06

you have to know what to put

20:08

in it. So I got a little

20:10

blurb of what that looks like for

20:13

this particular one. So anyway, there's going

20:15

to be lots of these kinds of

20:17

things. More are going to be coming.

20:19

MCP servers built into your editors. So

20:21

anyway, just want to pass that one

20:23

along specifically because of the great hex

20:25

support. Yeah. All right, last up, conference

20:27

news. Elekstra Conf, US, 2025 is now

20:30

open for submitting talks and workshops. You're

20:32

going to find some more information at

20:34

elekstraconf.com. We've also got a Twitter post,

20:36

talks a little bit more about it.

20:38

So Elekstra Conf, US, 2025 will be

20:40

in Orlando one last time, I think.

20:42

The last time, because they signed a

20:44

multi-year contract there, but Orlando is also

20:47

a pretty fun place for a bunch

20:49

of theme parks out there. So I'm

20:51

particularly excited about Super Mario, Mario World.

20:53

I'm a kid of the late 80s,

20:55

early 90s, so I'm not going to

20:57

be able to avoid that place. I

20:59

will force my kids to go along

21:01

with me and have fun. Oh, enough

21:03

about that. Anyway, you can submit a

21:06

talk by April 29th or a workshop

21:08

by April 15th. Any of the topics

21:10

of Phoenix Live View or other kinds

21:12

of distributed systems is always going to

21:14

be good. And you can join the

21:16

wait list for pre-sale of the tickets

21:18

now on that. So that's elixirconf.com. So

21:20

one more time is they're taking talks.

21:23

If you got an idea, go give

21:25

it, go propose a talk. They got

21:27

some really fun things out there in

21:29

the past. So very excited to see

21:31

what comes up. elixirconf US is going

21:33

to be on August 27th for the

21:35

workshop. 9th in Orlando and virtual. So

21:37

you'll find that there. And that's it

21:40

for the news. Today we're being joined

21:42

by our special guest, Kristof Nalepa. Kristof,

21:44

welcome to the show. Hi, thanks for

21:46

having me. I'm excited you could join

21:48

us because you work at Software Mansion

21:50

and you and your team or whoever's

21:52

involved, which I want to learn more

21:54

about, have built live debugger. And we've

21:57

talked about it on the news. I

21:59

love this tool. I use this tool.

22:01

This is an incredible tool that lets

22:03

you, if you haven't seen it yet,

22:05

dear listener, you need to go try

22:07

it out immediately. This is a thing

22:09

that lets you see the state of

22:11

what's going on inside your live view

22:14

in a local development environment. It's incredible.

22:16

So I'm really happy to be able

22:18

to talk with you more about this,

22:20

learn more of the story, and how

22:22

we can really take advantage of it.

22:24

But before we get into all of

22:26

that, I'd love to hear more about

22:28

you. Like, where do you live and

22:31

what kind of work are you doing?

22:33

Yes, so, hi, my name is Kristof.

22:35

I live in Poland, Krakow, and I'm

22:37

working as a software engineer in Softur

22:39

Mansion. I am curious to hear about

22:41

how long have you been working with

22:43

elixir. It's actually not that long because

22:45

I've been working as a software engineer

22:47

for like four years. I actually started

22:50

with Java during my college education. I

22:52

did a lot of stuff in spring

22:54

framework and I was hoping to become

22:56

a Java developer. Fortunately, this didn't happen.

22:58

I haven't written any line of code

23:00

in Java professionally. So... I think it's

23:02

great when the things that we really

23:04

want don't happen and we don't know

23:07

that it's actually better for us at

23:09

the time. Yeah, that's true and I'm

23:11

really happy that I ended here. I

23:13

started like working four years ago and

23:15

I started with React. I switched basically

23:17

front end. Then I switched back to...

23:19

back and stuff. I was introduced to

23:21

Erlang. I was actually working on instant

23:24

messaging server. It's called Mungusiam. It's open

23:26

source. I think it's maintained by Erlang

23:28

Solutions. After that I landed in Alexei

23:30

World and I've been working with Alexei

23:32

for like three and a half years.

23:34

Mostly with live view actually, yeah, that's

23:36

it. Can you tell me a little

23:38

bit about what software, software mansion does?

23:41

Because I've seen that name several times

23:43

now just in, you know, Alexei News.

23:45

From what I remember, software mansion does

23:47

a lot with like video web streaming.

23:49

Can you give me a fuller picture

23:51

there of what software mansion is doing?

23:53

Originally, salt formation was focused on react

23:55

native and it was like a main

23:58

technology for us. But right now we

24:00

are doing a lot of different stuff.

24:02

We have a big focus on media

24:04

technologies and there are like plenty, plenty

24:06

of products that we develop. Probably the

24:08

biggest one is membrane, probably main media

24:10

library for elixir. To be honest, I'm

24:12

not that familiar with it because I

24:15

mostly focus on the web staff and

24:17

the media department in our company is

24:19

quite big. I sit next to them,

24:21

so that's basically it. But otherwise, software

24:23

mention is also a software consultancy, so

24:25

as a hiring. Yeah, that's right. We

24:27

are mostly focused on clients and our

24:29

products are more for advertisement. Maybe you

24:31

can give us an intro to live

24:34

debugger. Big picture, what is this project?

24:36

What is this project? What is this

24:38

project? What is this? caused you or

24:40

it's a team to actually say this

24:42

is something we want to invest in

24:44

making. But first like start off with

24:46

what is this, how do I use

24:48

it? Like in one sentence, live debugger

24:51

is a tool designed to simplify the

24:53

debugging process of applications written in Phoenix

24:55

Liveview and how to use it. It's

24:57

basically a hex package that you add

24:59

as a dependency to your project and

25:01

after you run your project it will

25:03

automatically start a... new application and by

25:05

application I mean the OTP application which

25:08

will start a separate Phoenix endpoint on

25:10

a different part with its own router

25:12

that hosts our custom views that are

25:14

actually written in live view so live

25:16

debugger is written completely in live view

25:18

and after you access the the port

25:20

of live debugger. You will get access

25:22

to plenty of features that will help

25:25

you to understand what's happening in your

25:27

application. It will allow you to inspect

25:29

states of each live view and live

25:31

component. It will allow you to see

25:33

the transitions of these states. Also, it

25:35

will allow you to see the components

25:37

tree of currently displayed live view. Yeah,

25:39

much more basically. But yeah, these are

25:42

like main features of live debugger. It

25:44

allows you to understand what's happening in

25:46

your app. Yeah, I'll say personally when

25:48

I first started using it, I jumped

25:50

into an existing project that had been

25:52

developed by a number of different people

25:54

over time. And it was very complex,

25:56

live view application, complex in meaning like

25:59

you're having. dynamic live components are being

26:01

loaded in under different contexts. And I'm

26:03

trying to jump into this project and

26:05

just get my bearings of what is

26:07

going on with this thing, what component

26:09

am I looking at right now? And

26:11

live debugger was awesome. I just opened

26:13

it up and as I'm clicking around

26:15

and I, oh I click this in

26:18

the, in the live view and Boom,

26:20

here's the component that comes up, it's

26:22

just made obvious in the tree, and

26:24

then I'm able to see what the

26:26

state is of that live component or

26:28

the live view, and then as I

26:30

click around in the application, and the

26:32

state is changing, I'm seeing those events

26:35

just happening, this handle event was fired,

26:37

and this is the state change before

26:39

and after. And one of the things

26:41

I love, I just gotta say, I

26:43

love this, is like if you've ever

26:45

done an Iowa inspect on your state.

26:47

like the socket

26:49

or something like that.

26:52

It's just huge

26:54

and it's unusable in

26:56

that the default

26:58

is to shorten it,

27:00

right? So that

27:02

it doesn't completely blow

27:04

out your whole

27:06

console, scroll back. You

27:09

know, everything gets

27:11

shrunk down. It's like,

27:13

well, that's the

27:15

piece of data I

27:17

wanted. Okay, I

27:19

need to do an

27:21

IO inspector on

27:23

this deeper part of

27:26

the assigns and

27:28

something like that. And

27:30

what I love

27:32

is that in the

27:34

Live Debugger it's

27:36

all available, it might

27:38

be collapsed as

27:40

a tree but I

27:43

can click and

27:45

expand and none of

27:47

it's been redacted

27:49

or shrunken or all

27:51

the data's there.

27:53

Yay, this is awesome.

27:55

I love that.

27:57

So yeah, I think

27:59

people should be

28:02

using this. Yeah, so

28:04

one of the

28:06

things you mentioned there

28:08

is just a

28:10

dev -only package. You

28:12

can just add it

28:14

to your Mix

28:16

file and say dev

28:19

-only so like there's

28:21

no concern about

28:23

this going anywhere else.

28:25

Super easy to

28:27

add and then it

28:29

runs on a

28:31

separate port so you

28:33

can just open

28:36

it up alongside your

28:38

application. Yeah, so

28:40

I guess my next

28:42

question is what

28:44

was the driver for

28:46

creating this? Is

28:48

this inspired by a

28:50

tool from a

28:53

different community or is

28:55

this just like

28:57

we're having a difficult

28:59

time figuring out

29:01

what's going on? Like

29:03

what was the

29:05

driver for this? So

29:07

first of all,

29:10

I'm really glad that

29:12

it helps you. That

29:15

was the goal of

29:17

this project to help people.

29:19

When it comes to

29:21

reasons, I think these two

29:24

are combined in case

29:26

of this project. So when

29:28

I joined Soft Formation,

29:30

it was like a year

29:33

ago, I started working

29:35

on a rather big client

29:37

project which used LiveView

29:39

and some other Elixir technologies

29:42

like Ash framework. And

29:44

it was quite a big

29:46

application, quite complex with

29:48

a lot of interactions between

29:50

live components. And actually

29:53

what's more, the team who

29:55

was responsible for creating

29:57

this application was learning LiveView

29:59

during the development. So

30:02

some of code was over.

30:04

and over complicated. For example, they were not using

30:06

clay components, which caused live views to be extremely

30:08

big, and their state was enormous. This

30:11

is the situation I was like

30:13

one year ago, and I was

30:15

trying to understand this application, and

30:18

it was extremely hard for me,

30:20

because every time I wanted to

30:22

like see. what's happening in the

30:25

state. I had to like use

30:27

DBG and it landed in the

30:29

the sea of logs and it

30:31

was almost impossible to find it.

30:34

It was literally like looking for

30:36

a needle in a haystack. But

30:38

somehow I managed it. I mean

30:41

I could like turn off logs

30:43

and that was that was okay

30:45

for some time. That was basically

30:47

a situation where like refactoring the

30:49

code, making it more easy to

30:51

work with. And one time I

30:53

was chatting with my teammate and

30:55

he was like completely new to

30:57

the live view ward. He originates

30:59

from the from the react actually

31:01

and he mentioned that he misses

31:04

react dev tools sometimes in this

31:06

project. And you know I have

31:09

some experience with react and I

31:11

was using react dev tools and

31:13

I was like, wow, this is a

31:16

great idea, maybe we should do

31:18

it. That's how it started. That

31:20

was the main inspiration. We had

31:22

basically a problem and idea

31:25

for a solution for this

31:27

problem and decided to research

31:29

it. So I took some

31:31

recent development hours, started working

31:34

on POC. I found some

31:36

libraries that... was doing something

31:38

similar for live view applications.

31:40

One of them is probably

31:42

time travel, which was abandoned

31:45

by outer like three years

31:47

ago, I think. And it

31:49

was really cool. It uses

31:51

from extension and it

31:53

does similar stuff to

31:55

live debugger. Actually, their

31:57

tracing functionality is completely...

32:00

different to our, but nevertheless, I

32:02

started to like think her and

32:04

created a POC that was really

32:06

simple. It was an increment button

32:08

and when you clicked it, the

32:10

trace was appearing and you could

32:12

see the state of the live

32:15

view. So yeah, this is how

32:17

it started. That's pretty incredible. It

32:19

reminds me a little bit of,

32:21

you know, back in the day,

32:23

Phoenix used to not annotate, it's

32:25

HTML. Right. And so if you

32:27

had a bunch of like templates

32:30

that... even were recursive, right, could

32:32

even render itself with just however

32:34

needed, how far it needed to

32:36

go. And you needed to debug

32:38

some sort of like, I don't

32:40

know, something was floating right instead

32:43

of left. You needed to figure

32:45

out where is this coming from?

32:47

What template is this coming from?

32:49

And it was really difficult. You

32:51

had to almost like just grab

32:53

some random classes in some little

32:55

template. And by classes, I mean,

32:58

HDML classes, right? That would usually

33:00

get you to where you needed

33:02

to go. You surely can't just

33:04

grab Brett for div. That would

33:06

be everything. But then since then,

33:08

they added annotations to the Higgs

33:10

tag engine, and now it's really

33:13

easy to see, you know, when

33:15

you're in the browser trying to

33:17

debug something that's displaying, you know,

33:19

weirdly, you can see exactly which

33:21

template it's coming from. I've seen

33:23

some other debuggers in it, and

33:25

it doesn't. pollute like the actual

33:28

HTML like what you're seeing, you

33:30

know, with like a bunch of

33:32

notes or something to where you

33:34

can't even like see what you're

33:36

doing anymore. So speaking of that,

33:38

did you consider using a Chrome

33:41

extension to like facilitate some of

33:43

the live debugger things on the

33:45

client side? Because it's as far

33:47

as I understand it is all

33:49

server side handled, right? Yeah, so

33:51

Chrome extension is coming in next

33:53

version of live debugger. it's already

33:56

written. I mean it's for now

33:58

it's quite simple so basically we

34:00

got a lot of feedback after

34:02

release of the first version that

34:04

people would like to have live

34:06

debugger in the same browser or

34:08

browser that's their project with their

34:11

project. So we decided to create

34:13

a Chrome extension. So you will

34:15

be actually able to. run Dev

34:17

Tools application from Dev Tools and

34:19

there will be a new card

34:21

there with live debuggers so we

34:24

will be actually able to open

34:26

it in the Dev Tools extension

34:28

and yes we are planning to

34:30

extend this extension there

34:32

will be more features

34:34

associated with components highlighting

34:36

and other stuff so definitely we'll go

34:39

this way. Yeah so what is the

34:41

Chrome extension like enabling for

34:43

you? What does that give you?

34:45

like on top of just normal,

34:48

you know, HTML, you know, another

34:50

frame or something, for example.

34:52

Actually, in like, JavaScript world,

34:55

you can inspect elements in

34:57

application. So you can right

34:59

click on something and click

35:01

inspect, and it will show

35:04

you the HDML that is

35:06

associated with this element

35:08

in the browser. So we want

35:10

to do something similar like this

35:12

to this to this. Basically,

35:14

we hope that somehow you will be

35:16

able to, not somehow, but with the

35:19

extension, you will be able to right

35:21

click in your application and it will

35:23

show you a live component that generated

35:25

this piece of code. The idea would

35:27

be using the browser integration be able

35:29

to right click on an element in

35:31

a page and drive into the live

35:34

view debugger from that direction as opposed

35:36

to the live view debugger being a

35:38

separate thing and having to drill down

35:40

from the top to get down into

35:42

it. That's right. That's cool. That's right.

35:45

Yeah, that's pretty slick. And so you

35:47

mentioned the time travel bit too. So

35:49

you can kind of like scroll back

35:51

in history to see what the what

35:53

the assigns were, you know, at a

35:55

moment. That's that's killer. But yeah, you're

35:57

hugging into like standard tracing.

36:00

guess to figure out like yeah what's

36:02

on the assigned and then and then

36:04

and then to print that out you

36:06

know in the in the app I'm

36:09

guessing you're just using standard like inspect

36:11

protocol kind of things and so yeah

36:13

usually that's that's true so when it

36:16

comes to tracing we are using like

36:18

the DPG module it's airline module After

36:20

that, we are basically, we are inspecting

36:23

the airline terms to like display it

36:25

to the user. So I have in

36:27

my head how I think this works

36:30

and I'd love to hear if this

36:32

is right and maybe you can describe

36:34

further how this is actually doing it.

36:37

But from what I gather and think

36:39

it's I have this live view of

36:41

the debugger and because it's running in

36:44

the same instance of my application, it

36:46

has access to everything. And it is...

36:48

finding the live views, it has a

36:51

list of the live views I could

36:53

join to, and then it's doing like

36:55

a get state on that process to

36:58

get like what is the entire state

37:00

of what's going on in that process

37:02

and then being able to represent and

37:05

display that in a way that's navigatable.

37:07

Is that what's going on? Yeah, that's

37:09

true. This is what's happening. So there

37:12

is like this view containing all active

37:14

live views in the note. So we

37:16

do some discovery there and we basically

37:19

gather information about active live views. And

37:21

after that, when we have the pit

37:23

of the live-view process, we can do

37:26

everything with it. I mean, this is

37:28

a process we can ask for its

37:30

state. We can trace functions, which is...

37:33

that are executed by this process. So

37:35

yeah, that's it. I think that's so

37:37

cool. You know, that's a feature that's

37:40

built into the beam, which is this

37:42

debug ability to say get the entire

37:44

state. And I think, if I'm right,

37:47

I think there's a way to put

37:49

an entire state. Is that right? Yeah,

37:51

that's true. Because then you could, you

37:54

have this list of, these are the

37:56

actions that have happened in this sequence

37:58

of interactions on this. you could say

38:01

time travel by go back and reset

38:03

the state of the live view to

38:05

this previous state. Is that something that's

38:08

possible? I don't see any reason why

38:10

it shouldn't be possible. I mean, as

38:12

far as I know and as far

38:15

as I play around, played around with

38:17

it, it's totally possible and you can

38:19

do whatever you want with this state.

38:22

I mean, it's just a process. That's

38:24

like that whole time travel idea, right,

38:26

that I've seen in the React Dev

38:28

Tools too, where you can go back

38:31

to a previous state. Because like if

38:33

you're trying to recreate a bug state,

38:35

that can be very difficult to get

38:38

it just right. You know, so for

38:40

some bugs, that can be really nasty

38:42

like that. So being able to like

38:45

just step back and put the live

38:47

view back into that previous state where

38:49

I can see the bug and see

38:52

what you know, go back and forth

38:54

and that would just be insane. Well,

38:56

it's coming, not in the next version,

38:59

but in the future. We are planning

39:01

to do something like this in the

39:03

future. And as I said, I was

39:06

playing around with it. I think I've

39:08

got somewhere a POC, so yeah, it's

39:10

possible and it'll happen. Well, before we

39:13

talk about some of the other cool

39:15

stuff you have planned, and I just

39:17

want to make sure we cover how

39:20

this should or should not be used,

39:22

right? As I understand it. This is

39:24

really should only be a dev local

39:27

tool, right? No one should say, oh,

39:29

let me deploy this to my server.

39:31

Or is that something that you think

39:34

people could do? You know, how should

39:36

people be using this? I really discourage

39:38

using Clive debugger on production. It doesn't

39:41

meant to be a... production library. For

39:43

now it's it should be used purely

39:45

for local development and I want to

39:48

like make sure that it's clear. So

39:50

we haven't considered what consequences it can

39:52

have in terms of security basically when

39:55

you use live debugger on on production.

39:57

As you could see you can easily

39:59

see all active live views for a

40:02

given note. So probably you could

40:04

see what exactly user is doing.

40:06

For now, it'd be a definitely

40:08

dependency. Yeah, I would agree with that. I

40:11

can't even imagine like normal debugger

40:13

tracers being in production. You know,

40:15

that's always like a tension point

40:17

too, right? Even without live debugger,

40:19

just trying to do it the

40:21

old school way with like red

40:23

bug or something or recon. It's

40:26

always like, oh, I don't really

40:28

want to include this dependency in

40:30

here at all, because then it

40:32

can happen. But on the other

40:34

hand, I'm going to need it

40:36

when I need it, you know,

40:38

in production, perhaps, hopefully, hopefully not.

40:40

There's usually like three or four

40:42

things I try before doing it live

40:44

in prod, but trying to at least

40:46

replicate, you know, whatever the bug

40:49

is in the staging or local

40:51

environment, you know, first. copying, you

40:53

know, data over to try to

40:55

replicate, but rather than on the

40:58

actual, you know, prod stuff. Glad

41:00

we got that out of the

41:02

way, though. Like, people need to

41:04

have a realistic expectation of how

41:06

you can safely use this and

41:09

what it's intended for. I'm just

41:11

curious, I guess. It has no

41:13

effect on, like, the usability of

41:15

this, perhaps, but there's not a

41:17

lot that I'm aware of Phoenix

41:20

or mixed packages out there. That

41:22

hook in so much into like asset

41:24

pipelines or other like web asset kind

41:26

of things and I'm curious from your

41:28

perspective Open web is one of them

41:30

right? Open web has like its own

41:32

router and it needs to you forward

41:34

routes over to it live debuggers going

41:36

to be kind of the same thing

41:39

but you guys have your own server

41:41

on top of that. How has it

41:43

been to like develop a hex package

41:45

that has its own like asset pipeline

41:47

and its own server that starts up

41:49

you know alongside like Did you find that

41:52

to be difficult or obtuse or lots

41:54

of little gotches in there that just

41:56

made that experience like kind of bad?

41:58

It was difficult and... beginning I

42:00

have to admit we have like

42:03

this is like the second approach

42:05

of like setting up this of

42:07

setup of this project because originally

42:10

we were doing something similar to

42:12

Phoenix Live dashboard because yeah similar

42:14

similar like library to us I

42:17

guess and Oban Pro is a

42:19

good example too. Yeah, it was

42:21

it was difficult. I mean we

42:23

had we had some problems with

42:26

actually after the there was a

42:28

first internal release that's only for

42:30

for for projects in our company.

42:33

It was still using the the

42:35

old way to of setup of

42:37

the library. We gave it to

42:40

one of our projects. and they

42:42

were like it's not working I

42:44

mean it the application is not

42:47

starting and we decided to change

42:49

it completely but yeah we have

42:51

some we have some issues with

42:54

we had some issues actually because

42:56

it's it should be in past

42:58

with parsing JavaScript because we have

43:01

a lot of custom CSSs we

43:03

had some issues with it it

43:05

was really difficult to wrap it

43:08

up but It's working fine now,

43:10

I guess. And the setup is

43:12

quite good. Yeah, your approach now

43:14

is I'm going to have my

43:17

own server. Yeah, exactly. Yeah. It

43:19

was easier this way, basically. Yeah.

43:21

I noticed that because you have

43:24

instructions on there for the constant

43:26

security policy. So if anyone has

43:28

that like those CSP headers running

43:31

in endeavor staging or something where

43:33

you have live debugger enabled, you

43:35

do have to like allow. this

43:38

other, because it's on a different

43:40

port at this point, it has

43:42

to be this other host, you

43:45

have to allow these assets from

43:47

another host to be loaded. It's,

43:49

it gets, it gets to be

43:52

a thing. Similarly, you know, I

43:54

noticed that you, that live debugger

43:56

has igniter support, so I'm curious

43:59

from your perspective. How was it

44:01

to build in Igniter support? You

44:03

know, just, and for the listeners,

44:05

Igniter is a way to like

44:08

standardize injecting code into your project.

44:10

So it's very helpful for like

44:12

installers, for example, in existing code

44:15

bases or even, you know, or

44:17

skeleton's code bases? From your perspective,

44:19

Kristofa, how was live debuggers, you

44:22

know, supportive Igniter, how did that,

44:24

how did that go? I don't

44:26

know how difficult it was to

44:29

create a Igniter extension because Zach

44:31

did it actually for us. He

44:33

created a full request and wrote

44:36

me on this card and I

44:38

was like, well, okay. Yeah, go

44:40

for it. And yeah, we could

44:43

use Zach because Igniter is really

44:45

cool. Thanks, Zach. Well, for everyone

44:47

else out there, it's only about

44:50

180 lines long. That's the whole,

44:52

that's the whole task. So it

44:54

doesn't look to be all that

44:56

much. And a lot of that

44:59

is docs and text, you know,

45:01

just raw strings in there, not

45:03

even, it's just not even the

45:06

actual logic to do things. So

45:08

anyway, it looks like it would

45:10

have been pretty straightforward. Yeah, I

45:13

mean, I mean, the code is

45:15

pretty short. And I have to

45:17

admit that it's doing a lot

45:20

of cool stuff. I mean, the

45:22

whole setup is basically executing a

45:24

single comment in the terminal. So,

45:27

It's really good. Well with the

45:29

time we have left, I do

45:31

want to come back to what

45:34

we'd already teased and is some

45:36

of the what's coming next? What

45:38

are you looking for to build?

45:41

And really, I guess the big

45:43

question is, you took this contribution

45:45

from Zach Daniel. for doing igniter

45:48

support. Are you looking for community

45:50

contributions here? Or is it like,

45:52

no, we really have a plan.

45:54

We know what we're trying to

45:57

deliver on this next thing. What

45:59

is it you would like to

46:01

see? From our perspective, currently on

46:04

live debugger, we have a whole

46:06

team for live debugger. So I'm

46:08

working on it full time and

46:11

there are... actually two more people

46:13

Alan and Hubert who are working

46:15

on it part-time. and they're doing

46:18

a good job and I'm happy

46:20

to work with them. But contributors

46:22

are welcome. We've got all our

46:25

tasks in GitHub projects, so it's

46:27

available for everyone. You can see

46:29

what's currently we're working on. Yeah,

46:32

so contributors are welcome and we

46:34

would really like to hear feedback

46:36

from you guys, from everyone out

46:39

there, who is listening to this

46:41

podcast and is using a live

46:43

debugger. Yeah, we are doing it

46:45

for community. If you had any

46:48

ideas for features or if you

46:50

spotted any bugs, feel free to

46:52

report it via a good happy

46:55

issue. When it comes to our

46:57

plans, we will be releasing next

46:59

version, next minor version, 0.0, probably

47:02

end of this month, definitely before

47:04

Alexeiakov in Europe, so maybe the

47:06

beginning of May. There will be

47:09

some bigger features that we are

47:11

planning, so definitely we are planning,

47:13

as I mentioned as I mentioned

47:16

before. extension for live debugger to

47:18

perform. The dark note is coming.

47:20

And finally we are panning a

47:23

more advanced filtering of callback traces.

47:25

So it's rather simple, but we

47:27

had to make some refactors to

47:30

achieve this functionality, but you will

47:32

be able to filter out some

47:34

callbacks. So for example, you want

47:36

to just see only handle events.

47:39

You will be able to do

47:41

it by filtering out the rest

47:43

of them. Hopefully we'll be able

47:46

to achieve pattern matching in case

47:48

of filtering. So you will be

47:50

actually able to use pattern matching

47:53

to filter out not needed traces.

47:55

But it's definitely not in this

47:57

version. Interesting. Well, that's really cool.

48:00

It's interesting that you're spending full

48:02

time on that too. So that

48:04

to me is showing that software

48:07

mansion says, hey, we think this

48:09

is an important enough feature for

48:11

the community. Maybe it's been an

48:14

affinity to the company, but they're

48:16

dedicating your time to actually work

48:18

on that and push that forward.

48:21

So I think that's wonderful. And

48:23

I really appreciate your initiative in

48:25

making this happen and pushing this forward

48:27

because I love it. I'm going to

48:29

keep using it and I am

48:32

really excited about some of the

48:34

tools and ideas that you've talked

48:36

about bringing into the future like,

48:38

you know, editable state. Yes. If

48:40

people want to get in touch

48:42

with you or follow you online,

48:45

where should they go to do

48:47

that? I'm on Alexei Lange's leg,

48:49

I think it will be the

48:51

best way probably. But when it

48:53

comes to like official news about

48:56

live debugger, I encourage you to

48:58

follow software mention accounts on Twitter

49:00

and the Blue Sky. Yeah, probably

49:02

also... blog of software mention on

49:04

medium is useful to subscribe because

49:07

we will be creating some some

49:09

more blog posts about live debaggers

49:11

soon. These are like the main

49:14

channels. Also I sometimes post on

49:16

read it, Alexei read it. Yeah,

49:18

I should mention that we have

49:20

a link in the show notes

49:23

to the blog post. It's fairly

49:25

recent, the end of March, that's

49:27

introduction to live debugger. walking you

49:29

through how the different pieces work and what

49:31

they can help you do in your application.

49:34

Great resource. Well, thank you Christoff for coming

49:36

on and talking about what you've been working

49:38

on and sharing that. At some point, I

49:40

wouldn't be surprised at all if this just

49:42

becomes part of a standard install. You know,

49:44

maybe it becomes part of Phoenix. Maybe

49:47

not. Maybe it's like React Dev Tools and

49:49

it stays its own separate thing, but it's

49:51

like the thing that everyone always sticks into

49:53

their application because it's just so

49:55

darn helpful. Well thank you again, but unfortunately

49:57

that's all the time we have for today.

50:00

Thank you for listening. We hope

50:02

you'll join us next time

50:04

us next time on thinking, Alexa.

Unlock more with Podchaser Pro

  • Audience Insights
  • Contact Information
  • Demographics
  • Charts
  • Sponsor History
  • and More!
Pro Features